stylelint
Version:
Modern CSS linter
219 lines (187 loc) • 7.61 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = function (options) {
var rawConfig = function () {
if (options.config) return options.config;
if (options.rules) return options;
return null;
}();
var configBasedir = options.configBasedir || process.cwd();
if (rawConfig) {
return augmentConfig(rawConfig, configBasedir, {
addIgnorePatterns: true,
ignorePath: options.ignorePath
}).then(function (augmentedConfig) {
return {
config: (0, _lodash.merge)(augmentedConfig, options.configOverrides),
configDir: configBasedir
};
});
}
var cosmiconfigOptions = {
// Turn off argv option to avoid hijacking the all-too-common
// `--config` argument when stylelint is used in conjunction with other CLI's
// (e.g. webpack)
argv: false,
// Allow extensions on rc filenames
rcExtensions: true
};
if (options.configFile) {
cosmiconfigOptions.configPath = _path2.default.resolve(process.cwd(), options.configFile);
}
var rootConfigDir = void 0;
return (0, _cosmiconfig2.default)("stylelint", cosmiconfigOptions).then(function (result) {
if (!result) throw (0, _utils.configurationError)("No configuration found");
rootConfigDir = _path2.default.dirname(result.filepath);
return augmentConfig(result.config, rootConfigDir, {
addIgnorePatterns: true,
ignorePath: options.ignorePath
});
}).then(function (augmentedConfig) {
var finalConfig = options.configOverrides ? (0, _lodash.merge)({}, augmentedConfig, options.configOverrides) : augmentedConfig;
return {
config: finalConfig,
configDir: rootConfigDir
};
});
};
exports.augmentConfig = augmentConfig;
exports.addIgnoreFiles = addIgnoreFiles;
var _path = require("path");
var _path2 = _interopRequireDefault(_path);
var _fs = require("fs");
var _fs2 = _interopRequireDefault(_fs);
var _cosmiconfig = require("cosmiconfig");
var _cosmiconfig2 = _interopRequireDefault(_cosmiconfig);
var _resolveFrom = require("resolve-from");
var _resolveFrom2 = _interopRequireDefault(_resolveFrom);
var _lodash = require("lodash");
var _utils = require("./utils");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var IGNORE_FILENAME = ".stylelintignore";
var FILE_NOT_FOUND_ERROR_CODE = "ENOENT";
/**
* - Accept a raw config or look up `.stylelintrc` (using cosmiconfig).
* - Add patterns from `.stylelintignore` to the config's `ignoreFiles`.
* - Resolve plugin names to absolute paths.
* - Resolve extends by finding, augmenting, and merging
* extended configs
*
* @param {object} options - May either be an options object with a `config` property,
* or just the config object itself. All the `options` properties documented below
* are for the options object, not a config.
* @param {object} [options.config]
* @param {object} [options.configFile] - Specify a configuration file (path) instead
* @param {object} [options.configBasedir] - Specify a base directory that things should be
* considered relative to.
* @param {object} [options.configOverrides] - An object to merge on top of the
* final derived configuration object
* @param {object} [options.ignorePath] - Specify a file of ignore patterns.
* The path can be absolute or relative to `process.cwd()`.
* Defaults to `${configDir}/.stylelintignore`.
* @return {object} Object with `config` and `configDir` properties.
*/
/**
* Given a configuration object, return a new augmented version with
* - Plugins resolved to absolute paths
* - Extended configs merged in
*
* @param {object} config
* @param {string} configDir
* @param {object} [options]
* @param {boolean} [options.addIgnorePatterns=false] - Look for `.stylelintignore` and
* add its patterns to `config.ignoreFiles`.
* @param {string} [options.ignorePath] - See above.
* @return {object}
*/
function augmentConfig(config, configDir) {
var options = arguments.length <= 2 || arguments[2] === undefined ? {} : arguments[2];
var start = options.addIgnorePatterns ? addIgnoreFiles(config, configDir, options.ignorePath) : Promise.resolve(config);
return start.then(function (configWithIgnorePatterns) {
var absolutizedConfig = absolutizePlugins(configWithIgnorePatterns, configDir);
if (absolutizedConfig.extends) {
return extendConfig(absolutizedConfig, configDir);
}
return Promise.resolve(absolutizedConfig);
});
}
function addIgnoreFiles(config, configDir, ignorePath) {
return findIgnorePatterns(configDir, ignorePath).then(function (ignorePatterns) {
config.ignoreFiles = [].concat(ignorePatterns, config.ignoreFiles || []);
return config;
});
}
function findIgnorePatterns(configDir, ignorePath) {
var defaultedIgnorePath = _path2.default.resolve(configDir, IGNORE_FILENAME);
if (ignorePath) {
defaultedIgnorePath = _path2.default.isAbsolute(ignorePath) ? ignorePath : _path2.default.resolve(process.cwd(), ignorePath);
}
return new Promise(function (resolve, reject) {
_fs2.default.readFile(defaultedIgnorePath, "utf8", function (err, data) {
if (err) {
// If the file's not found, great, we'll just give an empty array
if (err.code === FILE_NOT_FOUND_ERROR_CODE) {
return resolve([]);
}
return reject(err);
}
var ignorePatterns = data.split(/\r?\n/g).filter(function (val) {
return val.trim() !== "";
}) // Remove empty lines
.filter(function (val) {
return val.trim()[0] !== "#";
}); // Remove comments
resolve(ignorePatterns);
});
});
}
// Replace all plugin lookups with absolute paths
function absolutizePlugins(config, configDir) {
if (!config.plugins) {
return config;
}
return (0, _lodash.assign)({}, config, {
plugins: config.plugins.map(function (lookup) {
return getModulePath(configDir, lookup);
})
});
}
function extendConfig(config, configDir) {
var extendLookups = [].concat(config.extends);
var origConfig = (0, _lodash.omit)(config, "extends");
var resultPromise = extendLookups.reduce(function (mergeConfigs, extendLookup) {
return mergeConfigs.then(function (mergedConfig) {
return loadExtendedConfig(mergedConfig, configDir, extendLookup).then(function (extendedConfig) {
return (0, _lodash.merge)({}, mergedConfig, extendedConfig);
});
});
}, Promise.resolve(origConfig));
return resultPromise.then(function (mergedConfig) {
return (0, _lodash.merge)({}, mergedConfig, origConfig);
});
}
function loadExtendedConfig(config, configDir, extendLookup) {
var extendPath = getModulePath(configDir, extendLookup);
var extendDir = _path2.default.dirname(extendPath);
return (0, _cosmiconfig2.default)(null, {
configPath: extendPath,
// In case `--config` was used: do not pay attention to it again
argv: false
}).then(function (result) {
// Make sure to also augment the config that we're merging in
// ... but the `ignoreFiles` option only works with the
// config that is being directly invoked, not any
// extended configs
return augmentConfig(stripIgnoreFiles(result.config), extendDir);
});
}
function getModulePath(basedir, lookup) {
var path = (0, _resolveFrom2.default)(basedir, lookup);
if (path) return path;
throw (0, _utils.configurationError)("Could not find \"" + lookup + "\". Do you need a `configBasedir`?");
}
function stripIgnoreFiles(config) {
return (0, _lodash.omit)(config, "ignoreFiles");
}