Comparing version 2.3.0 to 2.4.0
{ | ||
"name": "jshint", | ||
"version": "2.3.0", | ||
"version": "2.4.0", | ||
"homepage": "http://jshint.com/", | ||
@@ -36,6 +36,7 @@ "description": "Static analysis tool for JavaScript", | ||
"dependencies": { | ||
"shelljs": "0.1.x", | ||
"underscore": "1.4.x", | ||
"cli": "0.4.x", | ||
"minimatch": "0.x.x", | ||
"shelljs": "0.1.x", | ||
"underscore": "1.4.x", | ||
"cli": "0.4.x", | ||
"minimatch": "0.x.x", | ||
"htmlparser2": "3.3.x", | ||
"console-browserify": "0.1.x" | ||
@@ -45,5 +46,5 @@ }, | ||
"devDependencies": { | ||
"jshint": "2.3.x", | ||
"jshint": "2.4.x", | ||
"shelljs": "0.1.x", | ||
"browserify": "2.12.x", | ||
"browserify": "3.x", | ||
"coveraje": "0.2.x", | ||
@@ -50,0 +51,0 @@ "nodeunit": "0.8.x", |
103
src/cli.js
"use strict"; | ||
var _ = require("underscore"); | ||
var cli = require("cli"); | ||
@@ -7,2 +8,3 @@ var path = require("path"); | ||
var minimatch = require("minimatch"); | ||
var htmlparser = require("htmlparser2"); | ||
var JSHINT = require("./jshint.js").JSHINT; | ||
@@ -16,2 +18,3 @@ var defReporter = require("./reporters/default").reporter; | ||
"Exclude files matching the given filename pattern (same as .jshintignore)", "string", null], | ||
"exclude-path": ["exclude-path", "Pass in a custom jshintignore file path", "string", null], | ||
"verbose": ["verbose", "Show message codes"], | ||
@@ -22,2 +25,9 @@ "show-non-errors": ["show-non-errors", "Show additional data generated by jshint"], | ||
"extract": [ | ||
"extract", | ||
"Extract inline scripts contained in HTML (auto|always|never, default to never)", | ||
"string", | ||
"never" | ||
], | ||
// Deprecated options. | ||
@@ -114,3 +124,7 @@ "jslint-reporter": [ | ||
return require(fp).jshintConfig || null; | ||
try { | ||
return require(fp).jshintConfig; | ||
} catch (e) { | ||
return null; | ||
} | ||
} | ||
@@ -178,4 +192,4 @@ | ||
*/ | ||
function loadIgnores(exclude) { | ||
var file = findFile(".jshintignore"); | ||
function loadIgnores(exclude, excludePath) { | ||
var file = findFile(excludePath || ".jshintignore"); | ||
@@ -227,2 +241,58 @@ if (!file && !exclude) { | ||
/** | ||
* Extract JS code from a given source code. The source code my be either HTML | ||
* code or JS code. In the latter case, no extraction will be done unless | ||
* 'always' is given. | ||
* | ||
* @param {string} code a piece of code | ||
* @param {string} when 'always' will extract the JS code, no matter what. | ||
* 'never' won't do anything. 'auto' will check if the code looks like HTML | ||
* before extracting it. | ||
* | ||
* @return {string} the extracted code | ||
*/ | ||
function extract(code, when) { | ||
// A JS file won't start with a less-than character, whereas a HTML file | ||
// should always start with that. | ||
if (when !== "always" && (when !== "auto" || !/^\s*</.test(code))) | ||
return code; | ||
var inscript = false; | ||
var index = 0; | ||
var js = []; | ||
// Test if current tag is a valid <script> tag. | ||
function onopen(name, attrs) { | ||
if (name !== "script") | ||
return; | ||
if (attrs.type && !/text\/javascript/.test(attrs.type.toLowerCase())) | ||
return; | ||
// Mark that we're inside a <script> a tag and push all new lines | ||
// in between the last </script> tag and this <script> tag to preserve | ||
// location information. | ||
inscript = true; | ||
js.push.apply(js, code.slice(index, parser.endIndex).match(/\n\r|\n|\r/g)); | ||
} | ||
function onclose(name) { | ||
if (name !== "script" || !inscript) | ||
return; | ||
inscript = false; | ||
index = parser.startIndex; | ||
} | ||
function ontext(data) { | ||
if (inscript) | ||
js.push(data); // Collect JavaScript code. | ||
} | ||
var parser = new htmlparser.Parser({ onopentag: onopen, onclosetag: onclose, ontext: ontext }); | ||
parser.parseComplete(code); | ||
return js.join(""); | ||
} | ||
/** | ||
* Recursively gather all files that need to be linted, | ||
@@ -313,2 +383,4 @@ * excluding those that user asked to ignore. | ||
var exports = { | ||
extract: extract, | ||
/** | ||
@@ -333,2 +405,8 @@ * Loads and parses a configuration file. | ||
config.dirname = path.dirname(fp); | ||
if (config['extends']) { | ||
_.extend(config, exports.loadConfig(path.resolve(config.dirname, config['extends']))); | ||
delete config['extends']; | ||
} | ||
return config; | ||
@@ -390,3 +468,3 @@ } catch (err) { | ||
cli.withStdin(function (code) { | ||
lint(code, results, opts.config || {}, data); | ||
lint(extract(code, opts.extract), results, opts.config || {}, data); | ||
(opts.reporter || defReporter)(results, data, { verbose: opts.verbose }); | ||
@@ -410,3 +488,3 @@ cb(results.length === 0); | ||
lint(code, results, config, data, file); | ||
lint(extract(code, opts.extract), results, config, data, file); | ||
}); | ||
@@ -418,3 +496,3 @@ | ||
/** | ||
/** | ||
* Helper exposed for testing. | ||
@@ -506,9 +584,10 @@ * Used to determine is stdout has any buffered output before exiting the program | ||
done(exports.run({ | ||
args: cli.args, | ||
config: config, | ||
reporter: reporter, | ||
ignores: loadIgnores(options.exclude), | ||
args: cli.args, | ||
config: config, | ||
reporter: reporter, | ||
ignores: loadIgnores(options.exclude, options["exclude-path"]), | ||
extensions: options["extra-ext"], | ||
verbose: options.verbose, | ||
useStdin: {"-": true, "/dev/stdin": true}[args[args.length - 1]] | ||
verbose: options.verbose, | ||
extract: options.extract, | ||
useStdin: {"-": true, "/dev/stdin": true}[args[args.length - 1]] | ||
}, done)); | ||
@@ -515,0 +594,0 @@ } |
@@ -962,18 +962,18 @@ /* | ||
case "b": | ||
char = "\b"; | ||
char = "\\b"; | ||
break; | ||
case "f": | ||
char = "\f"; | ||
char = "\\f"; | ||
break; | ||
case "n": | ||
char = "\n"; | ||
char = "\\n"; | ||
break; | ||
case "r": | ||
char = "\r"; | ||
char = "\\r"; | ||
break; | ||
case "t": | ||
char = "\t"; | ||
char = "\\t"; | ||
break; | ||
case "0": | ||
char = "\0"; | ||
char = "\\0"; | ||
@@ -1018,3 +1018,7 @@ // Octal literals fail in strict mode. | ||
case "\\": | ||
char = "\\\\"; | ||
break; | ||
case "\"": | ||
char = "\\\""; | ||
break; | ||
case "/": | ||
@@ -1319,12 +1323,13 @@ break; | ||
var startsWith = function (prefix) { | ||
return this.indexOf(prefix) === 0; | ||
}; | ||
var endsWith = function (suffix) { | ||
return this.indexOf(suffix, this.length - suffix.length) !== -1; | ||
}; | ||
var inputTrimmed = this.input.trim(); | ||
// If we are ignoring linter errors, replace the input with empty string | ||
// if it doesn't already at least start or end a multi-line comment | ||
if (state.ignoreLinterErrors === true) { | ||
var startsWith = function (prefix) { | ||
return this.indexOf(prefix) === 0; | ||
}; | ||
var endsWith = function (suffix) { | ||
return this.indexOf(suffix, this.length - suffix.length) !== -1; | ||
}; | ||
var inputTrimmed = this.input.trim(); | ||
if (! (startsWith.call(inputTrimmed, "/*") || endsWith.call(inputTrimmed, "*/"))) { | ||
@@ -1351,3 +1356,11 @@ this.input = ""; | ||
if (state.option.maxlen && state.option.maxlen < this.input.length) { | ||
this.trigger("warning", { code: "W101", line: this.line, character: this.input.length }); | ||
var inComment = state.tokens.curr.comment || | ||
startsWith.call(inputTrimmed, "//") || | ||
startsWith.call(inputTrimmed, "/*"); | ||
var shouldTriggerError = !inComment || !reg.maxlenException.test(inputTrimmed); | ||
if (shouldTriggerError) { | ||
this.trigger("warning", { code: "W101", line: this.line, character: this.input.length }); | ||
} | ||
} | ||
@@ -1354,0 +1367,0 @@ |
@@ -43,3 +43,3 @@ "use strict"; | ||
E026: "Missing '}' to match '{' from line {a}.", | ||
E027: "Missing ']' to match '[' form line {a}.", | ||
E027: "Missing ']' to match '[' from line {a}.", | ||
E028: "Illegal comma.", | ||
@@ -56,4 +56,4 @@ E029: "Unclosed string.", | ||
E036: "Expected to see a statement and instead saw a block.", | ||
E037: null, // Vacant | ||
E038: null, // Vacant | ||
E037: null, | ||
E038: null, | ||
E039: "Function declarations are not invocable. Wrap the whole function invocation in parens.", | ||
@@ -64,3 +64,3 @@ E040: "Each value should have its own case label.", | ||
E043: "Too many errors.", | ||
E044: "'{a}' is already defined and can't be redefined.", | ||
E044: null, | ||
E045: "Invalid for each loop.", | ||
@@ -131,3 +131,3 @@ E046: "A yield statement shall be within a generator function (with syntax: `function*`)", | ||
W056: "Bad constructor.", | ||
W057: "Weird construction. Is 'new' unnecessary?", | ||
W057: "Weird construction. Is 'new' necessary?", | ||
W058: "Missing '()' invoking a constructor.", | ||
@@ -201,3 +201,4 @@ W059: "Avoid arguments.{a}.", | ||
W121: "Extending prototype of native object: '{a}'.", | ||
W122: "Invalid typeof value '{a}'" | ||
W122: "Invalid typeof value '{a}'", | ||
W123: "'{a}' is already defined in outer scope." | ||
}; | ||
@@ -204,0 +205,0 @@ |
@@ -35,1 +35,5 @@ /* | ||
exports.fallsThrough = /^\s*\/\*\s*falls?\sthrough\s*\*\/\s*$/; | ||
// very conservative rule (eg: only one space between the start of the comment and the first character) | ||
// to relax the maxlen option | ||
exports.maxlenException = /^(?:(?:\/\/|\/\*|\*) ?)?[^ ]+$/; |
@@ -55,2 +55,5 @@ // jshint -W001 | ||
btoa : false, | ||
CanvasGradient : false, | ||
CanvasPattern : false, | ||
CanvasRenderingContext2D: false, | ||
clearInterval : false, | ||
@@ -378,16 +381,20 @@ clearTimeout : false, | ||
__dirname : false, | ||
Buffer : false, | ||
console : false, | ||
exports : true, // In Node it is ok to exports = module.exports = foo(); | ||
GLOBAL : false, | ||
global : false, | ||
module : false, | ||
process : false, | ||
require : false, | ||
setTimeout : false, | ||
clearTimeout : false, | ||
setInterval : false, | ||
clearInterval : false, | ||
setImmediate : false, // v0.9.1+ | ||
clearImmediate: false // v0.9.1+ | ||
// These globals are writeable because Node allows the following | ||
// usage pattern: var Buffer = require("buffer").Buffer; | ||
Buffer : true, | ||
console : true, | ||
exports : true, | ||
process : true, | ||
setTimeout : true, | ||
clearTimeout : true, | ||
setInterval : true, | ||
clearInterval : true, | ||
setImmediate : true, // v0.9.1+ | ||
clearImmediate: true // v0.9.1+ | ||
}; | ||
@@ -394,0 +401,0 @@ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
617174
57587
6
+ Addedhtmlparser2@3.3.x
+ Addedcore-util-is@1.0.3(transitive)
+ Addeddomelementtype@1.3.1(transitive)
+ Addeddomhandler@2.1.0(transitive)
+ Addeddomutils@1.1.6(transitive)
+ Addedhtmlparser2@3.3.0(transitive)
+ Addedinherits@2.0.4(transitive)
+ Addedisarray@0.0.1(transitive)
+ Addedreadable-stream@1.0.34(transitive)
+ Addedstring_decoder@0.10.31(transitive)