UNPKG

prettier-eslint

Version:

Formats your JavaScript using prettier followed by eslint --fix

457 lines (365 loc) 13.5 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.requireModule = exports.getOptionsForFormatting = exports.getESLintCLIEngine = undefined; var _keys = require("babel-runtime/core-js/object/keys"); var _keys2 = _interopRequireDefault(_keys); var _stringify = require("babel-runtime/core-js/json/stringify"); var _stringify2 = _interopRequireDefault(_stringify); var _slicedToArray2 = require("babel-runtime/helpers/slicedToArray"); var _slicedToArray3 = _interopRequireDefault(_slicedToArray2); var _entries = require("babel-runtime/core-js/object/entries"); var _entries2 = _interopRequireDefault(_entries); var _map = require("babel-runtime/core-js/map"); var _map2 = _interopRequireDefault(_map); var _extends2 = require("babel-runtime/helpers/extends"); var _extends3 = _interopRequireDefault(_extends2); var _commonTags = require("common-tags"); var _dlv = require("dlv"); var _dlv2 = _interopRequireDefault(_dlv); var _loglevelColoredLevelPrefix = require("loglevel-colored-level-prefix"); var _loglevelColoredLevelPrefix2 = _interopRequireDefault(_loglevelColoredLevelPrefix); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } var logger = (0, _loglevelColoredLevelPrefix2.default)({ prefix: "prettier-eslint" }); /* eslint import/no-dynamic-require:0 */ var RULE_DISABLED = {}; var RULE_NOT_CONFIGURED = "RULE_NOT_CONFIGURED"; var ruleValueExists = function ruleValueExists(prettierRuleValue) { return prettierRuleValue !== RULE_NOT_CONFIGURED && prettierRuleValue !== RULE_DISABLED && typeof prettierRuleValue !== "undefined"; }; var OPTION_GETTERS = { printWidth: { ruleValue: function ruleValue(rules) { return getRuleValue(rules, "max-len", "code"); }, ruleValueToPrettierOption: getPrintWidth }, tabWidth: { ruleValue: function ruleValue(rules) { var value = getRuleValue(rules, "indent"); if (value === "tab") { value = getRuleValue(rules, "max-len", "tabWidth"); } return value; }, ruleValueToPrettierOption: getTabWidth }, singleQuote: { ruleValue: function ruleValue(rules) { return getRuleValue(rules, "quotes"); }, ruleValueToPrettierOption: getSingleQuote }, trailingComma: { ruleValue: function ruleValue(rules) { return getRuleValue(rules, "comma-dangle", []); }, ruleValueToPrettierOption: getTrailingComma }, bracketSpacing: { ruleValue: function ruleValue(rules) { return getRuleValue(rules, "object-curly-spacing"); }, ruleValueToPrettierOption: getBracketSpacing }, semi: { ruleValue: function ruleValue(rules) { return getRuleValue(rules, "semi"); }, ruleValueToPrettierOption: getSemi }, useTabs: { ruleValue: function ruleValue(rules) { return getRuleValue(rules, "indent"); }, ruleValueToPrettierOption: getUseTabs }, jsxBracketSameLine: { ruleValue: function ruleValue(rules) { return getRuleValue(rules, "react/jsx-closing-bracket-location", "nonEmpty"); }, ruleValueToPrettierOption: getJsxBracketSameLine }, arrowParens: { ruleValue: function ruleValue(rules) { return getRuleValue(rules, "arrow-parens"); }, ruleValueToPrettierOption: getArrowParens } }; /* eslint import/prefer-default-export:0 */ exports.getESLintCLIEngine = getESLintCLIEngine; exports.getOptionsForFormatting = getOptionsForFormatting; exports.requireModule = requireModule; function getOptionsForFormatting(eslintConfig) { var prettierOptions = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; var fallbackPrettierOptions = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; var eslintPath = arguments[3]; var eslint = getRelevantESLintConfig(eslintConfig, eslintPath); var prettier = getPrettierOptionsFromESLintRules(eslintConfig, prettierOptions, fallbackPrettierOptions); // Disable "prettier/prettier", we don't need to run prettier twice eslint = (0, _extends3.default)({}, eslint, { rules: (0, _extends3.default)({}, eslint.rules, { "prettier/prettier": ["off"] }) }); return { eslint, prettier }; } function getRelevantESLintConfig(eslintConfig, eslintPath) { var cliEngine = getESLintCLIEngine(eslintPath); // TODO: Actually test this branch // istanbul ignore next var loadedRules = cliEngine.getRules && cliEngine.getRules() || new _map2.default([["valid-jsdoc", { meta: {} }], ["global-require", { meta: {} }], ["no-with", { meta: {} }]]); var rules = eslintConfig.rules; logger.debug("turning off unfixable rules"); var relevantRules = (0, _entries2.default)(rules).reduce(function (rulesAccumulator, _ref) { var _ref2 = (0, _slicedToArray3.default)(_ref, 2), name = _ref2[0], rule = _ref2[1]; if (loadedRules.has(name)) { var _loadedRules$get = loadedRules.get(name), fixable = _loadedRules$get.meta.fixable; if (!fixable) { logger.trace("turing off rule:", (0, _stringify2.default)({ [name]: rule })); rule = ["off"]; } } rulesAccumulator[name] = rule; return rulesAccumulator; }, {}); return (0, _extends3.default)({ // defaults useEslintrc: false }, eslintConfig, { // overrides rules: relevantRules, fix: true, globals: [] }); } /** * This accepts an eslintConfig object and converts * it to the `prettier` options object */ function getPrettierOptionsFromESLintRules(eslintConfig, prettierOptions, fallbackPrettierOptions) { var rules = eslintConfig.rules; var prettierPluginOptions = getRuleValue(rules, "prettier/prettier", []); if (ruleValueExists(prettierPluginOptions)) { prettierOptions = (0, _extends3.default)({}, prettierPluginOptions, prettierOptions); } return (0, _keys2.default)(OPTION_GETTERS).reduce(function (options, key) { return configureOptions(prettierOptions, fallbackPrettierOptions, key, options, rules); }, prettierOptions); } // If an ESLint rule that prettier can be configured with is enabled create a // prettier configuration object that reflects the ESLint rule configuration. function configureOptions(prettierOptions, fallbackPrettierOptions, key, options, rules) { var givenOption = prettierOptions[key]; var optionIsGiven = givenOption !== undefined; if (optionIsGiven) { options[key] = givenOption; } else { var _OPTION_GETTERS$key = OPTION_GETTERS[key], ruleValue = _OPTION_GETTERS$key.ruleValue, ruleValueToPrettierOption = _OPTION_GETTERS$key.ruleValueToPrettierOption; var eslintRuleValue = ruleValue(rules); var option = ruleValueToPrettierOption(eslintRuleValue, fallbackPrettierOptions, rules); if (option !== undefined) { options[key] = option; } } return options; } function getPrintWidth(eslintValue, fallbacks) { return makePrettierOption("printWidth", eslintValue, fallbacks); } function getTabWidth(eslintValue, fallbacks) { return makePrettierOption("tabWidth", eslintValue, fallbacks); } function getSingleQuote(eslintValue, fallbacks) { var prettierValue = void 0; if (eslintValue === "single") { prettierValue = true; } else if (eslintValue === "double") { prettierValue = false; } else if (eslintValue === "backtick") { prettierValue = false; } else { prettierValue = eslintValue; } return makePrettierOption("singleQuote", prettierValue, fallbacks); } function getTrailingComma(eslintValue, fallbacks) { var prettierValue = void 0; if (eslintValue === "never") { prettierValue = "none"; } else if (typeof eslintValue === "string" && eslintValue.indexOf("always") === 0) { prettierValue = "es5"; } else if (typeof eslintValue === "object") { prettierValue = getValFromTrailingCommaConfig(eslintValue); } else { prettierValue = RULE_NOT_CONFIGURED; } return makePrettierOption("trailingComma", prettierValue, fallbacks); } function getValFromTrailingCommaConfig(objectConfig) { var _objectConfig$arrays = objectConfig.arrays, arrays = _objectConfig$arrays === undefined ? "" : _objectConfig$arrays, _objectConfig$objects = objectConfig.objects, objects = _objectConfig$objects === undefined ? "" : _objectConfig$objects, _objectConfig$functio = objectConfig.functions, functions = _objectConfig$functio === undefined ? "" : _objectConfig$functio; var fns = isAlways(functions); var es5 = [arrays, objects].some(isAlways); if (fns) { return "all"; } else if (es5) { return "es5"; } else { return "none"; } } function getBracketSpacing(eslintValue, fallbacks) { var prettierValue = void 0; if (eslintValue === "never") { prettierValue = false; } else if (eslintValue === "always") { prettierValue = true; } else { prettierValue = eslintValue; } return makePrettierOption("bracketSpacing", prettierValue, fallbacks); } function getSemi(eslintValue, fallbacks) { var prettierValue = void 0; if (eslintValue === "never") { prettierValue = false; } else if (eslintValue === "always") { prettierValue = true; } else { prettierValue = eslintValue; } return makePrettierOption("semi", prettierValue, fallbacks); } function getUseTabs(eslintValue, fallbacks) { var prettierValue = void 0; if (eslintValue === "tab") { prettierValue = true; } else { prettierValue = RULE_NOT_CONFIGURED; } return makePrettierOption("useTabs", prettierValue, fallbacks); } function getJsxBracketSameLine(eslintValue, fallbacks) { var prettierValue = void 0; if (eslintValue === "after-props") { prettierValue = true; } else if (eslintValue === "tag-aligned" || eslintValue === "line-aligned" || eslintValue === "props-aligned") { prettierValue = false; } else { prettierValue = eslintValue; } return makePrettierOption("jsxBracketSameLine", prettierValue, fallbacks); } function getArrowParens(eslintValue, fallbacks) { var prettierValue = void 0; if (eslintValue === "as-needed") { prettierValue = "avoid"; } else { prettierValue = eslintValue; } return makePrettierOption("arrowParens", prettierValue, fallbacks); } function extractRuleValue(objPath, name, value) { // XXX: Ignore code coverage for the following else case // There are currently no eslint rules which we can infer prettier // options from, that have an object option which we don't know how // to infer from. // istanbul ignore else if (objPath) { logger.trace(_commonTags.oneLine` Getting the value from object configuration of ${name}. delving into ${(0, _stringify2.default)(value)} with path "${objPath}" `); return (0, _dlv2.default)(value, objPath, RULE_NOT_CONFIGURED); } // istanbul ignore next logger.debug(_commonTags.oneLine` The ${name} rule is using an object configuration of ${(0, _stringify2.default)(value)} but prettier-eslint is not currently capable of getting the prettier value based on an object configuration for ${name}. Please file an issue (and make a pull request?) `); // istanbul ignore next return undefined; } function getRuleValue(rules, name, objPath) { var ruleConfig = rules[name]; if (Array.isArray(ruleConfig)) { var _ruleConfig = (0, _slicedToArray3.default)(ruleConfig, 2), ruleSetting = _ruleConfig[0], value = _ruleConfig[1]; // If `ruleSetting` is set to disable the ESLint rule don't use `value` as // it might be a value provided by an overriden config package e.g. airbnb // overriden by config-prettier. The airbnb values are provided even though // config-prettier disables the rule. Instead use fallback or prettier // default. if (ruleSetting === 0 || ruleSetting === "off") { return RULE_DISABLED; } if (typeof value === "object") { return extractRuleValue(objPath, name, value); } else { logger.trace(_commonTags.oneLine` The ${name} rule is configured with a non-object value of ${value}. Using that value. `); return value; } } return RULE_NOT_CONFIGURED; } function isAlways(val) { return val.indexOf("always") === 0; } function makePrettierOption(prettierRuleName, prettierRuleValue, fallbacks) { if (ruleValueExists(prettierRuleValue)) { return prettierRuleValue; } var fallback = fallbacks[prettierRuleName]; if (typeof fallback !== "undefined") { logger.debug(_commonTags.oneLine` The ${prettierRuleName} rule is not configured, using provided fallback of ${fallback} `); return fallback; } logger.debug(_commonTags.oneLine` The ${prettierRuleName} rule is not configured, let prettier decide `); return undefined; } function requireModule(modulePath, name) { try { logger.trace(`requiring "${name}" module at "${modulePath}"`); return require(modulePath); } catch (error) { logger.error(_commonTags.oneLine` There was trouble getting "${name}". Is "${modulePath}" a correct path to the "${name}" module? `); throw error; } } function getESLintCLIEngine(eslintPath, eslintOptions) { var _requireModule = requireModule(eslintPath, "eslint"), CLIEngine = _requireModule.CLIEngine; try { return new CLIEngine(eslintOptions); } catch (error) { logger.error(`There was trouble creating the ESLint CLIEngine.`); throw error; } }