Skip to content

Commit

Permalink
Add splitList: boolean to selector-nested-pattern (#6896)
Browse files Browse the repository at this point in the history
Co-authored-by: Masafumi Koba <473530+ybiquitous@users.noreply.github.com>
  • Loading branch information
is2ei and ybiquitous committed Jun 5, 2023
1 parent 83be8b5 commit 8f489b0
Show file tree
Hide file tree
Showing 4 changed files with 107 additions and 21 deletions.
5 changes: 5 additions & 0 deletions .changeset/chilled-lizards-film.md
@@ -0,0 +1,5 @@
---
"stylelint": minor
---

Added: `splitList: boolean` to `selector-nested-pattern`
34 changes: 34 additions & 0 deletions lib/rules/selector-nested-pattern/README.md
Expand Up @@ -77,3 +77,37 @@ a {
&:focus {}
}
```

## Optional secondary options

### `splitList: true | false` (default: `false`)

Split selector lists into individual selectors.

For example, with `true`.

Given the string:

```json
"^&:(?:hover|focus)$"
```

The following patterns are considered problems:

<!-- prettier-ignore -->
```css
a {
.bar:hover,
&:focus {}
}
```

The following patterns are _not_ considered problems:

<!-- prettier-ignore -->
```css
a {
&:hover,
&:focus {}
}
```
39 changes: 36 additions & 3 deletions lib/rules/selector-nested-pattern/__tests__/index.js
Expand Up @@ -152,12 +152,45 @@ testRule({
endColumn: 18,
},
{
code: '.foo { &:hover, &focus {} }',
message: messages.expected('&:hover, &focus', '^&:(?:hover|focus)$'),
code: '.foo { &:hover, &:focus {} }',
message: messages.expected('&:hover, &:focus', '^&:(?:hover|focus)$'),
line: 1,
column: 8,
endLine: 1,
endColumn: 23,
endColumn: 24,
},
],
});

testRule({
ruleName,
config: ['^&:(?:hover|focus)$', { splitList: true }],

accept: [
{
code: '.foo { &:hover {} }',
},
{
code: '.foo { &:hover, &:focus {} }',
},
],

reject: [
{
code: '.foo { .bar:hover {} }',
message: messages.expected('.bar:hover', '^&:(?:hover|focus)$'),
line: 1,
column: 8,
endLine: 1,
endColumn: 18,
},
{
code: '.foo { .bar:hover, &:focus {} }',
message: messages.expected('.bar:hover', '^&:(?:hover|focus)$'),
line: 1,
column: 8,
endLine: 1,
endColumn: 18,
},
],
});
Expand Down
50 changes: 32 additions & 18 deletions lib/rules/selector-nested-pattern/index.js
Expand Up @@ -4,7 +4,7 @@ const isStandardSyntaxRule = require('../../utils/isStandardSyntaxRule');
const report = require('../../utils/report');
const ruleMessages = require('../../utils/ruleMessages');
const validateOptions = require('../../utils/validateOptions');
const { isRegExp, isString } = require('../../utils/validateTypes');
const { isBoolean, isRegExp, isString } = require('../../utils/validateTypes');

const ruleName = 'selector-nested-pattern';

Expand All @@ -17,18 +17,30 @@ const meta = {
};

/** @type {import('stylelint').Rule} */
const rule = (primary) => {
const rule = (primary, secondaryOptions) => {
return (root, result) => {
const validOptions = validateOptions(result, ruleName, {
actual: primary,
possible: [isRegExp, isString],
});
const validOptions = validateOptions(
result,
ruleName,
{
actual: primary,
possible: [isRegExp, isString],
},
{
actual: secondaryOptions,
possible: {
splitList: [isBoolean],
},
optional: true,
},
);

if (!validOptions) {
return;
}

const normalizedPattern = isString(primary) ? new RegExp(primary) : primary;
const splitList = secondaryOptions && secondaryOptions.splitList;

root.walkRules((ruleNode) => {
if (ruleNode.parent && ruleNode.parent.type !== 'rule') {
Expand All @@ -39,20 +51,22 @@ const rule = (primary) => {
return;
}

const selector = ruleNode.selector;
const selectors = splitList ? ruleNode.selectors : [ruleNode.selector];

if (normalizedPattern.test(selector)) {
return;
}
for (const selector of selectors) {
if (normalizedPattern.test(selector)) {
continue;
}

report({
result,
ruleName,
message: messages.expected,
messageArgs: [selector, primary],
node: ruleNode,
word: selector,
});
report({
result,
ruleName,
message: messages.expected,
messageArgs: [selector, primary],
node: ruleNode,
word: selector,
});
}
});
};
};
Expand Down

0 comments on commit 8f489b0

Please sign in to comment.