UNPKG

2.95 kBJavaScriptView Raw
1/*
2 * grunt
3 * https://github.com/cowboy/grunt
4 *
5 * Copyright (c) 2012 "Cowboy" Ben Alman
6 * Licensed under the MIT license.
7 * http://benalman.com/about/license/
8 */
9
10var jshint = require('jshint').JSHINT;
11
12// ============================================================================
13// TASKS
14// ============================================================================
15
16task.registerBasicTask('lint', 'Validate files with JSHint.', function(data, name) {
17 // Get flags and globals.
18 var options = config('jshint.options');
19 var globals = config('jshint.globals');
20
21 // Display flags and globals.
22 verbose.writeflags(options, 'Options');
23 verbose.writeflags(globals, 'Globals');
24
25 // Lint specified files.
26 file.expand(data).forEach(function(filepath) {
27 task.helper('lint', file.read(filepath), options, globals, filepath);
28 });
29
30 // Fail task if errors were logged.
31 if (task.hadErrors()) { return false; }
32
33 // Otherwise, print a success message.
34 log.writeln('Lint free.');
35});
36
37// ============================================================================
38// HELPERS
39// ============================================================================
40
41// Lint source code with JSHint.
42task.registerHelper('lint', function(src, options, globals, extraMsg) {
43 // JSHint sometimes modifies objects you pass in, so clone them.
44 options = underscore.clone(options);
45 globals = underscore.clone(globals);
46 // Enable/disable debugging if option explicitly set.
47 if (option('debug') !== undefined) {
48 options.devel = options.debug = option('debug');
49 }
50 var msg = 'Linting' + (extraMsg ? ' ' + extraMsg : '') + '...';
51 verbose.write(msg);
52 // Lint.
53 var result = jshint(src, options || {}, globals || {});
54 // Attempt to work around JSHint erroneously reporting bugs.
55 if (!result) {
56 jshint.errors = jshint.errors.filter(function(o) {
57 // This is not a bug: exports = module.exports = something
58 // https://github.com/jshint/jshint/issues/289
59 return o && !(o.reason === 'Read only.' && /\bexports\s*[=]/.test(o.evidence));
60 });
61 // If no errors are left, JSHint actually succeeded.
62 result = jshint.errors.length === 0;
63 }
64 if (result) {
65 // Success!
66 verbose.ok();
67 } else {
68 // Something went wrong.
69 verbose.or.write(msg);
70 log.error();
71 // Iterate over all errors.
72 jshint.errors.forEach(function(e) {
73 // Sometimes there's no error object.
74 if (!e) { return; }
75 var pos;
76 if (e.evidence) {
77 // Manually increment errorcount since we're not using log.error().
78 fail.errorcount++;
79 // Descriptive code error.
80 pos = '['.red + ('L' + e.line).yellow + ':'.red + ('C' + e.character).yellow + ']'.red;
81 log.writeln(pos + ' ' + e.reason.yellow).writeln(e.evidence.inverse);
82 } else {
83 // Generic "Whoops, too many errors" error.
84 log.error(e.reason);
85 }
86 });
87 log.writeln();
88 }
89});