UNPKG

4.17 kBJavaScriptView Raw
1module.exports.lintText = lintText
2module.exports.lintFiles = lintFiles
3
4var dezalgo = require('dezalgo')
5var eslint = require('eslint')
6var findRoot = require('find-root')
7var fs = require('fs')
8var glob = require('glob')
9var parallel = require('run-parallel')
10var path = require('path')
11var uniq = require('uniq')
12
13var DEFAULT_PATTERNS = [
14 '**/*.js',
15 '**/*.jsx'
16]
17
18var DEFAULT_IGNORE_PATTERNS = [
19 'coverage/**',
20 'node_modules/**',
21 '**/*.min.js',
22 '**/bundle.js'
23]
24
25var ESLINT_CONFIG = {
26 baseConfig: require(path.join(__dirname, 'rc', '.eslintrc.json')),
27 useEslintrc: true
28}
29
30/**
31 * Lint text to enforce JavaScript Standard Style.
32 *
33 * @param {string} text file text to lint
34 * @param {Object} opts options object
35 * @param {Array.<String>} opts.ignore file globs to ignore (has sane defaults)
36 * @param {string} opts.cwd current working directory (default: process.cwd())
37 * @param {function(Error, Object)} cb callback
38 */
39function lintText (text, opts, cb) {
40 if (typeof opts === 'function') {
41 cb = opts
42 opts = {}
43 }
44 opts = parseOpts(opts)
45 cb = dezalgo(cb)
46
47 var result
48 try {
49 result = new eslint.CLIEngine(ESLINT_CONFIG).executeOnText(text)
50 } catch (err) {
51 return cb(err)
52 }
53 return cb(null, result)
54}
55
56/**
57 * Lint files to enforce JavaScript Standard Style.
58 *
59 * @param {Array.<string>} files file globs to lint
60 * @param {Object} opts options object
61 * @param {Array.<String>} opts.ignore file globs to ignore (has sane defaults)
62 * @param {string} opts.cwd current working directory (default: process.cwd())
63 * @param {function(Error, Object)} cb callback
64 */
65function lintFiles (files, opts, cb) {
66 if (typeof opts === 'function') {
67 cb = opts
68 opts = {}
69 }
70 opts = parseOpts(opts)
71 cb = dezalgo(cb)
72
73 if (typeof files === 'string') files = [ files ]
74 if (files.length === 0) files = DEFAULT_PATTERNS
75
76 // traverse filesystem
77 parallel(files.map(function (pattern) {
78 return function (cb) {
79 glob(pattern, {
80 cwd: opts.cwd,
81 ignore: opts.ignore,
82 nodir: true
83 }, cb)
84 }
85 }), function (err, results) {
86 if (err) return cb(err)
87
88 // flatten nested arrays
89 var files = results.reduce(function (files, result) {
90 result.forEach(function (file) {
91 files.push(path.join(opts.cwd, file))
92 })
93 return files
94 }, [])
95
96 // de-dupe
97 files = uniq(files)
98
99 // ignore files in .gitignore
100 if (opts.ignoreMatcher) {
101 files = files.filter(function (file) {
102 return !opts.ignoreMatcher.shouldIgnore(file)
103 })
104 }
105
106 // undocumented – do not use (used by bin/cmd.js)
107 if (opts._onFiles) opts._onFiles(files)
108
109 var result
110 try {
111 result = new eslint.CLIEngine(ESLINT_CONFIG).executeOnFiles(files)
112 } catch (err) {
113 return cb(err)
114 }
115 return cb(null, result)
116 })
117}
118
119function parseOpts (opts) {
120 if (!opts) opts = {}
121
122 if (!opts.cwd) opts.cwd = process.cwd()
123
124 // Add user ignore patterns to default ignore patterns
125 var ignore = (opts.ignore || []).concat(DEFAULT_IGNORE_PATTERNS)
126
127 var root
128 try {
129 root = findRoot(opts.cwd)
130 } catch (e) {}
131
132 if (root) {
133 // Add ignore patterns from the closest `package.json`
134 try {
135 var packageOpts = require(path.join(root, 'package.json')).standard
136 if (packageOpts) ignore = ignore.concat(packageOpts.ignore)
137 } catch (e) {}
138
139 // Add ignore patterns from project root `.gitignore`
140 try {
141 var gitignore = fs.readFileSync(path.join(root, '.gitignore'), 'utf8')
142 ignore = ignore.concat(gitignore.split(/\r?\n|\r/).filter(nonEmpty))
143 } catch (e) {}
144 }
145
146 // Remove leading "current folder" prefix
147 ignore = ignore.map(function (pattern) {
148 return pattern.indexOf('./') === 0 ? pattern.slice(2) : pattern
149 })
150
151 // Allow "folder/" to ignore all sub-folders and files, a la .gitignore
152 opts.ignore = []
153 ignore.forEach(function (pattern) {
154 opts.ignore.push(pattern)
155 opts.ignore.push(pattern + '/**')
156 })
157
158 return opts
159}
160
161function nonEmpty (line) {
162 return line.trim() !== '' && line[0] !== '#'
163}