-
Notifications
You must be signed in to change notification settings - Fork 67
/
lint.js
99 lines (80 loc) · 2.77 KB
/
lint.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
var path = require('path');
var PluginError = require('plugin-error');
var RcLoader = require('rcloader');
var jshintcli = require('jshint/src/cli');
var minimatch = require('minimatch');
var assign = require('lodash/assign');
var forEach = require('lodash/forEach');
var isString = require('lodash/isString');
var isFunction = require('lodash/isFunction');
module.exports = function createLintFunction(userOpts) {
userOpts = userOpts || {};
// Default jshint
// Need to assign within the createLintFunction code,
// else repeated requires (like in tests) will
// not update the variable
var jshint = require('jshint').JSHINT;
if (userOpts.linter) {
if (isString(userOpts.linter)) {
// require throws an error if the component can't be found,
// so we're guaranteed that `require(jshint)` will not be undefined
jshint = require(userOpts.linter).JSHINT;
} else { // should be a function
jshint = userOpts.linter;
}
if (!isFunction(jshint)) {
throw new PluginError('gulp-jshint',
'Invalid linter "'+ userOpts.linter + '". Must be a function or requirable package.'
);
}
delete userOpts.linter;
}
var rcLoader = new RcLoader('.jshintrc', userOpts, {
loader: function (path) {
var cfg = jshintcli.loadConfig(path);
delete cfg.dirname;
return cfg;
}
});
var reportErrors = function (file, out, cfg) {
var filePath = file.path ? path.relative(process.cwd(), file.path): 'stdin';
out.results = jshint.errors.map(function (err) {
if (!err) return;
return { file: filePath, error: err };
}).filter(Boolean);
out.opt = cfg;
out.data = [jshint.data()];
out.data[0].file = filePath;
};
return function lint(file, cb) {
// pass through dirs, streaming files, etc.
if (!file.isBuffer()) {
return cb(null, file);
}
rcLoader.for(file.path, function (err, cfg) {
if (err) return cb(err);
var globals = {};
if (cfg.globals) {
globals = cfg.globals;
delete cfg.globals;
}
if (cfg.overrides) {
forEach(cfg.overrides, function (options, pattern) {
if (!minimatch(file.path, pattern, { nocase: true, matchBase: true })) return;
if (options.globals) {
globals = assign(globals, options.globals);
delete options.globals;
}
assign(cfg, options);
});
delete cfg.overrides;
}
// get or create file.jshint, we will write all output here
var out = file.jshint || (file.jshint = {});
var str = isString(out.extracted) ? out.extracted : file.contents.toString('utf8');
out.success = jshint(str, cfg, globals);
if (!out.success) reportErrors(file, out, cfg);
return cb(null, file);
});
};
};