putout
Version:
the pluggable code transformer
127 lines (97 loc) • 2.85 kB
JavaScript
'use strict';
const {homedir} = require('os');
const {readdirSync} = require('fs');
const {
dirname,
join,
} = require('path');
const once = require('once');
const tryCatch = require('try-catch');
const escalade = require('escalade/sync');
const parseMatch = require('./parse-match');
const defaultOptions = require('../../putout.json');
const merge = require('../merge');
const recursiveRead = require('./recursive-read');
const home = homedir();
module.exports = (info = {}) => {
const {
rulesdir,
name = '',
options = {},
readOptions = _readOptions,
readHomeOptions = _readHomeOptions,
readCodeMods = _readCodeMods,
} = info;
const [dir, customOptions] = readOptions(name);
const homeOptions = readHomeOptions();
const defaultMatch = parseMatch(name, defaultOptions.match);
const optionsList = [
defaultOptions,
homeOptions,
defaultMatch,
customOptions,
options,
];
const mergedOptions = merge(...optionsList);
const mergedDefaultsMatch = merge(
mergedOptions,
parseMatch(name, mergedOptions.match),
options,
);
const mergedMatch = merge(customOptions, options, parseMatch(name, options.match));
const resultOptions = merge(
readCodeMods(),
readRules(dir, rulesdir),
mergedOptions,
mergedDefaultsMatch,
mergedMatch,
);
return {
...resultOptions,
dir,
};
};
const includes = (name) => (dir, names) => names.includes(name) && name;
function _readOptions(name) {
const [dir, options] = recursiveRead(name, '.putout.json');
if (dir)
return [dir, options];
const [, packagePath] = tryCatch(escalade, name, includes('package.json'));
if (packagePath)
return [
dirname(packagePath),
require(packagePath).putout || {},
{},
];
return [
'',
{},
];
}
const isInclude = (a) => a !== 'node_modules';
function readRules(dirOpt, rulesDir) {
if (!rulesDir)
return {};
const dir = join(dirOpt, rulesDir);
const [e, names] = tryCatch(readdirSync, dir);
if (e)
return {};
const plugins = [];
for (const name of names.filter(isInclude)) {
const full = join(dir, name);
const plugin = require(full);
const shortName = name.replace('putout-plugin-');
plugins.push([shortName, plugin]);
}
return {
plugins,
};
}
const _readHomeOptions = once(() => {
const name = join(home, '.putout.json');
const [, data = {}] = tryCatch(require, name);
return data;
});
const _readCodeMods = once(() => {
return readRules(home, '.putout');
});