diff --git a/docs/user-guide/rules.md b/docs/user-guide/rules.md index e42f695919..27c1e70088 100644 --- a/docs/user-guide/rules.md +++ b/docs/user-guide/rules.md @@ -308,7 +308,7 @@ Here are all the rules within stylelint, grouped first [by category](../../VISIO #### Selector list -- [`selector-list-comma-newline-after`](../../lib/rules/selector-list-comma-newline-after/README.md): Require a newline or disallow whitespace after the commas of selector lists. +- [`selector-list-comma-newline-after`](../../lib/rules/selector-list-comma-newline-after/README.md): Require a newline or disallow whitespace after the commas of selector lists (Autofixable). - [`selector-list-comma-newline-before`](../../lib/rules/selector-list-comma-newline-before/README.md): Require a newline or disallow whitespace before the commas of selector lists (Autofixable). - [`selector-list-comma-space-after`](../../lib/rules/selector-list-comma-space-after/README.md): Require a single space or disallow whitespace after the commas of selector lists (Autofixable). - [`selector-list-comma-space-before`](../../lib/rules/selector-list-comma-space-before/README.md): Require a single space or disallow whitespace before the commas of selector lists (Autofixable). diff --git a/lib/rules/selector-list-comma-newline-after/README.md b/lib/rules/selector-list-comma-newline-after/README.md index c44de86114..3ba159e2ca 100644 --- a/lib/rules/selector-list-comma-newline-after/README.md +++ b/lib/rules/selector-list-comma-newline-after/README.md @@ -16,6 +16,8 @@ a, /* comment */ b { color: pink; } ``` +The `--fix` option on the [command line](../../../docs/user-guide/cli.md#autofixing-errors) can automatically fix all of the problems reported by this rule. + ## Options `string`: `"always"|"always-multi-line"|"never-multi-line"` diff --git a/lib/rules/selector-list-comma-newline-after/__tests__/index.js b/lib/rules/selector-list-comma-newline-after/__tests__/index.js index 6ac320b89e..87f533f83c 100644 --- a/lib/rules/selector-list-comma-newline-after/__tests__/index.js +++ b/lib/rules/selector-list-comma-newline-after/__tests__/index.js @@ -6,6 +6,7 @@ const { messages, ruleName } = rule; testRule(rule, { ruleName, config: ["always"], + fix: true, accept: [ { @@ -130,36 +131,42 @@ testRule(rule, { reject: [ { code: "a,b {}", + fixed: "a,\nb {}", message: messages.expectedAfter(), line: 1, column: 2 }, { code: "a, b {}", + fixed: "a,\n b {}", message: messages.expectedAfter(), line: 1, column: 2 }, { code: "a, b {}", + fixed: "a,\n b {}", message: messages.expectedAfter(), line: 1, column: 2 }, { code: "a,\tb {}", + fixed: "a,\n\tb {}", message: messages.expectedAfter(), line: 1, column: 2 }, { code: "a,\nb,c {}", + fixed: "a,\nb,\nc {}", message: messages.expectedAfter(), line: 2, column: 2 }, { code: "a,\r\nb,c {}", + fixed: "a,\r\nb,\r\nc {}", description: "CRLF", message: messages.expectedAfter(), line: 2, @@ -167,6 +174,7 @@ testRule(rule, { }, { code: "a, /* comment */ b {}", + fixed: "a, /* comment */\n b {}", description: "with post-comma comment without newline after", message: messages.expectedAfter(), line: 1, @@ -174,10 +182,19 @@ testRule(rule, { }, { code: "a, /* comment\n commentline2 */b {}", + fixed: "a, /* comment\n commentline2 */\nb {}", description: "with post-comma multi-line comment without newline after", message: messages.expectedAfter(), line: 1, column: 2 + }, + { + code: "a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z {\n}", + fixed: + "a,\nb,\nc,\nd,\ne,\nf,\ng,\nh,\ni,\nj,\nk,\nl,\nm,\nn,\no,\np,\nq,\nr,\ns,\nt,\nu,\nv,\nw,\nx,\ny,\nz {\n}", + message: messages.expectedAfter(), + line: 1, + column: 2 } ] }); @@ -185,6 +202,7 @@ testRule(rule, { testRule(rule, { ruleName, config: ["always-multi-line"], + fix: true, accept: [ { @@ -216,18 +234,21 @@ testRule(rule, { reject: [ { code: "a,\nb, c {}", + fixed: "a,\nb,\n c {}", message: messages.expectedAfterMultiLine(), line: 2, column: 2 }, { code: "a,\nb, c {\n}", + fixed: "a,\nb,\n c {\n}", message: messages.expectedAfterMultiLine(), line: 2, column: 2 }, { code: "a,\r\nb, c {\r\n}", + fixed: "a,\r\nb,\r\n c {\r\n}", description: "CRLF", message: messages.expectedAfterMultiLine(), line: 2, @@ -239,6 +260,7 @@ testRule(rule, { testRule(rule, { ruleName, config: ["never-multi-line"], + fix: true, accept: [ { @@ -265,12 +287,14 @@ testRule(rule, { reject: [ { code: "a,\nb ,c {}", + fixed: "a,b ,c {}", message: messages.rejectedAfterMultiLine(), line: 1, column: 2 }, { code: "a,\r\nb ,c {}", + fixed: "a,b ,c {}", description: "CRLF", message: messages.rejectedAfterMultiLine(), line: 1, @@ -278,6 +302,29 @@ testRule(rule, { }, { code: "a,\nb ,c {\n}", + fixed: "a,b ,c {\n}", + message: messages.rejectedAfterMultiLine(), + line: 1, + column: 2 + }, + { + code: "a,\n\n \t b ,c {\n}", + fixed: "a,b ,c {\n}", + message: messages.rejectedAfterMultiLine(), + line: 1, + column: 2 + }, + { + code: "a,\n/*comment*/\nb ,\nc {\n}", + fixed: "a,\n/*comment*/b ,c {\n}", + message: messages.rejectedAfterMultiLine(), + line: 1, + column: 2 + }, + { + code: + "a,\nb,\nc,\nd,\ne,\nf,\ng,\nh,\ni,\nj,\nk,\nl,\nm,\nn,\no,\np,\nq,\nr,\ns,\nt,\nu,\nv,\nw,\nx,\ny,\nz {\n}", + fixed: "a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z {\n}", message: messages.rejectedAfterMultiLine(), line: 1, column: 2 @@ -290,6 +337,7 @@ testRule(rule, { config: ["always"], skipBasicChecks: true, syntax: "scss", + fix: true, accept: [ { @@ -322,6 +370,7 @@ testRule(rule, { config: ["always"], skipBasicChecks: true, syntax: "less", + fix: true, accept: [ { diff --git a/lib/rules/selector-list-comma-newline-after/index.js b/lib/rules/selector-list-comma-newline-after/index.js index 9fe800b9f8..6ade20f23a 100644 --- a/lib/rules/selector-list-comma-newline-after/index.js +++ b/lib/rules/selector-list-comma-newline-after/index.js @@ -17,7 +17,7 @@ const messages = ruleMessages(ruleName, { 'Unexpected whitespace after "," in a multi-line list' }); -const rule = function(expectation) { +const rule = function(expectation, options, context) { const checker = whitespaceChecker("newline", expectation, messages); return (root, result) => { @@ -42,6 +42,8 @@ const rule = function(expectation) { ? rule.raws.selector.raw : rule.selector; + const fixIndices = []; + styleSearch( { source: selector, @@ -68,17 +70,49 @@ const rule = function(expectation) { checker.afterOneOnly({ source: selector, index: indextoCheckAfter, - err: m => + err: m => { + if (context.fix) { + fixIndices.push(indextoCheckAfter + 1); + + return; + } + report({ message: m, node: rule, index: match.startIndex, result, ruleName - }) + }); + } }); } ); + + if (fixIndices.length) { + let fixedSelector = selector; + + fixIndices + .sort((a, b) => b - a) + .forEach(index => { + const beforeSelector = fixedSelector.slice(0, index); + let afterSelector = fixedSelector.slice(index); + + if (expectation.indexOf("always") === 0) { + afterSelector = context.newline + afterSelector; + } else if (expectation.indexOf("never-multi-line") === 0) { + afterSelector = afterSelector.replace(/^\s*/, ""); + } + + fixedSelector = beforeSelector + afterSelector; + }); + + if (rule.raws.selector) { + rule.raws.selector.raw = fixedSelector; + } else { + rule.selector = fixedSelector; + } + } }); }; };