From 9a9c5ad9675b3fd2a376f5f2907ebdd5f53d2154 Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Thu, 10 Sep 2015 22:10:13 +0200 Subject: [PATCH] Add ability to provide custom logger By default, use process.stdout.write to print the report Fixes #35 Closes #34 --- .gitignore | 1 + README.md | 50 +++++++++++++++++++++ index.js | 18 +++++--- test/expected/checkstyle-xml.xml | 2 +- test/main.js | 76 +++++++++++++++++++++++++------- 5 files changed, 124 insertions(+), 23 deletions(-) diff --git a/.gitignore b/.gitignore index e22121a..fc848a8 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ *.iml coverage/ +test-output.xml diff --git a/README.md b/README.md index b30251d..6bf5448 100644 --- a/README.md +++ b/README.md @@ -102,6 +102,56 @@ gulp.task('lint', function() { }); ``` +### Reporter options +You can also pass options to the built-in formatter, by passing a second option to `reporter`. + +```js +gulp.task('lint', function() { + gulp.files('lib/*.css') + .pipe(csslint()) + .pipe(csslint.reporter('junit-xml', options)); +}); +``` + +See the documentation for the formatters regarding what options they support. + +This plugin supports one option outside of that, called `logger`, allowing you to specify how to log out the report. +Default is using `process.stdout.write`, but you can use e.g. `console.log`, or `gutil.log`. + +```js +gulp.task('lint', function() { + gulp.files('lib/*.css') + .pipe(csslint()) + .pipe(csslint.reporter('junit-xml', {logger: console.log.bind(console)})); +}); +``` + +```js +gulp.task('lint', function() { + gulp.files('lib/*.css') + .pipe(csslint()) + .pipe(csslint.reporter('junit-xml', {logger: gutil.log.bind(null, 'gulp-csslint:')})); +}); +``` + +`logger` is called once for the starting format of the reporter, then once for each file containing violations, then +lastly once for the ending format. Instead of writing to `stdout`, you can write to file using this option. + +```js +gulp.task('lint', function(cb) { + var fs = require('fs'); + var output = ''; + + gulp.files('lib/*.css') + .pipe(csslint()) + .pipe(csslint.reporter('junit-xml', {logger: function(str) { output += str; }})); + + fs.writeFile('some/path/junit.xml', output, cb); +}); +``` + +This functionality is only available when not using custom reporters. + ## Custom rules Use the `csslint.addRule(rule)` method to define custom rules that run in addition to the rules defined in the csslintrc file. See [Working with Rules](https://github.com/CSSLint/csslint/wiki/Working-with-Rules) for details. diff --git a/index.js b/index.js index 44bbda7..eee348a 100644 --- a/index.js +++ b/index.js @@ -71,11 +71,15 @@ var cssLintPlugin = function(options) { }); }; -cssLintPlugin.reporter = function(customReporter) { +cssLintPlugin.reporter = function(customReporter, options) { var reporter = csslint.getFormatter('text'); var builtInReporter = true; var output; + options = options || {}; + + var logger = options.logger || process.stdout.write.bind(process.stdout); + if (typeof customReporter === 'function') { reporter = customReporter; builtInReporter = false; @@ -101,7 +105,7 @@ cssLintPlugin.reporter = function(customReporter) { // Only report if CSSLint was ran and errors were found if (file.csslint && !file.csslint.success) { if (builtInReporter) { - output.push(reporter.formatResults(file.csslint.originalReport, file.path)); + output.push(reporter.formatResults(file.csslint.originalReport, file.path, options)); } else { reporter(file); @@ -111,14 +115,14 @@ cssLintPlugin.reporter = function(customReporter) { return cb(null, file); }, function(cb) { - var report; - if (builtInReporter) { output.push(reporter.endFormat()); - report = output.join(''); - // Only print report if the report is not empty - report && gutil.log(report); + output + .filter(function(str) { + return str; + }) + .forEach(logger); } return cb(); diff --git a/test/expected/checkstyle-xml.xml b/test/expected/checkstyle-xml.xml index c16efb9..aab44f1 100644 --- a/test/expected/checkstyle-xml.xml +++ b/test/expected/checkstyle-xml.xml @@ -1 +1 @@ - \ No newline at end of file + diff --git a/test/main.js b/test/main.js index 5414491..e006985 100644 --- a/test/main.js +++ b/test/main.js @@ -19,7 +19,7 @@ var getFile = function(filePath) { var getContents = function(filePath) { filePath = 'test/' + filePath; - return fs.readFileSync(filePath, 'utf8'); + return fs.readFileSync(filePath, 'utf8').trim(); }; describe('gulp-csslint', function() { @@ -276,16 +276,15 @@ describe('gulp-csslint', function() { }); describe('cssLintPlugin.reporter()', function() { - it('should support built-in CSSLint formatters', sinon.test(function(done) { + it('should support built-in CSSLint formatters', function(done) { var a = 0; var file = getFile('fixtures/usingImportant.css'); var expected = getContents('expected/checkstyle-xml.xml'); + var callback = sinon.spy(); var lintStream = cssLintPlugin(); - var reporterStream = cssLintPlugin.reporter('checkstyle-xml'); - - sinon.stub(gutil, 'log'); + var reporterStream = cssLintPlugin.reporter('checkstyle-xml', {logger: callback}); reporterStream.on('data', function() { ++a; @@ -299,27 +298,75 @@ describe('gulp-csslint', function() { reporterStream.once('end', function() { a.should.equal(1); - sinon.assert.calledOnce(gutil.log); - sinon.assert.calledWith(gutil.log, expected); + sinon.assert.calledThrice(callback); + callback.firstCall.args[0].should.equal(''); + callback.secondCall.args[0].should.equal(expected); + callback.thirdCall.args[0].should.equal(''); - gutil.log.restore(); done(); }); lintStream.write(file); lintStream.end(); - })); + }); - it('should not print empty output by built-in CSSLint formatters', sinon.test(function(done) { + it('should write report to disk', function(done) { var a = 0; + var output = ''; - var file = getFile('fixtures/validCSS.css'); + var file = getFile('fixtures/usingImportant.css'); + var expected = getContents('expected/checkstyle-xml.xml'); var lintStream = cssLintPlugin(); - var reporterStream = cssLintPlugin.reporter('text'); + var reporterStream = cssLintPlugin.reporter('checkstyle-xml', { + logger: function(str) { + output += str; + } + }); sinon.stub(gutil, 'log'); + reporterStream.on('data', function() { + ++a; + }); + lintStream.on('data', function(file) { + reporterStream.write(file); + }); + lintStream.once('end', function() { + reporterStream.end(); + }); + + reporterStream.once('end', function() { + fs.writeFile('test-output.xml', output, function() { + a.should.equal(1); + sinon.assert.notCalled(gutil.log); + + gutil.log.restore(); + + fs.readFile('test-output.xml', function(err, content) { + (err === null).should.be.true; + + var toString = content.toString(); + + toString.should.equal('' + expected + ''); + done(); + }); + }); + }); + + lintStream.write(file); + lintStream.end(); + }); + + it('should not print empty output by built-in CSSLint formatters', function(done) { + var a = 0; + + var file = getFile('fixtures/validCSS.css'); + var callback = sinon.spy(); + + var lintStream = cssLintPlugin(); + var reporterStream = cssLintPlugin.reporter('text', {logger: callback}); + reporterStream.on('data', function() { ++a; }); @@ -333,15 +380,14 @@ describe('gulp-csslint', function() { }); reporterStream.once('end', function() { + sinon.assert.notCalled(callback); a.should.equal(1); - sinon.assert.callCount(gutil.log, 0); - gutil.log.restore(); done(); }); lintStream.write(file); lintStream.end(); - })); + }); }); });