Skip to content

Commit

Permalink
Add autofix to selector-list-comma-newline-after (#3815)
Browse files Browse the repository at this point in the history
  • Loading branch information
ota-meshi authored and ntwb committed Nov 27, 2018
1 parent 279b8b4 commit df0630d
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 4 deletions.
2 changes: 1 addition & 1 deletion docs/user-guide/rules.md
Expand Up @@ -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).
Expand Down
2 changes: 2 additions & 0 deletions lib/rules/selector-list-comma-newline-after/README.md
Expand Up @@ -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"`
Expand Down
49 changes: 49 additions & 0 deletions lib/rules/selector-list-comma-newline-after/__tests__/index.js
Expand Up @@ -6,6 +6,7 @@ const { messages, ruleName } = rule;
testRule(rule, {
ruleName,
config: ["always"],
fix: true,

accept: [
{
Expand Down Expand Up @@ -130,61 +131,78 @@ 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,
column: 2
},
{
code: "a, /* comment */ b {}",
fixed: "a, /* comment */\n b {}",
description: "with post-comma comment without newline after",
message: messages.expectedAfter(),
line: 1,
column: 2
},
{
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
}
]
});

testRule(rule, {
ruleName,
config: ["always-multi-line"],
fix: true,

accept: [
{
Expand Down Expand Up @@ -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,
Expand All @@ -239,6 +260,7 @@ testRule(rule, {
testRule(rule, {
ruleName,
config: ["never-multi-line"],
fix: true,

accept: [
{
Expand All @@ -265,19 +287,44 @@ 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,
column: 2
},
{
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
Expand All @@ -290,6 +337,7 @@ testRule(rule, {
config: ["always"],
skipBasicChecks: true,
syntax: "scss",
fix: true,

accept: [
{
Expand Down Expand Up @@ -322,6 +370,7 @@ testRule(rule, {
config: ["always"],
skipBasicChecks: true,
syntax: "less",
fix: true,

accept: [
{
Expand Down
40 changes: 37 additions & 3 deletions lib/rules/selector-list-comma-newline-after/index.js
Expand Up @@ -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) => {
Expand All @@ -42,6 +42,8 @@ const rule = function(expectation) {
? rule.raws.selector.raw
: rule.selector;

const fixIndices = [];

styleSearch(
{
source: selector,
Expand All @@ -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;
}
}
});
};
};
Expand Down

0 comments on commit df0630d

Please sign in to comment.