forked from enviPath/enviPy
Current Dev State
This commit is contained in:
358
static/js/ketcher2/node_modules/eslint/lib/config/autoconfig.js
generated
vendored
Normal file
358
static/js/ketcher2/node_modules/eslint/lib/config/autoconfig.js
generated
vendored
Normal file
@ -0,0 +1,358 @@
|
||||
/**
|
||||
* @fileoverview Used for creating a suggested configuration based on project code.
|
||||
* @author Ian VanSchooten
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Requirements
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
const lodash = require("lodash"),
|
||||
eslint = require("../eslint"),
|
||||
configRule = require("./config-rule"),
|
||||
ConfigOps = require("./config-ops"),
|
||||
recConfig = require("../../conf/eslint-recommended");
|
||||
|
||||
const debug = require("debug")("eslint:autoconfig");
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Data
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
const MAX_CONFIG_COMBINATIONS = 17, // 16 combinations + 1 for severity only
|
||||
RECOMMENDED_CONFIG_NAME = "eslint:recommended";
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Private
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Information about a rule configuration, in the context of a Registry.
|
||||
*
|
||||
* @typedef {Object} registryItem
|
||||
* @param {ruleConfig} config A valid configuration for the rule
|
||||
* @param {number} specificity The number of elements in the ruleConfig array
|
||||
* @param {number} errorCount The number of errors encountered when linting with the config
|
||||
*/
|
||||
|
||||
/**
|
||||
* This callback is used to measure execution status in a progress bar
|
||||
* @callback progressCallback
|
||||
* @param {number} The total number of times the callback will be called.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Create registryItems for rules
|
||||
* @param {rulesConfig} rulesConfig Hash of rule names and arrays of ruleConfig items
|
||||
* @returns {Object} registryItems for each rule in provided rulesConfig
|
||||
*/
|
||||
function makeRegistryItems(rulesConfig) {
|
||||
return Object.keys(rulesConfig).reduce((accumulator, ruleId) => {
|
||||
accumulator[ruleId] = rulesConfig[ruleId].map(config => ({
|
||||
config,
|
||||
specificity: config.length || 1,
|
||||
errorCount: void 0
|
||||
}));
|
||||
return accumulator;
|
||||
}, {});
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an object in which to store rule configs and error counts
|
||||
*
|
||||
* Unless a rulesConfig is provided at construction, the registry will not contain
|
||||
* any rules, only methods. This will be useful for building up registries manually.
|
||||
*
|
||||
* Registry class
|
||||
*/
|
||||
class Registry {
|
||||
|
||||
/**
|
||||
* @param {rulesConfig} [rulesConfig] Hash of rule names and arrays of possible configurations
|
||||
*/
|
||||
constructor(rulesConfig) {
|
||||
this.rules = (rulesConfig) ? makeRegistryItems(rulesConfig) : {};
|
||||
}
|
||||
|
||||
/**
|
||||
* Populate the registry with core rule configs.
|
||||
*
|
||||
* It will set the registry's `rule` property to an object having rule names
|
||||
* as keys and an array of registryItems as values.
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
populateFromCoreRules() {
|
||||
const rulesConfig = configRule.createCoreRuleConfigs();
|
||||
|
||||
this.rules = makeRegistryItems(rulesConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates sets of rule configurations which can be used for linting
|
||||
* and initializes registry errors to zero for those configurations (side effect).
|
||||
*
|
||||
* This combines as many rules together as possible, such that the first sets
|
||||
* in the array will have the highest number of rules configured, and later sets
|
||||
* will have fewer and fewer, as not all rules have the same number of possible
|
||||
* configurations.
|
||||
*
|
||||
* The length of the returned array will be <= MAX_CONFIG_COMBINATIONS.
|
||||
*
|
||||
* @param {Object} registry The autoconfig registry
|
||||
* @returns {Object[]} "rules" configurations to use for linting
|
||||
*/
|
||||
buildRuleSets() {
|
||||
let idx = 0;
|
||||
const ruleIds = Object.keys(this.rules),
|
||||
ruleSets = [];
|
||||
|
||||
/**
|
||||
* Add a rule configuration from the registry to the ruleSets
|
||||
*
|
||||
* This is broken out into its own function so that it doesn't need to be
|
||||
* created inside of the while loop.
|
||||
*
|
||||
* @param {string} rule The ruleId to add.
|
||||
* @returns {void}
|
||||
*/
|
||||
const addRuleToRuleSet = function(rule) {
|
||||
|
||||
/*
|
||||
* This check ensures that there is a rule configuration and that
|
||||
* it has fewer than the max combinations allowed.
|
||||
* If it has too many configs, we will only use the most basic of
|
||||
* the possible configurations.
|
||||
*/
|
||||
const hasFewCombos = (this.rules[rule].length <= MAX_CONFIG_COMBINATIONS);
|
||||
|
||||
if (this.rules[rule][idx] && (hasFewCombos || this.rules[rule][idx].specificity <= 2)) {
|
||||
|
||||
/*
|
||||
* If the rule has too many possible combinations, only take
|
||||
* simple ones, avoiding objects.
|
||||
*/
|
||||
if (!hasFewCombos && typeof this.rules[rule][idx].config[1] === "object") {
|
||||
return;
|
||||
}
|
||||
|
||||
ruleSets[idx] = ruleSets[idx] || {};
|
||||
ruleSets[idx][rule] = this.rules[rule][idx].config;
|
||||
|
||||
/*
|
||||
* Initialize errorCount to zero, since this is a config which
|
||||
* will be linted.
|
||||
*/
|
||||
this.rules[rule][idx].errorCount = 0;
|
||||
}
|
||||
}.bind(this);
|
||||
|
||||
while (ruleSets.length === idx) {
|
||||
ruleIds.forEach(addRuleToRuleSet);
|
||||
idx += 1;
|
||||
}
|
||||
|
||||
return ruleSets;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all items from the registry with a non-zero number of errors
|
||||
*
|
||||
* Note: this also removes rule configurations which were not linted
|
||||
* (meaning, they have an undefined errorCount).
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
stripFailingConfigs() {
|
||||
const ruleIds = Object.keys(this.rules),
|
||||
newRegistry = new Registry();
|
||||
|
||||
newRegistry.rules = Object.assign({}, this.rules);
|
||||
ruleIds.forEach(ruleId => {
|
||||
const errorFreeItems = newRegistry.rules[ruleId].filter(registryItem => (registryItem.errorCount === 0));
|
||||
|
||||
if (errorFreeItems.length > 0) {
|
||||
newRegistry.rules[ruleId] = errorFreeItems;
|
||||
} else {
|
||||
delete newRegistry.rules[ruleId];
|
||||
}
|
||||
});
|
||||
|
||||
return newRegistry;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes rule configurations which were not included in a ruleSet
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
stripExtraConfigs() {
|
||||
const ruleIds = Object.keys(this.rules),
|
||||
newRegistry = new Registry();
|
||||
|
||||
newRegistry.rules = Object.assign({}, this.rules);
|
||||
ruleIds.forEach(ruleId => {
|
||||
newRegistry.rules[ruleId] = newRegistry.rules[ruleId].filter(registryItem => (typeof registryItem.errorCount !== "undefined"));
|
||||
});
|
||||
|
||||
return newRegistry;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a registry of rules which had no error-free configs.
|
||||
* The new registry is intended to be analyzed to determine whether its rules
|
||||
* should be disabled or set to warning.
|
||||
*
|
||||
* @returns {Registry} A registry of failing rules.
|
||||
*/
|
||||
getFailingRulesRegistry() {
|
||||
const ruleIds = Object.keys(this.rules),
|
||||
failingRegistry = new Registry();
|
||||
|
||||
ruleIds.forEach(ruleId => {
|
||||
const failingConfigs = this.rules[ruleId].filter(registryItem => (registryItem.errorCount > 0));
|
||||
|
||||
if (failingConfigs && failingConfigs.length === this.rules[ruleId].length) {
|
||||
failingRegistry.rules[ruleId] = failingConfigs;
|
||||
}
|
||||
});
|
||||
|
||||
return failingRegistry;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an eslint config for any rules which only have one configuration
|
||||
* in the registry.
|
||||
*
|
||||
* @returns {Object} An eslint config with rules section populated
|
||||
*/
|
||||
createConfig() {
|
||||
const ruleIds = Object.keys(this.rules),
|
||||
config = { rules: {} };
|
||||
|
||||
ruleIds.forEach(ruleId => {
|
||||
if (this.rules[ruleId].length === 1) {
|
||||
config.rules[ruleId] = this.rules[ruleId][0].config;
|
||||
}
|
||||
});
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a cloned registry containing only configs with a desired specificity
|
||||
*
|
||||
* @param {number} specificity Only keep configs with this specificity
|
||||
* @returns {Registry} A registry of rules
|
||||
*/
|
||||
filterBySpecificity(specificity) {
|
||||
const ruleIds = Object.keys(this.rules),
|
||||
newRegistry = new Registry();
|
||||
|
||||
newRegistry.rules = Object.assign({}, this.rules);
|
||||
ruleIds.forEach(ruleId => {
|
||||
newRegistry.rules[ruleId] = this.rules[ruleId].filter(registryItem => (registryItem.specificity === specificity));
|
||||
});
|
||||
|
||||
return newRegistry;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lint SourceCodes against all configurations in the registry, and record results
|
||||
*
|
||||
* @param {Object[]} sourceCodes SourceCode objects for each filename
|
||||
* @param {Object} config ESLint config object
|
||||
* @param {progressCallback} [cb] Optional callback for reporting execution status
|
||||
* @returns {Registry} New registry with errorCount populated
|
||||
*/
|
||||
lintSourceCode(sourceCodes, config, cb) {
|
||||
let ruleSetIdx,
|
||||
lintedRegistry;
|
||||
|
||||
lintedRegistry = new Registry();
|
||||
lintedRegistry.rules = Object.assign({}, this.rules);
|
||||
|
||||
const ruleSets = lintedRegistry.buildRuleSets();
|
||||
|
||||
lintedRegistry = lintedRegistry.stripExtraConfigs();
|
||||
|
||||
debug("Linting with all possible rule combinations");
|
||||
|
||||
const filenames = Object.keys(sourceCodes);
|
||||
const totalFilesLinting = filenames.length * ruleSets.length;
|
||||
|
||||
filenames.forEach(filename => {
|
||||
debug(`Linting file: ${filename}`);
|
||||
|
||||
ruleSetIdx = 0;
|
||||
|
||||
ruleSets.forEach(ruleSet => {
|
||||
const lintConfig = Object.assign({}, config, { rules: ruleSet });
|
||||
const lintResults = eslint.verify(sourceCodes[filename], lintConfig);
|
||||
|
||||
lintResults.forEach(result => {
|
||||
|
||||
// It is possible that the error is from a configuration comment
|
||||
// in a linted file, in which case there may not be a config
|
||||
// set in this ruleSetIdx.
|
||||
// (https://github.com/eslint/eslint/issues/5992)
|
||||
// (https://github.com/eslint/eslint/issues/7860)
|
||||
if (
|
||||
lintedRegistry.rules[result.ruleId] &&
|
||||
lintedRegistry.rules[result.ruleId][ruleSetIdx]
|
||||
) {
|
||||
lintedRegistry.rules[result.ruleId][ruleSetIdx].errorCount += 1;
|
||||
}
|
||||
});
|
||||
|
||||
ruleSetIdx += 1;
|
||||
|
||||
if (cb) {
|
||||
cb(totalFilesLinting); // eslint-disable-line callback-return
|
||||
}
|
||||
});
|
||||
|
||||
// Deallocate for GC
|
||||
sourceCodes[filename] = null;
|
||||
});
|
||||
|
||||
return lintedRegistry;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract rule configuration into eslint:recommended where possible.
|
||||
*
|
||||
* This will return a new config with `"extends": "eslint:recommended"` and
|
||||
* only the rules which have configurations different from the recommended config.
|
||||
*
|
||||
* @param {Object} config config object
|
||||
* @returns {Object} config object using `"extends": "eslint:recommended"`
|
||||
*/
|
||||
function extendFromRecommended(config) {
|
||||
const newConfig = Object.assign({}, config);
|
||||
|
||||
ConfigOps.normalizeToStrings(newConfig);
|
||||
|
||||
const recRules = Object.keys(recConfig.rules).filter(ruleId => ConfigOps.isErrorSeverity(recConfig.rules[ruleId]));
|
||||
|
||||
recRules.forEach(ruleId => {
|
||||
if (lodash.isEqual(recConfig.rules[ruleId], newConfig.rules[ruleId])) {
|
||||
delete newConfig.rules[ruleId];
|
||||
}
|
||||
});
|
||||
newConfig.extends = RECOMMENDED_CONFIG_NAME;
|
||||
return newConfig;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Public Interface
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
module.exports = {
|
||||
Registry,
|
||||
extendFromRecommended
|
||||
};
|
||||
613
static/js/ketcher2/node_modules/eslint/lib/config/config-file.js
generated
vendored
Normal file
613
static/js/ketcher2/node_modules/eslint/lib/config/config-file.js
generated
vendored
Normal file
@ -0,0 +1,613 @@
|
||||
/**
|
||||
* @fileoverview Helper to locate and load configuration files.
|
||||
* @author Nicholas C. Zakas
|
||||
*/
|
||||
|
||||
/* eslint no-use-before-define: 0 */
|
||||
|
||||
"use strict";
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Requirements
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
const fs = require("fs"),
|
||||
path = require("path"),
|
||||
shell = require("shelljs"),
|
||||
ConfigOps = require("./config-ops"),
|
||||
validator = require("./config-validator"),
|
||||
Plugins = require("./plugins"),
|
||||
pathUtil = require("../util/path-util"),
|
||||
ModuleResolver = require("../util/module-resolver"),
|
||||
pathIsInside = require("path-is-inside"),
|
||||
stripBom = require("strip-bom"),
|
||||
stripComments = require("strip-json-comments"),
|
||||
stringify = require("json-stable-stringify"),
|
||||
defaultOptions = require("../../conf/eslint-recommended"),
|
||||
requireUncached = require("require-uncached");
|
||||
|
||||
const debug = require("debug")("eslint:config-file");
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Helpers
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Determines sort order for object keys for json-stable-stringify
|
||||
*
|
||||
* see: https://github.com/substack/json-stable-stringify#cmp
|
||||
*
|
||||
* @param {Object} a The first comparison object ({key: akey, value: avalue})
|
||||
* @param {Object} b The second comparison object ({key: bkey, value: bvalue})
|
||||
* @returns {number} 1 or -1, used in stringify cmp method
|
||||
*/
|
||||
function sortByKey(a, b) {
|
||||
return a.key > b.key ? 1 : -1;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Private
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
const CONFIG_FILES = [
|
||||
".eslintrc.js",
|
||||
".eslintrc.yaml",
|
||||
".eslintrc.yml",
|
||||
".eslintrc.json",
|
||||
".eslintrc",
|
||||
"package.json"
|
||||
];
|
||||
|
||||
const resolver = new ModuleResolver();
|
||||
|
||||
/**
|
||||
* Convenience wrapper for synchronously reading file contents.
|
||||
* @param {string} filePath The filename to read.
|
||||
* @returns {string} The file contents.
|
||||
* @private
|
||||
*/
|
||||
function readFile(filePath) {
|
||||
return stripBom(fs.readFileSync(filePath, "utf8"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if a given string represents a filepath or not using the same
|
||||
* conventions as require(), meaning that the first character must be nonalphanumeric
|
||||
* and not the @ sign which is used for scoped packages to be considered a file path.
|
||||
* @param {string} filePath The string to check.
|
||||
* @returns {boolean} True if it's a filepath, false if not.
|
||||
* @private
|
||||
*/
|
||||
function isFilePath(filePath) {
|
||||
return path.isAbsolute(filePath) || !/\w|@/.test(filePath.charAt(0));
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads a YAML configuration from a file.
|
||||
* @param {string} filePath The filename to load.
|
||||
* @returns {Object} The configuration object from the file.
|
||||
* @throws {Error} If the file cannot be read.
|
||||
* @private
|
||||
*/
|
||||
function loadYAMLConfigFile(filePath) {
|
||||
debug(`Loading YAML config file: ${filePath}`);
|
||||
|
||||
// lazy load YAML to improve performance when not used
|
||||
const yaml = require("js-yaml");
|
||||
|
||||
try {
|
||||
|
||||
// empty YAML file can be null, so always use
|
||||
return yaml.safeLoad(readFile(filePath)) || {};
|
||||
} catch (e) {
|
||||
debug(`Error reading YAML file: ${filePath}`);
|
||||
e.message = `Cannot read config file: ${filePath}\nError: ${e.message}`;
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads a JSON configuration from a file.
|
||||
* @param {string} filePath The filename to load.
|
||||
* @returns {Object} The configuration object from the file.
|
||||
* @throws {Error} If the file cannot be read.
|
||||
* @private
|
||||
*/
|
||||
function loadJSONConfigFile(filePath) {
|
||||
debug(`Loading JSON config file: ${filePath}`);
|
||||
|
||||
try {
|
||||
return JSON.parse(stripComments(readFile(filePath)));
|
||||
} catch (e) {
|
||||
debug(`Error reading JSON file: ${filePath}`);
|
||||
e.message = `Cannot read config file: ${filePath}\nError: ${e.message}`;
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads a legacy (.eslintrc) configuration from a file.
|
||||
* @param {string} filePath The filename to load.
|
||||
* @returns {Object} The configuration object from the file.
|
||||
* @throws {Error} If the file cannot be read.
|
||||
* @private
|
||||
*/
|
||||
function loadLegacyConfigFile(filePath) {
|
||||
debug(`Loading config file: ${filePath}`);
|
||||
|
||||
// lazy load YAML to improve performance when not used
|
||||
const yaml = require("js-yaml");
|
||||
|
||||
try {
|
||||
return yaml.safeLoad(stripComments(readFile(filePath))) || /* istanbul ignore next */ {};
|
||||
} catch (e) {
|
||||
debug(`Error reading YAML file: ${filePath}`);
|
||||
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 {Object} The configuration object from the file.
|
||||
* @throws {Error} If the file cannot be read.
|
||||
* @private
|
||||
*/
|
||||
function loadJSConfigFile(filePath) {
|
||||
debug(`Loading JS config file: ${filePath}`);
|
||||
try {
|
||||
return requireUncached(filePath);
|
||||
} catch (e) {
|
||||
debug(`Error reading JavaScript file: ${filePath}`);
|
||||
e.message = `Cannot read config file: ${filePath}\nError: ${e.message}`;
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads a configuration from a package.json file.
|
||||
* @param {string} filePath The filename to load.
|
||||
* @returns {Object} The configuration object from the file.
|
||||
* @throws {Error} If the file cannot be read.
|
||||
* @private
|
||||
*/
|
||||
function loadPackageJSONConfigFile(filePath) {
|
||||
debug(`Loading package.json config file: ${filePath}`);
|
||||
try {
|
||||
return loadJSONConfigFile(filePath).eslintConfig || null;
|
||||
} catch (e) {
|
||||
debug(`Error reading package.json file: ${filePath}`);
|
||||
e.message = `Cannot read config file: ${filePath}\nError: ${e.message}`;
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an error to notify about a missing config to extend from.
|
||||
* @param {string} configName The name of the missing config.
|
||||
* @returns {Error} The error object to throw
|
||||
* @private
|
||||
*/
|
||||
function configMissingError(configName) {
|
||||
const error = new Error(`Failed to load config "${configName}" to extend from.`);
|
||||
|
||||
error.messageTemplate = "extend-config-missing";
|
||||
error.messageData = {
|
||||
configName
|
||||
};
|
||||
return error;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads a configuration file regardless of the source. Inspects the file path
|
||||
* to determine the correctly way to load the config file.
|
||||
* @param {Object} file The path to the configuration.
|
||||
* @returns {Object} The configuration information.
|
||||
* @private
|
||||
*/
|
||||
function loadConfigFile(file) {
|
||||
const filePath = file.filePath;
|
||||
let config;
|
||||
|
||||
switch (path.extname(filePath)) {
|
||||
case ".js":
|
||||
config = loadJSConfigFile(filePath);
|
||||
if (file.configName) {
|
||||
config = config.configs[file.configName];
|
||||
if (!config) {
|
||||
throw configMissingError(file.configFullName);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case ".json":
|
||||
if (path.basename(filePath) === "package.json") {
|
||||
config = loadPackageJSONConfigFile(filePath);
|
||||
if (config === null) {
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
config = loadJSONConfigFile(filePath);
|
||||
}
|
||||
break;
|
||||
|
||||
case ".yaml":
|
||||
case ".yml":
|
||||
config = loadYAMLConfigFile(filePath);
|
||||
break;
|
||||
|
||||
default:
|
||||
config = loadLegacyConfigFile(filePath);
|
||||
}
|
||||
|
||||
return ConfigOps.merge(ConfigOps.createEmptyConfig(), config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a configuration file in JSON format.
|
||||
* @param {Object} config The configuration object to write.
|
||||
* @param {string} filePath The filename to write to.
|
||||
* @returns {void}
|
||||
* @private
|
||||
*/
|
||||
function writeJSONConfigFile(config, filePath) {
|
||||
debug(`Writing JSON config file: ${filePath}`);
|
||||
|
||||
const content = stringify(config, { cmp: sortByKey, space: 4 });
|
||||
|
||||
fs.writeFileSync(filePath, content, "utf8");
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a configuration file in YAML format.
|
||||
* @param {Object} config The configuration object to write.
|
||||
* @param {string} filePath The filename to write to.
|
||||
* @returns {void}
|
||||
* @private
|
||||
*/
|
||||
function writeYAMLConfigFile(config, filePath) {
|
||||
debug(`Writing YAML config file: ${filePath}`);
|
||||
|
||||
// lazy load YAML to improve performance when not used
|
||||
const yaml = require("js-yaml");
|
||||
|
||||
const content = yaml.safeDump(config, { sortKeys: true });
|
||||
|
||||
fs.writeFileSync(filePath, content, "utf8");
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a configuration file in JavaScript format.
|
||||
* @param {Object} config The configuration object to write.
|
||||
* @param {string} filePath The filename to write to.
|
||||
* @returns {void}
|
||||
* @private
|
||||
*/
|
||||
function writeJSConfigFile(config, filePath) {
|
||||
debug(`Writing JS config file: ${filePath}`);
|
||||
|
||||
const content = `module.exports = ${stringify(config, { cmp: sortByKey, space: 4 })};`;
|
||||
|
||||
fs.writeFileSync(filePath, content, "utf8");
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a configuration file.
|
||||
* @param {Object} config The configuration object to write.
|
||||
* @param {string} filePath The filename to write to.
|
||||
* @returns {void}
|
||||
* @throws {Error} When an unknown file type is specified.
|
||||
* @private
|
||||
*/
|
||||
function write(config, filePath) {
|
||||
switch (path.extname(filePath)) {
|
||||
case ".js":
|
||||
writeJSConfigFile(config, filePath);
|
||||
break;
|
||||
|
||||
case ".json":
|
||||
writeJSONConfigFile(config, filePath);
|
||||
break;
|
||||
|
||||
case ".yaml":
|
||||
case ".yml":
|
||||
writeYAMLConfigFile(config, filePath);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new Error("Can't write to unknown file type.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the base directory for node packages referenced in a config file.
|
||||
* This does not include node_modules in the path so it can be used for all
|
||||
* references relative to a config file.
|
||||
* @param {string} configFilePath The config file referencing the file.
|
||||
* @returns {string} The base directory for the file path.
|
||||
* @private
|
||||
*/
|
||||
function getBaseDir(configFilePath) {
|
||||
|
||||
// calculates the path of the project including ESLint as dependency
|
||||
const projectPath = path.resolve(__dirname, "../../../");
|
||||
|
||||
if (configFilePath && pathIsInside(configFilePath, projectPath)) {
|
||||
|
||||
// be careful of https://github.com/substack/node-resolve/issues/78
|
||||
return path.join(path.resolve(configFilePath));
|
||||
}
|
||||
|
||||
/*
|
||||
* default to ESLint project path since it's unlikely that plugins will be
|
||||
* in this directory
|
||||
*/
|
||||
return path.join(projectPath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the lookup path, including node_modules, for package
|
||||
* references relative to a config file.
|
||||
* @param {string} configFilePath The config file referencing the file.
|
||||
* @returns {string} The lookup path for the file path.
|
||||
* @private
|
||||
*/
|
||||
function getLookupPath(configFilePath) {
|
||||
const basedir = getBaseDir(configFilePath);
|
||||
|
||||
return path.join(basedir, "node_modules");
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves a eslint core config path
|
||||
* @param {string} name The eslint config name.
|
||||
* @returns {string} The resolved path of the config.
|
||||
* @private
|
||||
*/
|
||||
function getEslintCoreConfigPath(name) {
|
||||
if (name === "eslint:recommended") {
|
||||
|
||||
/*
|
||||
* Add an explicit substitution for eslint:recommended to
|
||||
* conf/eslint-recommended.js.
|
||||
*/
|
||||
return path.resolve(__dirname, "../../conf/eslint-recommended.js");
|
||||
}
|
||||
|
||||
if (name === "eslint:all") {
|
||||
|
||||
/*
|
||||
* Add an explicit substitution for eslint:all to conf/eslint-all.js
|
||||
*/
|
||||
return path.resolve(__dirname, "../../conf/eslint-all.js");
|
||||
}
|
||||
|
||||
throw configMissingError(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies values from the "extends" field in a configuration file.
|
||||
* @param {Object} config The configuration information.
|
||||
* @param {string} filePath The file path from which the configuration information
|
||||
* was loaded.
|
||||
* @param {string} [relativeTo] The path to resolve relative to.
|
||||
* @returns {Object} A new configuration object with all of the "extends" fields
|
||||
* loaded and merged.
|
||||
* @private
|
||||
*/
|
||||
function applyExtends(config, filePath, relativeTo) {
|
||||
let configExtends = config.extends;
|
||||
|
||||
// normalize into an array for easier handling
|
||||
if (!Array.isArray(config.extends)) {
|
||||
configExtends = [config.extends];
|
||||
}
|
||||
|
||||
// Make the last element in an array take the highest precedence
|
||||
config = configExtends.reduceRight((previousValue, parentPath) => {
|
||||
try {
|
||||
if (parentPath.startsWith("eslint:")) {
|
||||
parentPath = getEslintCoreConfigPath(parentPath);
|
||||
} else if (isFilePath(parentPath)) {
|
||||
|
||||
/*
|
||||
* If the `extends` path is relative, use the directory of the current configuration
|
||||
* file as the reference point. Otherwise, use as-is.
|
||||
*/
|
||||
parentPath = (path.isAbsolute(parentPath)
|
||||
? parentPath
|
||||
: path.join(relativeTo || path.dirname(filePath), parentPath)
|
||||
);
|
||||
}
|
||||
debug(`Loading ${parentPath}`);
|
||||
return ConfigOps.merge(load(parentPath, false, relativeTo), previousValue);
|
||||
} catch (e) {
|
||||
|
||||
/*
|
||||
* If the file referenced by `extends` failed to load, add the path
|
||||
* to the configuration file that referenced it to the error
|
||||
* message so the user is able to see where it was referenced from,
|
||||
* then re-throw.
|
||||
*/
|
||||
e.message += `\nReferenced from: ${filePath}`;
|
||||
throw e;
|
||||
}
|
||||
|
||||
}, config);
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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" or "eslint-config
|
||||
* @returns {string} Normalized name of the package
|
||||
* @private
|
||||
*/
|
||||
function normalizePackageName(name, prefix) {
|
||||
|
||||
/*
|
||||
* 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 (name.indexOf("\\") > -1) {
|
||||
name = pathUtil.convertPathToPosix(name);
|
||||
}
|
||||
|
||||
if (name.charAt(0) === "@") {
|
||||
|
||||
/*
|
||||
* it's a scoped package
|
||||
* package name is "eslint-config", or just a username
|
||||
*/
|
||||
const scopedPackageShortcutRegex = new RegExp(`^(@[^/]+)(?:/(?:${prefix})?)?$`),
|
||||
scopedPackageNameRegex = new RegExp(`^${prefix}(-|$)`);
|
||||
|
||||
if (scopedPackageShortcutRegex.test(name)) {
|
||||
name = name.replace(scopedPackageShortcutRegex, `$1/${prefix}`);
|
||||
} else if (!scopedPackageNameRegex.test(name.split("/")[1])) {
|
||||
|
||||
/*
|
||||
* for scoped packages, insert the eslint-config after the first / unless
|
||||
* the path is already @scope/eslint or @scope/eslint-config-xxx
|
||||
*/
|
||||
name = name.replace(/^@([^/]+)\/(.*)$/, `@$1/${prefix}-$2`);
|
||||
}
|
||||
} else if (name.indexOf(`${prefix}-`) !== 0) {
|
||||
name = `${prefix}-${name}`;
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves a configuration file path into the fully-formed path, whether filename
|
||||
* or package name.
|
||||
* @param {string} filePath The filepath to resolve.
|
||||
* @param {string} [relativeTo] The path to resolve relative to.
|
||||
* @returns {Object} An object containing 3 properties:
|
||||
* - 'filePath' (required) the resolved path that can be used directly to load the configuration.
|
||||
* - 'configName' the name of the configuration inside the plugin.
|
||||
* - 'configFullName' the name of the configuration as used in the eslint config (e.g. 'plugin:node/recommended').
|
||||
* @private
|
||||
*/
|
||||
function resolve(filePath, relativeTo) {
|
||||
if (isFilePath(filePath)) {
|
||||
return { filePath: path.resolve(relativeTo || "", filePath) };
|
||||
}
|
||||
let normalizedPackageName;
|
||||
|
||||
if (filePath.startsWith("plugin:")) {
|
||||
const configFullName = filePath;
|
||||
const pluginName = filePath.substr(7, filePath.lastIndexOf("/") - 7);
|
||||
const configName = filePath.substr(filePath.lastIndexOf("/") + 1, filePath.length - filePath.lastIndexOf("/") - 1);
|
||||
|
||||
normalizedPackageName = normalizePackageName(pluginName, "eslint-plugin");
|
||||
debug(`Attempting to resolve ${normalizedPackageName}`);
|
||||
filePath = resolver.resolve(normalizedPackageName, getLookupPath(relativeTo));
|
||||
return { filePath, configName, configFullName };
|
||||
}
|
||||
normalizedPackageName = normalizePackageName(filePath, "eslint-config");
|
||||
debug(`Attempting to resolve ${normalizedPackageName}`);
|
||||
filePath = resolver.resolve(normalizedPackageName, getLookupPath(relativeTo));
|
||||
return { filePath };
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads a configuration file from the given file path.
|
||||
* @param {string} filePath The filename or package name to load the configuration
|
||||
* information from.
|
||||
* @param {boolean} [applyEnvironments=false] Set to true to merge in environment settings.
|
||||
* @param {string} [relativeTo] The path to resolve relative to.
|
||||
* @returns {Object} The configuration information.
|
||||
* @private
|
||||
*/
|
||||
function load(filePath, applyEnvironments, relativeTo) {
|
||||
const resolvedPath = resolve(filePath, relativeTo),
|
||||
dirname = path.dirname(resolvedPath.filePath),
|
||||
lookupPath = getLookupPath(dirname);
|
||||
let config = loadConfigFile(resolvedPath);
|
||||
|
||||
if (config) {
|
||||
|
||||
// ensure plugins are properly loaded first
|
||||
if (config.plugins) {
|
||||
Plugins.loadAll(config.plugins);
|
||||
}
|
||||
|
||||
// remove parser from config if it is the default parser
|
||||
if (config.parser === defaultOptions.parser) {
|
||||
config.parser = null;
|
||||
}
|
||||
|
||||
// include full path of parser if present
|
||||
if (config.parser) {
|
||||
if (isFilePath(config.parser)) {
|
||||
config.parser = path.resolve(dirname || "", config.parser);
|
||||
} else {
|
||||
config.parser = resolver.resolve(config.parser, lookupPath);
|
||||
}
|
||||
}
|
||||
|
||||
// validate the configuration before continuing
|
||||
validator.validate(config, filePath);
|
||||
|
||||
/*
|
||||
* If an `extends` property is defined, it represents a configuration file to use as
|
||||
* a "parent". Load the referenced file and merge the configuration recursively.
|
||||
*/
|
||||
if (config.extends) {
|
||||
config = applyExtends(config, filePath, dirname);
|
||||
}
|
||||
|
||||
if (config.env && applyEnvironments) {
|
||||
|
||||
// Merge in environment-specific globals and parserOptions.
|
||||
config = ConfigOps.applyEnvironments(config);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Public Interface
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
module.exports = {
|
||||
|
||||
getBaseDir,
|
||||
getLookupPath,
|
||||
load,
|
||||
resolve,
|
||||
write,
|
||||
applyExtends,
|
||||
normalizePackageName,
|
||||
CONFIG_FILES,
|
||||
|
||||
/**
|
||||
* Retrieves the configuration filename for a given directory. It loops over all
|
||||
* of the valid configuration filenames in order to find the first one that exists.
|
||||
* @param {string} directory The directory to check for a config file.
|
||||
* @returns {?string} The filename of the configuration file for the directory
|
||||
* or null if there is no configuration file in the directory.
|
||||
*/
|
||||
getFilenameForDirectory(directory) {
|
||||
for (let i = 0, len = CONFIG_FILES.length; i < len; i++) {
|
||||
const filename = path.join(directory, CONFIG_FILES[i]);
|
||||
|
||||
if (shell.test("-f", filename)) {
|
||||
return filename;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
};
|
||||
495
static/js/ketcher2/node_modules/eslint/lib/config/config-initializer.js
generated
vendored
Normal file
495
static/js/ketcher2/node_modules/eslint/lib/config/config-initializer.js
generated
vendored
Normal file
@ -0,0 +1,495 @@
|
||||
/**
|
||||
* @fileoverview Config initialization wizard.
|
||||
* @author Ilya Volodin
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Requirements
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
const util = require("util"),
|
||||
inquirer = require("inquirer"),
|
||||
ProgressBar = require("progress"),
|
||||
autoconfig = require("./autoconfig.js"),
|
||||
ConfigFile = require("./config-file"),
|
||||
ConfigOps = require("./config-ops"),
|
||||
getSourceCodeOfFiles = require("../util/source-code-util").getSourceCodeOfFiles,
|
||||
npmUtil = require("../util/npm-util"),
|
||||
recConfig = require("../../conf/eslint-recommended"),
|
||||
log = require("../logging");
|
||||
|
||||
const debug = require("debug")("eslint:config-initializer");
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Private
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/* istanbul ignore next: hard to test fs function */
|
||||
/**
|
||||
* Create .eslintrc file in the current working directory
|
||||
* @param {Object} config object that contains user's answers
|
||||
* @param {string} format The file format to write to.
|
||||
* @returns {void}
|
||||
*/
|
||||
function writeFile(config, format) {
|
||||
|
||||
// default is .js
|
||||
let extname = ".js";
|
||||
|
||||
if (format === "YAML") {
|
||||
extname = ".yml";
|
||||
} else if (format === "JSON") {
|
||||
extname = ".json";
|
||||
}
|
||||
|
||||
const installedESLint = config.installedESLint;
|
||||
|
||||
delete config.installedESLint;
|
||||
|
||||
ConfigFile.write(config, `./.eslintrc${extname}`);
|
||||
log.info(`Successfully created .eslintrc${extname} file in ${process.cwd()}`);
|
||||
|
||||
if (installedESLint) {
|
||||
log.info("ESLint was installed locally. We recommend using this local copy instead of your globally-installed copy.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Synchronously install necessary plugins, configs, parsers, etc. based on the config
|
||||
* @param {Object} config config object
|
||||
* @returns {void}
|
||||
*/
|
||||
function installModules(config) {
|
||||
let modules = [];
|
||||
|
||||
// Create a list of modules which should be installed based on config
|
||||
if (config.plugins) {
|
||||
modules = modules.concat(config.plugins.map(name => `eslint-plugin-${name}`));
|
||||
}
|
||||
if (config.extends && config.extends.indexOf("eslint:") === -1) {
|
||||
modules.push(`eslint-config-${config.extends}`);
|
||||
}
|
||||
|
||||
// Determine which modules are already installed
|
||||
if (modules.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Add eslint to list in case user does not have it installed locally
|
||||
modules.unshift("eslint");
|
||||
|
||||
const installStatus = npmUtil.checkDevDeps(modules);
|
||||
|
||||
// Install packages which aren't already installed
|
||||
const modulesToInstall = Object.keys(installStatus).filter(module => {
|
||||
const notInstalled = installStatus[module] === false;
|
||||
|
||||
if (module === "eslint" && notInstalled) {
|
||||
log.info("Local ESLint installation not found.");
|
||||
config.installedESLint = true;
|
||||
}
|
||||
|
||||
return notInstalled;
|
||||
});
|
||||
|
||||
if (modulesToInstall.length > 0) {
|
||||
log.info(`Installing ${modulesToInstall.join(", ")}`);
|
||||
npmUtil.installSyncSaveDev(modulesToInstall);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the `rules` of a config by examining a user's source code
|
||||
*
|
||||
* Note: This clones the config object and returns a new config to avoid mutating
|
||||
* the original config parameter.
|
||||
*
|
||||
* @param {Object} answers answers received from inquirer
|
||||
* @param {Object} config config object
|
||||
* @returns {Object} config object with configured rules
|
||||
*/
|
||||
function configureRules(answers, config) {
|
||||
const BAR_TOTAL = 20,
|
||||
BAR_SOURCE_CODE_TOTAL = 4,
|
||||
newConfig = Object.assign({}, config),
|
||||
disabledConfigs = {};
|
||||
let sourceCodes,
|
||||
registry;
|
||||
|
||||
// Set up a progress bar, as this process can take a long time
|
||||
const bar = new ProgressBar("Determining Config: :percent [:bar] :elapseds elapsed, eta :etas ", {
|
||||
width: 30,
|
||||
total: BAR_TOTAL
|
||||
});
|
||||
|
||||
bar.tick(0); // Shows the progress bar
|
||||
|
||||
// Get the SourceCode of all chosen files
|
||||
const patterns = answers.patterns.split(/[\s]+/);
|
||||
|
||||
try {
|
||||
sourceCodes = getSourceCodeOfFiles(patterns, { baseConfig: newConfig, useEslintrc: false }, total => {
|
||||
bar.tick((BAR_SOURCE_CODE_TOTAL / total));
|
||||
});
|
||||
} catch (e) {
|
||||
log.info("\n");
|
||||
throw e;
|
||||
}
|
||||
const fileQty = Object.keys(sourceCodes).length;
|
||||
|
||||
if (fileQty === 0) {
|
||||
log.info("\n");
|
||||
throw new Error("Automatic Configuration failed. No files were able to be parsed.");
|
||||
}
|
||||
|
||||
// Create a registry of rule configs
|
||||
registry = new autoconfig.Registry();
|
||||
registry.populateFromCoreRules();
|
||||
|
||||
// Lint all files with each rule config in the registry
|
||||
registry = registry.lintSourceCode(sourceCodes, newConfig, total => {
|
||||
bar.tick((BAR_TOTAL - BAR_SOURCE_CODE_TOTAL) / total); // Subtract out ticks used at beginning
|
||||
});
|
||||
debug(`\nRegistry: ${util.inspect(registry.rules, { depth: null })}`);
|
||||
|
||||
// Create a list of recommended rules, because we don't want to disable them
|
||||
const recRules = Object.keys(recConfig.rules).filter(ruleId => ConfigOps.isErrorSeverity(recConfig.rules[ruleId]));
|
||||
|
||||
// Find and disable rules which had no error-free configuration
|
||||
const failingRegistry = registry.getFailingRulesRegistry();
|
||||
|
||||
Object.keys(failingRegistry.rules).forEach(ruleId => {
|
||||
|
||||
// If the rule is recommended, set it to error, otherwise disable it
|
||||
disabledConfigs[ruleId] = (recRules.indexOf(ruleId) !== -1) ? 2 : 0;
|
||||
});
|
||||
|
||||
// Now that we know which rules to disable, strip out configs with errors
|
||||
registry = registry.stripFailingConfigs();
|
||||
|
||||
// If there is only one config that results in no errors for a rule, we should use it.
|
||||
// createConfig will only add rules that have one configuration in the registry.
|
||||
const singleConfigs = registry.createConfig().rules;
|
||||
|
||||
// The "sweet spot" for number of options in a config seems to be two (severity plus one option).
|
||||
// Very often, a third option (usually an object) is available to address
|
||||
// edge cases, exceptions, or unique situations. We will prefer to use a config with
|
||||
// specificity of two.
|
||||
const specTwoConfigs = registry.filterBySpecificity(2).createConfig().rules;
|
||||
|
||||
// Maybe a specific combination using all three options works
|
||||
const specThreeConfigs = registry.filterBySpecificity(3).createConfig().rules;
|
||||
|
||||
// If all else fails, try to use the default (severity only)
|
||||
const defaultConfigs = registry.filterBySpecificity(1).createConfig().rules;
|
||||
|
||||
// Combine configs in reverse priority order (later take precedence)
|
||||
newConfig.rules = Object.assign({}, disabledConfigs, defaultConfigs, specThreeConfigs, specTwoConfigs, singleConfigs);
|
||||
|
||||
// Make sure progress bar has finished (floating point rounding)
|
||||
bar.update(BAR_TOTAL);
|
||||
|
||||
// Log out some stats to let the user know what happened
|
||||
const finalRuleIds = Object.keys(newConfig.rules);
|
||||
const totalRules = finalRuleIds.length;
|
||||
const enabledRules = finalRuleIds.filter(ruleId => (newConfig.rules[ruleId] !== 0)).length;
|
||||
const resultMessage = [
|
||||
`\nEnabled ${enabledRules} out of ${totalRules}`,
|
||||
`rules based on ${fileQty}`,
|
||||
`file${(fileQty === 1) ? "." : "s."}`
|
||||
].join(" ");
|
||||
|
||||
log.info(resultMessage);
|
||||
|
||||
ConfigOps.normalizeToStrings(newConfig);
|
||||
return newConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* process user's answers and create config object
|
||||
* @param {Object} answers answers received from inquirer
|
||||
* @returns {Object} config object
|
||||
*/
|
||||
function processAnswers(answers) {
|
||||
let config = { rules: {}, env: {} };
|
||||
|
||||
if (answers.es6) {
|
||||
config.env.es6 = true;
|
||||
if (answers.modules) {
|
||||
config.parserOptions = config.parserOptions || {};
|
||||
config.parserOptions.sourceType = "module";
|
||||
}
|
||||
}
|
||||
if (answers.commonjs) {
|
||||
config.env.commonjs = true;
|
||||
}
|
||||
answers.env.forEach(env => {
|
||||
config.env[env] = true;
|
||||
});
|
||||
if (answers.jsx) {
|
||||
config.parserOptions = config.parserOptions || {};
|
||||
config.parserOptions.ecmaFeatures = config.parserOptions.ecmaFeatures || {};
|
||||
config.parserOptions.ecmaFeatures.jsx = true;
|
||||
if (answers.react) {
|
||||
config.plugins = ["react"];
|
||||
config.parserOptions.ecmaFeatures.experimentalObjectRestSpread = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (answers.source === "prompt") {
|
||||
config.extends = "eslint:recommended";
|
||||
config.rules.indent = ["error", answers.indent];
|
||||
config.rules.quotes = ["error", answers.quotes];
|
||||
config.rules["linebreak-style"] = ["error", answers.linebreak];
|
||||
config.rules.semi = ["error", answers.semi ? "always" : "never"];
|
||||
}
|
||||
|
||||
installModules(config);
|
||||
|
||||
if (answers.source === "auto") {
|
||||
config = configureRules(answers, config);
|
||||
config = autoconfig.extendFromRecommended(config);
|
||||
}
|
||||
|
||||
ConfigOps.normalizeToStrings(config);
|
||||
return config;
|
||||
}
|
||||
|
||||
/**
|
||||
* process user's style guide of choice and return an appropriate config object.
|
||||
* @param {string} guide name of the chosen style guide
|
||||
* @returns {Object} config object
|
||||
*/
|
||||
function getConfigForStyleGuide(guide) {
|
||||
const guides = {
|
||||
google: { extends: "google" },
|
||||
airbnb: { extends: "airbnb", plugins: ["react", "jsx-a11y", "import"] },
|
||||
"airbnb-base": { extends: "airbnb-base", plugins: ["import"] },
|
||||
standard: { extends: "standard", plugins: ["standard", "promise"] }
|
||||
};
|
||||
|
||||
if (!guides[guide]) {
|
||||
throw new Error("You referenced an unsupported guide.");
|
||||
}
|
||||
|
||||
installModules(guides[guide]);
|
||||
|
||||
return guides[guide];
|
||||
}
|
||||
|
||||
/* istanbul ignore next: no need to test inquirer*/
|
||||
/**
|
||||
* Ask use a few questions on command prompt
|
||||
* @param {Function} callback callback function when file has been written
|
||||
* @returns {void}
|
||||
*/
|
||||
function promptUser(callback) {
|
||||
let config;
|
||||
|
||||
inquirer.prompt([
|
||||
{
|
||||
type: "list",
|
||||
name: "source",
|
||||
message: "How would you like to configure ESLint?",
|
||||
default: "prompt",
|
||||
choices: [
|
||||
{ name: "Answer questions about your style", value: "prompt" },
|
||||
{ name: "Use a popular style guide", value: "guide" },
|
||||
{ name: "Inspect your JavaScript file(s)", value: "auto" }
|
||||
]
|
||||
},
|
||||
{
|
||||
type: "list",
|
||||
name: "styleguide",
|
||||
message: "Which style guide do you want to follow?",
|
||||
choices: [{ name: "Google", value: "google" }, { name: "Airbnb", value: "airbnb" }, { name: "Standard", value: "standard" }],
|
||||
when(answers) {
|
||||
answers.packageJsonExists = npmUtil.checkPackageJson();
|
||||
return answers.source === "guide" && answers.packageJsonExists;
|
||||
}
|
||||
},
|
||||
{
|
||||
type: "confirm",
|
||||
name: "airbnbReact",
|
||||
message: "Do you use React?",
|
||||
default: false,
|
||||
when(answers) {
|
||||
return answers.styleguide === "airbnb";
|
||||
}
|
||||
},
|
||||
{
|
||||
type: "input",
|
||||
name: "patterns",
|
||||
message: "Which file(s), path(s), or glob(s) should be examined?",
|
||||
when(answers) {
|
||||
return (answers.source === "auto");
|
||||
},
|
||||
validate(input) {
|
||||
if (input.trim().length === 0 && input.trim() !== ",") {
|
||||
return "You must tell us what code to examine. Try again.";
|
||||
}
|
||||
return true;
|
||||
}
|
||||
},
|
||||
{
|
||||
type: "list",
|
||||
name: "format",
|
||||
message: "What format do you want your config file to be in?",
|
||||
default: "JavaScript",
|
||||
choices: ["JavaScript", "YAML", "JSON"],
|
||||
when(answers) {
|
||||
return ((answers.source === "guide" && answers.packageJsonExists) || answers.source === "auto");
|
||||
}
|
||||
}
|
||||
], earlyAnswers => {
|
||||
|
||||
// early exit if you are using a style guide
|
||||
if (earlyAnswers.source === "guide") {
|
||||
if (!earlyAnswers.packageJsonExists) {
|
||||
log.info("A package.json is necessary to install plugins such as style guides. Run `npm init` to create a package.json file and try again.");
|
||||
return;
|
||||
}
|
||||
if (earlyAnswers.styleguide === "airbnb" && !earlyAnswers.airbnbReact) {
|
||||
earlyAnswers.styleguide = "airbnb-base";
|
||||
}
|
||||
try {
|
||||
config = getConfigForStyleGuide(earlyAnswers.styleguide);
|
||||
writeFile(config, earlyAnswers.format);
|
||||
} catch (err) {
|
||||
callback(err);
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// continue with the questions otherwise...
|
||||
inquirer.prompt([
|
||||
{
|
||||
type: "confirm",
|
||||
name: "es6",
|
||||
message: "Are you using ECMAScript 6 features?",
|
||||
default: false
|
||||
},
|
||||
{
|
||||
type: "confirm",
|
||||
name: "modules",
|
||||
message: "Are you using ES6 modules?",
|
||||
default: false,
|
||||
when(answers) {
|
||||
return answers.es6 === true;
|
||||
}
|
||||
},
|
||||
{
|
||||
type: "checkbox",
|
||||
name: "env",
|
||||
message: "Where will your code run?",
|
||||
default: ["browser"],
|
||||
choices: [{ name: "Browser", value: "browser" }, { name: "Node", value: "node" }]
|
||||
},
|
||||
{
|
||||
type: "confirm",
|
||||
name: "commonjs",
|
||||
message: "Do you use CommonJS?",
|
||||
default: false,
|
||||
when(answers) {
|
||||
return answers.env.some(env => env === "browser");
|
||||
}
|
||||
},
|
||||
{
|
||||
type: "confirm",
|
||||
name: "jsx",
|
||||
message: "Do you use JSX?",
|
||||
default: false
|
||||
},
|
||||
{
|
||||
type: "confirm",
|
||||
name: "react",
|
||||
message: "Do you use React?",
|
||||
default: false,
|
||||
when(answers) {
|
||||
return answers.jsx;
|
||||
}
|
||||
}
|
||||
], secondAnswers => {
|
||||
|
||||
// early exit if you are using automatic style generation
|
||||
if (earlyAnswers.source === "auto") {
|
||||
try {
|
||||
const combinedAnswers = Object.assign({}, earlyAnswers, secondAnswers);
|
||||
|
||||
config = processAnswers(combinedAnswers);
|
||||
installModules(config);
|
||||
writeFile(config, earlyAnswers.format);
|
||||
} catch (err) {
|
||||
callback(err);
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// continue with the style questions otherwise...
|
||||
inquirer.prompt([
|
||||
{
|
||||
type: "list",
|
||||
name: "indent",
|
||||
message: "What style of indentation do you use?",
|
||||
default: "tab",
|
||||
choices: [{ name: "Tabs", value: "tab" }, { name: "Spaces", value: 4 }]
|
||||
},
|
||||
{
|
||||
type: "list",
|
||||
name: "quotes",
|
||||
message: "What quotes do you use for strings?",
|
||||
default: "double",
|
||||
choices: [{ name: "Double", value: "double" }, { name: "Single", value: "single" }]
|
||||
},
|
||||
{
|
||||
type: "list",
|
||||
name: "linebreak",
|
||||
message: "What line endings do you use?",
|
||||
default: "unix",
|
||||
choices: [{ name: "Unix", value: "unix" }, { name: "Windows", value: "windows" }]
|
||||
},
|
||||
{
|
||||
type: "confirm",
|
||||
name: "semi",
|
||||
message: "Do you require semicolons?",
|
||||
default: true
|
||||
},
|
||||
{
|
||||
type: "list",
|
||||
name: "format",
|
||||
message: "What format do you want your config file to be in?",
|
||||
default: "JavaScript",
|
||||
choices: ["JavaScript", "YAML", "JSON"]
|
||||
}
|
||||
], answers => {
|
||||
try {
|
||||
const totalAnswers = Object.assign({}, earlyAnswers, secondAnswers, answers);
|
||||
|
||||
config = processAnswers(totalAnswers);
|
||||
installModules(config);
|
||||
writeFile(config, answers.format);
|
||||
} catch (err) {
|
||||
callback(err); // eslint-disable-line callback-return
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Public Interface
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
const init = {
|
||||
getConfigForStyleGuide,
|
||||
processAnswers,
|
||||
/* istanbul ignore next */initializeConfig(callback) {
|
||||
promptUser(callback);
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = init;
|
||||
272
static/js/ketcher2/node_modules/eslint/lib/config/config-ops.js
generated
vendored
Normal file
272
static/js/ketcher2/node_modules/eslint/lib/config/config-ops.js
generated
vendored
Normal file
@ -0,0 +1,272 @@
|
||||
/**
|
||||
* @fileoverview Config file operations. This file must be usable in the browser,
|
||||
* so no Node-specific code can be here.
|
||||
* @author Nicholas C. Zakas
|
||||
*/
|
||||
"use strict";
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Requirements
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
const Environments = require("./environments");
|
||||
|
||||
const debug = require("debug")("eslint:config-ops");
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// 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"];
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Public Interface
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
module.exports = {
|
||||
|
||||
/**
|
||||
* Creates an empty configuration object suitable for merging as a base.
|
||||
* @returns {Object} A configuration object.
|
||||
*/
|
||||
createEmptyConfig() {
|
||||
return {
|
||||
globals: {},
|
||||
env: {},
|
||||
rules: {},
|
||||
parserOptions: {}
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
* Creates an environment config based on the specified environments.
|
||||
* @param {Object<string,boolean>} env The environment settings.
|
||||
* @returns {Object} A configuration object with the appropriate rules and globals
|
||||
* set.
|
||||
*/
|
||||
createEnvironmentConfig(env) {
|
||||
|
||||
const envConfig = this.createEmptyConfig();
|
||||
|
||||
if (env) {
|
||||
|
||||
envConfig.env = env;
|
||||
|
||||
Object.keys(env).filter(name => env[name]).forEach(name => {
|
||||
const environment = Environments.get(name);
|
||||
|
||||
if (environment) {
|
||||
debug(`Creating config for environment ${name}`);
|
||||
if (environment.globals) {
|
||||
Object.assign(envConfig.globals, environment.globals);
|
||||
}
|
||||
|
||||
if (environment.parserOptions) {
|
||||
Object.assign(envConfig.parserOptions, environment.parserOptions);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return envConfig;
|
||||
},
|
||||
|
||||
/**
|
||||
* Given a config with environment settings, applies the globals and
|
||||
* ecmaFeatures to the configuration and returns the result.
|
||||
* @param {Object} config The configuration information.
|
||||
* @returns {Object} The updated configuration information.
|
||||
*/
|
||||
applyEnvironments(config) {
|
||||
if (config.env && typeof config.env === "object") {
|
||||
debug("Apply environment settings to config");
|
||||
return this.merge(this.createEnvironmentConfig(config.env), config);
|
||||
}
|
||||
|
||||
return config;
|
||||
},
|
||||
|
||||
/**
|
||||
* Merges two config objects. This will not only add missing keys, but will also modify values to match.
|
||||
* @param {Object} target config object
|
||||
* @param {Object} src config object. Overrides in this config object will take priority over base.
|
||||
* @param {boolean} [combine] Whether to combine arrays or not
|
||||
* @param {boolean} [isRule] Whether its a rule
|
||||
* @returns {Object} merged config object.
|
||||
*/
|
||||
merge: function deepmerge(target, src, combine, isRule) {
|
||||
|
||||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2012 Nicholas Fisher
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This code is taken from deepmerge repo
|
||||
* (https://github.com/KyleAMathews/deepmerge)
|
||||
* and modified to meet our needs.
|
||||
*/
|
||||
const array = Array.isArray(src) || Array.isArray(target);
|
||||
let dst = array && [] || {};
|
||||
|
||||
combine = !!combine;
|
||||
isRule = !!isRule;
|
||||
if (array) {
|
||||
target = target || [];
|
||||
|
||||
// src could be a string, so check for array
|
||||
if (isRule && Array.isArray(src) && src.length > 1) {
|
||||
dst = dst.concat(src);
|
||||
} else {
|
||||
dst = dst.concat(target);
|
||||
}
|
||||
if (typeof src !== "object" && !Array.isArray(src)) {
|
||||
src = [src];
|
||||
}
|
||||
Object.keys(src).forEach((e, i) => {
|
||||
e = src[i];
|
||||
if (typeof dst[i] === "undefined") {
|
||||
dst[i] = e;
|
||||
} else if (typeof e === "object") {
|
||||
if (isRule) {
|
||||
dst[i] = e;
|
||||
} else {
|
||||
dst[i] = deepmerge(target[i], e, combine, isRule);
|
||||
}
|
||||
} else {
|
||||
if (!combine) {
|
||||
dst[i] = e;
|
||||
} else {
|
||||
if (dst.indexOf(e) === -1) {
|
||||
dst.push(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
if (target && typeof target === "object") {
|
||||
Object.keys(target).forEach(key => {
|
||||
dst[key] = target[key];
|
||||
});
|
||||
}
|
||||
Object.keys(src).forEach(key => {
|
||||
if (Array.isArray(src[key]) || Array.isArray(target[key])) {
|
||||
dst[key] = deepmerge(target[key], src[key], key === "plugins", isRule);
|
||||
} else if (typeof src[key] !== "object" || !src[key] || key === "exported" || key === "astGlobals") {
|
||||
dst[key] = src[key];
|
||||
} else {
|
||||
dst[key] = deepmerge(target[key] || {}, src[key], combine, key === "rules");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return dst;
|
||||
},
|
||||
|
||||
/**
|
||||
* Converts new-style severity settings (off, warn, error) into old-style
|
||||
* severity settings (0, 1, 2) for all rules. Assumption is that severity
|
||||
* values have already been validated as correct.
|
||||
* @param {Object} config The config object to normalize.
|
||||
* @returns {void}
|
||||
*/
|
||||
normalize(config) {
|
||||
|
||||
if (config.rules) {
|
||||
Object.keys(config.rules).forEach(ruleId => {
|
||||
const ruleConfig = config.rules[ruleId];
|
||||
|
||||
if (typeof ruleConfig === "string") {
|
||||
config.rules[ruleId] = RULE_SEVERITY[ruleConfig.toLowerCase()] || 0;
|
||||
} else if (Array.isArray(ruleConfig) && typeof ruleConfig[0] === "string") {
|
||||
ruleConfig[0] = RULE_SEVERITY[ruleConfig[0].toLowerCase()] || 0;
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 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}
|
||||
*/
|
||||
normalizeToStrings(config) {
|
||||
|
||||
if (config.rules) {
|
||||
Object.keys(config.rules).forEach(ruleId => {
|
||||
const ruleConfig = config.rules[ruleId];
|
||||
|
||||
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.
|
||||
*/
|
||||
isErrorSeverity(ruleConfig) {
|
||||
|
||||
let severity = Array.isArray(ruleConfig) ? ruleConfig[0] : ruleConfig;
|
||||
|
||||
if (typeof severity === "string") {
|
||||
severity = RULE_SEVERITY[severity.toLowerCase()] || 0;
|
||||
}
|
||||
|
||||
return (typeof severity === "number" && severity === 2);
|
||||
},
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
isValidSeverity(ruleConfig) {
|
||||
let severity = Array.isArray(ruleConfig) ? ruleConfig[0] : ruleConfig;
|
||||
|
||||
if (typeof severity === "string") {
|
||||
severity = severity.toLowerCase();
|
||||
}
|
||||
return VALID_SEVERITIES.indexOf(severity) !== -1;
|
||||
},
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
isEverySeverityValid(config) {
|
||||
return Object.keys(config).every(ruleId => this.isValidSeverity(config[ruleId]));
|
||||
}
|
||||
};
|
||||
321
static/js/ketcher2/node_modules/eslint/lib/config/config-rule.js
generated
vendored
Normal file
321
static/js/ketcher2/node_modules/eslint/lib/config/config-rule.js
generated
vendored
Normal file
@ -0,0 +1,321 @@
|
||||
/**
|
||||
* @fileoverview Create configurations for a rule
|
||||
* @author Ian VanSchooten
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Requirements
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
const rules = require("../rules"),
|
||||
loadRules = require("../load-rules");
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Helpers
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Wrap all of the elements of an array into arrays.
|
||||
* @param {*[]} xs Any array.
|
||||
* @returns {Array[]} An array of arrays.
|
||||
*/
|
||||
function explodeArray(xs) {
|
||||
return xs.reduce((accumulator, x) => {
|
||||
accumulator.push([x]);
|
||||
return accumulator;
|
||||
}, []);
|
||||
}
|
||||
|
||||
/**
|
||||
* Mix two arrays such that each element of the second array is concatenated
|
||||
* onto each element of the first array.
|
||||
*
|
||||
* For example:
|
||||
* combineArrays([a, [b, c]], [x, y]); // -> [[a, x], [a, y], [b, c, x], [b, c, y]]
|
||||
*
|
||||
* @param {array} arr1 The first array to combine.
|
||||
* @param {array} arr2 The second array to combine.
|
||||
* @returns {array} A mixture of the elements of the first and second arrays.
|
||||
*/
|
||||
function combineArrays(arr1, arr2) {
|
||||
const res = [];
|
||||
|
||||
if (arr1.length === 0) {
|
||||
return explodeArray(arr2);
|
||||
}
|
||||
if (arr2.length === 0) {
|
||||
return explodeArray(arr1);
|
||||
}
|
||||
arr1.forEach(x1 => {
|
||||
arr2.forEach(x2 => {
|
||||
res.push([].concat(x1, x2));
|
||||
});
|
||||
});
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Group together valid rule configurations based on object properties
|
||||
*
|
||||
* e.g.:
|
||||
* groupByProperty([
|
||||
* {before: true},
|
||||
* {before: false},
|
||||
* {after: true},
|
||||
* {after: false}
|
||||
* ]);
|
||||
*
|
||||
* will return:
|
||||
* [
|
||||
* [{before: true}, {before: false}],
|
||||
* [{after: true}, {after: false}]
|
||||
* ]
|
||||
*
|
||||
* @param {Object[]} objects Array of objects, each with one property/value pair
|
||||
* @returns {Array[]} Array of arrays of objects grouped by property
|
||||
*/
|
||||
function groupByProperty(objects) {
|
||||
const groupedObj = objects.reduce((accumulator, obj) => {
|
||||
const prop = Object.keys(obj)[0];
|
||||
|
||||
accumulator[prop] = accumulator[prop] ? accumulator[prop].concat(obj) : [obj];
|
||||
return accumulator;
|
||||
}, {});
|
||||
|
||||
return Object.keys(groupedObj).map(prop => groupedObj[prop]);
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Private
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Configuration settings for a rule.
|
||||
*
|
||||
* A configuration can be a single number (severity), or an array where the first
|
||||
* element in the array is the severity, and is the only required element.
|
||||
* Configs may also have one or more additional elements to specify rule
|
||||
* configuration or options.
|
||||
*
|
||||
* @typedef {array|number} ruleConfig
|
||||
* @param {number} 0 The rule's severity (0, 1, 2).
|
||||
*/
|
||||
|
||||
/**
|
||||
* Object whose keys are rule names and values are arrays of valid ruleConfig items
|
||||
* which should be linted against the target source code to determine error counts.
|
||||
* (a ruleConfigSet.ruleConfigs).
|
||||
*
|
||||
* e.g. rulesConfig = {
|
||||
* "comma-dangle": [2, [2, "always"], [2, "always-multiline"], [2, "never"]],
|
||||
* "no-console": [2]
|
||||
* }
|
||||
* @typedef rulesConfig
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Create valid rule configurations by combining two arrays,
|
||||
* with each array containing multiple objects each with a
|
||||
* single property/value pair and matching properties.
|
||||
*
|
||||
* e.g.:
|
||||
* combinePropertyObjects(
|
||||
* [{before: true}, {before: false}],
|
||||
* [{after: true}, {after: false}]
|
||||
* );
|
||||
*
|
||||
* will return:
|
||||
* [
|
||||
* {before: true, after: true},
|
||||
* {before: true, after: false},
|
||||
* {before: false, after: true},
|
||||
* {before: false, after: false}
|
||||
* ]
|
||||
*
|
||||
* @param {Object[]} objArr1 Single key/value objects, all with the same key
|
||||
* @param {Object[]} objArr2 Single key/value objects, all with another key
|
||||
* @returns {Object[]} Combined objects for each combination of input properties and values
|
||||
*/
|
||||
function combinePropertyObjects(objArr1, objArr2) {
|
||||
const res = [];
|
||||
|
||||
if (objArr1.length === 0) {
|
||||
return objArr2;
|
||||
}
|
||||
if (objArr2.length === 0) {
|
||||
return objArr1;
|
||||
}
|
||||
objArr1.forEach(obj1 => {
|
||||
objArr2.forEach(obj2 => {
|
||||
const combinedObj = {};
|
||||
const obj1Props = Object.keys(obj1);
|
||||
const obj2Props = Object.keys(obj2);
|
||||
|
||||
obj1Props.forEach(prop1 => {
|
||||
combinedObj[prop1] = obj1[prop1];
|
||||
});
|
||||
obj2Props.forEach(prop2 => {
|
||||
combinedObj[prop2] = obj2[prop2];
|
||||
});
|
||||
res.push(combinedObj);
|
||||
});
|
||||
});
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance of a rule configuration set
|
||||
*
|
||||
* A rule configuration set is an array of configurations that are valid for a
|
||||
* given rule. For example, the configuration set for the "semi" rule could be:
|
||||
*
|
||||
* ruleConfigSet.ruleConfigs // -> [[2], [2, "always"], [2, "never"]]
|
||||
*
|
||||
* Rule configuration set class
|
||||
*/
|
||||
class RuleConfigSet {
|
||||
|
||||
/**
|
||||
* @param {ruleConfig[]} configs Valid rule configurations
|
||||
*/
|
||||
constructor(configs) {
|
||||
|
||||
/**
|
||||
* Stored valid rule configurations for this instance
|
||||
* @type {array}
|
||||
*/
|
||||
this.ruleConfigs = configs || [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a severity level to the front of all configs in the instance.
|
||||
* This should only be called after all configs have been added to the instance.
|
||||
*
|
||||
* @param {number} [severity=2] The level of severity for the rule (0, 1, 2)
|
||||
* @returns {void}
|
||||
*/
|
||||
addErrorSeverity(severity) {
|
||||
severity = severity || 2;
|
||||
|
||||
this.ruleConfigs = this.ruleConfigs.map(config => {
|
||||
config.unshift(severity);
|
||||
return config;
|
||||
});
|
||||
|
||||
// Add a single config at the beginning consisting of only the severity
|
||||
this.ruleConfigs.unshift(severity);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add rule configs from an array of strings (schema enums)
|
||||
* @param {string[]} enums Array of valid rule options (e.g. ["always", "never"])
|
||||
* @returns {void}
|
||||
*/
|
||||
addEnums(enums) {
|
||||
this.ruleConfigs = this.ruleConfigs.concat(combineArrays(this.ruleConfigs, enums));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add rule configurations from a schema object
|
||||
* @param {Object} obj Schema item with type === "object"
|
||||
* @returns {boolean} true if at least one schema for the object could be generated, false otherwise
|
||||
*/
|
||||
addObject(obj) {
|
||||
const objectConfigSet = {
|
||||
objectConfigs: [],
|
||||
add(property, values) {
|
||||
for (let idx = 0; idx < values.length; idx++) {
|
||||
const optionObj = {};
|
||||
|
||||
optionObj[property] = values[idx];
|
||||
this.objectConfigs.push(optionObj);
|
||||
}
|
||||
},
|
||||
|
||||
combine() {
|
||||
this.objectConfigs = groupByProperty(this.objectConfigs).reduce((accumulator, objArr) => combinePropertyObjects(accumulator, objArr), []);
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* The object schema could have multiple independent properties.
|
||||
* If any contain enums or booleans, they can be added and then combined
|
||||
*/
|
||||
Object.keys(obj.properties).forEach(prop => {
|
||||
if (obj.properties[prop].enum) {
|
||||
objectConfigSet.add(prop, obj.properties[prop].enum);
|
||||
}
|
||||
if (obj.properties[prop].type && obj.properties[prop].type === "boolean") {
|
||||
objectConfigSet.add(prop, [true, false]);
|
||||
}
|
||||
});
|
||||
objectConfigSet.combine();
|
||||
|
||||
if (objectConfigSet.objectConfigs.length > 0) {
|
||||
this.ruleConfigs = this.ruleConfigs.concat(combineArrays(this.ruleConfigs, objectConfigSet.objectConfigs));
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate valid rule configurations based on a schema object
|
||||
* @param {Object} schema A rule's schema object
|
||||
* @returns {array[]} Valid rule configurations
|
||||
*/
|
||||
function generateConfigsFromSchema(schema) {
|
||||
const configSet = new RuleConfigSet();
|
||||
|
||||
if (Array.isArray(schema)) {
|
||||
for (const opt of schema) {
|
||||
if (opt.enum) {
|
||||
configSet.addEnums(opt.enum);
|
||||
} else if (opt.type && opt.type === "object") {
|
||||
if (!configSet.addObject(opt)) {
|
||||
break;
|
||||
}
|
||||
|
||||
// TODO (IanVS): support oneOf
|
||||
} else {
|
||||
|
||||
// If we don't know how to fill in this option, don't fill in any of the following options.
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
configSet.addErrorSeverity();
|
||||
return configSet.ruleConfigs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate possible rule configurations for all of the core rules
|
||||
* @returns {rulesConfig} Hash of rule names and arrays of possible configurations
|
||||
*/
|
||||
function createCoreRuleConfigs() {
|
||||
const ruleList = loadRules();
|
||||
|
||||
return Object.keys(ruleList).reduce((accumulator, id) => {
|
||||
const rule = rules.get(id);
|
||||
const schema = (typeof rule === "function") ? rule.schema : rule.meta.schema;
|
||||
|
||||
accumulator[id] = generateConfigsFromSchema(schema);
|
||||
return accumulator;
|
||||
}, {});
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Public Interface
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
module.exports = {
|
||||
generateConfigsFromSchema,
|
||||
createCoreRuleConfigs
|
||||
};
|
||||
171
static/js/ketcher2/node_modules/eslint/lib/config/config-validator.js
generated
vendored
Normal file
171
static/js/ketcher2/node_modules/eslint/lib/config/config-validator.js
generated
vendored
Normal file
@ -0,0 +1,171 @@
|
||||
/**
|
||||
* @fileoverview Validates configs.
|
||||
* @author Brandon Mills
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Requirements
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
const rules = require("../rules"),
|
||||
Environments = require("./environments"),
|
||||
schemaValidator = require("is-my-json-valid"),
|
||||
util = require("util");
|
||||
|
||||
const validators = {
|
||||
rules: Object.create(null)
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Private
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Gets a complete options schema for a rule.
|
||||
* @param {string} id The rule's unique name.
|
||||
* @returns {Object} JSON Schema for the rule's options.
|
||||
*/
|
||||
function getRuleOptionsSchema(id) {
|
||||
const rule = rules.get(id),
|
||||
schema = rule && rule.schema || rule && rule.meta && rule.meta.schema;
|
||||
|
||||
// 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
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
// 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
|
||||
*/
|
||||
function validateRuleSeverity(options) {
|
||||
const severity = Array.isArray(options) ? options[0] : options;
|
||||
|
||||
if (severity !== 0 && severity !== 1 && severity !== 2 && !(typeof severity === "string" && /^(?:off|warn|error)$/i.test(severity))) {
|
||||
throw new Error(`\tSeverity should be one of the following: 0 = off, 1 = warn, 2 = error (you passed '${util.inspect(severity).replace(/'/g, "\"").replace(/\n/g, "")}').\n`);
|
||||
}
|
||||
|
||||
return severity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the non-severity options passed to a rule, based on its schema.
|
||||
* @param {string} id The rule's unique name
|
||||
* @param {array} localOptions The options for the rule, excluding severity
|
||||
* @returns {void}
|
||||
*/
|
||||
function validateRuleSchema(id, localOptions) {
|
||||
const schema = getRuleOptionsSchema(id);
|
||||
|
||||
if (!validators.rules[id] && schema) {
|
||||
validators.rules[id] = schemaValidator(schema, { verbose: true });
|
||||
}
|
||||
|
||||
const validateRule = validators.rules[id];
|
||||
|
||||
if (validateRule) {
|
||||
validateRule(localOptions);
|
||||
if (validateRule.errors) {
|
||||
throw new Error(validateRule.errors.map(error => `\tValue "${error.value}" ${error.message}.\n`).join(""));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates a rule's options against its schema.
|
||||
* @param {string} id The rule's unique name.
|
||||
* @param {array|number} options The given options for the rule.
|
||||
* @param {string} source The name of the configuration source.
|
||||
* @returns {void}
|
||||
*/
|
||||
function validateRuleOptions(id, options, source) {
|
||||
try {
|
||||
const severity = validateRuleSeverity(options);
|
||||
|
||||
if (severity !== 0 && !(typeof severity === "string" && severity.toLowerCase() === "off")) {
|
||||
validateRuleSchema(id, Array.isArray(options) ? options.slice(1) : []);
|
||||
}
|
||||
} catch (err) {
|
||||
throw new Error(`${source}:\n\tConfiguration for rule "${id}" is invalid:\n${err.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates an environment object
|
||||
* @param {Object} environment The environment config object to validate.
|
||||
* @param {string} source The location to report with any errors.
|
||||
* @returns {void}
|
||||
*/
|
||||
function validateEnvironment(environment, source) {
|
||||
|
||||
// not having an environment is ok
|
||||
if (!environment) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (Array.isArray(environment)) {
|
||||
throw new Error("Environment must not be an array");
|
||||
}
|
||||
|
||||
if (typeof environment === "object") {
|
||||
Object.keys(environment).forEach(env => {
|
||||
if (!Environments.get(env)) {
|
||||
const message = [
|
||||
source, ":\n",
|
||||
"\tEnvironment key \"", env, "\" is unknown\n"
|
||||
];
|
||||
|
||||
throw new Error(message.join(""));
|
||||
}
|
||||
});
|
||||
} else {
|
||||
throw new Error("Environment must be an object");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates an entire config object.
|
||||
* @param {Object} config The config object to validate.
|
||||
* @param {string} source The location to report with any errors.
|
||||
* @returns {void}
|
||||
*/
|
||||
function validate(config, source) {
|
||||
|
||||
if (typeof config.rules === "object") {
|
||||
Object.keys(config.rules).forEach(id => {
|
||||
validateRuleOptions(id, config.rules[id], source);
|
||||
});
|
||||
}
|
||||
|
||||
validateEnvironment(config.env, source);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Public Interface
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
module.exports = {
|
||||
getRuleOptionsSchema,
|
||||
validate,
|
||||
validateRuleOptions
|
||||
};
|
||||
82
static/js/ketcher2/node_modules/eslint/lib/config/environments.js
generated
vendored
Normal file
82
static/js/ketcher2/node_modules/eslint/lib/config/environments.js
generated
vendored
Normal file
@ -0,0 +1,82 @@
|
||||
/**
|
||||
* @fileoverview Environments manager
|
||||
* @author Nicholas C. Zakas
|
||||
*/
|
||||
"use strict";
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Requirements
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
const envs = require("../../conf/environments");
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Private
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
let environments = new Map();
|
||||
|
||||
/**
|
||||
* Loads the default environments.
|
||||
* @returns {void}
|
||||
* @private
|
||||
*/
|
||||
function load() {
|
||||
Object.keys(envs).forEach(envName => {
|
||||
environments.set(envName, envs[envName]);
|
||||
});
|
||||
}
|
||||
|
||||
// always load default environments upfront
|
||||
load();
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Public Interface
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
module.exports = {
|
||||
|
||||
load,
|
||||
|
||||
/**
|
||||
* Gets the environment with the given name.
|
||||
* @param {string} name The name of the environment to retrieve.
|
||||
* @returns {Object?} The environment object or null if not found.
|
||||
*/
|
||||
get(name) {
|
||||
return environments.get(name) || null;
|
||||
},
|
||||
|
||||
/**
|
||||
* Defines an environment.
|
||||
* @param {string} name The name of the environment.
|
||||
* @param {Object} env The environment settings.
|
||||
* @returns {void}
|
||||
*/
|
||||
define(name, env) {
|
||||
environments.set(name, env);
|
||||
},
|
||||
|
||||
/**
|
||||
* Imports all environments from a plugin.
|
||||
* @param {Object} plugin The plugin object.
|
||||
* @param {string} pluginName The name of the plugin.
|
||||
* @returns {void}
|
||||
*/
|
||||
importPlugin(plugin, pluginName) {
|
||||
if (plugin.environments) {
|
||||
Object.keys(plugin.environments).forEach(envName => {
|
||||
this.define(`${pluginName}/${envName}`, plugin.environments[envName]);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Resets all environments. Only use for tests!
|
||||
* @returns {void}
|
||||
*/
|
||||
testReset() {
|
||||
environments = new Map();
|
||||
load();
|
||||
}
|
||||
};
|
||||
172
static/js/ketcher2/node_modules/eslint/lib/config/plugins.js
generated
vendored
Normal file
172
static/js/ketcher2/node_modules/eslint/lib/config/plugins.js
generated
vendored
Normal file
@ -0,0 +1,172 @@
|
||||
/**
|
||||
* @fileoverview Plugins manager
|
||||
* @author Nicholas C. Zakas
|
||||
*/
|
||||
"use strict";
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Requirements
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
const Environments = require("./environments"),
|
||||
Rules = require("../rules");
|
||||
|
||||
const debug = require("debug")("eslint:plugins");
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Private
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
let plugins = Object.create(null);
|
||||
|
||||
const PLUGIN_NAME_PREFIX = "eslint-plugin-",
|
||||
NAMESPACE_REGEX = /^@.*\//i;
|
||||
|
||||
/**
|
||||
* Removes the prefix `eslint-plugin-` from a plugin name.
|
||||
* @param {string} pluginName The name of the plugin which may have the prefix.
|
||||
* @returns {string} The name of the plugin without prefix.
|
||||
*/
|
||||
function removePrefix(pluginName) {
|
||||
return pluginName.indexOf(PLUGIN_NAME_PREFIX) === 0 ? pluginName.substring(PLUGIN_NAME_PREFIX.length) : pluginName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the scope (namespace) of a plugin.
|
||||
* @param {string} pluginName The name of the plugin which may have the prefix.
|
||||
* @returns {string} The name of the plugins namepace if it has one.
|
||||
*/
|
||||
function getNamespace(pluginName) {
|
||||
return pluginName.match(NAMESPACE_REGEX) ? pluginName.match(NAMESPACE_REGEX)[0] : "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the namespace from a plugin name.
|
||||
* @param {string} pluginName The name of the plugin which may have the prefix.
|
||||
* @returns {string} The name of the plugin without the namespace.
|
||||
*/
|
||||
function removeNamespace(pluginName) {
|
||||
return pluginName.replace(NAMESPACE_REGEX, "");
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Public Interface
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
module.exports = {
|
||||
|
||||
removePrefix,
|
||||
getNamespace,
|
||||
removeNamespace,
|
||||
|
||||
/**
|
||||
* Defines a plugin with a given name rather than loading from disk.
|
||||
* @param {string} pluginName The name of the plugin to load.
|
||||
* @param {Object} plugin The plugin object.
|
||||
* @returns {void}
|
||||
*/
|
||||
define(pluginName, plugin) {
|
||||
const pluginNamespace = getNamespace(pluginName),
|
||||
pluginNameWithoutNamespace = removeNamespace(pluginName),
|
||||
pluginNameWithoutPrefix = removePrefix(pluginNameWithoutNamespace),
|
||||
shortName = pluginNamespace + pluginNameWithoutPrefix;
|
||||
|
||||
// load up environments and rules
|
||||
plugins[shortName] = plugin;
|
||||
Environments.importPlugin(plugin, shortName);
|
||||
Rules.importPlugin(plugin, shortName);
|
||||
|
||||
// load up environments and rules for the name that '@scope/' was omitted
|
||||
// 3 lines below will be removed by 4.0.0
|
||||
plugins[pluginNameWithoutPrefix] = plugin;
|
||||
Environments.importPlugin(plugin, pluginNameWithoutPrefix);
|
||||
Rules.importPlugin(plugin, pluginNameWithoutPrefix);
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets a plugin with the given name.
|
||||
* @param {string} pluginName The name of the plugin to retrieve.
|
||||
* @returns {Object} The plugin or null if not loaded.
|
||||
*/
|
||||
get(pluginName) {
|
||||
return plugins[pluginName] || null;
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns all plugins that are loaded.
|
||||
* @returns {Object} The plugins cache.
|
||||
*/
|
||||
getAll() {
|
||||
return plugins;
|
||||
},
|
||||
|
||||
/**
|
||||
* Loads a plugin with the given name.
|
||||
* @param {string} pluginName The name of the plugin to load.
|
||||
* @returns {void}
|
||||
* @throws {Error} If the plugin cannot be loaded.
|
||||
*/
|
||||
load(pluginName) {
|
||||
const pluginNamespace = getNamespace(pluginName),
|
||||
pluginNameWithoutNamespace = removeNamespace(pluginName),
|
||||
pluginNameWithoutPrefix = removePrefix(pluginNameWithoutNamespace),
|
||||
shortName = pluginNamespace + pluginNameWithoutPrefix,
|
||||
longName = pluginNamespace + PLUGIN_NAME_PREFIX + pluginNameWithoutPrefix;
|
||||
let plugin = null;
|
||||
|
||||
if (pluginName.match(/\s+/)) {
|
||||
const whitespaceError = new Error(`Whitespace found in plugin name '${pluginName}'`);
|
||||
|
||||
whitespaceError.messageTemplate = "whitespace-found";
|
||||
whitespaceError.messageData = {
|
||||
pluginName: longName
|
||||
};
|
||||
throw whitespaceError;
|
||||
}
|
||||
|
||||
if (!plugins[shortName]) {
|
||||
try {
|
||||
plugin = require(longName);
|
||||
} catch (pluginLoadErr) {
|
||||
try {
|
||||
|
||||
// Check whether the plugin exists
|
||||
require.resolve(longName);
|
||||
} catch (missingPluginErr) {
|
||||
|
||||
// If the plugin can't be resolved, display the missing plugin error (usually a config or install error)
|
||||
debug(`Failed to load plugin ${longName}.`);
|
||||
missingPluginErr.message = `Failed to load plugin ${pluginName}: ${missingPluginErr.message}`;
|
||||
missingPluginErr.messageTemplate = "plugin-missing";
|
||||
missingPluginErr.messageData = {
|
||||
pluginName: longName
|
||||
};
|
||||
throw missingPluginErr;
|
||||
}
|
||||
|
||||
// Otherwise, the plugin exists and is throwing on module load for some reason, so print the stack trace.
|
||||
throw pluginLoadErr;
|
||||
}
|
||||
|
||||
this.define(pluginName, plugin);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Loads all plugins from an array.
|
||||
* @param {string[]} pluginNames An array of plugins names.
|
||||
* @returns {void}
|
||||
* @throws {Error} If a plugin cannot be loaded.
|
||||
*/
|
||||
loadAll(pluginNames) {
|
||||
pluginNames.forEach(this.load, this);
|
||||
},
|
||||
|
||||
/**
|
||||
* Resets plugin information. Use for tests only.
|
||||
* @returns {void}
|
||||
*/
|
||||
testReset() {
|
||||
plugins = Object.create(null);
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user