gulp-eslint
Advanced tools
Comparing version 1.1.0-rc-2 to 1.1.0-rc-3
170
index.js
@@ -10,5 +10,5 @@ 'use strict'; | ||
/** | ||
* Append eslint result to each file | ||
* Append ESLint result to each file | ||
* | ||
* @param {(Object|String)} [options] - Configure rules, env, global, and other options for running eslint | ||
* @param {(Object|String)} [options] - Configure rules, env, global, and other options for running ESLint | ||
* @returns {stream} gulp file stream | ||
@@ -27,3 +27,3 @@ */ | ||
// ignore warnings | ||
result = util.getQuietResult(result, options.quiet); | ||
result = util.filterResult(result, options.quiet); | ||
} | ||
@@ -42,12 +42,11 @@ | ||
} else if (linter.isPathIgnored(filePath)) { | ||
// Note: | ||
// Vinyl files can have an independently defined cwd, but eslint works relative to `process.cwd()`. | ||
// Vinyl files can have an independently defined cwd, but ESLint works relative to `process.cwd()`. | ||
// (https://github.com/gulpjs/gulp/blob/master/docs/recipes/specifying-a-cwd.md) | ||
// Also, eslint doesn't adjust file paths relative to an ancestory .eslintignore path. | ||
// E.g., If ../.eslintignore has "foo/*.js", eslint will ignore ./foo/*.js, instead of ../foo/*.js. | ||
// Also, ESLint doesn't adjust file paths relative to an ancestory .eslintignore path. | ||
// E.g., If ../.eslintignore has "foo/*.js", ESLint will ignore ./foo/*.js, instead of ../foo/*.js. | ||
// Eslint rolls this into `CLIEngine.executeOnText`. So, gulp-eslint must account for this limitation. | ||
if (linter.options.ignore && options.warnFileIgnored) { | ||
// Warn that gulp.src is needlessly reading files that eslint ignores | ||
// Warn that gulp.src is needlessly reading files that ESLint ignores | ||
file.eslint = util.createIgnoreResult(file); | ||
@@ -58,3 +57,3 @@ } | ||
} else if (file.isStream()) { | ||
// eslint is synchronous, so wait for the complete contents | ||
// ESLint is synchronous, so wait for the complete contents | ||
// replace content stream with new readable content stream | ||
@@ -66,2 +65,3 @@ file.contents = file.contents.pipe(new BufferStreams(function(err, buf, done) { | ||
buf = new Buffer(file.eslint.output); | ||
file.eslint.fixed = true; | ||
} | ||
@@ -77,2 +77,3 @@ done(null, buf); | ||
file.contents = new Buffer(file.eslint.output); | ||
file.eslint.fixed = true; | ||
} | ||
@@ -85,27 +86,47 @@ cb(null, file); | ||
/** | ||
* Fail when an eslint error is found in eslint results. | ||
* Handle each ESLint result as it passes through the stream. | ||
* | ||
* @param {Function} action - A function to handle each ESLint result | ||
* @returns {stream} gulp file stream | ||
*/ | ||
gulpEslint.failOnError = function() { | ||
return util.transform(function(file, enc, output) { | ||
var messages = file.eslint && file.eslint.messages || [], | ||
error = null; | ||
gulpEslint.result = function(action) { | ||
if (typeof action !== 'function') { | ||
throw new Error('Expected callable argument'); | ||
} | ||
messages.some(function(message) { | ||
if (util.isErrorMessage(message)) { | ||
error = new PluginError( | ||
'gulp-eslint', | ||
{ | ||
name: 'ESLintError', | ||
fileName: file.path, | ||
message: message.message, | ||
lineNumber: message.line | ||
} | ||
); | ||
return true; | ||
} | ||
}); | ||
return util.transform(function(file, enc, done) { | ||
if (file.eslint) { | ||
util.tryResultAction(action, file.eslint, util.handleCallback(done, file)); | ||
} else { | ||
done(null, file); | ||
} | ||
}); | ||
}; | ||
return output(error, file); | ||
/** | ||
* Handle all ESLint results at the end of the stream. | ||
* | ||
* @param {Function} action - A function to handle all ESLint results | ||
* @returns {stream} gulp file stream | ||
*/ | ||
gulpEslint.results = function(action) { | ||
if (typeof action !== 'function') { | ||
throw new Error('Expected callable argument'); | ||
} | ||
var results = []; | ||
results.errorCount = 0; | ||
results.warningCount = 0; | ||
return util.transform(function(file, enc, done) { | ||
if (file.eslint) { | ||
results.push(file.eslint); | ||
// collect total error/warning count | ||
results.errorCount += file.eslint.errorCount; | ||
results.warningCount += file.eslint.warningCount; | ||
} | ||
done(null, file); | ||
}, function(done) { | ||
util.tryResultAction(action, results, util.handleCallback(done)); | ||
}); | ||
@@ -115,28 +136,40 @@ }; | ||
/** | ||
* Fail when the stream ends if any eslint error(s) occurred | ||
* Fail when an ESLint error is found in ESLint results. | ||
* | ||
* @returns {stream} gulp file stream | ||
*/ | ||
gulpEslint.failOnError = function() { | ||
return gulpEslint.result(function(result) { | ||
var error = util.firstResultMessage(result, util.isErrorMessage); | ||
if (error) { | ||
throw new PluginError( | ||
'gulp-eslint', | ||
{ | ||
name: 'ESLintError', | ||
fileName: result.filePath, | ||
message: error.message, | ||
lineNumber: error.line | ||
} | ||
); | ||
} | ||
}); | ||
}; | ||
/** | ||
* Fail when the stream ends if any ESLint error(s) occurred | ||
* | ||
* @returns {stream} gulp file stream | ||
*/ | ||
gulpEslint.failAfterError = function() { | ||
var errorCount = 0; | ||
return util.transform(function(file, enc, cb) { | ||
var messages = file.eslint && file.eslint.messages || []; | ||
messages.forEach(function(message) { | ||
if (util.isErrorMessage(message)) { | ||
errorCount++; | ||
} | ||
}); | ||
cb(null, file); | ||
}, function(cb) { | ||
// Only format results if files has been lint'd | ||
if (errorCount > 0) { | ||
this.emit('error', new PluginError( | ||
return gulpEslint.results(function(results) { | ||
var count = results.errorCount; | ||
if (count > 0) { | ||
throw new PluginError( | ||
'gulp-eslint', | ||
{ | ||
name: 'ESLintError', | ||
message: 'Failed with ' + errorCount + (errorCount === 1 ? ' error' : ' errors') | ||
message: 'Failed with ' + count + (count === 1 ? ' error' : ' errors') | ||
} | ||
)); | ||
); | ||
} | ||
cb(); | ||
}); | ||
@@ -146,26 +179,14 @@ }; | ||
/** | ||
* Wait until all files have been linted and format all results at once. | ||
* Format the results of each file individually. | ||
* | ||
* @param {(String|Function)} [formatter=stylish] - The name or function for a eslint result formatter | ||
* @param {(Function|stream)} [writable=gulp-util.log] - A funtion or stream to write the formatted eslint results. | ||
* @param {(String|Function)} [formatter=stylish] - The name or function for a ESLint result formatter | ||
* @param {(Function|Stream)} [writable=gulp-util.log] - A funtion or stream to write the formatted ESLint results. | ||
* @returns {stream} gulp file stream | ||
*/ | ||
gulpEslint.format = function(formatter, writable) { | ||
var results = []; | ||
gulpEslint.formatEach = function(formatter, writable) { | ||
formatter = util.resolveFormatter(formatter); | ||
writable = util.resolveWritable(writable); | ||
return util.transform(function(file, enc, cb) { | ||
if (file.eslint) { | ||
results.push(file.eslint); | ||
} | ||
cb(null, file); | ||
}, function(cb) { | ||
// Only format results if files has been lint'd | ||
if (results.length) { | ||
util.writeResults(results, formatter, writable); | ||
} | ||
// reset buffered results | ||
results = []; | ||
cb(); | ||
return gulpEslint.result(function(result) { | ||
util.writeResults([result], formatter, writable); | ||
}); | ||
@@ -175,22 +196,17 @@ }; | ||
/** | ||
* Format the results of each file individually. | ||
* Wait until all files have been linted and format all results at once. | ||
* | ||
* @param {(String|Function)} [formatter=stylish] - The name or function for a eslint result formatter | ||
* @param {(Function|Stream)} [writable=gulp-util.log] - A funtion or stream to write the formatted eslint results. | ||
* @param {(String|Function)} [formatter=stylish] - The name or function for a ESLint result formatter | ||
* @param {(Function|stream)} [writable=gulp-util.log] - A funtion or stream to write the formatted ESLint results. | ||
* @returns {stream} gulp file stream | ||
*/ | ||
gulpEslint.formatEach = function(formatter, writable) { | ||
gulpEslint.format = function(formatter, writable) { | ||
formatter = util.resolveFormatter(formatter); | ||
writable = util.resolveWritable(writable); | ||
return util.transform(function(file, enc, cb) { | ||
var error = null; | ||
if (file.eslint) { | ||
try { | ||
util.writeResults([file.eslint], formatter, writable); | ||
} catch (err) { | ||
error = new PluginError('gulp-eslint', err); | ||
} | ||
return gulpEslint.results(function(results) { | ||
// Only format results if files has been lint'd | ||
if (results.length) { | ||
util.writeResults(results, formatter, writable); | ||
} | ||
cb(error, file); | ||
}); | ||
@@ -197,0 +213,0 @@ }; |
{ | ||
"name": "gulp-eslint", | ||
"version": "1.1.0-rc-2", | ||
"description": "A gulp plugin for processing files with eslint", | ||
"version": "1.1.0-rc-3", | ||
"description": "A gulp plugin for processing files with ESLint", | ||
"repository": "adametry/gulp-eslint", | ||
@@ -18,3 +18,3 @@ "files": [ | ||
"gulp": "gulp", | ||
"gulp-example": "gulp --gulpfile=example/gulpfile.js", | ||
"gulp-example": "gulp --gulpfile=example/config.js", | ||
"coverage": "istanbul cover _mocha", | ||
@@ -21,0 +21,0 @@ "coveralls": "${npm_package_scripts_coverage} && istanbul-coveralls" |
@@ -21,3 +21,3 @@ # gulp-eslint [![Build Status](https://travis-ci.org/adametry/gulp-eslint.svg)](https://travis-ci.org/adametry/gulp-eslint) [![Coverage Status](https://img.shields.io/coveralls/adametry/gulp-eslint.svg)](https://coveralls.io/r/adametry/gulp-eslint) | ||
return gulp.src(['js/**/*.js']) | ||
// eslint() attaches the lint output to the eslint property | ||
// eslint() attaches the lint output to the "eslint" property | ||
// of the file object so it can be used by other modules. | ||
@@ -43,2 +43,9 @@ .pipe(eslint()) | ||
.pipe(eslint({ | ||
// "expree" is installed with ESLint. | ||
// Any other parser will need to be installed. | ||
parser: 'espree', | ||
extends: 'eslint:recommended', | ||
ecmaFeatures: { | ||
'modules': true | ||
}, | ||
rulePaths: [ | ||
@@ -168,3 +175,3 @@ 'custom-rules/' | ||
```javascript | ||
// Cause the stream to stop(/fail) when the stream ends if any eslint error(s) occurred. | ||
// Cause the stream to stop(/fail) when the stream ends if any ESLint error(s) occurred. | ||
gulp.src('**/*.js') | ||
@@ -178,3 +185,3 @@ .pipe(eslint()) | ||
Format all linted files once. This should be used in the stream after piping through `eslint`; otherwise, this will find no eslint results to format. | ||
Format all linted files once. This should be used in the stream after piping through `eslint`; otherwise, this will find no ESLint results to format. | ||
@@ -184,6 +191,6 @@ The `formatter` argument may be a `String`, `Function`, or `undefined`. As a `String`, a formatter module by that name or path will be resolved as a module, relative to `process.cwd()`, or as one of the [ESLint-provided formatters](https://github.com/eslint/eslint/tree/master/lib/formatters). If `undefined`, the ESLint “stylish” formatter will be resolved. A `Function` will be called with an `Array` of file linting results to format. | ||
```javascript | ||
// use the default "stylish" eslint formatter | ||
// use the default "stylish" ESLint formatter | ||
eslint.format() | ||
// use the "checkstyle" eslint formatter | ||
// use the "checkstyle" ESLint formatter | ||
eslint.format('checkstyle') | ||
@@ -190,0 +197,0 @@ |
122
util.js
@@ -28,6 +28,6 @@ 'use strict'; | ||
* Mimic the CLIEngine's createIgnoreResult function, | ||
* only without the eslint CLI reference. | ||
* only without the ESLint CLI reference. | ||
* | ||
* @param {Object} file - file with a "path" property | ||
* @returns {Object} An eslint report with an ignore warning | ||
* @returns {Object} An ESLint report with an ignore warning | ||
*/ | ||
@@ -107,5 +107,72 @@ exports.createIgnoreResult = function(file) { | ||
/** | ||
* Resolve writable | ||
* Ensure that callback errors are wrapped in a gulp PluginError | ||
* | ||
* @param {Object} message - an eslint message | ||
* @param {Function} callback - callback to wrap | ||
* @param {Object} [value=] - A value to pass to the callback | ||
* @returns {Function} A callback to call(back) the callback | ||
*/ | ||
exports.handleCallback = function(callback, value) { | ||
return function(err) { | ||
if (err != null && !(err instanceof gutil.PluginError)) { | ||
err = new gutil.PluginError(err.plugin || 'gulp-eslint', err, { | ||
showStack: (err.showStack !== false) | ||
}); | ||
} | ||
callback(err, value); | ||
}; | ||
}; | ||
/** | ||
* Call sync or async action and handle any thrown or async error | ||
* | ||
* @param {Function} action - Result action to call | ||
* @param {(Object|Array)} result - An ESLint result or result list | ||
* @param {Function} done - An callback for when the action is complete | ||
*/ | ||
exports.tryResultAction = function(action, result, done) { | ||
try { | ||
if (action.length > 1) { | ||
// async action | ||
action.call(this, result, done); | ||
} else { | ||
// sync action | ||
action.call(this, result); | ||
done(); | ||
} | ||
} catch (error) { | ||
done(error == null ? new Error('Unknown Error') : error); | ||
} | ||
}; | ||
/** | ||
* Get the first item in a list that meets a condition | ||
* | ||
* @param {Array} list - A list to search | ||
* @param {Function} condition - A condition function that is passed an item and returns a boolean | ||
* @returns {(Object|Null)} The first item to meet a condition or null, if no item meets the condition | ||
*/ | ||
function first(list, condition) { | ||
for (var i = 0, len = list && list.length || 0; i < len; i++) { | ||
if (condition(list[i])) { | ||
return list[i]; | ||
} | ||
} | ||
return null; | ||
} | ||
/** | ||
* Get first message in an ESLint result to meet a condition | ||
* | ||
* @param {Object} result - An ESLint result | ||
* @param {Function} condition - A condition function that is passed a message and returns a boolean | ||
* @returns {Object} The first message to pass the condition or null | ||
*/ | ||
exports.firstResultMessage = function(result, condition) { | ||
return first(result.messages, condition); | ||
}; | ||
/** | ||
* Determine if a message is an error | ||
* | ||
* @param {Object} message - an ESLint message | ||
* @returns {Boolean} whether the message is an error message | ||
@@ -122,18 +189,41 @@ */ | ||
function reduceErrorCount(count, message) { | ||
/** | ||
* Increment count if message is an error | ||
* | ||
* @param {Number} count - count of errors | ||
* @param {Object} message - an ESLint message | ||
* @returns {Number} The number of errors, message included | ||
*/ | ||
function countErrorMessage(count, message) { | ||
return count + isErrorMessage(message); | ||
} | ||
function reduceWarningCount(count, message) { | ||
/** | ||
* Increment count if message is a warning | ||
* | ||
* @param {Number} count - count of warnings | ||
* @param {Object} message - an ESLint message | ||
* @returns {Number} The number of warnings, message included | ||
*/ | ||
function countWarningMessage(count, message) { | ||
return count + (message.severity === 1); | ||
} | ||
exports.getQuietResult = function(result, filter) { | ||
/** | ||
* Filter result messages, update error and warning counts | ||
* | ||
* @param {Object} result - an ESLint result | ||
* @param {Function} [filter=isErrorMessage] - A function that evaluates what messages to keep | ||
* @returns {Object} A filtered ESLint result | ||
*/ | ||
exports.filterResult = function(result, filter) { | ||
if (typeof filter !== 'function') { | ||
filter = isErrorMessage; | ||
} | ||
var messages = result.messages.filter(filter); | ||
var messages = result.messages.filter(filter, result); | ||
return { | ||
filePath: result.filePath, | ||
messages: messages, | ||
errorCount: messages.reduce(reduceErrorCount, 0), | ||
warningCount: messages.reduce(reduceWarningCount, 0) | ||
errorCount: messages.reduce(countErrorMessage, 0), | ||
warningCount: messages.reduce(countWarningMessage, 0) | ||
}; | ||
@@ -147,8 +237,8 @@ }; | ||
* @param {(String|Function)} [formatter=stylish] - A name to resolve as a formatter. If a function is provided, the same function is returned. | ||
* @returns {Function} An eslint formatter | ||
* @returns {Function} An ESLint formatter | ||
*/ | ||
exports.resolveFormatter = function(formatter) { | ||
// use eslint to look up formatter references | ||
// use ESLint to look up formatter references | ||
if (typeof formatter !== 'function') { | ||
// load formatter (module, relative to cwd, eslint formatter) | ||
// load formatter (module, relative to cwd, ESLint formatter) | ||
formatter = CLIEngine.getFormatter(formatter) || formatter; | ||
@@ -183,5 +273,5 @@ } | ||
* | ||
* @param {Object[]} results - A list of eslint results | ||
* @param {Function} formatter - A function used to format eslint results | ||
* @param {Function} writable - A function used to write formatted eslint results | ||
* @param {Object[]} results - A list of ESLint results | ||
* @param {Function} formatter - A function used to format ESLint results | ||
* @param {Function} writable - A function used to write formatted ESLint results | ||
*/ | ||
@@ -188,0 +278,0 @@ exports.writeResults = function(results, formatter, writable) { |
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
26846
444
228