kitchensink
Version:
Dispatch's awesome components and style guide
217 lines (182 loc) • 6.02 kB
JavaScript
/**
* Command line config helpers
*/
var fs = require('fs');
var path = require('path');
var stripJSONComments = require('strip-json-comments');
var yaml = require('js-yaml');
var parseJson = require('jsonlint').parse;
var supportsColor = require('chalk').supportsColor;
var glob = require('glob');
var resolve = require('resolve');
var stripBOM = require('strip-bom');
// Configuration sources in priority order.
var configs = ['package.json', '.jscsrc', '.jscs.json', '.jscs.yaml'];
// Before, "findup-sync" package was used,
// but it does not provide filter callback
function findup(patterns, options, fn) {
/* jshint -W083 */
var lastpath;
var file;
options = Object.create(options);
options.maxDepth = 1;
options.cwd = path.resolve(options.cwd);
do {
file = patterns.filter(function(pattern) {
var configPath = glob.sync(pattern, options)[0];
if (configPath) {
return fn(path.join(options.cwd, configPath));
}
})[0];
if (file) {
return path.join(options.cwd, file);
}
lastpath = options.cwd;
options.cwd = path.resolve(options.cwd, '..');
} while (options.cwd !== lastpath);
}
/**
* Get content of the configuration file.
*
* @param {String} config - partial path to configuration file
* @param {String} directory - directory path which will be joined with config argument
* @return {Object}
*/
exports.getContent = function(config, directory) {
if (!config) {
return;
}
if (!directory) {
directory = process.cwd();
}
var configPath = path.resolve(directory, config);
var ext;
var data;
var content;
var requireConfigPath;
if (fs.existsSync(configPath)) {
config = path.basename(config);
ext = path.extname(configPath);
if (ext === '.js') {
content = require(configPath);
} else {
data = stripBOM(fs.readFileSync(configPath, 'utf8'));
if (ext === '.json') {
content = parseJson(stripJSONComments(data));
} else if (ext === '.yaml') {
content = yaml.safeLoad(data);
} else {
// try both JSON and YAML
try {
content = parseJson(stripJSONComments(data));
} catch (jsonError) {
try {
content = yaml.safeLoad(data);
} catch (yamlError) {
if (stripJSONComments(data).trim()[0] === '{') {
// the intention was probably JSON
throw jsonError;
} else {
// assume the intention was YAML
throw yamlError;
}
}
}
}
}
} else {
// Try to load it as a node module
try {
requireConfigPath = resolve.sync(config, { basedir: directory });
content = require(requireConfigPath);
} catch (e) {}
}
if (content) {
// Adding property via Object.defineProperty makes it
// non-enumerable and avoids warning for unsupported rules
Object.defineProperty(content, 'configPath', {
value: requireConfigPath || configPath
});
}
return content && config === 'package.json' ? content.jscsConfig : content;
};
/**
* Get content of the configuration file.
*
* @param {String} config - partial path to configuration file
* @param {String} [cwd = process.cwd()] - directory path which will be joined with config argument
* @return {Object|undefined}
*/
exports.load = function(config, cwd) {
var content;
var directory = cwd || process.cwd();
// If config option is given, attempt to load it
if (config) {
return this.getContent(config, directory);
}
content = this.getContent(
findup(configs, { nocase: true, cwd: directory }, function(configPath) {
if (path.basename(configPath) === 'package.json') {
return !!this.getContent(configPath);
}
return true;
}.bind(this))
);
if (content) {
return content;
}
// Try to load standard configs from home dir
var directoryArr = [process.env.USERPROFILE, process.env.HOMEPATH, process.env.HOME];
for (var i = 0, dirLen = directoryArr.length; i < dirLen; i++) {
if (!directoryArr[i]) {
continue;
}
for (var j = 0, len = configs.length; j < len; j++) {
content = this.getContent(configs[j], directoryArr[i]);
if (content) {
return content;
}
}
}
};
/**
* Get reporter function and path to it.
*
* @param {String} reporter - path or the name of one of the pre-defined reporters
* @param {Boolean} [colors = true] - should it be a colorful output?
* @return {{writer: Function, path: String}}
*/
exports.getReporter = function(reporter, colors) {
var writerPath;
var writer;
if (colors !== false) {
colors = true;
}
if (reporter) {
// ensure reporter is a string (and allow non-string types to be coerced)
reporter = reporter.toString();
writerPath = path.resolve(process.cwd(), reporter);
if (!fs.existsSync(writerPath)) {
writerPath = path.resolve(__dirname, './reporters/' + reporter);
}
} else {
writerPath = path.resolve(
__dirname, './reporters/', (colors && supportsColor ? 'console' : 'text')
);
}
try {
writer = require(writerPath);
} catch (e) {
writer = null;
}
if (!writer) {
try {
writer = require(reporter);
writerPath = reporter;
} catch (e) {}
}
return {
path: writerPath,
writer: writer
};
};