forked from webpack-contrib/jshint-loader
-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.js
154 lines (135 loc) · 3.53 KB
/
index.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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
var jshint = require("jshint").JSHINT;
var RcLoader = require("rcloader");
var stripJsonComments = require("strip-json-comments");
var loaderUtils = require("loader-utils");
var fs = require("fs");
// setup RcLoader
var rcLoader = new RcLoader(".jshintrc", null, {
loader: function(path) {
return path;
}
});
function loadRcConfig(callback){
var sync = typeof callback !== "function";
if(sync){
var path = rcLoader.for(this.resourcePath);
if(typeof path !== "string") {
// no .jshintrc found
return {};
} else {
this.addDependency(path);
var file = fs.readFileSync(path, "utf8");
return JSON.parse(stripJsonComments(file));
}
}
else {
rcLoader.for(this.resourcePath, function(err, path) {
if(typeof path !== "string") {
// no .jshintrc found
return callback(null, {});
}
this.addDependency(path);
fs.readFile(path, "utf8", function(err, file) {
var options;
if(!err) {
try {
options = JSON.parse(stripJsonComments(file));
}
catch(e) {
err = new Error("Can't parse config file: " + path);
}
}
callback(err, options);
});
}.bind(this));
}
}
function jsHint(input, options) {
// copy options to own object
if(this.options.jshint) {
for(var name in this.options.jshint) {
options[name] = this.options.jshint[name];
}
}
// copy query into options
var query = loaderUtils.parseQuery(this.query);
for(var name in query) {
options[name] = query[name];
}
// copy globals from options
var globals = {};
if(options.globals) {
if(Array.isArray(options.globals)) {
options.globals.forEach(function(g) {
globals[g] = true;
}, this);
} else {
for(var g in options.globals)
globals[g] = options.globals[g];
}
delete options.globals;
}
// move flags
var emitErrors = options.emitErrors;
delete options.emitErrors;
var failOnHint = options.failOnHint;
delete options.failOnHint;
// custom reporter
var reporter = options.reporter;
delete options.reporter;
// module system globals
globals.require = true;
globals.module = true;
globals.exports = true;
globals.global = true;
globals.process = true;
globals.define = true;
var source = input.split(/\r\n?|\n/g);
var result = jshint(source, options, globals);
var errors = jshint.errors;
if(!result) {
if(reporter) {
reporter.call(this, errors);
} else {
var hints = [];
if(errors) errors.forEach(function(error) {
if(!error) return;
var message = " " + error.reason + " @ line " + error.line + " char " + error.character + "\n " + error.evidence;
hints.push(message);
}, this);
var message = hints.join("\n\n");
var emitter = emitErrors ? this.emitError : this.emitWarning;
if(emitter)
emitter("jshint results in errors\n" + message);
else
throw new Error("Your module system doesn't support emitWarning. Update availible? \n" + message);
}
}
if(failOnHint && !result)
throw new Error("Module failed in cause of jshint error.");
}
module.exports = function(input, map) {
this.cacheable && this.cacheable();
var callback = this.async();
if(!callback) {
// load .jshintrc synchronously
var config = loadRcConfig.call(this);
jsHint.call(this, input, config);
return input;
}
// load .jshintrc asynchronously
loadRcConfig.call(this, function(err, config) {
if(err) return callback(err);
try {
jsHint.call(this, input, config);
}
catch(e) {
return callback(e);
}
callback(null, input, map);
}.bind(this));
}