diff --git a/docs/developer-guide/formatters.md b/docs/developer-guide/formatters.md index 246ddbfd45..8f64eb91fe 100644 --- a/docs/developer-guide/formatters.md +++ b/docs/developer-guide/formatters.md @@ -1,6 +1,14 @@ # Writing formatters -A formatter is a function that accepts *an array of these stylelint result objects* and outputs a string: +A formatter is a function with the following signature: + +```js +function formatter(results, returnValue) { + return "a string of formatted results"; +} +``` + +Where the first argument (`results`) is an array of stylelint result objects in the form: ```js // A stylelint result object @@ -32,6 +40,40 @@ A formatter is a function that accepts *an array of these stylelint result objec } ``` +And the second argument (`returnValue`) is an object with one or more of the following keys: + +```js +{ + errored: false, // `true` if there were any warnings with "error" severity + needlessDisables: [ // Present if stylelint was configured with `reportNeedlessDisables: true` + { + source: "path/to/file.css", + ranges: [ + { + start: 10, + unusedRule: "indentation" + } + ] + } + ], + invalidScopeDisables: [ // Present if stylelint was configured with `reportInvalidScopeDisables: true` + { + source: "path/to/file.css", + ranges: [ + { + start: 1, + unusedRule: "color-named" + } + ] + } + ], + maxWarningsExceeded: { // Present if stylelint was configured with a `maxWarnings` count + maxWarnings: 10, + foundWarnings: 15 + } +} +``` + ## `stylelint.formatters` stylelint's internal formatters are exposed publicly in `stylelint.formatters`. diff --git a/lib/__tests__/standalone-formatter.test.js b/lib/__tests__/standalone-formatter.test.js index d5c64fa03e..87dd0b8a81 100644 --- a/lib/__tests__/standalone-formatter.test.js +++ b/lib/__tests__/standalone-formatter.test.js @@ -50,3 +50,53 @@ it('standalone with invalid formatter option', () => { ); }); }); + +it('standalone formatter receives {needlessDisables} as second argument', () => { + const formatter = jest.fn((results, { needlessDisables }) => { + return JSON.stringify({ results, needlessDisables }, null, 2); + }); + + return standalone({ + code: ` + /* stylelint-disable yo */ + a {} + `, + config: configBlockNoEmpty, + reportNeedlessDisables: true, + formatter, + }).then((linted) => { + const { output, results, needlessDisables } = linted; + + expect(needlessDisables).not.toBeUndefined(); + expect(needlessDisables).toHaveLength(1); + + expect(typeof output).toBe('string'); + expect(formatter).toHaveBeenCalledTimes(1); + expect(output).toBe(JSON.stringify({ results, needlessDisables }, null, 2)); + }); +}); + +it('standalone formatter receives {invalidScopeDisables} as second argument', () => { + const formatter = jest.fn((results, { invalidScopeDisables }) => { + return JSON.stringify({ results, invalidScopeDisables }, null, 2); + }); + + return standalone({ + code: ` + /* stylelint-disable indentation */ + a { color: red; } + `, + config: configBlockNoEmpty, + reportInvalidScopeDisables: true, + formatter, + }).then((linted) => { + const { output, results, invalidScopeDisables } = linted; + + expect(invalidScopeDisables).not.toBeUndefined(); + expect(invalidScopeDisables).toHaveLength(1); + + expect(typeof output).toBe('string'); + expect(formatter).toHaveBeenCalledTimes(1); + expect(output).toBe(JSON.stringify({ results, invalidScopeDisables }, null, 2)); + }); +}); diff --git a/lib/standalone.js b/lib/standalone.js index 3b4b0a977c..bb0e10c478 100644 --- a/lib/standalone.js +++ b/lib/standalone.js @@ -293,11 +293,12 @@ module.exports = function( const errored = stylelintResults.some( (result) => result.errored || result.parseErrors.length > 0, ); + /** @type {StylelintStandaloneReturnValue} */ const returnValue /*: stylelint$standaloneReturnValue*/ = { errored, - output: formatterFunction(stylelintResults), - results: stylelintResults, + results: [], + output: '', }; if (reportNeedlessDisables) { @@ -322,6 +323,9 @@ module.exports = function( } } + returnValue.output = formatterFunction(stylelintResults, returnValue); + returnValue.results = stylelintResults; + debug(`Linting complete in ${Date.now() - startTime}ms`); return returnValue;