diff --git a/docs/user-guide/ignore-code.md b/docs/user-guide/ignore-code.md index de8e292636..b93683b338 100644 --- a/docs/user-guide/ignore-code.md +++ b/docs/user-guide/ignore-code.md @@ -62,6 +62,16 @@ stylelint supports complex, overlapping disabling & enabling patterns: **Caveat:** Comments within _selector and value lists_ are currently ignored. +You may also include a description at the end of the comment, after two hyphens: + +```css +/* stylelint-disable -- Reason for disabling stylelint. */ +/* stylelint-disable foo -- Reason for disabling the foo rule. */ +/* stylelint-disable foo, bar -- Reason for disabling the foo and bar rules. */ +``` + +**Important:** There must be a space on both sides of the hyphens. + ## Files entirely You can use a `.stylelintignore` file to ignore specific files. For example: diff --git a/lib/__tests__/disableRanges-integration.test.js b/lib/__tests__/disableRanges-integration.test.js index 5fdf74803c..eaff2e989c 100644 --- a/lib/__tests__/disableRanges-integration.test.js +++ b/lib/__tests__/disableRanges-integration.test.js @@ -27,6 +27,22 @@ testRule({ { code: 'b { color: pink;}\n/* stylelint-disable */\na {}', }, + // Command comment descriptions. + { + code: '/* stylelint-disable -- Description */\na {}', + }, + { + code: '/* stylelint-disable-line -- Description */ a {}', + }, + { + code: 'a {} /* stylelint-disable-line -- Description */ ', + }, + { + code: '/* stylelint-disable-next-line -- Description */\na {}', + }, + { + code: 'b { color: pink;}\n/* stylelint-disable -- Description */\na {}', + }, ], reject: [ @@ -58,6 +74,23 @@ testRule({ code: 'a {}\n/* stylelint-disable-next-line */', message: blockNoEmpty.messages.rejected, }, + // Command comment descriptions. + { + code: '/* stylelint-disable--Description */\na {}', + message: blockNoEmpty.messages.rejected, + }, + { + code: '/* stylelint-disable-- Description */\na {}', + message: blockNoEmpty.messages.rejected, + }, + { + code: '/* stylelint-disable --Description */\na {}', + message: blockNoEmpty.messages.rejected, + }, + { + code: '/* stylelint-disable - - Description */\na {}', + message: blockNoEmpty.messages.rejected, + }, ], }); diff --git a/lib/__tests__/disableRanges.test.js b/lib/__tests__/disableRanges.test.js index b17618c15e..fc93c29ebb 100644 --- a/lib/__tests__/disableRanges.test.js +++ b/lib/__tests__/disableRanges.test.js @@ -644,6 +644,132 @@ it('enable rule without disabling rule', () => { }); }); +// Command comment descriptions. + +it('disable (with description) without re-enabling', () => { + return testDisableRanges('/* stylelint-disable -- Description */\na {}').then((result) => { + expect(result.stylelint.disabledRanges).toEqual({ + all: [ + { + start: 1, + strictStart: true, + }, + ], + }); + }); +}); + +it('disable and re-enable (with descriptions)', () => { + return testDisableRanges(`a {} + /* stylelint-disable -- Description */ + b {} + /* stylelint-enable -- Description */ + .foo {}`).then((result) => { + expect(result.stylelint.disabledRanges).toEqual({ + all: [ + { + start: 2, + end: 4, + strictStart: true, + strictEnd: true, + }, + ], + }); + }); +}); + +it('disable rule (with description) without re-enabling', () => { + return testDisableRanges('/* stylelint-disable foo-bar -- Description */\na {}').then( + (result) => { + expect(result.stylelint.disabledRanges).toEqual({ + all: [], + 'foo-bar': [ + { + start: 1, + strictStart: true, + end: undefined, + strictEnd: undefined, + }, + ], + }); + }, + ); +}); + +it('disable rules (with description) with newline in rule list', () => { + return testDisableRanges( + '/* stylelint-disable foo-bar, hoo-hah,\n\tslime -- Description */\n' + 'b {}\n', + ).then((result) => { + expect(result.stylelint.disabledRanges).toEqual({ + all: [], + 'foo-bar': [ + { + start: 1, + strictStart: true, + }, + ], + 'hoo-hah': [ + { + start: 1, + strictStart: true, + }, + ], + slime: [ + { + start: 1, + strictStart: true, + }, + ], + }); + }); +}); + +it('SCSS // line-disabling comment (with description)', () => { + const scssSource = `a { + color: pink !important; // stylelint-disable-line declaration-no-important -- Description + }`; + + return postcss() + .use(assignDisabledRanges) + .process(scssSource, { syntax: scss, from: undefined }) + .then((result) => { + expect(result.stylelint.disabledRanges).toEqual({ + all: [], + 'declaration-no-important': [ + { + start: 2, + end: 2, + strictStart: true, + strictEnd: true, + }, + ], + }); + }); +}); + +it('Less // line-disabling comment (with description)', () => { + const lessSource = `a { + color: pink !important; // stylelint-disable-line declaration-no-important -- Description + }`; + + return postcss() + .use(assignDisabledRanges) + .process(lessSource, { syntax: less, from: undefined }) + .then((result) => { + expect(result.stylelint.disabledRanges).toEqual({ + all: [], + 'declaration-no-important': [ + { + start: 2, + end: 2, + strictStart: true, + strictEnd: true, + }, + ], + }); + }); +}); + function testDisableRanges(source, cb) { return postcss().use(assignDisabledRanges).process(source, { from: undefined }).then(cb); } diff --git a/lib/assignDisabledRanges.js b/lib/assignDisabledRanges.js index f33611dcc6..31406d74b4 100644 --- a/lib/assignDisabledRanges.js +++ b/lib/assignDisabledRanges.js @@ -241,6 +241,8 @@ module.exports = function (root, result) { function getCommandRules(command, fullText) { const rules = fullText .slice(command.length) + .split(/\s-{2,}\s/u)[0] // Allow for description (f.e. /* stylelint-disable a, b -- Description */). + .trim() .split(',') .filter(Boolean) .map((r) => r.trim());