UNPKG

3.47 kBJavaScriptView Raw
1const Future = require('fluture');
2const merge = require('deepmerge');
3const clone = require('lodash.clonedeep');
4const { CLIEngine } = require('eslint');
5const { assoc, curry, evolve, keys, omit, pipe, prop, reduce } = require('ramda');
6const { basename, join } = require('path');
7
8const MODULES = join(__dirname, 'node_modules');
9const getEslintOptions = config => config.module.rule('lint').use('eslint').get('options');
10const renameKeys = curry((definition, obj) =>
11 reduce((acc, key) => assoc(definition[key] || key, obj[key], acc), {}, keys(obj)));
12const reduceToTrueKeys = reduce((acc, key) => assoc(key, true, acc), {});
13const getEslintRcConfig = pipe(
14 getEslintOptions,
15 clone,
16 assoc('useEslintrc', true),
17 omit(['failOnError', 'emitWarning', 'emitError']),
18 renameKeys({ envs: 'env', baseConfig: 'extends' }),
19 evolve({
20 extends: prop('extends'),
21 globals: reduceToTrueKeys,
22 env: reduceToTrueKeys
23 })
24);
25
26module.exports = (neutrino, opts = {}) => {
27 const isNotDev = process.env.NODE_ENV !== 'development';
28 const options = merge.all([
29 opts,
30 !opts.include && !opts.exclude ? { include: [neutrino.options.source], exclude: [neutrino.options.static] } : {}
31 ]);
32
33 neutrino.config
34 .resolve
35 .modules
36 .add(MODULES)
37 .end()
38 .end()
39 .resolveLoader
40 .modules
41 .add(MODULES)
42 .end()
43 .end()
44 .module
45 .rule('lint')
46 .test(options.test || /\.(js|jsx)$/)
47 .pre()
48 .when(options.include, rule => rule.include.merge(options.include))
49 .when(options.exclude, rule => rule.exclude.merge(options.exclude))
50 .use('eslint')
51 .loader(require.resolve('eslint-loader'))
52 .options(merge({
53 failOnError: isNotDev,
54 emitWarning: isNotDev,
55 emitError: isNotDev,
56 cwd: neutrino.options.root,
57 useEslintrc: false,
58 root: true,
59 plugins: ['babel'],
60 baseConfig: {},
61 envs: ['es6'],
62 parser: 'babel-eslint',
63 parserOptions: {
64 ecmaVersion: 2017,
65 sourceType: 'module',
66 ecmaFeatures: {
67 objectLiteralDuplicateProperties: false,
68 generators: true,
69 impliedStrict: true
70 }
71 },
72 settings: {},
73 globals: ['process'],
74 rules: {}
75 }, options.eslint || {}));
76
77 neutrino.register('eslintrc', () => getEslintRcConfig(neutrino.config));
78 neutrino.register('lint', () => {
79 const { fix = false } = neutrino.options.args;
80 const ignorePattern = (options.exclude || [])
81 .map(exclude => join(
82 basename(neutrino.options.source),
83 basename(exclude),
84 '**/*'
85 ));
86 const eslintConfig = merge(getEslintOptions(neutrino.config), { ignorePattern, fix });
87
88 return Future
89 .of(eslintConfig)
90 .map(options => new CLIEngine(options))
91 .chain(cli => Future.both(Future.of(cli.executeOnFiles(options.include)), Future.of(cli.getFormatter())))
92 .map(([report, formatter]) => {
93 fix && CLIEngine.outputFixes(report);
94 return [report, formatter];
95 })
96 .chain(([report, formatter]) => {
97 const errors = CLIEngine.getErrorResults(report.results);
98 const formatted = formatter(report.results);
99
100 return errors.length ? Future.reject(formatted) : Future.of(formatted);
101 });
102 });
103};