(module.exports = function (key, value) {
return store[key] || (store[key] = value !== undefined ? value : {});
})('versions', []).push({
- version: '3.19.2',
+ version: '3.19.3',
mode: IS_PURE ? 'pure' : 'global',
copyright: '© 2021 Denis Pushkarev (zloirock.ru)'
});
return this;
};
-module.exports = function (IteratorConstructor, NAME, next) {
+module.exports = function (IteratorConstructor, NAME, next, ENUMERABLE_NEXT) {
var TO_STRING_TAG = NAME + ' Iterator';
IteratorConstructor.prototype = create(IteratorPrototype, {
- next: createPropertyDescriptor(1, next)
+ next: createPropertyDescriptor(+!ENUMERABLE_NEXT, next)
});
setToStringTag(IteratorConstructor, TO_STRING_TAG, false, true);
Iterators[TO_STRING_TAG] = returnThis;
var SPECIES = wellKnownSymbol('species');
var PROMISE = 'Promise';
-var getInternalState = InternalStateModule.get;
+var getInternalState = InternalStateModule.getterFor(PROMISE);
var setInternalState = InternalStateModule.set;
var getInternalPromiseState = InternalStateModule.getterFor(PROMISE);
var NativePromisePrototype = NativePromise && NativePromise.prototype;
}
return step;
-});
+}, true);
var URLSearchParamsState = function (init) {
this.entries = [];
timing = __webpack_require__(857),
ruleReplacements = __webpack_require__(858);
+const {
+ getRuleFromConfig
+} = __webpack_require__(859);
+
+const {
+ FlatConfigArray
+} = __webpack_require__(860);
+
const debug = __webpack_require__(496)("eslint:linter");
const MAX_AUTOFIX_PASSES = 10;
column: 1
}
};
-const parserSymbol = Symbol.for("eslint.RuleTester.parser"); //------------------------------------------------------------------------------
+const parserSymbol = Symbol.for("eslint.RuleTester.parser");
+
+const globals = __webpack_require__(877); //------------------------------------------------------------------------------
// Typedefs
//------------------------------------------------------------------------------
/** @typedef {import("../shared/types").ParserOptions} ParserOptions */
+/** @typedef {import("../shared/types").LanguageOptions} LanguageOptions */
+
/** @typedef {import("../shared/types").Processor} Processor */
/** @typedef {import("../shared/types").Rule} Rule */
// Helpers
//------------------------------------------------------------------------------
+/**
+ * Determines if a given object is Espree.
+ * @param {Object} parser The parser to check.
+ * @returns {boolean} True if the parser is Espree or false if not.
+ */
+
+
+function isEspree(parser) {
+ return !!(parser === espree || parser[parserSymbol] === espree);
+}
+/**
+ * Retrieves globals for the given ecmaVersion.
+ * @param {number} ecmaVersion The version to retrieve globals for.
+ * @returns {Object} The globals for the given ecmaVersion.
+ */
+
+
+function getGlobalsForEcmaVersion(ecmaVersion) {
+ switch (ecmaVersion) {
+ case 3:
+ return globals.es3;
+
+ case 5:
+ return globals.es5;
+
+ default:
+ if (ecmaVersion < 2015) {
+ return globals["es".concat(ecmaVersion + 2009)];
+ }
+
+ return globals["es".concat(ecmaVersion)];
+ }
+}
/**
* Ensures that variables representing built-in properties of the Global Object,
* and any globals declared by special block comments, are present in the global
* @returns {void}
*/
+
function addDeclaredGlobals(globalScope, configGlobals, _ref) {
let {
exportedVariables,
for (const ruleId of directiveRules) {
// push to directives, if the rule is defined(including null, e.g. /*eslint enable*/)
- if (ruleId === null || ruleMapper(ruleId) !== null) {
+ if (ruleId === null || !!ruleMapper(ruleId)) {
result.directives.push({
parentComment,
type,
const rule = ruleMapper(name);
const ruleValue = parseResult.config[name];
- if (rule === null) {
+ if (!rule) {
problems.push(createLintingProblem({
ruleId: name,
loc: comment.loc
function normalizeEcmaVersion(parser, ecmaVersion) {
- if ((parser[parserSymbol] || parser) === espree) {
+ if (isEspree(parser)) {
if (ecmaVersion === "latest") {
return espree.latestEcmaVersion;
}
return ecmaVersion >= 2015 ? ecmaVersion - 2009 : ecmaVersion;
}
+/**
+ * Normalize ECMAScript version from the initial config into languageOptions (year)
+ * format.
+ * @param {any} [ecmaVersion] ECMAScript version from the initial config
+ * @returns {number} normalized ECMAScript version
+ */
+
+
+function normalizeEcmaVersionForLanguageOptions(ecmaVersion) {
+ switch (ecmaVersion) {
+ case 3:
+ return 3;
+ // void 0 = no ecmaVersion specified so use the default
+
+ case 5:
+ case void 0:
+ return 5;
+
+ default:
+ if (typeof ecmaVersion === "number") {
+ return ecmaVersion >= 2015 ? ecmaVersion : ecmaVersion + 2009;
+ }
+
+ }
+ /*
+ * We default to the latest supported ecmaVersion for everything else.
+ * Remember, this is for languageOptions.ecmaVersion, which sets the version
+ * that is used for a number of processes inside of ESLint. It's normally
+ * safe to assume people want the latest unless otherwise specified.
+ */
+
+
+ return espree.latestEcmaVersion + 2009;
+}
const eslintEnvPattern = /\/\*\s*eslint-env\s(.+?)(?:\*\/|$)/gsu;
/**
function normalizeVerifyOptions(providedOptions, config) {
- const disableInlineConfig = config.noInlineConfig === true;
+ const linterOptions = config.linterOptions || config; // .noInlineConfig for eslintrc, .linterOptions.noInlineConfig for flat
+
+ const disableInlineConfig = linterOptions.noInlineConfig === true;
const ignoreInlineConfig = providedOptions.allowInlineConfig === false;
const configNameOfNoInlineConfig = config.configNameOfNoInlineConfig ? " (".concat(config.configNameOfNoInlineConfig, ")") : "";
let reportUnusedDisableDirectives = providedOptions.reportUnusedDisableDirectives;
}
if (typeof reportUnusedDisableDirectives !== "string") {
- reportUnusedDisableDirectives = config.reportUnusedDisableDirectives ? "warn" : "off";
+ reportUnusedDisableDirectives = linterOptions.reportUnusedDisableDirectives ? "warn" : "off";
}
return {
mergedParserOptions.ecmaVersion = normalizeEcmaVersion(parser, mergedParserOptions.ecmaVersion);
return mergedParserOptions;
}
+/**
+ * Converts parserOptions to languageOptions for backwards compatibility with eslintrc.
+ * @param {ConfigData} config Config object.
+ * @param {Object} config.globals Global variable definitions.
+ * @param {Parser} config.parser The parser to use.
+ * @param {ParserOptions} config.parserOptions The parserOptions to use.
+ * @returns {LanguageOptions} The languageOptions equivalent.
+ */
+
+
+function createLanguageOptions(_ref2) {
+ let {
+ globals: configuredGlobals,
+ parser,
+ parserOptions
+ } = _ref2;
+ const {
+ ecmaVersion,
+ sourceType
+ } = parserOptions;
+ return {
+ globals: configuredGlobals,
+ ecmaVersion: normalizeEcmaVersionForLanguageOptions(ecmaVersion),
+ sourceType,
+ parser,
+ parserOptions
+ };
+}
/**
* Combines the provided globals object with the globals from environments
* @param {Record<string, GlobalConf>} providedGlobals The 'globals' key in a config
/**
* Analyze scope of the given AST.
* @param {ASTNode} ast The `Program` node to analyze.
- * @param {ParserOptions} parserOptions The parser options.
+ * @param {LanguageOptions} languageOptions The parser options.
* @param {Record<string, string[]>} visitorKeys The visitor keys.
* @returns {ScopeManager} The analysis result.
*/
-function analyzeScope(ast, parserOptions, visitorKeys) {
+function analyzeScope(ast, languageOptions, visitorKeys) {
+ const parserOptions = languageOptions.parserOptions;
const ecmaFeatures = parserOptions.ecmaFeatures || {};
- const ecmaVersion = parserOptions.ecmaVersion || DEFAULT_ECMA_VERSION;
+ const ecmaVersion = languageOptions.ecmaVersion || DEFAULT_ECMA_VERSION;
return eslintScope.analyze(ast, {
ignoreEval: true,
nodejsScope: ecmaFeatures.globalReturn,
impliedStrict: ecmaFeatures.impliedStrict,
ecmaVersion: typeof ecmaVersion === "number" ? ecmaVersion : 6,
- sourceType: parserOptions.sourceType || "script",
+ sourceType: languageOptions.sourceType || "script",
childVisitorKeys: visitorKeys || evk.KEYS,
fallback: Traverser.getKeys
});
* optimization of functions, so it's best to keep the try-catch as isolated
* as possible
* @param {string} text The text to parse.
- * @param {Parser} parser The parser to parse.
- * @param {ParserOptions} providedParserOptions Options to pass to the parser
+ * @param {LanguageOptions} languageOptions Options to pass to the parser
* @param {string} filePath The path to the file being parsed.
* @returns {{success: false, error: Problem}|{success: true, sourceCode: SourceCode}}
* An object containing the AST and parser services if parsing was successful, or the error if parsing failed
*/
-function parse(text, parser, providedParserOptions, filePath) {
+function parse(text, languageOptions, filePath) {
const textToParse = stripUnicodeBOM(text).replace(astUtils.shebangPattern, (match, captured) => "//".concat(captured));
- const parserOptions = Object.assign({}, providedParserOptions, {
+ const {
+ ecmaVersion,
+ sourceType,
+ parser
+ } = languageOptions;
+ const parserOptions = Object.assign({
+ ecmaVersion,
+ sourceType
+ }, languageOptions.parserOptions, {
loc: true,
range: true,
raw: true,
const ast = parseResult.ast;
const parserServices = parseResult.services || {};
const visitorKeys = parseResult.visitorKeys || evk.KEYS;
- const scopeManager = parseResult.scopeManager || analyzeScope(ast, parserOptions, visitorKeys);
+ const scopeManager = parseResult.scopeManager || analyzeScope(ast, languageOptions, visitorKeys);
return {
success: true,
* Marks a variable as used in the current scope
* @param {ScopeManager} scopeManager The scope manager for this AST. The scope may be mutated by this function.
* @param {ASTNode} currentNode The node currently being traversed
- * @param {Object} parserOptions The options used to parse this text
+ * @param {LanguageOptions} languageOptions The options used to parse this text
* @param {string} name The name of the variable that should be marked as used.
* @returns {boolean} True if the variable was found and marked as used, false if not.
*/
-function markVariableAsUsed(scopeManager, currentNode, parserOptions, name) {
- const hasGlobalReturn = parserOptions.ecmaFeatures && parserOptions.ecmaFeatures.globalReturn;
- const specialScope = hasGlobalReturn || parserOptions.sourceType === "module";
+function markVariableAsUsed(scopeManager, currentNode, languageOptions, name) {
+ const parserOptions = languageOptions.parserOptions;
+ const sourceType = languageOptions.sourceType;
+ const hasGlobalReturn = parserOptions.ecmaFeatures && parserOptions.ecmaFeatures.globalReturn || sourceType === "commonjs";
+ const specialScope = hasGlobalReturn || sourceType === "module";
const currentScope = getScope(scopeManager, currentNode); // Special Node.js scope means we need to start one level deeper
const initialScope = currentScope.type === "global" && specialScope ? currentScope.childScopes[0] : currentScope;
* @param {SourceCode} sourceCode A SourceCode object for the given text
* @param {Object} configuredRules The rules configuration
* @param {function(string): Rule} ruleMapper A mapper function from rule names to rules
- * @param {Object} parserOptions The options that were passed to the parser
- * @param {string} parserName The name of the parser in the config
+ * @param {string | undefined} parserName The name of the parser in the config
+ * @param {LanguageOptions} languageOptions The options for parsing the code.
* @param {Object} settings The settings that were enabled in the config
* @param {string} filename The reported filename of the code
* @param {boolean} disableFixes If true, it doesn't make `fix` properties.
* @returns {Problem[]} An array of reported problems
*/
-function runRules(sourceCode, configuredRules, ruleMapper, parserOptions, parserName, settings, filename, disableFixes, cwd, physicalFilename) {
+function runRules(sourceCode, configuredRules, ruleMapper, parserName, languageOptions, settings, filename, disableFixes, cwd, physicalFilename) {
const emitter = createEmitter();
const nodeQueue = [];
let currentNode = sourceCode.ast;
getPhysicalFilename: () => physicalFilename || filename,
getScope: () => getScope(sourceCode.scopeManager, currentNode),
getSourceCode: () => sourceCode,
- markVariableAsUsed: name => markVariableAsUsed(sourceCode.scopeManager, currentNode, parserOptions, name),
- parserOptions,
+ markVariableAsUsed: name => markVariableAsUsed(sourceCode.scopeManager, currentNode, languageOptions, name),
+ parserOptions: { ...languageOptions.parserOptions
+ },
parserPath: parserName,
+ languageOptions,
parserServices: sourceCode.parserServices,
settings
}));
const rule = ruleMapper(ruleId);
- if (rule === null) {
+ if (!rule) {
lintingProblems.push(createLintingProblem({
ruleId
}));
*/
-const internalSlotsMap = new WeakMap(); //------------------------------------------------------------------------------
+const internalSlotsMap = new WeakMap();
+/**
+ * Throws an error when the given linter is in flat config mode.
+ * @param {Linter} linter The linter to check.
+ * @returns {void}
+ * @throws {Error} If the linter is in flat config mode.
+ */
+
+function assertEslintrcConfig(linter) {
+ const {
+ configType
+ } = internalSlotsMap.get(linter);
+
+ if (configType === "flat") {
+ throw new Error("This method cannot be used with flat config. Add your entries directly into the config array.");
+ }
+} //------------------------------------------------------------------------------
// Public Interface
//------------------------------------------------------------------------------
/**
* Object that is responsible for verifying JavaScript text
- * @name eslint
+ * @name Linter
*/
+
class Linter {
/**
* Initialize the Linter.
* @param {Object} [config] the config object
* @param {string} [config.cwd] path to a directory that should be considered as the current working directory, can be undefined.
+ * @param {"flat"|"eslintrc"} [config.configType="eslintrc"] the type of config used.
*/
constructor() {
let {
- cwd
+ cwd,
+ configType
} = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
internalSlotsMap.set(this, {
cwd: normalizeCwd(cwd),
lastConfigArray: null,
lastSourceCode: null,
+ configType,
+ // TODO: Remove after flat config conversion
parserMap: new Map([["espree", espree]]),
ruleMap: new Rules()
});
const parserOptions = resolveParserOptions(parser, config.parserOptions || {}, enabledEnvs);
const configuredGlobals = resolveGlobals(config.globals || {}, enabledEnvs);
const settings = config.settings || {};
+ const languageOptions = createLanguageOptions({
+ globals: config.globals,
+ parser,
+ parserOptions
+ });
if (!slots.lastSourceCode) {
- const parseResult = parse(text, parser, parserOptions, options.filename);
+ const parseResult = parse(text, languageOptions, options.filename);
if (!parseResult.success) {
return [parseResult.error];
ast: slots.lastSourceCode.ast,
parserServices: slots.lastSourceCode.parserServices,
visitorKeys: slots.lastSourceCode.visitorKeys,
- scopeManager: analyzeScope(slots.lastSourceCode.ast, parserOptions)
+ scopeManager: analyzeScope(slots.lastSourceCode.ast, languageOptions)
});
}
}
let lintingProblems;
try {
- lintingProblems = runRules(sourceCode, configuredRules, ruleId => getRule(slots, ruleId), parserOptions, parserName, settings, options.filename, options.disableFixes, slots.cwd, providedOptions.physicalFilename);
+ lintingProblems = runRules(sourceCode, configuredRules, ruleId => getRule(slots, ruleId), parserName, languageOptions, settings, options.filename, options.disableFixes, slots.cwd, providedOptions.physicalFilename);
} catch (err) {
err.message += "\nOccurred while linting ".concat(options.filename);
debug("An error occurred while traversing");
verify(textOrSourceCode, config, filenameOrOptions) {
debug("Verify");
+ const {
+ configType
+ } = internalSlotsMap.get(this);
const options = typeof filenameOrOptions === "string" ? {
filename: filenameOrOptions
- } : filenameOrOptions || {}; // CLIEngine passes a `ConfigArray` object.
+ } : filenameOrOptions || {};
+
+ if (config) {
+ if (configType === "flat") {
+ /*
+ * Because of how Webpack packages up the files, we can't
+ * compare directly to `FlatConfigArray` using `instanceof`
+ * because it's not the same `FlatConfigArray` as in the tests.
+ * So, we work around it by assuming an array is, in fact, a
+ * `FlatConfigArray` if it has a `getConfig()` method.
+ */
+ let configArray = config;
+
+ if (!Array.isArray(config) || typeof config.getConfig !== "function") {
+ configArray = new FlatConfigArray(config);
+ configArray.normalizeSync();
+ }
+
+ return this._verifyWithFlatConfigArray(textOrSourceCode, configArray, options, true);
+ }
- if (config && typeof config.extractConfig === "function") {
- return this._verifyWithConfigArray(textOrSourceCode, config, options);
+ if (typeof config.extractConfig === "function") {
+ return this._verifyWithConfigArray(textOrSourceCode, config, options);
+ }
}
+ /*
+ * If we get to here, it means `config` is just an object rather
+ * than a config array so we can go right into linting.
+ */
+
/*
* `Linter` doesn't support `overrides` property in configuration.
* So we cannot apply multiple processors.
return this._verifyWithoutProcessors(textOrSourceCode, config, options);
}
+ /**
+ * Verify with a processor.
+ * @param {string|SourceCode} textOrSourceCode The source code.
+ * @param {FlatConfig} config The config array.
+ * @param {VerifyOptions&ProcessorOptions} options The options.
+ * @param {FlatConfigArray} [configForRecursive] The `ConfigArray` object to apply multiple processors recursively.
+ * @returns {LintMessage[]} The found problems.
+ */
+
+
+ _verifyWithFlatConfigArrayAndProcessor(textOrSourceCode, config, options, configForRecursive) {
+ const filename = options.filename || "<input>";
+ const filenameToExpose = normalizeFilename(filename);
+ const physicalFilename = options.physicalFilename || filenameToExpose;
+ const text = ensureText(textOrSourceCode);
+
+ const preprocess = options.preprocess || (rawText => [rawText]);
+
+ const postprocess = options.postprocess || (messagesList => messagesList.flat());
+
+ const filterCodeBlock = options.filterCodeBlock || (blockFilename => blockFilename.endsWith(".js"));
+
+ const originalExtname = path.extname(filename);
+ const messageLists = preprocess(text, filenameToExpose).map((block, i) => {
+ debug("A code block was found: %o", block.filename || "(unnamed)"); // Keep the legacy behavior.
+
+ if (typeof block === "string") {
+ return this._verifyWithFlatConfigArrayAndWithoutProcessors(block, config, options);
+ }
+
+ const blockText = block.text;
+ const blockName = path.join(filename, "".concat(i, "_").concat(block.filename)); // Skip this block if filtered.
+
+ if (!filterCodeBlock(blockName, blockText)) {
+ debug("This code block was skipped.");
+ return [];
+ } // Resolve configuration again if the file content or extension was changed.
+
+
+ if (configForRecursive && (text !== blockText || path.extname(blockName) !== originalExtname)) {
+ debug("Resolving configuration again because the file content or extension was changed.");
+ return this._verifyWithFlatConfigArray(blockText, configForRecursive, { ...options,
+ filename: blockName,
+ physicalFilename
+ });
+ } // Does lint.
+
+
+ return this._verifyWithFlatConfigArrayAndWithoutProcessors(blockText, config, { ...options,
+ filename: blockName,
+ physicalFilename
+ });
+ });
+ return postprocess(messageLists, filenameToExpose);
+ }
+ /**
+ * Same as linter.verify, except without support for processors.
+ * @param {string|SourceCode} textOrSourceCode The text to parse or a SourceCode object.
+ * @param {FlatConfig} providedConfig An ESLintConfig instance to configure everything.
+ * @param {VerifyOptions} [providedOptions] The optional filename of the file being checked.
+ * @throws {Error} If during rule execution.
+ * @returns {LintMessage[]} The results as an array of messages or an empty array if no messages.
+ */
+
+
+ _verifyWithFlatConfigArrayAndWithoutProcessors(textOrSourceCode, providedConfig, providedOptions) {
+ const slots = internalSlotsMap.get(this);
+ const config = providedConfig || {};
+ const options = normalizeVerifyOptions(providedOptions, config);
+ let text; // evaluate arguments
+
+ if (typeof textOrSourceCode === "string") {
+ slots.lastSourceCode = null;
+ text = textOrSourceCode;
+ } else {
+ slots.lastSourceCode = textOrSourceCode;
+ text = textOrSourceCode.text;
+ }
+
+ const languageOptions = config.languageOptions;
+ languageOptions.ecmaVersion = normalizeEcmaVersionForLanguageOptions(languageOptions.ecmaVersion); // add configured globals and language globals
+
+ const configuredGlobals = { ...getGlobalsForEcmaVersion(languageOptions.ecmaVersion),
+ ...(languageOptions.sourceType === "commonjs" ? globals.commonjs : void 0),
+ ...languageOptions.globals
+ }; // Espree expects this information to be passed in
+
+ if (isEspree(languageOptions.parser)) {
+ const parserOptions = languageOptions.parserOptions;
+
+ if (languageOptions.sourceType) {
+ parserOptions.sourceType = languageOptions.sourceType;
+
+ if (parserOptions.sourceType === "module" && parserOptions.ecmaFeatures && parserOptions.ecmaFeatures.globalReturn) {
+ parserOptions.ecmaFeatures.globalReturn = false;
+ }
+ }
+ }
+
+ const settings = config.settings || {};
+
+ if (!slots.lastSourceCode) {
+ const parseResult = parse(text, languageOptions, options.filename);
+
+ if (!parseResult.success) {
+ return [parseResult.error];
+ }
+
+ slots.lastSourceCode = parseResult.sourceCode;
+ } else {
+ /*
+ * If the given source code object as the first argument does not have scopeManager, analyze the scope.
+ * This is for backward compatibility (SourceCode is frozen so it cannot rebind).
+ */
+ if (!slots.lastSourceCode.scopeManager) {
+ slots.lastSourceCode = new SourceCode({
+ text: slots.lastSourceCode.text,
+ ast: slots.lastSourceCode.ast,
+ parserServices: slots.lastSourceCode.parserServices,
+ visitorKeys: slots.lastSourceCode.visitorKeys,
+ scopeManager: analyzeScope(slots.lastSourceCode.ast, languageOptions)
+ });
+ }
+ }
+
+ const sourceCode = slots.lastSourceCode;
+ const commentDirectives = options.allowInlineConfig ? getDirectiveComments(options.filename, sourceCode.ast, ruleId => getRuleFromConfig(ruleId, config), options.warnInlineConfig) : {
+ configuredRules: {},
+ enabledGlobals: {},
+ exportedVariables: {},
+ problems: [],
+ disableDirectives: []
+ }; // augment global scope with declared global variables
+
+ addDeclaredGlobals(sourceCode.scopeManager.scopes[0], configuredGlobals, {
+ exportedVariables: commentDirectives.exportedVariables,
+ enabledGlobals: commentDirectives.enabledGlobals
+ });
+ const configuredRules = Object.assign({}, config.rules, commentDirectives.configuredRules);
+ let lintingProblems;
+
+ try {
+ lintingProblems = runRules(sourceCode, configuredRules, ruleId => getRuleFromConfig(ruleId, config), void 0, languageOptions, settings, options.filename, options.disableFixes, slots.cwd, providedOptions.physicalFilename);
+ } catch (err) {
+ err.message += "\nOccurred while linting ".concat(options.filename);
+ debug("An error occurred while traversing");
+ debug("Filename:", options.filename);
+
+ if (err.currentNode) {
+ const {
+ line
+ } = err.currentNode.loc.start;
+ debug("Line:", line);
+ err.message += ":".concat(line);
+ }
+
+ debug("Parser Options:", languageOptions.parserOptions); // debug("Parser Path:", parserName);
+
+ debug("Settings:", settings);
+
+ if (err.ruleId) {
+ err.message += "\nRule: \"".concat(err.ruleId, "\"");
+ }
+
+ throw err;
+ }
+
+ return applyDisableDirectives({
+ directives: commentDirectives.disableDirectives,
+ disableFixes: options.disableFixes,
+ problems: lintingProblems.concat(commentDirectives.problems).sort((problemA, problemB) => problemA.line - problemB.line || problemA.column - problemB.column),
+ reportUnusedDisableDirectives: options.reportUnusedDisableDirectives
+ });
+ }
/**
* Verify a given code with `ConfigArray`.
* @param {string|SourceCode} textOrSourceCode The source code.
return this._verifyWithoutProcessors(textOrSourceCode, config, options);
}
+ /**
+ * Verify a given code with a flat config.
+ * @param {string|SourceCode} textOrSourceCode The source code.
+ * @param {FlatConfigArray} configArray The config array.
+ * @param {VerifyOptions&ProcessorOptions} options The options.
+ * @param {boolean} [firstCall=false] Indicates if this is being called directly
+ * from verify(). (TODO: Remove once eslintrc is removed.)
+ * @returns {LintMessage[]} The found problems.
+ */
+
+
+ _verifyWithFlatConfigArray(textOrSourceCode, configArray, options) {
+ let firstCall = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
+ debug("With flat config: %s", options.filename); // we need a filename to match configs against
+
+ const filename = options.filename || "<input>"; // Store the config array in order to get plugin envs and rules later.
+
+ internalSlotsMap.get(this).lastConfigArray = configArray;
+ const config = configArray.getConfig(filename); // Verify.
+
+ if (config.processor) {
+ debug("Apply the processor: %o", config.processor);
+ const {
+ preprocess,
+ postprocess,
+ supportsAutofix
+ } = config.processor;
+ const disableFixes = options.disableFixes || !supportsAutofix;
+ return this._verifyWithFlatConfigArrayAndProcessor(textOrSourceCode, config, { ...options,
+ filename,
+ disableFixes,
+ postprocess,
+ preprocess
+ }, configArray);
+ } // check for options-based processing
+
+
+ if (firstCall && (options.preprocess || options.postprocess)) {
+ return this._verifyWithFlatConfigArrayAndProcessor(textOrSourceCode, config, options);
+ }
+
+ return this._verifyWithFlatConfigArrayAndWithoutProcessors(textOrSourceCode, config, options);
+ }
/**
* Verify with a processor.
* @param {string|SourceCode} textOrSourceCode The source code.
defineRule(ruleId, ruleModule) {
+ assertEslintrcConfig(this);
internalSlotsMap.get(this).ruleMap.define(ruleId, ruleModule);
}
/**
defineRules(rulesToDefine) {
+ assertEslintrcConfig(this);
Object.getOwnPropertyNames(rulesToDefine).forEach(ruleId => {
this.defineRule(ruleId, rulesToDefine[ruleId]);
});
getRules() {
+ assertEslintrcConfig(this);
const {
lastConfigArray,
ruleMap
defineParser(parserId, parserModule) {
+ assertEslintrcConfig(this);
internalSlotsMap.get(this).parserMap.set(parserId, parserModule);
}
/**
* Performs multiple autofix passes over the text until as many fixes as possible
* have been applied.
* @param {string} text The source text to apply fixes to.
- * @param {ConfigData|ConfigArray} config The ESLint config object to use.
+ * @param {ConfigData|ConfigArray|FlatConfigArray} config The ESLint config object to use.
* @param {VerifyOptions&ProcessorOptions&FixOptions} options The ESLint options object to use.
* @returns {{fixed:boolean,messages:LintMessage[],output:string}} The result of the fix operation as returned from the
* SourceCodeFixer.
const sourceType = normalizeSourceType(options.sourceType);
const ranges = options.range === true;
const locations = options.loc === true;
- const allowReserved = ecmaVersion === 3 ? "never" : false;
+
+ if (ecmaVersion !== 3 && options.allowReserved) {
+
+ // a value of `false` is intentionally allowed here, so a shared config can overwrite it when needed
+ throw new Error("`allowReserved` is only supported when ecmaVersion is 3");
+ }
+ if (typeof options.allowReserved !== "undefined" && typeof options.allowReserved !== "boolean") {
+ throw new Error("`allowReserved`, when present, must be `true` or `false`");
+ }
+ const allowReserved = ecmaVersion === 3 ? (options.allowReserved || "never") : false;
const ecmaFeatures = options.ecmaFeatures || {};
const allowReturnOutsideFunction = options.sourceType === "commonjs" ||
Boolean(ecmaFeatures.globalReturn);
};
};
-const version$1 = "9.1.0";
+const version$1 = "9.2.0";
/**
* @fileoverview Main Espree file that converts Acorn into Esprima output.
/***/ ((module) => {
"use strict";
-module.exports = JSON.parse('{"name":"eslint","version":"8.3.0","author":"Nicholas C. Zakas <nicholas+npm@nczconsulting.com>","description":"An AST-based pattern checker for JavaScript.","bin":{"eslint":"./bin/eslint.js"},"main":"./lib/api.js","exports":{"./package.json":"./package.json",".":"./lib/api.js","./use-at-your-own-risk":"./lib/unsupported-api.js"},"scripts":{"test":"node Makefile.js test","test:cli":"mocha","lint":"node Makefile.js lint","fix":"node Makefile.js lint -- fix","fuzz":"node Makefile.js fuzz","generate-release":"node Makefile.js generateRelease","generate-alpharelease":"node Makefile.js generatePrerelease -- alpha","generate-betarelease":"node Makefile.js generatePrerelease -- beta","generate-rcrelease":"node Makefile.js generatePrerelease -- rc","publish-release":"node Makefile.js publishRelease","gensite":"node Makefile.js gensite","webpack":"node Makefile.js webpack","perf":"node Makefile.js perf"},"gitHooks":{"pre-commit":"lint-staged"},"lint-staged":{"*.js":"eslint --fix","*.md":"markdownlint"},"files":["LICENSE","README.md","bin","conf","lib","messages"],"repository":"eslint/eslint","funding":"https://opencollective.com/eslint","homepage":"https://eslint.org","bugs":"https://github.com/eslint/eslint/issues/","dependencies":{"@eslint/eslintrc":"^1.0.4","@humanwhocodes/config-array":"^0.6.0","ajv":"^6.10.0","chalk":"^4.0.0","cross-spawn":"^7.0.2","debug":"^4.3.2","doctrine":"^3.0.0","enquirer":"^2.3.5","escape-string-regexp":"^4.0.0","eslint-scope":"^7.1.0","eslint-utils":"^3.0.0","eslint-visitor-keys":"^3.1.0","espree":"^9.1.0","esquery":"^1.4.0","esutils":"^2.0.2","fast-deep-equal":"^3.1.3","file-entry-cache":"^6.0.1","functional-red-black-tree":"^1.0.1","glob-parent":"^6.0.1","globals":"^13.6.0","ignore":"^4.0.6","import-fresh":"^3.0.0","imurmurhash":"^0.1.4","is-glob":"^4.0.0","js-yaml":"^4.1.0","json-stable-stringify-without-jsonify":"^1.0.1","levn":"^0.4.1","lodash.merge":"^4.6.2","minimatch":"^3.0.4","natural-compare":"^1.4.0","optionator":"^0.9.1","progress":"^2.0.0","regexpp":"^3.2.0","semver":"^7.2.1","strip-ansi":"^6.0.1","strip-json-comments":"^3.1.0","text-table":"^0.2.0","v8-compile-cache":"^2.0.3"},"devDependencies":{"@babel/core":"^7.4.3","@babel/preset-env":"^7.4.3","babel-loader":"^8.0.5","chai":"^4.0.1","cheerio":"^0.22.0","common-tags":"^1.8.0","core-js":"^3.1.3","dateformat":"^4.5.1","ejs":"^3.0.2","eslint":"file:.","eslint-config-eslint":"file:packages/eslint-config-eslint","eslint-plugin-eslint-comments":"^3.2.0","eslint-plugin-eslint-plugin":"^4.0.1","eslint-plugin-internal-rules":"file:tools/internal-rules","eslint-plugin-jsdoc":"^37.0.0","eslint-plugin-node":"^11.1.0","eslint-release":"^3.2.0","eslump":"^3.0.0","esprima":"^4.0.1","fs-teardown":"^0.1.3","glob":"^7.1.6","jsdoc":"^3.5.5","karma":"^6.1.1","karma-chrome-launcher":"^3.1.0","karma-mocha":"^2.0.1","karma-mocha-reporter":"^2.2.5","karma-webpack":"^5.0.0","lint-staged":"^11.0.0","load-perf":"^0.2.0","markdownlint":"^0.23.1","markdownlint-cli":"^0.28.1","memfs":"^3.0.1","mocha":"^8.3.2","mocha-junit-reporter":"^2.0.0","node-polyfill-webpack-plugin":"^1.0.3","npm-license":"^0.3.3","nyc":"^15.0.1","proxyquire":"^2.0.1","puppeteer":"^9.1.1","recast":"^0.20.4","regenerator-runtime":"^0.13.2","shelljs":"^0.8.2","sinon":"^11.0.0","temp":"^0.9.0","webpack":"^5.23.0","webpack-cli":"^4.5.0","yorkie":"^2.0.0"},"keywords":["ast","lint","javascript","ecmascript","espree"],"license":"MIT","engines":{"node":"^12.22.0 || ^14.17.0 || >=16.0.0"}}');
+module.exports = JSON.parse('{"name":"eslint","version":"8.4.0","author":"Nicholas C. Zakas <nicholas+npm@nczconsulting.com>","description":"An AST-based pattern checker for JavaScript.","bin":{"eslint":"./bin/eslint.js"},"main":"./lib/api.js","exports":{"./package.json":"./package.json",".":"./lib/api.js","./use-at-your-own-risk":"./lib/unsupported-api.js"},"scripts":{"test":"node Makefile.js test","test:cli":"mocha","lint":"node Makefile.js lint","fix":"node Makefile.js lint -- fix","fuzz":"node Makefile.js fuzz","generate-release":"node Makefile.js generateRelease","generate-alpharelease":"node Makefile.js generatePrerelease -- alpha","generate-betarelease":"node Makefile.js generatePrerelease -- beta","generate-rcrelease":"node Makefile.js generatePrerelease -- rc","publish-release":"node Makefile.js publishRelease","gensite":"node Makefile.js gensite","webpack":"node Makefile.js webpack","perf":"node Makefile.js perf"},"gitHooks":{"pre-commit":"lint-staged"},"lint-staged":{"*.js":"eslint --fix","*.md":"markdownlint"},"files":["LICENSE","README.md","bin","conf","lib","messages"],"repository":"eslint/eslint","funding":"https://opencollective.com/eslint","homepage":"https://eslint.org","bugs":"https://github.com/eslint/eslint/issues/","dependencies":{"@eslint/eslintrc":"^1.0.5","@humanwhocodes/config-array":"^0.9.2","ajv":"^6.10.0","chalk":"^4.0.0","cross-spawn":"^7.0.2","debug":"^4.3.2","doctrine":"^3.0.0","enquirer":"^2.3.5","escape-string-regexp":"^4.0.0","eslint-scope":"^7.1.0","eslint-utils":"^3.0.0","eslint-visitor-keys":"^3.1.0","espree":"^9.2.0","esquery":"^1.4.0","esutils":"^2.0.2","fast-deep-equal":"^3.1.3","file-entry-cache":"^6.0.1","functional-red-black-tree":"^1.0.1","glob-parent":"^6.0.1","globals":"^13.6.0","ignore":"^4.0.6","import-fresh":"^3.0.0","imurmurhash":"^0.1.4","is-glob":"^4.0.0","js-yaml":"^4.1.0","json-stable-stringify-without-jsonify":"^1.0.1","levn":"^0.4.1","lodash.merge":"^4.6.2","minimatch":"^3.0.4","natural-compare":"^1.4.0","optionator":"^0.9.1","progress":"^2.0.0","regexpp":"^3.2.0","semver":"^7.2.1","strip-ansi":"^6.0.1","strip-json-comments":"^3.1.0","text-table":"^0.2.0","v8-compile-cache":"^2.0.3"},"devDependencies":{"@babel/core":"^7.4.3","@babel/preset-env":"^7.4.3","babel-loader":"^8.0.5","chai":"^4.0.1","cheerio":"^0.22.0","common-tags":"^1.8.0","core-js":"^3.1.3","dateformat":"^4.5.1","ejs":"^3.0.2","eslint":"file:.","eslint-config-eslint":"file:packages/eslint-config-eslint","eslint-plugin-eslint-comments":"^3.2.0","eslint-plugin-eslint-plugin":"^4.0.1","eslint-plugin-internal-rules":"file:tools/internal-rules","eslint-plugin-jsdoc":"^37.0.0","eslint-plugin-node":"^11.1.0","eslint-release":"^3.2.0","eslump":"^3.0.0","esprima":"^4.0.1","fs-teardown":"^0.1.3","glob":"^7.1.6","jsdoc":"^3.5.5","karma":"^6.1.1","karma-chrome-launcher":"^3.1.0","karma-mocha":"^2.0.1","karma-mocha-reporter":"^2.2.5","karma-webpack":"^5.0.0","lint-staged":"^11.0.0","load-perf":"^0.2.0","markdownlint":"^0.24.0","markdownlint-cli":"^0.30.0","memfs":"^3.0.1","mocha":"^8.3.2","mocha-junit-reporter":"^2.0.0","node-polyfill-webpack-plugin":"^1.0.3","npm-license":"^0.3.3","nyc":"^15.0.1","proxyquire":"^2.0.1","puppeteer":"^9.1.1","recast":"^0.20.4","regenerator-runtime":"^0.13.2","shelljs":"^0.8.2","sinon":"^11.0.0","temp":"^0.9.0","webpack":"^5.23.0","webpack-cli":"^4.5.0","yorkie":"^2.0.0"},"keywords":["ast","lint","javascript","ecmascript","espree"],"license":"MIT","engines":{"node":"^12.22.0 || ^14.17.0 || >=16.0.0"}}');
/***/ }),
/* 444 */
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "suggestion",
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
deprecated: true,
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "suggestion",
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "suggestion",
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "suggestion",
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "suggestion",
* @author Chiawen Chen
*/
+/** @type {import('../shared/types').Rule} */
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
const validIdentifier = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/u; // `null` literal must be handled separately.
const literalTypesToCheck = new Set(["string", "boolean"]);
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "suggestion",
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "layout",
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "problem",
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
},
additionalProperties: false
};
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "suggestion",
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "suggestion",
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "layout",
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
additionalProperties: false
}]
};
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "layout",
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
const reference = findReference(scope, node);
return reference && reference.resolved && reference.resolved.defs.length > 0;
}
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "suggestion",
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
deprecated: true,
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "suggestion",
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "suggestion",
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
enum: ["first", "off"]
}]
};
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "layout",
/* istanbul ignore next: this rule has known coverage issues, but it's deprecated and shouldn't be updated in the future anyway. */
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "layout",
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "suggestion",
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "suggestion",
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "layout",
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
},
schema: [OPTIONS_OR_INTEGER_SCHEMA],
messages: {
- exceed: "{{name}} has too many lines ({{lineCount}}). Maximum allowed is {{maxLines}}."
+ exceed: "{{name}} has exceeded the limit of lines allowed by {{linesExceed}}. Maximum allowed number of lines per function is {{maxLines}}."
}
},
}
let lineCount = 0;
+ let comments = 0;
+ let blankLines = 0;
for (let i = node.loc.start.line - 1; i < node.loc.end.line; ++i) {
const line = lines[i];
if (skipComments) {
if (commentLineNumbers.has(i + 1) && isFullLineComment(line, i + 1, commentLineNumbers.get(i + 1))) {
+ if (lineCount <= maxLines) {
+ comments++;
+ }
+
continue;
}
}
if (skipBlankLines) {
if (line.match(/^\s*$/u)) {
+ if (lineCount <= maxLines) {
+ blankLines++;
+ }
+
continue;
}
}
if (lineCount > maxLines) {
const name = upperCaseFirst(astUtils.getFunctionNameWithKind(funcNode));
+ const linesExceed = lineCount - maxLines;
+ const loc = {
+ start: {
+ line: node.loc.start.line + maxLines + (comments + blankLines),
+ column: 0
+ },
+ end: node.loc.end
+ };
context.report({
node,
+ loc,
messageId: "exceed",
data: {
name,
- lineCount,
+ linesExceed,
maxLines
}
});
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "suggestion",
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "layout",
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "suggestion",
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "problem",
return false;
}
}
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "suggestion",
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
deprecated: true,
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "suggestion",
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "suggestion",
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "problem",
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "problem",
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "problem",
case "ArrowFunctionExpression":
case "FunctionExpression":
case "ObjectExpression":
+ case "ClassExpression":
return true;
case "TemplateLiteral":
return isLeftConstant && isRightConstant || isLeftShortCircuit || isRightShortCircuit;
}
+ case "NewExpression":
+ return inBooleanPosition;
+
case "AssignmentExpression":
if (node.operator === "=") {
return isConstant(node.right, inBooleanPosition);
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "problem",
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "suggestion",
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "problem",
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "problem",
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "suggestion",
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "suggestion",
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "problem",
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "problem",
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
}
};
}
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "problem",
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "problem",
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "suggestion",
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "suggestion",
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "suggestion",
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
} = __webpack_require__(501);
const astUtils = __webpack_require__(548);
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "suggestion",
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "suggestion",
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
return "program";
}
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "problem",
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "problem",
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "suggestion",
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "suggestion",
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "problem",
return x;
}
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "problem",
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
deprecated: true,
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "layout",
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "suggestion",
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "layout",
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "suggestion",
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "suggestion",
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "problem",
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "suggestion",
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "suggestion",
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "suggestion",
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
deprecated: true,
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "problem",
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "suggestion",
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "suggestion",
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "suggestion",
//------------------------------------------------------------------------------
const stopNodePattern = /(?:Statement|Declaration|Function(?:Expression)?|Program)$/u;
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "suggestion",
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
deprecated: true,
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
deprecated: true,
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
deprecated: true,
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "suggestion",
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "suggestion",
uniqueItems: true
}]
};
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "suggestion",
},
uniqueItems: true
};
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
deprecated: true,
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "suggestion",
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "suggestion",
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "problem",
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "suggestion",
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "layout",
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "problem",
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
deprecated: true,
// Public Interface
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "layout",
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "problem",
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "suggestion",
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "suggestion",
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "suggestion",
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "suggestion",
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "problem",
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
function isDestructuringPattern(node) {
return node.type === "ObjectPattern" || node.type === "ArrayPattern";
}
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
function alwaysFalse() {
return false;
}
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "suggestion",
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "problem",
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "suggestion",
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
});
return charList;
}
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "suggestion",
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "suggestion",
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "suggestion",
const POSITION_SCHEMA = {
enum: ["beside", "below", "any"]
};
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "layout",
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "layout",
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "suggestion",
function canBeFixed(node) {
return node.type === "Identifier" || node.type === "MemberExpression" && (node.object.type === "Identifier" || node.object.type === "ThisExpression") && (!node.computed || node.property.type === "Literal");
}
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "layout",
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "suggestion",
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "suggestion",
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
}
};
}
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "suggestion",
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "layout",
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
* @deprecated in ESLint v5.10.0
*/
+/** @type {import('../shared/types').Rule} */
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "suggestion",
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "layout",
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
const nodeList = getChildren(node.parent);
return nodeList !== null && nodeList[nodeList.length - 1] === node; // before `}` or etc.
}
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "suggestion",
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "suggestion",
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "suggestion",
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "layout",
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "layout",
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "problem",
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "suggestion",
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "layout",
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
type: "layout",
// Rule Definition
//------------------------------------------------------------------------------
+/** @type {import('../shared/types').Rule} */
+
module.exports = {
meta: {
/***/ }),
/* 859 */
-/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+/***/ ((module) => {
"use strict";
+/**
+ * @fileoverview Shared functions to work with configs.
+ * @author Nicholas C. Zakas
+ */
+ //-----------------------------------------------------------------------------
+// Functions
+//-----------------------------------------------------------------------------
+/**
+ * Parses a ruleId into its plugin and rule parts.
+ * @param {string} ruleId The rule ID to parse.
+ * @returns {{pluginName:string,ruleName:string}} The plugin and rule
+ * parts of the ruleId;
+ */
+
+function parseRuleId(ruleId) {
+ let pluginName, ruleName; // distinguish between core rules and plugin rules
+
+ if (ruleId.includes("/")) {
+ pluginName = ruleId.slice(0, ruleId.lastIndexOf("/"));
+ ruleName = ruleId.slice(pluginName.length + 1);
+ } else {
+ pluginName = "@";
+ ruleName = ruleId;
+ }
+
+ return {
+ pluginName,
+ ruleName
+ };
+}
+/**
+ * Retrieves a rule instance from a given config based on the ruleId.
+ * @param {string} ruleId The rule ID to look for.
+ * @param {FlatConfig} config The config to search.
+ * @returns {import("../shared/types").Rule|undefined} The rule if found
+ * or undefined if not.
+ */
+
+
+function getRuleFromConfig(ruleId, config) {
+ const {
+ pluginName,
+ ruleName
+ } = parseRuleId(ruleId);
+ const plugin = config.plugins && config.plugins[pluginName];
+ let rule = plugin && plugin.rules && plugin.rules[ruleName]; // normalize function rules into objects
+
+ if (rule && typeof rule === "function") {
+ rule = {
+ create: rule
+ };
+ }
+
+ return rule;
+} //-----------------------------------------------------------------------------
+// Exports
+//-----------------------------------------------------------------------------
-const {
- CLIEngine
-} = __webpack_require__(860);
module.exports = {
- CLIEngine
+ parseRuleId,
+ getRuleFromConfig
};
/***/ }),
/* 860 */
-/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
"use strict";
-/* provided dependency */ var process = __webpack_require__(494);
/**
- * @fileoverview Main CLI object.
+ * @fileoverview Flat Config Array
* @author Nicholas C. Zakas
*/
+ //-----------------------------------------------------------------------------
+// Requirements
+//-----------------------------------------------------------------------------
-/*
- * The CLI object should *not* call process.exit() directly. It should only return
- * exit codes. This allows other programs to use the CLI object and still control
- * when the program exits.
+const {
+ ConfigArray,
+ ConfigArraySymbol
+} = __webpack_require__(861);
+
+const {
+ flatConfigSchema
+} = __webpack_require__(870);
+
+const {
+ RuleValidator
+} = __webpack_require__(871);
+
+const {
+ defaultConfig
+} = __webpack_require__(874);
+
+const recommendedConfig = __webpack_require__(875);
+
+const allConfig = __webpack_require__(876); //-----------------------------------------------------------------------------
+// Helpers
+//-----------------------------------------------------------------------------
+
+
+const ruleValidator = new RuleValidator();
+/**
+ * Splits a plugin identifier in the form a/b/c into two parts: a/b and c.
+ * @param {string} identifier The identifier to parse.
+ * @returns {{objectName: string, pluginName: string}} The parts of the plugin
+ * name.
*/
-//------------------------------------------------------------------------------
-// Requirements
-//------------------------------------------------------------------------------
-const fs = __webpack_require__(861);
+function splitPluginIdentifier(identifier) {
+ const parts = identifier.split("/");
+ return {
+ objectName: parts.pop(),
+ pluginName: parts.join("/")
+ };
+} //-----------------------------------------------------------------------------
+// Exports
+//-----------------------------------------------------------------------------
-const path = __webpack_require__(429);
+/**
+ * Represents an array containing configuration information for ESLint.
+ */
-const defaultOptions = __webpack_require__(862);
-const pkg = __webpack_require__(443);
+class FlatConfigArray extends ConfigArray {
+ /**
+ * Creates a new instance.
+ * @param {*[]} configs An array of configuration information.
+ * @param {{basePath: string, baseConfig: FlatConfig}} options The options
+ * to use for the config array instance.
+ */
+ constructor(configs) {
+ let {
+ basePath,
+ baseConfig = defaultConfig
+ } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
+ super(configs, {
+ basePath,
+ schema: flatConfigSchema
+ });
+ this.unshift(...baseConfig);
+ }
+ /* eslint-disable class-methods-use-this -- Desired as instance method */
-const {
- Legacy: {
- ConfigOps,
- naming,
- CascadingConfigArrayFactory,
- IgnorePattern,
- getUsedExtractedConfigs,
- ModuleResolver
+ /**
+ * Replaces a config with another config to allow us to put strings
+ * in the config array that will be replaced by objects before
+ * normalization.
+ * @param {Object} config The config to preprocess.
+ * @returns {Object} The preprocessed config.
+ */
+
+
+ [ConfigArraySymbol.preprocessConfig](config) {
+ if (config === "eslint:recommended") {
+ return recommendedConfig;
+ }
+
+ if (config === "eslint:all") {
+ return allConfig;
+ }
+
+ return config;
}
-} = __webpack_require__(863);
+ /**
+ * Finalizes the config by replacing plugin references with their objects
+ * and validating rule option schemas.
+ * @param {Object} config The config to finalize.
+ * @returns {Object} The finalized config.
+ * @throws {TypeError} If the config is invalid.
+ */
-const {
- FileEnumerator
-} = __webpack_require__(877);
-const {
- Linter
-} = __webpack_require__(881);
+ [ConfigArraySymbol.finalizeConfig](config) {
+ const {
+ plugins,
+ languageOptions,
+ processor
+ } = config; // Check parser value
-const builtInRules = __webpack_require__(545);
+ if (languageOptions && languageOptions.parser && typeof languageOptions.parser === "string") {
+ const {
+ pluginName,
+ objectName: parserName
+ } = splitPluginIdentifier(languageOptions.parser);
-const loadRules = __webpack_require__(882);
+ if (!plugins || !plugins[pluginName] || !plugins[pluginName].parsers || !plugins[pluginName].parsers[parserName]) {
+ throw new TypeError("Key \"parser\": Could not find \"".concat(parserName, "\" in plugin \"").concat(pluginName, "\"."));
+ }
-const hash = __webpack_require__(884);
+ languageOptions.parser = plugins[pluginName].parsers[parserName];
+ } // Check processor value
-const LintResultCache = __webpack_require__(886);
-const debug = __webpack_require__(496)("eslint:cli-engine");
+ if (processor && typeof processor === "string") {
+ const {
+ pluginName,
+ objectName: processorName
+ } = splitPluginIdentifier(processor);
-const validFixTypes = new Set(["directive", "problem", "suggestion", "layout"]); //------------------------------------------------------------------------------
-// Typedefs
-//------------------------------------------------------------------------------
-// For VSCode IntelliSense
+ if (!plugins || !plugins[pluginName] || !plugins[pluginName].processors || !plugins[pluginName].processors[processorName]) {
+ throw new TypeError("Key \"processor\": Could not find \"".concat(processorName, "\" in plugin \"").concat(pluginName, "\"."));
+ }
-/** @typedef {import("../shared/types").ConfigData} ConfigData */
+ config.processor = plugins[pluginName].processors[processorName];
+ }
-/** @typedef {import("../shared/types").DeprecatedRuleInfo} DeprecatedRuleInfo */
+ ruleValidator.validate(config);
+ return config;
+ }
+ /* eslint-enable class-methods-use-this -- Desired as instance method */
-/** @typedef {import("../shared/types").LintMessage} LintMessage */
-/** @typedef {import("../shared/types").ParserOptions} ParserOptions */
+}
-/** @typedef {import("../shared/types").Plugin} Plugin */
+exports.FlatConfigArray = FlatConfigArray;
-/** @typedef {import("../shared/types").RuleConf} RuleConf */
+/***/ }),
+/* 861 */
+/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
-/** @typedef {import("../shared/types").Rule} Rule */
+"use strict";
-/** @typedef {ReturnType<CascadingConfigArrayFactory.getConfigArrayForFile>} ConfigArray */
-/** @typedef {ReturnType<ConfigArray.extractConfig>} ExtractedConfig */
+Object.defineProperty(exports, "__esModule", ({
+ value: true
+}));
-/**
- * The options to configure a CLI engine with.
- * @typedef {Object} CLIEngineOptions
- * @property {boolean} [allowInlineConfig] Enable or disable inline configuration comments.
- * @property {ConfigData} [baseConfig] Base config object, extended by all configs used with this CLIEngine instance
- * @property {boolean} [cache] Enable result caching.
- * @property {string} [cacheLocation] The cache file to use instead of .eslintcache.
- * @property {string} [configFile] The configuration file to use.
- * @property {string} [cwd] The value to use for the current working directory.
- * @property {string[]} [envs] An array of environments to load.
- * @property {string[]|null} [extensions] An array of file extensions to check.
- * @property {boolean|Function} [fix] Execute in autofix mode. If a function, should return a boolean.
- * @property {string[]} [fixTypes] Array of rule types to apply fixes for.
- * @property {string[]} [globals] An array of global variables to declare.
- * @property {boolean} [ignore] False disables use of .eslintignore.
- * @property {string} [ignorePath] The ignore file to use instead of .eslintignore.
- * @property {string|string[]} [ignorePattern] One or more glob patterns to ignore.
- * @property {boolean} [useEslintrc] False disables looking for .eslintrc
- * @property {string} [parser] The name of the parser to use.
- * @property {ParserOptions} [parserOptions] An object of parserOption settings to use.
- * @property {string[]} [plugins] An array of plugins to load.
- * @property {Record<string,RuleConf>} [rules] An object of rules to use.
- * @property {string[]} [rulePaths] An array of directories to load custom rules from.
- * @property {boolean} [reportUnusedDisableDirectives] `true` adds reports for unused eslint-disable directives
- * @property {boolean} [globInputPaths] Set to false to skip glob resolution of input file paths to lint (default: true). If false, each input file paths is assumed to be a non-glob path to an existing file.
- * @property {string} [resolvePluginsRelativeTo] The folder where plugins should be resolved from, defaulting to the CWD
- */
+function _interopDefault(ex) {
+ return ex && typeof ex === 'object' && 'default' in ex ? ex['default'] : ex;
+}
-/**
- * A linting result.
- * @typedef {Object} LintResult
- * @property {string} filePath The path to the file that was linted.
- * @property {LintMessage[]} messages All of the messages for the result.
- * @property {number} errorCount Number of errors for the result.
- * @property {number} warningCount Number of warnings for the result.
- * @property {number} fixableErrorCount Number of fixable errors for the result.
- * @property {number} fixableWarningCount Number of fixable warnings for the result.
- * @property {string} [source] The source code of the file that was linted.
- * @property {string} [output] The source code of the file that was linted, with as many fixes applied as possible.
- */
+var path = _interopDefault(__webpack_require__(429));
-/**
- * Linting results.
- * @typedef {Object} LintReport
- * @property {LintResult[]} results All of the result.
- * @property {number} errorCount Number of errors for the result.
- * @property {number} warningCount Number of warnings for the result.
- * @property {number} fixableErrorCount Number of fixable errors for the result.
- * @property {number} fixableWarningCount Number of fixable warnings for the result.
- * @property {DeprecatedRuleInfo[]} usedDeprecatedRules The list of used deprecated rules.
- */
+var minimatch = _interopDefault(__webpack_require__(862));
+
+var createDebug = _interopDefault(__webpack_require__(496));
+var objectSchema = __webpack_require__(866);
/**
- * Private data for CLIEngine.
- * @typedef {Object} CLIEngineInternalSlots
- * @property {Map<string, Plugin>} additionalPluginPool The map for additional plugins.
- * @property {string} cacheFilePath The path to the cache of lint results.
- * @property {CascadingConfigArrayFactory} configArrayFactory The factory of configs.
- * @property {(filePath: string) => boolean} defaultIgnores The default predicate function to check if a file ignored or not.
- * @property {FileEnumerator} fileEnumerator The file enumerator.
- * @property {ConfigArray[]} lastConfigArrays The list of config arrays that the last `executeOnFiles` or `executeOnText` used.
- * @property {LintResultCache|null} lintResultCache The cache of lint results.
- * @property {Linter} linter The linter instance which has loaded rules.
- * @property {CLIEngineOptions} options The normalized options of this instance.
+ * @fileoverview ConfigSchema
+ * @author Nicholas C. Zakas
*/
//------------------------------------------------------------------------------
// Helpers
//------------------------------------------------------------------------------
-/** @type {WeakMap<CLIEngine, CLIEngineInternalSlots>} */
-
-const internalSlotsMap = new WeakMap();
/**
- * Determines if each fix type in an array is supported by ESLint and throws
- * an error if not.
- * @param {string[]} fixTypes An array of fix types to check.
+ * Assets that a given value is an array.
+ * @param {*} value The value to check.
* @returns {void}
- * @throws {Error} If an invalid fix type is found.
+ * @throws {TypeError} When the value is not an array.
*/
-function validateFixTypes(fixTypes) {
- for (const fixType of fixTypes) {
- if (!validFixTypes.has(fixType)) {
- throw new Error("Invalid fix type \"".concat(fixType, "\" found."));
- }
+
+function assertIsArray(value) {
+ if (!Array.isArray(value)) {
+ throw new TypeError('Expected value to be an array.');
}
}
/**
- * It will calculate the error and warning count for collection of messages per file
- * @param {LintMessage[]} messages Collection of messages
- * @returns {Object} Contains the stats
- * @private
+ * Assets that a given value is an array containing only strings and functions.
+ * @param {*} value The value to check.
+ * @returns {void}
+ * @throws {TypeError} When the value is not an array of strings and functions.
*/
-function calculateStatsPerFile(messages) {
- return messages.reduce((stat, message) => {
- if (message.fatal || message.severity === 2) {
- stat.errorCount++;
+function assertIsArrayOfStringsAndFunctions(value, name) {
+ assertIsArray(value);
- if (message.fatal) {
- stat.fatalErrorCount++;
- }
+ if (value.some(item => typeof item !== 'string' && typeof item !== 'function')) {
+ throw new TypeError('Expected array to only contain strings.');
+ }
+} //------------------------------------------------------------------------------
+// Exports
+//------------------------------------------------------------------------------
- if (message.fix) {
- stat.fixableErrorCount++;
- }
- } else {
- stat.warningCount++;
+/**
+ * The base schema that every ConfigArray uses.
+ * @type Object
+ */
- if (message.fix) {
- stat.fixableWarningCount++;
+
+const baseSchema = Object.freeze({
+ name: {
+ required: false,
+
+ merge() {
+ return undefined;
+ },
+
+ validate(value) {
+ if (typeof value !== 'string') {
+ throw new TypeError('Property must be a string.');
}
}
- return stat;
- }, {
- errorCount: 0,
- fatalErrorCount: 0,
- warningCount: 0,
- fixableErrorCount: 0,
- fixableWarningCount: 0
- });
-}
+ },
+ files: {
+ required: false,
+
+ merge() {
+ return undefined;
+ },
+
+ validate(value) {
+ // first check if it's an array
+ assertIsArray(value); // then check each member
+
+ value.forEach(item => {
+ if (Array.isArray(item)) {
+ assertIsArrayOfStringsAndFunctions(item);
+ } else if (typeof item !== 'string' && typeof item !== 'function') {
+ throw new TypeError('Items must be a string, a function, or an array of strings and functions.');
+ }
+ });
+ }
+
+ },
+ ignores: {
+ required: false,
+
+ merge() {
+ return undefined;
+ },
+
+ validate: assertIsArrayOfStringsAndFunctions
+ }
+});
/**
- * It will calculate the error and warning count for collection of results from all files
- * @param {LintResult[]} results Collection of messages from all the files
- * @returns {Object} Contains the stats
- * @private
+ * @fileoverview ConfigArray
+ * @author Nicholas C. Zakas
*/
+//------------------------------------------------------------------------------
+// Helpers
+//------------------------------------------------------------------------------
+const debug = createDebug('@hwc/config-array');
+const MINIMATCH_OPTIONS = {
+ matchBase: true
+};
+const CONFIG_TYPES = new Set(['array', 'function']);
+/**
+ * Shorthand for checking if a value is a string.
+ * @param {any} value The value to check.
+ * @returns {boolean} True if a string, false if not.
+ */
-function calculateStatsPerRun(results) {
- return results.reduce((stat, result) => {
- stat.errorCount += result.errorCount;
- stat.fatalErrorCount += result.fatalErrorCount;
- stat.warningCount += result.warningCount;
- stat.fixableErrorCount += result.fixableErrorCount;
- stat.fixableWarningCount += result.fixableWarningCount;
- return stat;
- }, {
- errorCount: 0,
- fatalErrorCount: 0,
- warningCount: 0,
- fixableErrorCount: 0,
- fixableWarningCount: 0
- });
+function isString(value) {
+ return typeof value === 'string';
}
/**
- * Processes an source code using ESLint.
- * @param {Object} config The config object.
- * @param {string} config.text The source code to verify.
- * @param {string} config.cwd The path to the current working directory.
- * @param {string|undefined} config.filePath The path to the file of `text`. If this is undefined, it uses `<text>`.
- * @param {ConfigArray} config.config The config.
- * @param {boolean} config.fix If `true` then it does fix.
- * @param {boolean} config.allowInlineConfig If `true` then it uses directive comments.
- * @param {boolean} config.reportUnusedDisableDirectives If `true` then it reports unused `eslint-disable` comments.
- * @param {FileEnumerator} config.fileEnumerator The file enumerator to check if a path is a target or not.
- * @param {Linter} config.linter The linter instance to verify.
- * @returns {LintResult} The result of linting.
- * @private
+ * Normalizes a `ConfigArray` by flattening it and executing any functions
+ * that are found inside.
+ * @param {Array} items The items in a `ConfigArray`.
+ * @param {Object} context The context object to pass into any function
+ * found.
+ * @param {Array<string>} extraConfigTypes The config types to check.
+ * @returns {Promise<Array>} A flattened array containing only config objects.
+ * @throws {TypeError} When a config function returns a function.
*/
-function verifyText(_ref) {
- let {
- text,
- cwd,
- filePath: providedFilePath,
- config,
- fix,
- allowInlineConfig,
- reportUnusedDisableDirectives,
- fileEnumerator,
- linter
- } = _ref;
- const filePath = providedFilePath || "<text>";
- debug("Lint ".concat(filePath));
- /*
- * Verify.
- * `config.extractConfig(filePath)` requires an absolute path, but `linter`
- * doesn't know CWD, so it gives `linter` an absolute path always.
- */
+async function normalize(items, context, extraConfigTypes) {
+ const allowFunctions = extraConfigTypes.includes('function');
+ const allowArrays = extraConfigTypes.includes('array');
- const filePathToVerify = filePath === "<text>" ? path.join(cwd, filePath) : filePath;
- const {
- fixed,
- messages,
- output
- } = linter.verifyAndFix(text, config, {
- allowInlineConfig,
- filename: filePathToVerify,
- fix,
- reportUnusedDisableDirectives,
+ async function* flatTraverse(array) {
+ for (let item of array) {
+ if (typeof item === 'function') {
+ if (!allowFunctions) {
+ throw new TypeError('Unexpected function.');
+ }
- /**
- * Check if the linter should adopt a given code block or not.
- * @param {string} blockFilename The virtual filename of a code block.
- * @returns {boolean} `true` if the linter should adopt the code block.
- */
- filterCodeBlock(blockFilename) {
- return fileEnumerator.isTargetPath(blockFilename);
- }
+ item = item(context);
- }); // Tweak and return.
+ if (item.then) {
+ item = await item;
+ }
+ }
- const result = {
- filePath,
- messages,
- ...calculateStatsPerFile(messages)
- };
+ if (Array.isArray(item)) {
+ if (!allowArrays) {
+ throw new TypeError('Unexpected array.');
+ }
- if (fixed) {
- result.output = output;
+ yield* flatTraverse(item);
+ } else if (typeof item === 'function') {
+ throw new TypeError('A config function can only return an object or array.');
+ } else {
+ yield item;
+ }
+ }
}
+ /*
+ * Async iterables cannot be used with the spread operator, so we need to manually
+ * create the array to return.
+ */
- if (result.errorCount + result.warningCount > 0 && typeof result.output === "undefined") {
- result.source = text;
+
+ const asyncIterable = await flatTraverse(items);
+ const configs = [];
+
+ for await (const config of asyncIterable) {
+ configs.push(config);
}
- return result;
+ return configs;
}
/**
- * Returns result with warning by ignore settings
- * @param {string} filePath File path of checked code
- * @param {string} baseDir Absolute path of base directory
- * @returns {LintResult} Result with single warning
- * @private
+ * Normalizes a `ConfigArray` by flattening it and executing any functions
+ * that are found inside.
+ * @param {Array} items The items in a `ConfigArray`.
+ * @param {Object} context The context object to pass into any function
+ * found.
+ * @param {Array<string>} extraConfigTypes The config types to check.
+ * @returns {Array} A flattened array containing only config objects.
+ * @throws {TypeError} When a config function returns a function.
*/
-function createIgnoreResult(filePath, baseDir) {
- let message;
- const isHidden = filePath.split(path.sep).find(segment => /^\./u.test(segment));
- const isInNodeModules = baseDir && path.relative(baseDir, filePath).startsWith("node_modules");
+function normalizeSync(items, context, extraConfigTypes) {
+ const allowFunctions = extraConfigTypes.includes('function');
+ const allowArrays = extraConfigTypes.includes('array');
- if (isHidden) {
- message = "File ignored by default. Use a negated ignore pattern (like \"--ignore-pattern '!<relative/path/to/filename>'\") to override.";
- } else if (isInNodeModules) {
- message = "File ignored by default. Use \"--ignore-pattern '!node_modules/*'\" to override.";
- } else {
- message = "File ignored because of a matching ignore pattern. Use \"--no-ignore\" to override.";
- }
+ function* flatTraverse(array) {
+ for (let item of array) {
+ if (typeof item === 'function') {
+ if (!allowFunctions) {
+ throw new TypeError('Unexpected function.');
+ }
- return {
- filePath: path.resolve(filePath),
- messages: [{
- fatal: false,
- severity: 1,
- message
- }],
- errorCount: 0,
- warningCount: 1,
- fixableErrorCount: 0,
- fixableWarningCount: 0
- };
-}
-/**
- * Get a rule.
- * @param {string} ruleId The rule ID to get.
- * @param {ConfigArray[]} configArrays The config arrays that have plugin rules.
- * @returns {Rule|null} The rule or null.
- */
+ item = item(context);
+ if (item.then) {
+ throw new TypeError('Async config functions are not supported.');
+ }
+ }
-function getRule(ruleId, configArrays) {
- for (const configArray of configArrays) {
- const rule = configArray.pluginRules.get(ruleId);
+ if (Array.isArray(item)) {
+ if (!allowArrays) {
+ throw new TypeError('Unexpected array.');
+ }
- if (rule) {
- return rule;
+ yield* flatTraverse(item);
+ } else if (typeof item === 'function') {
+ throw new TypeError('A config function can only return an object or array.');
+ } else {
+ yield item;
+ }
}
}
- return builtInRules.get(ruleId) || null;
+ return [...flatTraverse(items)];
}
/**
- * Checks whether a message's rule type should be fixed.
- * @param {LintMessage} message The message to check.
- * @param {ConfigArray[]} lastConfigArrays The list of config arrays that the last `executeOnFiles` or `executeOnText` used.
- * @param {string[]} fixTypes An array of fix types to check.
- * @returns {boolean} Whether the message should be fixed.
+ * Determines if a given file path should be ignored based on the given
+ * matcher.
+ * @param {string|() => boolean} matcher The pattern to match.
+ * @param {string} filePath The absolute path of the file to check.
+ * @param {string} relativeFilePath The relative path of the file to check.
+ * @returns {boolean} True if the path should be ignored and false if not.
*/
-function shouldMessageBeFixed(message, lastConfigArrays, fixTypes) {
- if (!message.ruleId) {
- return fixTypes.has("directive");
+function shouldIgnoreFilePath(matcher, filePath, relativeFilePath) {
+ if (typeof matcher === 'function') {
+ return matcher(filePath);
}
- const rule = message.ruleId && getRule(message.ruleId, lastConfigArrays);
- return Boolean(rule && rule.meta && fixTypes.has(rule.meta.type));
+ return minimatch(relativeFilePath, matcher, MINIMATCH_OPTIONS);
}
/**
- * Collect used deprecated rules.
- * @param {ConfigArray[]} usedConfigArrays The config arrays which were used.
- * @returns {IterableIterator<DeprecatedRuleInfo>} Used deprecated rules.
+ * Determines if a given file path is matched by a config. If the config
+ * has no `files` field, then it matches; otherwise, if a `files` field
+ * is present then we match the globs in `files` and exclude any globs in
+ * `ignores`.
+ * @param {string} filePath The absolute file path to check.
+ * @param {Object} config The config object to check.
+ * @returns {boolean} True if the file path is matched by the config,
+ * false if not.
*/
-function* iterateRuleDeprecationWarnings(usedConfigArrays) {
- const processedRuleIds = new Set(); // Flatten used configs.
+function pathMatches(filePath, basePath, config) {
+ // a config without `files` field always match
+ if (!config.files) {
+ return true;
+ }
+ /*
+ * For both files and ignores, functions are passed the absolute
+ * file path while strings are compared against the relative
+ * file path.
+ */
- /** @type {ExtractedConfig[]} */
- const configs = [].concat(...usedConfigArrays.map(getUsedExtractedConfigs)); // Traverse rule configs.
+ const relativeFilePath = path.relative(basePath, filePath); // if files isn't an array, throw an error
- for (const config of configs) {
- for (const [ruleId, ruleConfig] of Object.entries(config.rules)) {
- // Skip if it was processed.
- if (processedRuleIds.has(ruleId)) {
- continue;
- }
+ if (!Array.isArray(config.files) || config.files.length === 0) {
+ throw new TypeError('The files key must be a non-empty array.');
+ } // match both strings and functions
- processedRuleIds.add(ruleId); // Skip if it's not used.
- if (!ConfigOps.getRuleSeverity(ruleConfig)) {
- continue;
- }
+ const match = pattern => {
+ if (isString(pattern)) {
+ return minimatch(relativeFilePath, pattern, MINIMATCH_OPTIONS);
+ }
- const rule = getRule(ruleId, usedConfigArrays); // Skip if it's not deprecated.
+ if (typeof pattern === 'function') {
+ return pattern(filePath);
+ }
- if (!(rule && rule.meta && rule.meta.deprecated)) {
- continue;
- } // This rule was used and deprecated.
+ throw new TypeError("Unexpected matcher type ".concat(pattern, "."));
+ };
+ const isFilePathIgnored = matcher => {
+ return shouldIgnoreFilePath(matcher, filePath, relativeFilePath);
+ }; // check for all matches to config.files
- yield {
- ruleId,
- replacedBy: rule.meta.replacedBy || []
- };
+
+ let filePathMatchesPattern = config.files.some(pattern => {
+ if (Array.isArray(pattern)) {
+ return pattern.every(match);
}
+
+ return match(pattern);
+ });
+ /*
+ * If the file path matches the config.files patterns, then check to see
+ * if there are any files to ignore.
+ */
+
+ if (filePathMatchesPattern && config.ignores) {
+ filePathMatchesPattern = !config.ignores.some(isFilePathIgnored);
}
+
+ return filePathMatchesPattern;
}
/**
- * Checks if the given message is an error message.
- * @param {LintMessage} message The message to check.
- * @returns {boolean} Whether or not the message is an error message.
- * @private
+ * Ensures that a ConfigArray has been normalized.
+ * @param {ConfigArray} configArray The ConfigArray to check.
+ * @returns {void}
+ * @throws {Error} When the `ConfigArray` is not normalized.
*/
-function isErrorMessage(message) {
- return message.severity === 2;
+function assertNormalized(configArray) {
+ // TODO: Throw more verbose error
+ if (!configArray.isNormalized()) {
+ throw new Error('ConfigArray must be normalized to perform this operation.');
+ }
}
/**
- * return the cacheFile to be used by eslint, based on whether the provided parameter is
- * a directory or looks like a directory (ends in `path.sep`), in which case the file
- * name will be the `cacheFile/.cache_hashOfCWD`
- *
- * if cacheFile points to a file or looks like a file then in will just use that file
- * @param {string} cacheFile The name of file to be used to store the cache
- * @param {string} cwd Current working directory
- * @returns {string} the resolved path to the cache file
+ * Ensures that config types are valid.
+ * @param {Array<string>} extraConfigTypes The config types to check.
+ * @returns {void}
+ * @throws {Error} When the config types array is invalid.
*/
-function getCacheFile(cacheFile, cwd) {
- /*
- * make sure the path separators are normalized for the environment/os
- * keeping the trailing path separator if present
- */
- const normalizedCacheFile = path.normalize(cacheFile);
- const resolvedCacheFile = path.resolve(cwd, normalizedCacheFile);
- const looksLikeADirectory = normalizedCacheFile.slice(-1) === path.sep;
- /**
- * return the name for the cache file in case the provided parameter is a directory
- * @returns {string} the resolved path to the cacheFile
- */
+function assertExtraConfigTypes(extraConfigTypes) {
+ if (extraConfigTypes.length > 2) {
+ throw new TypeError('configTypes must be an array with at most two items.');
+ }
- function getCacheFileForDirectory() {
- return path.join(resolvedCacheFile, ".cache_".concat(hash(cwd)));
+ for (const configType of extraConfigTypes) {
+ if (!CONFIG_TYPES.has(configType)) {
+ throw new TypeError("Unexpected config type \"".concat(configType, "\" found. Expected one of: \"object\", \"array\", \"function\"."));
+ }
}
+} //------------------------------------------------------------------------------
+// Public Interface
+//------------------------------------------------------------------------------
- let fileStats;
- try {
- fileStats = fs.lstatSync(resolvedCacheFile);
- } catch {
- fileStats = null;
- }
- /*
- * in case the file exists we need to verify if the provided path
- * is a directory or a file. If it is a directory we want to create a file
- * inside that directory
- */
+const ConfigArraySymbol = {
+ isNormalized: Symbol('isNormalized'),
+ configCache: Symbol('configCache'),
+ schema: Symbol('schema'),
+ finalizeConfig: Symbol('finalizeConfig'),
+ preprocessConfig: Symbol('preprocessConfig')
+}; // used to store calculate data for faster lookup
+const dataCache = new WeakMap();
+/**
+ * Represents an array of config objects and provides method for working with
+ * those config objects.
+ */
- if (fileStats) {
- /*
- * is a directory or is a file, but the original file the user provided
- * looks like a directory but `path.resolve` removed the `last path.sep`
- * so we need to still treat this like a directory
+class ConfigArray extends Array {
+ /**
+ * Creates a new instance of ConfigArray.
+ * @param {Iterable|Function|Object} configs An iterable yielding config
+ * objects, or a config function, or a config object.
+ * @param {string} [options.basePath=""] The path of the config file
+ * @param {boolean} [options.normalized=false] Flag indicating if the
+ * configs have already been normalized.
+ * @param {Object} [options.schema] The additional schema
+ * definitions to use for the ConfigArray schema.
+ * @param {Array<string>} [options.configTypes] List of config types supported.
+ */
+ constructor(configs) {
+ let {
+ basePath = '',
+ normalized = false,
+ schema: customSchema,
+ extraConfigTypes = []
+ } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
+ super();
+ /**
+ * Tracks if the array has been normalized.
+ * @property isNormalized
+ * @type boolean
+ * @private
*/
- if (fileStats.isDirectory() || looksLikeADirectory) {
- return getCacheFileForDirectory();
- } // is file so just use that file
+ this[ConfigArraySymbol.isNormalized] = normalized;
+ /**
+ * The schema used for validating and merging configs.
+ * @property schema
+ * @type ObjectSchema
+ * @private
+ */
- return resolvedCacheFile;
- }
- /*
- * here we known the file or directory doesn't exist,
- * so we will try to infer if its a directory if it looks like a directory
- * for the current operating system.
- */
- // if the last character passed is a path separator we assume is a directory
+ this[ConfigArraySymbol.schema] = new objectSchema.ObjectSchema({ ...customSchema,
+ ...baseSchema
+ });
+ /**
+ * The path of the config file that this array was loaded from.
+ * This is used to calculate filename matches.
+ * @property basePath
+ * @type string
+ */
+ this.basePath = basePath;
+ assertExtraConfigTypes(extraConfigTypes);
+ /**
+ * The supported config types.
+ * @property configTypes
+ * @type Array<string>
+ */
- if (looksLikeADirectory) {
- return getCacheFileForDirectory();
- }
+ this.extraConfigTypes = Object.freeze([...extraConfigTypes]);
+ /**
+ * A cache to store calculated configs for faster repeat lookup.
+ * @property configCache
+ * @type Map
+ * @private
+ */
- return resolvedCacheFile;
-}
-/**
- * Convert a string array to a boolean map.
- * @param {string[]|null} keys The keys to assign true.
- * @param {boolean} defaultValue The default value for each property.
- * @param {string} displayName The property name which is used in error message.
- * @throws {Error} Requires array.
- * @returns {Record<string,boolean>} The boolean map.
- */
+ this[ConfigArraySymbol.configCache] = new Map(); // init cache
+ dataCache.set(this, {}); // load the configs into this array
-function toBooleanMap(keys, defaultValue, displayName) {
- if (keys && !Array.isArray(keys)) {
- throw new Error("".concat(displayName, " must be an array."));
+ if (Array.isArray(configs)) {
+ this.push(...configs);
+ } else {
+ this.push(configs);
+ }
}
+ /**
+ * Prevent normal array methods from creating a new `ConfigArray` instance.
+ * This is to ensure that methods such as `slice()` won't try to create a
+ * new instance of `ConfigArray` behind the scenes as doing so may throw
+ * an error due to the different constructor signature.
+ * @returns {Function} The `Array` constructor.
+ */
- if (keys && keys.length > 0) {
- return keys.reduce((map, def) => {
- const [key, value] = def.split(":");
-
- if (key !== "__proto__") {
- map[key] = value === void 0 ? defaultValue : value === "true";
- }
- return map;
- }, {});
+ static get [Symbol.species]() {
+ return Array;
}
+ /**
+ * Returns the `files` globs from every config object in the array.
+ * This can be used to determine which files will be matched by a
+ * config array or to use as a glob pattern when no patterns are provided
+ * for a command line interface.
+ * @returns {Array<string|Function>} An array of matchers.
+ */
- return void 0;
-}
-/**
- * Create a config data from CLI options.
- * @param {CLIEngineOptions} options The options
- * @returns {ConfigData|null} The created config data.
- */
+ get files() {
+ assertNormalized(this); // if this data has been cached, retrieve it
-function createConfigDataFromOptions(options) {
- const {
- ignorePattern,
- parser,
- parserOptions,
- plugins,
- rules
- } = options;
- const env = toBooleanMap(options.envs, true, "envs");
- const globals = toBooleanMap(options.globals, false, "globals");
+ const cache = dataCache.get(this);
- if (env === void 0 && globals === void 0 && (ignorePattern === void 0 || ignorePattern.length === 0) && parser === void 0 && parserOptions === void 0 && plugins === void 0 && rules === void 0) {
- return null;
- }
+ if (cache.files) {
+ return cache.files;
+ } // otherwise calculate it
- return {
- env,
- globals,
- ignorePatterns: ignorePattern,
- parser,
- parserOptions,
- plugins,
- rules
- };
-}
-/**
- * Checks whether a directory exists at the given location
- * @param {string} resolvedPath A path from the CWD
- * @throws {Error} As thrown by `fs.statSync` or `fs.isDirectory`.
- * @returns {boolean} `true` if a directory exists
- */
+ const result = [];
-function directoryExists(resolvedPath) {
- try {
- return fs.statSync(resolvedPath).isDirectory();
- } catch (error) {
- if (error && (error.code === "ENOENT" || error.code === "ENOTDIR")) {
- return false;
- }
+ for (const config of this) {
+ if (config.files) {
+ config.files.forEach(filePattern => {
+ result.push(filePattern);
+ });
+ }
+ } // store result
- throw error;
+
+ cache.files = result;
+ dataCache.set(this, cache);
+ return result;
}
-} //------------------------------------------------------------------------------
-// Public Interface
-//------------------------------------------------------------------------------
+ /**
+ * Returns ignore matchers that should always be ignored regardless of
+ * the matching `files` fields in any configs. This is necessary to mimic
+ * the behavior of things like .gitignore and .eslintignore, allowing a
+ * globbing operation to be faster.
+ * @returns {string[]} An array of string patterns and functions to be ignored.
+ */
-/**
- * Core CLI.
- */
+ get ignores() {
+ assertNormalized(this); // if this data has been cached, retrieve it
-class CLIEngine {
- /**
- * Creates a new instance of the core CLI engine.
- * @param {CLIEngineOptions} providedOptions The options for this instance.
- * @param {Object} [additionalData] Additional settings that are not CLIEngineOptions.
- * @param {Record<string,Plugin>|null} [additionalData.preloadedPlugins] Preloaded plugins.
- */
- constructor(providedOptions) {
- let {
- preloadedPlugins
- } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
- const options = Object.assign(Object.create(null), defaultOptions, {
- cwd: process.cwd()
- }, providedOptions);
+ const cache = dataCache.get(this);
- if (options.fix === void 0) {
- options.fix = false;
- }
+ if (cache.ignores) {
+ return cache.ignores;
+ } // otherwise calculate it
- const additionalPluginPool = new Map();
- if (preloadedPlugins) {
- for (const [id, plugin] of Object.entries(preloadedPlugins)) {
- additionalPluginPool.set(id, plugin);
+ const result = [];
+
+ for (const config of this) {
+ if (config.ignores && !config.files) {
+ result.push(...config.ignores);
}
- }
+ } // store result
- const cacheFilePath = getCacheFile(options.cacheLocation || options.cacheFile, options.cwd);
- const configArrayFactory = new CascadingConfigArrayFactory({
- additionalPluginPool,
- baseConfig: options.baseConfig || null,
- cliConfig: createConfigDataFromOptions(options),
- cwd: options.cwd,
- ignorePath: options.ignorePath,
- resolvePluginsRelativeTo: options.resolvePluginsRelativeTo,
- rulePaths: options.rulePaths,
- specificConfigPath: options.configFile,
- useEslintrc: options.useEslintrc,
- builtInRules,
- loadRules,
- eslintRecommendedPath: path.resolve(__dirname, "../../conf/eslint-recommended.js"),
- eslintAllPath: path.resolve(__dirname, "../../conf/eslint-all.js")
- });
- const fileEnumerator = new FileEnumerator({
- configArrayFactory,
- cwd: options.cwd,
- extensions: options.extensions,
- globInputPaths: options.globInputPaths,
- errorOnUnmatchedPattern: options.errorOnUnmatchedPattern,
- ignore: options.ignore
- });
- const lintResultCache = options.cache ? new LintResultCache(cacheFilePath, options.cacheStrategy) : null;
- const linter = new Linter({
- cwd: options.cwd
- });
- /** @type {ConfigArray[]} */
- const lastConfigArrays = [configArrayFactory.getConfigArrayForFile()]; // Store private data.
+ cache.ignores = result;
+ dataCache.set(this, cache);
+ return result;
+ }
+ /**
+ * Indicates if the config array has been normalized.
+ * @returns {boolean} True if the config array is normalized, false if not.
+ */
- internalSlotsMap.set(this, {
- additionalPluginPool,
- cacheFilePath,
- configArrayFactory,
- defaultIgnores: IgnorePattern.createDefaultIgnore(options.cwd),
- fileEnumerator,
- lastConfigArrays,
- lintResultCache,
- linter,
- options
- }); // setup special filter for fixes
- if (options.fix && options.fixTypes && options.fixTypes.length > 0) {
- debug("Using fix types ".concat(options.fixTypes)); // throw an error if any invalid fix types are found
+ isNormalized() {
+ return this[ConfigArraySymbol.isNormalized];
+ }
+ /**
+ * Normalizes a config array by flattening embedded arrays and executing
+ * config functions.
+ * @param {ConfigContext} context The context object for config functions.
+ * @returns {Promise<ConfigArray>} The current ConfigArray instance.
+ */
- validateFixTypes(options.fixTypes); // convert to Set for faster lookup
- const fixTypes = new Set(options.fixTypes); // save original value of options.fix in case it's a function
+ async normalize() {
+ let context = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
- const originalFix = typeof options.fix === "function" ? options.fix : () => true;
+ if (!this.isNormalized()) {
+ const normalizedConfigs = await normalize(this, context, this.extraConfigTypes);
+ this.length = 0;
+ this.push(...normalizedConfigs.map(this[ConfigArraySymbol.preprocessConfig]));
+ this[ConfigArraySymbol.isNormalized] = true; // prevent further changes
- options.fix = message => shouldMessageBeFixed(message, lastConfigArrays, fixTypes) && originalFix(message);
+ Object.freeze(this);
}
- }
-
- getRules() {
- const {
- lastConfigArrays
- } = internalSlotsMap.get(this);
- return new Map(function* () {
- yield* builtInRules;
- for (const configArray of lastConfigArrays) {
- yield* configArray.pluginRules;
- }
- }());
+ return this;
}
/**
- * Returns results that only contains errors.
- * @param {LintResult[]} results The results to filter.
- * @returns {LintResult[]} The filtered results.
+ * Normalizes a config array by flattening embedded arrays and executing
+ * config functions.
+ * @param {ConfigContext} context The context object for config functions.
+ * @returns {ConfigArray} The current ConfigArray instance.
*/
- static getErrorResults(results) {
- const filtered = [];
- results.forEach(result => {
- const filteredMessages = result.messages.filter(isErrorMessage);
+ normalizeSync() {
+ let context = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
- if (filteredMessages.length > 0) {
- filtered.push({ ...result,
- messages: filteredMessages,
- errorCount: filteredMessages.length,
- warningCount: 0,
- fixableErrorCount: result.fixableErrorCount,
- fixableWarningCount: 0
- });
- }
- });
- return filtered;
+ if (!this.isNormalized()) {
+ const normalizedConfigs = normalizeSync(this, context, this.extraConfigTypes);
+ this.length = 0;
+ this.push(...normalizedConfigs.map(this[ConfigArraySymbol.preprocessConfig]));
+ this[ConfigArraySymbol.isNormalized] = true; // prevent further changes
+
+ Object.freeze(this);
+ }
+
+ return this;
}
/**
- * Outputs fixes from the given results to files.
- * @param {LintReport} report The report object created by CLIEngine.
- * @returns {void}
+ * Finalizes the state of a config before being cached and returned by
+ * `getConfig()`. Does nothing by default but is provided to be
+ * overridden by subclasses as necessary.
+ * @param {Object} config The config to finalize.
+ * @returns {Object} The finalized config.
*/
- static outputFixes(report) {
- report.results.filter(result => Object.prototype.hasOwnProperty.call(result, "output")).forEach(result => {
- fs.writeFileSync(result.filePath, result.output);
- });
+ [ConfigArraySymbol.finalizeConfig](config) {
+ return config;
}
/**
- * Resolves the patterns passed into executeOnFiles() into glob-based patterns
- * for easier handling.
- * @param {string[]} patterns The file patterns passed on the command line.
- * @returns {string[]} The equivalent glob patterns.
+ * Preprocesses a config during the normalization process. This is the
+ * method to override if you want to convert an array item before it is
+ * validated for the first time. For example, if you want to replace a
+ * string with an object, this is the method to override.
+ * @param {Object} config The config to preprocess.
+ * @returns {Object} The config to use in place of the argument.
*/
- resolveFileGlobPatterns(patterns) {
- const {
- options
- } = internalSlotsMap.get(this);
-
- if (options.globInputPaths === false) {
- return patterns.filter(Boolean);
- }
-
- const extensions = (options.extensions || [".js"]).map(ext => ext.replace(/^\./u, ""));
- const dirSuffix = "/**/*.{".concat(extensions.join(","), "}");
- return patterns.filter(Boolean).map(pathname => {
- const resolvedPath = path.resolve(options.cwd, pathname);
- const newPath = directoryExists(resolvedPath) ? pathname.replace(/[/\\]$/u, "") + dirSuffix : pathname;
- return path.normalize(newPath).replace(/\\/gu, "/");
- });
+ [ConfigArraySymbol.preprocessConfig](config) {
+ return config;
}
/**
- * Executes the current configuration on an array of file and directory names.
- * @param {string[]} patterns An array of file and directory names.
- * @throws {Error} As may be thrown by `fs.unlinkSync`.
- * @returns {LintReport} The results for all files that were linted.
+ * Returns the config object for a given file path.
+ * @param {string} filePath The complete path of a file to get a config for.
+ * @returns {Object} The config object for this file.
*/
- executeOnFiles(patterns) {
- const {
- cacheFilePath,
- fileEnumerator,
- lastConfigArrays,
- lintResultCache,
- linter,
- options: {
- allowInlineConfig,
- cache,
- cwd,
- fix,
- reportUnusedDisableDirectives
- }
- } = internalSlotsMap.get(this);
- const results = [];
- const startTime = Date.now(); // Clear the last used config arrays.
+ getConfig(filePath) {
+ assertNormalized(this); // first check the cache to avoid duplicate work
- lastConfigArrays.length = 0; // Delete cache file; should this do here?
+ let finalConfig = this[ConfigArraySymbol.configCache].get(filePath);
- if (!cache) {
- try {
- fs.unlinkSync(cacheFilePath);
- } catch (error) {
- const errorCode = error && error.code; // Ignore errors when no such file exists or file system is read only (and cache file does not exist)
+ if (finalConfig) {
+ return finalConfig;
+ } // TODO: Maybe move elsewhere?
- if (errorCode !== "ENOENT" && !(errorCode === "EROFS" && !fs.existsSync(cacheFilePath))) {
- throw error;
- }
- }
- } // Iterate source code files.
+ const relativeFilePath = path.relative(this.basePath, filePath); // if there is a global matcher ignoring this file, just return null
- for (const {
- config,
- filePath,
- ignored
- } of fileEnumerator.iterateFiles(patterns)) {
- if (ignored) {
- results.push(createIgnoreResult(filePath, cwd));
- continue;
+ for (const shouldIgnore of this.ignores) {
+ if (shouldIgnoreFilePath(shouldIgnore, filePath, relativeFilePath)) {
+ // cache and return result - finalConfig is undefined at this point
+ this[ConfigArraySymbol.configCache].set(filePath, finalConfig);
+ return finalConfig;
}
- /*
- * Store used configs for:
- * - this method uses to collect used deprecated rules.
- * - `getRules()` method uses to collect all loaded rules.
- * - `--fix-type` option uses to get the loaded rule's meta data.
- */
+ } // filePath isn't automatically ignored, so try to construct config
- if (!lastConfigArrays.includes(config)) {
- lastConfigArrays.push(config);
- } // Skip if there is cached result.
+ const matchingConfigs = [];
+ for (const config of this) {
+ if (pathMatches(filePath, this.basePath, config)) {
+ debug("Matching config found for ".concat(filePath));
+ matchingConfigs.push(config);
+ } else {
+ debug("No matching config found for ".concat(filePath));
+ }
+ } // if matching both files and ignores, there will be no config to create
- if (lintResultCache) {
- const cachedResult = lintResultCache.getCachedLintResults(filePath, config);
- if (cachedResult) {
- const hadMessages = cachedResult.messages && cachedResult.messages.length > 0;
+ if (matchingConfigs.length === 0) {
+ // cache and return result - finalConfig is undefined at this point
+ this[ConfigArraySymbol.configCache].set(filePath, finalConfig);
+ return finalConfig;
+ } // otherwise construct the config
- if (hadMessages && fix) {
- debug("Reprocessing cached file to allow autofix: ".concat(filePath));
- } else {
- debug("Skipping file since it hasn't changed: ".concat(filePath));
- results.push(cachedResult);
- continue;
- }
- }
- } // Do lint.
+ finalConfig = matchingConfigs.reduce((result, config) => {
+ return this[ConfigArraySymbol.schema].merge(result, config);
+ }, {}, this);
+ finalConfig = this[ConfigArraySymbol.finalizeConfig](finalConfig);
+ this[ConfigArraySymbol.configCache].set(filePath, finalConfig);
+ return finalConfig;
+ }
+ /**
+ * Determines if the given filepath is ignored based on the configs.
+ * @param {string} filePath The complete path of a file to check.
+ * @returns {boolean} True if the path is ignored, false if not.
+ */
- const result = verifyText({
- text: fs.readFileSync(filePath, "utf8"),
- filePath,
- config,
- cwd,
- fix,
- allowInlineConfig,
- reportUnusedDisableDirectives,
- fileEnumerator,
- linter
- });
- results.push(result);
- /*
- * Store the lint result in the LintResultCache.
- * NOTE: The LintResultCache will remove the file source and any
- * other properties that are difficult to serialize, and will
- * hydrate those properties back in on future lint runs.
- */
- if (lintResultCache) {
- lintResultCache.setCachedLintResults(filePath, config, result);
- }
- } // Persist the cache to disk.
+ isIgnored(filePath) {
+ return this.getConfig(filePath) === undefined;
+ }
+}
- if (lintResultCache) {
- lintResultCache.reconcile();
- }
+exports.ConfigArray = ConfigArray;
+exports.ConfigArraySymbol = ConfigArraySymbol;
- debug("Linting complete in: ".concat(Date.now() - startTime, "ms"));
- let usedDeprecatedRules;
- return {
- results,
- ...calculateStatsPerRun(results),
+/***/ }),
+/* 862 */
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
- // Initialize it lazily because CLI and `ESLint` API don't use it.
- get usedDeprecatedRules() {
- if (!usedDeprecatedRules) {
- usedDeprecatedRules = Array.from(iterateRuleDeprecationWarnings(lastConfigArrays));
- }
+/* provided dependency */ var console = __webpack_require__(438);
+module.exports = minimatch;
+minimatch.Minimatch = Minimatch;
+var path = {
+ sep: '/'
+};
- return usedDeprecatedRules;
- }
+try {
+ path = __webpack_require__(429);
+} catch (er) {}
- };
- }
- /**
- * Executes the current configuration on text.
- * @param {string} text A string of JavaScript code to lint.
- * @param {string} [filename] An optional string representing the texts filename.
- * @param {boolean} [warnIgnored] Always warn when a file is ignored
- * @returns {LintReport} The results for the linting.
- */
+var GLOBSTAR = minimatch.GLOBSTAR = Minimatch.GLOBSTAR = {};
+var expand = __webpack_require__(863);
- executeOnText(text, filename, warnIgnored) {
- const {
- configArrayFactory,
- fileEnumerator,
- lastConfigArrays,
- linter,
- options: {
- allowInlineConfig,
- cwd,
- fix,
- reportUnusedDisableDirectives
- }
- } = internalSlotsMap.get(this);
- const results = [];
- const startTime = Date.now();
- const resolvedFilename = filename && path.resolve(cwd, filename); // Clear the last used config arrays.
+var plTypes = {
+ '!': {
+ open: '(?:(?!(?:',
+ close: '))[^/]*?)'
+ },
+ '?': {
+ open: '(?:',
+ close: ')?'
+ },
+ '+': {
+ open: '(?:',
+ close: ')+'
+ },
+ '*': {
+ open: '(?:',
+ close: ')*'
+ },
+ '@': {
+ open: '(?:',
+ close: ')'
+ }
+}; // any single thing other than /
+// don't need to escape / when using new RegExp()
- lastConfigArrays.length = 0;
+var qmark = '[^/]'; // * => any number of characters
- if (resolvedFilename && this.isPathIgnored(resolvedFilename)) {
- if (warnIgnored) {
- results.push(createIgnoreResult(resolvedFilename, cwd));
- }
- } else {
- const config = configArrayFactory.getConfigArrayForFile(resolvedFilename || "__placeholder__.js");
- /*
- * Store used configs for:
- * - this method uses to collect used deprecated rules.
- * - `getRules()` method uses to collect all loaded rules.
- * - `--fix-type` option uses to get the loaded rule's meta data.
- */
+var star = qmark + '*?'; // ** when dots are allowed. Anything goes, except .. and .
+// not (^ or / followed by one or two dots followed by $ or /),
+// followed by anything, any number of times.
- lastConfigArrays.push(config); // Do lint.
+var twoStarDot = '(?:(?!(?:\\\/|^)(?:\\.{1,2})($|\\\/)).)*?'; // not a ^ or / followed by a dot,
+// followed by anything, any number of times.
- results.push(verifyText({
- text,
- filePath: resolvedFilename,
- config,
- cwd,
- fix,
- allowInlineConfig,
- reportUnusedDisableDirectives,
- fileEnumerator,
- linter
- }));
- }
+var twoStarNoDot = '(?:(?!(?:\\\/|^)\\.).)*?'; // characters that need to be escaped in RegExp.
- debug("Linting complete in: ".concat(Date.now() - startTime, "ms"));
- let usedDeprecatedRules;
- return {
- results,
- ...calculateStatsPerRun(results),
+var reSpecials = charSet('().*{}+?[]^$\\!'); // "abc" -> { a:true, b:true, c:true }
- // Initialize it lazily because CLI and `ESLint` API don't use it.
- get usedDeprecatedRules() {
- if (!usedDeprecatedRules) {
- usedDeprecatedRules = Array.from(iterateRuleDeprecationWarnings(lastConfigArrays));
- }
+function charSet(s) {
+ return s.split('').reduce(function (set, c) {
+ set[c] = true;
+ return set;
+ }, {});
+} // normalizes slashes.
- return usedDeprecatedRules;
- }
- };
- }
- /**
- * Returns a configuration object for the given file based on the CLI options.
- * This is the same logic used by the ESLint CLI executable to determine
- * configuration for each file it processes.
- * @param {string} filePath The path of the file to retrieve a config object for.
- * @throws {Error} If filepath a directory path.
- * @returns {ConfigData} A configuration object for the file.
- */
+var slashSplit = /\/+/;
+minimatch.filter = filter;
+function filter(pattern, options) {
+ options = options || {};
+ return function (p, i, list) {
+ return minimatch(p, pattern, options);
+ };
+}
- getConfigForFile(filePath) {
- const {
- configArrayFactory,
- options
- } = internalSlotsMap.get(this);
- const absolutePath = path.resolve(options.cwd, filePath);
+function ext(a, b) {
+ a = a || {};
+ b = b || {};
+ var t = {};
+ Object.keys(b).forEach(function (k) {
+ t[k] = b[k];
+ });
+ Object.keys(a).forEach(function (k) {
+ t[k] = a[k];
+ });
+ return t;
+}
- if (directoryExists(absolutePath)) {
- throw Object.assign(new Error("'filePath' should not be a directory path."), {
- messageTemplate: "print-config-with-directory-path"
- });
- }
+minimatch.defaults = function (def) {
+ if (!def || !Object.keys(def).length) return minimatch;
+ var orig = minimatch;
- return configArrayFactory.getConfigArrayForFile(absolutePath).extractConfig(absolutePath).toCompatibleObjectAsConfigFileContent();
- }
- /**
- * Checks if a given path is ignored by ESLint.
- * @param {string} filePath The path of the file to check.
- * @returns {boolean} Whether or not the given path is ignored.
- */
+ var m = function minimatch(p, pattern, options) {
+ return orig.minimatch(p, pattern, ext(def, options));
+ };
+ m.Minimatch = function Minimatch(pattern, options) {
+ return new orig.Minimatch(pattern, ext(def, options));
+ };
- isPathIgnored(filePath) {
- const {
- configArrayFactory,
- defaultIgnores,
- options: {
- cwd,
- ignore
- }
- } = internalSlotsMap.get(this);
- const absolutePath = path.resolve(cwd, filePath);
+ return m;
+};
- if (ignore) {
- const config = configArrayFactory.getConfigArrayForFile(absolutePath).extractConfig(absolutePath);
- const ignores = config.ignores || defaultIgnores;
- return ignores(absolutePath);
- }
+Minimatch.defaults = function (def) {
+ if (!def || !Object.keys(def).length) return Minimatch;
+ return minimatch.defaults(def).Minimatch;
+};
- return defaultIgnores(absolutePath);
+function minimatch(p, pattern, options) {
+ if (typeof pattern !== 'string') {
+ throw new TypeError('glob pattern string required');
}
- /**
- * Returns the formatter representing the given format or null if the `format` is not a string.
- * @param {string} [format] The name of the format to load or the path to a
- * custom formatter.
- * @throws {any} As may be thrown by requiring of formatter
- * @returns {(Function|null)} The formatter function or null if the `format` is not a string.
- */
-
- getFormatter(format) {
- // default is stylish
- const resolvedFormatName = format || "stylish"; // only strings are valid formatters
+ if (!options) options = {}; // shortcut: comments match nothing.
- if (typeof resolvedFormatName === "string") {
- // replace \ with / for Windows compatibility
- const normalizedFormatName = resolvedFormatName.replace(/\\/gu, "/");
- const slots = internalSlotsMap.get(this);
- const cwd = slots ? slots.options.cwd : process.cwd();
- const namespace = naming.getNamespaceFromTerm(normalizedFormatName);
- let formatterPath; // if there's a slash, then it's a file (TODO: this check seems dubious for scoped npm packages)
+ if (!options.nocomment && pattern.charAt(0) === '#') {
+ return false;
+ } // "" only matches ""
- if (!namespace && normalizedFormatName.indexOf("/") > -1) {
- formatterPath = path.resolve(cwd, normalizedFormatName);
- } else {
- try {
- const npmFormat = naming.normalizePackageName(normalizedFormatName, "eslint-formatter");
- formatterPath = ModuleResolver.resolve(npmFormat, path.join(cwd, "__placeholder__.js"));
- } catch {
- formatterPath = path.resolve(__dirname, "formatters", normalizedFormatName);
- }
- }
- try {
- return __webpack_require__(883)(formatterPath);
- } catch (ex) {
- if (format === "table" || format === "codeframe") {
- ex.message = "The ".concat(format, " formatter is no longer part of core ESLint. Install it manually with `npm install -D eslint-formatter-").concat(format, "`");
- } else {
- ex.message = "There was a problem loading formatter: ".concat(formatterPath, "\nError: ").concat(ex.message);
- }
+ if (pattern.trim() === '') return p === '';
+ return new Minimatch(pattern, options).match(p);
+}
- throw ex;
- }
- } else {
- return null;
- }
+function Minimatch(pattern, options) {
+ if (!(this instanceof Minimatch)) {
+ return new Minimatch(pattern, options);
}
-}
+ if (typeof pattern !== 'string') {
+ throw new TypeError('glob pattern string required');
+ }
-CLIEngine.version = pkg.version;
-CLIEngine.getFormatter = CLIEngine.prototype.getFormatter;
-module.exports = {
- CLIEngine,
+ if (!options) options = {};
+ pattern = pattern.trim(); // windows support: need to use /, not \
- /**
- * Get the internal slots of a given CLIEngine instance for tests.
- * @param {CLIEngine} instance The CLIEngine instance to get.
- * @returns {CLIEngineInternalSlots} The internal slots.
- */
- getCLIEngineInternalSlots(instance) {
- return internalSlotsMap.get(instance);
+ if (path.sep !== '/') {
+ pattern = pattern.split(path.sep).join('/');
}
-};
+ this.options = options;
+ this.set = [];
+ this.pattern = pattern;
+ this.regexp = null;
+ this.negate = false;
+ this.comment = false;
+ this.empty = false; // make the set of regexps etc.
-/***/ }),
-/* 861 */
-/***/ ((module) => {
+ this.make();
+}
-"use strict";
-module.exports = require("fs");
+Minimatch.prototype.debug = function () {};
-/***/ }),
-/* 862 */
-/***/ ((module) => {
+Minimatch.prototype.make = make;
-"use strict";
-/**
- * @fileoverview Default CLIEngineOptions.
- * @author Ian VanSchooten
- */
+function make() {
+ // don't do it more than once.
+ if (this._made) return;
+ var pattern = this.pattern;
+ var options = this.options; // empty patterns and comments match nothing.
+ if (!options.nocomment && pattern.charAt(0) === '#') {
+ this.comment = true;
+ return;
+ }
-module.exports = {
- configFile: null,
- baseConfig: false,
- rulePaths: [],
- useEslintrc: true,
- envs: [],
- globals: [],
- extensions: null,
- ignore: true,
- ignorePath: void 0,
- cache: false,
+ if (!pattern) {
+ this.empty = true;
+ return;
+ } // step 1: figure out negation, etc.
- /*
- * in order to honor the cacheFile option if specified
- * this option should not have a default value otherwise
- * it will always be used
- */
- cacheLocation: "",
- cacheFile: ".eslintcache",
- cacheStrategy: "metadata",
- fix: false,
- allowInlineConfig: true,
- reportUnusedDisableDirectives: void 0,
- globInputPaths: true
-};
-/***/ }),
-/* 863 */
-/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
+ this.parseNegate(); // step 2: expand braces
-"use strict";
-/* provided dependency */ var process = __webpack_require__(494);
+ var set = this.globSet = this.braceExpand();
+ if (options.debug) this.debug = console.error;
+ this.debug(this.pattern, set); // step 3: now we have a set, so turn each one into a series of path-portion
+ // matching patterns.
+ // These will be regexps, except in the case of "**", which is
+ // set to the GLOBSTAR object for globstar behavior,
+ // and will not contain any / characters
+ set = this.globParts = set.map(function (s) {
+ return s.split(slashSplit);
+ });
+ this.debug(this.pattern, set); // glob --> regexps
-Object.defineProperty(exports, "__esModule", ({ value: true }));
+ set = set.map(function (s, si, set) {
+ return s.map(this.parse, this);
+ }, this);
+ this.debug(this.pattern, set); // filter out everything that didn't compile properly.
-var fs = __webpack_require__(861);
-var path = __webpack_require__(429);
-var importFresh = __webpack_require__(864);
-var stripComments = __webpack_require__(870);
-var util = __webpack_require__(439);
-var Ajv = __webpack_require__(446);
-var globals = __webpack_require__(492);
-var Module = __webpack_require__(866);
-var assert = __webpack_require__(431);
-var ignore = __webpack_require__(737);
-var debugOrig = __webpack_require__(496);
-var minimatch = __webpack_require__(871);
-var os = __webpack_require__(875);
-var url = __webpack_require__(876);
+ set = set.filter(function (s) {
+ return s.indexOf(false) === -1;
+ });
+ this.debug(this.pattern, set);
+ this.set = set;
+}
-function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
+Minimatch.prototype.parseNegate = parseNegate;
-var fs__default = /*#__PURE__*/_interopDefaultLegacy(fs);
-var path__default = /*#__PURE__*/_interopDefaultLegacy(path);
-var importFresh__default = /*#__PURE__*/_interopDefaultLegacy(importFresh);
-var stripComments__default = /*#__PURE__*/_interopDefaultLegacy(stripComments);
-var util__default = /*#__PURE__*/_interopDefaultLegacy(util);
-var Ajv__default = /*#__PURE__*/_interopDefaultLegacy(Ajv);
-var globals__default = /*#__PURE__*/_interopDefaultLegacy(globals);
-var Module__default = /*#__PURE__*/_interopDefaultLegacy(Module);
-var assert__default = /*#__PURE__*/_interopDefaultLegacy(assert);
-var ignore__default = /*#__PURE__*/_interopDefaultLegacy(ignore);
-var debugOrig__default = /*#__PURE__*/_interopDefaultLegacy(debugOrig);
-var minimatch__default = /*#__PURE__*/_interopDefaultLegacy(minimatch);
-var os__default = /*#__PURE__*/_interopDefaultLegacy(os);
+function parseNegate() {
+ var pattern = this.pattern;
+ var negate = false;
+ var options = this.options;
+ var negateOffset = 0;
+ if (options.nonegate) return;
-/**
- * @fileoverview Config file operations. This file must be usable in the browser,
- * so no Node-specific code can be here.
- * @author Nicholas C. Zakas
- */
+ for (var i = 0, l = pattern.length; i < l && pattern.charAt(i) === '!'; i++) {
+ negate = !negate;
+ negateOffset++;
+ }
-//------------------------------------------------------------------------------
-// Private
-//------------------------------------------------------------------------------
+ if (negateOffset) this.pattern = pattern.substr(negateOffset);
+ this.negate = negate;
+} // Brace expansion:
+// a{b,c}d -> abd acd
+// a{b,}c -> abc ac
+// a{0..3}d -> a0d a1d a2d a3d
+// a{b,c{d,e}f}g -> abg acdfg acefg
+// a{b,c}d{e,f}g -> abdeg acdeg abdeg abdfg
+//
+// Invalid sets are not expanded.
+// a{2..}b -> a{2..}b
+// a{b}c -> a{b}c
-const RULE_SEVERITY_STRINGS = ["off", "warn", "error"],
- RULE_SEVERITY = RULE_SEVERITY_STRINGS.reduce((map, value, index) => {
- map[value] = index;
- return map;
- }, {}),
- VALID_SEVERITIES = [0, 1, 2, "off", "warn", "error"];
-//------------------------------------------------------------------------------
-// Public Interface
-//------------------------------------------------------------------------------
+minimatch.braceExpand = function (pattern, options) {
+ return braceExpand(pattern, options);
+};
-/**
- * Normalizes the severity value of a rule's configuration to a number
- * @param {(number|string|[number, ...*]|[string, ...*])} ruleConfig A rule's configuration value, generally
- * received from the user. A valid config value is either 0, 1, 2, the string "off" (treated the same as 0),
- * the string "warn" (treated the same as 1), the string "error" (treated the same as 2), or an array
- * whose first element is one of the above values. Strings are matched case-insensitively.
- * @returns {(0|1|2)} The numeric severity value if the config value was valid, otherwise 0.
- */
-function getRuleSeverity(ruleConfig) {
- const severityValue = Array.isArray(ruleConfig) ? ruleConfig[0] : ruleConfig;
+Minimatch.prototype.braceExpand = braceExpand;
- if (severityValue === 0 || severityValue === 1 || severityValue === 2) {
- return severityValue;
+function braceExpand(pattern, options) {
+ if (!options) {
+ if (this instanceof Minimatch) {
+ options = this.options;
+ } else {
+ options = {};
}
+ }
- if (typeof severityValue === "string") {
- return RULE_SEVERITY[severityValue.toLowerCase()] || 0;
- }
+ pattern = typeof pattern === 'undefined' ? this.pattern : pattern;
- return 0;
-}
+ if (typeof pattern === 'undefined') {
+ throw new TypeError('undefined pattern');
+ }
-/**
- * Converts old-style severity settings (0, 1, 2) into new-style
- * severity settings (off, warn, error) for all rules. Assumption is that severity
- * values have already been validated as correct.
- * @param {Object} config The config object to normalize.
- * @returns {void}
- */
-function normalizeToStrings(config) {
+ if (options.nobrace || !pattern.match(/\{.*\}/)) {
+ // shortcut. no need to expand.
+ return [pattern];
+ }
- if (config.rules) {
- Object.keys(config.rules).forEach(ruleId => {
- const ruleConfig = config.rules[ruleId];
+ return expand(pattern);
+} // parse a component of the expanded set.
+// At this point, no pattern may contain "/" in it
+// so we're going to return a 2d array, where each entry is the full
+// pattern, split on '/', and then turned into a regular expression.
+// A regexp is made at the end which joins each array with an
+// escaped /, and another full one which joins each regexp with |.
+//
+// Following the lead of Bash 4.1, note that "**" only has special meaning
+// when it is the *only* thing in a path portion. Otherwise, any series
+// of * is equivalent to a single *. Globstar behavior is enabled by
+// default, and can be disabled by setting options.noglobstar.
- if (typeof ruleConfig === "number") {
- config.rules[ruleId] = RULE_SEVERITY_STRINGS[ruleConfig] || RULE_SEVERITY_STRINGS[0];
- } else if (Array.isArray(ruleConfig) && typeof ruleConfig[0] === "number") {
- ruleConfig[0] = RULE_SEVERITY_STRINGS[ruleConfig[0]] || RULE_SEVERITY_STRINGS[0];
- }
- });
- }
-}
-/**
- * Determines if the severity for the given rule configuration represents an error.
- * @param {int|string|Array} ruleConfig The configuration for an individual rule.
- * @returns {boolean} True if the rule represents an error, false if not.
- */
-function isErrorSeverity(ruleConfig) {
- return getRuleSeverity(ruleConfig) === 2;
-}
+Minimatch.prototype.parse = parse;
+var SUBPARSE = {};
-/**
- * Checks whether a given config has valid severity or not.
- * @param {number|string|Array} ruleConfig The configuration for an individual rule.
- * @returns {boolean} `true` if the configuration has valid severity.
- */
-function isValidSeverity(ruleConfig) {
- let severity = Array.isArray(ruleConfig) ? ruleConfig[0] : ruleConfig;
+function parse(pattern, isSub) {
+ if (pattern.length > 1024 * 64) {
+ throw new TypeError('pattern is too long');
+ }
- if (typeof severity === "string") {
- severity = severity.toLowerCase();
- }
- return VALID_SEVERITIES.indexOf(severity) !== -1;
-}
+ var options = this.options; // shortcuts
-/**
- * Checks whether every rule of a given config has valid severity or not.
- * @param {Object} config The configuration for rules.
- * @returns {boolean} `true` if the configuration has valid severity.
- */
-function isEverySeverityValid(config) {
- return Object.keys(config).every(ruleId => isValidSeverity(config[ruleId]));
-}
+ if (!options.noglobstar && pattern === '**') return GLOBSTAR;
+ if (pattern === '') return '';
+ var re = '';
+ var hasMagic = !!options.nocase;
+ var escaping = false; // ? => one single character
-/**
- * Normalizes a value for a global in a config
- * @param {(boolean|string|null)} configuredValue The value given for a global in configuration or in
- * a global directive comment
- * @returns {("readable"|"writeable"|"off")} The value normalized as a string
- * @throws Error if global value is invalid
- */
-function normalizeConfigGlobal(configuredValue) {
- switch (configuredValue) {
- case "off":
- return "off";
+ var patternListStack = [];
+ var negativeLists = [];
+ var stateChar;
+ var inClass = false;
+ var reClassStart = -1;
+ var classStart = -1; // . and .. never match anything that doesn't start with .,
+ // even when options.dot is set.
- case true:
- case "true":
- case "writeable":
- case "writable":
- return "writable";
+ var patternStart = pattern.charAt(0) === '.' ? '' // anything
+ // not (start or / followed by . or .. followed by / or end)
+ : options.dot ? '(?!(?:^|\\\/)\\.{1,2}(?:$|\\\/))' : '(?!\\.)';
+ var self = this;
- case null:
- case false:
- case "false":
- case "readable":
- case "readonly":
- return "readonly";
+ function clearStateChar() {
+ if (stateChar) {
+ // we had some state-tracking character
+ // that wasn't consumed by this pass.
+ switch (stateChar) {
+ case '*':
+ re += star;
+ hasMagic = true;
+ break;
+
+ case '?':
+ re += qmark;
+ hasMagic = true;
+ break;
default:
- throw new Error(`'${configuredValue}' is not a valid configuration for a global (use 'readonly', 'writable', or 'off')`);
+ re += '\\' + stateChar;
+ break;
+ }
+
+ self.debug('clearStateChar %j %j', stateChar, re);
+ stateChar = false;
}
-}
+ }
-var ConfigOps = {
- __proto__: null,
- getRuleSeverity: getRuleSeverity,
- normalizeToStrings: normalizeToStrings,
- isErrorSeverity: isErrorSeverity,
- isValidSeverity: isValidSeverity,
- isEverySeverityValid: isEverySeverityValid,
- normalizeConfigGlobal: normalizeConfigGlobal
-};
+ for (var i = 0, len = pattern.length, c; i < len && (c = pattern.charAt(i)); i++) {
+ this.debug('%s\t%s %s %j', pattern, i, re, c); // skip over any that are escaped.
-/**
- * @fileoverview Provide the function that emits deprecation warnings.
- * @author Toru Nagashima <http://github.com/mysticatea>
- */
+ if (escaping && reSpecials[c]) {
+ re += '\\' + c;
+ escaping = false;
+ continue;
+ }
-//------------------------------------------------------------------------------
-// Private
-//------------------------------------------------------------------------------
+ switch (c) {
+ case '/':
+ // completely not allowed, even escaped.
+ // Should already be path-split by now.
+ return false;
+
+ case '\\':
+ clearStateChar();
+ escaping = true;
+ continue;
+ // the various stateChar values
+ // for the "extglob" stuff.
+
+ case '?':
+ case '*':
+ case '+':
+ case '@':
+ case '!':
+ this.debug('%s\t%s %s %j <-- stateChar', pattern, i, re, c); // all of those are literals inside a class, except that
+ // the glob [!a] means [^a] in regexp
+
+ if (inClass) {
+ this.debug(' in class');
+ if (c === '!' && i === classStart + 1) c = '^';
+ re += c;
+ continue;
+ } // if we already have a stateChar, then it means
+ // that there was something like ** or +? in there.
+ // Handle the stateChar, then proceed with this one.
+
+
+ self.debug('call clearStateChar %j', stateChar);
+ clearStateChar();
+ stateChar = c; // if extglob is disabled, then +(asdf|foo) isn't a thing.
+ // just clear the statechar *now*, rather than even diving into
+ // the patternList stuff.
+
+ if (options.noext) clearStateChar();
+ continue;
+
+ case '(':
+ if (inClass) {
+ re += '(';
+ continue;
+ }
+
+ if (!stateChar) {
+ re += '\\(';
+ continue;
+ }
+
+ patternListStack.push({
+ type: stateChar,
+ start: i - 1,
+ reStart: re.length,
+ open: plTypes[stateChar].open,
+ close: plTypes[stateChar].close
+ }); // negation is (?:(?!js)[^/]*)
+
+ re += stateChar === '!' ? '(?:(?!(?:' : '(?:';
+ this.debug('plType %j %j', stateChar, re);
+ stateChar = false;
+ continue;
+
+ case ')':
+ if (inClass || !patternListStack.length) {
+ re += '\\)';
+ continue;
+ }
+
+ clearStateChar();
+ hasMagic = true;
+ var pl = patternListStack.pop(); // negation is (?:(?!js)[^/]*)
+ // The others are (?:<pattern>)<type>
+
+ re += pl.close;
+
+ if (pl.type === '!') {
+ negativeLists.push(pl);
+ }
+
+ pl.reEnd = re.length;
+ continue;
+
+ case '|':
+ if (inClass || !patternListStack.length || escaping) {
+ re += '\\|';
+ escaping = false;
+ continue;
+ }
+
+ clearStateChar();
+ re += '|';
+ continue;
+ // these are mostly the same in regexp and glob
+
+ case '[':
+ // swallow any state-tracking char before the [
+ clearStateChar();
+
+ if (inClass) {
+ re += '\\' + c;
+ continue;
+ }
+
+ inClass = true;
+ classStart = i;
+ reClassStart = re.length;
+ re += c;
+ continue;
+
+ case ']':
+ // a right bracket shall lose its special
+ // meaning and represent itself in
+ // a bracket expression if it occurs
+ // first in the list. -- POSIX.2 2.8.3.2
+ if (i === classStart + 1 || !inClass) {
+ re += '\\' + c;
+ escaping = false;
+ continue;
+ } // handle the case where we left a class open.
+ // "[z-a]" is valid, equivalent to "\[z-a\]"
+
+
+ if (inClass) {
+ // split where the last [ was, make sure we don't have
+ // an invalid re. if so, re-walk the contents of the
+ // would-be class to re-translate any characters that
+ // were passed through as-is
+ // TODO: It would probably be faster to determine this
+ // without a try/catch and a new RegExp, but it's tricky
+ // to do safely. For now, this is safe and works.
+ var cs = pattern.substring(classStart + 1, i);
+
+ try {
+ RegExp('[' + cs + ']');
+ } catch (er) {
+ // not a valid class!
+ var sp = this.parse(cs, SUBPARSE);
+ re = re.substr(0, reClassStart) + '\\[' + sp[0] + '\\]';
+ hasMagic = hasMagic || sp[1];
+ inClass = false;
+ continue;
+ }
+ } // finish up the class.
+
+
+ hasMagic = true;
+ inClass = false;
+ re += c;
+ continue;
+
+ default:
+ // swallow any state char that wasn't consumed
+ clearStateChar();
+
+ if (escaping) {
+ // no need
+ escaping = false;
+ } else if (reSpecials[c] && !(c === '^' && inClass)) {
+ re += '\\';
+ }
+
+ re += c;
+ } // switch
+
+ } // for
+ // handle the case where we left a class open.
+ // "[abc" is valid, equivalent to "\[abc"
+
+
+ if (inClass) {
+ // split where the last [ was, and escape it
+ // this is a huge pita. We now have to re-walk
+ // the contents of the would-be class to re-translate
+ // any characters that were passed through as-is
+ cs = pattern.substr(classStart + 1);
+ sp = this.parse(cs, SUBPARSE);
+ re = re.substr(0, reClassStart) + '\\[' + sp[0];
+ hasMagic = hasMagic || sp[1];
+ } // handle the case where we had a +( thing at the *end*
+ // of the pattern.
+ // each pattern list stack adds 3 chars, and we need to go through
+ // and escape any | chars that were passed through as-is for the regexp.
+ // Go through and escape them, taking care not to double-escape any
+ // | chars that were already escaped.
+
+
+ for (pl = patternListStack.pop(); pl; pl = patternListStack.pop()) {
+ var tail = re.slice(pl.reStart + pl.open.length);
+ this.debug('setting tail', re, pl); // maybe some even number of \, then maybe 1 \, followed by a |
+
+ tail = tail.replace(/((?:\\{2}){0,64})(\\?)\|/g, function (_, $1, $2) {
+ if (!$2) {
+ // the | isn't already escaped, so escape it.
+ $2 = '\\';
+ } // need to escape all those slashes *again*, without escaping the
+ // one that we need for escaping the | character. As it works out,
+ // escaping an even number of slashes can be done by simply repeating
+ // it exactly after itself. That's why this trick works.
+ //
+ // I am sorry that you have to see this.
+
+
+ return $1 + $1 + $2 + '|';
+ });
+ this.debug('tail=%j\n %s', tail, tail, pl, re);
+ var t = pl.type === '*' ? star : pl.type === '?' ? qmark : '\\' + pl.type;
+ hasMagic = true;
+ re = re.slice(0, pl.reStart) + t + '\\(' + tail;
+ } // handle trailing things that only matter at the very end.
+
+
+ clearStateChar();
+
+ if (escaping) {
+ // trailing \\
+ re += '\\\\';
+ } // only need to apply the nodot start if the re starts with
+ // something that could conceivably capture a dot
+
+
+ var addPatternStart = false;
+
+ switch (re.charAt(0)) {
+ case '.':
+ case '[':
+ case '(':
+ addPatternStart = true;
+ } // Hack to work around lack of negative lookbehind in JS
+ // A pattern like: *.!(x).!(y|z) needs to ensure that a name
+ // like 'a.xyz.yz' doesn't match. So, the first negative
+ // lookahead, has to look ALL the way ahead, to the end of
+ // the pattern.
+
+
+ for (var n = negativeLists.length - 1; n > -1; n--) {
+ var nl = negativeLists[n];
+ var nlBefore = re.slice(0, nl.reStart);
+ var nlFirst = re.slice(nl.reStart, nl.reEnd - 8);
+ var nlLast = re.slice(nl.reEnd - 8, nl.reEnd);
+ var nlAfter = re.slice(nl.reEnd);
+ nlLast += nlAfter; // Handle nested stuff like *(*.js|!(*.json)), where open parens
+ // mean that we should *not* include the ) in the bit that is considered
+ // "after" the negated section.
+
+ var openParensBefore = nlBefore.split('(').length - 1;
+ var cleanAfter = nlAfter;
+
+ for (i = 0; i < openParensBefore; i++) {
+ cleanAfter = cleanAfter.replace(/\)[+*?]?/, '');
+ }
+
+ nlAfter = cleanAfter;
+ var dollar = '';
+
+ if (nlAfter === '' && isSub !== SUBPARSE) {
+ dollar = '$';
+ }
+
+ var newRe = nlBefore + nlFirst + nlAfter + dollar + nlLast;
+ re = newRe;
+ } // if the re is not "" at this point, then we need to make sure
+ // it doesn't match against an empty path part.
+ // Otherwise a/* will match a/, which it should not.
+
+
+ if (re !== '' && hasMagic) {
+ re = '(?=.)' + re;
+ }
+
+ if (addPatternStart) {
+ re = patternStart + re;
+ } // parsing just a piece of a larger pattern.
+
+
+ if (isSub === SUBPARSE) {
+ return [re, hasMagic];
+ } // skip the regexp for non-magical patterns
+ // unescape anything in it, though, so that it'll be
+ // an exact match against a file etc.
+
+
+ if (!hasMagic) {
+ return globUnescape(pattern);
+ }
+
+ var flags = options.nocase ? 'i' : '';
+
+ try {
+ var regExp = new RegExp('^' + re + '$', flags);
+ } catch (er) {
+ // If it was an invalid regular expression, then it can't match
+ // anything. This trick looks for a character after the end of
+ // the string, which is of course impossible, except in multi-line
+ // mode, but it's not a /m regex.
+ return new RegExp('$.');
+ }
+
+ regExp._glob = pattern;
+ regExp._src = re;
+ return regExp;
+}
+
+minimatch.makeRe = function (pattern, options) {
+ return new Minimatch(pattern, options || {}).makeRe();
+};
+
+Minimatch.prototype.makeRe = makeRe;
+
+function makeRe() {
+ if (this.regexp || this.regexp === false) return this.regexp; // at this point, this.set is a 2d array of partial
+ // pattern strings, or "**".
+ //
+ // It's better to use .match(). This function shouldn't
+ // be used, really, but it's pretty convenient sometimes,
+ // when you just want to work with a regex.
+
+ var set = this.set;
+
+ if (!set.length) {
+ this.regexp = false;
+ return this.regexp;
+ }
+
+ var options = this.options;
+ var twoStar = options.noglobstar ? star : options.dot ? twoStarDot : twoStarNoDot;
+ var flags = options.nocase ? 'i' : '';
+ var re = set.map(function (pattern) {
+ return pattern.map(function (p) {
+ return p === GLOBSTAR ? twoStar : typeof p === 'string' ? regExpEscape(p) : p._src;
+ }).join('\\\/');
+ }).join('|'); // must match entire pattern
+ // ending in a * or ** will make it less strict.
+
+ re = '^(?:' + re + ')$'; // can match anything, as long as it's not this.
+
+ if (this.negate) re = '^(?!' + re + ').*$';
+
+ try {
+ this.regexp = new RegExp(re, flags);
+ } catch (ex) {
+ this.regexp = false;
+ }
+
+ return this.regexp;
+}
+
+minimatch.match = function (list, pattern, options) {
+ options = options || {};
+ var mm = new Minimatch(pattern, options);
+ list = list.filter(function (f) {
+ return mm.match(f);
+ });
+
+ if (mm.options.nonull && !list.length) {
+ list.push(pattern);
+ }
+
+ return list;
+};
+
+Minimatch.prototype.match = match;
+
+function match(f, partial) {
+ this.debug('match', f, this.pattern); // short-circuit in the case of busted things.
+ // comments, etc.
+
+ if (this.comment) return false;
+ if (this.empty) return f === '';
+ if (f === '/' && partial) return true;
+ var options = this.options; // windows: need to use /, not \
+
+ if (path.sep !== '/') {
+ f = f.split(path.sep).join('/');
+ } // treat the test path as a set of pathparts.
+
+
+ f = f.split(slashSplit);
+ this.debug(this.pattern, 'split', f); // just ONE of the pattern sets in this.set needs to match
+ // in order for it to be valid. If negating, then just one
+ // match means that we have failed.
+ // Either way, return on the first hit.
+
+ var set = this.set;
+ this.debug(this.pattern, 'set', set); // Find the basename of the path by looking for the last non-empty segment
+
+ var filename;
+ var i;
+
+ for (i = f.length - 1; i >= 0; i--) {
+ filename = f[i];
+ if (filename) break;
+ }
+
+ for (i = 0; i < set.length; i++) {
+ var pattern = set[i];
+ var file = f;
+
+ if (options.matchBase && pattern.length === 1) {
+ file = [filename];
+ }
+
+ var hit = this.matchOne(file, pattern, partial);
+
+ if (hit) {
+ if (options.flipNegate) return true;
+ return !this.negate;
+ }
+ } // didn't get any hits. this is success if it's a negative
+ // pattern, failure otherwise.
+
+
+ if (options.flipNegate) return false;
+ return this.negate;
+} // set partial to true to test if, for example,
+// "/a/b" matches the start of "/*/b/*/d"
+// Partial means, if you run out of file before you run
+// out of pattern, then that's fine, as long as all
+// the parts match.
+
+
+Minimatch.prototype.matchOne = function (file, pattern, partial) {
+ var options = this.options;
+ this.debug('matchOne', {
+ 'this': this,
+ file: file,
+ pattern: pattern
+ });
+ this.debug('matchOne', file.length, pattern.length);
+
+ for (var fi = 0, pi = 0, fl = file.length, pl = pattern.length; fi < fl && pi < pl; fi++, pi++) {
+ this.debug('matchOne loop');
+ var p = pattern[pi];
+ var f = file[fi];
+ this.debug(pattern, p, f); // should be impossible.
+ // some invalid regexp stuff in the set.
+
+ if (p === false) return false;
+
+ if (p === GLOBSTAR) {
+ this.debug('GLOBSTAR', [pattern, p, f]); // "**"
+ // a/**/b/**/c would match the following:
+ // a/b/x/y/z/c
+ // a/x/y/z/b/c
+ // a/b/x/b/x/c
+ // a/b/c
+ // To do this, take the rest of the pattern after
+ // the **, and see if it would match the file remainder.
+ // If so, return success.
+ // If not, the ** "swallows" a segment, and try again.
+ // This is recursively awful.
+ //
+ // a/**/b/**/c matching a/b/x/y/z/c
+ // - a matches a
+ // - doublestar
+ // - matchOne(b/x/y/z/c, b/**/c)
+ // - b matches b
+ // - doublestar
+ // - matchOne(x/y/z/c, c) -> no
+ // - matchOne(y/z/c, c) -> no
+ // - matchOne(z/c, c) -> no
+ // - matchOne(c, c) yes, hit
+
+ var fr = fi;
+ var pr = pi + 1;
+
+ if (pr === pl) {
+ this.debug('** at the end'); // a ** at the end will just swallow the rest.
+ // We have found a match.
+ // however, it will not swallow /.x, unless
+ // options.dot is set.
+ // . and .. are *never* matched by **, for explosively
+ // exponential reasons.
+
+ for (; fi < fl; fi++) {
+ if (file[fi] === '.' || file[fi] === '..' || !options.dot && file[fi].charAt(0) === '.') return false;
+ }
+
+ return true;
+ } // ok, let's see if we can swallow whatever we can.
+
+
+ while (fr < fl) {
+ var swallowee = file[fr];
+ this.debug('\nglobstar while', file, fr, pattern, pr, swallowee); // XXX remove this slice. Just pass the start index.
+
+ if (this.matchOne(file.slice(fr), pattern.slice(pr), partial)) {
+ this.debug('globstar found match!', fr, fl, swallowee); // found a match.
+
+ return true;
+ } else {
+ // can't swallow "." or ".." ever.
+ // can only swallow ".foo" when explicitly asked.
+ if (swallowee === '.' || swallowee === '..' || !options.dot && swallowee.charAt(0) === '.') {
+ this.debug('dot detected!', file, fr, pattern, pr);
+ break;
+ } // ** swallows a segment, and continue.
+
+
+ this.debug('globstar swallow a segment, and continue');
+ fr++;
+ }
+ } // no match was found.
+ // However, in partial mode, we can't say this is necessarily over.
+ // If there's more *pattern* left, then
+
+
+ if (partial) {
+ // ran out of file
+ this.debug('\n>>> no match, partial?', file, fr, pattern, pr);
+ if (fr === fl) return true;
+ }
+
+ return false;
+ } // something other than **
+ // non-magic patterns just have to match exactly
+ // patterns with magic have been turned into regexps.
+
+
+ var hit;
+
+ if (typeof p === 'string') {
+ if (options.nocase) {
+ hit = f.toLowerCase() === p.toLowerCase();
+ } else {
+ hit = f === p;
+ }
+
+ this.debug('string match', p, f, hit);
+ } else {
+ hit = f.match(p);
+ this.debug('pattern match', p, f, hit);
+ }
+
+ if (!hit) return false;
+ } // Note: ending in / means that we'll get a final ""
+ // at the end of the pattern. This can only match a
+ // corresponding "" at the end of the file.
+ // If the file ends in /, then it can only match a
+ // a pattern that ends in /, unless the pattern just
+ // doesn't have any more for it. But, a/b/ should *not*
+ // match "a/b/*", even though "" matches against the
+ // [^/]*? pattern, except in partial mode, where it might
+ // simply not be reached yet.
+ // However, a/b/ should still satisfy a/*
+ // now either we fell off the end of the pattern, or we're done.
+
+
+ if (fi === fl && pi === pl) {
+ // ran out of pattern and filename at the same time.
+ // an exact hit!
+ return true;
+ } else if (fi === fl) {
+ // ran out of file, but still had pattern left.
+ // this is ok if we're doing the match as part of
+ // a glob fs traversal.
+ return partial;
+ } else if (pi === pl) {
+ // ran out of pattern, still have file left.
+ // this is only acceptable if we're on the very last
+ // empty segment of a file with a trailing slash.
+ // a/* should match a/b/
+ var emptyFileEnd = fi === fl - 1 && file[fi] === '';
+ return emptyFileEnd;
+ } // should be unreachable.
+
+
+ throw new Error('wtf?');
+}; // replace stuff like \* with *
+
+
+function globUnescape(s) {
+ return s.replace(/\\(.)/g, '$1');
+}
+
+function regExpEscape(s) {
+ return s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
+}
+
+/***/ }),
+/* 863 */
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+var concatMap = __webpack_require__(864);
+
+var balanced = __webpack_require__(865);
+
+module.exports = expandTop;
+var escSlash = '\0SLASH' + Math.random() + '\0';
+var escOpen = '\0OPEN' + Math.random() + '\0';
+var escClose = '\0CLOSE' + Math.random() + '\0';
+var escComma = '\0COMMA' + Math.random() + '\0';
+var escPeriod = '\0PERIOD' + Math.random() + '\0';
+
+function numeric(str) {
+ return parseInt(str, 10) == str ? parseInt(str, 10) : str.charCodeAt(0);
+}
+
+function escapeBraces(str) {
+ return str.split('\\\\').join(escSlash).split('\\{').join(escOpen).split('\\}').join(escClose).split('\\,').join(escComma).split('\\.').join(escPeriod);
+}
+
+function unescapeBraces(str) {
+ return str.split(escSlash).join('\\').split(escOpen).join('{').split(escClose).join('}').split(escComma).join(',').split(escPeriod).join('.');
+} // Basically just str.split(","), but handling cases
+// where we have nested braced sections, which should be
+// treated as individual members, like {a,{b,c},d}
+
+
+function parseCommaParts(str) {
+ if (!str) return [''];
+ var parts = [];
+ var m = balanced('{', '}', str);
+ if (!m) return str.split(',');
+ var pre = m.pre;
+ var body = m.body;
+ var post = m.post;
+ var p = pre.split(',');
+ p[p.length - 1] += '{' + body + '}';
+ var postParts = parseCommaParts(post);
+
+ if (post.length) {
+ p[p.length - 1] += postParts.shift();
+ p.push.apply(p, postParts);
+ }
+
+ parts.push.apply(parts, p);
+ return parts;
+}
+
+function expandTop(str) {
+ if (!str) return []; // I don't know why Bash 4.3 does this, but it does.
+ // Anything starting with {} will have the first two bytes preserved
+ // but *only* at the top level, so {},a}b will not expand to anything,
+ // but a{},b}c will be expanded to [a}c,abc].
+ // One could argue that this is a bug in Bash, but since the goal of
+ // this module is to match Bash's rules, we escape a leading {}
+
+ if (str.substr(0, 2) === '{}') {
+ str = '\\{\\}' + str.substr(2);
+ }
+
+ return expand(escapeBraces(str), true).map(unescapeBraces);
+}
+
+function identity(e) {
+ return e;
+}
+
+function embrace(str) {
+ return '{' + str + '}';
+}
+
+function isPadded(el) {
+ return /^-?0\d/.test(el);
+}
+
+function lte(i, y) {
+ return i <= y;
+}
+
+function gte(i, y) {
+ return i >= y;
+}
+
+function expand(str, isTop) {
+ var expansions = [];
+ var m = balanced('{', '}', str);
+ if (!m || /\$$/.test(m.pre)) return [str];
+ var isNumericSequence = /^-?\d+\.\.-?\d+(?:\.\.-?\d+)?$/.test(m.body);
+ var isAlphaSequence = /^[a-zA-Z]\.\.[a-zA-Z](?:\.\.-?\d+)?$/.test(m.body);
+ var isSequence = isNumericSequence || isAlphaSequence;
+ var isOptions = m.body.indexOf(',') >= 0;
+
+ if (!isSequence && !isOptions) {
+ // {a},b}
+ if (m.post.match(/,.*\}/)) {
+ str = m.pre + '{' + m.body + escClose + m.post;
+ return expand(str);
+ }
+
+ return [str];
+ }
+
+ var n;
+
+ if (isSequence) {
+ n = m.body.split(/\.\./);
+ } else {
+ n = parseCommaParts(m.body);
+
+ if (n.length === 1) {
+ // x{{a,b}}y ==> x{a}y x{b}y
+ n = expand(n[0], false).map(embrace);
+
+ if (n.length === 1) {
+ var post = m.post.length ? expand(m.post, false) : [''];
+ return post.map(function (p) {
+ return m.pre + n[0] + p;
+ });
+ }
+ }
+ } // at this point, n is the parts, and we know it's not a comma set
+ // with a single entry.
+ // no need to expand pre, since it is guaranteed to be free of brace-sets
+
+
+ var pre = m.pre;
+ var post = m.post.length ? expand(m.post, false) : [''];
+ var N;
+
+ if (isSequence) {
+ var x = numeric(n[0]);
+ var y = numeric(n[1]);
+ var width = Math.max(n[0].length, n[1].length);
+ var incr = n.length == 3 ? Math.abs(numeric(n[2])) : 1;
+ var test = lte;
+ var reverse = y < x;
+
+ if (reverse) {
+ incr *= -1;
+ test = gte;
+ }
+
+ var pad = n.some(isPadded);
+ N = [];
+
+ for (var i = x; test(i, y); i += incr) {
+ var c;
+
+ if (isAlphaSequence) {
+ c = String.fromCharCode(i);
+ if (c === '\\') c = '';
+ } else {
+ c = String(i);
+
+ if (pad) {
+ var need = width - c.length;
+
+ if (need > 0) {
+ var z = new Array(need + 1).join('0');
+ if (i < 0) c = '-' + z + c.slice(1);else c = z + c;
+ }
+ }
+ }
+
+ N.push(c);
+ }
+ } else {
+ N = concatMap(n, function (el) {
+ return expand(el, false);
+ });
+ }
+
+ for (var j = 0; j < N.length; j++) {
+ for (var k = 0; k < post.length; k++) {
+ var expansion = pre + N[j] + post[k];
+ if (!isTop || isSequence || expansion) expansions.push(expansion);
+ }
+ }
+
+ return expansions;
+}
+
+/***/ }),
+/* 864 */
+/***/ ((module) => {
+
+module.exports = function (xs, fn) {
+ var res = [];
+
+ for (var i = 0; i < xs.length; i++) {
+ var x = fn(xs[i], i);
+ if (isArray(x)) res.push.apply(res, x);else res.push(x);
+ }
+
+ return res;
+};
+
+var isArray = Array.isArray || function (xs) {
+ return Object.prototype.toString.call(xs) === '[object Array]';
+};
+
+/***/ }),
+/* 865 */
+/***/ ((module) => {
+
+"use strict";
+
+
+module.exports = balanced;
+
+function balanced(a, b, str) {
+ if (a instanceof RegExp) a = maybeMatch(a, str);
+ if (b instanceof RegExp) b = maybeMatch(b, str);
+ var r = range(a, b, str);
+ return r && {
+ start: r[0],
+ end: r[1],
+ pre: str.slice(0, r[0]),
+ body: str.slice(r[0] + a.length, r[1]),
+ post: str.slice(r[1] + b.length)
+ };
+}
+
+function maybeMatch(reg, str) {
+ var m = str.match(reg);
+ return m ? m[0] : null;
+}
+
+balanced.range = range;
+
+function range(a, b, str) {
+ var begs, beg, left, right, result;
+ var ai = str.indexOf(a);
+ var bi = str.indexOf(b, ai + 1);
+ var i = ai;
+
+ if (ai >= 0 && bi > 0) {
+ if (a === b) {
+ return [ai, bi];
+ }
+
+ begs = [];
+ left = str.length;
+
+ while (i >= 0 && !result) {
+ if (i == ai) {
+ begs.push(i);
+ ai = str.indexOf(a, i + 1);
+ } else if (begs.length == 1) {
+ result = [begs.pop(), bi];
+ } else {
+ beg = begs.pop();
+
+ if (beg < left) {
+ left = beg;
+ right = bi;
+ }
+
+ bi = str.indexOf(b, i + 1);
+ }
+
+ i = ai < bi && ai >= 0 ? ai : bi;
+ }
+
+ if (begs.length) {
+ result = [left, right];
+ }
+ }
+
+ return result;
+}
+
+/***/ }),
+/* 866 */
+/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
+
+/**
+ * @filedescription Object Schema Package
+ */
+exports.ObjectSchema = __webpack_require__(867).ObjectSchema;
+exports.MergeStrategy = __webpack_require__(868).MergeStrategy;
+exports.ValidationStrategy = __webpack_require__(869).ValidationStrategy;
+
+/***/ }),
+/* 867 */
+/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
+
+"use strict";
+/**
+ * @filedescription Object Schema
+ */
+ //-----------------------------------------------------------------------------
+// Requirements
+//-----------------------------------------------------------------------------
+
+const {
+ MergeStrategy
+} = __webpack_require__(868);
+
+const {
+ ValidationStrategy
+} = __webpack_require__(869); //-----------------------------------------------------------------------------
+// Private
+//-----------------------------------------------------------------------------
+
+
+const strategies = Symbol("strategies");
+const requiredKeys = Symbol("requiredKeys");
+/**
+ * Validates a schema strategy.
+ * @param {string} name The name of the key this strategy is for.
+ * @param {Object} strategy The strategy for the object key.
+ * @param {boolean} [strategy.required=true] Whether the key is required.
+ * @param {string[]} [strategy.requires] Other keys that are required when
+ * this key is present.
+ * @param {Function} strategy.merge A method to call when merging two objects
+ * with the same key.
+ * @param {Function} strategy.validate A method to call when validating an
+ * object with the key.
+ * @returns {void}
+ * @throws {Error} When the strategy is missing a name.
+ * @throws {Error} When the strategy is missing a merge() method.
+ * @throws {Error} When the strategy is missing a validate() method.
+ */
+
+function validateDefinition(name, strategy) {
+ let hasSchema = false;
+
+ if (strategy.schema) {
+ if (typeof strategy.schema === "object") {
+ hasSchema = true;
+ } else {
+ throw new TypeError("Schema must be an object.");
+ }
+ }
+
+ if (typeof strategy.merge === "string") {
+ if (!(strategy.merge in MergeStrategy)) {
+ throw new TypeError("Definition for key \"".concat(name, "\" missing valid merge strategy."));
+ }
+ } else if (!hasSchema && typeof strategy.merge !== "function") {
+ throw new TypeError("Definition for key \"".concat(name, "\" must have a merge property."));
+ }
+
+ if (typeof strategy.validate === "string") {
+ if (!(strategy.validate in ValidationStrategy)) {
+ throw new TypeError("Definition for key \"".concat(name, "\" missing valid validation strategy."));
+ }
+ } else if (!hasSchema && typeof strategy.validate !== "function") {
+ throw new TypeError("Definition for key \"".concat(name, "\" must have a validate() method."));
+ }
+} //-----------------------------------------------------------------------------
+// Class
+//-----------------------------------------------------------------------------
+
+/**
+ * Represents an object validation/merging schema.
+ */
+
+
+class ObjectSchema {
+ /**
+ * Creates a new instance.
+ */
+ constructor(definitions) {
+ if (!definitions) {
+ throw new Error("Schema definitions missing.");
+ }
+ /**
+ * Track all strategies in the schema by key.
+ * @type {Map}
+ * @property strategies
+ */
+
+
+ this[strategies] = new Map();
+ /**
+ * Separately track any keys that are required for faster validation.
+ * @type {Map}
+ * @property requiredKeys
+ */
+
+ this[requiredKeys] = new Map(); // add in all strategies
+
+ for (const key of Object.keys(definitions)) {
+ validateDefinition(key, definitions[key]); // normalize merge and validate methods if subschema is present
+
+ if (typeof definitions[key].schema === "object") {
+ const schema = new ObjectSchema(definitions[key].schema);
+ definitions[key] = { ...definitions[key],
+
+ merge() {
+ let first = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
+ let second = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
+ return schema.merge(first, second);
+ },
+
+ validate(value) {
+ ValidationStrategy.object(value);
+ schema.validate(value);
+ }
+
+ };
+ } // normalize the merge method in case there's a string
+
+
+ if (typeof definitions[key].merge === "string") {
+ definitions[key] = { ...definitions[key],
+ merge: MergeStrategy[definitions[key].merge]
+ };
+ }
+
+ ; // normalize the validate method in case there's a string
+
+ if (typeof definitions[key].validate === "string") {
+ definitions[key] = { ...definitions[key],
+ validate: ValidationStrategy[definitions[key].validate]
+ };
+ }
+
+ ;
+ this[strategies].set(key, definitions[key]);
+
+ if (definitions[key].required) {
+ this[requiredKeys].set(key, definitions[key]);
+ }
+ }
+ }
+ /**
+ * Determines if a strategy has been registered for the given object key.
+ * @param {string} key The object key to find a strategy for.
+ * @returns {boolean} True if the key has a strategy registered, false if not.
+ */
+
+
+ hasKey(key) {
+ return this[strategies].has(key);
+ }
+ /**
+ * Merges objects together to create a new object comprised of the keys
+ * of the all objects. Keys are merged based on the each key's merge
+ * strategy.
+ * @param {...Object} objects The objects to merge.
+ * @returns {Object} A new object with a mix of all objects' keys.
+ * @throws {Error} If any object is invalid.
+ */
+
+
+ merge() {
+ for (var _len = arguments.length, objects = new Array(_len), _key = 0; _key < _len; _key++) {
+ objects[_key] = arguments[_key];
+ }
+
+ // double check arguments
+ if (objects.length < 2) {
+ throw new Error("merge() requires at least two arguments.");
+ }
+
+ if (objects.some(object => object == null || typeof object !== "object")) {
+ throw new Error("All arguments must be objects.");
+ }
+
+ return objects.reduce((result, object) => {
+ this.validate(object);
+
+ for (const [key, strategy] of this[strategies]) {
+ try {
+ if (key in result || key in object) {
+ const value = strategy.merge.call(this, result[key], object[key]);
+
+ if (value !== undefined) {
+ result[key] = value;
+ }
+ }
+ } catch (ex) {
+ ex.message = "Key \"".concat(key, "\": ") + ex.message;
+ throw ex;
+ }
+ }
+
+ return result;
+ }, {});
+ }
+ /**
+ * Validates an object's keys based on the validate strategy for each key.
+ * @param {Object} object The object to validate.
+ * @returns {void}
+ * @throws {Error} When the object is invalid.
+ */
+
+
+ validate(object) {
+ // check existing keys first
+ for (const key of Object.keys(object)) {
+ // check to see if the key is defined
+ if (!this.hasKey(key)) {
+ throw new Error("Unexpected key \"".concat(key, "\" found."));
+ } // validate existing keys
+
+
+ const strategy = this[strategies].get(key); // first check to see if any other keys are required
+
+ if (Array.isArray(strategy.requires)) {
+ if (!strategy.requires.every(otherKey => otherKey in object)) {
+ throw new Error("Key \"".concat(key, "\" requires keys \"").concat(strategy.requires.join("\", \""), "\"."));
+ }
+ } // now apply remaining validation strategy
+
+
+ try {
+ strategy.validate.call(strategy, object[key]);
+ } catch (ex) {
+ ex.message = "Key \"".concat(key, "\": ") + ex.message;
+ throw ex;
+ }
+ } // ensure required keys aren't missing
+
+
+ for (const [key] of this[requiredKeys]) {
+ if (!(key in object)) {
+ throw new Error("Missing required key \"".concat(key, "\"."));
+ }
+ }
+ }
+
+}
+
+exports.ObjectSchema = ObjectSchema;
+
+/***/ }),
+/* 868 */
+/***/ ((__unused_webpack_module, exports) => {
+
+"use strict";
+/**
+ * @filedescription Merge Strategy
+ */
+ //-----------------------------------------------------------------------------
+// Class
+//-----------------------------------------------------------------------------
+
+/**
+ * Container class for several different merge strategies.
+ */
+
+class MergeStrategy {
+ /**
+ * Merges two keys by overwriting the first with the second.
+ * @param {*} value1 The value from the first object key.
+ * @param {*} value2 The value from the second object key.
+ * @returns {*} The second value.
+ */
+ static overwrite(value1, value2) {
+ return value2;
+ }
+ /**
+ * Merges two keys by replacing the first with the second only if the
+ * second is defined.
+ * @param {*} value1 The value from the first object key.
+ * @param {*} value2 The value from the second object key.
+ * @returns {*} The second value if it is defined.
+ */
+
+
+ static replace(value1, value2) {
+ if (typeof value2 !== "undefined") {
+ return value2;
+ }
+
+ return value1;
+ }
+ /**
+ * Merges two properties by assigning properties from the second to the first.
+ * @param {*} value1 The value from the first object key.
+ * @param {*} value2 The value from the second object key.
+ * @returns {*} A new object containing properties from both value1 and
+ * value2.
+ */
+
+
+ static assign(value1, value2) {
+ return Object.assign({}, value1, value2);
+ }
+
+}
+
+exports.MergeStrategy = MergeStrategy;
+
+/***/ }),
+/* 869 */
+/***/ ((__unused_webpack_module, exports) => {
+
+"use strict";
+/**
+ * @filedescription Validation Strategy
+ */
+ //-----------------------------------------------------------------------------
+// Class
+//-----------------------------------------------------------------------------
+
+/**
+ * Container class for several different validation strategies.
+ */
+
+class ValidationStrategy {
+ /**
+ * Validates that a value is an array.
+ * @param {*} value The value to validate.
+ * @returns {void}
+ * @throws {TypeError} If the value is invalid.
+ */
+ static array(value) {
+ if (!Array.isArray(value)) {
+ throw new TypeError("Expected an array.");
+ }
+ }
+ /**
+ * Validates that a value is a boolean.
+ * @param {*} value The value to validate.
+ * @returns {void}
+ * @throws {TypeError} If the value is invalid.
+ */
+
+
+ static boolean(value) {
+ if (typeof value !== "boolean") {
+ throw new TypeError("Expected a Boolean.");
+ }
+ }
+ /**
+ * Validates that a value is a number.
+ * @param {*} value The value to validate.
+ * @returns {void}
+ * @throws {TypeError} If the value is invalid.
+ */
+
+
+ static number(value) {
+ if (typeof value !== "number") {
+ throw new TypeError("Expected a number.");
+ }
+ }
+ /**
+ * Validates that a value is a object.
+ * @param {*} value The value to validate.
+ * @returns {void}
+ * @throws {TypeError} If the value is invalid.
+ */
+
+
+ static object(value) {
+ if (!value || typeof value !== "object") {
+ throw new TypeError("Expected an object.");
+ }
+ }
+ /**
+ * Validates that a value is a object or null.
+ * @param {*} value The value to validate.
+ * @returns {void}
+ * @throws {TypeError} If the value is invalid.
+ */
+
+
+ static "object?"(value) {
+ if (typeof value !== "object") {
+ throw new TypeError("Expected an object or null.");
+ }
+ }
+ /**
+ * Validates that a value is a string.
+ * @param {*} value The value to validate.
+ * @returns {void}
+ * @throws {TypeError} If the value is invalid.
+ */
+
+
+ static string(value) {
+ if (typeof value !== "string") {
+ throw new TypeError("Expected a string.");
+ }
+ }
+ /**
+ * Validates that a value is a non-empty string.
+ * @param {*} value The value to validate.
+ * @returns {void}
+ * @throws {TypeError} If the value is invalid.
+ */
+
+
+ static "string!"(value) {
+ if (typeof value !== "string" || value.length === 0) {
+ throw new TypeError("Expected a non-empty string.");
+ }
+ }
+
+}
+
+exports.ValidationStrategy = ValidationStrategy;
+
+/***/ }),
+/* 870 */
+/***/ ((__unused_webpack_module, exports) => {
+
+"use strict";
+/**
+ * @fileoverview Flat config schema
+ * @author Nicholas C. Zakas
+ */
+ //-----------------------------------------------------------------------------
+// Type Definitions
+//-----------------------------------------------------------------------------
+
+/**
+ * @typedef ObjectPropertySchema
+ * @property {Function|string} merge The function or name of the function to call
+ * to merge multiple objects with this property.
+ * @property {Function|string} validate The function or name of the function to call
+ * to validate the value of this property.
+ */
+//-----------------------------------------------------------------------------
+// Helpers
+//-----------------------------------------------------------------------------
+
+const ruleSeverities = new Map([[0, 0], ["off", 0], [1, 1], ["warn", 1], [2, 2], ["error", 2]]);
+const globalVariablesValues = new Set([true, "true", "writable", "writeable", false, "false", "readonly", "readable", null, "off"]);
+/**
+ * Check if a value is a non-null object.
+ * @param {any} value The value to check.
+ * @returns {boolean} `true` if the value is a non-null object.
+ */
+
+function isNonNullObject(value) {
+ return typeof value === "object" && value !== null;
+}
+/**
+ * Check if a value is undefined.
+ * @param {any} value The value to check.
+ * @returns {boolean} `true` if the value is undefined.
+ */
+
+
+function isUndefined(value) {
+ return typeof value === "undefined";
+}
+/**
+ * Deeply merges two objects.
+ * @param {Object} first The base object.
+ * @param {Object} second The overrides object.
+ * @returns {Object} An object with properties from both first and second.
+ */
+
+
+function deepMerge() {
+ let first = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
+ let second = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
+
+ /*
+ * If the second value is an array, just return it. We don't merge
+ * arrays because order matters and we can't know the correct order.
+ */
+ if (Array.isArray(second)) {
+ return second;
+ }
+ /*
+ * First create a result object where properties from the second object
+ * overwrite properties from the first. This sets up a baseline to use
+ * later rather than needing to inspect and change every property
+ * individually.
+ */
+
+
+ const result = { ...first,
+ ...second
+ };
+
+ for (const key of Object.keys(second)) {
+ // avoid hairy edge case
+ if (key === "__proto__") {
+ continue;
+ }
+
+ const firstValue = first[key];
+ const secondValue = second[key];
+
+ if (isNonNullObject(firstValue)) {
+ result[key] = deepMerge(firstValue, secondValue);
+ } else if (isUndefined(firstValue)) {
+ if (isNonNullObject(secondValue)) {
+ result[key] = deepMerge(Array.isArray(secondValue) ? [] : {}, secondValue);
+ } else if (!isUndefined(secondValue)) {
+ result[key] = secondValue;
+ }
+ }
+ }
+
+ return result;
+}
+/**
+ * Normalizes the rule options config for a given rule by ensuring that
+ * it is an array and that the first item is 0, 1, or 2.
+ * @param {Array|string|number} ruleOptions The rule options config.
+ * @returns {Array} An array of rule options.
+ */
+
+
+function normalizeRuleOptions(ruleOptions) {
+ const finalOptions = Array.isArray(ruleOptions) ? ruleOptions.slice(0) : [ruleOptions];
+ finalOptions[0] = ruleSeverities.get(finalOptions[0]);
+ return finalOptions;
+} //-----------------------------------------------------------------------------
+// Assertions
+//-----------------------------------------------------------------------------
+
+/**
+ * Validates that a value is a valid rule options entry.
+ * @param {any} value The value to check.
+ * @returns {void}
+ * @throws {TypeError} If the value isn't a valid rule options.
+ */
+
+
+function assertIsRuleOptions(value) {
+ if (typeof value !== "string" && typeof value !== "number" && !Array.isArray(value)) {
+ throw new TypeError("Expected a string, number, or array.");
+ }
+}
+/**
+ * Validates that a value is valid rule severity.
+ * @param {any} value The value to check.
+ * @returns {void}
+ * @throws {TypeError} If the value isn't a valid rule severity.
+ */
+
+
+function assertIsRuleSeverity(value) {
+ const severity = typeof value === "string" ? ruleSeverities.get(value.toLowerCase()) : ruleSeverities.get(value);
+
+ if (typeof severity === "undefined") {
+ throw new TypeError("Expected severity of \"off\", 0, \"warn\", 1, \"error\", or 2.");
+ }
+}
+/**
+ * Validates that a given string is the form pluginName/objectName.
+ * @param {string} value The string to check.
+ * @returns {void}
+ * @throws {TypeError} If the string isn't in the correct format.
+ */
+
+
+function assertIsPluginMemberName(value) {
+ if (!/[@a-z0-9-_$]+(?:\/(?:[a-z0-9-_$]+))+$/iu.test(value)) {
+ throw new TypeError("Expected string in the form \"pluginName/objectName\" but found \"".concat(value, "\"."));
+ }
+}
+/**
+ * Validates that a value is an object.
+ * @param {any} value The value to check.
+ * @returns {void}
+ * @throws {TypeError} If the value isn't an object.
+ */
+
+
+function assertIsObject(value) {
+ if (!isNonNullObject(value)) {
+ throw new TypeError("Expected an object.");
+ }
+}
+/**
+ * Validates that a value is an object or a string.
+ * @param {any} value The value to check.
+ * @returns {void}
+ * @throws {TypeError} If the value isn't an object or a string.
+ */
+
+
+function assertIsObjectOrString(value) {
+ if ((!value || typeof value !== "object") && typeof value !== "string") {
+ throw new TypeError("Expected an object or string.");
+ }
+} //-----------------------------------------------------------------------------
+// Low-Level Schemas
+//-----------------------------------------------------------------------------
+
+/** @type {ObjectPropertySchema} */
+
+
+const booleanSchema = {
+ merge: "replace",
+ validate: "boolean"
+};
+/** @type {ObjectPropertySchema} */
+
+const deepObjectAssignSchema = {
+ merge() {
+ let first = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
+ let second = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
+ return deepMerge(first, second);
+ },
+
+ validate: "object"
+}; //-----------------------------------------------------------------------------
+// High-Level Schemas
+//-----------------------------------------------------------------------------
+
+/** @type {ObjectPropertySchema} */
+
+const globalsSchema = {
+ merge: "assign",
+
+ validate(value) {
+ assertIsObject(value);
+
+ for (const key of Object.keys(value)) {
+ // avoid hairy edge case
+ if (key === "__proto__") {
+ continue;
+ }
+
+ if (key !== key.trim()) {
+ throw new TypeError("Global \"".concat(key, "\" has leading or trailing whitespace."));
+ }
+
+ if (!globalVariablesValues.has(value[key])) {
+ throw new TypeError("Key \"".concat(key, "\": Expected \"readonly\", \"writable\", or \"off\"."));
+ }
+ }
+ }
+
+};
+/** @type {ObjectPropertySchema} */
+
+const parserSchema = {
+ merge: "replace",
+
+ validate(value) {
+ assertIsObjectOrString(value);
+
+ if (typeof value === "object" && typeof value.parse !== "function" && typeof value.parseForESLint !== "function") {
+ throw new TypeError("Expected object to have a parse() or parseForESLint() method.");
+ }
+
+ if (typeof value === "string") {
+ assertIsPluginMemberName(value);
+ }
+ }
+
+};
+/** @type {ObjectPropertySchema} */
+
+const pluginsSchema = {
+ merge() {
+ let first = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
+ let second = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
+ const keys = new Set([...Object.keys(first), ...Object.keys(second)]);
+ const result = {}; // manually validate that plugins are not redefined
+
+ for (const key of keys) {
+ // avoid hairy edge case
+ if (key === "__proto__") {
+ continue;
+ }
+
+ if (key in first && key in second && first[key] !== second[key]) {
+ throw new TypeError("Cannot redefine plugin \"".concat(key, "\"."));
+ }
+
+ result[key] = second[key] || first[key];
+ }
+
+ return result;
+ },
+
+ validate(value) {
+ // first check the value to be sure it's an object
+ if (value === null || typeof value !== "object") {
+ throw new TypeError("Expected an object.");
+ } // second check the keys to make sure they are objects
+
+
+ for (const key of Object.keys(value)) {
+ // avoid hairy edge case
+ if (key === "__proto__") {
+ continue;
+ }
+
+ if (value[key] === null || typeof value[key] !== "object") {
+ throw new TypeError("Key \"".concat(key, "\": Expected an object."));
+ }
+ }
+ }
+
+};
+/** @type {ObjectPropertySchema} */
+
+const processorSchema = {
+ merge: "replace",
+
+ validate(value) {
+ if (typeof value === "string") {
+ assertIsPluginMemberName(value);
+ } else if (value && typeof value === "object") {
+ if (typeof value.preprocess !== "function" || typeof value.postprocess !== "function") {
+ throw new TypeError("Object must have a preprocess() and a postprocess() method.");
+ }
+ } else {
+ throw new TypeError("Expected an object or a string.");
+ }
+ }
+
+};
+/** @type {ObjectPropertySchema} */
+
+const rulesSchema = {
+ merge() {
+ let first = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
+ let second = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
+ const result = { ...first,
+ ...second
+ };
+
+ for (const ruleId of Object.keys(result)) {
+ // avoid hairy edge case
+ if (ruleId === "__proto__") {
+ /* eslint-disable-next-line no-proto -- Though deprecated, may still be present */
+ delete result.__proto__;
+ continue;
+ }
+
+ result[ruleId] = normalizeRuleOptions(result[ruleId]);
+ /*
+ * If either rule config is missing, then the correct
+ * config is already present and we just need to normalize
+ * the severity.
+ */
+
+ if (!(ruleId in first) || !(ruleId in second)) {
+ continue;
+ }
+
+ const firstRuleOptions = normalizeRuleOptions(first[ruleId]);
+ const secondRuleOptions = normalizeRuleOptions(second[ruleId]);
+ /*
+ * If the second rule config only has a severity (length of 1),
+ * then use that severity and keep the rest of the options from
+ * the first rule config.
+ */
+
+ if (secondRuleOptions.length === 1) {
+ result[ruleId] = [secondRuleOptions[0], ...firstRuleOptions.slice(1)];
+ continue;
+ }
+ /*
+ * In any other situation, then the second rule config takes
+ * precedence. That means the value at `result[ruleId]` is
+ * already correct and no further work is necessary.
+ */
+
+ }
+
+ return result;
+ },
+
+ validate(value) {
+ assertIsObject(value);
+ let lastRuleId; // Performance: One try-catch has less overhead than one per loop iteration
+
+ try {
+ /*
+ * We are not checking the rule schema here because there is no
+ * guarantee that the rule definition is present at this point. Instead
+ * we wait and check the rule schema during the finalization step
+ * of calculating a config.
+ */
+ for (const ruleId of Object.keys(value)) {
+ // avoid hairy edge case
+ if (ruleId === "__proto__") {
+ continue;
+ }
+
+ lastRuleId = ruleId;
+ const ruleOptions = value[ruleId];
+ assertIsRuleOptions(ruleOptions);
+
+ if (Array.isArray(ruleOptions)) {
+ assertIsRuleSeverity(ruleOptions[0]);
+ } else {
+ assertIsRuleSeverity(ruleOptions);
+ }
+ }
+ } catch (error) {
+ error.message = "Key \"".concat(lastRuleId, "\": ").concat(error.message);
+ throw error;
+ }
+ }
-// Defitions for deprecation warnings.
-const deprecationWarningMessages = {
- ESLINT_LEGACY_ECMAFEATURES:
- "The 'ecmaFeatures' config file property is deprecated and has no effect.",
- ESLINT_PERSONAL_CONFIG_LOAD:
- "'~/.eslintrc.*' config files have been deprecated. " +
- "Please use a config file per project or the '--config' option.",
- ESLINT_PERSONAL_CONFIG_SUPPRESS:
- "'~/.eslintrc.*' config files have been deprecated. " +
- "Please remove it or add 'root:true' to the config files in your " +
- "projects in order to avoid loading '~/.eslintrc.*' accidentally."
};
+/** @type {ObjectPropertySchema} */
+
+const ecmaVersionSchema = {
+ merge: "replace",
+
+ validate(value) {
+ if (typeof value === "number" || value === "latest") {
+ return;
+ }
+
+ throw new TypeError("Expected a number or \"latest\".");
+ }
+
+};
+/** @type {ObjectPropertySchema} */
+
+const sourceTypeSchema = {
+ merge: "replace",
+
+ validate(value) {
+ if (typeof value !== "string" || !/^(?:script|module|commonjs)$/u.test(value)) {
+ throw new TypeError("Expected \"script\", \"module\", or \"commonjs\".");
+ }
+ }
+
+}; //-----------------------------------------------------------------------------
+// Full schema
+//-----------------------------------------------------------------------------
+
+exports.flatConfigSchema = {
+ settings: deepObjectAssignSchema,
+ linterOptions: {
+ schema: {
+ noInlineConfig: booleanSchema,
+ reportUnusedDisableDirectives: booleanSchema
+ }
+ },
+ languageOptions: {
+ schema: {
+ ecmaVersion: ecmaVersionSchema,
+ sourceType: sourceTypeSchema,
+ globals: globalsSchema,
+ parser: parserSchema,
+ parserOptions: deepObjectAssignSchema
+ }
+ },
+ processor: processorSchema,
+ plugins: pluginsSchema,
+ rules: rulesSchema
+};
+
+/***/ }),
+/* 871 */
+/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
+
+"use strict";
+/**
+ * @fileoverview Rule Validator
+ * @author Nicholas C. Zakas
+ */
+ //-----------------------------------------------------------------------------
+// Requirements
+//-----------------------------------------------------------------------------
-const sourceFileErrorCache = new Set();
+const ajv = __webpack_require__(872)();
+
+const {
+ parseRuleId,
+ getRuleFromConfig
+} = __webpack_require__(859);
+
+const ruleReplacements = __webpack_require__(858); //-----------------------------------------------------------------------------
+// Helpers
+//-----------------------------------------------------------------------------
/**
- * Emits a deprecation warning containing a given filepath. A new deprecation warning is emitted
- * for each unique file path, but repeated invocations with the same file path have no effect.
- * No warnings are emitted if the `--no-deprecation` or `--no-warnings` Node runtime flags are active.
- * @param {string} source The name of the configuration source to report the warning for.
- * @param {string} errorCode The warning message to show.
+ * Throws a helpful error when a rule cannot be found.
+ * @param {Object} ruleId The rule identifier.
+ * @param {string} ruleId.pluginName The ID of the rule to find.
+ * @param {string} ruleId.ruleName The ID of the rule to find.
+ * @param {Object} config The config to search in.
+ * @throws {TypeError} For missing plugin or rule.
* @returns {void}
*/
-function emitDeprecationWarning(source, errorCode) {
- const cacheKey = JSON.stringify({ source, errorCode });
- if (sourceFileErrorCache.has(cacheKey)) {
- return;
+
+function throwRuleNotFoundError(_ref, config) {
+ let {
+ pluginName,
+ ruleName
+ } = _ref;
+ const ruleId = pluginName === "@" ? ruleName : "".concat(pluginName, "/").concat(ruleName);
+ const errorMessageHeader = "Key \"rules\": Key \"".concat(ruleId, "\"");
+ let errorMessage = "".concat(errorMessageHeader, ": Could not find plugin \"").concat(pluginName, "\"."); // if the plugin exists then we need to check if the rule exists
+
+ if (config.plugins && config.plugins[pluginName]) {
+ const replacementRuleName = ruleReplacements.rules[ruleName];
+
+ if (pluginName === "@" && replacementRuleName) {
+ errorMessage = "".concat(errorMessageHeader, ": Rule \"").concat(ruleName, "\" was removed and replaced by \"").concat(replacementRuleName, "\".");
+ } else {
+ errorMessage = "".concat(errorMessageHeader, ": Could not find \"").concat(ruleName, "\" in plugin \"").concat(pluginName, "\"."); // otherwise, let's see if we can find the rule name elsewhere
+
+ for (const [otherPluginName, otherPlugin] of Object.entries(config.plugins)) {
+ if (otherPlugin.rules && otherPlugin.rules[ruleName]) {
+ errorMessage += " Did you mean \"".concat(otherPluginName, "/").concat(ruleName, "\"?");
+ break;
+ }
+ }
+ } // falls through to throw error
+
+ }
+
+ throw new TypeError(errorMessage);
+}
+/**
+ * Gets a complete options schema for a rule.
+ * @param {{create: Function, schema: (Array|null)}} rule A new-style rule object
+ * @returns {Object} JSON Schema for the rule's options.
+ */
+
+
+function getRuleOptionsSchema(rule) {
+ if (!rule) {
+ return null;
+ }
+
+ const schema = rule.schema || rule.meta && rule.meta.schema;
+
+ if (Array.isArray(schema)) {
+ if (schema.length) {
+ return {
+ type: "array",
+ items: schema,
+ minItems: 0,
+ maxItems: schema.length
+ };
}
- sourceFileErrorCache.add(cacheKey);
- const rel = path__default["default"].relative(process.cwd(), source);
- const message = deprecationWarningMessages[errorCode];
+ return {
+ type: "array",
+ minItems: 0,
+ maxItems: 0
+ };
+ } // Given a full schema, leave it alone
+
+
+ return schema || null;
+} //-----------------------------------------------------------------------------
+// Exports
+//-----------------------------------------------------------------------------
+
+/**
+ * Implements validation functionality for the rules portion of a config.
+ */
+
+
+class RuleValidator {
+ /**
+ * Creates a new instance.
+ */
+ constructor() {
+ /**
+ * A collection of compiled validators for rules that have already
+ * been validated.
+ * @type {WeakMap}
+ */
+ this.validators = new WeakMap();
+ }
+ /**
+ * Validates all of the rule configurations in a config against each
+ * rule's schema.
+ * @param {Object} config The full config to validate. This object must
+ * contain both the rules section and the plugins section.
+ * @returns {void}
+ * @throws {Error} If a rule's configuration does not match its schema.
+ */
+
+
+ validate(config) {
+ if (!config.rules) {
+ return;
+ }
+
+ for (const [ruleId, ruleOptions] of Object.entries(config.rules)) {
+ // check for edge case
+ if (ruleId === "__proto__") {
+ continue;
+ }
+ /*
+ * If a rule is disabled, we don't do any validation. This allows
+ * users to safely set any value to 0 or "off" without worrying
+ * that it will cause a validation error.
+ *
+ * Note: ruleOptions is always an array at this point because
+ * this validation occurs after FlatConfigArray has merged and
+ * normalized values.
+ */
+
+
+ if (ruleOptions[0] === 0) {
+ continue;
+ }
+
+ const rule = getRuleFromConfig(ruleId, config);
+
+ if (!rule) {
+ throwRuleNotFoundError(parseRuleId(ruleId), config);
+ } // Precompile and cache validator the first time
+
+
+ if (!this.validators.has(rule)) {
+ const schema = getRuleOptionsSchema(rule);
+
+ if (schema) {
+ this.validators.set(rule, ajv.compile(schema));
+ }
+ }
+
+ const validateRule = this.validators.get(rule);
+
+ if (validateRule) {
+ validateRule(ruleOptions.slice(1));
+
+ if (validateRule.errors) {
+ throw new Error("Key \"rules\": Key \"".concat(ruleId, "\": ").concat(validateRule.errors.map(error => "\tValue ".concat(JSON.stringify(error.data), " ").concat(error.message, ".\n")).join("")));
+ }
+ }
+ }
+ }
- process.emitWarning(
- `${message} (found in "${rel}")`,
- "DeprecationWarning",
- errorCode
- );
}
+exports.RuleValidator = RuleValidator;
+
+/***/ }),
+/* 872 */
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+"use strict";
/**
* @fileoverview The instance of Ajv validator.
* @author Evgeny Poberezkin
*/
+ //------------------------------------------------------------------------------
+// Requirements
+//------------------------------------------------------------------------------
+
+const Ajv = __webpack_require__(446),
+ metaSchema = __webpack_require__(873); //------------------------------------------------------------------------------
+// Public Interface
+//------------------------------------------------------------------------------
+
+
+module.exports = function () {
+ let additionalOptions = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
+ const ajv = new Ajv({
+ meta: false,
+ useDefaults: true,
+ validateSchema: false,
+ missingRefs: "ignore",
+ verbose: true,
+ schemaId: "auto",
+ ...additionalOptions
+ });
+ ajv.addMetaSchema(metaSchema); // eslint-disable-next-line no-underscore-dangle -- Ajv's API
+
+ ajv._opts.defaultMeta = metaSchema.id;
+ return ajv;
+};
+
+/***/ }),
+/* 873 */
+/***/ ((module) => {
+
+"use strict";
+module.exports = JSON.parse('{"id":"http://json-schema.org/draft-04/schema#","$schema":"http://json-schema.org/draft-04/schema#","description":"Core schema meta-schema","definitions":{"schemaArray":{"type":"array","minItems":1,"items":{"$ref":"#"}},"positiveInteger":{"type":"integer","minimum":0},"positiveIntegerDefault0":{"allOf":[{"$ref":"#/definitions/positiveInteger"},{"default":0}]},"simpleTypes":{"enum":["array","boolean","integer","null","number","object","string"]},"stringArray":{"type":"array","items":{"type":"string"},"minItems":1,"uniqueItems":true}},"type":"object","properties":{"id":{"type":"string"},"$schema":{"type":"string"},"title":{"type":"string"},"description":{"type":"string"},"default":{},"multipleOf":{"type":"number","minimum":0,"exclusiveMinimum":true},"maximum":{"type":"number"},"exclusiveMaximum":{"type":"boolean","default":false},"minimum":{"type":"number"},"exclusiveMinimum":{"type":"boolean","default":false},"maxLength":{"$ref":"#/definitions/positiveInteger"},"minLength":{"$ref":"#/definitions/positiveIntegerDefault0"},"pattern":{"type":"string","format":"regex"},"additionalItems":{"anyOf":[{"type":"boolean"},{"$ref":"#"}],"default":{}},"items":{"anyOf":[{"$ref":"#"},{"$ref":"#/definitions/schemaArray"}],"default":{}},"maxItems":{"$ref":"#/definitions/positiveInteger"},"minItems":{"$ref":"#/definitions/positiveIntegerDefault0"},"uniqueItems":{"type":"boolean","default":false},"maxProperties":{"$ref":"#/definitions/positiveInteger"},"minProperties":{"$ref":"#/definitions/positiveIntegerDefault0"},"required":{"$ref":"#/definitions/stringArray"},"additionalProperties":{"anyOf":[{"type":"boolean"},{"$ref":"#"}],"default":{}},"definitions":{"type":"object","additionalProperties":{"$ref":"#"},"default":{}},"properties":{"type":"object","additionalProperties":{"$ref":"#"},"default":{}},"patternProperties":{"type":"object","additionalProperties":{"$ref":"#"},"default":{}},"dependencies":{"type":"object","additionalProperties":{"anyOf":[{"$ref":"#"},{"$ref":"#/definitions/stringArray"}]}},"enum":{"type":"array","minItems":1,"uniqueItems":true},"type":{"anyOf":[{"$ref":"#/definitions/simpleTypes"},{"type":"array","items":{"$ref":"#/definitions/simpleTypes"},"minItems":1,"uniqueItems":true}]},"format":{"type":"string"},"allOf":{"$ref":"#/definitions/schemaArray"},"anyOf":{"$ref":"#/definitions/schemaArray"},"oneOf":{"$ref":"#/definitions/schemaArray"},"not":{"$ref":"#"}},"dependencies":{"exclusiveMaximum":["maximum"],"exclusiveMinimum":["minimum"]},"default":{}}');
+
+/***/ }),
+/* 874 */
+/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
+"use strict";
+/**
+ * @fileoverview Default configuration
+ * @author Nicholas C. Zakas
+ */
+ //-----------------------------------------------------------------------------
+// Requirements
//-----------------------------------------------------------------------------
+
+const Rules = __webpack_require__(545); //-----------------------------------------------------------------------------
// Helpers
//-----------------------------------------------------------------------------
-/*
- * Copied from ajv/lib/refs/json-schema-draft-04.json
- * The MIT License (MIT)
- * Copyright (c) 2015-2017 Evgeny Poberezkin
- */
-const metaSchema = {
- id: "http://json-schema.org/draft-04/schema#",
- $schema: "http://json-schema.org/draft-04/schema#",
- description: "Core schema meta-schema",
- definitions: {
- schemaArray: {
- type: "array",
- minItems: 1,
- items: { $ref: "#" }
- },
- positiveInteger: {
- type: "integer",
- minimum: 0
- },
- positiveIntegerDefault0: {
- allOf: [{ $ref: "#/definitions/positiveInteger" }, { default: 0 }]
- },
- simpleTypes: {
- enum: ["array", "boolean", "integer", "null", "number", "object", "string"]
+
+exports.defaultConfig = [{
+ plugins: {
+ "@": {
+ parsers: {
+ espree: __webpack_require__(436)
+ },
+
+ /*
+ * Because we try to delay loading rules until absolutely
+ * necessary, a proxy allows us to hook into the lazy-loading
+ * aspect of the rules map while still keeping all of the
+ * relevant configuration inside of the config array.
+ */
+ rules: new Proxy({}, {
+ get(target, property) {
+ return Rules.get(property);
},
- stringArray: {
- type: "array",
- items: { type: "string" },
- minItems: 1,
- uniqueItems: true
+
+ has(target, property) {
+ return Rules.has(property);
}
- },
- type: "object",
- properties: {
- id: {
- type: "string"
- },
- $schema: {
- type: "string"
- },
- title: {
- type: "string"
- },
- description: {
- type: "string"
- },
- default: { },
- multipleOf: {
- type: "number",
- minimum: 0,
- exclusiveMinimum: true
- },
- maximum: {
- type: "number"
- },
- exclusiveMaximum: {
- type: "boolean",
- default: false
- },
- minimum: {
- type: "number"
- },
- exclusiveMinimum: {
- type: "boolean",
- default: false
- },
- maxLength: { $ref: "#/definitions/positiveInteger" },
- minLength: { $ref: "#/definitions/positiveIntegerDefault0" },
- pattern: {
- type: "string",
- format: "regex"
- },
- additionalItems: {
- anyOf: [
- { type: "boolean" },
- { $ref: "#" }
- ],
- default: { }
- },
- items: {
- anyOf: [
- { $ref: "#" },
- { $ref: "#/definitions/schemaArray" }
- ],
- default: { }
- },
- maxItems: { $ref: "#/definitions/positiveInteger" },
- minItems: { $ref: "#/definitions/positiveIntegerDefault0" },
- uniqueItems: {
- type: "boolean",
- default: false
- },
- maxProperties: { $ref: "#/definitions/positiveInteger" },
- minProperties: { $ref: "#/definitions/positiveIntegerDefault0" },
- required: { $ref: "#/definitions/stringArray" },
- additionalProperties: {
- anyOf: [
- { type: "boolean" },
- { $ref: "#" }
- ],
- default: { }
- },
- definitions: {
- type: "object",
- additionalProperties: { $ref: "#" },
- default: { }
- },
- properties: {
- type: "object",
- additionalProperties: { $ref: "#" },
- default: { }
- },
- patternProperties: {
- type: "object",
- additionalProperties: { $ref: "#" },
- default: { }
- },
- dependencies: {
- type: "object",
- additionalProperties: {
- anyOf: [
- { $ref: "#" },
- { $ref: "#/definitions/stringArray" }
- ]
- }
- },
- enum: {
- type: "array",
- minItems: 1,
- uniqueItems: true
- },
- type: {
- anyOf: [
- { $ref: "#/definitions/simpleTypes" },
- {
- type: "array",
- items: { $ref: "#/definitions/simpleTypes" },
- minItems: 1,
- uniqueItems: true
- }
- ]
- },
- format: { type: "string" },
- allOf: { $ref: "#/definitions/schemaArray" },
- anyOf: { $ref: "#/definitions/schemaArray" },
- oneOf: { $ref: "#/definitions/schemaArray" },
- not: { $ref: "#" }
- },
- dependencies: {
- exclusiveMaximum: ["maximum"],
- exclusiveMinimum: ["minimum"]
- },
- default: { }
+
+ })
+ }
+ },
+ ignores: ["**/node_modules/**", ".git/**"],
+ languageOptions: {
+ ecmaVersion: "latest",
+ sourceType: "module",
+ parser: "@/espree",
+ parserOptions: {}
+ }
+}, {
+ files: ["**/*.cjs"],
+ languageOptions: {
+ sourceType: "commonjs"
+ }
+}];
+
+/***/ }),
+/* 875 */
+/***/ ((module) => {
+
+"use strict";
+/**
+ * @fileoverview Configuration applied when a user configuration extends from
+ * eslint:recommended.
+ * @author Nicholas C. Zakas
+ */
+
+/* eslint sort-keys: ["error", "asc"] -- Long, so make more readable */
+
+/** @type {import("../lib/shared/types").ConfigData} */
+
+module.exports = {
+ rules: {
+ "constructor-super": "error",
+ "for-direction": "error",
+ "getter-return": "error",
+ "no-async-promise-executor": "error",
+ "no-case-declarations": "error",
+ "no-class-assign": "error",
+ "no-compare-neg-zero": "error",
+ "no-cond-assign": "error",
+ "no-const-assign": "error",
+ "no-constant-condition": "error",
+ "no-control-regex": "error",
+ "no-debugger": "error",
+ "no-delete-var": "error",
+ "no-dupe-args": "error",
+ "no-dupe-class-members": "error",
+ "no-dupe-else-if": "error",
+ "no-dupe-keys": "error",
+ "no-duplicate-case": "error",
+ "no-empty": "error",
+ "no-empty-character-class": "error",
+ "no-empty-pattern": "error",
+ "no-ex-assign": "error",
+ "no-extra-boolean-cast": "error",
+ "no-extra-semi": "error",
+ "no-fallthrough": "error",
+ "no-func-assign": "error",
+ "no-global-assign": "error",
+ "no-import-assign": "error",
+ "no-inner-declarations": "error",
+ "no-invalid-regexp": "error",
+ "no-irregular-whitespace": "error",
+ "no-loss-of-precision": "error",
+ "no-misleading-character-class": "error",
+ "no-mixed-spaces-and-tabs": "error",
+ "no-new-symbol": "error",
+ "no-nonoctal-decimal-escape": "error",
+ "no-obj-calls": "error",
+ "no-octal": "error",
+ "no-prototype-builtins": "error",
+ "no-redeclare": "error",
+ "no-regex-spaces": "error",
+ "no-self-assign": "error",
+ "no-setter-return": "error",
+ "no-shadow-restricted-names": "error",
+ "no-sparse-arrays": "error",
+ "no-this-before-super": "error",
+ "no-undef": "error",
+ "no-unexpected-multiline": "error",
+ "no-unreachable": "error",
+ "no-unsafe-finally": "error",
+ "no-unsafe-negation": "error",
+ "no-unsafe-optional-chaining": "error",
+ "no-unused-labels": "error",
+ "no-unused-vars": "error",
+ "no-useless-backreference": "error",
+ "no-useless-catch": "error",
+ "no-useless-escape": "error",
+ "no-with": "error",
+ "require-yield": "error",
+ "use-isnan": "error",
+ "valid-typeof": "error"
+ }
+};
+
+/***/ }),
+/* 876 */
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+"use strict";
+/**
+ * @fileoverview Config to enable all rules.
+ * @author Robert Fletcher
+ */
+ //------------------------------------------------------------------------------
+// Requirements
+//------------------------------------------------------------------------------
+
+const builtInRules = __webpack_require__(545); //------------------------------------------------------------------------------
+// Helpers
+//------------------------------------------------------------------------------
+
+
+const allRules = {};
+
+for (const [ruleId, rule] of builtInRules) {
+ if (!rule.meta.deprecated) {
+ allRules[ruleId] = "error";
+ }
+} //------------------------------------------------------------------------------
+// Public Interface
+//------------------------------------------------------------------------------
+
+/** @type {import("../lib/shared/types").ConfigData} */
+
+
+module.exports = {
+ rules: allRules
+};
+
+/***/ }),
+/* 877 */
+/***/ ((module) => {
+
+"use strict";
+/**
+ * @fileoverview Globals for ecmaVersion/sourceType
+ * @author Nicholas C. Zakas
+ */
+ //-----------------------------------------------------------------------------
+// Globals
+//-----------------------------------------------------------------------------
+
+const commonjs = {
+ exports: true,
+ global: false,
+ module: false,
+ require: false
+};
+const es3 = {
+ Array: false,
+ Boolean: false,
+ constructor: false,
+ Date: false,
+ decodeURI: false,
+ decodeURIComponent: false,
+ encodeURI: false,
+ encodeURIComponent: false,
+ Error: false,
+ escape: false,
+ eval: false,
+ EvalError: false,
+ Function: false,
+ hasOwnProperty: false,
+ Infinity: false,
+ isFinite: false,
+ isNaN: false,
+ isPrototypeOf: false,
+ Math: false,
+ NaN: false,
+ Number: false,
+ Object: false,
+ parseFloat: false,
+ parseInt: false,
+ propertyIsEnumerable: false,
+ RangeError: false,
+ ReferenceError: false,
+ RegExp: false,
+ String: false,
+ SyntaxError: false,
+ toLocaleString: false,
+ toString: false,
+ TypeError: false,
+ undefined: false,
+ unescape: false,
+ URIError: false,
+ valueOf: false
+};
+const es5 = { ...es3,
+ JSON: false
+};
+const es2015 = { ...es5,
+ ArrayBuffer: false,
+ DataView: false,
+ Float32Array: false,
+ Float64Array: false,
+ Int16Array: false,
+ Int32Array: false,
+ Int8Array: false,
+ Map: false,
+ Promise: false,
+ Proxy: false,
+ Reflect: false,
+ Set: false,
+ Symbol: false,
+ Uint16Array: false,
+ Uint32Array: false,
+ Uint8Array: false,
+ Uint8ClampedArray: false,
+ WeakMap: false,
+ WeakSet: false
+}; // no new globals in ES2016
+
+const es2016 = { ...es2015
+};
+const es2017 = { ...es2016,
+ Atomics: false,
+ SharedArrayBuffer: false
+}; // no new globals in ES2018
+
+const es2018 = { ...es2017
+}; // no new globals in ES2019
+
+const es2019 = { ...es2018
+};
+const es2020 = { ...es2019,
+ BigInt: false,
+ BigInt64Array: false,
+ BigUint64Array: false,
+ globalThis: false
+};
+const es2021 = { ...es2020,
+ AggregateError: false,
+ FinalizationRegistry: false,
+ WeakRef: false
+};
+const es2022 = { ...es2021
+}; //-----------------------------------------------------------------------------
+// Exports
+//-----------------------------------------------------------------------------
+
+module.exports = {
+ commonjs,
+ es3,
+ es5,
+ es2015,
+ es2016,
+ es2017,
+ es2018,
+ es2019,
+ es2020,
+ es2021,
+ es2022
+};
+
+/***/ }),
+/* 878 */
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+"use strict";
+
+
+const {
+ ESLint
+} = __webpack_require__(879);
+
+module.exports = {
+ ESLint
};
-//------------------------------------------------------------------------------
-// Public Interface
-//------------------------------------------------------------------------------
+/***/ }),
+/* 879 */
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+
+"use strict";
+/* provided dependency */ var process = __webpack_require__(494);
+/**
+ * @fileoverview Main API Class
+ * @author Kai Cataldo
+ * @author Toru Nagashima
+ */
+ //------------------------------------------------------------------------------
+// Requirements
+//------------------------------------------------------------------------------
+
+const path = __webpack_require__(429);
+
+const fs = __webpack_require__(880);
+
+const {
+ promisify
+} = __webpack_require__(439);
+
+const {
+ CLIEngine,
+ getCLIEngineInternalSlots
+} = __webpack_require__(881);
+
+const BuiltinRules = __webpack_require__(545);
+
+const {
+ Legacy: {
+ ConfigOps: {
+ getRuleSeverity
+ }
+ }
+} = __webpack_require__(883);
+
+const {
+ version
+} = __webpack_require__(443); //------------------------------------------------------------------------------
+// Typedefs
+//------------------------------------------------------------------------------
+
+/** @typedef {import("../cli-engine/cli-engine").LintReport} CLIEngineLintReport */
+
+/** @typedef {import("../shared/types").DeprecatedRuleInfo} DeprecatedRuleInfo */
+
+/** @typedef {import("../shared/types").ConfigData} ConfigData */
+
+/** @typedef {import("../shared/types").LintMessage} LintMessage */
+
+/** @typedef {import("../shared/types").Plugin} Plugin */
+
+/** @typedef {import("../shared/types").Rule} Rule */
+
+/**
+ * The main formatter object.
+ * @typedef Formatter
+ * @property {function(LintResult[]): string | Promise<string>} format format function.
+ */
+
+/**
+ * The options with which to configure the ESLint instance.
+ * @typedef {Object} ESLintOptions
+ * @property {boolean} [allowInlineConfig] Enable or disable inline configuration comments.
+ * @property {ConfigData} [baseConfig] Base config object, extended by all configs used with this instance
+ * @property {boolean} [cache] Enable result caching.
+ * @property {string} [cacheLocation] The cache file to use instead of .eslintcache.
+ * @property {"metadata" | "content"} [cacheStrategy] The strategy used to detect changed files.
+ * @property {string} [cwd] The value to use for the current working directory.
+ * @property {boolean} [errorOnUnmatchedPattern] If `false` then `ESLint#lintFiles()` doesn't throw even if no target files found. Defaults to `true`.
+ * @property {string[]} [extensions] An array of file extensions to check.
+ * @property {boolean|Function} [fix] Execute in autofix mode. If a function, should return a boolean.
+ * @property {string[]} [fixTypes] Array of rule types to apply fixes for.
+ * @property {boolean} [globInputPaths] Set to false to skip glob resolution of input file paths to lint (default: true). If false, each input file paths is assumed to be a non-glob path to an existing file.
+ * @property {boolean} [ignore] False disables use of .eslintignore.
+ * @property {string} [ignorePath] The ignore file to use instead of .eslintignore.
+ * @property {ConfigData} [overrideConfig] Override config object, overrides all configs used with this instance
+ * @property {string} [overrideConfigFile] The configuration file to use.
+ * @property {Record<string,Plugin>|null} [plugins] Preloaded plugins. This is a map-like object, keys are plugin IDs and each value is implementation.
+ * @property {"error" | "warn" | "off"} [reportUnusedDisableDirectives] the severity to report unused eslint-disable directives.
+ * @property {string} [resolvePluginsRelativeTo] The folder where plugins should be resolved from, defaulting to the CWD.
+ * @property {string[]} [rulePaths] An array of directories to load custom rules from.
+ * @property {boolean} [useEslintrc] False disables looking for .eslintrc.* files.
+ */
+
+/**
+ * A rules metadata object.
+ * @typedef {Object} RulesMeta
+ * @property {string} id The plugin ID.
+ * @property {Object} definition The plugin definition.
+ */
+
+/**
+ * A linting result.
+ * @typedef {Object} LintResult
+ * @property {string} filePath The path to the file that was linted.
+ * @property {LintMessage[]} messages All of the messages for the result.
+ * @property {number} errorCount Number of errors for the result.
+ * @property {number} warningCount Number of warnings for the result.
+ * @property {number} fixableErrorCount Number of fixable errors for the result.
+ * @property {number} fixableWarningCount Number of fixable warnings for the result.
+ * @property {string} [source] The source code of the file that was linted.
+ * @property {string} [output] The source code of the file that was linted, with as many fixes applied as possible.
+ * @property {DeprecatedRuleInfo[]} usedDeprecatedRules The list of used deprecated rules.
+ */
+
+/**
+ * Private members for the `ESLint` instance.
+ * @typedef {Object} ESLintPrivateMembers
+ * @property {CLIEngine} cliEngine The wrapped CLIEngine instance.
+ * @property {ESLintOptions} options The options used to instantiate the ESLint instance.
+ */
+//------------------------------------------------------------------------------
+// Helpers
+//------------------------------------------------------------------------------
+
+
+const writeFile = promisify(fs.writeFile);
+/**
+ * The map with which to store private class members.
+ * @type {WeakMap<ESLint, ESLintPrivateMembers>}
+ */
+
+const privateMembersMap = new WeakMap();
+/**
+ * Check if a given value is a non-empty string or not.
+ * @param {any} x The value to check.
+ * @returns {boolean} `true` if `x` is a non-empty string.
+ */
+
+function isNonEmptyString(x) {
+ return typeof x === "string" && x.trim() !== "";
+}
+/**
+ * Check if a given value is an array of non-empty stringss or not.
+ * @param {any} x The value to check.
+ * @returns {boolean} `true` if `x` is an array of non-empty stringss.
+ */
+
+
+function isArrayOfNonEmptyString(x) {
+ return Array.isArray(x) && x.every(isNonEmptyString);
+}
+/**
+ * Check if a given value is a valid fix type or not.
+ * @param {any} x The value to check.
+ * @returns {boolean} `true` if `x` is valid fix type.
+ */
+
+
+function isFixType(x) {
+ return x === "directive" || x === "problem" || x === "suggestion" || x === "layout";
+}
+/**
+ * Check if a given value is an array of fix types or not.
+ * @param {any} x The value to check.
+ * @returns {boolean} `true` if `x` is an array of fix types.
+ */
+
+
+function isFixTypeArray(x) {
+ return Array.isArray(x) && x.every(isFixType);
+}
+/**
+ * The error for invalid options.
+ */
+
+
+class ESLintInvalidOptionsError extends Error {
+ constructor(messages) {
+ super("Invalid Options:\n- ".concat(messages.join("\n- ")));
+ this.code = "ESLINT_INVALID_OPTIONS";
+ Error.captureStackTrace(this, ESLintInvalidOptionsError);
+ }
+
+}
+/**
+ * Validates and normalizes options for the wrapped CLIEngine instance.
+ * @param {ESLintOptions} options The options to process.
+ * @throws {ESLintInvalidOptionsError} If of any of a variety of type errors.
+ * @returns {ESLintOptions} The normalized options.
+ */
+
+
+function processOptions(_ref) {
+ let {
+ allowInlineConfig = true,
+ // ← we cannot use `overrideConfig.noInlineConfig` instead because `allowInlineConfig` has side-effect that suppress warnings that show inline configs are ignored.
+ baseConfig = null,
+ cache = false,
+ cacheLocation = ".eslintcache",
+ cacheStrategy = "metadata",
+ cwd = process.cwd(),
+ errorOnUnmatchedPattern = true,
+ extensions = null,
+ // ← should be null by default because if it's an array then it suppresses RFC20 feature.
+ fix = false,
+ fixTypes = null,
+ // ← should be null by default because if it's an array then it suppresses rules that don't have the `meta.type` property.
+ globInputPaths = true,
+ ignore = true,
+ ignorePath = null,
+ // ← should be null by default because if it's a string then it may throw ENOENT.
+ overrideConfig = null,
+ overrideConfigFile = null,
+ plugins = {},
+ reportUnusedDisableDirectives = null,
+ // ← should be null by default because if it's a string then it overrides the 'reportUnusedDisableDirectives' setting in config files. And we cannot use `overrideConfig.reportUnusedDisableDirectives` instead because we cannot configure the `error` severity with that.
+ resolvePluginsRelativeTo = null,
+ // ← should be null by default because if it's a string then it suppresses RFC47 feature.
+ rulePaths = [],
+ useEslintrc = true,
+ ...unknownOptions
+ } = _ref;
+ const errors = [];
+ const unknownOptionKeys = Object.keys(unknownOptions);
+
+ if (unknownOptionKeys.length >= 1) {
+ errors.push("Unknown options: ".concat(unknownOptionKeys.join(", ")));
+
+ if (unknownOptionKeys.includes("cacheFile")) {
+ errors.push("'cacheFile' has been removed. Please use the 'cacheLocation' option instead.");
+ }
+
+ if (unknownOptionKeys.includes("configFile")) {
+ errors.push("'configFile' has been removed. Please use the 'overrideConfigFile' option instead.");
+ }
+
+ if (unknownOptionKeys.includes("envs")) {
+ errors.push("'envs' has been removed. Please use the 'overrideConfig.env' option instead.");
+ }
+
+ if (unknownOptionKeys.includes("globals")) {
+ errors.push("'globals' has been removed. Please use the 'overrideConfig.globals' option instead.");
+ }
+
+ if (unknownOptionKeys.includes("ignorePattern")) {
+ errors.push("'ignorePattern' has been removed. Please use the 'overrideConfig.ignorePatterns' option instead.");
+ }
+
+ if (unknownOptionKeys.includes("parser")) {
+ errors.push("'parser' has been removed. Please use the 'overrideConfig.parser' option instead.");
+ }
+
+ if (unknownOptionKeys.includes("parserOptions")) {
+ errors.push("'parserOptions' has been removed. Please use the 'overrideConfig.parserOptions' option instead.");
+ }
+
+ if (unknownOptionKeys.includes("rules")) {
+ errors.push("'rules' has been removed. Please use the 'overrideConfig.rules' option instead.");
+ }
+ }
+
+ if (typeof allowInlineConfig !== "boolean") {
+ errors.push("'allowInlineConfig' must be a boolean.");
+ }
-var ajvOrig = (additionalOptions = {}) => {
- const ajv = new Ajv__default["default"]({
- meta: false,
- useDefaults: true,
- validateSchema: false,
- missingRefs: "ignore",
- verbose: true,
- schemaId: "auto",
- ...additionalOptions
- });
+ if (typeof baseConfig !== "object") {
+ errors.push("'baseConfig' must be an object or null.");
+ }
- ajv.addMetaSchema(metaSchema);
- // eslint-disable-next-line no-underscore-dangle
- ajv._opts.defaultMeta = metaSchema.id;
+ if (typeof cache !== "boolean") {
+ errors.push("'cache' must be a boolean.");
+ }
- return ajv;
-};
+ if (!isNonEmptyString(cacheLocation)) {
+ errors.push("'cacheLocation' must be a non-empty string.");
+ }
-/**
- * @fileoverview Defines a schema for configs.
- * @author Sylvan Mably
- */
+ if (cacheStrategy !== "metadata" && cacheStrategy !== "content") {
+ errors.push("'cacheStrategy' must be any of \"metadata\", \"content\".");
+ }
-const baseConfigProperties = {
- $schema: { type: "string" },
- env: { type: "object" },
- extends: { $ref: "#/definitions/stringOrStrings" },
- globals: { type: "object" },
- overrides: {
- type: "array",
- items: { $ref: "#/definitions/overrideConfig" },
- additionalItems: false
- },
- parser: { type: ["string", "null"] },
- parserOptions: { type: "object" },
- plugins: { type: "array" },
- processor: { type: "string" },
- rules: { type: "object" },
- settings: { type: "object" },
- noInlineConfig: { type: "boolean" },
- reportUnusedDisableDirectives: { type: "boolean" },
+ if (!isNonEmptyString(cwd) || !path.isAbsolute(cwd)) {
+ errors.push("'cwd' must be an absolute path.");
+ }
- ecmaFeatures: { type: "object" } // deprecated; logs a warning when used
-};
+ if (typeof errorOnUnmatchedPattern !== "boolean") {
+ errors.push("'errorOnUnmatchedPattern' must be a boolean.");
+ }
-const configSchema = {
- definitions: {
- stringOrStrings: {
- oneOf: [
- { type: "string" },
- {
- type: "array",
- items: { type: "string" },
- additionalItems: false
- }
- ]
- },
- stringOrStringsRequired: {
- oneOf: [
- { type: "string" },
- {
- type: "array",
- items: { type: "string" },
- additionalItems: false,
- minItems: 1
- }
- ]
- },
+ if (!isArrayOfNonEmptyString(extensions) && extensions !== null) {
+ errors.push("'extensions' must be an array of non-empty strings or null.");
+ }
- // Config at top-level.
- objectConfig: {
- type: "object",
- properties: {
- root: { type: "boolean" },
- ignorePatterns: { $ref: "#/definitions/stringOrStrings" },
- ...baseConfigProperties
- },
- additionalProperties: false
- },
+ if (typeof fix !== "boolean" && typeof fix !== "function") {
+ errors.push("'fix' must be a boolean or a function.");
+ }
- // Config in `overrides`.
- overrideConfig: {
- type: "object",
- properties: {
- excludedFiles: { $ref: "#/definitions/stringOrStrings" },
- files: { $ref: "#/definitions/stringOrStringsRequired" },
- ...baseConfigProperties
- },
- required: ["files"],
- additionalProperties: false
- }
- },
+ if (fixTypes !== null && !isFixTypeArray(fixTypes)) {
+ errors.push("'fixTypes' must be an array of any of \"directive\", \"problem\", \"suggestion\", and \"layout\".");
+ }
- $ref: "#/definitions/objectConfig"
-};
+ if (typeof globInputPaths !== "boolean") {
+ errors.push("'globInputPaths' must be a boolean.");
+ }
+
+ if (typeof ignore !== "boolean") {
+ errors.push("'ignore' must be a boolean.");
+ }
+
+ if (!isNonEmptyString(ignorePath) && ignorePath !== null) {
+ errors.push("'ignorePath' must be a non-empty string or null.");
+ }
+
+ if (typeof overrideConfig !== "object") {
+ errors.push("'overrideConfig' must be an object or null.");
+ }
+
+ if (!isNonEmptyString(overrideConfigFile) && overrideConfigFile !== null) {
+ errors.push("'overrideConfigFile' must be a non-empty string or null.");
+ }
+
+ if (typeof plugins !== "object") {
+ errors.push("'plugins' must be an object or null.");
+ } else if (plugins !== null && Object.keys(plugins).includes("")) {
+ errors.push("'plugins' must not include an empty string.");
+ }
+ if (Array.isArray(plugins)) {
+ errors.push("'plugins' doesn't add plugins to configuration to load. Please use the 'overrideConfig.plugins' option instead.");
+ }
+
+ if (reportUnusedDisableDirectives !== "error" && reportUnusedDisableDirectives !== "warn" && reportUnusedDisableDirectives !== "off" && reportUnusedDisableDirectives !== null) {
+ errors.push("'reportUnusedDisableDirectives' must be any of \"error\", \"warn\", \"off\", and null.");
+ }
+
+ if (!isNonEmptyString(resolvePluginsRelativeTo) && resolvePluginsRelativeTo !== null) {
+ errors.push("'resolvePluginsRelativeTo' must be a non-empty string or null.");
+ }
+
+ if (!isArrayOfNonEmptyString(rulePaths)) {
+ errors.push("'rulePaths' must be an array of non-empty strings.");
+ }
+
+ if (typeof useEslintrc !== "boolean") {
+ errors.push("'useEslintrc' must be a boolean.");
+ }
+
+ if (errors.length > 0) {
+ throw new ESLintInvalidOptionsError(errors);
+ }
+
+ return {
+ allowInlineConfig,
+ baseConfig,
+ cache,
+ cacheLocation,
+ cacheStrategy,
+ configFile: overrideConfigFile,
+ cwd,
+ errorOnUnmatchedPattern,
+ extensions,
+ fix,
+ fixTypes,
+ globInputPaths,
+ ignore,
+ ignorePath,
+ reportUnusedDisableDirectives,
+ resolvePluginsRelativeTo,
+ rulePaths,
+ useEslintrc
+ };
+}
/**
- * @fileoverview Defines environment settings and globals.
- * @author Elan Shanker
+ * Check if a value has one or more properties and that value is not undefined.
+ * @param {any} obj The value to check.
+ * @returns {boolean} `true` if `obj` has one or more properties that that value is not undefined.
*/
-//------------------------------------------------------------------------------
-// Helpers
-//------------------------------------------------------------------------------
+function hasDefinedProperty(obj) {
+ if (typeof obj === "object" && obj !== null) {
+ for (const key in obj) {
+ if (typeof obj[key] !== "undefined") {
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
/**
- * Get the object that has difference.
- * @param {Record<string,boolean>} current The newer object.
- * @param {Record<string,boolean>} prev The older object.
- * @returns {Record<string,boolean>} The difference object.
+ * Create rulesMeta object.
+ * @param {Map<string,Rule>} rules a map of rules from which to generate the object.
+ * @returns {Object} metadata for all enabled rules.
*/
-function getDiff(current, prev) {
- const retv = {};
- for (const [key, value] of Object.entries(current)) {
- if (!Object.hasOwnProperty.call(prev, key)) {
- retv[key] = value;
- }
- }
- return retv;
+function createRulesMeta(rules) {
+ return Array.from(rules).reduce((retVal, _ref2) => {
+ let [id, rule] = _ref2;
+ retVal[id] = rule.meta;
+ return retVal;
+ }, {});
}
+/** @type {WeakMap<ExtractedConfig, DeprecatedRuleInfo[]>} */
-const newGlobals2015 = getDiff(globals__default["default"].es2015, globals__default["default"].es5); // 19 variables such as Promise, Map, ...
-const newGlobals2017 = {
- Atomics: false,
- SharedArrayBuffer: false
-};
-const newGlobals2020 = {
- BigInt: false,
- BigInt64Array: false,
- BigUint64Array: false,
- globalThis: false
-};
-const newGlobals2021 = {
- AggregateError: false,
- FinalizationRegistry: false,
- WeakRef: false
-};
+const usedDeprecatedRulesCache = new WeakMap();
+/**
+ * Create used deprecated rule list.
+ * @param {CLIEngine} cliEngine The CLIEngine instance.
+ * @param {string} maybeFilePath The absolute path to a lint target file or `"<text>"`.
+ * @returns {DeprecatedRuleInfo[]} The used deprecated rule list.
+ */
-//------------------------------------------------------------------------------
-// Public Interface
-//------------------------------------------------------------------------------
+function getOrFindUsedDeprecatedRules(cliEngine, maybeFilePath) {
+ const {
+ configArrayFactory,
+ options: {
+ cwd
+ }
+ } = getCLIEngineInternalSlots(cliEngine);
+ const filePath = path.isAbsolute(maybeFilePath) ? maybeFilePath : path.join(cwd, "__placeholder__.js");
+ const configArray = configArrayFactory.getConfigArrayForFile(filePath);
+ const config = configArray.extractConfig(filePath); // Most files use the same config, so cache it.
-/** @type {Map<string, import("../lib/shared/types").Environment>} */
-var environments = new Map(Object.entries({
+ if (!usedDeprecatedRulesCache.has(config)) {
+ const pluginRules = configArray.pluginRules;
+ const retv = [];
- // Language
- builtin: {
- globals: globals__default["default"].es5
- },
- es6: {
- globals: newGlobals2015,
- parserOptions: {
- ecmaVersion: 6
- }
- },
- es2015: {
- globals: newGlobals2015,
- parserOptions: {
- ecmaVersion: 6
- }
- },
- es2017: {
- globals: { ...newGlobals2015, ...newGlobals2017 },
- parserOptions: {
- ecmaVersion: 8
- }
- },
- es2020: {
- globals: { ...newGlobals2015, ...newGlobals2017, ...newGlobals2020 },
- parserOptions: {
- ecmaVersion: 11
- }
- },
- es2021: {
- globals: { ...newGlobals2015, ...newGlobals2017, ...newGlobals2020, ...newGlobals2021 },
- parserOptions: {
- ecmaVersion: 12
- }
- },
+ for (const [ruleId, ruleConf] of Object.entries(config.rules)) {
+ if (getRuleSeverity(ruleConf) === 0) {
+ continue;
+ }
- // Platforms
- browser: {
- globals: globals__default["default"].browser
- },
- node: {
- globals: globals__default["default"].node,
- parserOptions: {
- ecmaFeatures: {
- globalReturn: true
- }
- }
- },
- "shared-node-browser": {
- globals: globals__default["default"]["shared-node-browser"]
- },
- worker: {
- globals: globals__default["default"].worker
- },
- serviceworker: {
- globals: globals__default["default"].serviceworker
- },
+ const rule = pluginRules.get(ruleId) || BuiltinRules.get(ruleId);
+ const meta = rule && rule.meta;
- // Frameworks
- commonjs: {
- globals: globals__default["default"].commonjs,
- parserOptions: {
- ecmaFeatures: {
- globalReturn: true
- }
- }
- },
- amd: {
- globals: globals__default["default"].amd
- },
- mocha: {
- globals: globals__default["default"].mocha
- },
- jasmine: {
- globals: globals__default["default"].jasmine
- },
- jest: {
- globals: globals__default["default"].jest
- },
- phantomjs: {
- globals: globals__default["default"].phantomjs
- },
- jquery: {
- globals: globals__default["default"].jquery
- },
- qunit: {
- globals: globals__default["default"].qunit
- },
- prototypejs: {
- globals: globals__default["default"].prototypejs
- },
- shelljs: {
- globals: globals__default["default"].shelljs
- },
- meteor: {
- globals: globals__default["default"].meteor
- },
- mongo: {
- globals: globals__default["default"].mongo
- },
- protractor: {
- globals: globals__default["default"].protractor
- },
- applescript: {
- globals: globals__default["default"].applescript
- },
- nashorn: {
- globals: globals__default["default"].nashorn
- },
- atomtest: {
- globals: globals__default["default"].atomtest
- },
- embertest: {
- globals: globals__default["default"].embertest
- },
- webextensions: {
- globals: globals__default["default"].webextensions
- },
- greasemonkey: {
- globals: globals__default["default"].greasemonkey
+ if (meta && meta.deprecated) {
+ retv.push({
+ ruleId,
+ replacedBy: meta.replacedBy || []
+ });
+ }
}
-}));
+ usedDeprecatedRulesCache.set(config, Object.freeze(retv));
+ }
+
+ return usedDeprecatedRulesCache.get(config);
+}
/**
- * @fileoverview Validates configs.
- * @author Brandon Mills
+ * Processes the linting results generated by a CLIEngine linting report to
+ * match the ESLint class's API.
+ * @param {CLIEngine} cliEngine The CLIEngine instance.
+ * @param {CLIEngineLintReport} report The CLIEngine linting report to process.
+ * @returns {LintResult[]} The processed linting results.
*/
-const ajv = ajvOrig();
-const ruleValidators = new WeakMap();
-const noop = Function.prototype;
+function processCLIEngineLintReport(cliEngine, _ref3) {
+ let {
+ results
+ } = _ref3;
+ const descriptor = {
+ configurable: true,
+ enumerable: true,
-//------------------------------------------------------------------------------
-// Private
-//------------------------------------------------------------------------------
-let validateSchema;
-const severityMap = {
- error: 2,
- warn: 1,
- off: 0
-};
+ get() {
+ return getOrFindUsedDeprecatedRules(cliEngine, this.filePath);
+ }
-const validated = new WeakSet();
+ };
-//-----------------------------------------------------------------------------
-// Exports
-//-----------------------------------------------------------------------------
+ for (const result of results) {
+ Object.defineProperty(result, "usedDeprecatedRules", descriptor);
+ }
-class ConfigValidator {
- constructor({ builtInRules = new Map() } = {}) {
- this.builtInRules = builtInRules;
- }
+ return results;
+}
+/**
+ * An Array.prototype.sort() compatible compare function to order results by their file path.
+ * @param {LintResult} a The first lint result.
+ * @param {LintResult} b The second lint result.
+ * @returns {number} An integer representing the order in which the two results should occur.
+ */
- /**
- * Gets a complete options schema for a rule.
- * @param {{create: Function, schema: (Array|null)}} rule A new-style rule object
- * @returns {Object} JSON Schema for the rule's options.
- */
- getRuleOptionsSchema(rule) {
- if (!rule) {
- return null;
- }
- const schema = rule.schema || rule.meta && rule.meta.schema;
+function compareResultsByFilePath(a, b) {
+ if (a.filePath < b.filePath) {
+ return -1;
+ }
- // Given a tuple of schemas, insert warning level at the beginning
- if (Array.isArray(schema)) {
- if (schema.length) {
- return {
- type: "array",
- items: schema,
- minItems: 0,
- maxItems: schema.length
- };
- }
- return {
- type: "array",
- minItems: 0,
- maxItems: 0
- };
+ if (a.filePath > b.filePath) {
+ return 1;
+ }
- }
+ return 0;
+}
+/**
+ * Main API.
+ */
- // Given a full schema, leave it alone
- return schema || null;
- }
- /**
- * Validates a rule's severity and returns the severity value. Throws an error if the severity is invalid.
- * @param {options} options The given options for the rule.
- * @returns {number|string} The rule's severity value
+class ESLint {
+ /**
+ * Creates a new instance of the main ESLint API.
+ * @param {ESLintOptions} options The options for this instance.
+ */
+ constructor() {
+ let options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
+ const processedOptions = processOptions(options);
+ const cliEngine = new CLIEngine(processedOptions, {
+ preloadedPlugins: options.plugins
+ });
+ const {
+ configArrayFactory,
+ lastConfigArrays
+ } = getCLIEngineInternalSlots(cliEngine);
+ let updated = false;
+ /*
+ * Address `overrideConfig` to set override config.
+ * Operate the `configArrayFactory` internal slot directly because this
+ * functionality doesn't exist as the public API of CLIEngine.
*/
- validateRuleSeverity(options) {
- const severity = Array.isArray(options) ? options[0] : options;
- const normSeverity = typeof severity === "string" ? severityMap[severity.toLowerCase()] : severity;
- if (normSeverity === 0 || normSeverity === 1 || normSeverity === 2) {
- return normSeverity;
- }
+ if (hasDefinedProperty(options.overrideConfig)) {
+ configArrayFactory.setOverrideConfig(options.overrideConfig);
+ updated = true;
+ } // Update caches.
- 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`);
- }
+ if (updated) {
+ configArrayFactory.clearCache();
+ lastConfigArrays[0] = configArrayFactory.getConfigArrayForFile();
+ } // Initialize private properties.
- /**
- * Validates the non-severity options passed to a rule, based on its schema.
- * @param {{create: Function}} rule The rule to validate
- * @param {Array} localOptions The options for the rule, excluding severity
- * @returns {void}
- */
- validateRuleSchema(rule, localOptions) {
- if (!ruleValidators.has(rule)) {
- const schema = this.getRuleOptionsSchema(rule);
- if (schema) {
- ruleValidators.set(rule, ajv.compile(schema));
- }
- }
+ privateMembersMap.set(this, {
+ cliEngine,
+ options: processedOptions
+ });
+ }
+ /**
+ * The version text.
+ * @type {string}
+ */
- const validateRule = ruleValidators.get(rule);
- if (validateRule) {
- validateRule(localOptions);
- if (validateRule.errors) {
- throw new Error(validateRule.errors.map(
- error => `\tValue ${JSON.stringify(error.data)} ${error.message}.\n`
- ).join(""));
- }
- }
+ static get version() {
+ return version;
+ }
+ /**
+ * Outputs fixes from the given results to files.
+ * @param {LintResult[]} results The lint results.
+ * @returns {Promise<void>} Returns a promise that is used to track side effects.
+ */
+
+
+ static async outputFixes(results) {
+ if (!Array.isArray(results)) {
+ throw new Error("'results' must be an array");
}
- /**
- * Validates a rule's options against its schema.
- * @param {{create: Function}|null} rule The rule that the config is being validated for
- * @param {string} ruleId The rule's unique name.
- * @param {Array|number} options The given options for the rule.
- * @param {string|null} source The name of the configuration source to report in any errors. If null or undefined,
- * no source is prepended to the message.
- * @returns {void}
- */
- validateRuleOptions(rule, ruleId, options, source = null) {
- try {
- const severity = this.validateRuleSeverity(options);
+ await Promise.all(results.filter(result => {
+ if (typeof result !== "object" || result === null) {
+ throw new Error("'results' must include only objects");
+ }
- if (severity !== 0) {
- this.validateRuleSchema(rule, Array.isArray(options) ? options.slice(1) : []);
- }
- } catch (err) {
- const enhancedMessage = `Configuration for rule "${ruleId}" is invalid:\n${err.message}`;
+ return typeof result.output === "string" && path.isAbsolute(result.filePath);
+ }).map(r => writeFile(r.filePath, r.output)));
+ }
+ /**
+ * Returns results that only contains errors.
+ * @param {LintResult[]} results The results to filter.
+ * @returns {LintResult[]} The filtered results.
+ */
- if (typeof source === "string") {
- throw new Error(`${source}:\n\t${enhancedMessage}`);
- } else {
- throw new Error(enhancedMessage);
- }
- }
+
+ static getErrorResults(results) {
+ return CLIEngine.getErrorResults(results);
+ }
+ /**
+ * Returns meta objects for each rule represented in the lint results.
+ * @param {LintResult[]} results The results to fetch rules meta for.
+ * @returns {Object} A mapping of ruleIds to rule meta objects.
+ */
+
+
+ getRulesMetaForResults(results) {
+ const resultRuleIds = new Set(); // first gather all ruleIds from all results
+
+ for (const result of results) {
+ for (const {
+ ruleId
+ } of result.messages) {
+ resultRuleIds.add(ruleId);
+ }
+ } // create a map of all rules in the results
+
+
+ const {
+ cliEngine
+ } = privateMembersMap.get(this);
+ const rules = cliEngine.getRules();
+ const resultRules = new Map();
+
+ for (const [ruleId, rule] of rules) {
+ if (resultRuleIds.has(ruleId)) {
+ resultRules.set(ruleId, rule);
+ }
}
- /**
- * Validates an environment object
- * @param {Object} environment The environment config object to validate.
- * @param {string} source The name of the configuration source to report in any errors.
- * @param {function(envId:string): Object} [getAdditionalEnv] A map from strings to loaded environments.
- * @returns {void}
- */
- validateEnvironment(
- environment,
- source,
- getAdditionalEnv = noop
- ) {
+ return createRulesMeta(resultRules);
+ }
+ /**
+ * Executes the current configuration on an array of file and directory names.
+ * @param {string[]} patterns An array of file and directory names.
+ * @returns {Promise<LintResult[]>} The results of linting the file patterns given.
+ */
- // not having an environment is ok
- if (!environment) {
- return;
- }
- Object.keys(environment).forEach(id => {
- const env = getAdditionalEnv(id) || environments.get(id) || null;
+ async lintFiles(patterns) {
+ if (!isNonEmptyString(patterns) && !isArrayOfNonEmptyString(patterns)) {
+ throw new Error("'patterns' must be a non-empty string or an array of non-empty strings");
+ }
+
+ const {
+ cliEngine
+ } = privateMembersMap.get(this);
+ return processCLIEngineLintReport(cliEngine, cliEngine.executeOnFiles(patterns));
+ }
+ /**
+ * Executes the current configuration on text.
+ * @param {string} code A string of JavaScript code to lint.
+ * @param {Object} [options] The options.
+ * @param {string} [options.filePath] The path to the file of the source code.
+ * @param {boolean} [options.warnIgnored] When set to true, warn if given filePath is an ignored path.
+ * @returns {Promise<LintResult[]>} The results of linting the string of code given.
+ */
+
- if (!env) {
- const message = `${source}:\n\tEnvironment key "${id}" is unknown\n`;
+ async lintText(code) {
+ let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
- throw new Error(message);
- }
- });
+ if (typeof code !== "string") {
+ throw new Error("'code' must be a string");
}
- /**
- * Validates a rules config object
- * @param {Object} rulesConfig The rules config object to validate.
- * @param {string} source The name of the configuration source to report in any errors.
- * @param {function(ruleId:string): Object} getAdditionalRule A map from strings to loaded rules
- * @returns {void}
- */
- validateRules(
- rulesConfig,
- source,
- getAdditionalRule = noop
- ) {
- if (!rulesConfig) {
- return;
- }
+ if (typeof options !== "object") {
+ throw new Error("'options' must be an object, null, or undefined");
+ }
- Object.keys(rulesConfig).forEach(id => {
- const rule = getAdditionalRule(id) || this.builtInRules.get(id) || null;
+ const {
+ filePath,
+ warnIgnored = false,
+ ...unknownOptions
+ } = options || {};
+ const unknownOptionKeys = Object.keys(unknownOptions);
- this.validateRuleOptions(rule, id, rulesConfig[id], source);
- });
+ if (unknownOptionKeys.length > 0) {
+ throw new Error("'options' must not include the unknown option(s): ".concat(unknownOptionKeys.join(", ")));
}
- /**
- * Validates a `globals` section of a config file
- * @param {Object} globalsConfig The `globals` section
- * @param {string|null} source The name of the configuration source to report in the event of an error.
- * @returns {void}
- */
- validateGlobals(globalsConfig, source = null) {
- if (!globalsConfig) {
- return;
- }
+ if (filePath !== void 0 && !isNonEmptyString(filePath)) {
+ throw new Error("'options.filePath' must be a non-empty string or undefined");
+ }
- Object.entries(globalsConfig)
- .forEach(([configuredGlobal, configuredValue]) => {
- try {
- normalizeConfigGlobal(configuredValue);
- } catch (err) {
- throw new Error(`ESLint configuration of global '${configuredGlobal}' in ${source} is invalid:\n${err.message}`);
- }
- });
+ if (typeof warnIgnored !== "boolean") {
+ throw new Error("'options.warnIgnored' must be a boolean or undefined");
}
- /**
- * Validate `processor` configuration.
- * @param {string|undefined} processorName The processor name.
- * @param {string} source The name of config file.
- * @param {function(id:string): Processor} getProcessor The getter of defined processors.
- * @returns {void}
- */
- validateProcessor(processorName, source, getProcessor) {
- if (processorName && !getProcessor(processorName)) {
- throw new Error(`ESLint configuration of processor in '${source}' is invalid: '${processorName}' was not found.`);
- }
+ const {
+ cliEngine
+ } = privateMembersMap.get(this);
+ return processCLIEngineLintReport(cliEngine, cliEngine.executeOnText(code, filePath, warnIgnored));
+ }
+ /**
+ * Returns the formatter representing the given formatter name.
+ * @param {string} [name] The name of the formatter to load.
+ * The following values are allowed:
+ * - `undefined` ... Load `stylish` builtin formatter.
+ * - A builtin formatter name ... Load the builtin formatter.
+ * - A thirdparty formatter name:
+ * - `foo` → `eslint-formatter-foo`
+ * - `@foo` → `@foo/eslint-formatter`
+ * - `@foo/bar` → `@foo/eslint-formatter-bar`
+ * - A file path ... Load the file.
+ * @returns {Promise<Formatter>} A promise resolving to the formatter object.
+ * This promise will be rejected if the given formatter was not found or not
+ * a function.
+ */
+
+
+ async loadFormatter() {
+ let name = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : "stylish";
+
+ if (typeof name !== "string") {
+ throw new Error("'name' must be a string");
}
- /**
- * Formats an array of schema validation errors.
- * @param {Array} errors An array of error messages to format.
- * @returns {string} Formatted error message
- */
- formatErrors(errors) {
- return errors.map(error => {
- if (error.keyword === "additionalProperties") {
- const formattedPropertyPath = error.dataPath.length ? `${error.dataPath.slice(1)}.${error.params.additionalProperty}` : error.params.additionalProperty;
+ const {
+ cliEngine,
+ options
+ } = privateMembersMap.get(this);
+ const formatter = cliEngine.getFormatter(name);
- return `Unexpected top-level property "${formattedPropertyPath}"`;
- }
- if (error.keyword === "type") {
- const formattedField = error.dataPath.slice(1);
- const formattedExpectedType = Array.isArray(error.schema) ? error.schema.join("/") : error.schema;
- const formattedValue = JSON.stringify(error.data);
+ if (typeof formatter !== "function") {
+ throw new Error("Formatter must be a function, but got a ".concat(typeof formatter, "."));
+ }
- return `Property "${formattedField}" is the wrong type (expected ${formattedExpectedType} but got \`${formattedValue}\`)`;
+ return {
+ /**
+ * The main formatter method.
+ * @param {LintResults[]} results The lint results to format.
+ * @returns {string | Promise<string>} The formatted lint results.
+ */
+ format(results) {
+ let rulesMeta = null;
+ results.sort(compareResultsByFilePath);
+ return formatter(results, {
+ get cwd() {
+ return options.cwd;
+ },
+
+ get rulesMeta() {
+ if (!rulesMeta) {
+ rulesMeta = createRulesMeta(cliEngine.getRules());
}
- const field = error.dataPath[0] === "." ? error.dataPath.slice(1) : error.dataPath;
+ return rulesMeta;
+ }
- return `"${field}" ${error.message}. Value: ${JSON.stringify(error.data)}`;
- }).map(message => `\t- ${message}.\n`).join("");
- }
+ });
+ }
- /**
- * Validates the top level properties of the config object.
- * @param {Object} config The config object to validate.
- * @param {string} source The name of the configuration source to report in any errors.
- * @returns {void}
- */
- validateConfigSchema(config, source = null) {
- validateSchema = validateSchema || ajv.compile(configSchema);
+ };
+ }
+ /**
+ * Returns a configuration object for the given file based on the CLI options.
+ * This is the same logic used by the ESLint CLI executable to determine
+ * configuration for each file it processes.
+ * @param {string} filePath The path of the file to retrieve a config object for.
+ * @returns {Promise<ConfigData>} A configuration object for the file.
+ */
- if (!validateSchema(config)) {
- throw new Error(`ESLint configuration in ${source} is invalid:\n${this.formatErrors(validateSchema.errors)}`);
- }
- if (Object.hasOwnProperty.call(config, "ecmaFeatures")) {
- emitDeprecationWarning(source, "ESLINT_LEGACY_ECMAFEATURES");
- }
+ async calculateConfigForFile(filePath) {
+ if (!isNonEmptyString(filePath)) {
+ throw new Error("'filePath' must be a non-empty string");
}
- /**
- * Validates an entire config object.
- * @param {Object} config The config object to validate.
- * @param {string} source The name of the configuration source to report in any errors.
- * @param {function(ruleId:string): Object} [getAdditionalRule] A map from strings to loaded rules.
- * @param {function(envId:string): Object} [getAdditionalEnv] A map from strings to loaded envs.
- * @returns {void}
- */
- validate(config, source, getAdditionalRule, getAdditionalEnv) {
- this.validateConfigSchema(config, source);
- this.validateRules(config.rules, source, getAdditionalRule);
- this.validateEnvironment(config.env, source, getAdditionalEnv);
- this.validateGlobals(config.globals, source);
+ const {
+ cliEngine
+ } = privateMembersMap.get(this);
+ return cliEngine.getConfigForFile(filePath);
+ }
+ /**
+ * Checks if a given path is ignored by ESLint.
+ * @param {string} filePath The path of the file to check.
+ * @returns {Promise<boolean>} Whether or not the given path is ignored.
+ */
- for (const override of config.overrides || []) {
- this.validateRules(override.rules, source, getAdditionalRule);
- this.validateEnvironment(override.env, source, getAdditionalEnv);
- this.validateGlobals(config.globals, source);
- }
+
+ async isPathIgnored(filePath) {
+ if (!isNonEmptyString(filePath)) {
+ throw new Error("'filePath' must be a non-empty string");
}
- /**
- * Validate config array object.
- * @param {ConfigArray} configArray The config array to validate.
- * @returns {void}
- */
- validateConfigArray(configArray) {
- const getPluginEnv = Map.prototype.get.bind(configArray.pluginEnvironments);
- const getPluginProcessor = Map.prototype.get.bind(configArray.pluginProcessors);
- const getPluginRule = Map.prototype.get.bind(configArray.pluginRules);
+ const {
+ cliEngine
+ } = privateMembersMap.get(this);
+ return cliEngine.isPathIgnored(filePath);
+ }
- // Validate.
- for (const element of configArray) {
- if (validated.has(element)) {
- continue;
- }
- validated.add(element);
+} //------------------------------------------------------------------------------
+// Public Interface
+//------------------------------------------------------------------------------
- this.validateEnvironment(element.env, element.name, getPluginEnv);
- this.validateGlobals(element.globals, element.name);
- this.validateProcessor(element.processor, element.name, getPluginProcessor);
- this.validateRules(element.rules, element.name, getPluginRule);
- }
- }
-}
+module.exports = {
+ ESLint,
-/**
- * @fileoverview Common helpers for naming of plugins, formatters and configs
- */
+ /**
+ * Get the private class members of a given ESLint instance for tests.
+ * @param {ESLint} instance The ESLint instance to get.
+ * @returns {ESLintPrivateMembers} The instance's private class members.
+ */
+ getESLintPrivateMembers(instance) {
+ return privateMembersMap.get(instance);
+ }
-const NAMESPACE_REGEX = /^@.*\//iu;
+};
+
+/***/ }),
+/* 880 */
+/***/ ((module) => {
+
+"use strict";
+module.exports = require("fs");
+
+/***/ }),
+/* 881 */
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+"use strict";
+/* provided dependency */ var process = __webpack_require__(494);
/**
- * Brings package name to correct format based on prefix
- * @param {string} name The name of the package.
- * @param {string} prefix Can be either "eslint-plugin", "eslint-config" or "eslint-formatter"
- * @returns {string} Normalized name of the package
- * @private
+ * @fileoverview Main CLI object.
+ * @author Nicholas C. Zakas
*/
-function normalizePackageName(name, prefix) {
- let normalizedName = name;
- /**
- * On Windows, name can come in with Windows slashes instead of Unix slashes.
- * Normalize to Unix first to avoid errors later on.
- * https://github.com/eslint/eslint/issues/5644
- */
- if (normalizedName.includes("\\")) {
- normalizedName = normalizedName.replace(/\\/gu, "/");
- }
+/*
+ * The CLI object should *not* call process.exit() directly. It should only return
+ * exit codes. This allows other programs to use the CLI object and still control
+ * when the program exits.
+ */
+//------------------------------------------------------------------------------
+// Requirements
+//------------------------------------------------------------------------------
- if (normalizedName.charAt(0) === "@") {
+const fs = __webpack_require__(880);
- /**
- * it's a scoped package
- * package name is the prefix, or just a username
- */
- const scopedPackageShortcutRegex = new RegExp(`^(@[^/]+)(?:/(?:${prefix})?)?$`, "u"),
- scopedPackageNameRegex = new RegExp(`^${prefix}(-|$)`, "u");
+const path = __webpack_require__(429);
- if (scopedPackageShortcutRegex.test(normalizedName)) {
- normalizedName = normalizedName.replace(scopedPackageShortcutRegex, `$1/${prefix}`);
- } else if (!scopedPackageNameRegex.test(normalizedName.split("/")[1])) {
+const defaultOptions = __webpack_require__(882);
- /**
- * for scoped packages, insert the prefix after the first / unless
- * the path is already @scope/eslint or @scope/eslint-xxx-yyy
- */
- normalizedName = normalizedName.replace(/^@([^/]+)\/(.*)$/u, `@$1/${prefix}-$2`);
- }
- } else if (!normalizedName.startsWith(`${prefix}-`)) {
- normalizedName = `${prefix}-${normalizedName}`;
- }
+const pkg = __webpack_require__(443);
- return normalizedName;
-}
+const {
+ Legacy: {
+ ConfigOps,
+ naming,
+ CascadingConfigArrayFactory,
+ IgnorePattern,
+ getUsedExtractedConfigs,
+ ModuleResolver
+ }
+} = __webpack_require__(883);
-/**
- * Removes the prefix from a fullname.
- * @param {string} fullname The term which may have the prefix.
- * @param {string} prefix The prefix to remove.
- * @returns {string} The term without prefix.
- */
-function getShorthandName(fullname, prefix) {
- if (fullname[0] === "@") {
- let matchResult = new RegExp(`^(@[^/]+)/${prefix}$`, "u").exec(fullname);
+const {
+ FileEnumerator
+} = __webpack_require__(893);
- if (matchResult) {
- return matchResult[1];
- }
+const {
+ Linter
+} = __webpack_require__(897);
- matchResult = new RegExp(`^(@[^/]+)/${prefix}-(.+)$`, "u").exec(fullname);
- if (matchResult) {
- return `${matchResult[1]}/${matchResult[2]}`;
- }
- } else if (fullname.startsWith(`${prefix}-`)) {
- return fullname.slice(prefix.length + 1);
- }
+const builtInRules = __webpack_require__(545);
- return fullname;
-}
+const loadRules = __webpack_require__(898);
+
+const hash = __webpack_require__(900);
+
+const LintResultCache = __webpack_require__(902);
+
+const debug = __webpack_require__(496)("eslint:cli-engine");
+
+const validFixTypes = new Set(["directive", "problem", "suggestion", "layout"]); //------------------------------------------------------------------------------
+// Typedefs
+//------------------------------------------------------------------------------
+// For VSCode IntelliSense
+
+/** @typedef {import("../shared/types").ConfigData} ConfigData */
+
+/** @typedef {import("../shared/types").DeprecatedRuleInfo} DeprecatedRuleInfo */
+
+/** @typedef {import("../shared/types").LintMessage} LintMessage */
+
+/** @typedef {import("../shared/types").ParserOptions} ParserOptions */
+
+/** @typedef {import("../shared/types").Plugin} Plugin */
+
+/** @typedef {import("../shared/types").RuleConf} RuleConf */
+
+/** @typedef {import("../shared/types").Rule} Rule */
+
+/** @typedef {ReturnType<CascadingConfigArrayFactory.getConfigArrayForFile>} ConfigArray */
+
+/** @typedef {ReturnType<ConfigArray.extractConfig>} ExtractedConfig */
/**
- * Gets the scope (namespace) of a term.
- * @param {string} term The term which may have the namespace.
- * @returns {string} The namespace of the term if it has one.
+ * The options to configure a CLI engine with.
+ * @typedef {Object} CLIEngineOptions
+ * @property {boolean} [allowInlineConfig] Enable or disable inline configuration comments.
+ * @property {ConfigData} [baseConfig] Base config object, extended by all configs used with this CLIEngine instance
+ * @property {boolean} [cache] Enable result caching.
+ * @property {string} [cacheLocation] The cache file to use instead of .eslintcache.
+ * @property {string} [configFile] The configuration file to use.
+ * @property {string} [cwd] The value to use for the current working directory.
+ * @property {string[]} [envs] An array of environments to load.
+ * @property {string[]|null} [extensions] An array of file extensions to check.
+ * @property {boolean|Function} [fix] Execute in autofix mode. If a function, should return a boolean.
+ * @property {string[]} [fixTypes] Array of rule types to apply fixes for.
+ * @property {string[]} [globals] An array of global variables to declare.
+ * @property {boolean} [ignore] False disables use of .eslintignore.
+ * @property {string} [ignorePath] The ignore file to use instead of .eslintignore.
+ * @property {string|string[]} [ignorePattern] One or more glob patterns to ignore.
+ * @property {boolean} [useEslintrc] False disables looking for .eslintrc
+ * @property {string} [parser] The name of the parser to use.
+ * @property {ParserOptions} [parserOptions] An object of parserOption settings to use.
+ * @property {string[]} [plugins] An array of plugins to load.
+ * @property {Record<string,RuleConf>} [rules] An object of rules to use.
+ * @property {string[]} [rulePaths] An array of directories to load custom rules from.
+ * @property {boolean} [reportUnusedDisableDirectives] `true` adds reports for unused eslint-disable directives
+ * @property {boolean} [globInputPaths] Set to false to skip glob resolution of input file paths to lint (default: true). If false, each input file paths is assumed to be a non-glob path to an existing file.
+ * @property {string} [resolvePluginsRelativeTo] The folder where plugins should be resolved from, defaulting to the CWD
*/
-function getNamespaceFromTerm(term) {
- const match = term.match(NAMESPACE_REGEX);
- return match ? match[0] : "";
-}
+/**
+ * A linting result.
+ * @typedef {Object} LintResult
+ * @property {string} filePath The path to the file that was linted.
+ * @property {LintMessage[]} messages All of the messages for the result.
+ * @property {number} errorCount Number of errors for the result.
+ * @property {number} warningCount Number of warnings for the result.
+ * @property {number} fixableErrorCount Number of fixable errors for the result.
+ * @property {number} fixableWarningCount Number of fixable warnings for the result.
+ * @property {string} [source] The source code of the file that was linted.
+ * @property {string} [output] The source code of the file that was linted, with as many fixes applied as possible.
+ */
-var naming = {
- __proto__: null,
- normalizePackageName: normalizePackageName,
- getShorthandName: getShorthandName,
- getNamespaceFromTerm: getNamespaceFromTerm
-};
+/**
+ * Linting results.
+ * @typedef {Object} LintReport
+ * @property {LintResult[]} results All of the result.
+ * @property {number} errorCount Number of errors for the result.
+ * @property {number} warningCount Number of warnings for the result.
+ * @property {number} fixableErrorCount Number of fixable errors for the result.
+ * @property {number} fixableWarningCount Number of fixable warnings for the result.
+ * @property {DeprecatedRuleInfo[]} usedDeprecatedRules The list of used deprecated rules.
+ */
/**
- * Utility for resolving a module relative to another module
- * @author Teddy Katz
+ * Private data for CLIEngine.
+ * @typedef {Object} CLIEngineInternalSlots
+ * @property {Map<string, Plugin>} additionalPluginPool The map for additional plugins.
+ * @property {string} cacheFilePath The path to the cache of lint results.
+ * @property {CascadingConfigArrayFactory} configArrayFactory The factory of configs.
+ * @property {(filePath: string) => boolean} defaultIgnores The default predicate function to check if a file ignored or not.
+ * @property {FileEnumerator} fileEnumerator The file enumerator.
+ * @property {ConfigArray[]} lastConfigArrays The list of config arrays that the last `executeOnFiles` or `executeOnText` used.
+ * @property {LintResultCache|null} lintResultCache The cache of lint results.
+ * @property {Linter} linter The linter instance which has loaded rules.
+ * @property {CLIEngineOptions} options The normalized options of this instance.
*/
+//------------------------------------------------------------------------------
+// Helpers
+//------------------------------------------------------------------------------
-/*
- * `Module.createRequire` is added in v12.2.0. It supports URL as well.
- * We only support the case where the argument is a filepath, not a URL.
+/** @type {WeakMap<CLIEngine, CLIEngineInternalSlots>} */
+
+const internalSlotsMap = new WeakMap();
+/**
+ * Determines if each fix type in an array is supported by ESLint and throws
+ * an error if not.
+ * @param {string[]} fixTypes An array of fix types to check.
+ * @returns {void}
+ * @throws {Error} If an invalid fix type is found.
*/
-const createRequire = Module__default["default"].createRequire;
+function validateFixTypes(fixTypes) {
+ for (const fixType of fixTypes) {
+ if (!validFixTypes.has(fixType)) {
+ throw new Error("Invalid fix type \"".concat(fixType, "\" found."));
+ }
+ }
+}
/**
- * Resolves a Node module relative to another module
- * @param {string} moduleName The name of a Node module, or a path to a Node module.
- * @param {string} relativeToPath An absolute path indicating the module that `moduleName` should be resolved relative to. This must be
- * a file rather than a directory, but the file need not actually exist.
- * @returns {string} The absolute path that would result from calling `require.resolve(moduleName)` in a file located at `relativeToPath`
+ * It will calculate the error and warning count for collection of messages per file
+ * @param {LintMessage[]} messages Collection of messages
+ * @returns {Object} Contains the stats
+ * @private
*/
-function resolve(moduleName, relativeToPath) {
- try {
- return createRequire(relativeToPath).resolve(moduleName);
- } catch (error) {
- // This `if` block is for older Node.js than 12.0.0. We can remove this block in the future.
- if (
- typeof error === "object" &&
- error !== null &&
- error.code === "MODULE_NOT_FOUND" &&
- !error.requireStack &&
- error.message.includes(moduleName)
- ) {
- error.message += `\nRequire stack:\n- ${relativeToPath}`;
- }
- throw error;
+
+function calculateStatsPerFile(messages) {
+ return messages.reduce((stat, message) => {
+ if (message.fatal || message.severity === 2) {
+ stat.errorCount++;
+
+ if (message.fatal) {
+ stat.fatalErrorCount++;
+ }
+
+ if (message.fix) {
+ stat.fixableErrorCount++;
+ }
+ } else {
+ stat.warningCount++;
+
+ if (message.fix) {
+ stat.fixableWarningCount++;
+ }
}
+
+ return stat;
+ }, {
+ errorCount: 0,
+ fatalErrorCount: 0,
+ warningCount: 0,
+ fixableErrorCount: 0,
+ fixableWarningCount: 0
+ });
}
+/**
+ * It will calculate the error and warning count for collection of results from all files
+ * @param {LintResult[]} results Collection of messages from all the files
+ * @returns {Object} Contains the stats
+ * @private
+ */
-var ModuleResolver = {
- __proto__: null,
- resolve: resolve
-};
+function calculateStatsPerRun(results) {
+ return results.reduce((stat, result) => {
+ stat.errorCount += result.errorCount;
+ stat.fatalErrorCount += result.fatalErrorCount;
+ stat.warningCount += result.warningCount;
+ stat.fixableErrorCount += result.fixableErrorCount;
+ stat.fixableWarningCount += result.fixableWarningCount;
+ return stat;
+ }, {
+ errorCount: 0,
+ fatalErrorCount: 0,
+ warningCount: 0,
+ fixableErrorCount: 0,
+ fixableWarningCount: 0
+ });
+}
/**
- * @fileoverview `IgnorePattern` class.
- *
- * `IgnorePattern` class has the set of glob patterns and the base path.
- *
- * It provides two static methods.
- *
- * - `IgnorePattern.createDefaultIgnore(cwd)`
- * Create the default predicate function.
- * - `IgnorePattern.createIgnore(ignorePatterns)`
- * Create the predicate function from multiple `IgnorePattern` objects.
- *
- * It provides two properties and a method.
- *
- * - `patterns`
- * The glob patterns that ignore to lint.
- * - `basePath`
- * The base path of the glob patterns. If absolute paths existed in the
- * glob patterns, those are handled as relative paths to the base path.
- * - `getPatternsRelativeTo(basePath)`
- * Get `patterns` as modified for a given base path. It modifies the
- * absolute paths in the patterns as prepending the difference of two base
- * paths.
- *
- * `ConfigArrayFactory` creates `IgnorePattern` objects when it processes
- * `ignorePatterns` properties.
- *
- * @author Toru Nagashima <https://github.com/mysticatea>
+ * Processes an source code using ESLint.
+ * @param {Object} config The config object.
+ * @param {string} config.text The source code to verify.
+ * @param {string} config.cwd The path to the current working directory.
+ * @param {string|undefined} config.filePath The path to the file of `text`. If this is undefined, it uses `<text>`.
+ * @param {ConfigArray} config.config The config.
+ * @param {boolean} config.fix If `true` then it does fix.
+ * @param {boolean} config.allowInlineConfig If `true` then it uses directive comments.
+ * @param {boolean} config.reportUnusedDisableDirectives If `true` then it reports unused `eslint-disable` comments.
+ * @param {FileEnumerator} config.fileEnumerator The file enumerator to check if a path is a target or not.
+ * @param {Linter} config.linter The linter instance to verify.
+ * @returns {LintResult} The result of linting.
+ * @private
*/
-const debug$3 = debugOrig__default["default"]("eslintrc:ignore-pattern");
-/** @typedef {ReturnType<import("ignore").default>} Ignore */
+function verifyText(_ref) {
+ let {
+ text,
+ cwd,
+ filePath: providedFilePath,
+ config,
+ fix,
+ allowInlineConfig,
+ reportUnusedDisableDirectives,
+ fileEnumerator,
+ linter
+ } = _ref;
+ const filePath = providedFilePath || "<text>";
+ debug("Lint ".concat(filePath));
+ /*
+ * Verify.
+ * `config.extractConfig(filePath)` requires an absolute path, but `linter`
+ * doesn't know CWD, so it gives `linter` an absolute path always.
+ */
-//------------------------------------------------------------------------------
-// Helpers
-//------------------------------------------------------------------------------
+ const filePathToVerify = filePath === "<text>" ? path.join(cwd, filePath) : filePath;
+ const {
+ fixed,
+ messages,
+ output
+ } = linter.verifyAndFix(text, config, {
+ allowInlineConfig,
+ filename: filePathToVerify,
+ fix,
+ reportUnusedDisableDirectives,
-/**
- * Get the path to the common ancestor directory of given paths.
- * @param {string[]} sourcePaths The paths to calculate the common ancestor.
- * @returns {string} The path to the common ancestor directory.
- */
-function getCommonAncestorPath(sourcePaths) {
- let result = sourcePaths[0];
+ /**
+ * Check if the linter should adopt a given code block or not.
+ * @param {string} blockFilename The virtual filename of a code block.
+ * @returns {boolean} `true` if the linter should adopt the code block.
+ */
+ filterCodeBlock(blockFilename) {
+ return fileEnumerator.isTargetPath(blockFilename);
+ }
- for (let i = 1; i < sourcePaths.length; ++i) {
- const a = result;
- const b = sourcePaths[i];
+ }); // Tweak and return.
- // Set the shorter one (it's the common ancestor if one includes the other).
- result = a.length < b.length ? a : b;
+ const result = {
+ filePath,
+ messages,
+ ...calculateStatsPerFile(messages)
+ };
- // Set the common ancestor.
- for (let j = 0, lastSepPos = 0; j < a.length && j < b.length; ++j) {
- if (a[j] !== b[j]) {
- result = a.slice(0, lastSepPos);
- break;
- }
- if (a[j] === path__default["default"].sep) {
- lastSepPos = j;
- }
- }
- }
+ if (fixed) {
+ result.output = output;
+ }
- let resolvedResult = result || path__default["default"].sep;
+ if (result.errorCount + result.warningCount > 0 && typeof result.output === "undefined") {
+ result.source = text;
+ }
- // if Windows common ancestor is root of drive must have trailing slash to be absolute.
- if (resolvedResult && resolvedResult.endsWith(":") && process.platform === "win32") {
- resolvedResult += path__default["default"].sep;
- }
- return resolvedResult;
+ return result;
}
-
/**
- * Make relative path.
- * @param {string} from The source path to get relative path.
- * @param {string} to The destination path to get relative path.
- * @returns {string} The relative path.
+ * Returns result with warning by ignore settings
+ * @param {string} filePath File path of checked code
+ * @param {string} baseDir Absolute path of base directory
+ * @returns {LintResult} Result with single warning
+ * @private
*/
-function relative(from, to) {
- const relPath = path__default["default"].relative(from, to);
- if (path__default["default"].sep === "/") {
- return relPath;
- }
- return relPath.split(path__default["default"].sep).join("/");
-}
-/**
- * Get the trailing slash if existed.
- * @param {string} filePath The path to check.
- * @returns {string} The trailing slash if existed.
- */
-function dirSuffix(filePath) {
- const isDir = (
- filePath.endsWith(path__default["default"].sep) ||
- (process.platform === "win32" && filePath.endsWith("/"))
- );
+function createIgnoreResult(filePath, baseDir) {
+ let message;
+ const isHidden = filePath.split(path.sep).find(segment => /^\./u.test(segment));
+ const isInNodeModules = baseDir && path.relative(baseDir, filePath).startsWith("node_modules");
- return isDir ? "/" : "";
-}
+ if (isHidden) {
+ message = "File ignored by default. Use a negated ignore pattern (like \"--ignore-pattern '!<relative/path/to/filename>'\") to override.";
+ } else if (isInNodeModules) {
+ message = "File ignored by default. Use \"--ignore-pattern '!node_modules/*'\" to override.";
+ } else {
+ message = "File ignored because of a matching ignore pattern. Use \"--no-ignore\" to override.";
+ }
-const DefaultPatterns = Object.freeze(["/**/node_modules/*"]);
-const DotPatterns = Object.freeze([".*", "!.eslintrc.*", "!../"]);
+ return {
+ filePath: path.resolve(filePath),
+ messages: [{
+ fatal: false,
+ severity: 1,
+ message
+ }],
+ errorCount: 0,
+ warningCount: 1,
+ fixableErrorCount: 0,
+ fixableWarningCount: 0
+ };
+}
+/**
+ * Get a rule.
+ * @param {string} ruleId The rule ID to get.
+ * @param {ConfigArray[]} configArrays The config arrays that have plugin rules.
+ * @returns {Rule|null} The rule or null.
+ */
-//------------------------------------------------------------------------------
-// Public
-//------------------------------------------------------------------------------
-class IgnorePattern {
+function getRule(ruleId, configArrays) {
+ for (const configArray of configArrays) {
+ const rule = configArray.pluginRules.get(ruleId);
- /**
- * The default patterns.
- * @type {string[]}
- */
- static get DefaultPatterns() {
- return DefaultPatterns;
+ if (rule) {
+ return rule;
}
+ }
- /**
- * Create the default predicate function.
- * @param {string} cwd The current working directory.
- * @returns {((filePath:string, dot:boolean) => boolean) & {basePath:string; patterns:string[]}}
- * The preficate function.
- * The first argument is an absolute path that is checked.
- * The second argument is the flag to not ignore dotfiles.
- * If the predicate function returned `true`, it means the path should be ignored.
- */
- static createDefaultIgnore(cwd) {
- return this.createIgnore([new IgnorePattern(DefaultPatterns, cwd)]);
- }
+ return builtInRules.get(ruleId) || null;
+}
+/**
+ * Checks whether a message's rule type should be fixed.
+ * @param {LintMessage} message The message to check.
+ * @param {ConfigArray[]} lastConfigArrays The list of config arrays that the last `executeOnFiles` or `executeOnText` used.
+ * @param {string[]} fixTypes An array of fix types to check.
+ * @returns {boolean} Whether the message should be fixed.
+ */
- /**
- * Create the predicate function from multiple `IgnorePattern` objects.
- * @param {IgnorePattern[]} ignorePatterns The list of ignore patterns.
- * @returns {((filePath:string, dot?:boolean) => boolean) & {basePath:string; patterns:string[]}}
- * The preficate function.
- * The first argument is an absolute path that is checked.
- * The second argument is the flag to not ignore dotfiles.
- * If the predicate function returned `true`, it means the path should be ignored.
- */
- static createIgnore(ignorePatterns) {
- debug$3("Create with: %o", ignorePatterns);
- const basePath = getCommonAncestorPath(ignorePatterns.map(p => p.basePath));
- const patterns = [].concat(
- ...ignorePatterns.map(p => p.getPatternsRelativeTo(basePath))
- );
- const ig = ignore__default["default"]().add([...DotPatterns, ...patterns]);
- const dotIg = ignore__default["default"]().add(patterns);
+function shouldMessageBeFixed(message, lastConfigArrays, fixTypes) {
+ if (!message.ruleId) {
+ return fixTypes.has("directive");
+ }
- debug$3(" processed: %o", { basePath, patterns });
+ const rule = message.ruleId && getRule(message.ruleId, lastConfigArrays);
+ return Boolean(rule && rule.meta && fixTypes.has(rule.meta.type));
+}
+/**
+ * Collect used deprecated rules.
+ * @param {ConfigArray[]} usedConfigArrays The config arrays which were used.
+ * @returns {IterableIterator<DeprecatedRuleInfo>} Used deprecated rules.
+ */
- return Object.assign(
- (filePath, dot = false) => {
- assert__default["default"](path__default["default"].isAbsolute(filePath), "'filePath' should be an absolute path.");
- const relPathRaw = relative(basePath, filePath);
- const relPath = relPathRaw && (relPathRaw + dirSuffix(filePath));
- const adoptedIg = dot ? dotIg : ig;
- const result = relPath !== "" && adoptedIg.ignores(relPath);
- debug$3("Check", { filePath, dot, relativePath: relPath, result });
- return result;
- },
- { basePath, patterns }
- );
- }
+function* iterateRuleDeprecationWarnings(usedConfigArrays) {
+ const processedRuleIds = new Set(); // Flatten used configs.
- /**
- * Initialize a new `IgnorePattern` instance.
- * @param {string[]} patterns The glob patterns that ignore to lint.
- * @param {string} basePath The base path of `patterns`.
- */
- constructor(patterns, basePath) {
- assert__default["default"](path__default["default"].isAbsolute(basePath), "'basePath' should be an absolute path.");
+ /** @type {ExtractedConfig[]} */
- /**
- * The glob patterns that ignore to lint.
- * @type {string[]}
- */
- this.patterns = patterns;
+ const configs = [].concat(...usedConfigArrays.map(getUsedExtractedConfigs)); // Traverse rule configs.
- /**
- * The base path of `patterns`.
- * @type {string}
- */
- this.basePath = basePath;
+ for (const config of configs) {
+ for (const [ruleId, ruleConfig] of Object.entries(config.rules)) {
+ // Skip if it was processed.
+ if (processedRuleIds.has(ruleId)) {
+ continue;
+ }
- /**
- * If `true` then patterns which don't start with `/` will match the paths to the outside of `basePath`. Defaults to `false`.
- *
- * It's set `true` for `.eslintignore`, `package.json`, and `--ignore-path` for backward compatibility.
- * It's `false` as-is for `ignorePatterns` property in config files.
- * @type {boolean}
- */
- this.loose = false;
- }
+ processedRuleIds.add(ruleId); // Skip if it's not used.
- /**
- * Get `patterns` as modified for a given base path. It modifies the
- * absolute paths in the patterns as prepending the difference of two base
- * paths.
- * @param {string} newBasePath The base path.
- * @returns {string[]} Modifired patterns.
- */
- getPatternsRelativeTo(newBasePath) {
- assert__default["default"](path__default["default"].isAbsolute(newBasePath), "'newBasePath' should be an absolute path.");
- const { basePath, loose, patterns } = this;
+ if (!ConfigOps.getRuleSeverity(ruleConfig)) {
+ continue;
+ }
- if (newBasePath === basePath) {
- return patterns;
- }
- const prefix = `/${relative(newBasePath, basePath)}`;
+ const rule = getRule(ruleId, usedConfigArrays); // Skip if it's not deprecated.
- return patterns.map(pattern => {
- const negative = pattern.startsWith("!");
- const head = negative ? "!" : "";
- const body = negative ? pattern.slice(1) : pattern;
+ if (!(rule && rule.meta && rule.meta.deprecated)) {
+ continue;
+ } // This rule was used and deprecated.
- if (body.startsWith("/") || body.startsWith("../")) {
- return `${head}${prefix}${body}`;
- }
- return loose ? pattern : `${head}${prefix}/**/${body}`;
- });
+
+ yield {
+ ruleId,
+ replacedBy: rule.meta.replacedBy || []
+ };
}
+ }
}
-
/**
- * @fileoverview `ExtractedConfig` class.
- *
- * `ExtractedConfig` class expresses a final configuration for a specific file.
- *
- * It provides one method.
- *
- * - `toCompatibleObjectAsConfigFileContent()`
- * Convert this configuration to the compatible object as the content of
- * config files. It converts the loaded parser and plugins to strings.
- * `CLIEngine#getConfigForFile(filePath)` method uses this method.
- *
- * `ConfigArray#extractConfig(filePath)` creates a `ExtractedConfig` instance.
- *
- * @author Toru Nagashima <https://github.com/mysticatea>
+ * Checks if the given message is an error message.
+ * @param {LintMessage} message The message to check.
+ * @returns {boolean} Whether or not the message is an error message.
+ * @private
*/
-// For VSCode intellisense
-/** @typedef {import("../../shared/types").ConfigData} ConfigData */
-/** @typedef {import("../../shared/types").GlobalConf} GlobalConf */
-/** @typedef {import("../../shared/types").SeverityConf} SeverityConf */
-/** @typedef {import("./config-dependency").DependentParser} DependentParser */
-/** @typedef {import("./config-dependency").DependentPlugin} DependentPlugin */
-/**
- * Check if `xs` starts with `ys`.
- * @template T
- * @param {T[]} xs The array to check.
- * @param {T[]} ys The array that may be the first part of `xs`.
- * @returns {boolean} `true` if `xs` starts with `ys`.
- */
-function startsWith(xs, ys) {
- return xs.length >= ys.length && ys.every((y, i) => y === xs[i]);
+function isErrorMessage(message) {
+ return message.severity === 2;
}
-
/**
- * The class for extracted config data.
+ * return the cacheFile to be used by eslint, based on whether the provided parameter is
+ * a directory or looks like a directory (ends in `path.sep`), in which case the file
+ * name will be the `cacheFile/.cache_hashOfCWD`
+ *
+ * if cacheFile points to a file or looks like a file then in will just use that file
+ * @param {string} cacheFile The name of file to be used to store the cache
+ * @param {string} cwd Current working directory
+ * @returns {string} the resolved path to the cache file
*/
-class ExtractedConfig {
- constructor() {
-
- /**
- * The config name what `noInlineConfig` setting came from.
- * @type {string}
- */
- this.configNameOfNoInlineConfig = "";
-
- /**
- * Environments.
- * @type {Record<string, boolean>}
- */
- this.env = {};
-
- /**
- * Global variables.
- * @type {Record<string, GlobalConf>}
- */
- this.globals = {};
-
- /**
- * The glob patterns that ignore to lint.
- * @type {(((filePath:string, dot?:boolean) => boolean) & { basePath:string; patterns:string[] }) | undefined}
- */
- this.ignores = void 0;
-
- /**
- * The flag that disables directive comments.
- * @type {boolean|undefined}
- */
- this.noInlineConfig = void 0;
-
- /**
- * Parser definition.
- * @type {DependentParser|null}
- */
- this.parser = null;
- /**
- * Options for the parser.
- * @type {Object}
- */
- this.parserOptions = {};
- /**
- * Plugin definitions.
- * @type {Record<string, DependentPlugin>}
- */
- this.plugins = {};
+function getCacheFile(cacheFile, cwd) {
+ /*
+ * make sure the path separators are normalized for the environment/os
+ * keeping the trailing path separator if present
+ */
+ const normalizedCacheFile = path.normalize(cacheFile);
+ const resolvedCacheFile = path.resolve(cwd, normalizedCacheFile);
+ const looksLikeADirectory = normalizedCacheFile.slice(-1) === path.sep;
+ /**
+ * return the name for the cache file in case the provided parameter is a directory
+ * @returns {string} the resolved path to the cacheFile
+ */
- /**
- * Processor ID.
- * @type {string|null}
- */
- this.processor = null;
+ function getCacheFileForDirectory() {
+ return path.join(resolvedCacheFile, ".cache_".concat(hash(cwd)));
+ }
- /**
- * The flag that reports unused `eslint-disable` directive comments.
- * @type {boolean|undefined}
- */
- this.reportUnusedDisableDirectives = void 0;
+ let fileStats;
- /**
- * Rule settings.
- * @type {Record<string, [SeverityConf, ...any[]]>}
- */
- this.rules = {};
+ try {
+ fileStats = fs.lstatSync(resolvedCacheFile);
+ } catch {
+ fileStats = null;
+ }
+ /*
+ * in case the file exists we need to verify if the provided path
+ * is a directory or a file. If it is a directory we want to create a file
+ * inside that directory
+ */
- /**
- * Shared settings.
- * @type {Object}
- */
- this.settings = {};
- }
- /**
- * Convert this config to the compatible object as a config file content.
- * @returns {ConfigData} The converted object.
+ if (fileStats) {
+ /*
+ * is a directory or is a file, but the original file the user provided
+ * looks like a directory but `path.resolve` removed the `last path.sep`
+ * so we need to still treat this like a directory
*/
- toCompatibleObjectAsConfigFileContent() {
- const {
- /* eslint-disable no-unused-vars */
- configNameOfNoInlineConfig: _ignore1,
- processor: _ignore2,
- /* eslint-enable no-unused-vars */
- ignores,
- ...config
- } = this;
-
- config.parser = config.parser && config.parser.filePath;
- config.plugins = Object.keys(config.plugins).filter(Boolean).reverse();
- config.ignorePatterns = ignores ? ignores.patterns : [];
-
- // Strip the default patterns from `ignorePatterns`.
- if (startsWith(config.ignorePatterns, IgnorePattern.DefaultPatterns)) {
- config.ignorePatterns =
- config.ignorePatterns.slice(IgnorePattern.DefaultPatterns.length);
- }
+ if (fileStats.isDirectory() || looksLikeADirectory) {
+ return getCacheFileForDirectory();
+ } // is file so just use that file
- return config;
- }
-}
-/**
- * @fileoverview `ConfigArray` class.
- *
- * `ConfigArray` class expresses the full of a configuration. It has the entry
- * config file, base config files that were extended, loaded parsers, and loaded
- * plugins.
- *
- * `ConfigArray` class provides three properties and two methods.
- *
- * - `pluginEnvironments`
- * - `pluginProcessors`
- * - `pluginRules`
- * The `Map` objects that contain the members of all plugins that this
- * config array contains. Those map objects don't have mutation methods.
- * Those keys are the member ID such as `pluginId/memberName`.
- * - `isRoot()`
- * If `true` then this configuration has `root:true` property.
- * - `extractConfig(filePath)`
- * Extract the final configuration for a given file. This means merging
- * every config array element which that `criteria` property matched. The
- * `filePath` argument must be an absolute path.
- *
- * `ConfigArrayFactory` provides the loading logic of config files.
- *
- * @author Toru Nagashima <https://github.com/mysticatea>
- */
+ return resolvedCacheFile;
+ }
+ /*
+ * here we known the file or directory doesn't exist,
+ * so we will try to infer if its a directory if it looks like a directory
+ * for the current operating system.
+ */
+ // if the last character passed is a path separator we assume is a directory
-//------------------------------------------------------------------------------
-// Helpers
-//------------------------------------------------------------------------------
-// Define types for VSCode IntelliSense.
-/** @typedef {import("../../shared/types").Environment} Environment */
-/** @typedef {import("../../shared/types").GlobalConf} GlobalConf */
-/** @typedef {import("../../shared/types").RuleConf} RuleConf */
-/** @typedef {import("../../shared/types").Rule} Rule */
-/** @typedef {import("../../shared/types").Plugin} Plugin */
-/** @typedef {import("../../shared/types").Processor} Processor */
-/** @typedef {import("./config-dependency").DependentParser} DependentParser */
-/** @typedef {import("./config-dependency").DependentPlugin} DependentPlugin */
-/** @typedef {import("./override-tester")["OverrideTester"]} OverrideTester */
+ if (looksLikeADirectory) {
+ return getCacheFileForDirectory();
+ }
+ return resolvedCacheFile;
+}
/**
- * @typedef {Object} ConfigArrayElement
- * @property {string} name The name of this config element.
- * @property {string} filePath The path to the source file of this config element.
- * @property {InstanceType<OverrideTester>|null} criteria The tester for the `files` and `excludedFiles` of this config element.
- * @property {Record<string, boolean>|undefined} env The environment settings.
- * @property {Record<string, GlobalConf>|undefined} globals The global variable settings.
- * @property {IgnorePattern|undefined} ignorePattern The ignore patterns.
- * @property {boolean|undefined} noInlineConfig The flag that disables directive comments.
- * @property {DependentParser|undefined} parser The parser loader.
- * @property {Object|undefined} parserOptions The parser options.
- * @property {Record<string, DependentPlugin>|undefined} plugins The plugin loaders.
- * @property {string|undefined} processor The processor name to refer plugin's processor.
- * @property {boolean|undefined} reportUnusedDisableDirectives The flag to report unused `eslint-disable` comments.
- * @property {boolean|undefined} root The flag to express root.
- * @property {Record<string, RuleConf>|undefined} rules The rule settings
- * @property {Object|undefined} settings The shared settings.
- * @property {"config" | "ignore" | "implicit-processor"} type The element type.
+ * Convert a string array to a boolean map.
+ * @param {string[]|null} keys The keys to assign true.
+ * @param {boolean} defaultValue The default value for each property.
+ * @param {string} displayName The property name which is used in error message.
+ * @throws {Error} Requires array.
+ * @returns {Record<string,boolean>} The boolean map.
*/
-/**
- * @typedef {Object} ConfigArrayInternalSlots
- * @property {Map<string, ExtractedConfig>} cache The cache to extract configs.
- * @property {ReadonlyMap<string, Environment>|null} envMap The map from environment ID to environment definition.
- * @property {ReadonlyMap<string, Processor>|null} processorMap The map from processor ID to environment definition.
- * @property {ReadonlyMap<string, Rule>|null} ruleMap The map from rule ID to rule definition.
- */
-/** @type {WeakMap<ConfigArray, ConfigArrayInternalSlots>} */
-const internalSlotsMap$2 = new class extends WeakMap {
- get(key) {
- let value = super.get(key);
+function toBooleanMap(keys, defaultValue, displayName) {
+ if (keys && !Array.isArray(keys)) {
+ throw new Error("".concat(displayName, " must be an array."));
+ }
- if (!value) {
- value = {
- cache: new Map(),
- envMap: null,
- processorMap: null,
- ruleMap: null
- };
- super.set(key, value);
- }
+ if (keys && keys.length > 0) {
+ return keys.reduce((map, def) => {
+ const [key, value] = def.split(":");
- return value;
- }
-}();
+ if (key !== "__proto__") {
+ map[key] = value === void 0 ? defaultValue : value === "true";
+ }
+
+ return map;
+ }, {});
+ }
+ return void 0;
+}
/**
- * Get the indices which are matched to a given file.
- * @param {ConfigArrayElement[]} elements The elements.
- * @param {string} filePath The path to a target file.
- * @returns {number[]} The indices.
+ * Create a config data from CLI options.
+ * @param {CLIEngineOptions} options The options
+ * @returns {ConfigData|null} The created config data.
*/
-function getMatchedIndices(elements, filePath) {
- const indices = [];
- for (let i = elements.length - 1; i >= 0; --i) {
- const element = elements[i];
- if (!element.criteria || (filePath && element.criteria.test(filePath))) {
- indices.push(i);
- }
- }
+function createConfigDataFromOptions(options) {
+ const {
+ ignorePattern,
+ parser,
+ parserOptions,
+ plugins,
+ rules
+ } = options;
+ const env = toBooleanMap(options.envs, true, "envs");
+ const globals = toBooleanMap(options.globals, false, "globals");
- return indices;
-}
+ if (env === void 0 && globals === void 0 && (ignorePattern === void 0 || ignorePattern.length === 0) && parser === void 0 && parserOptions === void 0 && plugins === void 0 && rules === void 0) {
+ return null;
+ }
-/**
- * Check if a value is a non-null object.
- * @param {any} x The value to check.
- * @returns {boolean} `true` if the value is a non-null object.
- */
-function isNonNullObject(x) {
- return typeof x === "object" && x !== null;
+ return {
+ env,
+ globals,
+ ignorePatterns: ignorePattern,
+ parser,
+ parserOptions,
+ plugins,
+ rules
+ };
}
-
/**
- * Merge two objects.
- *
- * Assign every property values of `y` to `x` if `x` doesn't have the property.
- * If `x`'s property value is an object, it does recursive.
- * @param {Object} target The destination to merge
- * @param {Object|undefined} source The source to merge.
- * @returns {void}
+ * Checks whether a directory exists at the given location
+ * @param {string} resolvedPath A path from the CWD
+ * @throws {Error} As thrown by `fs.statSync` or `fs.isDirectory`.
+ * @returns {boolean} `true` if a directory exists
*/
-function mergeWithoutOverwrite(target, source) {
- if (!isNonNullObject(source)) {
- return;
- }
- for (const key of Object.keys(source)) {
- if (key === "__proto__") {
- continue;
- }
- if (isNonNullObject(target[key])) {
- mergeWithoutOverwrite(target[key], source[key]);
- } else if (target[key] === void 0) {
- if (isNonNullObject(source[key])) {
- target[key] = Array.isArray(source[key]) ? [] : {};
- mergeWithoutOverwrite(target[key], source[key]);
- } else if (source[key] !== void 0) {
- target[key] = source[key];
- }
- }
+function directoryExists(resolvedPath) {
+ try {
+ return fs.statSync(resolvedPath).isDirectory();
+ } catch (error) {
+ if (error && (error.code === "ENOENT" || error.code === "ENOTDIR")) {
+ return false;
}
-}
+
+ throw error;
+ }
+} //------------------------------------------------------------------------------
+// Public Interface
+//------------------------------------------------------------------------------
/**
- * The error for plugin conflicts.
+ * Core CLI.
*/
-class PluginConflictError extends Error {
- /**
- * Initialize this error object.
- * @param {string} pluginId The plugin ID.
- * @param {{filePath:string, importerName:string}[]} plugins The resolved plugins.
- */
- constructor(pluginId, plugins) {
- super(`Plugin "${pluginId}" was conflicted between ${plugins.map(p => `"${p.importerName}"`).join(" and ")}.`);
- this.messageTemplate = "plugin-conflict";
- this.messageData = { pluginId, plugins };
+
+class CLIEngine {
+ /**
+ * Creates a new instance of the core CLI engine.
+ * @param {CLIEngineOptions} providedOptions The options for this instance.
+ * @param {Object} [additionalData] Additional settings that are not CLIEngineOptions.
+ * @param {Record<string,Plugin>|null} [additionalData.preloadedPlugins] Preloaded plugins.
+ */
+ constructor(providedOptions) {
+ let {
+ preloadedPlugins
+ } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
+ const options = Object.assign(Object.create(null), defaultOptions, {
+ cwd: process.cwd()
+ }, providedOptions);
+
+ if (options.fix === void 0) {
+ options.fix = false;
}
-}
-/**
- * Merge plugins.
- * `target`'s definition is prior to `source`'s.
- * @param {Record<string, DependentPlugin>} target The destination to merge
- * @param {Record<string, DependentPlugin>|undefined} source The source to merge.
- * @returns {void}
- */
-function mergePlugins(target, source) {
- if (!isNonNullObject(source)) {
- return;
+ const additionalPluginPool = new Map();
+
+ if (preloadedPlugins) {
+ for (const [id, plugin] of Object.entries(preloadedPlugins)) {
+ additionalPluginPool.set(id, plugin);
+ }
}
- for (const key of Object.keys(source)) {
- if (key === "__proto__") {
- continue;
- }
- const targetValue = target[key];
- const sourceValue = source[key];
+ const cacheFilePath = getCacheFile(options.cacheLocation || options.cacheFile, options.cwd);
+ const configArrayFactory = new CascadingConfigArrayFactory({
+ additionalPluginPool,
+ baseConfig: options.baseConfig || null,
+ cliConfig: createConfigDataFromOptions(options),
+ cwd: options.cwd,
+ ignorePath: options.ignorePath,
+ resolvePluginsRelativeTo: options.resolvePluginsRelativeTo,
+ rulePaths: options.rulePaths,
+ specificConfigPath: options.configFile,
+ useEslintrc: options.useEslintrc,
+ builtInRules,
+ loadRules,
+ eslintRecommendedPath: path.resolve(__dirname, "../../conf/eslint-recommended.js"),
+ eslintAllPath: path.resolve(__dirname, "../../conf/eslint-all.js")
+ });
+ const fileEnumerator = new FileEnumerator({
+ configArrayFactory,
+ cwd: options.cwd,
+ extensions: options.extensions,
+ globInputPaths: options.globInputPaths,
+ errorOnUnmatchedPattern: options.errorOnUnmatchedPattern,
+ ignore: options.ignore
+ });
+ const lintResultCache = options.cache ? new LintResultCache(cacheFilePath, options.cacheStrategy) : null;
+ const linter = new Linter({
+ cwd: options.cwd
+ });
+ /** @type {ConfigArray[]} */
- // Adopt the plugin which was found at first.
- if (targetValue === void 0) {
- if (sourceValue.error) {
- throw sourceValue.error;
- }
- target[key] = sourceValue;
- } else if (sourceValue.filePath !== targetValue.filePath) {
- throw new PluginConflictError(key, [
- {
- filePath: targetValue.filePath,
- importerName: targetValue.importerName
- },
- {
- filePath: sourceValue.filePath,
- importerName: sourceValue.importerName
- }
- ]);
- }
+ const lastConfigArrays = [configArrayFactory.getConfigArrayForFile()]; // Store private data.
+
+ internalSlotsMap.set(this, {
+ additionalPluginPool,
+ cacheFilePath,
+ configArrayFactory,
+ defaultIgnores: IgnorePattern.createDefaultIgnore(options.cwd),
+ fileEnumerator,
+ lastConfigArrays,
+ lintResultCache,
+ linter,
+ options
+ }); // setup special filter for fixes
+
+ if (options.fix && options.fixTypes && options.fixTypes.length > 0) {
+ debug("Using fix types ".concat(options.fixTypes)); // throw an error if any invalid fix types are found
+
+ validateFixTypes(options.fixTypes); // convert to Set for faster lookup
+
+ const fixTypes = new Set(options.fixTypes); // save original value of options.fix in case it's a function
+
+ const originalFix = typeof options.fix === "function" ? options.fix : () => true;
+
+ options.fix = message => shouldMessageBeFixed(message, lastConfigArrays, fixTypes) && originalFix(message);
}
-}
+ }
-/**
- * Merge rule configs.
- * `target`'s definition is prior to `source`'s.
- * @param {Record<string, Array>} target The destination to merge
- * @param {Record<string, RuleConf>|undefined} source The source to merge.
- * @returns {void}
- */
-function mergeRuleConfigs(target, source) {
- if (!isNonNullObject(source)) {
- return;
+ getRules() {
+ const {
+ lastConfigArrays
+ } = internalSlotsMap.get(this);
+ return new Map(function* () {
+ yield* builtInRules;
+
+ for (const configArray of lastConfigArrays) {
+ yield* configArray.pluginRules;
+ }
+ }());
+ }
+ /**
+ * Returns results that only contains errors.
+ * @param {LintResult[]} results The results to filter.
+ * @returns {LintResult[]} The filtered results.
+ */
+
+
+ static getErrorResults(results) {
+ const filtered = [];
+ results.forEach(result => {
+ const filteredMessages = result.messages.filter(isErrorMessage);
+
+ if (filteredMessages.length > 0) {
+ filtered.push({ ...result,
+ messages: filteredMessages,
+ errorCount: filteredMessages.length,
+ warningCount: 0,
+ fixableErrorCount: result.fixableErrorCount,
+ fixableWarningCount: 0
+ });
+ }
+ });
+ return filtered;
+ }
+ /**
+ * Outputs fixes from the given results to files.
+ * @param {LintReport} report The report object created by CLIEngine.
+ * @returns {void}
+ */
+
+
+ static outputFixes(report) {
+ report.results.filter(result => Object.prototype.hasOwnProperty.call(result, "output")).forEach(result => {
+ fs.writeFileSync(result.filePath, result.output);
+ });
+ }
+ /**
+ * Resolves the patterns passed into executeOnFiles() into glob-based patterns
+ * for easier handling.
+ * @param {string[]} patterns The file patterns passed on the command line.
+ * @returns {string[]} The equivalent glob patterns.
+ */
+
+
+ resolveFileGlobPatterns(patterns) {
+ const {
+ options
+ } = internalSlotsMap.get(this);
+
+ if (options.globInputPaths === false) {
+ return patterns.filter(Boolean);
}
- for (const key of Object.keys(source)) {
- if (key === "__proto__") {
- continue;
- }
- const targetDef = target[key];
- const sourceDef = source[key];
+ const extensions = (options.extensions || [".js"]).map(ext => ext.replace(/^\./u, ""));
+ const dirSuffix = "/**/*.{".concat(extensions.join(","), "}");
+ return patterns.filter(Boolean).map(pathname => {
+ const resolvedPath = path.resolve(options.cwd, pathname);
+ const newPath = directoryExists(resolvedPath) ? pathname.replace(/[/\\]$/u, "") + dirSuffix : pathname;
+ return path.normalize(newPath).replace(/\\/gu, "/");
+ });
+ }
+ /**
+ * Executes the current configuration on an array of file and directory names.
+ * @param {string[]} patterns An array of file and directory names.
+ * @throws {Error} As may be thrown by `fs.unlinkSync`.
+ * @returns {LintReport} The results for all files that were linted.
+ */
- // Adopt the rule config which was found at first.
- if (targetDef === void 0) {
- if (Array.isArray(sourceDef)) {
- target[key] = [...sourceDef];
- } else {
- target[key] = [sourceDef];
- }
- /*
- * If the first found rule config is severity only and the current rule
- * config has options, merge the severity and the options.
- */
- } else if (
- targetDef.length === 1 &&
- Array.isArray(sourceDef) &&
- sourceDef.length >= 2
- ) {
- targetDef.push(...sourceDef.slice(1));
+ executeOnFiles(patterns) {
+ const {
+ cacheFilePath,
+ fileEnumerator,
+ lastConfigArrays,
+ lintResultCache,
+ linter,
+ options: {
+ allowInlineConfig,
+ cache,
+ cwd,
+ fix,
+ reportUnusedDisableDirectives
+ }
+ } = internalSlotsMap.get(this);
+ const results = [];
+ const startTime = Date.now(); // Clear the last used config arrays.
+
+ lastConfigArrays.length = 0; // Delete cache file; should this do here?
+
+ if (!cache) {
+ try {
+ fs.unlinkSync(cacheFilePath);
+ } catch (error) {
+ const errorCode = error && error.code; // Ignore errors when no such file exists or file system is read only (and cache file does not exist)
+
+ if (errorCode !== "ENOENT" && !(errorCode === "EROFS" && !fs.existsSync(cacheFilePath))) {
+ throw error;
}
- }
-}
+ }
+ } // Iterate source code files.
-/**
- * Create the extracted config.
- * @param {ConfigArray} instance The config elements.
- * @param {number[]} indices The indices to use.
- * @returns {ExtractedConfig} The extracted config.
- */
-function createConfig(instance, indices) {
- const config = new ExtractedConfig();
- const ignorePatterns = [];
- // Merge elements.
- for (const index of indices) {
- const element = instance[index];
+ for (const {
+ config,
+ filePath,
+ ignored
+ } of fileEnumerator.iterateFiles(patterns)) {
+ if (ignored) {
+ results.push(createIgnoreResult(filePath, cwd));
+ continue;
+ }
+ /*
+ * Store used configs for:
+ * - this method uses to collect used deprecated rules.
+ * - `getRules()` method uses to collect all loaded rules.
+ * - `--fix-type` option uses to get the loaded rule's meta data.
+ */
- // Adopt the parser which was found at first.
- if (!config.parser && element.parser) {
- if (element.parser.error) {
- throw element.parser.error;
- }
- config.parser = element.parser;
+
+ if (!lastConfigArrays.includes(config)) {
+ lastConfigArrays.push(config);
+ } // Skip if there is cached result.
+
+
+ if (lintResultCache) {
+ const cachedResult = lintResultCache.getCachedLintResults(filePath, config);
+
+ if (cachedResult) {
+ const hadMessages = cachedResult.messages && cachedResult.messages.length > 0;
+
+ if (hadMessages && fix) {
+ debug("Reprocessing cached file to allow autofix: ".concat(filePath));
+ } else {
+ debug("Skipping file since it hasn't changed: ".concat(filePath));
+ results.push(cachedResult);
+ continue;
+ }
}
+ } // Do lint.
+
+
+ const result = verifyText({
+ text: fs.readFileSync(filePath, "utf8"),
+ filePath,
+ config,
+ cwd,
+ fix,
+ allowInlineConfig,
+ reportUnusedDisableDirectives,
+ fileEnumerator,
+ linter
+ });
+ results.push(result);
+ /*
+ * Store the lint result in the LintResultCache.
+ * NOTE: The LintResultCache will remove the file source and any
+ * other properties that are difficult to serialize, and will
+ * hydrate those properties back in on future lint runs.
+ */
+
+ if (lintResultCache) {
+ lintResultCache.setCachedLintResults(filePath, config, result);
+ }
+ } // Persist the cache to disk.
- // Adopt the processor which was found at first.
- if (!config.processor && element.processor) {
- config.processor = element.processor;
- }
- // Adopt the noInlineConfig which was found at first.
- if (config.noInlineConfig === void 0 && element.noInlineConfig !== void 0) {
- config.noInlineConfig = element.noInlineConfig;
- config.configNameOfNoInlineConfig = element.name;
- }
+ if (lintResultCache) {
+ lintResultCache.reconcile();
+ }
- // Adopt the reportUnusedDisableDirectives which was found at first.
- if (config.reportUnusedDisableDirectives === void 0 && element.reportUnusedDisableDirectives !== void 0) {
- config.reportUnusedDisableDirectives = element.reportUnusedDisableDirectives;
- }
+ debug("Linting complete in: ".concat(Date.now() - startTime, "ms"));
+ let usedDeprecatedRules;
+ return {
+ results,
+ ...calculateStatsPerRun(results),
- // Collect ignorePatterns
- if (element.ignorePattern) {
- ignorePatterns.push(element.ignorePattern);
+ // Initialize it lazily because CLI and `ESLint` API don't use it.
+ get usedDeprecatedRules() {
+ if (!usedDeprecatedRules) {
+ usedDeprecatedRules = Array.from(iterateRuleDeprecationWarnings(lastConfigArrays));
}
- // Merge others.
- mergeWithoutOverwrite(config.env, element.env);
- mergeWithoutOverwrite(config.globals, element.globals);
- mergeWithoutOverwrite(config.parserOptions, element.parserOptions);
- mergeWithoutOverwrite(config.settings, element.settings);
- mergePlugins(config.plugins, element.plugins);
- mergeRuleConfigs(config.rules, element.rules);
- }
+ return usedDeprecatedRules;
+ }
- // Create the predicate function for ignore patterns.
- if (ignorePatterns.length > 0) {
- config.ignores = IgnorePattern.createIgnore(ignorePatterns.reverse());
- }
+ };
+ }
+ /**
+ * Executes the current configuration on text.
+ * @param {string} text A string of JavaScript code to lint.
+ * @param {string} [filename] An optional string representing the texts filename.
+ * @param {boolean} [warnIgnored] Always warn when a file is ignored
+ * @returns {LintReport} The results for the linting.
+ */
- return config;
-}
-/**
- * Collect definitions.
- * @template T, U
- * @param {string} pluginId The plugin ID for prefix.
- * @param {Record<string,T>} defs The definitions to collect.
- * @param {Map<string, U>} map The map to output.
- * @param {function(T): U} [normalize] The normalize function for each value.
- * @returns {void}
- */
-function collect(pluginId, defs, map, normalize) {
- if (defs) {
- const prefix = pluginId && `${pluginId}/`;
+ executeOnText(text, filename, warnIgnored) {
+ const {
+ configArrayFactory,
+ fileEnumerator,
+ lastConfigArrays,
+ linter,
+ options: {
+ allowInlineConfig,
+ cwd,
+ fix,
+ reportUnusedDisableDirectives
+ }
+ } = internalSlotsMap.get(this);
+ const results = [];
+ const startTime = Date.now();
+ const resolvedFilename = filename && path.resolve(cwd, filename); // Clear the last used config arrays.
- for (const [key, value] of Object.entries(defs)) {
- map.set(
- `${prefix}${key}`,
- normalize ? normalize(value) : value
- );
- }
- }
-}
+ lastConfigArrays.length = 0;
-/**
- * Normalize a rule definition.
- * @param {Function|Rule} rule The rule definition to normalize.
- * @returns {Rule} The normalized rule definition.
- */
-function normalizePluginRule(rule) {
- return typeof rule === "function" ? { create: rule } : rule;
-}
+ if (resolvedFilename && this.isPathIgnored(resolvedFilename)) {
+ if (warnIgnored) {
+ results.push(createIgnoreResult(resolvedFilename, cwd));
+ }
+ } else {
+ const config = configArrayFactory.getConfigArrayForFile(resolvedFilename || "__placeholder__.js");
+ /*
+ * Store used configs for:
+ * - this method uses to collect used deprecated rules.
+ * - `getRules()` method uses to collect all loaded rules.
+ * - `--fix-type` option uses to get the loaded rule's meta data.
+ */
-/**
- * Delete the mutation methods from a given map.
- * @param {Map<any, any>} map The map object to delete.
- * @returns {void}
- */
-function deleteMutationMethods(map) {
- Object.defineProperties(map, {
- clear: { configurable: true, value: void 0 },
- delete: { configurable: true, value: void 0 },
- set: { configurable: true, value: void 0 }
- });
-}
+ lastConfigArrays.push(config); // Do lint.
-/**
- * Create `envMap`, `processorMap`, `ruleMap` with the plugins in the config array.
- * @param {ConfigArrayElement[]} elements The config elements.
- * @param {ConfigArrayInternalSlots} slots The internal slots.
- * @returns {void}
- */
-function initPluginMemberMaps(elements, slots) {
- const processed = new Set();
+ results.push(verifyText({
+ text,
+ filePath: resolvedFilename,
+ config,
+ cwd,
+ fix,
+ allowInlineConfig,
+ reportUnusedDisableDirectives,
+ fileEnumerator,
+ linter
+ }));
+ }
- slots.envMap = new Map();
- slots.processorMap = new Map();
- slots.ruleMap = new Map();
+ debug("Linting complete in: ".concat(Date.now() - startTime, "ms"));
+ let usedDeprecatedRules;
+ return {
+ results,
+ ...calculateStatsPerRun(results),
- for (const element of elements) {
- if (!element.plugins) {
- continue;
+ // Initialize it lazily because CLI and `ESLint` API don't use it.
+ get usedDeprecatedRules() {
+ if (!usedDeprecatedRules) {
+ usedDeprecatedRules = Array.from(iterateRuleDeprecationWarnings(lastConfigArrays));
}
- for (const [pluginId, value] of Object.entries(element.plugins)) {
- const plugin = value.definition;
-
- if (!plugin || processed.has(pluginId)) {
- continue;
- }
- processed.add(pluginId);
+ return usedDeprecatedRules;
+ }
- collect(pluginId, plugin.environments, slots.envMap);
- collect(pluginId, plugin.processors, slots.processorMap);
- collect(pluginId, plugin.rules, slots.ruleMap, normalizePluginRule);
- }
- }
+ };
+ }
+ /**
+ * Returns a configuration object for the given file based on the CLI options.
+ * This is the same logic used by the ESLint CLI executable to determine
+ * configuration for each file it processes.
+ * @param {string} filePath The path of the file to retrieve a config object for.
+ * @throws {Error} If filepath a directory path.
+ * @returns {ConfigData} A configuration object for the file.
+ */
- deleteMutationMethods(slots.envMap);
- deleteMutationMethods(slots.processorMap);
- deleteMutationMethods(slots.ruleMap);
-}
-/**
- * Create `envMap`, `processorMap`, `ruleMap` with the plugins in the config array.
- * @param {ConfigArray} instance The config elements.
- * @returns {ConfigArrayInternalSlots} The extracted config.
- */
-function ensurePluginMemberMaps(instance) {
- const slots = internalSlotsMap$2.get(instance);
+ getConfigForFile(filePath) {
+ const {
+ configArrayFactory,
+ options
+ } = internalSlotsMap.get(this);
+ const absolutePath = path.resolve(options.cwd, filePath);
- if (!slots.ruleMap) {
- initPluginMemberMaps(instance, slots);
+ if (directoryExists(absolutePath)) {
+ throw Object.assign(new Error("'filePath' should not be a directory path."), {
+ messageTemplate: "print-config-with-directory-path"
+ });
}
- return slots;
-}
+ return configArrayFactory.getConfigArrayForFile(absolutePath).extractConfig(absolutePath).toCompatibleObjectAsConfigFileContent();
+ }
+ /**
+ * Checks if a given path is ignored by ESLint.
+ * @param {string} filePath The path of the file to check.
+ * @returns {boolean} Whether or not the given path is ignored.
+ */
-//------------------------------------------------------------------------------
-// Public Interface
-//------------------------------------------------------------------------------
-/**
- * The Config Array.
- *
- * `ConfigArray` instance contains all settings, parsers, and plugins.
- * You need to call `ConfigArray#extractConfig(filePath)` method in order to
- * extract, merge and get only the config data which is related to an arbitrary
- * file.
- * @extends {Array<ConfigArrayElement>}
- */
-class ConfigArray extends Array {
+ isPathIgnored(filePath) {
+ const {
+ configArrayFactory,
+ defaultIgnores,
+ options: {
+ cwd,
+ ignore
+ }
+ } = internalSlotsMap.get(this);
+ const absolutePath = path.resolve(cwd, filePath);
- /**
- * Get the plugin environments.
- * The returned map cannot be mutated.
- * @type {ReadonlyMap<string, Environment>} The plugin environments.
- */
- get pluginEnvironments() {
- return ensurePluginMemberMaps(this).envMap;
+ if (ignore) {
+ const config = configArrayFactory.getConfigArrayForFile(absolutePath).extractConfig(absolutePath);
+ const ignores = config.ignores || defaultIgnores;
+ return ignores(absolutePath);
}
- /**
- * Get the plugin processors.
- * The returned map cannot be mutated.
- * @type {ReadonlyMap<string, Processor>} The plugin processors.
- */
- get pluginProcessors() {
- return ensurePluginMemberMaps(this).processorMap;
- }
+ return defaultIgnores(absolutePath);
+ }
+ /**
+ * Returns the formatter representing the given format or null if the `format` is not a string.
+ * @param {string} [format] The name of the format to load or the path to a
+ * custom formatter.
+ * @throws {any} As may be thrown by requiring of formatter
+ * @returns {(Function|null)} The formatter function or null if the `format` is not a string.
+ */
- /**
- * Get the plugin rules.
- * The returned map cannot be mutated.
- * @returns {ReadonlyMap<string, Rule>} The plugin rules.
- */
- get pluginRules() {
- return ensurePluginMemberMaps(this).ruleMap;
- }
- /**
- * Check if this config has `root` flag.
- * @returns {boolean} `true` if this config array is root.
- */
- isRoot() {
- for (let i = this.length - 1; i >= 0; --i) {
- const root = this[i].root;
+ getFormatter(format) {
+ // default is stylish
+ const resolvedFormatName = format || "stylish"; // only strings are valid formatters
- if (typeof root === "boolean") {
- return root;
- }
- }
- return false;
- }
+ if (typeof resolvedFormatName === "string") {
+ // replace \ with / for Windows compatibility
+ const normalizedFormatName = resolvedFormatName.replace(/\\/gu, "/");
+ const slots = internalSlotsMap.get(this);
+ const cwd = slots ? slots.options.cwd : process.cwd();
+ const namespace = naming.getNamespaceFromTerm(normalizedFormatName);
+ let formatterPath; // if there's a slash, then it's a file (TODO: this check seems dubious for scoped npm packages)
- /**
- * Extract the config data which is related to a given file.
- * @param {string} filePath The absolute path to the target file.
- * @returns {ExtractedConfig} The extracted config data.
- */
- extractConfig(filePath) {
- const { cache } = internalSlotsMap$2.get(this);
- const indices = getMatchedIndices(this, filePath);
- const cacheKey = indices.join(",");
+ if (!namespace && normalizedFormatName.indexOf("/") > -1) {
+ formatterPath = path.resolve(cwd, normalizedFormatName);
+ } else {
+ try {
+ const npmFormat = naming.normalizePackageName(normalizedFormatName, "eslint-formatter");
+ formatterPath = ModuleResolver.resolve(npmFormat, path.join(cwd, "__placeholder__.js"));
+ } catch {
+ formatterPath = path.resolve(__dirname, "formatters", normalizedFormatName);
+ }
+ }
- if (!cache.has(cacheKey)) {
- cache.set(cacheKey, createConfig(this, indices));
+ try {
+ return __webpack_require__(899)(formatterPath);
+ } catch (ex) {
+ if (format === "table" || format === "codeframe") {
+ ex.message = "The ".concat(format, " formatter is no longer part of core ESLint. Install it manually with `npm install -D eslint-formatter-").concat(format, "`");
+ } else {
+ ex.message = "There was a problem loading formatter: ".concat(formatterPath, "\nError: ").concat(ex.message);
}
- return cache.get(cacheKey);
+ throw ex;
+ }
+ } else {
+ return null;
}
+ }
- /**
- * Check if a given path is an additional lint target.
- * @param {string} filePath The absolute path to the target file.
- * @returns {boolean} `true` if the file is an additional lint target.
- */
- isAdditionalTargetPath(filePath) {
- for (const { criteria, type } of this) {
- if (
- type === "config" &&
- criteria &&
- !criteria.endsWithWildcard &&
- criteria.test(filePath)
- ) {
- return true;
- }
- }
- return false;
- }
}
-/**
- * Get the used extracted configs.
- * CLIEngine will use this method to collect used deprecated rules.
- * @param {ConfigArray} instance The config array object to get.
- * @returns {ExtractedConfig[]} The used extracted configs.
- * @private
- */
-function getUsedExtractedConfigs(instance) {
- const { cache } = internalSlotsMap$2.get(instance);
+CLIEngine.version = pkg.version;
+CLIEngine.getFormatter = CLIEngine.prototype.getFormatter;
+module.exports = {
+ CLIEngine,
- return Array.from(cache.values());
-}
+ /**
+ * Get the internal slots of a given CLIEngine instance for tests.
+ * @param {CLIEngine} instance The CLIEngine instance to get.
+ * @returns {CLIEngineInternalSlots} The internal slots.
+ */
+ getCLIEngineInternalSlots(instance) {
+ return internalSlotsMap.get(instance);
+ }
-/**
- * @fileoverview `ConfigDependency` class.
- *
- * `ConfigDependency` class expresses a loaded parser or plugin.
- *
- * If the parser or plugin was loaded successfully, it has `definition` property
- * and `filePath` property. Otherwise, it has `error` property.
- *
- * When `JSON.stringify()` converted a `ConfigDependency` object to a JSON, it
- * omits `definition` property.
- *
- * `ConfigArrayFactory` creates `ConfigDependency` objects when it loads parsers
- * or plugins.
- *
- * @author Toru Nagashima <https://github.com/mysticatea>
- */
+};
+
+/***/ }),
+/* 882 */
+/***/ ((module) => {
+"use strict";
/**
- * The class is to store parsers or plugins.
- * This class hides the loaded object from `JSON.stringify()` and `console.log`.
- * @template T
+ * @fileoverview Default CLIEngineOptions.
+ * @author Ian VanSchooten
*/
-class ConfigDependency {
- /**
- * Initialize this instance.
- * @param {Object} data The dependency data.
- * @param {T} [data.definition] The dependency if the loading succeeded.
- * @param {Error} [data.error] The error object if the loading failed.
- * @param {string} [data.filePath] The actual path to the dependency if the loading succeeded.
- * @param {string} data.id The ID of this dependency.
- * @param {string} data.importerName The name of the config file which loads this dependency.
- * @param {string} data.importerPath The path to the config file which loads this dependency.
- */
- constructor({
- definition = null,
- error = null,
- filePath = null,
- id,
- importerName,
- importerPath
- }) {
- /**
- * The loaded dependency if the loading succeeded.
- * @type {T|null}
- */
- this.definition = definition;
+module.exports = {
+ configFile: null,
+ baseConfig: false,
+ rulePaths: [],
+ useEslintrc: true,
+ envs: [],
+ globals: [],
+ extensions: null,
+ ignore: true,
+ ignorePath: void 0,
+ cache: false,
- /**
- * The error object if the loading failed.
- * @type {Error|null}
- */
- this.error = error;
+ /*
+ * in order to honor the cacheFile option if specified
+ * this option should not have a default value otherwise
+ * it will always be used
+ */
+ cacheLocation: "",
+ cacheFile: ".eslintcache",
+ cacheStrategy: "metadata",
+ fix: false,
+ allowInlineConfig: true,
+ reportUnusedDisableDirectives: void 0,
+ globInputPaths: true
+};
- /**
- * The loaded dependency if the loading succeeded.
- * @type {string|null}
- */
- this.filePath = filePath;
+/***/ }),
+/* 883 */
+/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
- /**
- * The ID of this dependency.
- * @type {string}
- */
- this.id = id;
+"use strict";
+/* provided dependency */ var process = __webpack_require__(494);
- /**
- * The name of the config file which loads this dependency.
- * @type {string}
- */
- this.importerName = importerName;
- /**
- * The path to the config file which loads this dependency.
- * @type {string}
- */
- this.importerPath = importerPath;
- }
+Object.defineProperty(exports, "__esModule", ({ value: true }));
+
+var fs = __webpack_require__(880);
+var path = __webpack_require__(429);
+var importFresh = __webpack_require__(884);
+var stripComments = __webpack_require__(890);
+var util = __webpack_require__(439);
+var Ajv = __webpack_require__(446);
+var globals = __webpack_require__(492);
+var Module = __webpack_require__(886);
+var assert = __webpack_require__(431);
+var ignore = __webpack_require__(737);
+var debugOrig = __webpack_require__(496);
+var minimatch = __webpack_require__(862);
+var os = __webpack_require__(891);
+var url = __webpack_require__(892);
+
+function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
+
+var fs__default = /*#__PURE__*/_interopDefaultLegacy(fs);
+var path__default = /*#__PURE__*/_interopDefaultLegacy(path);
+var importFresh__default = /*#__PURE__*/_interopDefaultLegacy(importFresh);
+var stripComments__default = /*#__PURE__*/_interopDefaultLegacy(stripComments);
+var util__default = /*#__PURE__*/_interopDefaultLegacy(util);
+var Ajv__default = /*#__PURE__*/_interopDefaultLegacy(Ajv);
+var globals__default = /*#__PURE__*/_interopDefaultLegacy(globals);
+var Module__default = /*#__PURE__*/_interopDefaultLegacy(Module);
+var assert__default = /*#__PURE__*/_interopDefaultLegacy(assert);
+var ignore__default = /*#__PURE__*/_interopDefaultLegacy(ignore);
+var debugOrig__default = /*#__PURE__*/_interopDefaultLegacy(debugOrig);
+var minimatch__default = /*#__PURE__*/_interopDefaultLegacy(minimatch);
+var os__default = /*#__PURE__*/_interopDefaultLegacy(os);
+
+/**
+ * @fileoverview Config file operations. This file must be usable in the browser,
+ * so no Node-specific code can be here.
+ * @author Nicholas C. Zakas
+ */
+
+//------------------------------------------------------------------------------
+// Private
+//------------------------------------------------------------------------------
+
+const RULE_SEVERITY_STRINGS = ["off", "warn", "error"],
+ RULE_SEVERITY = RULE_SEVERITY_STRINGS.reduce((map, value, index) => {
+ map[value] = index;
+ return map;
+ }, {}),
+ VALID_SEVERITIES = [0, 1, 2, "off", "warn", "error"];
- // eslint-disable-next-line jsdoc/require-description
- /**
- * @returns {Object} a JSON compatible object.
- */
- toJSON() {
- const obj = this[util__default["default"].inspect.custom]();
+//------------------------------------------------------------------------------
+// Public Interface
+//------------------------------------------------------------------------------
- // Display `error.message` (`Error#message` is unenumerable).
- if (obj.error instanceof Error) {
- obj.error = { ...obj.error, message: obj.error.message };
- }
+/**
+ * Normalizes the severity value of a rule's configuration to a number
+ * @param {(number|string|[number, ...*]|[string, ...*])} ruleConfig A rule's configuration value, generally
+ * received from the user. A valid config value is either 0, 1, 2, the string "off" (treated the same as 0),
+ * the string "warn" (treated the same as 1), the string "error" (treated the same as 2), or an array
+ * whose first element is one of the above values. Strings are matched case-insensitively.
+ * @returns {(0|1|2)} The numeric severity value if the config value was valid, otherwise 0.
+ */
+function getRuleSeverity(ruleConfig) {
+ const severityValue = Array.isArray(ruleConfig) ? ruleConfig[0] : ruleConfig;
- return obj;
+ if (severityValue === 0 || severityValue === 1 || severityValue === 2) {
+ return severityValue;
}
- // eslint-disable-next-line jsdoc/require-description
- /**
- * @returns {Object} an object to display by `console.log()`.
- */
- [util__default["default"].inspect.custom]() {
- const {
- definition: _ignore, // eslint-disable-line no-unused-vars
- ...obj
- } = this;
-
- return obj;
+ if (typeof severityValue === "string") {
+ return RULE_SEVERITY[severityValue.toLowerCase()] || 0;
}
+
+ return 0;
}
/**
- * @fileoverview `OverrideTester` class.
- *
- * `OverrideTester` class handles `files` property and `excludedFiles` property
- * of `overrides` config.
- *
- * It provides one method.
- *
- * - `test(filePath)`
- * Test if a file path matches the pair of `files` property and
- * `excludedFiles` property. The `filePath` argument must be an absolute
- * path.
- *
- * `ConfigArrayFactory` creates `OverrideTester` objects when it processes
- * `overrides` properties.
- *
- * @author Toru Nagashima <https://github.com/mysticatea>
+ * Converts old-style severity settings (0, 1, 2) into new-style
+ * severity settings (off, warn, error) for all rules. Assumption is that severity
+ * values have already been validated as correct.
+ * @param {Object} config The config object to normalize.
+ * @returns {void}
*/
+function normalizeToStrings(config) {
-const { Minimatch } = minimatch__default["default"];
-
-const minimatchOpts = { dot: true, matchBase: true };
+ if (config.rules) {
+ Object.keys(config.rules).forEach(ruleId => {
+ const ruleConfig = config.rules[ruleId];
-/**
- * @typedef {Object} Pattern
- * @property {InstanceType<Minimatch>[] | null} includes The positive matchers.
- * @property {InstanceType<Minimatch>[] | null} excludes The negative matchers.
- */
+ if (typeof ruleConfig === "number") {
+ config.rules[ruleId] = RULE_SEVERITY_STRINGS[ruleConfig] || RULE_SEVERITY_STRINGS[0];
+ } else if (Array.isArray(ruleConfig) && typeof ruleConfig[0] === "number") {
+ ruleConfig[0] = RULE_SEVERITY_STRINGS[ruleConfig[0]] || RULE_SEVERITY_STRINGS[0];
+ }
+ });
+ }
+}
/**
- * Normalize a given pattern to an array.
- * @param {string|string[]|undefined} patterns A glob pattern or an array of glob patterns.
- * @returns {string[]|null} Normalized patterns.
- * @private
+ * Determines if the severity for the given rule configuration represents an error.
+ * @param {int|string|Array} ruleConfig The configuration for an individual rule.
+ * @returns {boolean} True if the rule represents an error, false if not.
*/
-function normalizePatterns(patterns) {
- if (Array.isArray(patterns)) {
- return patterns.filter(Boolean);
- }
- if (typeof patterns === "string" && patterns) {
- return [patterns];
- }
- return [];
+function isErrorSeverity(ruleConfig) {
+ return getRuleSeverity(ruleConfig) === 2;
}
/**
- * Create the matchers of given patterns.
- * @param {string[]} patterns The patterns.
- * @returns {InstanceType<Minimatch>[] | null} The matchers.
+ * Checks whether a given config has valid severity or not.
+ * @param {number|string|Array} ruleConfig The configuration for an individual rule.
+ * @returns {boolean} `true` if the configuration has valid severity.
*/
-function toMatcher(patterns) {
- if (patterns.length === 0) {
- return null;
- }
- return patterns.map(pattern => {
- if (/^\.[/\\]/u.test(pattern)) {
- return new Minimatch(
- pattern.slice(2),
+function isValidSeverity(ruleConfig) {
+ let severity = Array.isArray(ruleConfig) ? ruleConfig[0] : ruleConfig;
- // `./*.js` should not match with `subdir/foo.js`
- { ...minimatchOpts, matchBase: false }
- );
- }
- return new Minimatch(pattern, minimatchOpts);
- });
+ if (typeof severity === "string") {
+ severity = severity.toLowerCase();
+ }
+ return VALID_SEVERITIES.indexOf(severity) !== -1;
}
/**
- * Convert a given matcher to string.
- * @param {Pattern} matchers The matchers.
- * @returns {string} The string expression of the matcher.
+ * Checks whether every rule of a given config has valid severity or not.
+ * @param {Object} config The configuration for rules.
+ * @returns {boolean} `true` if the configuration has valid severity.
*/
-function patternToJson({ includes, excludes }) {
- return {
- includes: includes && includes.map(m => m.pattern),
- excludes: excludes && excludes.map(m => m.pattern)
- };
+function isEverySeverityValid(config) {
+ return Object.keys(config).every(ruleId => isValidSeverity(config[ruleId]));
}
/**
- * The class to test given paths are matched by the patterns.
+ * Normalizes a value for a global in a config
+ * @param {(boolean|string|null)} configuredValue The value given for a global in configuration or in
+ * a global directive comment
+ * @returns {("readable"|"writeable"|"off")} The value normalized as a string
+ * @throws Error if global value is invalid
*/
-class OverrideTester {
-
- /**
- * Create a tester with given criteria.
- * If there are no criteria, returns `null`.
- * @param {string|string[]} files The glob patterns for included files.
- * @param {string|string[]} excludedFiles The glob patterns for excluded files.
- * @param {string} basePath The path to the base directory to test paths.
- * @returns {OverrideTester|null} The created instance or `null`.
- */
- static create(files, excludedFiles, basePath) {
- const includePatterns = normalizePatterns(files);
- const excludePatterns = normalizePatterns(excludedFiles);
- let endsWithWildcard = false;
-
- if (includePatterns.length === 0) {
- return null;
- }
+function normalizeConfigGlobal(configuredValue) {
+ switch (configuredValue) {
+ case "off":
+ return "off";
- // Rejects absolute paths or relative paths to parents.
- for (const pattern of includePatterns) {
- if (path__default["default"].isAbsolute(pattern) || pattern.includes("..")) {
- throw new Error(`Invalid override pattern (expected relative path not containing '..'): ${pattern}`);
- }
- if (pattern.endsWith("*")) {
- endsWithWildcard = true;
- }
- }
- for (const pattern of excludePatterns) {
- if (path__default["default"].isAbsolute(pattern) || pattern.includes("..")) {
- throw new Error(`Invalid override pattern (expected relative path not containing '..'): ${pattern}`);
- }
- }
+ case true:
+ case "true":
+ case "writeable":
+ case "writable":
+ return "writable";
- const includes = toMatcher(includePatterns);
- const excludes = toMatcher(excludePatterns);
+ case null:
+ case false:
+ case "false":
+ case "readable":
+ case "readonly":
+ return "readonly";
- return new OverrideTester(
- [{ includes, excludes }],
- basePath,
- endsWithWildcard
- );
+ default:
+ throw new Error(`'${configuredValue}' is not a valid configuration for a global (use 'readonly', 'writable', or 'off')`);
}
+}
- /**
- * Combine two testers by logical and.
- * If either of the testers was `null`, returns the other tester.
- * The `basePath` property of the two must be the same value.
- * @param {OverrideTester|null} a A tester.
- * @param {OverrideTester|null} b Another tester.
- * @returns {OverrideTester|null} Combined tester.
- */
- static and(a, b) {
- if (!b) {
- return a && new OverrideTester(
- a.patterns,
- a.basePath,
- a.endsWithWildcard
- );
- }
- if (!a) {
- return new OverrideTester(
- b.patterns,
- b.basePath,
- b.endsWithWildcard
- );
- }
-
- assert__default["default"].strictEqual(a.basePath, b.basePath);
- return new OverrideTester(
- a.patterns.concat(b.patterns),
- a.basePath,
- a.endsWithWildcard || b.endsWithWildcard
- );
- }
+var ConfigOps = {
+ __proto__: null,
+ getRuleSeverity: getRuleSeverity,
+ normalizeToStrings: normalizeToStrings,
+ isErrorSeverity: isErrorSeverity,
+ isValidSeverity: isValidSeverity,
+ isEverySeverityValid: isEverySeverityValid,
+ normalizeConfigGlobal: normalizeConfigGlobal
+};
- /**
- * Initialize this instance.
- * @param {Pattern[]} patterns The matchers.
- * @param {string} basePath The base path.
- * @param {boolean} endsWithWildcard If `true` then a pattern ends with `*`.
- */
- constructor(patterns, basePath, endsWithWildcard = false) {
+/**
+ * @fileoverview Provide the function that emits deprecation warnings.
+ * @author Toru Nagashima <http://github.com/mysticatea>
+ */
- /** @type {Pattern[]} */
- this.patterns = patterns;
+//------------------------------------------------------------------------------
+// Private
+//------------------------------------------------------------------------------
- /** @type {string} */
- this.basePath = basePath;
+// Defitions for deprecation warnings.
+const deprecationWarningMessages = {
+ ESLINT_LEGACY_ECMAFEATURES:
+ "The 'ecmaFeatures' config file property is deprecated and has no effect.",
+ ESLINT_PERSONAL_CONFIG_LOAD:
+ "'~/.eslintrc.*' config files have been deprecated. " +
+ "Please use a config file per project or the '--config' option.",
+ ESLINT_PERSONAL_CONFIG_SUPPRESS:
+ "'~/.eslintrc.*' config files have been deprecated. " +
+ "Please remove it or add 'root:true' to the config files in your " +
+ "projects in order to avoid loading '~/.eslintrc.*' accidentally."
+};
- /** @type {boolean} */
- this.endsWithWildcard = endsWithWildcard;
- }
+const sourceFileErrorCache = new Set();
- /**
- * Test if a given path is matched or not.
- * @param {string} filePath The absolute path to the target file.
- * @returns {boolean} `true` if the path was matched.
- */
- test(filePath) {
- if (typeof filePath !== "string" || !path__default["default"].isAbsolute(filePath)) {
- throw new Error(`'filePath' should be an absolute path, but got ${filePath}.`);
- }
- const relativePath = path__default["default"].relative(this.basePath, filePath);
+/**
+ * Emits a deprecation warning containing a given filepath. A new deprecation warning is emitted
+ * for each unique file path, but repeated invocations with the same file path have no effect.
+ * No warnings are emitted if the `--no-deprecation` or `--no-warnings` Node runtime flags are active.
+ * @param {string} source The name of the configuration source to report the warning for.
+ * @param {string} errorCode The warning message to show.
+ * @returns {void}
+ */
+function emitDeprecationWarning(source, errorCode) {
+ const cacheKey = JSON.stringify({ source, errorCode });
- return this.patterns.every(({ includes, excludes }) => (
- (!includes || includes.some(m => m.match(relativePath))) &&
- (!excludes || !excludes.some(m => m.match(relativePath)))
- ));
+ if (sourceFileErrorCache.has(cacheKey)) {
+ return;
}
+ sourceFileErrorCache.add(cacheKey);
- // eslint-disable-next-line jsdoc/require-description
- /**
- * @returns {Object} a JSON compatible object.
- */
- toJSON() {
- if (this.patterns.length === 1) {
- return {
- ...patternToJson(this.patterns[0]),
- basePath: this.basePath
- };
- }
- return {
- AND: this.patterns.map(patternToJson),
- basePath: this.basePath
- };
- }
+ const rel = path__default["default"].relative(process.cwd(), source);
+ const message = deprecationWarningMessages[errorCode];
- // eslint-disable-next-line jsdoc/require-description
- /**
- * @returns {Object} an object to display by `console.log()`.
- */
- [util__default["default"].inspect.custom]() {
- return this.toJSON();
- }
+ process.emitWarning(
+ `${message} (found in "${rel}")`,
+ "DeprecationWarning",
+ errorCode
+ );
}
/**
- * @fileoverview `ConfigArray` class.
- * @author Toru Nagashima <https://github.com/mysticatea>
+ * @fileoverview The instance of Ajv validator.
+ * @author Evgeny Poberezkin
*/
-/**
- * @fileoverview The factory of `ConfigArray` objects.
- *
- * This class provides methods to create `ConfigArray` instance.
- *
- * - `create(configData, options)`
- * Create a `ConfigArray` instance from a config data. This is to handle CLI
- * options except `--config`.
- * - `loadFile(filePath, options)`
- * Create a `ConfigArray` instance from a config file. This is to handle
- * `--config` option. If the file was not found, throws the following error:
- * - If the filename was `*.js`, a `MODULE_NOT_FOUND` error.
- * - If the filename was `package.json`, an IO error or an
- * `ESLINT_CONFIG_FIELD_NOT_FOUND` error.
- * - Otherwise, an IO error such as `ENOENT`.
- * - `loadInDirectory(directoryPath, options)`
- * Create a `ConfigArray` instance from a config file which is on a given
- * directory. This tries to load `.eslintrc.*` or `package.json`. If not
- * found, returns an empty `ConfigArray`.
- * - `loadESLintIgnore(filePath)`
- * Create a `ConfigArray` instance from a config file that is `.eslintignore`
- * format. This is to handle `--ignore-path` option.
- * - `loadDefaultESLintIgnore()`
- * Create a `ConfigArray` instance from `.eslintignore` or `package.json` in
- * the current working directory.
- *
- * `ConfigArrayFactory` class has the responsibility that loads configuration
- * files, including loading `extends`, `parser`, and `plugins`. The created
- * `ConfigArray` instance has the loaded `extends`, `parser`, and `plugins`.
- *
- * But this class doesn't handle cascading. `CascadingConfigArrayFactory` class
- * handles cascading and hierarchy.
- *
- * @author Toru Nagashima <https://github.com/mysticatea>
- */
-const require$1 = Module.createRequire((typeof document === 'undefined' ? new ((__webpack_require__(876).URL))('file:' + __filename).href : (document.currentScript && document.currentScript.src || new URL('eslintrc.cjs', document.baseURI).href)));
+//-----------------------------------------------------------------------------
+// Helpers
+//-----------------------------------------------------------------------------
-const debug$2 = debugOrig__default["default"]("eslintrc:config-array-factory");
+/*
+ * Copied from ajv/lib/refs/json-schema-draft-04.json
+ * The MIT License (MIT)
+ * Copyright (c) 2015-2017 Evgeny Poberezkin
+ */
+const metaSchema = {
+ id: "http://json-schema.org/draft-04/schema#",
+ $schema: "http://json-schema.org/draft-04/schema#",
+ description: "Core schema meta-schema",
+ definitions: {
+ schemaArray: {
+ type: "array",
+ minItems: 1,
+ items: { $ref: "#" }
+ },
+ positiveInteger: {
+ type: "integer",
+ minimum: 0
+ },
+ positiveIntegerDefault0: {
+ allOf: [{ $ref: "#/definitions/positiveInteger" }, { default: 0 }]
+ },
+ simpleTypes: {
+ enum: ["array", "boolean", "integer", "null", "number", "object", "string"]
+ },
+ stringArray: {
+ type: "array",
+ items: { type: "string" },
+ minItems: 1,
+ uniqueItems: true
+ }
+ },
+ type: "object",
+ properties: {
+ id: {
+ type: "string"
+ },
+ $schema: {
+ type: "string"
+ },
+ title: {
+ type: "string"
+ },
+ description: {
+ type: "string"
+ },
+ default: { },
+ multipleOf: {
+ type: "number",
+ minimum: 0,
+ exclusiveMinimum: true
+ },
+ maximum: {
+ type: "number"
+ },
+ exclusiveMaximum: {
+ type: "boolean",
+ default: false
+ },
+ minimum: {
+ type: "number"
+ },
+ exclusiveMinimum: {
+ type: "boolean",
+ default: false
+ },
+ maxLength: { $ref: "#/definitions/positiveInteger" },
+ minLength: { $ref: "#/definitions/positiveIntegerDefault0" },
+ pattern: {
+ type: "string",
+ format: "regex"
+ },
+ additionalItems: {
+ anyOf: [
+ { type: "boolean" },
+ { $ref: "#" }
+ ],
+ default: { }
+ },
+ items: {
+ anyOf: [
+ { $ref: "#" },
+ { $ref: "#/definitions/schemaArray" }
+ ],
+ default: { }
+ },
+ maxItems: { $ref: "#/definitions/positiveInteger" },
+ minItems: { $ref: "#/definitions/positiveIntegerDefault0" },
+ uniqueItems: {
+ type: "boolean",
+ default: false
+ },
+ maxProperties: { $ref: "#/definitions/positiveInteger" },
+ minProperties: { $ref: "#/definitions/positiveIntegerDefault0" },
+ required: { $ref: "#/definitions/stringArray" },
+ additionalProperties: {
+ anyOf: [
+ { type: "boolean" },
+ { $ref: "#" }
+ ],
+ default: { }
+ },
+ definitions: {
+ type: "object",
+ additionalProperties: { $ref: "#" },
+ default: { }
+ },
+ properties: {
+ type: "object",
+ additionalProperties: { $ref: "#" },
+ default: { }
+ },
+ patternProperties: {
+ type: "object",
+ additionalProperties: { $ref: "#" },
+ default: { }
+ },
+ dependencies: {
+ type: "object",
+ additionalProperties: {
+ anyOf: [
+ { $ref: "#" },
+ { $ref: "#/definitions/stringArray" }
+ ]
+ }
+ },
+ enum: {
+ type: "array",
+ minItems: 1,
+ uniqueItems: true
+ },
+ type: {
+ anyOf: [
+ { $ref: "#/definitions/simpleTypes" },
+ {
+ type: "array",
+ items: { $ref: "#/definitions/simpleTypes" },
+ minItems: 1,
+ uniqueItems: true
+ }
+ ]
+ },
+ format: { type: "string" },
+ allOf: { $ref: "#/definitions/schemaArray" },
+ anyOf: { $ref: "#/definitions/schemaArray" },
+ oneOf: { $ref: "#/definitions/schemaArray" },
+ not: { $ref: "#" }
+ },
+ dependencies: {
+ exclusiveMaximum: ["maximum"],
+ exclusiveMinimum: ["minimum"]
+ },
+ default: { }
+};
//------------------------------------------------------------------------------
-// Helpers
+// Public Interface
//------------------------------------------------------------------------------
-const configFilenames = [
- ".eslintrc.js",
- ".eslintrc.cjs",
- ".eslintrc.yaml",
- ".eslintrc.yml",
- ".eslintrc.json",
- ".eslintrc",
- "package.json"
-];
-
-// Define types for VSCode IntelliSense.
-/** @typedef {import("./shared/types").ConfigData} ConfigData */
-/** @typedef {import("./shared/types").OverrideConfigData} OverrideConfigData */
-/** @typedef {import("./shared/types").Parser} Parser */
-/** @typedef {import("./shared/types").Plugin} Plugin */
-/** @typedef {import("./shared/types").Rule} Rule */
-/** @typedef {import("./config-array/config-dependency").DependentParser} DependentParser */
-/** @typedef {import("./config-array/config-dependency").DependentPlugin} DependentPlugin */
-/** @typedef {ConfigArray[0]} ConfigArrayElement */
-
-/**
- * @typedef {Object} ConfigArrayFactoryOptions
- * @property {Map<string,Plugin>} [additionalPluginPool] The map for additional plugins.
- * @property {string} [cwd] The path to the current working directory.
- * @property {string} [resolvePluginsRelativeTo] A path to the directory that plugins should be resolved from. Defaults to `cwd`.
- * @property {Map<string,Rule>} builtInRules The rules that are built in to ESLint.
- * @property {Object} [resolver=ModuleResolver] The module resolver object.
- * @property {string} eslintAllPath The path to the definitions for eslint:all.
- * @property {string} eslintRecommendedPath The path to the definitions for eslint:recommended.
- */
+var ajvOrig = (additionalOptions = {}) => {
+ const ajv = new Ajv__default["default"]({
+ meta: false,
+ useDefaults: true,
+ validateSchema: false,
+ missingRefs: "ignore",
+ verbose: true,
+ schemaId: "auto",
+ ...additionalOptions
+ });
-/**
- * @typedef {Object} ConfigArrayFactoryInternalSlots
- * @property {Map<string,Plugin>} additionalPluginPool The map for additional plugins.
- * @property {string} cwd The path to the current working directory.
- * @property {string | undefined} resolvePluginsRelativeTo An absolute path the the directory that plugins should be resolved from.
- * @property {Map<string,Rule>} builtInRules The rules that are built in to ESLint.
- * @property {Object} [resolver=ModuleResolver] The module resolver object.
- * @property {string} eslintAllPath The path to the definitions for eslint:all.
- * @property {string} eslintRecommendedPath The path to the definitions for eslint:recommended.
- */
+ ajv.addMetaSchema(metaSchema);
+ // eslint-disable-next-line no-underscore-dangle
+ ajv._opts.defaultMeta = metaSchema.id;
-/**
- * @typedef {Object} ConfigArrayFactoryLoadingContext
- * @property {string} filePath The path to the current configuration.
- * @property {string} matchBasePath The base path to resolve relative paths in `overrides[].files`, `overrides[].excludedFiles`, and `ignorePatterns`.
- * @property {string} name The name of the current configuration.
- * @property {string} pluginBasePath The base path to resolve plugins.
- * @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.
- */
+ return ajv;
+};
/**
- * @typedef {Object} ConfigArrayFactoryLoadingContext
- * @property {string} filePath The path to the current configuration.
- * @property {string} matchBasePath The base path to resolve relative paths in `overrides[].files`, `overrides[].excludedFiles`, and `ignorePatterns`.
- * @property {string} name The name of the current configuration.
- * @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.
+ * @fileoverview Defines a schema for configs.
+ * @author Sylvan Mably
*/
-/** @type {WeakMap<ConfigArrayFactory, ConfigArrayFactoryInternalSlots>} */
-const internalSlotsMap$1 = new WeakMap();
-
-/**
- * Check if a given string is a file path.
- * @param {string} nameOrPath A module name or file path.
- * @returns {boolean} `true` if the `nameOrPath` is a file path.
- */
-function isFilePath(nameOrPath) {
- return (
- /^\.{1,2}[/\\]/u.test(nameOrPath) ||
- path__default["default"].isAbsolute(nameOrPath)
- );
-}
+const baseConfigProperties = {
+ $schema: { type: "string" },
+ env: { type: "object" },
+ extends: { $ref: "#/definitions/stringOrStrings" },
+ globals: { type: "object" },
+ overrides: {
+ type: "array",
+ items: { $ref: "#/definitions/overrideConfig" },
+ additionalItems: false
+ },
+ parser: { type: ["string", "null"] },
+ parserOptions: { type: "object" },
+ plugins: { type: "array" },
+ processor: { type: "string" },
+ rules: { type: "object" },
+ settings: { type: "object" },
+ noInlineConfig: { type: "boolean" },
+ reportUnusedDisableDirectives: { type: "boolean" },
-/**
- * Convenience wrapper for synchronously reading file contents.
- * @param {string} filePath The filename to read.
- * @returns {string} The file contents, with the BOM removed.
- * @private
- */
-function readFile(filePath) {
- return fs__default["default"].readFileSync(filePath, "utf8").replace(/^\ufeff/u, "");
-}
+ ecmaFeatures: { type: "object" } // deprecated; logs a warning when used
+};
-/**
- * Loads a YAML configuration from a file.
- * @param {string} filePath The filename to load.
- * @returns {ConfigData} The configuration object from the file.
- * @throws {Error} If the file cannot be read.
- * @private
- */
-function loadYAMLConfigFile(filePath) {
- debug$2(`Loading YAML config file: ${filePath}`);
+const configSchema = {
+ definitions: {
+ stringOrStrings: {
+ oneOf: [
+ { type: "string" },
+ {
+ type: "array",
+ items: { type: "string" },
+ additionalItems: false
+ }
+ ]
+ },
+ stringOrStringsRequired: {
+ oneOf: [
+ { type: "string" },
+ {
+ type: "array",
+ items: { type: "string" },
+ additionalItems: false,
+ minItems: 1
+ }
+ ]
+ },
- // lazy load YAML to improve performance when not used
- const yaml = require$1("js-yaml");
+ // Config at top-level.
+ objectConfig: {
+ type: "object",
+ properties: {
+ root: { type: "boolean" },
+ ignorePatterns: { $ref: "#/definitions/stringOrStrings" },
+ ...baseConfigProperties
+ },
+ additionalProperties: false
+ },
- try {
+ // Config in `overrides`.
+ overrideConfig: {
+ type: "object",
+ properties: {
+ excludedFiles: { $ref: "#/definitions/stringOrStrings" },
+ files: { $ref: "#/definitions/stringOrStringsRequired" },
+ ...baseConfigProperties
+ },
+ required: ["files"],
+ additionalProperties: false
+ }
+ },
- // empty YAML file can be null, so always use
- return yaml.load(readFile(filePath)) || {};
- } catch (e) {
- debug$2(`Error reading YAML file: ${filePath}`);
- e.message = `Cannot read config file: ${filePath}\nError: ${e.message}`;
- throw e;
- }
-}
+ $ref: "#/definitions/objectConfig"
+};
/**
- * Loads a JSON configuration from a file.
- * @param {string} filePath The filename to load.
- * @returns {ConfigData} The configuration object from the file.
- * @throws {Error} If the file cannot be read.
- * @private
+ * @fileoverview Defines environment settings and globals.
+ * @author Elan Shanker
*/
-function loadJSONConfigFile(filePath) {
- debug$2(`Loading JSON config file: ${filePath}`);
- try {
- return JSON.parse(stripComments__default["default"](readFile(filePath)));
- } catch (e) {
- debug$2(`Error reading JSON file: ${filePath}`);
- e.message = `Cannot read config file: ${filePath}\nError: ${e.message}`;
- e.messageTemplate = "failed-to-read-json";
- e.messageData = {
- path: filePath,
- message: e.message
- };
- throw e;
- }
-}
+//------------------------------------------------------------------------------
+// Helpers
+//------------------------------------------------------------------------------
/**
- * Loads a legacy (.eslintrc) configuration from a file.
- * @param {string} filePath The filename to load.
- * @returns {ConfigData} The configuration object from the file.
- * @throws {Error} If the file cannot be read.
- * @private
+ * Get the object that has difference.
+ * @param {Record<string,boolean>} current The newer object.
+ * @param {Record<string,boolean>} prev The older object.
+ * @returns {Record<string,boolean>} The difference object.
*/
-function loadLegacyConfigFile(filePath) {
- debug$2(`Loading legacy config file: ${filePath}`);
-
- // lazy load YAML to improve performance when not used
- const yaml = require$1("js-yaml");
+function getDiff(current, prev) {
+ const retv = {};
- try {
- return yaml.load(stripComments__default["default"](readFile(filePath))) || /* istanbul ignore next */ {};
- } catch (e) {
- debug$2("Error reading YAML file: %s\n%o", filePath, e);
- e.message = `Cannot read config file: ${filePath}\nError: ${e.message}`;
- throw e;
+ for (const [key, value] of Object.entries(current)) {
+ if (!Object.hasOwnProperty.call(prev, key)) {
+ retv[key] = value;
+ }
}
-}
-/**
- * Loads a JavaScript configuration from a file.
- * @param {string} filePath The filename to load.
- * @returns {ConfigData} The configuration object from the file.
- * @throws {Error} If the file cannot be read.
- * @private
- */
-function loadJSConfigFile(filePath) {
- debug$2(`Loading JS config file: ${filePath}`);
- try {
- return importFresh__default["default"](filePath);
- } catch (e) {
- debug$2(`Error reading JavaScript file: ${filePath}`);
- e.message = `Cannot read config file: ${filePath}\nError: ${e.message}`;
- throw e;
- }
+ return retv;
}
-/**
- * Loads a configuration from a package.json file.
- * @param {string} filePath The filename to load.
- * @returns {ConfigData} The configuration object from the file.
- * @throws {Error} If the file cannot be read.
- * @private
- */
-function loadPackageJSONConfigFile(filePath) {
- debug$2(`Loading package.json config file: ${filePath}`);
- try {
- const packageData = loadJSONConfigFile(filePath);
-
- if (!Object.hasOwnProperty.call(packageData, "eslintConfig")) {
- throw Object.assign(
- new Error("package.json file doesn't have 'eslintConfig' field."),
- { code: "ESLINT_CONFIG_FIELD_NOT_FOUND" }
- );
- }
+const newGlobals2015 = getDiff(globals__default["default"].es2015, globals__default["default"].es5); // 19 variables such as Promise, Map, ...
+const newGlobals2017 = {
+ Atomics: false,
+ SharedArrayBuffer: false
+};
+const newGlobals2020 = {
+ BigInt: false,
+ BigInt64Array: false,
+ BigUint64Array: false,
+ globalThis: false
+};
- return packageData.eslintConfig;
- } catch (e) {
- debug$2(`Error reading package.json file: ${filePath}`);
- e.message = `Cannot read config file: ${filePath}\nError: ${e.message}`;
- throw e;
- }
-}
+const newGlobals2021 = {
+ AggregateError: false,
+ FinalizationRegistry: false,
+ WeakRef: false
+};
-/**
- * Loads a `.eslintignore` from a file.
- * @param {string} filePath The filename to load.
- * @returns {string[]} The ignore patterns from the file.
- * @private
- */
-function loadESLintIgnoreFile(filePath) {
- debug$2(`Loading .eslintignore file: ${filePath}`);
+//------------------------------------------------------------------------------
+// Public Interface
+//------------------------------------------------------------------------------
- try {
- return readFile(filePath)
- .split(/\r?\n/gu)
- .filter(line => line.trim() !== "" && !line.startsWith("#"));
- } catch (e) {
- debug$2(`Error reading .eslintignore file: ${filePath}`);
- e.message = `Cannot read .eslintignore file: ${filePath}\nError: ${e.message}`;
- throw e;
- }
-}
+/** @type {Map<string, import("../lib/shared/types").Environment>} */
+var environments = new Map(Object.entries({
-/**
- * Creates an error to notify about a missing config to extend from.
- * @param {string} configName The name of the missing config.
- * @param {string} importerName The name of the config that imported the missing config
- * @param {string} messageTemplate The text template to source error strings from.
- * @returns {Error} The error object to throw
- * @private
- */
-function configInvalidError(configName, importerName, messageTemplate) {
- return Object.assign(
- new Error(`Failed to load config "${configName}" to extend from.`),
- {
- messageTemplate,
- messageData: { configName, importerName }
+ // Language
+ builtin: {
+ globals: globals__default["default"].es5
+ },
+ es6: {
+ globals: newGlobals2015,
+ parserOptions: {
+ ecmaVersion: 6
}
- );
-}
-
-/**
- * Loads a configuration file regardless of the source. Inspects the file path
- * to determine the correctly way to load the config file.
- * @param {string} filePath The path to the configuration.
- * @returns {ConfigData|null} The configuration information.
- * @private
- */
-function loadConfigFile(filePath) {
- switch (path__default["default"].extname(filePath)) {
- case ".js":
- case ".cjs":
- return loadJSConfigFile(filePath);
+ },
+ es2015: {
+ globals: newGlobals2015,
+ parserOptions: {
+ ecmaVersion: 6
+ }
+ },
+ es2017: {
+ globals: { ...newGlobals2015, ...newGlobals2017 },
+ parserOptions: {
+ ecmaVersion: 8
+ }
+ },
+ es2020: {
+ globals: { ...newGlobals2015, ...newGlobals2017, ...newGlobals2020 },
+ parserOptions: {
+ ecmaVersion: 11
+ }
+ },
+ es2021: {
+ globals: { ...newGlobals2015, ...newGlobals2017, ...newGlobals2020, ...newGlobals2021 },
+ parserOptions: {
+ ecmaVersion: 12
+ }
+ },
- case ".json":
- if (path__default["default"].basename(filePath) === "package.json") {
- return loadPackageJSONConfigFile(filePath);
+ // Platforms
+ browser: {
+ globals: globals__default["default"].browser
+ },
+ node: {
+ globals: globals__default["default"].node,
+ parserOptions: {
+ ecmaFeatures: {
+ globalReturn: true
}
- return loadJSONConfigFile(filePath);
-
- case ".yaml":
- case ".yml":
- return loadYAMLConfigFile(filePath);
-
- default:
- return loadLegacyConfigFile(filePath);
- }
-}
-
-/**
- * Write debug log.
- * @param {string} request The requested module name.
- * @param {string} relativeTo The file path to resolve the request relative to.
- * @param {string} filePath The resolved file path.
- * @returns {void}
- */
-function writeDebugLogForLoading(request, relativeTo, filePath) {
- /* istanbul ignore next */
- if (debug$2.enabled) {
- let nameAndVersion = null;
-
- try {
- const packageJsonPath = resolve(
- `${request}/package.json`,
- relativeTo
- );
- const { version = "unknown" } = require$1(packageJsonPath);
-
- nameAndVersion = `${request}@${version}`;
- } catch (error) {
- debug$2("package.json was not found:", error.message);
- nameAndVersion = request;
}
+ },
+ "shared-node-browser": {
+ globals: globals__default["default"]["shared-node-browser"]
+ },
+ worker: {
+ globals: globals__default["default"].worker
+ },
+ serviceworker: {
+ globals: globals__default["default"].serviceworker
+ },
- debug$2("Loaded: %s (%s)", nameAndVersion, filePath);
+ // Frameworks
+ commonjs: {
+ globals: globals__default["default"].commonjs,
+ parserOptions: {
+ ecmaFeatures: {
+ globalReturn: true
+ }
+ }
+ },
+ amd: {
+ globals: globals__default["default"].amd
+ },
+ mocha: {
+ globals: globals__default["default"].mocha
+ },
+ jasmine: {
+ globals: globals__default["default"].jasmine
+ },
+ jest: {
+ globals: globals__default["default"].jest
+ },
+ phantomjs: {
+ globals: globals__default["default"].phantomjs
+ },
+ jquery: {
+ globals: globals__default["default"].jquery
+ },
+ qunit: {
+ globals: globals__default["default"].qunit
+ },
+ prototypejs: {
+ globals: globals__default["default"].prototypejs
+ },
+ shelljs: {
+ globals: globals__default["default"].shelljs
+ },
+ meteor: {
+ globals: globals__default["default"].meteor
+ },
+ mongo: {
+ globals: globals__default["default"].mongo
+ },
+ protractor: {
+ globals: globals__default["default"].protractor
+ },
+ applescript: {
+ globals: globals__default["default"].applescript
+ },
+ nashorn: {
+ globals: globals__default["default"].nashorn
+ },
+ atomtest: {
+ globals: globals__default["default"].atomtest
+ },
+ embertest: {
+ globals: globals__default["default"].embertest
+ },
+ webextensions: {
+ globals: globals__default["default"].webextensions
+ },
+ greasemonkey: {
+ globals: globals__default["default"].greasemonkey
}
-}
+}));
/**
- * Create a new context with default values.
- * @param {ConfigArrayFactoryInternalSlots} slots The internal slots.
- * @param {"config" | "ignore" | "implicit-processor" | undefined} providedType The type of the current configuration. Default is `"config"`.
- * @param {string | undefined} providedName The name of the current configuration. Default is the relative path from `cwd` to `filePath`.
- * @param {string | undefined} providedFilePath The path to the current configuration. Default is empty string.
- * @param {string | undefined} providedMatchBasePath The type of the current configuration. Default is the directory of `filePath` or `cwd`.
- * @returns {ConfigArrayFactoryLoadingContext} The created context.
+ * @fileoverview Validates configs.
+ * @author Brandon Mills
*/
-function createContext(
- { cwd, resolvePluginsRelativeTo },
- providedType,
- providedName,
- providedFilePath,
- providedMatchBasePath
-) {
- const filePath = providedFilePath
- ? path__default["default"].resolve(cwd, providedFilePath)
- : "";
- const matchBasePath =
- (providedMatchBasePath && path__default["default"].resolve(cwd, providedMatchBasePath)) ||
- (filePath && path__default["default"].dirname(filePath)) ||
- cwd;
- const name =
- providedName ||
- (filePath && path__default["default"].relative(cwd, filePath)) ||
- "";
- const pluginBasePath =
- resolvePluginsRelativeTo ||
- (filePath && path__default["default"].dirname(filePath)) ||
- cwd;
- const type = providedType || "config";
- return { filePath, matchBasePath, name, pluginBasePath, type };
-}
+const ajv = ajvOrig();
-/**
- * Normalize a given plugin.
- * - Ensure the object to have four properties: configs, environments, processors, and rules.
- * - Ensure the object to not have other properties.
- * @param {Plugin} plugin The plugin to normalize.
- * @returns {Plugin} The normalized plugin.
- */
-function normalizePlugin(plugin) {
- return {
- configs: plugin.configs || {},
- environments: plugin.environments || {},
- processors: plugin.processors || {},
- rules: plugin.rules || {}
- };
-}
+const ruleValidators = new WeakMap();
+const noop = Function.prototype;
//------------------------------------------------------------------------------
-// Public Interface
+// Private
//------------------------------------------------------------------------------
+let validateSchema;
+const severityMap = {
+ error: 2,
+ warn: 1,
+ off: 0
+};
-/**
- * The factory of `ConfigArray` objects.
- */
-class ConfigArrayFactory {
-
- /**
- * Initialize this instance.
- * @param {ConfigArrayFactoryOptions} [options] The map for additional plugins.
- */
- constructor({
- additionalPluginPool = new Map(),
- cwd = process.cwd(),
- resolvePluginsRelativeTo,
- builtInRules,
- resolver = ModuleResolver,
- eslintAllPath,
- eslintRecommendedPath
- } = {}) {
- internalSlotsMap$1.set(this, {
- additionalPluginPool,
- cwd,
- resolvePluginsRelativeTo:
- resolvePluginsRelativeTo &&
- path__default["default"].resolve(cwd, resolvePluginsRelativeTo),
- builtInRules,
- resolver,
- eslintAllPath,
- eslintRecommendedPath
- });
- }
-
- /**
- * Create `ConfigArray` instance from a config data.
- * @param {ConfigData|null} configData The config data to create.
- * @param {Object} [options] The options.
- * @param {string} [options.basePath] The base path to resolve relative paths in `overrides[].files`, `overrides[].excludedFiles`, and `ignorePatterns`.
- * @param {string} [options.filePath] The path to this config data.
- * @param {string} [options.name] The config name.
- * @returns {ConfigArray} Loaded config.
- */
- create(configData, { basePath, filePath, name } = {}) {
- if (!configData) {
- return new ConfigArray();
- }
-
- const slots = internalSlotsMap$1.get(this);
- const ctx = createContext(slots, "config", name, filePath, basePath);
- const elements = this._normalizeConfigData(configData, ctx);
-
- return new ConfigArray(...elements);
- }
+const validated = new WeakSet();
- /**
- * Load a config file.
- * @param {string} filePath The path to a config file.
- * @param {Object} [options] The options.
- * @param {string} [options.basePath] The base path to resolve relative paths in `overrides[].files`, `overrides[].excludedFiles`, and `ignorePatterns`.
- * @param {string} [options.name] The config name.
- * @returns {ConfigArray} Loaded config.
- */
- loadFile(filePath, { basePath, name } = {}) {
- const slots = internalSlotsMap$1.get(this);
- const ctx = createContext(slots, "config", name, filePath, basePath);
+//-----------------------------------------------------------------------------
+// Exports
+//-----------------------------------------------------------------------------
- return new ConfigArray(...this._loadConfigData(ctx));
+class ConfigValidator {
+ constructor({ builtInRules = new Map() } = {}) {
+ this.builtInRules = builtInRules;
}
/**
- * Load the config file on a given directory if exists.
- * @param {string} directoryPath The path to a directory.
- * @param {Object} [options] The options.
- * @param {string} [options.basePath] The base path to resolve relative paths in `overrides[].files`, `overrides[].excludedFiles`, and `ignorePatterns`.
- * @param {string} [options.name] The config name.
- * @returns {ConfigArray} Loaded config. An empty `ConfigArray` if any config doesn't exist.
+ * Gets a complete options schema for a rule.
+ * @param {{create: Function, schema: (Array|null)}} rule A new-style rule object
+ * @returns {Object} JSON Schema for the rule's options.
*/
- loadInDirectory(directoryPath, { basePath, name } = {}) {
- const slots = internalSlotsMap$1.get(this);
-
- for (const filename of configFilenames) {
- const ctx = createContext(
- slots,
- "config",
- name,
- path__default["default"].join(directoryPath, filename),
- basePath
- );
-
- if (fs__default["default"].existsSync(ctx.filePath) && fs__default["default"].statSync(ctx.filePath).isFile()) {
- let configData;
+ getRuleOptionsSchema(rule) {
+ if (!rule) {
+ return null;
+ }
- try {
- configData = loadConfigFile(ctx.filePath);
- } catch (error) {
- if (!error || error.code !== "ESLINT_CONFIG_FIELD_NOT_FOUND") {
- throw error;
- }
- }
+ const schema = rule.schema || rule.meta && rule.meta.schema;
- if (configData) {
- debug$2(`Config file found: ${ctx.filePath}`);
- return new ConfigArray(
- ...this._normalizeConfigData(configData, ctx)
- );
- }
+ // Given a tuple of schemas, insert warning level at the beginning
+ if (Array.isArray(schema)) {
+ if (schema.length) {
+ return {
+ type: "array",
+ items: schema,
+ minItems: 0,
+ maxItems: schema.length
+ };
}
+ return {
+ type: "array",
+ minItems: 0,
+ maxItems: 0
+ };
+
}
- debug$2(`Config file not found on ${directoryPath}`);
- return new ConfigArray();
+ // Given a full schema, leave it alone
+ return schema || null;
}
/**
- * Check if a config file on a given directory exists or not.
- * @param {string} directoryPath The path to a directory.
- * @returns {string | null} The path to the found config file. If not found then null.
+ * Validates a rule's severity and returns the severity value. Throws an error if the severity is invalid.
+ * @param {options} options The given options for the rule.
+ * @returns {number|string} The rule's severity value
*/
- static getPathToConfigFileInDirectory(directoryPath) {
- for (const filename of configFilenames) {
- const filePath = path__default["default"].join(directoryPath, filename);
+ validateRuleSeverity(options) {
+ const severity = Array.isArray(options) ? options[0] : options;
+ const normSeverity = typeof severity === "string" ? severityMap[severity.toLowerCase()] : severity;
- if (fs__default["default"].existsSync(filePath)) {
- if (filename === "package.json") {
- try {
- loadPackageJSONConfigFile(filePath);
- return filePath;
- } catch { /* ignore */ }
- } else {
- return filePath;
- }
- }
+ if (normSeverity === 0 || normSeverity === 1 || normSeverity === 2) {
+ return normSeverity;
}
- return null;
- }
- /**
- * Load `.eslintignore` file.
- * @param {string} filePath The path to a `.eslintignore` file to load.
- * @returns {ConfigArray} Loaded config. An empty `ConfigArray` if any config doesn't exist.
- */
- loadESLintIgnore(filePath) {
- const slots = internalSlotsMap$1.get(this);
- const ctx = createContext(
- slots,
- "ignore",
- void 0,
- filePath,
- slots.cwd
- );
- const ignorePatterns = loadESLintIgnoreFile(ctx.filePath);
+ 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`);
- return new ConfigArray(
- ...this._normalizeESLintIgnoreData(ignorePatterns, ctx)
- );
}
/**
- * Load `.eslintignore` file in the current working directory.
- * @returns {ConfigArray} Loaded config. An empty `ConfigArray` if any config doesn't exist.
+ * Validates the non-severity options passed to a rule, based on its schema.
+ * @param {{create: Function}} rule The rule to validate
+ * @param {Array} localOptions The options for the rule, excluding severity
+ * @returns {void}
*/
- loadDefaultESLintIgnore() {
- const slots = internalSlotsMap$1.get(this);
- const eslintIgnorePath = path__default["default"].resolve(slots.cwd, ".eslintignore");
- const packageJsonPath = path__default["default"].resolve(slots.cwd, "package.json");
+ validateRuleSchema(rule, localOptions) {
+ if (!ruleValidators.has(rule)) {
+ const schema = this.getRuleOptionsSchema(rule);
- if (fs__default["default"].existsSync(eslintIgnorePath)) {
- return this.loadESLintIgnore(eslintIgnorePath);
+ if (schema) {
+ ruleValidators.set(rule, ajv.compile(schema));
+ }
}
- if (fs__default["default"].existsSync(packageJsonPath)) {
- const data = loadJSONConfigFile(packageJsonPath);
- if (Object.hasOwnProperty.call(data, "eslintIgnore")) {
- if (!Array.isArray(data.eslintIgnore)) {
- throw new Error("Package.json eslintIgnore property requires an array of paths");
- }
- const ctx = createContext(
- slots,
- "ignore",
- "eslintIgnore in package.json",
- packageJsonPath,
- slots.cwd
- );
+ const validateRule = ruleValidators.get(rule);
- return new ConfigArray(
- ...this._normalizeESLintIgnoreData(data.eslintIgnore, ctx)
- );
+ if (validateRule) {
+ validateRule(localOptions);
+ if (validateRule.errors) {
+ throw new Error(validateRule.errors.map(
+ error => `\tValue ${JSON.stringify(error.data)} ${error.message}.\n`
+ ).join(""));
}
}
-
- return new ConfigArray();
}
/**
- * Load a given config file.
- * @param {ConfigArrayFactoryLoadingContext} ctx The loading context.
- * @returns {IterableIterator<ConfigArrayElement>} Loaded config.
- * @private
+ * Validates a rule's options against its schema.
+ * @param {{create: Function}|null} rule The rule that the config is being validated for
+ * @param {string} ruleId The rule's unique name.
+ * @param {Array|number} options The given options for the rule.
+ * @param {string|null} source The name of the configuration source to report in any errors. If null or undefined,
+ * no source is prepended to the message.
+ * @returns {void}
*/
- _loadConfigData(ctx) {
- return this._normalizeConfigData(loadConfigFile(ctx.filePath), ctx);
- }
+ validateRuleOptions(rule, ruleId, options, source = null) {
+ try {
+ const severity = this.validateRuleSeverity(options);
- /**
- * Normalize a given `.eslintignore` data to config array elements.
- * @param {string[]} ignorePatterns The patterns to ignore files.
- * @param {ConfigArrayFactoryLoadingContext} ctx The loading context.
- * @returns {IterableIterator<ConfigArrayElement>} The normalized config.
- * @private
- */
- *_normalizeESLintIgnoreData(ignorePatterns, ctx) {
- const elements = this._normalizeObjectConfigData(
- { ignorePatterns },
- ctx
- );
+ if (severity !== 0) {
+ this.validateRuleSchema(rule, Array.isArray(options) ? options.slice(1) : []);
+ }
+ } catch (err) {
+ const enhancedMessage = `Configuration for rule "${ruleId}" is invalid:\n${err.message}`;
- // Set `ignorePattern.loose` flag for backward compatibility.
- for (const element of elements) {
- if (element.ignorePattern) {
- element.ignorePattern.loose = true;
+ if (typeof source === "string") {
+ throw new Error(`${source}:\n\t${enhancedMessage}`);
+ } else {
+ throw new Error(enhancedMessage);
}
- yield element;
}
}
/**
- * Normalize a given config to an array.
- * @param {ConfigData} configData The config data to normalize.
- * @param {ConfigArrayFactoryLoadingContext} ctx The loading context.
- * @returns {IterableIterator<ConfigArrayElement>} The normalized config.
- * @private
+ * Validates an environment object
+ * @param {Object} environment The environment config object to validate.
+ * @param {string} source The name of the configuration source to report in any errors.
+ * @param {function(envId:string): Object} [getAdditionalEnv] A map from strings to loaded environments.
+ * @returns {void}
*/
- _normalizeConfigData(configData, ctx) {
- const validator = new ConfigValidator();
-
- validator.validateConfigSchema(configData, ctx.name || ctx.filePath);
- return this._normalizeObjectConfigData(configData, ctx);
- }
+ validateEnvironment(
+ environment,
+ source,
+ getAdditionalEnv = noop
+ ) {
- /**
- * Normalize a given config to an array.
- * @param {ConfigData|OverrideConfigData} configData The config data to normalize.
- * @param {ConfigArrayFactoryLoadingContext} ctx The loading context.
- * @returns {IterableIterator<ConfigArrayElement>} The normalized config.
- * @private
- */
- *_normalizeObjectConfigData(configData, ctx) {
- const { files, excludedFiles, ...configBody } = configData;
- const criteria = OverrideTester.create(
- files,
- excludedFiles,
- ctx.matchBasePath
- );
- const elements = this._normalizeObjectConfigDataBody(configBody, ctx);
+ // not having an environment is ok
+ if (!environment) {
+ return;
+ }
- // Apply the criteria to every element.
- for (const element of elements) {
+ Object.keys(environment).forEach(id => {
+ const env = getAdditionalEnv(id) || environments.get(id) || null;
- /*
- * Merge the criteria.
- * This is for the `overrides` entries that came from the
- * configurations of `overrides[].extends`.
- */
- element.criteria = OverrideTester.and(criteria, element.criteria);
+ if (!env) {
+ const message = `${source}:\n\tEnvironment key "${id}" is unknown\n`;
- /*
- * Remove `root` property to ignore `root` settings which came from
- * `extends` in `overrides`.
- */
- if (element.criteria) {
- element.root = void 0;
+ throw new Error(message);
}
-
- yield element;
- }
+ });
}
/**
- * Normalize a given config to an array.
- * @param {ConfigData} configData The config data to normalize.
- * @param {ConfigArrayFactoryLoadingContext} ctx The loading context.
- * @returns {IterableIterator<ConfigArrayElement>} The normalized config.
- * @private
+ * Validates a rules config object
+ * @param {Object} rulesConfig The rules config object to validate.
+ * @param {string} source The name of the configuration source to report in any errors.
+ * @param {function(ruleId:string): Object} getAdditionalRule A map from strings to loaded rules
+ * @returns {void}
*/
- *_normalizeObjectConfigDataBody(
- {
- env,
- extends: extend,
- globals,
- ignorePatterns,
- noInlineConfig,
- parser: parserName,
- parserOptions,
- plugins: pluginList,
- processor,
- reportUnusedDisableDirectives,
- root,
- rules,
- settings,
- overrides: overrideList = []
- },
- ctx
+ validateRules(
+ rulesConfig,
+ source,
+ getAdditionalRule = noop
) {
- const extendList = Array.isArray(extend) ? extend : [extend];
- const ignorePattern = ignorePatterns && new IgnorePattern(
- Array.isArray(ignorePatterns) ? ignorePatterns : [ignorePatterns],
- ctx.matchBasePath
- );
-
- // Flatten `extends`.
- for (const extendName of extendList.filter(Boolean)) {
- yield* this._loadExtends(extendName, ctx);
- }
-
- // Load parser & plugins.
- const parser = parserName && this._loadParser(parserName, ctx);
- const plugins = pluginList && this._loadPlugins(pluginList, ctx);
-
- // Yield pseudo config data for file extension processors.
- if (plugins) {
- yield* this._takeFileExtensionProcessors(plugins, ctx);
+ if (!rulesConfig) {
+ return;
}
- // Yield the config data except `extends` and `overrides`.
- yield {
-
- // Debug information.
- type: ctx.type,
- name: ctx.name,
- filePath: ctx.filePath,
+ Object.keys(rulesConfig).forEach(id => {
+ const rule = getAdditionalRule(id) || this.builtInRules.get(id) || null;
- // Config data.
- criteria: null,
- env,
- globals,
- ignorePattern,
- noInlineConfig,
- parser,
- parserOptions,
- plugins,
- processor,
- reportUnusedDisableDirectives,
- root,
- rules,
- settings
- };
+ this.validateRuleOptions(rule, id, rulesConfig[id], source);
+ });
+ }
- // Flatten `overries`.
- for (let i = 0; i < overrideList.length; ++i) {
- yield* this._normalizeObjectConfigData(
- overrideList[i],
- { ...ctx, name: `${ctx.name}#overrides[${i}]` }
- );
+ /**
+ * Validates a `globals` section of a config file
+ * @param {Object} globalsConfig The `globals` section
+ * @param {string|null} source The name of the configuration source to report in the event of an error.
+ * @returns {void}
+ */
+ validateGlobals(globalsConfig, source = null) {
+ if (!globalsConfig) {
+ return;
}
+
+ Object.entries(globalsConfig)
+ .forEach(([configuredGlobal, configuredValue]) => {
+ try {
+ normalizeConfigGlobal(configuredValue);
+ } catch (err) {
+ throw new Error(`ESLint configuration of global '${configuredGlobal}' in ${source} is invalid:\n${err.message}`);
+ }
+ });
}
/**
- * Load configs of an element in `extends`.
- * @param {string} extendName The name of a base config.
- * @param {ConfigArrayFactoryLoadingContext} ctx The loading context.
- * @returns {IterableIterator<ConfigArrayElement>} The normalized config.
- * @private
+ * Validate `processor` configuration.
+ * @param {string|undefined} processorName The processor name.
+ * @param {string} source The name of config file.
+ * @param {function(id:string): Processor} getProcessor The getter of defined processors.
+ * @returns {void}
+ */
+ validateProcessor(processorName, source, getProcessor) {
+ if (processorName && !getProcessor(processorName)) {
+ throw new Error(`ESLint configuration of processor in '${source}' is invalid: '${processorName}' was not found.`);
+ }
+ }
+
+ /**
+ * Formats an array of schema validation errors.
+ * @param {Array} errors An array of error messages to format.
+ * @returns {string} Formatted error message
*/
- _loadExtends(extendName, ctx) {
- debug$2("Loading {extends:%j} relative to %s", extendName, ctx.filePath);
- try {
- if (extendName.startsWith("eslint:")) {
- return this._loadExtendedBuiltInConfig(extendName, ctx);
+ formatErrors(errors) {
+ return errors.map(error => {
+ if (error.keyword === "additionalProperties") {
+ const formattedPropertyPath = error.dataPath.length ? `${error.dataPath.slice(1)}.${error.params.additionalProperty}` : error.params.additionalProperty;
+
+ return `Unexpected top-level property "${formattedPropertyPath}"`;
}
- if (extendName.startsWith("plugin:")) {
- return this._loadExtendedPluginConfig(extendName, ctx);
+ if (error.keyword === "type") {
+ const formattedField = error.dataPath.slice(1);
+ const formattedExpectedType = Array.isArray(error.schema) ? error.schema.join("/") : error.schema;
+ const formattedValue = JSON.stringify(error.data);
+
+ return `Property "${formattedField}" is the wrong type (expected ${formattedExpectedType} but got \`${formattedValue}\`)`;
}
- return this._loadExtendedShareableConfig(extendName, ctx);
- } catch (error) {
- error.message += `\nReferenced from: ${ctx.filePath || ctx.name}`;
- throw error;
- }
+
+ const field = error.dataPath[0] === "." ? error.dataPath.slice(1) : error.dataPath;
+
+ return `"${field}" ${error.message}. Value: ${JSON.stringify(error.data)}`;
+ }).map(message => `\t- ${message}.\n`).join("");
}
/**
- * Load configs of an element in `extends`.
- * @param {string} extendName The name of a base config.
- * @param {ConfigArrayFactoryLoadingContext} ctx The loading context.
- * @returns {IterableIterator<ConfigArrayElement>} The normalized config.
- * @private
+ * Validates the top level properties of the config object.
+ * @param {Object} config The config object to validate.
+ * @param {string} source The name of the configuration source to report in any errors.
+ * @returns {void}
*/
- _loadExtendedBuiltInConfig(extendName, ctx) {
- const { eslintAllPath, eslintRecommendedPath } = internalSlotsMap$1.get(this);
+ validateConfigSchema(config, source = null) {
+ validateSchema = validateSchema || ajv.compile(configSchema);
- if (extendName === "eslint:recommended") {
- return this._loadConfigData({
- ...ctx,
- filePath: eslintRecommendedPath,
- name: `${ctx.name} » ${extendName}`
- });
- }
- if (extendName === "eslint:all") {
- return this._loadConfigData({
- ...ctx,
- filePath: eslintAllPath,
- name: `${ctx.name} » ${extendName}`
- });
+ if (!validateSchema(config)) {
+ throw new Error(`ESLint configuration in ${source} is invalid:\n${this.formatErrors(validateSchema.errors)}`);
}
- throw configInvalidError(extendName, ctx.name, "extend-config-missing");
+ if (Object.hasOwnProperty.call(config, "ecmaFeatures")) {
+ emitDeprecationWarning(source, "ESLINT_LEGACY_ECMAFEATURES");
+ }
}
/**
- * Load configs of an element in `extends`.
- * @param {string} extendName The name of a base config.
- * @param {ConfigArrayFactoryLoadingContext} ctx The loading context.
- * @returns {IterableIterator<ConfigArrayElement>} The normalized config.
- * @private
+ * Validates an entire config object.
+ * @param {Object} config The config object to validate.
+ * @param {string} source The name of the configuration source to report in any errors.
+ * @param {function(ruleId:string): Object} [getAdditionalRule] A map from strings to loaded rules.
+ * @param {function(envId:string): Object} [getAdditionalEnv] A map from strings to loaded envs.
+ * @returns {void}
*/
- _loadExtendedPluginConfig(extendName, ctx) {
- const slashIndex = extendName.lastIndexOf("/");
+ validate(config, source, getAdditionalRule, getAdditionalEnv) {
+ this.validateConfigSchema(config, source);
+ this.validateRules(config.rules, source, getAdditionalRule);
+ this.validateEnvironment(config.env, source, getAdditionalEnv);
+ this.validateGlobals(config.globals, source);
- if (slashIndex === -1) {
- throw configInvalidError(extendName, ctx.filePath, "plugin-invalid");
+ for (const override of config.overrides || []) {
+ this.validateRules(override.rules, source, getAdditionalRule);
+ this.validateEnvironment(override.env, source, getAdditionalEnv);
+ this.validateGlobals(config.globals, source);
}
+ }
- const pluginName = extendName.slice("plugin:".length, slashIndex);
- const configName = extendName.slice(slashIndex + 1);
+ /**
+ * Validate config array object.
+ * @param {ConfigArray} configArray The config array to validate.
+ * @returns {void}
+ */
+ validateConfigArray(configArray) {
+ const getPluginEnv = Map.prototype.get.bind(configArray.pluginEnvironments);
+ const getPluginProcessor = Map.prototype.get.bind(configArray.pluginProcessors);
+ const getPluginRule = Map.prototype.get.bind(configArray.pluginRules);
- if (isFilePath(pluginName)) {
- throw new Error("'extends' cannot use a file path for plugins.");
+ // Validate.
+ for (const element of configArray) {
+ if (validated.has(element)) {
+ continue;
+ }
+ validated.add(element);
+
+ this.validateEnvironment(element.env, element.name, getPluginEnv);
+ this.validateGlobals(element.globals, element.name);
+ this.validateProcessor(element.processor, element.name, getPluginProcessor);
+ this.validateRules(element.rules, element.name, getPluginRule);
}
+ }
- const plugin = this._loadPlugin(pluginName, ctx);
- const configData =
- plugin.definition &&
- plugin.definition.configs[configName];
+}
- if (configData) {
- return this._normalizeConfigData(configData, {
- ...ctx,
- filePath: plugin.filePath || ctx.filePath,
- name: `${ctx.name} » plugin:${plugin.id}/${configName}`
- });
- }
+/**
+ * @fileoverview Common helpers for naming of plugins, formatters and configs
+ */
- throw plugin.error || configInvalidError(extendName, ctx.filePath, "extend-config-missing");
- }
+const NAMESPACE_REGEX = /^@.*\//iu;
+
+/**
+ * Brings package name to correct format based on prefix
+ * @param {string} name The name of the package.
+ * @param {string} prefix Can be either "eslint-plugin", "eslint-config" or "eslint-formatter"
+ * @returns {string} Normalized name of the package
+ * @private
+ */
+function normalizePackageName(name, prefix) {
+ let normalizedName = name;
/**
- * Load configs of an element in `extends`.
- * @param {string} extendName The name of a base config.
- * @param {ConfigArrayFactoryLoadingContext} ctx The loading context.
- * @returns {IterableIterator<ConfigArrayElement>} The normalized config.
- * @private
+ * On Windows, name can come in with Windows slashes instead of Unix slashes.
+ * Normalize to Unix first to avoid errors later on.
+ * https://github.com/eslint/eslint/issues/5644
*/
- _loadExtendedShareableConfig(extendName, ctx) {
- const { cwd, resolver } = internalSlotsMap$1.get(this);
- const relativeTo = ctx.filePath || path__default["default"].join(cwd, "__placeholder__.js");
- let request;
+ if (normalizedName.includes("\\")) {
+ normalizedName = normalizedName.replace(/\\/gu, "/");
+ }
- if (isFilePath(extendName)) {
- request = extendName;
- } else if (extendName.startsWith(".")) {
- request = `./${extendName}`; // For backward compatibility. A ton of tests depended on this behavior.
- } else {
- request = normalizePackageName(
- extendName,
- "eslint-config"
- );
+ if (normalizedName.charAt(0) === "@") {
+
+ /**
+ * it's a scoped package
+ * package name is the prefix, or just a username
+ */
+ const scopedPackageShortcutRegex = new RegExp(`^(@[^/]+)(?:/(?:${prefix})?)?$`, "u"),
+ scopedPackageNameRegex = new RegExp(`^${prefix}(-|$)`, "u");
+
+ if (scopedPackageShortcutRegex.test(normalizedName)) {
+ normalizedName = normalizedName.replace(scopedPackageShortcutRegex, `$1/${prefix}`);
+ } else if (!scopedPackageNameRegex.test(normalizedName.split("/")[1])) {
+
+ /**
+ * for scoped packages, insert the prefix after the first / unless
+ * the path is already @scope/eslint or @scope/eslint-xxx-yyy
+ */
+ normalizedName = normalizedName.replace(/^@([^/]+)\/(.*)$/u, `@$1/${prefix}-$2`);
}
+ } else if (!normalizedName.startsWith(`${prefix}-`)) {
+ normalizedName = `${prefix}-${normalizedName}`;
+ }
- let filePath;
+ return normalizedName;
+}
- try {
- filePath = resolver.resolve(request, relativeTo);
- } catch (error) {
- /* istanbul ignore else */
- if (error && error.code === "MODULE_NOT_FOUND") {
- throw configInvalidError(extendName, ctx.filePath, "extend-config-missing");
- }
- throw error;
+/**
+ * Removes the prefix from a fullname.
+ * @param {string} fullname The term which may have the prefix.
+ * @param {string} prefix The prefix to remove.
+ * @returns {string} The term without prefix.
+ */
+function getShorthandName(fullname, prefix) {
+ if (fullname[0] === "@") {
+ let matchResult = new RegExp(`^(@[^/]+)/${prefix}$`, "u").exec(fullname);
+
+ if (matchResult) {
+ return matchResult[1];
}
- writeDebugLogForLoading(request, relativeTo, filePath);
- return this._loadConfigData({
- ...ctx,
- filePath,
- name: `${ctx.name} » ${request}`
- });
+ matchResult = new RegExp(`^(@[^/]+)/${prefix}-(.+)$`, "u").exec(fullname);
+ if (matchResult) {
+ return `${matchResult[1]}/${matchResult[2]}`;
+ }
+ } else if (fullname.startsWith(`${prefix}-`)) {
+ return fullname.slice(prefix.length + 1);
}
- /**
- * Load given plugins.
- * @param {string[]} names The plugin names to load.
- * @param {ConfigArrayFactoryLoadingContext} ctx The loading context.
- * @returns {Record<string,DependentPlugin>} The loaded parser.
- * @private
- */
- _loadPlugins(names, ctx) {
- return names.reduce((map, name) => {
- if (isFilePath(name)) {
- throw new Error("Plugins array cannot includes file paths.");
- }
- const plugin = this._loadPlugin(name, ctx);
+ return fullname;
+}
- map[plugin.id] = plugin;
+/**
+ * Gets the scope (namespace) of a term.
+ * @param {string} term The term which may have the namespace.
+ * @returns {string} The namespace of the term if it has one.
+ */
+function getNamespaceFromTerm(term) {
+ const match = term.match(NAMESPACE_REGEX);
- return map;
- }, {});
+ return match ? match[0] : "";
+}
+
+var naming = {
+ __proto__: null,
+ normalizePackageName: normalizePackageName,
+ getShorthandName: getShorthandName,
+ getNamespaceFromTerm: getNamespaceFromTerm
+};
+
+/**
+ * Utility for resolving a module relative to another module
+ * @author Teddy Katz
+ */
+
+/*
+ * `Module.createRequire` is added in v12.2.0. It supports URL as well.
+ * We only support the case where the argument is a filepath, not a URL.
+ */
+const createRequire = Module__default["default"].createRequire;
+
+/**
+ * Resolves a Node module relative to another module
+ * @param {string} moduleName The name of a Node module, or a path to a Node module.
+ * @param {string} relativeToPath An absolute path indicating the module that `moduleName` should be resolved relative to. This must be
+ * a file rather than a directory, but the file need not actually exist.
+ * @returns {string} The absolute path that would result from calling `require.resolve(moduleName)` in a file located at `relativeToPath`
+ */
+function resolve(moduleName, relativeToPath) {
+ try {
+ return createRequire(relativeToPath).resolve(moduleName);
+ } catch (error) {
+
+ // This `if` block is for older Node.js than 12.0.0. We can remove this block in the future.
+ if (
+ typeof error === "object" &&
+ error !== null &&
+ error.code === "MODULE_NOT_FOUND" &&
+ !error.requireStack &&
+ error.message.includes(moduleName)
+ ) {
+ error.message += `\nRequire stack:\n- ${relativeToPath}`;
+ }
+ throw error;
}
+}
- /**
- * Load a given parser.
- * @param {string} nameOrPath The package name or the path to a parser file.
- * @param {ConfigArrayFactoryLoadingContext} ctx The loading context.
- * @returns {DependentParser} The loaded parser.
- */
- _loadParser(nameOrPath, ctx) {
- debug$2("Loading parser %j from %s", nameOrPath, ctx.filePath);
+var ModuleResolver = {
+ __proto__: null,
+ resolve: resolve
+};
- const { cwd, resolver } = internalSlotsMap$1.get(this);
- const relativeTo = ctx.filePath || path__default["default"].join(cwd, "__placeholder__.js");
+/**
+ * @fileoverview `IgnorePattern` class.
+ *
+ * `IgnorePattern` class has the set of glob patterns and the base path.
+ *
+ * It provides two static methods.
+ *
+ * - `IgnorePattern.createDefaultIgnore(cwd)`
+ * Create the default predicate function.
+ * - `IgnorePattern.createIgnore(ignorePatterns)`
+ * Create the predicate function from multiple `IgnorePattern` objects.
+ *
+ * It provides two properties and a method.
+ *
+ * - `patterns`
+ * The glob patterns that ignore to lint.
+ * - `basePath`
+ * The base path of the glob patterns. If absolute paths existed in the
+ * glob patterns, those are handled as relative paths to the base path.
+ * - `getPatternsRelativeTo(basePath)`
+ * Get `patterns` as modified for a given base path. It modifies the
+ * absolute paths in the patterns as prepending the difference of two base
+ * paths.
+ *
+ * `ConfigArrayFactory` creates `IgnorePattern` objects when it processes
+ * `ignorePatterns` properties.
+ *
+ * @author Toru Nagashima <https://github.com/mysticatea>
+ */
- try {
- const filePath = resolver.resolve(nameOrPath, relativeTo);
+const debug$3 = debugOrig__default["default"]("eslintrc:ignore-pattern");
- writeDebugLogForLoading(nameOrPath, relativeTo, filePath);
+/** @typedef {ReturnType<import("ignore").default>} Ignore */
- return new ConfigDependency({
- definition: require$1(filePath),
- filePath,
- id: nameOrPath,
- importerName: ctx.name,
- importerPath: ctx.filePath
- });
- } catch (error) {
+//------------------------------------------------------------------------------
+// Helpers
+//------------------------------------------------------------------------------
- // If the parser name is "espree", load the espree of ESLint.
- if (nameOrPath === "espree") {
- debug$2("Fallback espree.");
- return new ConfigDependency({
- definition: require$1("espree"),
- filePath: require$1.resolve("espree"),
- id: nameOrPath,
- importerName: ctx.name,
- importerPath: ctx.filePath
- });
- }
+/**
+ * Get the path to the common ancestor directory of given paths.
+ * @param {string[]} sourcePaths The paths to calculate the common ancestor.
+ * @returns {string} The path to the common ancestor directory.
+ */
+function getCommonAncestorPath(sourcePaths) {
+ let result = sourcePaths[0];
- debug$2("Failed to load parser '%s' declared in '%s'.", nameOrPath, ctx.name);
- error.message = `Failed to load parser '${nameOrPath}' declared in '${ctx.name}': ${error.message}`;
+ for (let i = 1; i < sourcePaths.length; ++i) {
+ const a = result;
+ const b = sourcePaths[i];
- return new ConfigDependency({
- error,
- id: nameOrPath,
- importerName: ctx.name,
- importerPath: ctx.filePath
- });
+ // Set the shorter one (it's the common ancestor if one includes the other).
+ result = a.length < b.length ? a : b;
+
+ // Set the common ancestor.
+ for (let j = 0, lastSepPos = 0; j < a.length && j < b.length; ++j) {
+ if (a[j] !== b[j]) {
+ result = a.slice(0, lastSepPos);
+ break;
+ }
+ if (a[j] === path__default["default"].sep) {
+ lastSepPos = j;
+ }
}
}
- /**
- * Load a given plugin.
- * @param {string} name The plugin name to load.
- * @param {ConfigArrayFactoryLoadingContext} ctx The loading context.
- * @returns {DependentPlugin} The loaded plugin.
- * @private
- */
- _loadPlugin(name, ctx) {
- debug$2("Loading plugin %j from %s", name, ctx.filePath);
+ let resolvedResult = result || path__default["default"].sep;
- const { additionalPluginPool, resolver } = internalSlotsMap$1.get(this);
- const request = normalizePackageName(name, "eslint-plugin");
- const id = getShorthandName(request, "eslint-plugin");
- const relativeTo = path__default["default"].join(ctx.pluginBasePath, "__placeholder__.js");
+ // if Windows common ancestor is root of drive must have trailing slash to be absolute.
+ if (resolvedResult && resolvedResult.endsWith(":") && process.platform === "win32") {
+ resolvedResult += path__default["default"].sep;
+ }
+ return resolvedResult;
+}
- if (name.match(/\s+/u)) {
- const error = Object.assign(
- new Error(`Whitespace found in plugin name '${name}'`),
- {
- messageTemplate: "whitespace-found",
- messageData: { pluginName: request }
- }
- );
+/**
+ * Make relative path.
+ * @param {string} from The source path to get relative path.
+ * @param {string} to The destination path to get relative path.
+ * @returns {string} The relative path.
+ */
+function relative(from, to) {
+ const relPath = path__default["default"].relative(from, to);
- return new ConfigDependency({
- error,
- id,
- importerName: ctx.name,
- importerPath: ctx.filePath
- });
- }
+ if (path__default["default"].sep === "/") {
+ return relPath;
+ }
+ return relPath.split(path__default["default"].sep).join("/");
+}
- // Check for additional pool.
- const plugin =
- additionalPluginPool.get(request) ||
- additionalPluginPool.get(id);
+/**
+ * Get the trailing slash if existed.
+ * @param {string} filePath The path to check.
+ * @returns {string} The trailing slash if existed.
+ */
+function dirSuffix(filePath) {
+ const isDir = (
+ filePath.endsWith(path__default["default"].sep) ||
+ (process.platform === "win32" && filePath.endsWith("/"))
+ );
- if (plugin) {
- return new ConfigDependency({
- definition: normalizePlugin(plugin),
- filePath: "", // It's unknown where the plugin came from.
- id,
- importerName: ctx.name,
- importerPath: ctx.filePath
- });
- }
+ return isDir ? "/" : "";
+}
+
+const DefaultPatterns = Object.freeze(["/**/node_modules/*"]);
+const DotPatterns = Object.freeze([".*", "!.eslintrc.*", "!../"]);
+
+//------------------------------------------------------------------------------
+// Public
+//------------------------------------------------------------------------------
+
+class IgnorePattern {
+
+ /**
+ * The default patterns.
+ * @type {string[]}
+ */
+ static get DefaultPatterns() {
+ return DefaultPatterns;
+ }
+
+ /**
+ * Create the default predicate function.
+ * @param {string} cwd The current working directory.
+ * @returns {((filePath:string, dot:boolean) => boolean) & {basePath:string; patterns:string[]}}
+ * The preficate function.
+ * The first argument is an absolute path that is checked.
+ * The second argument is the flag to not ignore dotfiles.
+ * If the predicate function returned `true`, it means the path should be ignored.
+ */
+ static createDefaultIgnore(cwd) {
+ return this.createIgnore([new IgnorePattern(DefaultPatterns, cwd)]);
+ }
+
+ /**
+ * Create the predicate function from multiple `IgnorePattern` objects.
+ * @param {IgnorePattern[]} ignorePatterns The list of ignore patterns.
+ * @returns {((filePath:string, dot?:boolean) => boolean) & {basePath:string; patterns:string[]}}
+ * The preficate function.
+ * The first argument is an absolute path that is checked.
+ * The second argument is the flag to not ignore dotfiles.
+ * If the predicate function returned `true`, it means the path should be ignored.
+ */
+ static createIgnore(ignorePatterns) {
+ debug$3("Create with: %o", ignorePatterns);
+
+ const basePath = getCommonAncestorPath(ignorePatterns.map(p => p.basePath));
+ const patterns = [].concat(
+ ...ignorePatterns.map(p => p.getPatternsRelativeTo(basePath))
+ );
+ const ig = ignore__default["default"]().add([...DotPatterns, ...patterns]);
+ const dotIg = ignore__default["default"]().add(patterns);
- let filePath;
- let error;
+ debug$3(" processed: %o", { basePath, patterns });
- try {
- filePath = resolver.resolve(request, relativeTo);
- } catch (resolveError) {
- error = resolveError;
- /* istanbul ignore else */
- if (error && error.code === "MODULE_NOT_FOUND") {
- error.messageTemplate = "plugin-missing";
- error.messageData = {
- pluginName: request,
- resolvePluginsRelativeTo: ctx.pluginBasePath,
- importerName: ctx.name
- };
- }
- }
+ return Object.assign(
+ (filePath, dot = false) => {
+ assert__default["default"](path__default["default"].isAbsolute(filePath), "'filePath' should be an absolute path.");
+ const relPathRaw = relative(basePath, filePath);
+ const relPath = relPathRaw && (relPathRaw + dirSuffix(filePath));
+ const adoptedIg = dot ? dotIg : ig;
+ const result = relPath !== "" && adoptedIg.ignores(relPath);
- if (filePath) {
- try {
- writeDebugLogForLoading(request, relativeTo, filePath);
+ debug$3("Check", { filePath, dot, relativePath: relPath, result });
+ return result;
+ },
+ { basePath, patterns }
+ );
+ }
- const startTime = Date.now();
- const pluginDefinition = require$1(filePath);
+ /**
+ * Initialize a new `IgnorePattern` instance.
+ * @param {string[]} patterns The glob patterns that ignore to lint.
+ * @param {string} basePath The base path of `patterns`.
+ */
+ constructor(patterns, basePath) {
+ assert__default["default"](path__default["default"].isAbsolute(basePath), "'basePath' should be an absolute path.");
- debug$2(`Plugin ${filePath} loaded in: ${Date.now() - startTime}ms`);
+ /**
+ * The glob patterns that ignore to lint.
+ * @type {string[]}
+ */
+ this.patterns = patterns;
- return new ConfigDependency({
- definition: normalizePlugin(pluginDefinition),
- filePath,
- id,
- importerName: ctx.name,
- importerPath: ctx.filePath
- });
- } catch (loadError) {
- error = loadError;
- }
- }
+ /**
+ * The base path of `patterns`.
+ * @type {string}
+ */
+ this.basePath = basePath;
- debug$2("Failed to load plugin '%s' declared in '%s'.", name, ctx.name);
- error.message = `Failed to load plugin '${name}' declared in '${ctx.name}': ${error.message}`;
- return new ConfigDependency({
- error,
- id,
- importerName: ctx.name,
- importerPath: ctx.filePath
- });
+ /**
+ * If `true` then patterns which don't start with `/` will match the paths to the outside of `basePath`. Defaults to `false`.
+ *
+ * It's set `true` for `.eslintignore`, `package.json`, and `--ignore-path` for backward compatibility.
+ * It's `false` as-is for `ignorePatterns` property in config files.
+ * @type {boolean}
+ */
+ this.loose = false;
}
/**
- * Take file expression processors as config array elements.
- * @param {Record<string,DependentPlugin>} plugins The plugin definitions.
- * @param {ConfigArrayFactoryLoadingContext} ctx The loading context.
- * @returns {IterableIterator<ConfigArrayElement>} The config array elements of file expression processors.
- * @private
+ * Get `patterns` as modified for a given base path. It modifies the
+ * absolute paths in the patterns as prepending the difference of two base
+ * paths.
+ * @param {string} newBasePath The base path.
+ * @returns {string[]} Modifired patterns.
*/
- *_takeFileExtensionProcessors(plugins, ctx) {
- for (const pluginId of Object.keys(plugins)) {
- const processors =
- plugins[pluginId] &&
- plugins[pluginId].definition &&
- plugins[pluginId].definition.processors;
+ getPatternsRelativeTo(newBasePath) {
+ assert__default["default"](path__default["default"].isAbsolute(newBasePath), "'newBasePath' should be an absolute path.");
+ const { basePath, loose, patterns } = this;
- if (!processors) {
- continue;
- }
+ if (newBasePath === basePath) {
+ return patterns;
+ }
+ const prefix = `/${relative(newBasePath, basePath)}`;
- for (const processorId of Object.keys(processors)) {
- if (processorId.startsWith(".")) {
- yield* this._normalizeObjectConfigData(
- {
- files: [`*${processorId}`],
- processor: `${pluginId}/${processorId}`
- },
- {
- ...ctx,
- type: "implicit-processor",
- name: `${ctx.name}#processors["${pluginId}/${processorId}"]`
- }
- );
- }
+ return patterns.map(pattern => {
+ const negative = pattern.startsWith("!");
+ const head = negative ? "!" : "";
+ const body = negative ? pattern.slice(1) : pattern;
+
+ if (body.startsWith("/") || body.startsWith("../")) {
+ return `${head}${prefix}${body}`;
}
- }
+ return loose ? pattern : `${head}${prefix}/**/${body}`;
+ });
}
}
/**
- * @fileoverview `CascadingConfigArrayFactory` class.
+ * @fileoverview `ExtractedConfig` class.
*
- * `CascadingConfigArrayFactory` class has a responsibility:
+ * `ExtractedConfig` class expresses a final configuration for a specific file.
*
- * 1. Handles cascading of config files.
+ * It provides one method.
*
- * It provides two methods:
+ * - `toCompatibleObjectAsConfigFileContent()`
+ * Convert this configuration to the compatible object as the content of
+ * config files. It converts the loaded parser and plugins to strings.
+ * `CLIEngine#getConfigForFile(filePath)` method uses this method.
*
- * - `getConfigArrayForFile(filePath)`
- * Get the corresponded configuration of a given file. This method doesn't
- * throw even if the given file didn't exist.
- * - `clearCache()`
- * Clear the internal cache. You have to call this method when
- * `additionalPluginPool` was updated if `baseConfig` or `cliConfig` depends
- * on the additional plugins. (`CLIEngine#addPlugin()` method calls this.)
+ * `ConfigArray#extractConfig(filePath)` creates a `ExtractedConfig` instance.
*
* @author Toru Nagashima <https://github.com/mysticatea>
*/
-const debug$1 = debugOrig__default["default"]("eslintrc:cascading-config-array-factory");
-
-//------------------------------------------------------------------------------
-// Helpers
-//------------------------------------------------------------------------------
-
-// Define types for VSCode IntelliSense.
-/** @typedef {import("./shared/types").ConfigData} ConfigData */
-/** @typedef {import("./shared/types").Parser} Parser */
-/** @typedef {import("./shared/types").Plugin} Plugin */
-/** @typedef {import("./shared/types").Rule} Rule */
-/** @typedef {ReturnType<ConfigArrayFactory["create"]>} ConfigArray */
+// For VSCode intellisense
+/** @typedef {import("../../shared/types").ConfigData} ConfigData */
+/** @typedef {import("../../shared/types").GlobalConf} GlobalConf */
+/** @typedef {import("../../shared/types").SeverityConf} SeverityConf */
+/** @typedef {import("./config-dependency").DependentParser} DependentParser */
+/** @typedef {import("./config-dependency").DependentPlugin} DependentPlugin */
/**
- * @typedef {Object} CascadingConfigArrayFactoryOptions
- * @property {Map<string,Plugin>} [additionalPluginPool] The map for additional plugins.
- * @property {ConfigData} [baseConfig] The config by `baseConfig` option.
- * @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.
- * @property {string} [cwd] The base directory to start lookup.
- * @property {string} [ignorePath] The path to the alternative file of `.eslintignore`.
- * @property {string[]} [rulePaths] The value of `--rulesdir` option.
- * @property {string} [specificConfigPath] The value of `--config` option.
- * @property {boolean} [useEslintrc] if `false` then it doesn't load config files.
- * @property {Function} loadRules The function to use to load rules.
- * @property {Map<string,Rule>} builtInRules The rules that are built in to ESLint.
- * @property {Object} [resolver=ModuleResolver] The module resolver object.
- * @property {string} eslintAllPath The path to the definitions for eslint:all.
- * @property {string} eslintRecommendedPath The path to the definitions for eslint:recommended.
+ * Check if `xs` starts with `ys`.
+ * @template T
+ * @param {T[]} xs The array to check.
+ * @param {T[]} ys The array that may be the first part of `xs`.
+ * @returns {boolean} `true` if `xs` starts with `ys`.
*/
+function startsWith(xs, ys) {
+ return xs.length >= ys.length && ys.every((y, i) => y === xs[i]);
+}
/**
- * @typedef {Object} CascadingConfigArrayFactoryInternalSlots
- * @property {ConfigArray} baseConfigArray The config array of `baseConfig` option.
- * @property {ConfigData} baseConfigData The config data of `baseConfig` option. This is used to reset `baseConfigArray`.
- * @property {ConfigArray} cliConfigArray The config array of CLI options.
- * @property {ConfigData} cliConfigData The config data of CLI options. This is used to reset `cliConfigArray`.
- * @property {ConfigArrayFactory} configArrayFactory The factory for config arrays.
- * @property {Map<string, ConfigArray>} configCache The cache from directory paths to config arrays.
- * @property {string} cwd The base directory to start lookup.
- * @property {WeakMap<ConfigArray, ConfigArray>} finalizeCache The cache from config arrays to finalized config arrays.
- * @property {string} [ignorePath] The path to the alternative file of `.eslintignore`.
- * @property {string[]|null} rulePaths The value of `--rulesdir` option. This is used to reset `baseConfigArray`.
- * @property {string|null} specificConfigPath The value of `--config` option. This is used to reset `cliConfigArray`.
- * @property {boolean} useEslintrc if `false` then it doesn't load config files.
- * @property {Function} loadRules The function to use to load rules.
- * @property {Map<string,Rule>} builtInRules The rules that are built in to ESLint.
- * @property {Object} [resolver=ModuleResolver] The module resolver object.
- * @property {string} eslintAllPath The path to the definitions for eslint:all.
- * @property {string} eslintRecommendedPath The path to the definitions for eslint:recommended.
+ * The class for extracted config data.
*/
+class ExtractedConfig {
+ constructor() {
-/** @type {WeakMap<CascadingConfigArrayFactory, CascadingConfigArrayFactoryInternalSlots>} */
-const internalSlotsMap = new WeakMap();
+ /**
+ * The config name what `noInlineConfig` setting came from.
+ * @type {string}
+ */
+ this.configNameOfNoInlineConfig = "";
-/**
- * Create the config array from `baseConfig` and `rulePaths`.
- * @param {CascadingConfigArrayFactoryInternalSlots} slots The slots.
- * @returns {ConfigArray} The config array of the base configs.
- */
-function createBaseConfigArray({
- configArrayFactory,
- baseConfigData,
- rulePaths,
- cwd,
- loadRules
-}) {
- const baseConfigArray = configArrayFactory.create(
- baseConfigData,
- { name: "BaseConfig" }
- );
+ /**
+ * Environments.
+ * @type {Record<string, boolean>}
+ */
+ this.env = {};
- /*
- * Create the config array element for the default ignore patterns.
- * This element has `ignorePattern` property that ignores the default
- * patterns in the current working directory.
- */
- baseConfigArray.unshift(configArrayFactory.create(
- { ignorePatterns: IgnorePattern.DefaultPatterns },
- { name: "DefaultIgnorePattern" }
- )[0]);
+ /**
+ * Global variables.
+ * @type {Record<string, GlobalConf>}
+ */
+ this.globals = {};
- /*
- * Load rules `--rulesdir` option as a pseudo plugin.
- * Use a pseudo plugin to define rules of `--rulesdir`, so we can validate
- * the rule's options with only information in the config array.
- */
- if (rulePaths && rulePaths.length > 0) {
- baseConfigArray.push({
- type: "config",
- name: "--rulesdir",
- filePath: "",
- plugins: {
- "": new ConfigDependency({
- definition: {
- rules: rulePaths.reduce(
- (map, rulesPath) => Object.assign(
- map,
- loadRules(rulesPath, cwd)
- ),
- {}
- )
- },
- filePath: "",
- id: "",
- importerName: "--rulesdir",
- importerPath: ""
- })
- }
- });
- }
+ /**
+ * The glob patterns that ignore to lint.
+ * @type {(((filePath:string, dot?:boolean) => boolean) & { basePath:string; patterns:string[] }) | undefined}
+ */
+ this.ignores = void 0;
- return baseConfigArray;
-}
+ /**
+ * The flag that disables directive comments.
+ * @type {boolean|undefined}
+ */
+ this.noInlineConfig = void 0;
-/**
- * Create the config array from CLI options.
- * @param {CascadingConfigArrayFactoryInternalSlots} slots The slots.
- * @returns {ConfigArray} The config array of the base configs.
- */
-function createCLIConfigArray({
- cliConfigData,
- configArrayFactory,
- cwd,
- ignorePath,
- specificConfigPath
-}) {
- const cliConfigArray = configArrayFactory.create(
- cliConfigData,
- { name: "CLIOptions" }
- );
+ /**
+ * Parser definition.
+ * @type {DependentParser|null}
+ */
+ this.parser = null;
- cliConfigArray.unshift(
- ...(ignorePath
- ? configArrayFactory.loadESLintIgnore(ignorePath)
- : configArrayFactory.loadDefaultESLintIgnore())
- );
+ /**
+ * Options for the parser.
+ * @type {Object}
+ */
+ this.parserOptions = {};
- if (specificConfigPath) {
- cliConfigArray.unshift(
- ...configArrayFactory.loadFile(
- specificConfigPath,
- { name: "--config", basePath: cwd }
- )
- );
- }
+ /**
+ * Plugin definitions.
+ * @type {Record<string, DependentPlugin>}
+ */
+ this.plugins = {};
- return cliConfigArray;
-}
+ /**
+ * Processor ID.
+ * @type {string|null}
+ */
+ this.processor = null;
-/**
- * The error type when there are files matched by a glob, but all of them have been ignored.
- */
-class ConfigurationNotFoundError extends Error {
+ /**
+ * The flag that reports unused `eslint-disable` directive comments.
+ * @type {boolean|undefined}
+ */
+ this.reportUnusedDisableDirectives = void 0;
+
+ /**
+ * Rule settings.
+ * @type {Record<string, [SeverityConf, ...any[]]>}
+ */
+ this.rules = {};
+
+ /**
+ * Shared settings.
+ * @type {Object}
+ */
+ this.settings = {};
+ }
- // eslint-disable-next-line jsdoc/require-description
/**
- * @param {string} directoryPath The directory path.
+ * Convert this config to the compatible object as a config file content.
+ * @returns {ConfigData} The converted object.
*/
- constructor(directoryPath) {
- super(`No ESLint configuration found in ${directoryPath}.`);
- this.messageTemplate = "no-config-found";
- this.messageData = { directoryPath };
+ toCompatibleObjectAsConfigFileContent() {
+ const {
+ /* eslint-disable no-unused-vars */
+ configNameOfNoInlineConfig: _ignore1,
+ processor: _ignore2,
+ /* eslint-enable no-unused-vars */
+ ignores,
+ ...config
+ } = this;
+
+ config.parser = config.parser && config.parser.filePath;
+ config.plugins = Object.keys(config.plugins).filter(Boolean).reverse();
+ config.ignorePatterns = ignores ? ignores.patterns : [];
+
+ // Strip the default patterns from `ignorePatterns`.
+ if (startsWith(config.ignorePatterns, IgnorePattern.DefaultPatterns)) {
+ config.ignorePatterns =
+ config.ignorePatterns.slice(IgnorePattern.DefaultPatterns.length);
+ }
+
+ return config;
}
}
/**
- * This class provides the functionality that enumerates every file which is
- * matched by given glob patterns and that configuration.
+ * @fileoverview `ConfigArray` class.
+ *
+ * `ConfigArray` class expresses the full of a configuration. It has the entry
+ * config file, base config files that were extended, loaded parsers, and loaded
+ * plugins.
+ *
+ * `ConfigArray` class provides three properties and two methods.
+ *
+ * - `pluginEnvironments`
+ * - `pluginProcessors`
+ * - `pluginRules`
+ * The `Map` objects that contain the members of all plugins that this
+ * config array contains. Those map objects don't have mutation methods.
+ * Those keys are the member ID such as `pluginId/memberName`.
+ * - `isRoot()`
+ * If `true` then this configuration has `root:true` property.
+ * - `extractConfig(filePath)`
+ * Extract the final configuration for a given file. This means merging
+ * every config array element which that `criteria` property matched. The
+ * `filePath` argument must be an absolute path.
+ *
+ * `ConfigArrayFactory` provides the loading logic of config files.
+ *
+ * @author Toru Nagashima <https://github.com/mysticatea>
*/
-class CascadingConfigArrayFactory {
- /**
- * Initialize this enumerator.
- * @param {CascadingConfigArrayFactoryOptions} options The options.
- */
- constructor({
- additionalPluginPool = new Map(),
- baseConfig: baseConfigData = null,
- cliConfig: cliConfigData = null,
- cwd = process.cwd(),
- ignorePath,
- resolvePluginsRelativeTo,
- rulePaths = [],
- specificConfigPath = null,
- useEslintrc = true,
- builtInRules = new Map(),
- loadRules,
- resolver,
- eslintRecommendedPath,
- eslintAllPath
- } = {}) {
- const configArrayFactory = new ConfigArrayFactory({
- additionalPluginPool,
- cwd,
- resolvePluginsRelativeTo,
- builtInRules,
- resolver,
- eslintRecommendedPath,
- eslintAllPath
- });
+//------------------------------------------------------------------------------
+// Helpers
+//------------------------------------------------------------------------------
+
+// Define types for VSCode IntelliSense.
+/** @typedef {import("../../shared/types").Environment} Environment */
+/** @typedef {import("../../shared/types").GlobalConf} GlobalConf */
+/** @typedef {import("../../shared/types").RuleConf} RuleConf */
+/** @typedef {import("../../shared/types").Rule} Rule */
+/** @typedef {import("../../shared/types").Plugin} Plugin */
+/** @typedef {import("../../shared/types").Processor} Processor */
+/** @typedef {import("./config-dependency").DependentParser} DependentParser */
+/** @typedef {import("./config-dependency").DependentPlugin} DependentPlugin */
+/** @typedef {import("./override-tester")["OverrideTester"]} OverrideTester */
+
+/**
+ * @typedef {Object} ConfigArrayElement
+ * @property {string} name The name of this config element.
+ * @property {string} filePath The path to the source file of this config element.
+ * @property {InstanceType<OverrideTester>|null} criteria The tester for the `files` and `excludedFiles` of this config element.
+ * @property {Record<string, boolean>|undefined} env The environment settings.
+ * @property {Record<string, GlobalConf>|undefined} globals The global variable settings.
+ * @property {IgnorePattern|undefined} ignorePattern The ignore patterns.
+ * @property {boolean|undefined} noInlineConfig The flag that disables directive comments.
+ * @property {DependentParser|undefined} parser The parser loader.
+ * @property {Object|undefined} parserOptions The parser options.
+ * @property {Record<string, DependentPlugin>|undefined} plugins The plugin loaders.
+ * @property {string|undefined} processor The processor name to refer plugin's processor.
+ * @property {boolean|undefined} reportUnusedDisableDirectives The flag to report unused `eslint-disable` comments.
+ * @property {boolean|undefined} root The flag to express root.
+ * @property {Record<string, RuleConf>|undefined} rules The rule settings
+ * @property {Object|undefined} settings The shared settings.
+ * @property {"config" | "ignore" | "implicit-processor"} type The element type.
+ */
+
+/**
+ * @typedef {Object} ConfigArrayInternalSlots
+ * @property {Map<string, ExtractedConfig>} cache The cache to extract configs.
+ * @property {ReadonlyMap<string, Environment>|null} envMap The map from environment ID to environment definition.
+ * @property {ReadonlyMap<string, Processor>|null} processorMap The map from processor ID to environment definition.
+ * @property {ReadonlyMap<string, Rule>|null} ruleMap The map from rule ID to rule definition.
+ */
+
+/** @type {WeakMap<ConfigArray, ConfigArrayInternalSlots>} */
+const internalSlotsMap$2 = new class extends WeakMap {
+ get(key) {
+ let value = super.get(key);
+
+ if (!value) {
+ value = {
+ cache: new Map(),
+ envMap: null,
+ processorMap: null,
+ ruleMap: null
+ };
+ super.set(key, value);
+ }
- internalSlotsMap.set(this, {
- baseConfigArray: createBaseConfigArray({
- baseConfigData,
- configArrayFactory,
- cwd,
- rulePaths,
- loadRules,
- resolver
- }),
- baseConfigData,
- cliConfigArray: createCLIConfigArray({
- cliConfigData,
- configArrayFactory,
- cwd,
- ignorePath,
- specificConfigPath
- }),
- cliConfigData,
- configArrayFactory,
- configCache: new Map(),
- cwd,
- finalizeCache: new WeakMap(),
- ignorePath,
- rulePaths,
- specificConfigPath,
- useEslintrc,
- builtInRules,
- loadRules
- });
+ return value;
}
+}();
- /**
- * The path to the current working directory.
- * This is used by tests.
- * @type {string}
- */
- get cwd() {
- const { cwd } = internalSlotsMap.get(this);
+/**
+ * Get the indices which are matched to a given file.
+ * @param {ConfigArrayElement[]} elements The elements.
+ * @param {string} filePath The path to a target file.
+ * @returns {number[]} The indices.
+ */
+function getMatchedIndices(elements, filePath) {
+ const indices = [];
- return cwd;
+ for (let i = elements.length - 1; i >= 0; --i) {
+ const element = elements[i];
+
+ if (!element.criteria || (filePath && element.criteria.test(filePath))) {
+ indices.push(i);
+ }
}
- /**
- * Get the config array of a given file.
- * If `filePath` was not given, it returns the config which contains only
- * `baseConfigData` and `cliConfigData`.
- * @param {string} [filePath] The file path to a file.
- * @param {Object} [options] The options.
- * @param {boolean} [options.ignoreNotFoundError] If `true` then it doesn't throw `ConfigurationNotFoundError`.
- * @returns {ConfigArray} The config array of the file.
- */
- getConfigArrayForFile(filePath, { ignoreNotFoundError = false } = {}) {
- const {
- baseConfigArray,
- cliConfigArray,
- cwd
- } = internalSlotsMap.get(this);
+ return indices;
+}
- if (!filePath) {
- return new ConfigArray(...baseConfigArray, ...cliConfigArray);
- }
+/**
+ * Check if a value is a non-null object.
+ * @param {any} x The value to check.
+ * @returns {boolean} `true` if the value is a non-null object.
+ */
+function isNonNullObject(x) {
+ return typeof x === "object" && x !== null;
+}
- const directoryPath = path__default["default"].dirname(path__default["default"].resolve(cwd, filePath));
+/**
+ * Merge two objects.
+ *
+ * Assign every property values of `y` to `x` if `x` doesn't have the property.
+ * If `x`'s property value is an object, it does recursive.
+ * @param {Object} target The destination to merge
+ * @param {Object|undefined} source The source to merge.
+ * @returns {void}
+ */
+function mergeWithoutOverwrite(target, source) {
+ if (!isNonNullObject(source)) {
+ return;
+ }
- debug$1(`Load config files for ${directoryPath}.`);
+ for (const key of Object.keys(source)) {
+ if (key === "__proto__") {
+ continue;
+ }
- return this._finalizeConfigArray(
- this._loadConfigInAncestors(directoryPath),
- directoryPath,
- ignoreNotFoundError
- );
+ if (isNonNullObject(target[key])) {
+ mergeWithoutOverwrite(target[key], source[key]);
+ } else if (target[key] === void 0) {
+ if (isNonNullObject(source[key])) {
+ target[key] = Array.isArray(source[key]) ? [] : {};
+ mergeWithoutOverwrite(target[key], source[key]);
+ } else if (source[key] !== void 0) {
+ target[key] = source[key];
+ }
+ }
}
+}
+
+/**
+ * The error for plugin conflicts.
+ */
+class PluginConflictError extends Error {
/**
- * Set the config data to override all configs.
- * Require to call `clearCache()` method after this method is called.
- * @param {ConfigData} configData The config data to override all configs.
- * @returns {void}
+ * Initialize this error object.
+ * @param {string} pluginId The plugin ID.
+ * @param {{filePath:string, importerName:string}[]} plugins The resolved plugins.
*/
- setOverrideConfig(configData) {
- const slots = internalSlotsMap.get(this);
+ constructor(pluginId, plugins) {
+ super(`Plugin "${pluginId}" was conflicted between ${plugins.map(p => `"${p.importerName}"`).join(" and ")}.`);
+ this.messageTemplate = "plugin-conflict";
+ this.messageData = { pluginId, plugins };
+ }
+}
- slots.cliConfigData = configData;
+/**
+ * Merge plugins.
+ * `target`'s definition is prior to `source`'s.
+ * @param {Record<string, DependentPlugin>} target The destination to merge
+ * @param {Record<string, DependentPlugin>|undefined} source The source to merge.
+ * @returns {void}
+ */
+function mergePlugins(target, source) {
+ if (!isNonNullObject(source)) {
+ return;
}
- /**
- * Clear config cache.
- * @returns {void}
- */
- clearCache() {
- const slots = internalSlotsMap.get(this);
+ for (const key of Object.keys(source)) {
+ if (key === "__proto__") {
+ continue;
+ }
+ const targetValue = target[key];
+ const sourceValue = source[key];
- slots.baseConfigArray = createBaseConfigArray(slots);
- slots.cliConfigArray = createCLIConfigArray(slots);
- slots.configCache.clear();
+ // Adopt the plugin which was found at first.
+ if (targetValue === void 0) {
+ if (sourceValue.error) {
+ throw sourceValue.error;
+ }
+ target[key] = sourceValue;
+ } else if (sourceValue.filePath !== targetValue.filePath) {
+ throw new PluginConflictError(key, [
+ {
+ filePath: targetValue.filePath,
+ importerName: targetValue.importerName
+ },
+ {
+ filePath: sourceValue.filePath,
+ importerName: sourceValue.importerName
+ }
+ ]);
+ }
}
+}
- /**
- * Load and normalize config files from the ancestor directories.
- * @param {string} directoryPath The path to a leaf directory.
- * @param {boolean} configsExistInSubdirs `true` if configurations exist in subdirectories.
- * @returns {ConfigArray} The loaded config.
- * @private
- */
- _loadConfigInAncestors(directoryPath, configsExistInSubdirs = false) {
- const {
- baseConfigArray,
- configArrayFactory,
- configCache,
- cwd,
- useEslintrc
- } = internalSlotsMap.get(this);
+/**
+ * Merge rule configs.
+ * `target`'s definition is prior to `source`'s.
+ * @param {Record<string, Array>} target The destination to merge
+ * @param {Record<string, RuleConf>|undefined} source The source to merge.
+ * @returns {void}
+ */
+function mergeRuleConfigs(target, source) {
+ if (!isNonNullObject(source)) {
+ return;
+ }
- if (!useEslintrc) {
- return baseConfigArray;
+ for (const key of Object.keys(source)) {
+ if (key === "__proto__") {
+ continue;
}
+ const targetDef = target[key];
+ const sourceDef = source[key];
- let configArray = configCache.get(directoryPath);
+ // Adopt the rule config which was found at first.
+ if (targetDef === void 0) {
+ if (Array.isArray(sourceDef)) {
+ target[key] = [...sourceDef];
+ } else {
+ target[key] = [sourceDef];
+ }
- // Hit cache.
- if (configArray) {
- debug$1(`Cache hit: ${directoryPath}.`);
- return configArray;
+ /*
+ * If the first found rule config is severity only and the current rule
+ * config has options, merge the severity and the options.
+ */
+ } else if (
+ targetDef.length === 1 &&
+ Array.isArray(sourceDef) &&
+ sourceDef.length >= 2
+ ) {
+ targetDef.push(...sourceDef.slice(1));
}
- debug$1(`No cache found: ${directoryPath}.`);
+ }
+}
- const homePath = os__default["default"].homedir();
+/**
+ * Create the extracted config.
+ * @param {ConfigArray} instance The config elements.
+ * @param {number[]} indices The indices to use.
+ * @returns {ExtractedConfig} The extracted config.
+ */
+function createConfig(instance, indices) {
+ const config = new ExtractedConfig();
+ const ignorePatterns = [];
- // Consider this is root.
- if (directoryPath === homePath && cwd !== homePath) {
- debug$1("Stop traversing because of considered root.");
- if (configsExistInSubdirs) {
- const filePath = ConfigArrayFactory.getPathToConfigFileInDirectory(directoryPath);
+ // Merge elements.
+ for (const index of indices) {
+ const element = instance[index];
- if (filePath) {
- emitDeprecationWarning(
- filePath,
- "ESLINT_PERSONAL_CONFIG_SUPPRESS"
- );
- }
+ // Adopt the parser which was found at first.
+ if (!config.parser && element.parser) {
+ if (element.parser.error) {
+ throw element.parser.error;
}
- return this._cacheConfig(directoryPath, baseConfigArray);
+ config.parser = element.parser;
}
- // Load the config on this directory.
- try {
- configArray = configArrayFactory.loadInDirectory(directoryPath);
- } catch (error) {
- /* istanbul ignore next */
- if (error.code === "EACCES") {
- debug$1("Stop traversing because of 'EACCES' error.");
- return this._cacheConfig(directoryPath, baseConfigArray);
- }
- throw error;
+ // Adopt the processor which was found at first.
+ if (!config.processor && element.processor) {
+ config.processor = element.processor;
}
- if (configArray.length > 0 && configArray.isRoot()) {
- debug$1("Stop traversing because of 'root:true'.");
- configArray.unshift(...baseConfigArray);
- return this._cacheConfig(directoryPath, configArray);
+ // Adopt the noInlineConfig which was found at first.
+ if (config.noInlineConfig === void 0 && element.noInlineConfig !== void 0) {
+ config.noInlineConfig = element.noInlineConfig;
+ config.configNameOfNoInlineConfig = element.name;
}
- // Load from the ancestors and merge it.
- const parentPath = path__default["default"].dirname(directoryPath);
- const parentConfigArray = parentPath && parentPath !== directoryPath
- ? this._loadConfigInAncestors(
- parentPath,
- configsExistInSubdirs || configArray.length > 0
- )
- : baseConfigArray;
+ // Adopt the reportUnusedDisableDirectives which was found at first.
+ if (config.reportUnusedDisableDirectives === void 0 && element.reportUnusedDisableDirectives !== void 0) {
+ config.reportUnusedDisableDirectives = element.reportUnusedDisableDirectives;
+ }
- if (configArray.length > 0) {
- configArray.unshift(...parentConfigArray);
- } else {
- configArray = parentConfigArray;
+ // Collect ignorePatterns
+ if (element.ignorePattern) {
+ ignorePatterns.push(element.ignorePattern);
}
- // Cache and return.
- return this._cacheConfig(directoryPath, configArray);
+ // Merge others.
+ mergeWithoutOverwrite(config.env, element.env);
+ mergeWithoutOverwrite(config.globals, element.globals);
+ mergeWithoutOverwrite(config.parserOptions, element.parserOptions);
+ mergeWithoutOverwrite(config.settings, element.settings);
+ mergePlugins(config.plugins, element.plugins);
+ mergeRuleConfigs(config.rules, element.rules);
}
- /**
- * Freeze and cache a given config.
- * @param {string} directoryPath The path to a directory as a cache key.
- * @param {ConfigArray} configArray The config array as a cache value.
- * @returns {ConfigArray} The `configArray` (frozen).
- */
- _cacheConfig(directoryPath, configArray) {
- const { configCache } = internalSlotsMap.get(this);
-
- Object.freeze(configArray);
- configCache.set(directoryPath, configArray);
-
- return configArray;
+ // Create the predicate function for ignore patterns.
+ if (ignorePatterns.length > 0) {
+ config.ignores = IgnorePattern.createIgnore(ignorePatterns.reverse());
}
- /**
- * Finalize a given config array.
- * Concatenate `--config` and other CLI options.
- * @param {ConfigArray} configArray The parent config array.
- * @param {string} directoryPath The path to the leaf directory to find config files.
- * @param {boolean} ignoreNotFoundError If `true` then it doesn't throw `ConfigurationNotFoundError`.
- * @returns {ConfigArray} The loaded config.
- * @private
- */
- _finalizeConfigArray(configArray, directoryPath, ignoreNotFoundError) {
- const {
- cliConfigArray,
- configArrayFactory,
- finalizeCache,
- useEslintrc,
- builtInRules
- } = internalSlotsMap.get(this);
-
- let finalConfigArray = finalizeCache.get(configArray);
-
- if (!finalConfigArray) {
- finalConfigArray = configArray;
-
- // Load the personal config if there are no regular config files.
- if (
- useEslintrc &&
- configArray.every(c => !c.filePath) &&
- cliConfigArray.every(c => !c.filePath) // `--config` option can be a file.
- ) {
- const homePath = os__default["default"].homedir();
-
- debug$1("Loading the config file of the home directory:", homePath);
-
- const personalConfigArray = configArrayFactory.loadInDirectory(
- homePath,
- { name: "PersonalConfig" }
- );
-
- if (
- personalConfigArray.length > 0 &&
- !directoryPath.startsWith(homePath)
- ) {
- const lastElement =
- personalConfigArray[personalConfigArray.length - 1];
-
- emitDeprecationWarning(
- lastElement.filePath,
- "ESLINT_PERSONAL_CONFIG_LOAD"
- );
- }
-
- finalConfigArray = finalConfigArray.concat(personalConfigArray);
- }
-
- // Apply CLI options.
- if (cliConfigArray.length > 0) {
- finalConfigArray = finalConfigArray.concat(cliConfigArray);
- }
-
- // Validate rule settings and environments.
- const validator = new ConfigValidator({
- builtInRules
- });
-
- validator.validateConfigArray(finalConfigArray);
+ return config;
+}
- // Cache it.
- Object.freeze(finalConfigArray);
- finalizeCache.set(configArray, finalConfigArray);
+/**
+ * Collect definitions.
+ * @template T, U
+ * @param {string} pluginId The plugin ID for prefix.
+ * @param {Record<string,T>} defs The definitions to collect.
+ * @param {Map<string, U>} map The map to output.
+ * @param {function(T): U} [normalize] The normalize function for each value.
+ * @returns {void}
+ */
+function collect(pluginId, defs, map, normalize) {
+ if (defs) {
+ const prefix = pluginId && `${pluginId}/`;
- debug$1(
- "Configuration was determined: %o on %s",
- finalConfigArray,
- directoryPath
+ for (const [key, value] of Object.entries(defs)) {
+ map.set(
+ `${prefix}${key}`,
+ normalize ? normalize(value) : value
);
}
-
- // At least one element (the default ignore patterns) exists.
- if (!ignoreNotFoundError && useEslintrc && finalConfigArray.length <= 1) {
- throw new ConfigurationNotFoundError(directoryPath);
- }
-
- return finalConfigArray;
}
}
/**
- * @fileoverview Compatibility class for flat config.
- * @author Nicholas C. Zakas
+ * Normalize a rule definition.
+ * @param {Function|Rule} rule The rule definition to normalize.
+ * @returns {Rule} The normalized rule definition.
*/
+function normalizePluginRule(rule) {
+ return typeof rule === "function" ? { create: rule } : rule;
+}
-const dirname = path__default["default"].dirname(url.fileURLToPath((typeof document === 'undefined' ? new ((__webpack_require__(876).URL))('file:' + __filename).href : (document.currentScript && document.currentScript.src || new URL('eslintrc.cjs', document.baseURI).href))));
-
-//-----------------------------------------------------------------------------
-// Helpers
-//-----------------------------------------------------------------------------
-
-/** @typedef {import("../../shared/types").Environment} Environment */
-/** @typedef {import("../../shared/types").Processor} Processor */
-
-const debug = debugOrig__default["default"]("eslintrc:flat-compat");
-const cafactory = Symbol("cafactory");
+/**
+ * Delete the mutation methods from a given map.
+ * @param {Map<any, any>} map The map object to delete.
+ * @returns {void}
+ */
+function deleteMutationMethods(map) {
+ Object.defineProperties(map, {
+ clear: { configurable: true, value: void 0 },
+ delete: { configurable: true, value: void 0 },
+ set: { configurable: true, value: void 0 }
+ });
+}
/**
- * Translates an ESLintRC-style config object into a flag-config-style config
- * object.
- * @param {Object} eslintrcConfig An ESLintRC-style config object.
- * @param {Object} options Options to help translate the config.
- * @param {string} options.resolveConfigRelativeTo To the directory to resolve
- * configs from.
- * @param {string} options.resolvePluginsRelativeTo The directory to resolve
- * plugins from.
- * @param {ReadOnlyMap<string,Environment>} options.pluginEnvironments A map of plugin environment
- * names to objects.
- * @param {ReadOnlyMap<string,Processor>} options.pluginProcessors A map of plugin processor
- * names to objects.
- * @returns {Object} A flag-config-style config object.
+ * Create `envMap`, `processorMap`, `ruleMap` with the plugins in the config array.
+ * @param {ConfigArrayElement[]} elements The config elements.
+ * @param {ConfigArrayInternalSlots} slots The internal slots.
+ * @returns {void}
*/
-function translateESLintRC(eslintrcConfig, {
- resolveConfigRelativeTo,
- resolvePluginsRelativeTo,
- pluginEnvironments,
- pluginProcessors
-}) {
+function initPluginMemberMaps(elements, slots) {
+ const processed = new Set();
- const flatConfig = {};
- const configs = [];
- const languageOptions = {};
- const linterOptions = {};
- const keysToCopy = ["settings", "rules", "processor"];
- const languageOptionsKeysToCopy = ["globals", "parser", "parserOptions"];
- const linterOptionsKeysToCopy = ["noInlineConfig", "reportUnusedDisableDirectives"];
+ slots.envMap = new Map();
+ slots.processorMap = new Map();
+ slots.ruleMap = new Map();
- // check for special settings for eslint:all and eslint:recommended:
- if (eslintrcConfig.settings) {
- if (eslintrcConfig.settings["eslint:all"] === true) {
- return ["eslint:all"];
+ for (const element of elements) {
+ if (!element.plugins) {
+ continue;
}
- if (eslintrcConfig.settings["eslint:recommended"] === true) {
- return ["eslint:recommended"];
+ for (const [pluginId, value] of Object.entries(element.plugins)) {
+ const plugin = value.definition;
+
+ if (!plugin || processed.has(pluginId)) {
+ continue;
+ }
+ processed.add(pluginId);
+
+ collect(pluginId, plugin.environments, slots.envMap);
+ collect(pluginId, plugin.processors, slots.processorMap);
+ collect(pluginId, plugin.rules, slots.ruleMap, normalizePluginRule);
}
}
- // copy over simple translations
- for (const key of keysToCopy) {
- if (key in eslintrcConfig && typeof eslintrcConfig[key] !== "undefined") {
- flatConfig[key] = eslintrcConfig[key];
- }
+ deleteMutationMethods(slots.envMap);
+ deleteMutationMethods(slots.processorMap);
+ deleteMutationMethods(slots.ruleMap);
+}
+
+/**
+ * Create `envMap`, `processorMap`, `ruleMap` with the plugins in the config array.
+ * @param {ConfigArray} instance The config elements.
+ * @returns {ConfigArrayInternalSlots} The extracted config.
+ */
+function ensurePluginMemberMaps(instance) {
+ const slots = internalSlotsMap$2.get(instance);
+
+ if (!slots.ruleMap) {
+ initPluginMemberMaps(instance, slots);
}
- // copy over languageOptions
- for (const key of languageOptionsKeysToCopy) {
- if (key in eslintrcConfig && typeof eslintrcConfig[key] !== "undefined") {
+ return slots;
+}
- // create the languageOptions key in the flat config
- flatConfig.languageOptions = languageOptions;
+//------------------------------------------------------------------------------
+// Public Interface
+//------------------------------------------------------------------------------
- if (key === "parser") {
- debug(`Resolving parser '${languageOptions[key]}' relative to ${resolveConfigRelativeTo}`);
+/**
+ * The Config Array.
+ *
+ * `ConfigArray` instance contains all settings, parsers, and plugins.
+ * You need to call `ConfigArray#extractConfig(filePath)` method in order to
+ * extract, merge and get only the config data which is related to an arbitrary
+ * file.
+ * @extends {Array<ConfigArrayElement>}
+ */
+class ConfigArray extends Array {
- if (eslintrcConfig[key].error) {
- throw eslintrcConfig[key].error;
- }
+ /**
+ * Get the plugin environments.
+ * The returned map cannot be mutated.
+ * @type {ReadonlyMap<string, Environment>} The plugin environments.
+ */
+ get pluginEnvironments() {
+ return ensurePluginMemberMaps(this).envMap;
+ }
- languageOptions[key] = eslintrcConfig[key].definition;
- continue;
- }
+ /**
+ * Get the plugin processors.
+ * The returned map cannot be mutated.
+ * @type {ReadonlyMap<string, Processor>} The plugin processors.
+ */
+ get pluginProcessors() {
+ return ensurePluginMemberMaps(this).processorMap;
+ }
- // clone any object values that are in the eslintrc config
- if (eslintrcConfig[key] && typeof eslintrcConfig[key] === "object") {
- languageOptions[key] = {
- ...eslintrcConfig[key]
- };
- } else {
- languageOptions[key] = eslintrcConfig[key];
- }
- }
+ /**
+ * Get the plugin rules.
+ * The returned map cannot be mutated.
+ * @returns {ReadonlyMap<string, Rule>} The plugin rules.
+ */
+ get pluginRules() {
+ return ensurePluginMemberMaps(this).ruleMap;
}
- // copy over linterOptions
- for (const key of linterOptionsKeysToCopy) {
- if (key in eslintrcConfig && typeof eslintrcConfig[key] !== "undefined") {
- flatConfig.linterOptions = linterOptions;
- linterOptions[key] = eslintrcConfig[key];
+ /**
+ * Check if this config has `root` flag.
+ * @returns {boolean} `true` if this config array is root.
+ */
+ isRoot() {
+ for (let i = this.length - 1; i >= 0; --i) {
+ const root = this[i].root;
+
+ if (typeof root === "boolean") {
+ return root;
+ }
}
+ return false;
}
- // move ecmaVersion a level up
- if (languageOptions.parserOptions) {
+ /**
+ * Extract the config data which is related to a given file.
+ * @param {string} filePath The absolute path to the target file.
+ * @returns {ExtractedConfig} The extracted config data.
+ */
+ extractConfig(filePath) {
+ const { cache } = internalSlotsMap$2.get(this);
+ const indices = getMatchedIndices(this, filePath);
+ const cacheKey = indices.join(",");
- if ("ecmaVersion" in languageOptions.parserOptions) {
- languageOptions.ecmaVersion = languageOptions.parserOptions.ecmaVersion;
- delete languageOptions.parserOptions.ecmaVersion;
+ if (!cache.has(cacheKey)) {
+ cache.set(cacheKey, createConfig(this, indices));
}
- if ("sourceType" in languageOptions.parserOptions) {
- languageOptions.sourceType = languageOptions.parserOptions.sourceType;
- delete languageOptions.parserOptions.sourceType;
- }
+ return cache.get(cacheKey);
+ }
- // check to see if we even need parserOptions anymore and remove it if not
- if (Object.keys(languageOptions.parserOptions).length === 0) {
- delete languageOptions.parserOptions;
+ /**
+ * Check if a given path is an additional lint target.
+ * @param {string} filePath The absolute path to the target file.
+ * @returns {boolean} `true` if the file is an additional lint target.
+ */
+ isAdditionalTargetPath(filePath) {
+ for (const { criteria, type } of this) {
+ if (
+ type === "config" &&
+ criteria &&
+ !criteria.endsWithWildcard &&
+ criteria.test(filePath)
+ ) {
+ return true;
+ }
}
+ return false;
}
+}
- // overrides
- if (eslintrcConfig.criteria) {
- flatConfig.files = [absoluteFilePath => eslintrcConfig.criteria.test(absoluteFilePath)];
- }
+/**
+ * Get the used extracted configs.
+ * CLIEngine will use this method to collect used deprecated rules.
+ * @param {ConfigArray} instance The config array object to get.
+ * @returns {ExtractedConfig[]} The used extracted configs.
+ * @private
+ */
+function getUsedExtractedConfigs(instance) {
+ const { cache } = internalSlotsMap$2.get(instance);
- // translate plugins
- if (eslintrcConfig.plugins && typeof eslintrcConfig.plugins === "object") {
- debug(`Translating plugins: ${eslintrcConfig.plugins}`);
+ return Array.from(cache.values());
+}
- flatConfig.plugins = {};
+/**
+ * @fileoverview `ConfigDependency` class.
+ *
+ * `ConfigDependency` class expresses a loaded parser or plugin.
+ *
+ * If the parser or plugin was loaded successfully, it has `definition` property
+ * and `filePath` property. Otherwise, it has `error` property.
+ *
+ * When `JSON.stringify()` converted a `ConfigDependency` object to a JSON, it
+ * omits `definition` property.
+ *
+ * `ConfigArrayFactory` creates `ConfigDependency` objects when it loads parsers
+ * or plugins.
+ *
+ * @author Toru Nagashima <https://github.com/mysticatea>
+ */
- for (const pluginName of Object.keys(eslintrcConfig.plugins)) {
+/**
+ * The class is to store parsers or plugins.
+ * This class hides the loaded object from `JSON.stringify()` and `console.log`.
+ * @template T
+ */
+class ConfigDependency {
- debug(`Translating plugin: ${pluginName}`);
- debug(`Resolving plugin '${pluginName} relative to ${resolvePluginsRelativeTo}`);
+ /**
+ * Initialize this instance.
+ * @param {Object} data The dependency data.
+ * @param {T} [data.definition] The dependency if the loading succeeded.
+ * @param {Error} [data.error] The error object if the loading failed.
+ * @param {string} [data.filePath] The actual path to the dependency if the loading succeeded.
+ * @param {string} data.id The ID of this dependency.
+ * @param {string} data.importerName The name of the config file which loads this dependency.
+ * @param {string} data.importerPath The path to the config file which loads this dependency.
+ */
+ constructor({
+ definition = null,
+ error = null,
+ filePath = null,
+ id,
+ importerName,
+ importerPath
+ }) {
- const { definition: plugin, error } = eslintrcConfig.plugins[pluginName];
+ /**
+ * The loaded dependency if the loading succeeded.
+ * @type {T|null}
+ */
+ this.definition = definition;
- if (error) {
- throw error;
- }
+ /**
+ * The error object if the loading failed.
+ * @type {Error|null}
+ */
+ this.error = error;
- flatConfig.plugins[pluginName] = plugin;
+ /**
+ * The loaded dependency if the loading succeeded.
+ * @type {string|null}
+ */
+ this.filePath = filePath;
- // create a config for any processors
- if (plugin.processors) {
- for (const processorName of Object.keys(plugin.processors)) {
- if (processorName.startsWith(".")) {
- debug(`Assigning processor: ${pluginName}/${processorName}`);
+ /**
+ * The ID of this dependency.
+ * @type {string}
+ */
+ this.id = id;
- configs.unshift({
- files: [`**/*${processorName}`],
- processor: pluginProcessors.get(`${pluginName}/${processorName}`)
- });
- }
+ /**
+ * The name of the config file which loads this dependency.
+ * @type {string}
+ */
+ this.importerName = importerName;
- }
- }
- }
+ /**
+ * The path to the config file which loads this dependency.
+ * @type {string}
+ */
+ this.importerPath = importerPath;
}
- // translate env - must come after plugins
- if (eslintrcConfig.env && typeof eslintrcConfig.env === "object") {
- for (const envName of Object.keys(eslintrcConfig.env)) {
+ // eslint-disable-next-line jsdoc/require-description
+ /**
+ * @returns {Object} a JSON compatible object.
+ */
+ toJSON() {
+ const obj = this[util__default["default"].inspect.custom]();
- // only add environments that are true
- if (eslintrcConfig.env[envName]) {
- debug(`Translating environment: ${envName}`);
+ // Display `error.message` (`Error#message` is unenumerable).
+ if (obj.error instanceof Error) {
+ obj.error = { ...obj.error, message: obj.error.message };
+ }
- if (environments.has(envName)) {
+ return obj;
+ }
- // built-in environments should be defined first
- configs.unshift(...translateESLintRC(environments.get(envName), {
- resolveConfigRelativeTo,
- resolvePluginsRelativeTo
- }));
- } else if (pluginEnvironments.has(envName)) {
+ // eslint-disable-next-line jsdoc/require-description
+ /**
+ * @returns {Object} an object to display by `console.log()`.
+ */
+ [util__default["default"].inspect.custom]() {
+ const {
+ definition: _ignore, // eslint-disable-line no-unused-vars
+ ...obj
+ } = this;
- // if the environment comes from a plugin, it should come after the plugin config
- configs.push(...translateESLintRC(pluginEnvironments.get(envName), {
- resolveConfigRelativeTo,
- resolvePluginsRelativeTo
- }));
- }
- }
- }
+ return obj;
}
+}
- // only add if there are actually keys in the config
- if (Object.keys(flatConfig).length > 0) {
- configs.push(flatConfig);
- }
+/**
+ * @fileoverview `OverrideTester` class.
+ *
+ * `OverrideTester` class handles `files` property and `excludedFiles` property
+ * of `overrides` config.
+ *
+ * It provides one method.
+ *
+ * - `test(filePath)`
+ * Test if a file path matches the pair of `files` property and
+ * `excludedFiles` property. The `filePath` argument must be an absolute
+ * path.
+ *
+ * `ConfigArrayFactory` creates `OverrideTester` objects when it processes
+ * `overrides` properties.
+ *
+ * @author Toru Nagashima <https://github.com/mysticatea>
+ */
- return configs;
-}
+const { Minimatch } = minimatch__default["default"];
+const minimatchOpts = { dot: true, matchBase: true };
-//-----------------------------------------------------------------------------
-// Exports
-//-----------------------------------------------------------------------------
+/**
+ * @typedef {Object} Pattern
+ * @property {InstanceType<Minimatch>[] | null} includes The positive matchers.
+ * @property {InstanceType<Minimatch>[] | null} excludes The negative matchers.
+ */
/**
- * A compatibility class for working with configs.
+ * Normalize a given pattern to an array.
+ * @param {string|string[]|undefined} patterns A glob pattern or an array of glob patterns.
+ * @returns {string[]|null} Normalized patterns.
+ * @private
*/
-class FlatCompat {
+function normalizePatterns(patterns) {
+ if (Array.isArray(patterns)) {
+ return patterns.filter(Boolean);
+ }
+ if (typeof patterns === "string" && patterns) {
+ return [patterns];
+ }
+ return [];
+}
- constructor({
- baseDirectory = process.cwd(),
- resolvePluginsRelativeTo = baseDirectory
- } = {}) {
- this.baseDirectory = baseDirectory;
- this.resolvePluginsRelativeTo = resolvePluginsRelativeTo;
- this[cafactory] = new ConfigArrayFactory({
- cwd: baseDirectory,
- resolvePluginsRelativeTo,
- eslintAllPath: path__default["default"].resolve(dirname, "../conf/eslint-all.cjs"),
- eslintRecommendedPath: path__default["default"].resolve(dirname, "../conf/eslint-recommended.cjs")
- });
+/**
+ * Create the matchers of given patterns.
+ * @param {string[]} patterns The patterns.
+ * @returns {InstanceType<Minimatch>[] | null} The matchers.
+ */
+function toMatcher(patterns) {
+ if (patterns.length === 0) {
+ return null;
}
+ return patterns.map(pattern => {
+ if (/^\.[/\\]/u.test(pattern)) {
+ return new Minimatch(
+ pattern.slice(2),
+
+ // `./*.js` should not match with `subdir/foo.js`
+ { ...minimatchOpts, matchBase: false }
+ );
+ }
+ return new Minimatch(pattern, minimatchOpts);
+ });
+}
+
+/**
+ * Convert a given matcher to string.
+ * @param {Pattern} matchers The matchers.
+ * @returns {string} The string expression of the matcher.
+ */
+function patternToJson({ includes, excludes }) {
+ return {
+ includes: includes && includes.map(m => m.pattern),
+ excludes: excludes && excludes.map(m => m.pattern)
+ };
+}
+
+/**
+ * The class to test given paths are matched by the patterns.
+ */
+class OverrideTester {
/**
- * Translates an ESLintRC-style config into a flag-config-style config.
- * @param {Object} eslintrcConfig The ESLintRC-style config object.
- * @returns {Object} A flag-config-style config object.
+ * Create a tester with given criteria.
+ * If there are no criteria, returns `null`.
+ * @param {string|string[]} files The glob patterns for included files.
+ * @param {string|string[]} excludedFiles The glob patterns for excluded files.
+ * @param {string} basePath The path to the base directory to test paths.
+ * @returns {OverrideTester|null} The created instance or `null`.
*/
- config(eslintrcConfig) {
- const eslintrcArray = this[cafactory].create(eslintrcConfig, {
- basePath: this.baseDirectory
- });
+ static create(files, excludedFiles, basePath) {
+ const includePatterns = normalizePatterns(files);
+ const excludePatterns = normalizePatterns(excludedFiles);
+ let endsWithWildcard = false;
- const flatArray = [];
- let hasIgnorePatterns = false;
+ if (includePatterns.length === 0) {
+ return null;
+ }
- eslintrcArray.forEach(configData => {
- if (configData.type === "config") {
- hasIgnorePatterns = hasIgnorePatterns || configData.ignorePattern;
- flatArray.push(...translateESLintRC(configData, {
- resolveConfigRelativeTo: path__default["default"].join(this.baseDirectory, "__placeholder.js"),
- resolvePluginsRelativeTo: path__default["default"].join(this.resolvePluginsRelativeTo, "__placeholder.js"),
- pluginEnvironments: eslintrcArray.pluginEnvironments,
- pluginProcessors: eslintrcArray.pluginProcessors
- }));
+ // Rejects absolute paths or relative paths to parents.
+ for (const pattern of includePatterns) {
+ if (path__default["default"].isAbsolute(pattern) || pattern.includes("..")) {
+ throw new Error(`Invalid override pattern (expected relative path not containing '..'): ${pattern}`);
}
- });
+ if (pattern.endsWith("*")) {
+ endsWithWildcard = true;
+ }
+ }
+ for (const pattern of excludePatterns) {
+ if (path__default["default"].isAbsolute(pattern) || pattern.includes("..")) {
+ throw new Error(`Invalid override pattern (expected relative path not containing '..'): ${pattern}`);
+ }
+ }
- // combine ignorePatterns to emulate ESLintRC behavior better
- if (hasIgnorePatterns) {
- flatArray.unshift({
- ignores: [filePath => {
+ const includes = toMatcher(includePatterns);
+ const excludes = toMatcher(excludePatterns);
- // Compute the final config for this file.
- // This filters config array elements by `files`/`excludedFiles` then merges the elements.
- const finalConfig = eslintrcArray.extractConfig(filePath);
+ return new OverrideTester(
+ [{ includes, excludes }],
+ basePath,
+ endsWithWildcard
+ );
+ }
- // Test the `ignorePattern` properties of the final config.
- return Boolean(finalConfig.ignores) && finalConfig.ignores(filePath);
- }]
- });
+ /**
+ * Combine two testers by logical and.
+ * If either of the testers was `null`, returns the other tester.
+ * The `basePath` property of the two must be the same value.
+ * @param {OverrideTester|null} a A tester.
+ * @param {OverrideTester|null} b Another tester.
+ * @returns {OverrideTester|null} Combined tester.
+ */
+ static and(a, b) {
+ if (!b) {
+ return a && new OverrideTester(
+ a.patterns,
+ a.basePath,
+ a.endsWithWildcard
+ );
+ }
+ if (!a) {
+ return new OverrideTester(
+ b.patterns,
+ b.basePath,
+ b.endsWithWildcard
+ );
}
- return flatArray;
+ assert__default["default"].strictEqual(a.basePath, b.basePath);
+ return new OverrideTester(
+ a.patterns.concat(b.patterns),
+ a.basePath,
+ a.endsWithWildcard || b.endsWithWildcard
+ );
}
/**
- * Translates the `env` section of an ESLintRC-style config.
- * @param {Object} envConfig The `env` section of an ESLintRC config.
- * @returns {Object} A flag-config object representing the environments.
+ * Initialize this instance.
+ * @param {Pattern[]} patterns The matchers.
+ * @param {string} basePath The base path.
+ * @param {boolean} endsWithWildcard If `true` then a pattern ends with `*`.
+ */
+ constructor(patterns, basePath, endsWithWildcard = false) {
+
+ /** @type {Pattern[]} */
+ this.patterns = patterns;
+
+ /** @type {string} */
+ this.basePath = basePath;
+
+ /** @type {boolean} */
+ this.endsWithWildcard = endsWithWildcard;
+ }
+
+ /**
+ * Test if a given path is matched or not.
+ * @param {string} filePath The absolute path to the target file.
+ * @returns {boolean} `true` if the path was matched.
*/
- env(envConfig) {
- return this.config({
- env: envConfig
- });
+ test(filePath) {
+ if (typeof filePath !== "string" || !path__default["default"].isAbsolute(filePath)) {
+ throw new Error(`'filePath' should be an absolute path, but got ${filePath}.`);
+ }
+ const relativePath = path__default["default"].relative(this.basePath, filePath);
+
+ return this.patterns.every(({ includes, excludes }) => (
+ (!includes || includes.some(m => m.match(relativePath))) &&
+ (!excludes || !excludes.some(m => m.match(relativePath)))
+ ));
}
+ // eslint-disable-next-line jsdoc/require-description
/**
- * Translates the `extends` section of an ESLintRC-style config.
- * @param {...string} configsToExtend The names of the configs to load.
- * @returns {Object} A flag-config object representing the config.
+ * @returns {Object} a JSON compatible object.
*/
- extends(...configsToExtend) {
- return this.config({
- extends: configsToExtend
- });
+ toJSON() {
+ if (this.patterns.length === 1) {
+ return {
+ ...patternToJson(this.patterns[0]),
+ basePath: this.basePath
+ };
+ }
+ return {
+ AND: this.patterns.map(patternToJson),
+ basePath: this.basePath
+ };
}
+ // eslint-disable-next-line jsdoc/require-description
/**
- * Translates the `plugins` section of an ESLintRC-style config.
- * @param {...string} plugins The names of the plugins to load.
- * @returns {Object} A flag-config object representing the plugins.
+ * @returns {Object} an object to display by `console.log()`.
*/
- plugins(...plugins) {
- return this.config({
- plugins
- });
+ [util__default["default"].inspect.custom]() {
+ return this.toJSON();
}
}
/**
- * @fileoverview Package exports for @eslint/eslintrc
- * @author Nicholas C. Zakas
+ * @fileoverview `ConfigArray` class.
+ * @author Toru Nagashima <https://github.com/mysticatea>
*/
-//-----------------------------------------------------------------------------
-// Exports
-//-----------------------------------------------------------------------------
+/**
+ * @fileoverview The factory of `ConfigArray` objects.
+ *
+ * This class provides methods to create `ConfigArray` instance.
+ *
+ * - `create(configData, options)`
+ * Create a `ConfigArray` instance from a config data. This is to handle CLI
+ * options except `--config`.
+ * - `loadFile(filePath, options)`
+ * Create a `ConfigArray` instance from a config file. This is to handle
+ * `--config` option. If the file was not found, throws the following error:
+ * - If the filename was `*.js`, a `MODULE_NOT_FOUND` error.
+ * - If the filename was `package.json`, an IO error or an
+ * `ESLINT_CONFIG_FIELD_NOT_FOUND` error.
+ * - Otherwise, an IO error such as `ENOENT`.
+ * - `loadInDirectory(directoryPath, options)`
+ * Create a `ConfigArray` instance from a config file which is on a given
+ * directory. This tries to load `.eslintrc.*` or `package.json`. If not
+ * found, returns an empty `ConfigArray`.
+ * - `loadESLintIgnore(filePath)`
+ * Create a `ConfigArray` instance from a config file that is `.eslintignore`
+ * format. This is to handle `--ignore-path` option.
+ * - `loadDefaultESLintIgnore()`
+ * Create a `ConfigArray` instance from `.eslintignore` or `package.json` in
+ * the current working directory.
+ *
+ * `ConfigArrayFactory` class has the responsibility that loads configuration
+ * files, including loading `extends`, `parser`, and `plugins`. The created
+ * `ConfigArray` instance has the loaded `extends`, `parser`, and `plugins`.
+ *
+ * But this class doesn't handle cascading. `CascadingConfigArrayFactory` class
+ * handles cascading and hierarchy.
+ *
+ * @author Toru Nagashima <https://github.com/mysticatea>
+ */
+const require$1 = Module.createRequire((typeof document === 'undefined' ? new ((__webpack_require__(892).URL))('file:' + __filename).href : (document.currentScript && document.currentScript.src || new URL('eslintrc.cjs', document.baseURI).href)));
-const Legacy = {
- ConfigArray,
- createConfigArrayFactoryContext: createContext,
- CascadingConfigArrayFactory,
- ConfigArrayFactory,
- ConfigDependency,
- ExtractedConfig,
- IgnorePattern,
- OverrideTester,
- getUsedExtractedConfigs,
- environments,
+const debug$2 = debugOrig__default["default"]("eslintrc:config-array-factory");
- // shared
- ConfigOps,
- ConfigValidator,
- ModuleResolver,
- naming
-};
+//------------------------------------------------------------------------------
+// Helpers
+//------------------------------------------------------------------------------
-exports.FlatCompat = FlatCompat;
-exports.Legacy = Legacy;
-//# sourceMappingURL=eslintrc.cjs.map
+const configFilenames = [
+ ".eslintrc.js",
+ ".eslintrc.cjs",
+ ".eslintrc.yaml",
+ ".eslintrc.yml",
+ ".eslintrc.json",
+ ".eslintrc",
+ "package.json"
+];
+
+// Define types for VSCode IntelliSense.
+/** @typedef {import("./shared/types").ConfigData} ConfigData */
+/** @typedef {import("./shared/types").OverrideConfigData} OverrideConfigData */
+/** @typedef {import("./shared/types").Parser} Parser */
+/** @typedef {import("./shared/types").Plugin} Plugin */
+/** @typedef {import("./shared/types").Rule} Rule */
+/** @typedef {import("./config-array/config-dependency").DependentParser} DependentParser */
+/** @typedef {import("./config-array/config-dependency").DependentPlugin} DependentPlugin */
+/** @typedef {ConfigArray[0]} ConfigArrayElement */
+/**
+ * @typedef {Object} ConfigArrayFactoryOptions
+ * @property {Map<string,Plugin>} [additionalPluginPool] The map for additional plugins.
+ * @property {string} [cwd] The path to the current working directory.
+ * @property {string} [resolvePluginsRelativeTo] A path to the directory that plugins should be resolved from. Defaults to `cwd`.
+ * @property {Map<string,Rule>} builtInRules The rules that are built in to ESLint.
+ * @property {Object} [resolver=ModuleResolver] The module resolver object.
+ * @property {string} eslintAllPath The path to the definitions for eslint:all.
+ * @property {string} eslintRecommendedPath The path to the definitions for eslint:recommended.
+ */
-/***/ }),
-/* 864 */
-/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+/**
+ * @typedef {Object} ConfigArrayFactoryInternalSlots
+ * @property {Map<string,Plugin>} additionalPluginPool The map for additional plugins.
+ * @property {string} cwd The path to the current working directory.
+ * @property {string | undefined} resolvePluginsRelativeTo An absolute path the the directory that plugins should be resolved from.
+ * @property {Map<string,Rule>} builtInRules The rules that are built in to ESLint.
+ * @property {Object} [resolver=ModuleResolver] The module resolver object.
+ * @property {string} eslintAllPath The path to the definitions for eslint:all.
+ * @property {string} eslintRecommendedPath The path to the definitions for eslint:recommended.
+ */
-"use strict";
+/**
+ * @typedef {Object} ConfigArrayFactoryLoadingContext
+ * @property {string} filePath The path to the current configuration.
+ * @property {string} matchBasePath The base path to resolve relative paths in `overrides[].files`, `overrides[].excludedFiles`, and `ignorePatterns`.
+ * @property {string} name The name of the current configuration.
+ * @property {string} pluginBasePath The base path to resolve plugins.
+ * @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.
+ */
+/**
+ * @typedef {Object} ConfigArrayFactoryLoadingContext
+ * @property {string} filePath The path to the current configuration.
+ * @property {string} matchBasePath The base path to resolve relative paths in `overrides[].files`, `overrides[].excludedFiles`, and `ignorePatterns`.
+ * @property {string} name The name of the current configuration.
+ * @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.
+ */
-const path = __webpack_require__(429);
+/** @type {WeakMap<ConfigArrayFactory, ConfigArrayFactoryInternalSlots>} */
+const internalSlotsMap$1 = new WeakMap();
-const resolveFrom = __webpack_require__(865);
+/**
+ * Check if a given string is a file path.
+ * @param {string} nameOrPath A module name or file path.
+ * @returns {boolean} `true` if the `nameOrPath` is a file path.
+ */
+function isFilePath(nameOrPath) {
+ return (
+ /^\.{1,2}[/\\]/u.test(nameOrPath) ||
+ path__default["default"].isAbsolute(nameOrPath)
+ );
+}
-const parentModule = __webpack_require__(867);
+/**
+ * Convenience wrapper for synchronously reading file contents.
+ * @param {string} filePath The filename to read.
+ * @returns {string} The file contents, with the BOM removed.
+ * @private
+ */
+function readFile(filePath) {
+ return fs__default["default"].readFileSync(filePath, "utf8").replace(/^\ufeff/u, "");
+}
-module.exports = moduleId => {
- if (typeof moduleId !== 'string') {
- throw new TypeError('Expected a string');
- }
+/**
+ * Loads a YAML configuration from a file.
+ * @param {string} filePath The filename to load.
+ * @returns {ConfigData} The configuration object from the file.
+ * @throws {Error} If the file cannot be read.
+ * @private
+ */
+function loadYAMLConfigFile(filePath) {
+ debug$2(`Loading YAML config file: ${filePath}`);
- const parentPath = parentModule(__filename);
- const cwd = parentPath ? path.dirname(parentPath) : __dirname;
- const filePath = resolveFrom(cwd, moduleId);
- const oldModule = __webpack_require__.c[filePath]; // Delete itself from module parent
+ // lazy load YAML to improve performance when not used
+ const yaml = require$1("js-yaml");
- if (oldModule && oldModule.parent) {
- let i = oldModule.parent.children.length;
+ try {
- while (i--) {
- if (oldModule.parent.children[i].id === filePath) {
- oldModule.parent.children.splice(i, 1);
- }
+ // empty YAML file can be null, so always use
+ return yaml.load(readFile(filePath)) || {};
+ } catch (e) {
+ debug$2(`Error reading YAML file: ${filePath}`);
+ e.message = `Cannot read config file: ${filePath}\nError: ${e.message}`;
+ throw e;
}
- }
+}
- delete __webpack_require__.c[filePath]; // Delete module from cache
+/**
+ * Loads a JSON configuration from a file.
+ * @param {string} filePath The filename to load.
+ * @returns {ConfigData} The configuration object from the file.
+ * @throws {Error} If the file cannot be read.
+ * @private
+ */
+function loadJSONConfigFile(filePath) {
+ debug$2(`Loading JSON config file: ${filePath}`);
- const parent = __webpack_require__.c[parentPath]; // If `filePath` and `parentPath` are the same, cache will already be deleted so we won't get a memory leak in next step
+ try {
+ return JSON.parse(stripComments__default["default"](readFile(filePath)));
+ } catch (e) {
+ debug$2(`Error reading JSON file: ${filePath}`);
+ e.message = `Cannot read config file: ${filePath}\nError: ${e.message}`;
+ e.messageTemplate = "failed-to-read-json";
+ e.messageData = {
+ path: filePath,
+ message: e.message
+ };
+ throw e;
+ }
+}
- return parent === undefined ? __webpack_require__(869)(filePath) : parent.require(filePath); // In case cache doesn't have parent, fall back to normal require
-};
+/**
+ * Loads a legacy (.eslintrc) configuration from a file.
+ * @param {string} filePath The filename to load.
+ * @returns {ConfigData} The configuration object from the file.
+ * @throws {Error} If the file cannot be read.
+ * @private
+ */
+function loadLegacyConfigFile(filePath) {
+ debug$2(`Loading legacy config file: ${filePath}`);
-/***/ }),
-/* 865 */
-/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+ // lazy load YAML to improve performance when not used
+ const yaml = require$1("js-yaml");
-"use strict";
+ try {
+ return yaml.load(stripComments__default["default"](readFile(filePath))) || /* istanbul ignore next */ {};
+ } catch (e) {
+ debug$2("Error reading YAML file: %s\n%o", filePath, e);
+ e.message = `Cannot read config file: ${filePath}\nError: ${e.message}`;
+ throw e;
+ }
+}
+/**
+ * Loads a JavaScript configuration from a file.
+ * @param {string} filePath The filename to load.
+ * @returns {ConfigData} The configuration object from the file.
+ * @throws {Error} If the file cannot be read.
+ * @private
+ */
+function loadJSConfigFile(filePath) {
+ debug$2(`Loading JS config file: ${filePath}`);
+ try {
+ return importFresh__default["default"](filePath);
+ } catch (e) {
+ debug$2(`Error reading JavaScript file: ${filePath}`);
+ e.message = `Cannot read config file: ${filePath}\nError: ${e.message}`;
+ throw e;
+ }
+}
-const path = __webpack_require__(429);
+/**
+ * Loads a configuration from a package.json file.
+ * @param {string} filePath The filename to load.
+ * @returns {ConfigData} The configuration object from the file.
+ * @throws {Error} If the file cannot be read.
+ * @private
+ */
+function loadPackageJSONConfigFile(filePath) {
+ debug$2(`Loading package.json config file: ${filePath}`);
+ try {
+ const packageData = loadJSONConfigFile(filePath);
-const Module = __webpack_require__(866);
+ if (!Object.hasOwnProperty.call(packageData, "eslintConfig")) {
+ throw Object.assign(
+ new Error("package.json file doesn't have 'eslintConfig' field."),
+ { code: "ESLINT_CONFIG_FIELD_NOT_FOUND" }
+ );
+ }
-const fs = __webpack_require__(861);
+ return packageData.eslintConfig;
+ } catch (e) {
+ debug$2(`Error reading package.json file: ${filePath}`);
+ e.message = `Cannot read config file: ${filePath}\nError: ${e.message}`;
+ throw e;
+ }
+}
-const resolveFrom = (fromDir, moduleId, silent) => {
- if (typeof fromDir !== 'string') {
- throw new TypeError("Expected `fromDir` to be of type `string`, got `".concat(typeof fromDir, "`"));
- }
+/**
+ * Loads a `.eslintignore` from a file.
+ * @param {string} filePath The filename to load.
+ * @returns {string[]} The ignore patterns from the file.
+ * @private
+ */
+function loadESLintIgnoreFile(filePath) {
+ debug$2(`Loading .eslintignore file: ${filePath}`);
- if (typeof moduleId !== 'string') {
- throw new TypeError("Expected `moduleId` to be of type `string`, got `".concat(typeof moduleId, "`"));
- }
+ try {
+ return readFile(filePath)
+ .split(/\r?\n/gu)
+ .filter(line => line.trim() !== "" && !line.startsWith("#"));
+ } catch (e) {
+ debug$2(`Error reading .eslintignore file: ${filePath}`);
+ e.message = `Cannot read .eslintignore file: ${filePath}\nError: ${e.message}`;
+ throw e;
+ }
+}
- try {
- fromDir = fs.realpathSync(fromDir);
- } catch (err) {
- if (err.code === 'ENOENT') {
- fromDir = path.resolve(fromDir);
- } else if (silent) {
- return null;
- } else {
- throw err;
+/**
+ * Creates an error to notify about a missing config to extend from.
+ * @param {string} configName The name of the missing config.
+ * @param {string} importerName The name of the config that imported the missing config
+ * @param {string} messageTemplate The text template to source error strings from.
+ * @returns {Error} The error object to throw
+ * @private
+ */
+function configInvalidError(configName, importerName, messageTemplate) {
+ return Object.assign(
+ new Error(`Failed to load config "${configName}" to extend from.`),
+ {
+ messageTemplate,
+ messageData: { configName, importerName }
+ }
+ );
+}
+
+/**
+ * Loads a configuration file regardless of the source. Inspects the file path
+ * to determine the correctly way to load the config file.
+ * @param {string} filePath The path to the configuration.
+ * @returns {ConfigData|null} The configuration information.
+ * @private
+ */
+function loadConfigFile(filePath) {
+ switch (path__default["default"].extname(filePath)) {
+ case ".js":
+ case ".cjs":
+ return loadJSConfigFile(filePath);
+
+ case ".json":
+ if (path__default["default"].basename(filePath) === "package.json") {
+ return loadPackageJSONConfigFile(filePath);
+ }
+ return loadJSONConfigFile(filePath);
+
+ case ".yaml":
+ case ".yml":
+ return loadYAMLConfigFile(filePath);
+
+ default:
+ return loadLegacyConfigFile(filePath);
}
- }
+}
- const fromFile = path.join(fromDir, 'noop.js');
+/**
+ * Write debug log.
+ * @param {string} request The requested module name.
+ * @param {string} relativeTo The file path to resolve the request relative to.
+ * @param {string} filePath The resolved file path.
+ * @returns {void}
+ */
+function writeDebugLogForLoading(request, relativeTo, filePath) {
+ /* istanbul ignore next */
+ if (debug$2.enabled) {
+ let nameAndVersion = null;
- const resolveFileName = () => Module._resolveFilename(moduleId, {
- id: fromFile,
- filename: fromFile,
- paths: Module._nodeModulePaths(fromDir)
- });
+ try {
+ const packageJsonPath = resolve(
+ `${request}/package.json`,
+ relativeTo
+ );
+ const { version = "unknown" } = require$1(packageJsonPath);
- if (silent) {
- try {
- return resolveFileName();
- } catch (err) {
- return null;
+ nameAndVersion = `${request}@${version}`;
+ } catch (error) {
+ debug$2("package.json was not found:", error.message);
+ nameAndVersion = request;
+ }
+
+ debug$2("Loaded: %s (%s)", nameAndVersion, filePath);
}
- }
+}
- return resolveFileName();
-};
+/**
+ * Create a new context with default values.
+ * @param {ConfigArrayFactoryInternalSlots} slots The internal slots.
+ * @param {"config" | "ignore" | "implicit-processor" | undefined} providedType The type of the current configuration. Default is `"config"`.
+ * @param {string | undefined} providedName The name of the current configuration. Default is the relative path from `cwd` to `filePath`.
+ * @param {string | undefined} providedFilePath The path to the current configuration. Default is empty string.
+ * @param {string | undefined} providedMatchBasePath The type of the current configuration. Default is the directory of `filePath` or `cwd`.
+ * @returns {ConfigArrayFactoryLoadingContext} The created context.
+ */
+function createContext(
+ { cwd, resolvePluginsRelativeTo },
+ providedType,
+ providedName,
+ providedFilePath,
+ providedMatchBasePath
+) {
+ const filePath = providedFilePath
+ ? path__default["default"].resolve(cwd, providedFilePath)
+ : "";
+ const matchBasePath =
+ (providedMatchBasePath && path__default["default"].resolve(cwd, providedMatchBasePath)) ||
+ (filePath && path__default["default"].dirname(filePath)) ||
+ cwd;
+ const name =
+ providedName ||
+ (filePath && path__default["default"].relative(cwd, filePath)) ||
+ "";
+ const pluginBasePath =
+ resolvePluginsRelativeTo ||
+ (filePath && path__default["default"].dirname(filePath)) ||
+ cwd;
+ const type = providedType || "config";
-module.exports = (fromDir, moduleId) => resolveFrom(fromDir, moduleId);
+ return { filePath, matchBasePath, name, pluginBasePath, type };
+}
-module.exports.silent = (fromDir, moduleId) => resolveFrom(fromDir, moduleId, true);
+/**
+ * Normalize a given plugin.
+ * - Ensure the object to have four properties: configs, environments, processors, and rules.
+ * - Ensure the object to not have other properties.
+ * @param {Plugin} plugin The plugin to normalize.
+ * @returns {Plugin} The normalized plugin.
+ */
+function normalizePlugin(plugin) {
+ return {
+ configs: plugin.configs || {},
+ environments: plugin.environments || {},
+ processors: plugin.processors || {},
+ rules: plugin.rules || {}
+ };
+}
-/***/ }),
-/* 866 */
-/***/ ((module) => {
+//------------------------------------------------------------------------------
+// Public Interface
+//------------------------------------------------------------------------------
+
+/**
+ * The factory of `ConfigArray` objects.
+ */
+class ConfigArrayFactory {
+
+ /**
+ * Initialize this instance.
+ * @param {ConfigArrayFactoryOptions} [options] The map for additional plugins.
+ */
+ constructor({
+ additionalPluginPool = new Map(),
+ cwd = process.cwd(),
+ resolvePluginsRelativeTo,
+ builtInRules,
+ resolver = ModuleResolver,
+ eslintAllPath,
+ eslintRecommendedPath
+ } = {}) {
+ internalSlotsMap$1.set(this, {
+ additionalPluginPool,
+ cwd,
+ resolvePluginsRelativeTo:
+ resolvePluginsRelativeTo &&
+ path__default["default"].resolve(cwd, resolvePluginsRelativeTo),
+ builtInRules,
+ resolver,
+ eslintAllPath,
+ eslintRecommendedPath
+ });
+ }
-"use strict";
-module.exports = require("module");
+ /**
+ * Create `ConfigArray` instance from a config data.
+ * @param {ConfigData|null} configData The config data to create.
+ * @param {Object} [options] The options.
+ * @param {string} [options.basePath] The base path to resolve relative paths in `overrides[].files`, `overrides[].excludedFiles`, and `ignorePatterns`.
+ * @param {string} [options.filePath] The path to this config data.
+ * @param {string} [options.name] The config name.
+ * @returns {ConfigArray} Loaded config.
+ */
+ create(configData, { basePath, filePath, name } = {}) {
+ if (!configData) {
+ return new ConfigArray();
+ }
-/***/ }),
-/* 867 */
-/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+ const slots = internalSlotsMap$1.get(this);
+ const ctx = createContext(slots, "config", name, filePath, basePath);
+ const elements = this._normalizeConfigData(configData, ctx);
-"use strict";
+ return new ConfigArray(...elements);
+ }
+ /**
+ * Load a config file.
+ * @param {string} filePath The path to a config file.
+ * @param {Object} [options] The options.
+ * @param {string} [options.basePath] The base path to resolve relative paths in `overrides[].files`, `overrides[].excludedFiles`, and `ignorePatterns`.
+ * @param {string} [options.name] The config name.
+ * @returns {ConfigArray} Loaded config.
+ */
+ loadFile(filePath, { basePath, name } = {}) {
+ const slots = internalSlotsMap$1.get(this);
+ const ctx = createContext(slots, "config", name, filePath, basePath);
-const callsites = __webpack_require__(868);
+ return new ConfigArray(...this._loadConfigData(ctx));
+ }
-module.exports = filepath => {
- const stacks = callsites();
+ /**
+ * Load the config file on a given directory if exists.
+ * @param {string} directoryPath The path to a directory.
+ * @param {Object} [options] The options.
+ * @param {string} [options.basePath] The base path to resolve relative paths in `overrides[].files`, `overrides[].excludedFiles`, and `ignorePatterns`.
+ * @param {string} [options.name] The config name.
+ * @returns {ConfigArray} Loaded config. An empty `ConfigArray` if any config doesn't exist.
+ */
+ loadInDirectory(directoryPath, { basePath, name } = {}) {
+ const slots = internalSlotsMap$1.get(this);
- if (!filepath) {
- return stacks[2].getFileName();
- }
+ for (const filename of configFilenames) {
+ const ctx = createContext(
+ slots,
+ "config",
+ name,
+ path__default["default"].join(directoryPath, filename),
+ basePath
+ );
- let seenVal = false; // Skip the first stack as it's this function
+ if (fs__default["default"].existsSync(ctx.filePath) && fs__default["default"].statSync(ctx.filePath).isFile()) {
+ let configData;
- stacks.shift();
+ try {
+ configData = loadConfigFile(ctx.filePath);
+ } catch (error) {
+ if (!error || error.code !== "ESLINT_CONFIG_FIELD_NOT_FOUND") {
+ throw error;
+ }
+ }
- for (const stack of stacks) {
- const parentFilepath = stack.getFileName();
+ if (configData) {
+ debug$2(`Config file found: ${ctx.filePath}`);
+ return new ConfigArray(
+ ...this._normalizeConfigData(configData, ctx)
+ );
+ }
+ }
+ }
- if (typeof parentFilepath !== 'string') {
- continue;
+ debug$2(`Config file not found on ${directoryPath}`);
+ return new ConfigArray();
}
- if (parentFilepath === filepath) {
- seenVal = true;
- continue;
- } // Skip native modules
-
-
- if (parentFilepath === 'module.js') {
- continue;
- }
+ /**
+ * Check if a config file on a given directory exists or not.
+ * @param {string} directoryPath The path to a directory.
+ * @returns {string | null} The path to the found config file. If not found then null.
+ */
+ static getPathToConfigFileInDirectory(directoryPath) {
+ for (const filename of configFilenames) {
+ const filePath = path__default["default"].join(directoryPath, filename);
- if (seenVal && parentFilepath !== filepath) {
- return parentFilepath;
+ if (fs__default["default"].existsSync(filePath)) {
+ if (filename === "package.json") {
+ try {
+ loadPackageJSONConfigFile(filePath);
+ return filePath;
+ } catch { /* ignore */ }
+ } else {
+ return filePath;
+ }
+ }
+ }
+ return null;
}
- }
-};
-/***/ }),
-/* 868 */
-/***/ ((module) => {
-
-"use strict";
+ /**
+ * Load `.eslintignore` file.
+ * @param {string} filePath The path to a `.eslintignore` file to load.
+ * @returns {ConfigArray} Loaded config. An empty `ConfigArray` if any config doesn't exist.
+ */
+ loadESLintIgnore(filePath) {
+ const slots = internalSlotsMap$1.get(this);
+ const ctx = createContext(
+ slots,
+ "ignore",
+ void 0,
+ filePath,
+ slots.cwd
+ );
+ const ignorePatterns = loadESLintIgnoreFile(ctx.filePath);
+ return new ConfigArray(
+ ...this._normalizeESLintIgnoreData(ignorePatterns, ctx)
+ );
+ }
-const callsites = () => {
- const _prepareStackTrace = Error.prepareStackTrace;
+ /**
+ * Load `.eslintignore` file in the current working directory.
+ * @returns {ConfigArray} Loaded config. An empty `ConfigArray` if any config doesn't exist.
+ */
+ loadDefaultESLintIgnore() {
+ const slots = internalSlotsMap$1.get(this);
+ const eslintIgnorePath = path__default["default"].resolve(slots.cwd, ".eslintignore");
+ const packageJsonPath = path__default["default"].resolve(slots.cwd, "package.json");
- Error.prepareStackTrace = (_, stack) => stack;
+ if (fs__default["default"].existsSync(eslintIgnorePath)) {
+ return this.loadESLintIgnore(eslintIgnorePath);
+ }
+ if (fs__default["default"].existsSync(packageJsonPath)) {
+ const data = loadJSONConfigFile(packageJsonPath);
- const stack = new Error().stack.slice(1);
- Error.prepareStackTrace = _prepareStackTrace;
- return stack;
-};
+ if (Object.hasOwnProperty.call(data, "eslintIgnore")) {
+ if (!Array.isArray(data.eslintIgnore)) {
+ throw new Error("Package.json eslintIgnore property requires an array of paths");
+ }
+ const ctx = createContext(
+ slots,
+ "ignore",
+ "eslintIgnore in package.json",
+ packageJsonPath,
+ slots.cwd
+ );
-module.exports = callsites; // TODO: Remove this for the next major release
+ return new ConfigArray(
+ ...this._normalizeESLintIgnoreData(data.eslintIgnore, ctx)
+ );
+ }
+ }
-module.exports["default"] = callsites;
+ return new ConfigArray();
+ }
-/***/ }),
-/* 869 */
-/***/ ((module) => {
+ /**
+ * Load a given config file.
+ * @param {ConfigArrayFactoryLoadingContext} ctx The loading context.
+ * @returns {IterableIterator<ConfigArrayElement>} Loaded config.
+ * @private
+ */
+ _loadConfigData(ctx) {
+ return this._normalizeConfigData(loadConfigFile(ctx.filePath), ctx);
+ }
-function webpackEmptyContext(req) {
- var e = new Error("Cannot find module '" + req + "'");
- e.code = 'MODULE_NOT_FOUND';
- throw e;
-}
-webpackEmptyContext.keys = () => ([]);
-webpackEmptyContext.resolve = webpackEmptyContext;
-webpackEmptyContext.id = 869;
-module.exports = webpackEmptyContext;
+ /**
+ * Normalize a given `.eslintignore` data to config array elements.
+ * @param {string[]} ignorePatterns The patterns to ignore files.
+ * @param {ConfigArrayFactoryLoadingContext} ctx The loading context.
+ * @returns {IterableIterator<ConfigArrayElement>} The normalized config.
+ * @private
+ */
+ *_normalizeESLintIgnoreData(ignorePatterns, ctx) {
+ const elements = this._normalizeObjectConfigData(
+ { ignorePatterns },
+ ctx
+ );
-/***/ }),
-/* 870 */
-/***/ ((module) => {
+ // Set `ignorePattern.loose` flag for backward compatibility.
+ for (const element of elements) {
+ if (element.ignorePattern) {
+ element.ignorePattern.loose = true;
+ }
+ yield element;
+ }
+ }
-"use strict";
+ /**
+ * Normalize a given config to an array.
+ * @param {ConfigData} configData The config data to normalize.
+ * @param {ConfigArrayFactoryLoadingContext} ctx The loading context.
+ * @returns {IterableIterator<ConfigArrayElement>} The normalized config.
+ * @private
+ */
+ _normalizeConfigData(configData, ctx) {
+ const validator = new ConfigValidator();
+ validator.validateConfigSchema(configData, ctx.name || ctx.filePath);
+ return this._normalizeObjectConfigData(configData, ctx);
+ }
-const singleComment = Symbol('singleComment');
-const multiComment = Symbol('multiComment');
+ /**
+ * Normalize a given config to an array.
+ * @param {ConfigData|OverrideConfigData} configData The config data to normalize.
+ * @param {ConfigArrayFactoryLoadingContext} ctx The loading context.
+ * @returns {IterableIterator<ConfigArrayElement>} The normalized config.
+ * @private
+ */
+ *_normalizeObjectConfigData(configData, ctx) {
+ const { files, excludedFiles, ...configBody } = configData;
+ const criteria = OverrideTester.create(
+ files,
+ excludedFiles,
+ ctx.matchBasePath
+ );
+ const elements = this._normalizeObjectConfigDataBody(configBody, ctx);
-const stripWithoutWhitespace = () => '';
+ // Apply the criteria to every element.
+ for (const element of elements) {
-const stripWithWhitespace = (string, start, end) => string.slice(start, end).replace(/\S/g, ' ');
+ /*
+ * Merge the criteria.
+ * This is for the `overrides` entries that came from the
+ * configurations of `overrides[].extends`.
+ */
+ element.criteria = OverrideTester.and(criteria, element.criteria);
-const isEscaped = (jsonString, quotePosition) => {
- let index = quotePosition - 1;
- let backslashCount = 0;
+ /*
+ * Remove `root` property to ignore `root` settings which came from
+ * `extends` in `overrides`.
+ */
+ if (element.criteria) {
+ element.root = void 0;
+ }
- while (jsonString[index] === '\\') {
- index -= 1;
- backslashCount += 1;
- }
+ yield element;
+ }
+ }
- return Boolean(backslashCount % 2);
-};
+ /**
+ * Normalize a given config to an array.
+ * @param {ConfigData} configData The config data to normalize.
+ * @param {ConfigArrayFactoryLoadingContext} ctx The loading context.
+ * @returns {IterableIterator<ConfigArrayElement>} The normalized config.
+ * @private
+ */
+ *_normalizeObjectConfigDataBody(
+ {
+ env,
+ extends: extend,
+ globals,
+ ignorePatterns,
+ noInlineConfig,
+ parser: parserName,
+ parserOptions,
+ plugins: pluginList,
+ processor,
+ reportUnusedDisableDirectives,
+ root,
+ rules,
+ settings,
+ overrides: overrideList = []
+ },
+ ctx
+ ) {
+ const extendList = Array.isArray(extend) ? extend : [extend];
+ const ignorePattern = ignorePatterns && new IgnorePattern(
+ Array.isArray(ignorePatterns) ? ignorePatterns : [ignorePatterns],
+ ctx.matchBasePath
+ );
-module.exports = function (jsonString) {
- let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
+ // Flatten `extends`.
+ for (const extendName of extendList.filter(Boolean)) {
+ yield* this._loadExtends(extendName, ctx);
+ }
- if (typeof jsonString !== 'string') {
- throw new TypeError("Expected argument `jsonString` to be a `string`, got `".concat(typeof jsonString, "`"));
- }
+ // Load parser & plugins.
+ const parser = parserName && this._loadParser(parserName, ctx);
+ const plugins = pluginList && this._loadPlugins(pluginList, ctx);
- const strip = options.whitespace === false ? stripWithoutWhitespace : stripWithWhitespace;
- let insideString = false;
- let insideComment = false;
- let offset = 0;
- let result = '';
+ // Yield pseudo config data for file extension processors.
+ if (plugins) {
+ yield* this._takeFileExtensionProcessors(plugins, ctx);
+ }
- for (let i = 0; i < jsonString.length; i++) {
- const currentCharacter = jsonString[i];
- const nextCharacter = jsonString[i + 1];
+ // Yield the config data except `extends` and `overrides`.
+ yield {
- if (!insideComment && currentCharacter === '"') {
- const escaped = isEscaped(jsonString, i);
+ // Debug information.
+ type: ctx.type,
+ name: ctx.name,
+ filePath: ctx.filePath,
- if (!escaped) {
- insideString = !insideString;
- }
- }
+ // Config data.
+ criteria: null,
+ env,
+ globals,
+ ignorePattern,
+ noInlineConfig,
+ parser,
+ parserOptions,
+ plugins,
+ processor,
+ reportUnusedDisableDirectives,
+ root,
+ rules,
+ settings
+ };
- if (insideString) {
- continue;
+ // Flatten `overries`.
+ for (let i = 0; i < overrideList.length; ++i) {
+ yield* this._normalizeObjectConfigData(
+ overrideList[i],
+ { ...ctx, name: `${ctx.name}#overrides[${i}]` }
+ );
+ }
}
- if (!insideComment && currentCharacter + nextCharacter === '//') {
- result += jsonString.slice(offset, i);
- offset = i;
- insideComment = singleComment;
- i++;
- } else if (insideComment === singleComment && currentCharacter + nextCharacter === '\r\n') {
- i++;
- insideComment = false;
- result += strip(jsonString, offset, i);
- offset = i;
- continue;
- } else if (insideComment === singleComment && currentCharacter === '\n') {
- insideComment = false;
- result += strip(jsonString, offset, i);
- offset = i;
- } else if (!insideComment && currentCharacter + nextCharacter === '/*') {
- result += jsonString.slice(offset, i);
- offset = i;
- insideComment = multiComment;
- i++;
- continue;
- } else if (insideComment === multiComment && currentCharacter + nextCharacter === '*/') {
- i++;
- insideComment = false;
- result += strip(jsonString, offset, i + 1);
- offset = i + 1;
- continue;
+ /**
+ * Load configs of an element in `extends`.
+ * @param {string} extendName The name of a base config.
+ * @param {ConfigArrayFactoryLoadingContext} ctx The loading context.
+ * @returns {IterableIterator<ConfigArrayElement>} The normalized config.
+ * @private
+ */
+ _loadExtends(extendName, ctx) {
+ debug$2("Loading {extends:%j} relative to %s", extendName, ctx.filePath);
+ try {
+ if (extendName.startsWith("eslint:")) {
+ return this._loadExtendedBuiltInConfig(extendName, ctx);
+ }
+ if (extendName.startsWith("plugin:")) {
+ return this._loadExtendedPluginConfig(extendName, ctx);
+ }
+ return this._loadExtendedShareableConfig(extendName, ctx);
+ } catch (error) {
+ error.message += `\nReferenced from: ${ctx.filePath || ctx.name}`;
+ throw error;
+ }
}
- }
-
- return result + (insideComment ? strip(jsonString.slice(offset)) : jsonString.slice(offset));
-};
-
-/***/ }),
-/* 871 */
-/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
-/* provided dependency */ var console = __webpack_require__(438);
-module.exports = minimatch;
-minimatch.Minimatch = Minimatch;
-var path = {
- sep: '/'
-};
+ /**
+ * Load configs of an element in `extends`.
+ * @param {string} extendName The name of a base config.
+ * @param {ConfigArrayFactoryLoadingContext} ctx The loading context.
+ * @returns {IterableIterator<ConfigArrayElement>} The normalized config.
+ * @private
+ */
+ _loadExtendedBuiltInConfig(extendName, ctx) {
+ const { eslintAllPath, eslintRecommendedPath } = internalSlotsMap$1.get(this);
-try {
- path = __webpack_require__(429);
-} catch (er) {}
+ if (extendName === "eslint:recommended") {
+ return this._loadConfigData({
+ ...ctx,
+ filePath: eslintRecommendedPath,
+ name: `${ctx.name} » ${extendName}`
+ });
+ }
+ if (extendName === "eslint:all") {
+ return this._loadConfigData({
+ ...ctx,
+ filePath: eslintAllPath,
+ name: `${ctx.name} » ${extendName}`
+ });
+ }
-var GLOBSTAR = minimatch.GLOBSTAR = Minimatch.GLOBSTAR = {};
+ throw configInvalidError(extendName, ctx.name, "extend-config-missing");
+ }
-var expand = __webpack_require__(872);
+ /**
+ * Load configs of an element in `extends`.
+ * @param {string} extendName The name of a base config.
+ * @param {ConfigArrayFactoryLoadingContext} ctx The loading context.
+ * @returns {IterableIterator<ConfigArrayElement>} The normalized config.
+ * @private
+ */
+ _loadExtendedPluginConfig(extendName, ctx) {
+ const slashIndex = extendName.lastIndexOf("/");
-var plTypes = {
- '!': {
- open: '(?:(?!(?:',
- close: '))[^/]*?)'
- },
- '?': {
- open: '(?:',
- close: ')?'
- },
- '+': {
- open: '(?:',
- close: ')+'
- },
- '*': {
- open: '(?:',
- close: ')*'
- },
- '@': {
- open: '(?:',
- close: ')'
- }
-}; // any single thing other than /
-// don't need to escape / when using new RegExp()
+ if (slashIndex === -1) {
+ throw configInvalidError(extendName, ctx.filePath, "plugin-invalid");
+ }
-var qmark = '[^/]'; // * => any number of characters
+ const pluginName = extendName.slice("plugin:".length, slashIndex);
+ const configName = extendName.slice(slashIndex + 1);
-var star = qmark + '*?'; // ** when dots are allowed. Anything goes, except .. and .
-// not (^ or / followed by one or two dots followed by $ or /),
-// followed by anything, any number of times.
+ if (isFilePath(pluginName)) {
+ throw new Error("'extends' cannot use a file path for plugins.");
+ }
-var twoStarDot = '(?:(?!(?:\\\/|^)(?:\\.{1,2})($|\\\/)).)*?'; // not a ^ or / followed by a dot,
-// followed by anything, any number of times.
+ const plugin = this._loadPlugin(pluginName, ctx);
+ const configData =
+ plugin.definition &&
+ plugin.definition.configs[configName];
-var twoStarNoDot = '(?:(?!(?:\\\/|^)\\.).)*?'; // characters that need to be escaped in RegExp.
+ if (configData) {
+ return this._normalizeConfigData(configData, {
+ ...ctx,
+ filePath: plugin.filePath || ctx.filePath,
+ name: `${ctx.name} » plugin:${plugin.id}/${configName}`
+ });
+ }
-var reSpecials = charSet('().*{}+?[]^$\\!'); // "abc" -> { a:true, b:true, c:true }
+ throw plugin.error || configInvalidError(extendName, ctx.filePath, "extend-config-missing");
+ }
-function charSet(s) {
- return s.split('').reduce(function (set, c) {
- set[c] = true;
- return set;
- }, {});
-} // normalizes slashes.
+ /**
+ * Load configs of an element in `extends`.
+ * @param {string} extendName The name of a base config.
+ * @param {ConfigArrayFactoryLoadingContext} ctx The loading context.
+ * @returns {IterableIterator<ConfigArrayElement>} The normalized config.
+ * @private
+ */
+ _loadExtendedShareableConfig(extendName, ctx) {
+ const { cwd, resolver } = internalSlotsMap$1.get(this);
+ const relativeTo = ctx.filePath || path__default["default"].join(cwd, "__placeholder__.js");
+ let request;
+ if (isFilePath(extendName)) {
+ request = extendName;
+ } else if (extendName.startsWith(".")) {
+ request = `./${extendName}`; // For backward compatibility. A ton of tests depended on this behavior.
+ } else {
+ request = normalizePackageName(
+ extendName,
+ "eslint-config"
+ );
+ }
-var slashSplit = /\/+/;
-minimatch.filter = filter;
+ let filePath;
-function filter(pattern, options) {
- options = options || {};
- return function (p, i, list) {
- return minimatch(p, pattern, options);
- };
-}
+ try {
+ filePath = resolver.resolve(request, relativeTo);
+ } catch (error) {
+ /* istanbul ignore else */
+ if (error && error.code === "MODULE_NOT_FOUND") {
+ throw configInvalidError(extendName, ctx.filePath, "extend-config-missing");
+ }
+ throw error;
+ }
-function ext(a, b) {
- a = a || {};
- b = b || {};
- var t = {};
- Object.keys(b).forEach(function (k) {
- t[k] = b[k];
- });
- Object.keys(a).forEach(function (k) {
- t[k] = a[k];
- });
- return t;
-}
+ writeDebugLogForLoading(request, relativeTo, filePath);
+ return this._loadConfigData({
+ ...ctx,
+ filePath,
+ name: `${ctx.name} » ${request}`
+ });
+ }
-minimatch.defaults = function (def) {
- if (!def || !Object.keys(def).length) return minimatch;
- var orig = minimatch;
+ /**
+ * Load given plugins.
+ * @param {string[]} names The plugin names to load.
+ * @param {ConfigArrayFactoryLoadingContext} ctx The loading context.
+ * @returns {Record<string,DependentPlugin>} The loaded parser.
+ * @private
+ */
+ _loadPlugins(names, ctx) {
+ return names.reduce((map, name) => {
+ if (isFilePath(name)) {
+ throw new Error("Plugins array cannot includes file paths.");
+ }
+ const plugin = this._loadPlugin(name, ctx);
- var m = function minimatch(p, pattern, options) {
- return orig.minimatch(p, pattern, ext(def, options));
- };
+ map[plugin.id] = plugin;
- m.Minimatch = function Minimatch(pattern, options) {
- return new orig.Minimatch(pattern, ext(def, options));
- };
+ return map;
+ }, {});
+ }
- return m;
-};
+ /**
+ * Load a given parser.
+ * @param {string} nameOrPath The package name or the path to a parser file.
+ * @param {ConfigArrayFactoryLoadingContext} ctx The loading context.
+ * @returns {DependentParser} The loaded parser.
+ */
+ _loadParser(nameOrPath, ctx) {
+ debug$2("Loading parser %j from %s", nameOrPath, ctx.filePath);
-Minimatch.defaults = function (def) {
- if (!def || !Object.keys(def).length) return Minimatch;
- return minimatch.defaults(def).Minimatch;
-};
+ const { cwd, resolver } = internalSlotsMap$1.get(this);
+ const relativeTo = ctx.filePath || path__default["default"].join(cwd, "__placeholder__.js");
-function minimatch(p, pattern, options) {
- if (typeof pattern !== 'string') {
- throw new TypeError('glob pattern string required');
- }
+ try {
+ const filePath = resolver.resolve(nameOrPath, relativeTo);
- if (!options) options = {}; // shortcut: comments match nothing.
+ writeDebugLogForLoading(nameOrPath, relativeTo, filePath);
- if (!options.nocomment && pattern.charAt(0) === '#') {
- return false;
- } // "" only matches ""
+ return new ConfigDependency({
+ definition: require$1(filePath),
+ filePath,
+ id: nameOrPath,
+ importerName: ctx.name,
+ importerPath: ctx.filePath
+ });
+ } catch (error) {
+ // If the parser name is "espree", load the espree of ESLint.
+ if (nameOrPath === "espree") {
+ debug$2("Fallback espree.");
+ return new ConfigDependency({
+ definition: require$1("espree"),
+ filePath: require$1.resolve("espree"),
+ id: nameOrPath,
+ importerName: ctx.name,
+ importerPath: ctx.filePath
+ });
+ }
- if (pattern.trim() === '') return p === '';
- return new Minimatch(pattern, options).match(p);
-}
+ debug$2("Failed to load parser '%s' declared in '%s'.", nameOrPath, ctx.name);
+ error.message = `Failed to load parser '${nameOrPath}' declared in '${ctx.name}': ${error.message}`;
-function Minimatch(pattern, options) {
- if (!(this instanceof Minimatch)) {
- return new Minimatch(pattern, options);
- }
+ return new ConfigDependency({
+ error,
+ id: nameOrPath,
+ importerName: ctx.name,
+ importerPath: ctx.filePath
+ });
+ }
+ }
- if (typeof pattern !== 'string') {
- throw new TypeError('glob pattern string required');
- }
+ /**
+ * Load a given plugin.
+ * @param {string} name The plugin name to load.
+ * @param {ConfigArrayFactoryLoadingContext} ctx The loading context.
+ * @returns {DependentPlugin} The loaded plugin.
+ * @private
+ */
+ _loadPlugin(name, ctx) {
+ debug$2("Loading plugin %j from %s", name, ctx.filePath);
- if (!options) options = {};
- pattern = pattern.trim(); // windows support: need to use /, not \
+ const { additionalPluginPool, resolver } = internalSlotsMap$1.get(this);
+ const request = normalizePackageName(name, "eslint-plugin");
+ const id = getShorthandName(request, "eslint-plugin");
+ const relativeTo = path__default["default"].join(ctx.pluginBasePath, "__placeholder__.js");
- if (path.sep !== '/') {
- pattern = pattern.split(path.sep).join('/');
- }
+ if (name.match(/\s+/u)) {
+ const error = Object.assign(
+ new Error(`Whitespace found in plugin name '${name}'`),
+ {
+ messageTemplate: "whitespace-found",
+ messageData: { pluginName: request }
+ }
+ );
- this.options = options;
- this.set = [];
- this.pattern = pattern;
- this.regexp = null;
- this.negate = false;
- this.comment = false;
- this.empty = false; // make the set of regexps etc.
+ return new ConfigDependency({
+ error,
+ id,
+ importerName: ctx.name,
+ importerPath: ctx.filePath
+ });
+ }
- this.make();
-}
+ // Check for additional pool.
+ const plugin =
+ additionalPluginPool.get(request) ||
+ additionalPluginPool.get(id);
-Minimatch.prototype.debug = function () {};
+ if (plugin) {
+ return new ConfigDependency({
+ definition: normalizePlugin(plugin),
+ filePath: "", // It's unknown where the plugin came from.
+ id,
+ importerName: ctx.name,
+ importerPath: ctx.filePath
+ });
+ }
-Minimatch.prototype.make = make;
+ let filePath;
+ let error;
-function make() {
- // don't do it more than once.
- if (this._made) return;
- var pattern = this.pattern;
- var options = this.options; // empty patterns and comments match nothing.
+ try {
+ filePath = resolver.resolve(request, relativeTo);
+ } catch (resolveError) {
+ error = resolveError;
+ /* istanbul ignore else */
+ if (error && error.code === "MODULE_NOT_FOUND") {
+ error.messageTemplate = "plugin-missing";
+ error.messageData = {
+ pluginName: request,
+ resolvePluginsRelativeTo: ctx.pluginBasePath,
+ importerName: ctx.name
+ };
+ }
+ }
- if (!options.nocomment && pattern.charAt(0) === '#') {
- this.comment = true;
- return;
- }
+ if (filePath) {
+ try {
+ writeDebugLogForLoading(request, relativeTo, filePath);
- if (!pattern) {
- this.empty = true;
- return;
- } // step 1: figure out negation, etc.
+ const startTime = Date.now();
+ const pluginDefinition = require$1(filePath);
+ debug$2(`Plugin ${filePath} loaded in: ${Date.now() - startTime}ms`);
- this.parseNegate(); // step 2: expand braces
+ return new ConfigDependency({
+ definition: normalizePlugin(pluginDefinition),
+ filePath,
+ id,
+ importerName: ctx.name,
+ importerPath: ctx.filePath
+ });
+ } catch (loadError) {
+ error = loadError;
+ }
+ }
- var set = this.globSet = this.braceExpand();
- if (options.debug) this.debug = console.error;
- this.debug(this.pattern, set); // step 3: now we have a set, so turn each one into a series of path-portion
- // matching patterns.
- // These will be regexps, except in the case of "**", which is
- // set to the GLOBSTAR object for globstar behavior,
- // and will not contain any / characters
+ debug$2("Failed to load plugin '%s' declared in '%s'.", name, ctx.name);
+ error.message = `Failed to load plugin '${name}' declared in '${ctx.name}': ${error.message}`;
+ return new ConfigDependency({
+ error,
+ id,
+ importerName: ctx.name,
+ importerPath: ctx.filePath
+ });
+ }
- set = this.globParts = set.map(function (s) {
- return s.split(slashSplit);
- });
- this.debug(this.pattern, set); // glob --> regexps
+ /**
+ * Take file expression processors as config array elements.
+ * @param {Record<string,DependentPlugin>} plugins The plugin definitions.
+ * @param {ConfigArrayFactoryLoadingContext} ctx The loading context.
+ * @returns {IterableIterator<ConfigArrayElement>} The config array elements of file expression processors.
+ * @private
+ */
+ *_takeFileExtensionProcessors(plugins, ctx) {
+ for (const pluginId of Object.keys(plugins)) {
+ const processors =
+ plugins[pluginId] &&
+ plugins[pluginId].definition &&
+ plugins[pluginId].definition.processors;
- set = set.map(function (s, si, set) {
- return s.map(this.parse, this);
- }, this);
- this.debug(this.pattern, set); // filter out everything that didn't compile properly.
+ if (!processors) {
+ continue;
+ }
- set = set.filter(function (s) {
- return s.indexOf(false) === -1;
- });
- this.debug(this.pattern, set);
- this.set = set;
+ for (const processorId of Object.keys(processors)) {
+ if (processorId.startsWith(".")) {
+ yield* this._normalizeObjectConfigData(
+ {
+ files: [`*${processorId}`],
+ processor: `${pluginId}/${processorId}`
+ },
+ {
+ ...ctx,
+ type: "implicit-processor",
+ name: `${ctx.name}#processors["${pluginId}/${processorId}"]`
+ }
+ );
+ }
+ }
+ }
+ }
}
-Minimatch.prototype.parseNegate = parseNegate;
-
-function parseNegate() {
- var pattern = this.pattern;
- var negate = false;
- var options = this.options;
- var negateOffset = 0;
- if (options.nonegate) return;
+/**
+ * @fileoverview `CascadingConfigArrayFactory` class.
+ *
+ * `CascadingConfigArrayFactory` class has a responsibility:
+ *
+ * 1. Handles cascading of config files.
+ *
+ * It provides two methods:
+ *
+ * - `getConfigArrayForFile(filePath)`
+ * Get the corresponded configuration of a given file. This method doesn't
+ * throw even if the given file didn't exist.
+ * - `clearCache()`
+ * Clear the internal cache. You have to call this method when
+ * `additionalPluginPool` was updated if `baseConfig` or `cliConfig` depends
+ * on the additional plugins. (`CLIEngine#addPlugin()` method calls this.)
+ *
+ * @author Toru Nagashima <https://github.com/mysticatea>
+ */
- for (var i = 0, l = pattern.length; i < l && pattern.charAt(i) === '!'; i++) {
- negate = !negate;
- negateOffset++;
- }
+const debug$1 = debugOrig__default["default"]("eslintrc:cascading-config-array-factory");
- if (negateOffset) this.pattern = pattern.substr(negateOffset);
- this.negate = negate;
-} // Brace expansion:
-// a{b,c}d -> abd acd
-// a{b,}c -> abc ac
-// a{0..3}d -> a0d a1d a2d a3d
-// a{b,c{d,e}f}g -> abg acdfg acefg
-// a{b,c}d{e,f}g -> abdeg acdeg abdeg abdfg
-//
-// Invalid sets are not expanded.
-// a{2..}b -> a{2..}b
-// a{b}c -> a{b}c
+//------------------------------------------------------------------------------
+// Helpers
+//------------------------------------------------------------------------------
+// Define types for VSCode IntelliSense.
+/** @typedef {import("./shared/types").ConfigData} ConfigData */
+/** @typedef {import("./shared/types").Parser} Parser */
+/** @typedef {import("./shared/types").Plugin} Plugin */
+/** @typedef {import("./shared/types").Rule} Rule */
+/** @typedef {ReturnType<ConfigArrayFactory["create"]>} ConfigArray */
-minimatch.braceExpand = function (pattern, options) {
- return braceExpand(pattern, options);
-};
+/**
+ * @typedef {Object} CascadingConfigArrayFactoryOptions
+ * @property {Map<string,Plugin>} [additionalPluginPool] The map for additional plugins.
+ * @property {ConfigData} [baseConfig] The config by `baseConfig` option.
+ * @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.
+ * @property {string} [cwd] The base directory to start lookup.
+ * @property {string} [ignorePath] The path to the alternative file of `.eslintignore`.
+ * @property {string[]} [rulePaths] The value of `--rulesdir` option.
+ * @property {string} [specificConfigPath] The value of `--config` option.
+ * @property {boolean} [useEslintrc] if `false` then it doesn't load config files.
+ * @property {Function} loadRules The function to use to load rules.
+ * @property {Map<string,Rule>} builtInRules The rules that are built in to ESLint.
+ * @property {Object} [resolver=ModuleResolver] The module resolver object.
+ * @property {string} eslintAllPath The path to the definitions for eslint:all.
+ * @property {string} eslintRecommendedPath The path to the definitions for eslint:recommended.
+ */
-Minimatch.prototype.braceExpand = braceExpand;
+/**
+ * @typedef {Object} CascadingConfigArrayFactoryInternalSlots
+ * @property {ConfigArray} baseConfigArray The config array of `baseConfig` option.
+ * @property {ConfigData} baseConfigData The config data of `baseConfig` option. This is used to reset `baseConfigArray`.
+ * @property {ConfigArray} cliConfigArray The config array of CLI options.
+ * @property {ConfigData} cliConfigData The config data of CLI options. This is used to reset `cliConfigArray`.
+ * @property {ConfigArrayFactory} configArrayFactory The factory for config arrays.
+ * @property {Map<string, ConfigArray>} configCache The cache from directory paths to config arrays.
+ * @property {string} cwd The base directory to start lookup.
+ * @property {WeakMap<ConfigArray, ConfigArray>} finalizeCache The cache from config arrays to finalized config arrays.
+ * @property {string} [ignorePath] The path to the alternative file of `.eslintignore`.
+ * @property {string[]|null} rulePaths The value of `--rulesdir` option. This is used to reset `baseConfigArray`.
+ * @property {string|null} specificConfigPath The value of `--config` option. This is used to reset `cliConfigArray`.
+ * @property {boolean} useEslintrc if `false` then it doesn't load config files.
+ * @property {Function} loadRules The function to use to load rules.
+ * @property {Map<string,Rule>} builtInRules The rules that are built in to ESLint.
+ * @property {Object} [resolver=ModuleResolver] The module resolver object.
+ * @property {string} eslintAllPath The path to the definitions for eslint:all.
+ * @property {string} eslintRecommendedPath The path to the definitions for eslint:recommended.
+ */
-function braceExpand(pattern, options) {
- if (!options) {
- if (this instanceof Minimatch) {
- options = this.options;
- } else {
- options = {};
- }
- }
+/** @type {WeakMap<CascadingConfigArrayFactory, CascadingConfigArrayFactoryInternalSlots>} */
+const internalSlotsMap = new WeakMap();
- pattern = typeof pattern === 'undefined' ? this.pattern : pattern;
+/**
+ * Create the config array from `baseConfig` and `rulePaths`.
+ * @param {CascadingConfigArrayFactoryInternalSlots} slots The slots.
+ * @returns {ConfigArray} The config array of the base configs.
+ */
+function createBaseConfigArray({
+ configArrayFactory,
+ baseConfigData,
+ rulePaths,
+ cwd,
+ loadRules
+}) {
+ const baseConfigArray = configArrayFactory.create(
+ baseConfigData,
+ { name: "BaseConfig" }
+ );
- if (typeof pattern === 'undefined') {
- throw new TypeError('undefined pattern');
- }
+ /*
+ * Create the config array element for the default ignore patterns.
+ * This element has `ignorePattern` property that ignores the default
+ * patterns in the current working directory.
+ */
+ baseConfigArray.unshift(configArrayFactory.create(
+ { ignorePatterns: IgnorePattern.DefaultPatterns },
+ { name: "DefaultIgnorePattern" }
+ )[0]);
- if (options.nobrace || !pattern.match(/\{.*\}/)) {
- // shortcut. no need to expand.
- return [pattern];
- }
+ /*
+ * Load rules `--rulesdir` option as a pseudo plugin.
+ * Use a pseudo plugin to define rules of `--rulesdir`, so we can validate
+ * the rule's options with only information in the config array.
+ */
+ if (rulePaths && rulePaths.length > 0) {
+ baseConfigArray.push({
+ type: "config",
+ name: "--rulesdir",
+ filePath: "",
+ plugins: {
+ "": new ConfigDependency({
+ definition: {
+ rules: rulePaths.reduce(
+ (map, rulesPath) => Object.assign(
+ map,
+ loadRules(rulesPath, cwd)
+ ),
+ {}
+ )
+ },
+ filePath: "",
+ id: "",
+ importerName: "--rulesdir",
+ importerPath: ""
+ })
+ }
+ });
+ }
- return expand(pattern);
-} // parse a component of the expanded set.
-// At this point, no pattern may contain "/" in it
-// so we're going to return a 2d array, where each entry is the full
-// pattern, split on '/', and then turned into a regular expression.
-// A regexp is made at the end which joins each array with an
-// escaped /, and another full one which joins each regexp with |.
-//
-// Following the lead of Bash 4.1, note that "**" only has special meaning
-// when it is the *only* thing in a path portion. Otherwise, any series
-// of * is equivalent to a single *. Globstar behavior is enabled by
-// default, and can be disabled by setting options.noglobstar.
+ return baseConfigArray;
+}
+/**
+ * Create the config array from CLI options.
+ * @param {CascadingConfigArrayFactoryInternalSlots} slots The slots.
+ * @returns {ConfigArray} The config array of the base configs.
+ */
+function createCLIConfigArray({
+ cliConfigData,
+ configArrayFactory,
+ cwd,
+ ignorePath,
+ specificConfigPath
+}) {
+ const cliConfigArray = configArrayFactory.create(
+ cliConfigData,
+ { name: "CLIOptions" }
+ );
-Minimatch.prototype.parse = parse;
-var SUBPARSE = {};
+ cliConfigArray.unshift(
+ ...(ignorePath
+ ? configArrayFactory.loadESLintIgnore(ignorePath)
+ : configArrayFactory.loadDefaultESLintIgnore())
+ );
-function parse(pattern, isSub) {
- if (pattern.length > 1024 * 64) {
- throw new TypeError('pattern is too long');
- }
+ if (specificConfigPath) {
+ cliConfigArray.unshift(
+ ...configArrayFactory.loadFile(
+ specificConfigPath,
+ { name: "--config", basePath: cwd }
+ )
+ );
+ }
- var options = this.options; // shortcuts
+ return cliConfigArray;
+}
- if (!options.noglobstar && pattern === '**') return GLOBSTAR;
- if (pattern === '') return '';
- var re = '';
- var hasMagic = !!options.nocase;
- var escaping = false; // ? => one single character
+/**
+ * The error type when there are files matched by a glob, but all of them have been ignored.
+ */
+class ConfigurationNotFoundError extends Error {
- var patternListStack = [];
- var negativeLists = [];
- var stateChar;
- var inClass = false;
- var reClassStart = -1;
- var classStart = -1; // . and .. never match anything that doesn't start with .,
- // even when options.dot is set.
+ // eslint-disable-next-line jsdoc/require-description
+ /**
+ * @param {string} directoryPath The directory path.
+ */
+ constructor(directoryPath) {
+ super(`No ESLint configuration found in ${directoryPath}.`);
+ this.messageTemplate = "no-config-found";
+ this.messageData = { directoryPath };
+ }
+}
- var patternStart = pattern.charAt(0) === '.' ? '' // anything
- // not (start or / followed by . or .. followed by / or end)
- : options.dot ? '(?!(?:^|\\\/)\\.{1,2}(?:$|\\\/))' : '(?!\\.)';
- var self = this;
+/**
+ * This class provides the functionality that enumerates every file which is
+ * matched by given glob patterns and that configuration.
+ */
+class CascadingConfigArrayFactory {
- function clearStateChar() {
- if (stateChar) {
- // we had some state-tracking character
- // that wasn't consumed by this pass.
- switch (stateChar) {
- case '*':
- re += star;
- hasMagic = true;
- break;
+ /**
+ * Initialize this enumerator.
+ * @param {CascadingConfigArrayFactoryOptions} options The options.
+ */
+ constructor({
+ additionalPluginPool = new Map(),
+ baseConfig: baseConfigData = null,
+ cliConfig: cliConfigData = null,
+ cwd = process.cwd(),
+ ignorePath,
+ resolvePluginsRelativeTo,
+ rulePaths = [],
+ specificConfigPath = null,
+ useEslintrc = true,
+ builtInRules = new Map(),
+ loadRules,
+ resolver,
+ eslintRecommendedPath,
+ eslintAllPath
+ } = {}) {
+ const configArrayFactory = new ConfigArrayFactory({
+ additionalPluginPool,
+ cwd,
+ resolvePluginsRelativeTo,
+ builtInRules,
+ resolver,
+ eslintRecommendedPath,
+ eslintAllPath
+ });
- case '?':
- re += qmark;
- hasMagic = true;
- break;
+ internalSlotsMap.set(this, {
+ baseConfigArray: createBaseConfigArray({
+ baseConfigData,
+ configArrayFactory,
+ cwd,
+ rulePaths,
+ loadRules,
+ resolver
+ }),
+ baseConfigData,
+ cliConfigArray: createCLIConfigArray({
+ cliConfigData,
+ configArrayFactory,
+ cwd,
+ ignorePath,
+ specificConfigPath
+ }),
+ cliConfigData,
+ configArrayFactory,
+ configCache: new Map(),
+ cwd,
+ finalizeCache: new WeakMap(),
+ ignorePath,
+ rulePaths,
+ specificConfigPath,
+ useEslintrc,
+ builtInRules,
+ loadRules
+ });
+ }
- default:
- re += '\\' + stateChar;
- break;
- }
+ /**
+ * The path to the current working directory.
+ * This is used by tests.
+ * @type {string}
+ */
+ get cwd() {
+ const { cwd } = internalSlotsMap.get(this);
- self.debug('clearStateChar %j %j', stateChar, re);
- stateChar = false;
+ return cwd;
}
- }
- for (var i = 0, len = pattern.length, c; i < len && (c = pattern.charAt(i)); i++) {
- this.debug('%s\t%s %s %j', pattern, i, re, c); // skip over any that are escaped.
+ /**
+ * Get the config array of a given file.
+ * If `filePath` was not given, it returns the config which contains only
+ * `baseConfigData` and `cliConfigData`.
+ * @param {string} [filePath] The file path to a file.
+ * @param {Object} [options] The options.
+ * @param {boolean} [options.ignoreNotFoundError] If `true` then it doesn't throw `ConfigurationNotFoundError`.
+ * @returns {ConfigArray} The config array of the file.
+ */
+ getConfigArrayForFile(filePath, { ignoreNotFoundError = false } = {}) {
+ const {
+ baseConfigArray,
+ cliConfigArray,
+ cwd
+ } = internalSlotsMap.get(this);
- if (escaping && reSpecials[c]) {
- re += '\\' + c;
- escaping = false;
- continue;
- }
+ if (!filePath) {
+ return new ConfigArray(...baseConfigArray, ...cliConfigArray);
+ }
- switch (c) {
- case '/':
- // completely not allowed, even escaped.
- // Should already be path-split by now.
- return false;
+ const directoryPath = path__default["default"].dirname(path__default["default"].resolve(cwd, filePath));
- case '\\':
- clearStateChar();
- escaping = true;
- continue;
- // the various stateChar values
- // for the "extglob" stuff.
+ debug$1(`Load config files for ${directoryPath}.`);
- case '?':
- case '*':
- case '+':
- case '@':
- case '!':
- this.debug('%s\t%s %s %j <-- stateChar', pattern, i, re, c); // all of those are literals inside a class, except that
- // the glob [!a] means [^a] in regexp
+ return this._finalizeConfigArray(
+ this._loadConfigInAncestors(directoryPath),
+ directoryPath,
+ ignoreNotFoundError
+ );
+ }
- if (inClass) {
- this.debug(' in class');
- if (c === '!' && i === classStart + 1) c = '^';
- re += c;
- continue;
- } // if we already have a stateChar, then it means
- // that there was something like ** or +? in there.
- // Handle the stateChar, then proceed with this one.
+ /**
+ * Set the config data to override all configs.
+ * Require to call `clearCache()` method after this method is called.
+ * @param {ConfigData} configData The config data to override all configs.
+ * @returns {void}
+ */
+ setOverrideConfig(configData) {
+ const slots = internalSlotsMap.get(this);
+ slots.cliConfigData = configData;
+ }
- self.debug('call clearStateChar %j', stateChar);
- clearStateChar();
- stateChar = c; // if extglob is disabled, then +(asdf|foo) isn't a thing.
- // just clear the statechar *now*, rather than even diving into
- // the patternList stuff.
+ /**
+ * Clear config cache.
+ * @returns {void}
+ */
+ clearCache() {
+ const slots = internalSlotsMap.get(this);
- if (options.noext) clearStateChar();
- continue;
+ slots.baseConfigArray = createBaseConfigArray(slots);
+ slots.cliConfigArray = createCLIConfigArray(slots);
+ slots.configCache.clear();
+ }
- case '(':
- if (inClass) {
- re += '(';
- continue;
- }
+ /**
+ * Load and normalize config files from the ancestor directories.
+ * @param {string} directoryPath The path to a leaf directory.
+ * @param {boolean} configsExistInSubdirs `true` if configurations exist in subdirectories.
+ * @returns {ConfigArray} The loaded config.
+ * @private
+ */
+ _loadConfigInAncestors(directoryPath, configsExistInSubdirs = false) {
+ const {
+ baseConfigArray,
+ configArrayFactory,
+ configCache,
+ cwd,
+ useEslintrc
+ } = internalSlotsMap.get(this);
- if (!stateChar) {
- re += '\\(';
- continue;
+ if (!useEslintrc) {
+ return baseConfigArray;
}
- patternListStack.push({
- type: stateChar,
- start: i - 1,
- reStart: re.length,
- open: plTypes[stateChar].open,
- close: plTypes[stateChar].close
- }); // negation is (?:(?!js)[^/]*)
-
- re += stateChar === '!' ? '(?:(?!(?:' : '(?:';
- this.debug('plType %j %j', stateChar, re);
- stateChar = false;
- continue;
+ let configArray = configCache.get(directoryPath);
- case ')':
- if (inClass || !patternListStack.length) {
- re += '\\)';
- continue;
+ // Hit cache.
+ if (configArray) {
+ debug$1(`Cache hit: ${directoryPath}.`);
+ return configArray;
}
+ debug$1(`No cache found: ${directoryPath}.`);
- clearStateChar();
- hasMagic = true;
- var pl = patternListStack.pop(); // negation is (?:(?!js)[^/]*)
- // The others are (?:<pattern>)<type>
+ const homePath = os__default["default"].homedir();
- re += pl.close;
+ // Consider this is root.
+ if (directoryPath === homePath && cwd !== homePath) {
+ debug$1("Stop traversing because of considered root.");
+ if (configsExistInSubdirs) {
+ const filePath = ConfigArrayFactory.getPathToConfigFileInDirectory(directoryPath);
- if (pl.type === '!') {
- negativeLists.push(pl);
+ if (filePath) {
+ emitDeprecationWarning(
+ filePath,
+ "ESLINT_PERSONAL_CONFIG_SUPPRESS"
+ );
+ }
+ }
+ return this._cacheConfig(directoryPath, baseConfigArray);
}
- pl.reEnd = re.length;
- continue;
-
- case '|':
- if (inClass || !patternListStack.length || escaping) {
- re += '\\|';
- escaping = false;
- continue;
+ // Load the config on this directory.
+ try {
+ configArray = configArrayFactory.loadInDirectory(directoryPath);
+ } catch (error) {
+ /* istanbul ignore next */
+ if (error.code === "EACCES") {
+ debug$1("Stop traversing because of 'EACCES' error.");
+ return this._cacheConfig(directoryPath, baseConfigArray);
+ }
+ throw error;
}
- clearStateChar();
- re += '|';
- continue;
- // these are mostly the same in regexp and glob
-
- case '[':
- // swallow any state-tracking char before the [
- clearStateChar();
-
- if (inClass) {
- re += '\\' + c;
- continue;
+ if (configArray.length > 0 && configArray.isRoot()) {
+ debug$1("Stop traversing because of 'root:true'.");
+ configArray.unshift(...baseConfigArray);
+ return this._cacheConfig(directoryPath, configArray);
}
- inClass = true;
- classStart = i;
- reClassStart = re.length;
- re += c;
- continue;
-
- case ']':
- // a right bracket shall lose its special
- // meaning and represent itself in
- // a bracket expression if it occurs
- // first in the list. -- POSIX.2 2.8.3.2
- if (i === classStart + 1 || !inClass) {
- re += '\\' + c;
- escaping = false;
- continue;
- } // handle the case where we left a class open.
- // "[z-a]" is valid, equivalent to "\[z-a\]"
-
-
- if (inClass) {
- // split where the last [ was, make sure we don't have
- // an invalid re. if so, re-walk the contents of the
- // would-be class to re-translate any characters that
- // were passed through as-is
- // TODO: It would probably be faster to determine this
- // without a try/catch and a new RegExp, but it's tricky
- // to do safely. For now, this is safe and works.
- var cs = pattern.substring(classStart + 1, i);
-
- try {
- RegExp('[' + cs + ']');
- } catch (er) {
- // not a valid class!
- var sp = this.parse(cs, SUBPARSE);
- re = re.substr(0, reClassStart) + '\\[' + sp[0] + '\\]';
- hasMagic = hasMagic || sp[1];
- inClass = false;
- continue;
- }
- } // finish up the class.
-
-
- hasMagic = true;
- inClass = false;
- re += c;
- continue;
-
- default:
- // swallow any state char that wasn't consumed
- clearStateChar();
+ // Load from the ancestors and merge it.
+ const parentPath = path__default["default"].dirname(directoryPath);
+ const parentConfigArray = parentPath && parentPath !== directoryPath
+ ? this._loadConfigInAncestors(
+ parentPath,
+ configsExistInSubdirs || configArray.length > 0
+ )
+ : baseConfigArray;
- if (escaping) {
- // no need
- escaping = false;
- } else if (reSpecials[c] && !(c === '^' && inClass)) {
- re += '\\';
+ if (configArray.length > 0) {
+ configArray.unshift(...parentConfigArray);
+ } else {
+ configArray = parentConfigArray;
}
- re += c;
- } // switch
+ // Cache and return.
+ return this._cacheConfig(directoryPath, configArray);
+ }
- } // for
- // handle the case where we left a class open.
- // "[abc" is valid, equivalent to "\[abc"
+ /**
+ * Freeze and cache a given config.
+ * @param {string} directoryPath The path to a directory as a cache key.
+ * @param {ConfigArray} configArray The config array as a cache value.
+ * @returns {ConfigArray} The `configArray` (frozen).
+ */
+ _cacheConfig(directoryPath, configArray) {
+ const { configCache } = internalSlotsMap.get(this);
+ Object.freeze(configArray);
+ configCache.set(directoryPath, configArray);
- if (inClass) {
- // split where the last [ was, and escape it
- // this is a huge pita. We now have to re-walk
- // the contents of the would-be class to re-translate
- // any characters that were passed through as-is
- cs = pattern.substr(classStart + 1);
- sp = this.parse(cs, SUBPARSE);
- re = re.substr(0, reClassStart) + '\\[' + sp[0];
- hasMagic = hasMagic || sp[1];
- } // handle the case where we had a +( thing at the *end*
- // of the pattern.
- // each pattern list stack adds 3 chars, and we need to go through
- // and escape any | chars that were passed through as-is for the regexp.
- // Go through and escape them, taking care not to double-escape any
- // | chars that were already escaped.
+ return configArray;
+ }
+ /**
+ * Finalize a given config array.
+ * Concatenate `--config` and other CLI options.
+ * @param {ConfigArray} configArray The parent config array.
+ * @param {string} directoryPath The path to the leaf directory to find config files.
+ * @param {boolean} ignoreNotFoundError If `true` then it doesn't throw `ConfigurationNotFoundError`.
+ * @returns {ConfigArray} The loaded config.
+ * @private
+ */
+ _finalizeConfigArray(configArray, directoryPath, ignoreNotFoundError) {
+ const {
+ cliConfigArray,
+ configArrayFactory,
+ finalizeCache,
+ useEslintrc,
+ builtInRules
+ } = internalSlotsMap.get(this);
- for (pl = patternListStack.pop(); pl; pl = patternListStack.pop()) {
- var tail = re.slice(pl.reStart + pl.open.length);
- this.debug('setting tail', re, pl); // maybe some even number of \, then maybe 1 \, followed by a |
+ let finalConfigArray = finalizeCache.get(configArray);
- tail = tail.replace(/((?:\\{2}){0,64})(\\?)\|/g, function (_, $1, $2) {
- if (!$2) {
- // the | isn't already escaped, so escape it.
- $2 = '\\';
- } // need to escape all those slashes *again*, without escaping the
- // one that we need for escaping the | character. As it works out,
- // escaping an even number of slashes can be done by simply repeating
- // it exactly after itself. That's why this trick works.
- //
- // I am sorry that you have to see this.
+ if (!finalConfigArray) {
+ finalConfigArray = configArray;
+ // Load the personal config if there are no regular config files.
+ if (
+ useEslintrc &&
+ configArray.every(c => !c.filePath) &&
+ cliConfigArray.every(c => !c.filePath) // `--config` option can be a file.
+ ) {
+ const homePath = os__default["default"].homedir();
- return $1 + $1 + $2 + '|';
- });
- this.debug('tail=%j\n %s', tail, tail, pl, re);
- var t = pl.type === '*' ? star : pl.type === '?' ? qmark : '\\' + pl.type;
- hasMagic = true;
- re = re.slice(0, pl.reStart) + t + '\\(' + tail;
- } // handle trailing things that only matter at the very end.
+ debug$1("Loading the config file of the home directory:", homePath);
+ const personalConfigArray = configArrayFactory.loadInDirectory(
+ homePath,
+ { name: "PersonalConfig" }
+ );
- clearStateChar();
+ if (
+ personalConfigArray.length > 0 &&
+ !directoryPath.startsWith(homePath)
+ ) {
+ const lastElement =
+ personalConfigArray[personalConfigArray.length - 1];
- if (escaping) {
- // trailing \\
- re += '\\\\';
- } // only need to apply the nodot start if the re starts with
- // something that could conceivably capture a dot
+ emitDeprecationWarning(
+ lastElement.filePath,
+ "ESLINT_PERSONAL_CONFIG_LOAD"
+ );
+ }
+ finalConfigArray = finalConfigArray.concat(personalConfigArray);
+ }
- var addPatternStart = false;
+ // Apply CLI options.
+ if (cliConfigArray.length > 0) {
+ finalConfigArray = finalConfigArray.concat(cliConfigArray);
+ }
- switch (re.charAt(0)) {
- case '.':
- case '[':
- case '(':
- addPatternStart = true;
- } // Hack to work around lack of negative lookbehind in JS
- // A pattern like: *.!(x).!(y|z) needs to ensure that a name
- // like 'a.xyz.yz' doesn't match. So, the first negative
- // lookahead, has to look ALL the way ahead, to the end of
- // the pattern.
+ // Validate rule settings and environments.
+ const validator = new ConfigValidator({
+ builtInRules
+ });
+ validator.validateConfigArray(finalConfigArray);
- for (var n = negativeLists.length - 1; n > -1; n--) {
- var nl = negativeLists[n];
- var nlBefore = re.slice(0, nl.reStart);
- var nlFirst = re.slice(nl.reStart, nl.reEnd - 8);
- var nlLast = re.slice(nl.reEnd - 8, nl.reEnd);
- var nlAfter = re.slice(nl.reEnd);
- nlLast += nlAfter; // Handle nested stuff like *(*.js|!(*.json)), where open parens
- // mean that we should *not* include the ) in the bit that is considered
- // "after" the negated section.
+ // Cache it.
+ Object.freeze(finalConfigArray);
+ finalizeCache.set(configArray, finalConfigArray);
- var openParensBefore = nlBefore.split('(').length - 1;
- var cleanAfter = nlAfter;
+ debug$1(
+ "Configuration was determined: %o on %s",
+ finalConfigArray,
+ directoryPath
+ );
+ }
- for (i = 0; i < openParensBefore; i++) {
- cleanAfter = cleanAfter.replace(/\)[+*?]?/, '');
+ // At least one element (the default ignore patterns) exists.
+ if (!ignoreNotFoundError && useEslintrc && finalConfigArray.length <= 1) {
+ throw new ConfigurationNotFoundError(directoryPath);
+ }
+
+ return finalConfigArray;
}
+}
- nlAfter = cleanAfter;
- var dollar = '';
+/**
+ * @fileoverview Compatibility class for flat config.
+ * @author Nicholas C. Zakas
+ */
- if (nlAfter === '' && isSub !== SUBPARSE) {
- dollar = '$';
- }
+const dirname = path__default["default"].dirname(url.fileURLToPath((typeof document === 'undefined' ? new ((__webpack_require__(892).URL))('file:' + __filename).href : (document.currentScript && document.currentScript.src || new URL('eslintrc.cjs', document.baseURI).href))));
- var newRe = nlBefore + nlFirst + nlAfter + dollar + nlLast;
- re = newRe;
- } // if the re is not "" at this point, then we need to make sure
- // it doesn't match against an empty path part.
- // Otherwise a/* will match a/, which it should not.
+//-----------------------------------------------------------------------------
+// Helpers
+//-----------------------------------------------------------------------------
+/** @typedef {import("../../shared/types").Environment} Environment */
+/** @typedef {import("../../shared/types").Processor} Processor */
- if (re !== '' && hasMagic) {
- re = '(?=.)' + re;
- }
+const debug = debugOrig__default["default"]("eslintrc:flat-compat");
+const cafactory = Symbol("cafactory");
- if (addPatternStart) {
- re = patternStart + re;
- } // parsing just a piece of a larger pattern.
+/**
+ * Translates an ESLintRC-style config object into a flag-config-style config
+ * object.
+ * @param {Object} eslintrcConfig An ESLintRC-style config object.
+ * @param {Object} options Options to help translate the config.
+ * @param {string} options.resolveConfigRelativeTo To the directory to resolve
+ * configs from.
+ * @param {string} options.resolvePluginsRelativeTo The directory to resolve
+ * plugins from.
+ * @param {ReadOnlyMap<string,Environment>} options.pluginEnvironments A map of plugin environment
+ * names to objects.
+ * @param {ReadOnlyMap<string,Processor>} options.pluginProcessors A map of plugin processor
+ * names to objects.
+ * @returns {Object} A flag-config-style config object.
+ */
+function translateESLintRC(eslintrcConfig, {
+ resolveConfigRelativeTo,
+ resolvePluginsRelativeTo,
+ pluginEnvironments,
+ pluginProcessors
+}) {
+ const flatConfig = {};
+ const configs = [];
+ const languageOptions = {};
+ const linterOptions = {};
+ const keysToCopy = ["settings", "rules", "processor"];
+ const languageOptionsKeysToCopy = ["globals", "parser", "parserOptions"];
+ const linterOptionsKeysToCopy = ["noInlineConfig", "reportUnusedDisableDirectives"];
- if (isSub === SUBPARSE) {
- return [re, hasMagic];
- } // skip the regexp for non-magical patterns
- // unescape anything in it, though, so that it'll be
- // an exact match against a file etc.
+ // check for special settings for eslint:all and eslint:recommended:
+ if (eslintrcConfig.settings) {
+ if (eslintrcConfig.settings["eslint:all"] === true) {
+ return ["eslint:all"];
+ }
+ if (eslintrcConfig.settings["eslint:recommended"] === true) {
+ return ["eslint:recommended"];
+ }
+ }
- if (!hasMagic) {
- return globUnescape(pattern);
- }
+ // copy over simple translations
+ for (const key of keysToCopy) {
+ if (key in eslintrcConfig && typeof eslintrcConfig[key] !== "undefined") {
+ flatConfig[key] = eslintrcConfig[key];
+ }
+ }
- var flags = options.nocase ? 'i' : '';
+ // copy over languageOptions
+ for (const key of languageOptionsKeysToCopy) {
+ if (key in eslintrcConfig && typeof eslintrcConfig[key] !== "undefined") {
- try {
- var regExp = new RegExp('^' + re + '$', flags);
- } catch (er) {
- // If it was an invalid regular expression, then it can't match
- // anything. This trick looks for a character after the end of
- // the string, which is of course impossible, except in multi-line
- // mode, but it's not a /m regex.
- return new RegExp('$.');
- }
+ // create the languageOptions key in the flat config
+ flatConfig.languageOptions = languageOptions;
- regExp._glob = pattern;
- regExp._src = re;
- return regExp;
-}
+ if (key === "parser") {
+ debug(`Resolving parser '${languageOptions[key]}' relative to ${resolveConfigRelativeTo}`);
-minimatch.makeRe = function (pattern, options) {
- return new Minimatch(pattern, options || {}).makeRe();
-};
+ if (eslintrcConfig[key].error) {
+ throw eslintrcConfig[key].error;
+ }
-Minimatch.prototype.makeRe = makeRe;
+ languageOptions[key] = eslintrcConfig[key].definition;
+ continue;
+ }
-function makeRe() {
- if (this.regexp || this.regexp === false) return this.regexp; // at this point, this.set is a 2d array of partial
- // pattern strings, or "**".
- //
- // It's better to use .match(). This function shouldn't
- // be used, really, but it's pretty convenient sometimes,
- // when you just want to work with a regex.
+ // clone any object values that are in the eslintrc config
+ if (eslintrcConfig[key] && typeof eslintrcConfig[key] === "object") {
+ languageOptions[key] = {
+ ...eslintrcConfig[key]
+ };
+ } else {
+ languageOptions[key] = eslintrcConfig[key];
+ }
+ }
+ }
- var set = this.set;
+ // copy over linterOptions
+ for (const key of linterOptionsKeysToCopy) {
+ if (key in eslintrcConfig && typeof eslintrcConfig[key] !== "undefined") {
+ flatConfig.linterOptions = linterOptions;
+ linterOptions[key] = eslintrcConfig[key];
+ }
+ }
- if (!set.length) {
- this.regexp = false;
- return this.regexp;
- }
+ // move ecmaVersion a level up
+ if (languageOptions.parserOptions) {
- var options = this.options;
- var twoStar = options.noglobstar ? star : options.dot ? twoStarDot : twoStarNoDot;
- var flags = options.nocase ? 'i' : '';
- var re = set.map(function (pattern) {
- return pattern.map(function (p) {
- return p === GLOBSTAR ? twoStar : typeof p === 'string' ? regExpEscape(p) : p._src;
- }).join('\\\/');
- }).join('|'); // must match entire pattern
- // ending in a * or ** will make it less strict.
+ if ("ecmaVersion" in languageOptions.parserOptions) {
+ languageOptions.ecmaVersion = languageOptions.parserOptions.ecmaVersion;
+ delete languageOptions.parserOptions.ecmaVersion;
+ }
- re = '^(?:' + re + ')$'; // can match anything, as long as it's not this.
+ if ("sourceType" in languageOptions.parserOptions) {
+ languageOptions.sourceType = languageOptions.parserOptions.sourceType;
+ delete languageOptions.parserOptions.sourceType;
+ }
- if (this.negate) re = '^(?!' + re + ').*$';
+ // check to see if we even need parserOptions anymore and remove it if not
+ if (Object.keys(languageOptions.parserOptions).length === 0) {
+ delete languageOptions.parserOptions;
+ }
+ }
- try {
- this.regexp = new RegExp(re, flags);
- } catch (ex) {
- this.regexp = false;
- }
+ // overrides
+ if (eslintrcConfig.criteria) {
+ flatConfig.files = [absoluteFilePath => eslintrcConfig.criteria.test(absoluteFilePath)];
+ }
- return this.regexp;
-}
+ // translate plugins
+ if (eslintrcConfig.plugins && typeof eslintrcConfig.plugins === "object") {
+ debug(`Translating plugins: ${eslintrcConfig.plugins}`);
-minimatch.match = function (list, pattern, options) {
- options = options || {};
- var mm = new Minimatch(pattern, options);
- list = list.filter(function (f) {
- return mm.match(f);
- });
+ flatConfig.plugins = {};
- if (mm.options.nonull && !list.length) {
- list.push(pattern);
- }
+ for (const pluginName of Object.keys(eslintrcConfig.plugins)) {
- return list;
-};
+ debug(`Translating plugin: ${pluginName}`);
+ debug(`Resolving plugin '${pluginName} relative to ${resolvePluginsRelativeTo}`);
-Minimatch.prototype.match = match;
+ const { definition: plugin, error } = eslintrcConfig.plugins[pluginName];
-function match(f, partial) {
- this.debug('match', f, this.pattern); // short-circuit in the case of busted things.
- // comments, etc.
+ if (error) {
+ throw error;
+ }
- if (this.comment) return false;
- if (this.empty) return f === '';
- if (f === '/' && partial) return true;
- var options = this.options; // windows: need to use /, not \
+ flatConfig.plugins[pluginName] = plugin;
- if (path.sep !== '/') {
- f = f.split(path.sep).join('/');
- } // treat the test path as a set of pathparts.
+ // create a config for any processors
+ if (plugin.processors) {
+ for (const processorName of Object.keys(plugin.processors)) {
+ if (processorName.startsWith(".")) {
+ debug(`Assigning processor: ${pluginName}/${processorName}`);
+ configs.unshift({
+ files: [`**/*${processorName}`],
+ processor: pluginProcessors.get(`${pluginName}/${processorName}`)
+ });
+ }
- f = f.split(slashSplit);
- this.debug(this.pattern, 'split', f); // just ONE of the pattern sets in this.set needs to match
- // in order for it to be valid. If negating, then just one
- // match means that we have failed.
- // Either way, return on the first hit.
+ }
+ }
+ }
+ }
- var set = this.set;
- this.debug(this.pattern, 'set', set); // Find the basename of the path by looking for the last non-empty segment
+ // translate env - must come after plugins
+ if (eslintrcConfig.env && typeof eslintrcConfig.env === "object") {
+ for (const envName of Object.keys(eslintrcConfig.env)) {
- var filename;
- var i;
+ // only add environments that are true
+ if (eslintrcConfig.env[envName]) {
+ debug(`Translating environment: ${envName}`);
- for (i = f.length - 1; i >= 0; i--) {
- filename = f[i];
- if (filename) break;
- }
+ if (environments.has(envName)) {
- for (i = 0; i < set.length; i++) {
- var pattern = set[i];
- var file = f;
+ // built-in environments should be defined first
+ configs.unshift(...translateESLintRC(environments.get(envName), {
+ resolveConfigRelativeTo,
+ resolvePluginsRelativeTo
+ }));
+ } else if (pluginEnvironments.has(envName)) {
- if (options.matchBase && pattern.length === 1) {
- file = [filename];
+ // if the environment comes from a plugin, it should come after the plugin config
+ configs.push(...translateESLintRC(pluginEnvironments.get(envName), {
+ resolveConfigRelativeTo,
+ resolvePluginsRelativeTo
+ }));
+ }
+ }
+ }
}
- var hit = this.matchOne(file, pattern, partial);
-
- if (hit) {
- if (options.flipNegate) return true;
- return !this.negate;
+ // only add if there are actually keys in the config
+ if (Object.keys(flatConfig).length > 0) {
+ configs.push(flatConfig);
}
- } // didn't get any hits. this is success if it's a negative
- // pattern, failure otherwise.
+ return configs;
+}
- if (options.flipNegate) return false;
- return this.negate;
-} // set partial to true to test if, for example,
-// "/a/b" matches the start of "/*/b/*/d"
-// Partial means, if you run out of file before you run
-// out of pattern, then that's fine, as long as all
-// the parts match.
+//-----------------------------------------------------------------------------
+// Exports
+//-----------------------------------------------------------------------------
-Minimatch.prototype.matchOne = function (file, pattern, partial) {
- var options = this.options;
- this.debug('matchOne', {
- 'this': this,
- file: file,
- pattern: pattern
- });
- this.debug('matchOne', file.length, pattern.length);
+/**
+ * A compatibility class for working with configs.
+ */
+class FlatCompat {
- for (var fi = 0, pi = 0, fl = file.length, pl = pattern.length; fi < fl && pi < pl; fi++, pi++) {
- this.debug('matchOne loop');
- var p = pattern[pi];
- var f = file[fi];
- this.debug(pattern, p, f); // should be impossible.
- // some invalid regexp stuff in the set.
+ constructor({
+ baseDirectory = process.cwd(),
+ resolvePluginsRelativeTo = baseDirectory
+ } = {}) {
+ this.baseDirectory = baseDirectory;
+ this.resolvePluginsRelativeTo = resolvePluginsRelativeTo;
+ this[cafactory] = new ConfigArrayFactory({
+ cwd: baseDirectory,
+ resolvePluginsRelativeTo,
+ eslintAllPath: path__default["default"].resolve(dirname, "../conf/eslint-all.cjs"),
+ eslintRecommendedPath: path__default["default"].resolve(dirname, "../conf/eslint-recommended.cjs")
+ });
+ }
- if (p === false) return false;
+ /**
+ * Translates an ESLintRC-style config into a flag-config-style config.
+ * @param {Object} eslintrcConfig The ESLintRC-style config object.
+ * @returns {Object} A flag-config-style config object.
+ */
+ config(eslintrcConfig) {
+ const eslintrcArray = this[cafactory].create(eslintrcConfig, {
+ basePath: this.baseDirectory
+ });
- if (p === GLOBSTAR) {
- this.debug('GLOBSTAR', [pattern, p, f]); // "**"
- // a/**/b/**/c would match the following:
- // a/b/x/y/z/c
- // a/x/y/z/b/c
- // a/b/x/b/x/c
- // a/b/c
- // To do this, take the rest of the pattern after
- // the **, and see if it would match the file remainder.
- // If so, return success.
- // If not, the ** "swallows" a segment, and try again.
- // This is recursively awful.
- //
- // a/**/b/**/c matching a/b/x/y/z/c
- // - a matches a
- // - doublestar
- // - matchOne(b/x/y/z/c, b/**/c)
- // - b matches b
- // - doublestar
- // - matchOne(x/y/z/c, c) -> no
- // - matchOne(y/z/c, c) -> no
- // - matchOne(z/c, c) -> no
- // - matchOne(c, c) yes, hit
+ const flatArray = [];
+ let hasIgnorePatterns = false;
- var fr = fi;
- var pr = pi + 1;
+ eslintrcArray.forEach(configData => {
+ if (configData.type === "config") {
+ hasIgnorePatterns = hasIgnorePatterns || configData.ignorePattern;
+ flatArray.push(...translateESLintRC(configData, {
+ resolveConfigRelativeTo: path__default["default"].join(this.baseDirectory, "__placeholder.js"),
+ resolvePluginsRelativeTo: path__default["default"].join(this.resolvePluginsRelativeTo, "__placeholder.js"),
+ pluginEnvironments: eslintrcArray.pluginEnvironments,
+ pluginProcessors: eslintrcArray.pluginProcessors
+ }));
+ }
+ });
- if (pr === pl) {
- this.debug('** at the end'); // a ** at the end will just swallow the rest.
- // We have found a match.
- // however, it will not swallow /.x, unless
- // options.dot is set.
- // . and .. are *never* matched by **, for explosively
- // exponential reasons.
+ // combine ignorePatterns to emulate ESLintRC behavior better
+ if (hasIgnorePatterns) {
+ flatArray.unshift({
+ ignores: [filePath => {
- for (; fi < fl; fi++) {
- if (file[fi] === '.' || file[fi] === '..' || !options.dot && file[fi].charAt(0) === '.') return false;
+ // Compute the final config for this file.
+ // This filters config array elements by `files`/`excludedFiles` then merges the elements.
+ const finalConfig = eslintrcArray.extractConfig(filePath);
+
+ // Test the `ignorePattern` properties of the final config.
+ return Boolean(finalConfig.ignores) && finalConfig.ignores(filePath);
+ }]
+ });
}
- return true;
- } // ok, let's see if we can swallow whatever we can.
+ return flatArray;
+ }
+ /**
+ * Translates the `env` section of an ESLintRC-style config.
+ * @param {Object} envConfig The `env` section of an ESLintRC config.
+ * @returns {Object} A flag-config object representing the environments.
+ */
+ env(envConfig) {
+ return this.config({
+ env: envConfig
+ });
+ }
- while (fr < fl) {
- var swallowee = file[fr];
- this.debug('\nglobstar while', file, fr, pattern, pr, swallowee); // XXX remove this slice. Just pass the start index.
+ /**
+ * Translates the `extends` section of an ESLintRC-style config.
+ * @param {...string} configsToExtend The names of the configs to load.
+ * @returns {Object} A flag-config object representing the config.
+ */
+ extends(...configsToExtend) {
+ return this.config({
+ extends: configsToExtend
+ });
+ }
- if (this.matchOne(file.slice(fr), pattern.slice(pr), partial)) {
- this.debug('globstar found match!', fr, fl, swallowee); // found a match.
+ /**
+ * Translates the `plugins` section of an ESLintRC-style config.
+ * @param {...string} plugins The names of the plugins to load.
+ * @returns {Object} A flag-config object representing the plugins.
+ */
+ plugins(...plugins) {
+ return this.config({
+ plugins
+ });
+ }
+}
- return true;
- } else {
- // can't swallow "." or ".." ever.
- // can only swallow ".foo" when explicitly asked.
- if (swallowee === '.' || swallowee === '..' || !options.dot && swallowee.charAt(0) === '.') {
- this.debug('dot detected!', file, fr, pattern, pr);
- break;
- } // ** swallows a segment, and continue.
+/**
+ * @fileoverview Package exports for @eslint/eslintrc
+ * @author Nicholas C. Zakas
+ */
+
+//-----------------------------------------------------------------------------
+// Exports
+//-----------------------------------------------------------------------------
+const Legacy = {
+ ConfigArray,
+ createConfigArrayFactoryContext: createContext,
+ CascadingConfigArrayFactory,
+ ConfigArrayFactory,
+ ConfigDependency,
+ ExtractedConfig,
+ IgnorePattern,
+ OverrideTester,
+ getUsedExtractedConfigs,
+ environments,
- this.debug('globstar swallow a segment, and continue');
- fr++;
- }
- } // no match was found.
- // However, in partial mode, we can't say this is necessarily over.
- // If there's more *pattern* left, then
+ // shared
+ ConfigOps,
+ ConfigValidator,
+ ModuleResolver,
+ naming
+};
+exports.FlatCompat = FlatCompat;
+exports.Legacy = Legacy;
+//# sourceMappingURL=eslintrc.cjs.map
- if (partial) {
- // ran out of file
- this.debug('\n>>> no match, partial?', file, fr, pattern, pr);
- if (fr === fl) return true;
- }
- return false;
- } // something other than **
- // non-magic patterns just have to match exactly
- // patterns with magic have been turned into regexps.
+/***/ }),
+/* 884 */
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
+"use strict";
- var hit;
- if (typeof p === 'string') {
- if (options.nocase) {
- hit = f.toLowerCase() === p.toLowerCase();
- } else {
- hit = f === p;
- }
+const path = __webpack_require__(429);
- this.debug('string match', p, f, hit);
- } else {
- hit = f.match(p);
- this.debug('pattern match', p, f, hit);
- }
+const resolveFrom = __webpack_require__(885);
- if (!hit) return false;
- } // Note: ending in / means that we'll get a final ""
- // at the end of the pattern. This can only match a
- // corresponding "" at the end of the file.
- // If the file ends in /, then it can only match a
- // a pattern that ends in /, unless the pattern just
- // doesn't have any more for it. But, a/b/ should *not*
- // match "a/b/*", even though "" matches against the
- // [^/]*? pattern, except in partial mode, where it might
- // simply not be reached yet.
- // However, a/b/ should still satisfy a/*
- // now either we fell off the end of the pattern, or we're done.
+const parentModule = __webpack_require__(887);
+module.exports = moduleId => {
+ if (typeof moduleId !== 'string') {
+ throw new TypeError('Expected a string');
+ }
- if (fi === fl && pi === pl) {
- // ran out of pattern and filename at the same time.
- // an exact hit!
- return true;
- } else if (fi === fl) {
- // ran out of file, but still had pattern left.
- // this is ok if we're doing the match as part of
- // a glob fs traversal.
- return partial;
- } else if (pi === pl) {
- // ran out of pattern, still have file left.
- // this is only acceptable if we're on the very last
- // empty segment of a file with a trailing slash.
- // a/* should match a/b/
- var emptyFileEnd = fi === fl - 1 && file[fi] === '';
- return emptyFileEnd;
- } // should be unreachable.
+ const parentPath = parentModule(__filename);
+ const cwd = parentPath ? path.dirname(parentPath) : __dirname;
+ const filePath = resolveFrom(cwd, moduleId);
+ const oldModule = __webpack_require__.c[filePath]; // Delete itself from module parent
+ if (oldModule && oldModule.parent) {
+ let i = oldModule.parent.children.length;
- throw new Error('wtf?');
-}; // replace stuff like \* with *
+ while (i--) {
+ if (oldModule.parent.children[i].id === filePath) {
+ oldModule.parent.children.splice(i, 1);
+ }
+ }
+ }
+ delete __webpack_require__.c[filePath]; // Delete module from cache
-function globUnescape(s) {
- return s.replace(/\\(.)/g, '$1');
-}
+ const parent = __webpack_require__.c[parentPath]; // If `filePath` and `parentPath` are the same, cache will already be deleted so we won't get a memory leak in next step
-function regExpEscape(s) {
- return s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
-}
+ return parent === undefined ? __webpack_require__(889)(filePath) : parent.require(filePath); // In case cache doesn't have parent, fall back to normal require
+};
/***/ }),
-/* 872 */
+/* 885 */
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
-var concatMap = __webpack_require__(873);
-
-var balanced = __webpack_require__(874);
+"use strict";
-module.exports = expandTop;
-var escSlash = '\0SLASH' + Math.random() + '\0';
-var escOpen = '\0OPEN' + Math.random() + '\0';
-var escClose = '\0CLOSE' + Math.random() + '\0';
-var escComma = '\0COMMA' + Math.random() + '\0';
-var escPeriod = '\0PERIOD' + Math.random() + '\0';
-function numeric(str) {
- return parseInt(str, 10) == str ? parseInt(str, 10) : str.charCodeAt(0);
-}
+const path = __webpack_require__(429);
-function escapeBraces(str) {
- return str.split('\\\\').join(escSlash).split('\\{').join(escOpen).split('\\}').join(escClose).split('\\,').join(escComma).split('\\.').join(escPeriod);
-}
+const Module = __webpack_require__(886);
-function unescapeBraces(str) {
- return str.split(escSlash).join('\\').split(escOpen).join('{').split(escClose).join('}').split(escComma).join(',').split(escPeriod).join('.');
-} // Basically just str.split(","), but handling cases
-// where we have nested braced sections, which should be
-// treated as individual members, like {a,{b,c},d}
+const fs = __webpack_require__(880);
+const resolveFrom = (fromDir, moduleId, silent) => {
+ if (typeof fromDir !== 'string') {
+ throw new TypeError("Expected `fromDir` to be of type `string`, got `".concat(typeof fromDir, "`"));
+ }
-function parseCommaParts(str) {
- if (!str) return [''];
- var parts = [];
- var m = balanced('{', '}', str);
- if (!m) return str.split(',');
- var pre = m.pre;
- var body = m.body;
- var post = m.post;
- var p = pre.split(',');
- p[p.length - 1] += '{' + body + '}';
- var postParts = parseCommaParts(post);
+ if (typeof moduleId !== 'string') {
+ throw new TypeError("Expected `moduleId` to be of type `string`, got `".concat(typeof moduleId, "`"));
+ }
- if (post.length) {
- p[p.length - 1] += postParts.shift();
- p.push.apply(p, postParts);
+ try {
+ fromDir = fs.realpathSync(fromDir);
+ } catch (err) {
+ if (err.code === 'ENOENT') {
+ fromDir = path.resolve(fromDir);
+ } else if (silent) {
+ return null;
+ } else {
+ throw err;
+ }
}
- parts.push.apply(parts, p);
- return parts;
-}
+ const fromFile = path.join(fromDir, 'noop.js');
-function expandTop(str) {
- if (!str) return []; // I don't know why Bash 4.3 does this, but it does.
- // Anything starting with {} will have the first two bytes preserved
- // but *only* at the top level, so {},a}b will not expand to anything,
- // but a{},b}c will be expanded to [a}c,abc].
- // One could argue that this is a bug in Bash, but since the goal of
- // this module is to match Bash's rules, we escape a leading {}
+ const resolveFileName = () => Module._resolveFilename(moduleId, {
+ id: fromFile,
+ filename: fromFile,
+ paths: Module._nodeModulePaths(fromDir)
+ });
- if (str.substr(0, 2) === '{}') {
- str = '\\{\\}' + str.substr(2);
+ if (silent) {
+ try {
+ return resolveFileName();
+ } catch (err) {
+ return null;
+ }
}
- return expand(escapeBraces(str), true).map(unescapeBraces);
-}
+ return resolveFileName();
+};
-function identity(e) {
- return e;
-}
+module.exports = (fromDir, moduleId) => resolveFrom(fromDir, moduleId);
-function embrace(str) {
- return '{' + str + '}';
-}
+module.exports.silent = (fromDir, moduleId) => resolveFrom(fromDir, moduleId, true);
-function isPadded(el) {
- return /^-?0\d/.test(el);
-}
+/***/ }),
+/* 886 */
+/***/ ((module) => {
-function lte(i, y) {
- return i <= y;
-}
+"use strict";
+module.exports = require("module");
-function gte(i, y) {
- return i >= y;
-}
+/***/ }),
+/* 887 */
+/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
-function expand(str, isTop) {
- var expansions = [];
- var m = balanced('{', '}', str);
- if (!m || /\$$/.test(m.pre)) return [str];
- var isNumericSequence = /^-?\d+\.\.-?\d+(?:\.\.-?\d+)?$/.test(m.body);
- var isAlphaSequence = /^[a-zA-Z]\.\.[a-zA-Z](?:\.\.-?\d+)?$/.test(m.body);
- var isSequence = isNumericSequence || isAlphaSequence;
- var isOptions = m.body.indexOf(',') >= 0;
+"use strict";
- if (!isSequence && !isOptions) {
- // {a},b}
- if (m.post.match(/,.*\}/)) {
- str = m.pre + '{' + m.body + escClose + m.post;
- return expand(str);
- }
- return [str];
+const callsites = __webpack_require__(888);
+
+module.exports = filepath => {
+ const stacks = callsites();
+
+ if (!filepath) {
+ return stacks[2].getFileName();
}
- var n;
+ let seenVal = false; // Skip the first stack as it's this function
- if (isSequence) {
- n = m.body.split(/\.\./);
- } else {
- n = parseCommaParts(m.body);
+ stacks.shift();
- if (n.length === 1) {
- // x{{a,b}}y ==> x{a}y x{b}y
- n = expand(n[0], false).map(embrace);
+ for (const stack of stacks) {
+ const parentFilepath = stack.getFileName();
- if (n.length === 1) {
- var post = m.post.length ? expand(m.post, false) : [''];
- return post.map(function (p) {
- return m.pre + n[0] + p;
- });
- }
+ if (typeof parentFilepath !== 'string') {
+ continue;
}
- } // at this point, n is the parts, and we know it's not a comma set
- // with a single entry.
- // no need to expand pre, since it is guaranteed to be free of brace-sets
+ if (parentFilepath === filepath) {
+ seenVal = true;
+ continue;
+ } // Skip native modules
- var pre = m.pre;
- var post = m.post.length ? expand(m.post, false) : [''];
- var N;
- if (isSequence) {
- var x = numeric(n[0]);
- var y = numeric(n[1]);
- var width = Math.max(n[0].length, n[1].length);
- var incr = n.length == 3 ? Math.abs(numeric(n[2])) : 1;
- var test = lte;
- var reverse = y < x;
+ if (parentFilepath === 'module.js') {
+ continue;
+ }
- if (reverse) {
- incr *= -1;
- test = gte;
+ if (seenVal && parentFilepath !== filepath) {
+ return parentFilepath;
}
+ }
+};
- var pad = n.some(isPadded);
- N = [];
+/***/ }),
+/* 888 */
+/***/ ((module) => {
- for (var i = x; test(i, y); i += incr) {
- var c;
+"use strict";
- if (isAlphaSequence) {
- c = String.fromCharCode(i);
- if (c === '\\') c = '';
- } else {
- c = String(i);
- if (pad) {
- var need = width - c.length;
+const callsites = () => {
+ const _prepareStackTrace = Error.prepareStackTrace;
- if (need > 0) {
- var z = new Array(need + 1).join('0');
- if (i < 0) c = '-' + z + c.slice(1);else c = z + c;
- }
- }
- }
+ Error.prepareStackTrace = (_, stack) => stack;
- N.push(c);
- }
- } else {
- N = concatMap(n, function (el) {
- return expand(el, false);
- });
- }
+ const stack = new Error().stack.slice(1);
+ Error.prepareStackTrace = _prepareStackTrace;
+ return stack;
+};
- for (var j = 0; j < N.length; j++) {
- for (var k = 0; k < post.length; k++) {
- var expansion = pre + N[j] + post[k];
- if (!isTop || isSequence || expansion) expansions.push(expansion);
- }
- }
+module.exports = callsites; // TODO: Remove this for the next major release
- return expansions;
-}
+module.exports["default"] = callsites;
/***/ }),
-/* 873 */
+/* 889 */
/***/ ((module) => {
-module.exports = function (xs, fn) {
- var res = [];
-
- for (var i = 0; i < xs.length; i++) {
- var x = fn(xs[i], i);
- if (isArray(x)) res.push.apply(res, x);else res.push(x);
- }
-
- return res;
-};
-
-var isArray = Array.isArray || function (xs) {
- return Object.prototype.toString.call(xs) === '[object Array]';
-};
+function webpackEmptyContext(req) {
+ var e = new Error("Cannot find module '" + req + "'");
+ e.code = 'MODULE_NOT_FOUND';
+ throw e;
+}
+webpackEmptyContext.keys = () => ([]);
+webpackEmptyContext.resolve = webpackEmptyContext;
+webpackEmptyContext.id = 889;
+module.exports = webpackEmptyContext;
/***/ }),
-/* 874 */
+/* 890 */
/***/ ((module) => {
"use strict";
-module.exports = balanced;
+const singleComment = Symbol('singleComment');
+const multiComment = Symbol('multiComment');
-function balanced(a, b, str) {
- if (a instanceof RegExp) a = maybeMatch(a, str);
- if (b instanceof RegExp) b = maybeMatch(b, str);
- var r = range(a, b, str);
- return r && {
- start: r[0],
- end: r[1],
- pre: str.slice(0, r[0]),
- body: str.slice(r[0] + a.length, r[1]),
- post: str.slice(r[1] + b.length)
- };
-}
+const stripWithoutWhitespace = () => '';
-function maybeMatch(reg, str) {
- var m = str.match(reg);
- return m ? m[0] : null;
-}
+const stripWithWhitespace = (string, start, end) => string.slice(start, end).replace(/\S/g, ' ');
-balanced.range = range;
+const isEscaped = (jsonString, quotePosition) => {
+ let index = quotePosition - 1;
+ let backslashCount = 0;
-function range(a, b, str) {
- var begs, beg, left, right, result;
- var ai = str.indexOf(a);
- var bi = str.indexOf(b, ai + 1);
- var i = ai;
+ while (jsonString[index] === '\\') {
+ index -= 1;
+ backslashCount += 1;
+ }
- if (ai >= 0 && bi > 0) {
- if (a === b) {
- return [ai, bi];
- }
+ return Boolean(backslashCount % 2);
+};
- begs = [];
- left = str.length;
+module.exports = function (jsonString) {
+ let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
- while (i >= 0 && !result) {
- if (i == ai) {
- begs.push(i);
- ai = str.indexOf(a, i + 1);
- } else if (begs.length == 1) {
- result = [begs.pop(), bi];
- } else {
- beg = begs.pop();
+ if (typeof jsonString !== 'string') {
+ throw new TypeError("Expected argument `jsonString` to be a `string`, got `".concat(typeof jsonString, "`"));
+ }
- if (beg < left) {
- left = beg;
- right = bi;
- }
+ const strip = options.whitespace === false ? stripWithoutWhitespace : stripWithWhitespace;
+ let insideString = false;
+ let insideComment = false;
+ let offset = 0;
+ let result = '';
- bi = str.indexOf(b, i + 1);
+ for (let i = 0; i < jsonString.length; i++) {
+ const currentCharacter = jsonString[i];
+ const nextCharacter = jsonString[i + 1];
+
+ if (!insideComment && currentCharacter === '"') {
+ const escaped = isEscaped(jsonString, i);
+
+ if (!escaped) {
+ insideString = !insideString;
}
+ }
- i = ai < bi && ai >= 0 ? ai : bi;
+ if (insideString) {
+ continue;
}
- if (begs.length) {
- result = [left, right];
+ if (!insideComment && currentCharacter + nextCharacter === '//') {
+ result += jsonString.slice(offset, i);
+ offset = i;
+ insideComment = singleComment;
+ i++;
+ } else if (insideComment === singleComment && currentCharacter + nextCharacter === '\r\n') {
+ i++;
+ insideComment = false;
+ result += strip(jsonString, offset, i);
+ offset = i;
+ continue;
+ } else if (insideComment === singleComment && currentCharacter === '\n') {
+ insideComment = false;
+ result += strip(jsonString, offset, i);
+ offset = i;
+ } else if (!insideComment && currentCharacter + nextCharacter === '/*') {
+ result += jsonString.slice(offset, i);
+ offset = i;
+ insideComment = multiComment;
+ i++;
+ continue;
+ } else if (insideComment === multiComment && currentCharacter + nextCharacter === '*/') {
+ i++;
+ insideComment = false;
+ result += strip(jsonString, offset, i + 1);
+ offset = i + 1;
+ continue;
}
}
- return result;
-}
+ return result + (insideComment ? strip(jsonString.slice(offset)) : jsonString.slice(offset));
+};
/***/ }),
-/* 875 */
+/* 891 */
/***/ ((module) => {
"use strict";
module.exports = require("os");
/***/ }),
-/* 876 */
+/* 892 */
/***/ ((module) => {
"use strict";
module.exports = require("url");
/***/ }),
-/* 877 */
+/* 893 */
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
"use strict";
// Requirements
//------------------------------------------------------------------------------
-const fs = __webpack_require__(861);
+const fs = __webpack_require__(880);
const path = __webpack_require__(429);
-const getGlobParent = __webpack_require__(878);
+const getGlobParent = __webpack_require__(894);
-const isGlob = __webpack_require__(879);
+const isGlob = __webpack_require__(895);
const escapeRegExp = __webpack_require__(525);
const {
Minimatch
-} = __webpack_require__(871);
+} = __webpack_require__(862);
const {
Legacy: {
IgnorePattern,
CascadingConfigArrayFactory
}
-} = __webpack_require__(863);
+} = __webpack_require__(883);
const debug = __webpack_require__(496)("eslint:file-enumerator"); //------------------------------------------------------------------------------
// Helpers
};
/***/ }),
-/* 878 */
+/* 894 */
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
"use strict";
-var isGlob = __webpack_require__(879);
+var isGlob = __webpack_require__(895);
var pathPosixDirname = (__webpack_require__(429).posix.dirname);
-var isWin32 = (__webpack_require__(875).platform)() === 'win32';
+var isWin32 = (__webpack_require__(891).platform)() === 'win32';
var slash = '/';
var backslash = /\\/g;
var escaped = /\\([!*?|[\](){}])/g;
}
/***/ }),
-/* 879 */
+/* 895 */
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
/*!
* Copyright (c) 2014-2017, Jon Schlinkert.
* Released under the MIT License.
*/
-var isExtglob = __webpack_require__(880);
+var isExtglob = __webpack_require__(896);
var chars = {
'{': '}',
};
/***/ }),
-/* 880 */
+/* 896 */
/***/ ((module) => {
/*!
};
/***/ }),
-/* 881 */
+/* 897 */
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
"use strict";
};
/***/ }),
-/* 882 */
+/* 898 */
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
"use strict";
// Requirements
//------------------------------------------------------------------------------
-const fs = __webpack_require__(861),
+const fs = __webpack_require__(880),
path = __webpack_require__(429);
const rulesDirCache = {}; //------------------------------------------------------------------------------
return;
}
- rules[file.slice(0, -3)] = __webpack_require__(883)(path.join(rulesDir, file));
+ rules[file.slice(0, -3)] = __webpack_require__(899)(path.join(rulesDir, file));
});
rulesDirCache[rulesDir] = rules;
return rules;
};
/***/ }),
-/* 883 */
+/* 899 */
/***/ ((module) => {
function webpackEmptyContext(req) {
}
webpackEmptyContext.keys = () => ([]);
webpackEmptyContext.resolve = webpackEmptyContext;
-webpackEmptyContext.id = 883;
+webpackEmptyContext.id = 899;
module.exports = webpackEmptyContext;
/***/ }),
-/* 884 */
+/* 900 */
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
"use strict";
// Requirements
//------------------------------------------------------------------------------
-const murmur = __webpack_require__(885); //------------------------------------------------------------------------------
+const murmur = __webpack_require__(901); //------------------------------------------------------------------------------
// Helpers
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
module.exports = hash;
/***/ }),
-/* 885 */
+/* 901 */
/***/ ((module) => {
/**
})();
/***/ }),
-/* 886 */
+/* 902 */
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
"use strict";
const assert = __webpack_require__(431);
-const fs = __webpack_require__(861);
+const fs = __webpack_require__(880);
-const fileEntryCache = __webpack_require__(887);
+const fileEntryCache = __webpack_require__(903);
-const stringify = __webpack_require__(905);
+const stringify = __webpack_require__(921);
const pkg = __webpack_require__(443);
-const hash = __webpack_require__(884);
+const hash = __webpack_require__(900);
const debug = __webpack_require__(496)("eslint:lint-result-cache"); //-----------------------------------------------------------------------------
// Helpers
module.exports = LintResultCache;
/***/ }),
-/* 887 */
+/* 903 */
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
var path = __webpack_require__(429);
-var crypto = __webpack_require__(888);
+var crypto = __webpack_require__(904);
module.exports = {
createFromFile: function (filePath, useChecksum) {
return this.create(fname, dir, useChecksum);
},
create: function (cacheId, _path, useChecksum) {
- var fs = __webpack_require__(861);
+ var fs = __webpack_require__(880);
- var flatCache = __webpack_require__(889);
+ var flatCache = __webpack_require__(905);
var cache = flatCache.load(cacheId, _path);
var normalizedEntries = {};
};
/***/ }),
-/* 888 */
+/* 904 */
/***/ ((module) => {
"use strict";
module.exports = require("crypto");
/***/ }),
-/* 889 */
+/* 905 */
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
var path = __webpack_require__(429);
-var fs = __webpack_require__(861);
+var fs = __webpack_require__(880);
-var utils = __webpack_require__(890);
+var utils = __webpack_require__(906);
-var del = __webpack_require__(892);
+var del = __webpack_require__(908);
var writeJSON = utils.writeJSON;
var cache = {
};
/***/ }),
-/* 890 */
+/* 906 */
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
-var fs = __webpack_require__(861);
+var fs = __webpack_require__(880);
var path = __webpack_require__(429);
-var flatted = __webpack_require__(891);
+var flatted = __webpack_require__(907);
module.exports = {
tryParse: function (filePath, defaultValue) {
};
/***/ }),
-/* 891 */
+/* 907 */
/***/ ((__unused_webpack_module, exports) => {
"use strict";
exports.fromJSON = fromJSON;
/***/ }),
-/* 892 */
+/* 908 */
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
-var rimraf = (__webpack_require__(893).sync);
+var rimraf = (__webpack_require__(909).sync);
-var fs = __webpack_require__(861);
+var fs = __webpack_require__(880);
module.exports = function del(file) {
if (fs.existsSync(file)) {
};
/***/ }),
-/* 893 */
+/* 909 */
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
/* provided dependency */ var process = __webpack_require__(494);
const path = __webpack_require__(429);
-const fs = __webpack_require__(861);
+const fs = __webpack_require__(880);
let glob = undefined;
try {
- glob = __webpack_require__(894);
+ glob = __webpack_require__(910);
} catch (_err) {// treat glob as optional.
}
rimraf.sync = rimrafSync;
/***/ }),
-/* 894 */
+/* 910 */
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
/* provided dependency */ var process = __webpack_require__(494);
// things that don't exist.
module.exports = glob;
-var rp = __webpack_require__(895);
+var rp = __webpack_require__(911);
-var minimatch = __webpack_require__(871);
+var minimatch = __webpack_require__(862);
var Minimatch = minimatch.Minimatch;
-var inherits = __webpack_require__(897);
+var inherits = __webpack_require__(913);
-var EE = (__webpack_require__(898).EventEmitter);
+var EE = (__webpack_require__(914).EventEmitter);
var path = __webpack_require__(429);
var assert = __webpack_require__(431);
-var isAbsolute = __webpack_require__(899);
+var isAbsolute = __webpack_require__(915);
-var globSync = __webpack_require__(900);
+var globSync = __webpack_require__(916);
-var common = __webpack_require__(901);
+var common = __webpack_require__(917);
var setopts = common.setopts;
var ownProp = common.ownProp;
-var inflight = __webpack_require__(902);
+var inflight = __webpack_require__(918);
var util = __webpack_require__(439);
var childrenIgnored = common.childrenIgnored;
var isIgnored = common.isIgnored;
-var once = __webpack_require__(904);
+var once = __webpack_require__(920);
function glob(pattern, options, cb) {
if (typeof options === 'function') cb = options, options = {};
};
/***/ }),
-/* 895 */
+/* 911 */
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
/* provided dependency */ var process = __webpack_require__(494);
realpath.monkeypatch = monkeypatch;
realpath.unmonkeypatch = unmonkeypatch;
-var fs = __webpack_require__(861);
+var fs = __webpack_require__(880);
var origRealpath = fs.realpath;
var origRealpathSync = fs.realpathSync;
var version = process.version;
var ok = /^v[0-5]\./.test(version);
-var old = __webpack_require__(896);
+var old = __webpack_require__(912);
function newError(er) {
return er && er.syscall === 'realpath' && (er.code === 'ELOOP' || er.code === 'ENOMEM' || er.code === 'ENAMETOOLONG');
}
/***/ }),
-/* 896 */
+/* 912 */
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
/* provided dependency */ var process = __webpack_require__(494);
var isWindows = process.platform === 'win32';
-var fs = __webpack_require__(861); // JavaScript implementation of realpath, ported from node pre-v6
+var fs = __webpack_require__(880); // JavaScript implementation of realpath, ported from node pre-v6
var DEBUG = process.env.NODE_DEBUG && /fs/.test(process.env.NODE_DEBUG);
};
/***/ }),
-/* 897 */
+/* 913 */
/***/ ((module) => {
if (typeof Object.create === 'function') {
}
/***/ }),
-/* 898 */
+/* 914 */
/***/ ((module) => {
"use strict";
module.exports = require("events");
/***/ }),
-/* 899 */
+/* 915 */
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
"use strict";
module.exports.win32 = win32;
/***/ }),
-/* 900 */
+/* 916 */
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
/* provided dependency */ var console = __webpack_require__(438);
module.exports = globSync;
globSync.GlobSync = GlobSync;
-var rp = __webpack_require__(895);
+var rp = __webpack_require__(911);
-var minimatch = __webpack_require__(871);
+var minimatch = __webpack_require__(862);
var Minimatch = minimatch.Minimatch;
-var Glob = (__webpack_require__(894).Glob);
+var Glob = (__webpack_require__(910).Glob);
var util = __webpack_require__(439);
var assert = __webpack_require__(431);
-var isAbsolute = __webpack_require__(899);
+var isAbsolute = __webpack_require__(915);
-var common = __webpack_require__(901);
+var common = __webpack_require__(917);
var setopts = common.setopts;
var ownProp = common.ownProp;
};
/***/ }),
-/* 901 */
+/* 917 */
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
/* provided dependency */ var process = __webpack_require__(494);
return Object.prototype.hasOwnProperty.call(obj, field);
}
-var fs = __webpack_require__(861);
+var fs = __webpack_require__(880);
var path = __webpack_require__(429);
-var minimatch = __webpack_require__(871);
+var minimatch = __webpack_require__(862);
-var isAbsolute = __webpack_require__(899);
+var isAbsolute = __webpack_require__(915);
var Minimatch = minimatch.Minimatch;
}
/***/ }),
-/* 902 */
+/* 918 */
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
/* provided dependency */ var process = __webpack_require__(494);
-var wrappy = __webpack_require__(903);
+var wrappy = __webpack_require__(919);
var reqs = Object.create(null);
-var once = __webpack_require__(904);
+var once = __webpack_require__(920);
module.exports = wrappy(inflight);
}
/***/ }),
-/* 903 */
+/* 919 */
/***/ ((module) => {
// Returns a wrapper function that returns a wrapped callback
}
/***/ }),
-/* 904 */
+/* 920 */
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
-var wrappy = __webpack_require__(903);
+var wrappy = __webpack_require__(919);
module.exports = wrappy(once);
module.exports.strict = wrappy(onceStrict);
}
/***/ }),
-/* 905 */
+/* 921 */
/***/ ((module) => {
module.exports = function (obj, opts) {
/******/ __webpack_require__(0);
/******/ __webpack_require__(427);
/******/ __webpack_require__(428);
-/******/ var __webpack_exports__ = __webpack_require__(859);
+/******/ var __webpack_exports__ = __webpack_require__(878);
/******/
/******/ return __webpack_exports__;
/******/ })()