From fc97414273b8819e867ac06109ff8b913e8b519a Mon Sep 17 00:00:00 2001 From: Landon Abney Date: Wed, 29 Jul 2015 00:07:17 -0700 Subject: [PATCH 1/3] Add a JSON formatter Add a JSON formatter option, allowing easier use in tools that have native modes of parsing this output. --- src/formatters/json.js | 33 +++++++++++++++++++++++++++++++++ tests/formatters/json.js | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+) create mode 100644 src/formatters/json.js create mode 100644 tests/formatters/json.js diff --git a/src/formatters/json.js b/src/formatters/json.js new file mode 100644 index 00000000..58bdd392 --- /dev/null +++ b/src/formatters/json.js @@ -0,0 +1,33 @@ +CSSLint.addFormatter({ + //format information + id: "json", + name: "JSON", + + /** + * Return content to be printed before all file results. + * @return {String} to prepend before all results + */ + startFormat: function() { + "use strict"; + return ""; + }, + + /** + * Return content to be printed after all file results. + * @return {String} to append after all results + */ + endFormat: function() { + "use strict"; + return ""; + }, + + /** + * Given CSS Lint results for a file, return output for this format. + * @param results {Object} with error and warning messages + * @return {String} output for results + */ + formatResults: function(results, filename, options) { + "use strict"; + return options.quiet ? "" : JSON.stringify(results); + } +}); \ No newline at end of file diff --git a/tests/formatters/json.js b/tests/formatters/json.js new file mode 100644 index 00000000..23938a8f --- /dev/null +++ b/tests/formatters/json.js @@ -0,0 +1,33 @@ +(function(){ + "use strict"; + var Assert = YUITest.Assert; + + YUITest.TestRunner.add(new YUITest.TestCase({ + + name: "JSON formatter", + + "File with no problems should say so": function() { + var result = { messages: [], stats: [] }, + actual = CSSLint.getFormatter("json").formatResults(result, "path/to/FILE", {fullPath: "/absolute/path/to/FILE"}); + Assert.areEqual("{\"messages\":[],\"stats\":[]}", actual); + }, + + "Should have no output when quiet option is specified and no errors": function() { + var result = { messages: [], stats: [] }, + actual = CSSLint.getFormatter("json").formatResults(result, "path/to/FILE", {fullPath: "/absolute/path/to/FILE", quiet: "true"}); + Assert.areEqual("", actual); + }, + + "File with problems should list them": function() { + var result = { messages: [ + { type: "warning", line: 1, col: 1, message: "BOGUS", evidence: "ALSO BOGUS", rule: [] }, + { type: "error", line: 2, col: 1, message: "BOGUS", evidence: "ALSO BOGUS", rule: [] } + ], stats: [] }, + expected = "{\"messages\":[{\"type\":\"warning\",\"line\":1,\"col\":1,\"message\":\"BOGUS\",\"evidence\":\"ALSO BOGUS\",\"rule\":[]},{\"type\":\"error\",\"line\":2,\"col\":1,\"message\":\"BOGUS\",\"evidence\":\"ALSO BOGUS\",\"rule\":[]}],\"stats\":[]}", + actual = CSSLint.getFormatter("json").formatResults(result, "path/to/FILE", {fullPath: "/absolute/path/to/FILE"}); + Assert.areEqual(expected, actual); + } + + })); + +})(); From 2ef32ffc12352807a6cfb08b75b64aa6578f6ed3 Mon Sep 17 00:00:00 2001 From: Landon Abney Date: Mon, 15 Feb 2016 13:29:06 -0800 Subject: [PATCH 2/3] Output errors even with --quiet Output results even if options.quiet is true. Adds a test to verify that this is working properly. --- src/formatters/json.js | 7 +++++-- tests/formatters/json.js | 10 ++++++++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/formatters/json.js b/src/formatters/json.js index 58bdd392..9ac7a8d3 100644 --- a/src/formatters/json.js +++ b/src/formatters/json.js @@ -1,3 +1,5 @@ +/* globals JSON: true */ + CSSLint.addFormatter({ //format information id: "json", @@ -24,10 +26,11 @@ CSSLint.addFormatter({ /** * Given CSS Lint results for a file, return output for this format. * @param results {Object} with error and warning messages + * @param filename {String} relative file path (Unused) * @return {String} output for results */ formatResults: function(results, filename, options) { "use strict"; - return options.quiet ? "" : JSON.stringify(results); + return options.quiet && results.messages.length < 1 ? "" : JSON.stringify(results); } -}); \ No newline at end of file +}); diff --git a/tests/formatters/json.js b/tests/formatters/json.js index 23938a8f..97022347 100644 --- a/tests/formatters/json.js +++ b/tests/formatters/json.js @@ -18,6 +18,16 @@ Assert.areEqual("", actual); }, + "Should have output when quiet option is specified and there are errors": function() { + var result = { messages: [ + { type: "warning", line: 1, col: 1, message: "BOGUS", evidence: "ALSO BOGUS", rule: [] }, + { type: "error", line: 2, col: 1, message: "BOGUS", evidence: "ALSO BOGUS", rule: [] } + ], stats: [] }, + expected = "{\"messages\":[{\"type\":\"warning\",\"line\":1,\"col\":1,\"message\":\"BOGUS\",\"evidence\":\"ALSO BOGUS\",\"rule\":[]},{\"type\":\"error\",\"line\":2,\"col\":1,\"message\":\"BOGUS\",\"evidence\":\"ALSO BOGUS\",\"rule\":[]}],\"stats\":[]}", + actual = CSSLint.getFormatter("json").formatResults(result, "path/to/FILE", {fullPath: "/absolute/path/to/FILE", quiet: "true"}); + Assert.areEqual(expected, actual); + }, + "File with problems should list them": function() { var result = { messages: [ { type: "warning", line: 1, col: 1, message: "BOGUS", evidence: "ALSO BOGUS", rule: [] }, From 828bbd5a7d00fde257c12669d46729ac5c69a232 Mon Sep 17 00:00:00 2001 From: Landon Abney Date: Mon, 29 Feb 2016 23:20:17 -0800 Subject: [PATCH 3/3] Handle multiple files Results from multiple files should be handled in a single JSON object instead of output as multiple objects. --- src/formatters/json.js | 20 +++++++++++++-- tests/formatters/json.js | 55 ++++++++++++++++++++++++++++++---------- 2 files changed, 60 insertions(+), 15 deletions(-) diff --git a/src/formatters/json.js b/src/formatters/json.js index 9ac7a8d3..72d926b2 100644 --- a/src/formatters/json.js +++ b/src/formatters/json.js @@ -11,6 +11,7 @@ CSSLint.addFormatter({ */ startFormat: function() { "use strict"; + this.json = []; return ""; }, @@ -20,7 +21,15 @@ CSSLint.addFormatter({ */ endFormat: function() { "use strict"; - return ""; + var ret = ""; + if (this.json.length > 0) { + if (this.json.length === 1) { + ret = JSON.stringify(this.json[0]); + } else { + ret = JSON.stringify(this.json); + } + } + return ret; }, /** @@ -31,6 +40,13 @@ CSSLint.addFormatter({ */ formatResults: function(results, filename, options) { "use strict"; - return options.quiet && results.messages.length < 1 ? "" : JSON.stringify(results); + if (results.messages.length > 0 || !options.quiet) { + this.json.push({ + filename: filename, + messages: results.messages, + stats: results.stats + }); + } + return ""; } }); diff --git a/tests/formatters/json.js b/tests/formatters/json.js index 97022347..21561902 100644 --- a/tests/formatters/json.js +++ b/tests/formatters/json.js @@ -7,24 +7,35 @@ name: "JSON formatter", "File with no problems should say so": function() { - var result = { messages: [], stats: [] }, - actual = CSSLint.getFormatter("json").formatResults(result, "path/to/FILE", {fullPath: "/absolute/path/to/FILE"}); - Assert.areEqual("{\"messages\":[],\"stats\":[]}", actual); + var result = { messages: [], stats: [] }; + var expected = "{\"filename\":\"path/to/FILE\",\"messages\":[],\"stats\":[]}"; + var formatter = CSSLint.getFormatter("json"); + var actual = formatter.startFormat() + + formatter.formatResults(result, "path/to/FILE", + {fullPath: "/absolute/path/to/FILE"}) + + formatter.endFormat(); + Assert.areEqual(expected, actual); }, "Should have no output when quiet option is specified and no errors": function() { - var result = { messages: [], stats: [] }, - actual = CSSLint.getFormatter("json").formatResults(result, "path/to/FILE", {fullPath: "/absolute/path/to/FILE", quiet: "true"}); + var result = { messages: [], stats: [] }; + var formatter = CSSLint.getFormatter("json"); + var actual = formatter.startFormat() + + formatter.formatResults(result, "path/to/FILE", + {fullPath: "/absolute/path/to/FILE", quiet: "true"}) + + formatter.endFormat(); Assert.areEqual("", actual); }, "Should have output when quiet option is specified and there are errors": function() { var result = { messages: [ - { type: "warning", line: 1, col: 1, message: "BOGUS", evidence: "ALSO BOGUS", rule: [] }, - { type: "error", line: 2, col: 1, message: "BOGUS", evidence: "ALSO BOGUS", rule: [] } - ], stats: [] }, - expected = "{\"messages\":[{\"type\":\"warning\",\"line\":1,\"col\":1,\"message\":\"BOGUS\",\"evidence\":\"ALSO BOGUS\",\"rule\":[]},{\"type\":\"error\",\"line\":2,\"col\":1,\"message\":\"BOGUS\",\"evidence\":\"ALSO BOGUS\",\"rule\":[]}],\"stats\":[]}", - actual = CSSLint.getFormatter("json").formatResults(result, "path/to/FILE", {fullPath: "/absolute/path/to/FILE", quiet: "true"}); + { type: "warning", line: 1, col: 1, message: "BOGUS", evidence: "ALSO BOGUS", rule: [] }], stats: [] }; + var expected = "{\"filename\":\"path/to/FILE\",\"messages\":[{\"type\":\"warning\",\"line\":1,\"col\":1,\"message\":\"BOGUS\",\"evidence\":\"ALSO BOGUS\",\"rule\":[]}],\"stats\":[]}"; + var formatter = CSSLint.getFormatter("json"); + var actual = formatter.startFormat() + + formatter.formatResults(result, "path/to/FILE", + {fullPath: "/absolute/path/to/FILE", quiet: "true"}) + + formatter.endFormat(); Assert.areEqual(expected, actual); }, @@ -32,9 +43,27 @@ var result = { messages: [ { type: "warning", line: 1, col: 1, message: "BOGUS", evidence: "ALSO BOGUS", rule: [] }, { type: "error", line: 2, col: 1, message: "BOGUS", evidence: "ALSO BOGUS", rule: [] } - ], stats: [] }, - expected = "{\"messages\":[{\"type\":\"warning\",\"line\":1,\"col\":1,\"message\":\"BOGUS\",\"evidence\":\"ALSO BOGUS\",\"rule\":[]},{\"type\":\"error\",\"line\":2,\"col\":1,\"message\":\"BOGUS\",\"evidence\":\"ALSO BOGUS\",\"rule\":[]}],\"stats\":[]}", - actual = CSSLint.getFormatter("json").formatResults(result, "path/to/FILE", {fullPath: "/absolute/path/to/FILE"}); + ], stats: [] }; + var expected = "{\"filename\":\"path/to/FILE\",\"messages\":[{\"type\":\"warning\",\"line\":1,\"col\":1,\"message\":\"BOGUS\",\"evidence\":\"ALSO BOGUS\",\"rule\":[]},{\"type\":\"error\",\"line\":2,\"col\":1,\"message\":\"BOGUS\",\"evidence\":\"ALSO BOGUS\",\"rule\":[]}],\"stats\":[]}"; + var formatter = CSSLint.getFormatter("json"); + var actual = formatter.startFormat() + + formatter.formatResults(result, "path/to/FILE", + {fullPath: "/absolute/path/to/FILE"}) + + formatter.endFormat(); + Assert.areEqual(expected, actual); + }, + + "Multiple files are handled properly": function () { + var result = { messages: [ + { type: "warning", line: 1, col: 1, message: "BOGUS", evidence: "ALSO BOGUS", rule: [] }], stats: [] }; + var expected = "[{\"filename\":\"path/to/FILE\",\"messages\":[{\"type\":\"warning\",\"line\":1,\"col\":1,\"message\":\"BOGUS\",\"evidence\":\"ALSO BOGUS\",\"rule\":[]}],\"stats\":[]},{\"filename\":\"path/to/FILE\",\"messages\":[{\"type\":\"warning\",\"line\":1,\"col\":1,\"message\":\"BOGUS\",\"evidence\":\"ALSO BOGUS\",\"rule\":[]}],\"stats\":[]}]"; + var formatter = CSSLint.getFormatter("json"); + var actual = formatter.startFormat() + + formatter.formatResults(result, "path/to/FILE", + {fullPath: "/absolute/path/to/FILE"}) + + formatter.formatResults(result, "path/to/FILE", + {fullPath: "/absolute/path/to/FILE"}) + + formatter.endFormat(); Assert.areEqual(expected, actual); }