Skip to content

Commit

Permalink
Add ignore: ["inside-block"] and splitList to selector-disallowed…
Browse files Browse the repository at this point in the history
…-list (#6334)

Co-authored-by: Richard Hallows <jeddy3@users.noreply.github.com>
Co-authored-by: Masafumi Koba <473530+ybiquitous@users.noreply.github.com>
  • Loading branch information
3 people committed Sep 13, 2022
1 parent dd04517 commit bb10282
Show file tree
Hide file tree
Showing 4 changed files with 164 additions and 18 deletions.
5 changes: 5 additions & 0 deletions .changeset/unlucky-dolphins-fetch.md
@@ -0,0 +1,5 @@
---
"stylelint": minor
---

Added: `ignore: ["inside-block"]` and `splitList` to `selector-disallowed-list`
47 changes: 47 additions & 0 deletions lib/rules/selector-disallowed-list/README.md
Expand Up @@ -66,3 +66,50 @@ a
```css
a[href] {}
```

## Optional secondary options

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

Split selector lists into individual selectors.

For example, with `true`.

Given:

```json
[".foo"]
```

The following pattern is considered a problem:

<!-- prettier-ignore -->
```css
.bar, .foo {}
```

The following pattern is _not_ considered a problem:

<!-- prettier-ignore -->
```css
.bar .foo {}
```

### `ignore: ["inside-block"]`

Ignore selectors that are inside a block.

Given:

```json
[".foo"]
```

The following pattern is _not_ considered a problem:

<!-- prettier-ignore -->
```css
.bar {
.foo {}
}
```
57 changes: 57 additions & 0 deletions lib/rules/selector-disallowed-list/__tests__/index.js
Expand Up @@ -66,6 +66,63 @@ testRule({
],
});

testRule({
ruleName,
config: [/^\.(foo)[,\s]?(?!\w).*$/, { ignore: ['inside-block'], splitList: true }],
accept: [
{
code: 'a.foo {}',
},
{
code: 'a\n>\n.foo {}',
},
{
code: '.bar > a > .foo {}',
},
{
code: '.bar { .foo {} }',
},
{
code: '.fooo {}',
},
],

reject: [
{
code: '.foo {}',
message: messages.rejected('.foo'),
line: 1,
column: 1,
endLine: 1,
endColumn: 5,
},
{
code: '.foo > .bar {}',
message: messages.rejected('.foo > .bar'),
line: 1,
column: 1,
endLine: 1,
endColumn: 12,
},
{
code: '.foo, .bar {}',
message: messages.rejected('.foo'),
line: 1,
column: 1,
endLine: 1,
endColumn: 5,
},
{
code: '.bar, .foo {}',
message: messages.rejected('.foo'),
line: 1,
column: 7,
endColumn: 11,
endLine: 1,
},
],
});

testRule({
ruleName,
config: /\.foo[^>]*>.*\.bar/,
Expand Down
73 changes: 55 additions & 18 deletions lib/rules/selector-disallowed-list/index.js
Expand Up @@ -3,9 +3,10 @@
const isStandardSyntaxRule = require('../../utils/isStandardSyntaxRule');
const matchesStringOrRegExp = require('../../utils/matchesStringOrRegExp');
const report = require('../../utils/report');
const optionsMatches = require('../../utils/optionsMatches');
const ruleMessages = require('../../utils/ruleMessages');
const validateOptions = require('../../utils/validateOptions');
const { isRegExp, isString } = require('../../utils/validateTypes');
const { isRegExp, isString, isBoolean } = require('../../utils/validateTypes');

const ruleName = 'selector-disallowed-list';

Expand All @@ -17,38 +18,74 @@ const meta = {
url: 'https://stylelint.io/user-guide/rules/list/selector-disallowed-list',
};

/** @type {import('stylelint').Rule<string | RegExp | Array<string | RegExp>>} */
const rule = (primary) => {
/** @type {import('stylelint').Rule<string | RegExp | Array<string | RegExp>, { splitList: boolean, ignore: string[] }>} */
const rule = (primary, secondaryOptions) => {
return (root, result) => {
const validOptions = validateOptions(result, ruleName, {
actual: primary,
possible: [isString, isRegExp],
});
const validOptions = validateOptions(
result,
ruleName,
{
actual: primary,
possible: [isString, isRegExp],
},
{
actual: secondaryOptions,
possible: {
ignore: ['inside-block'],
splitList: [isBoolean],
},
optional: true,
},
);

if (!validOptions) {
return;
}

const ignoreInsideBlock = optionsMatches(secondaryOptions, 'ignore', 'inside-block');
const splitList = secondaryOptions && secondaryOptions.splitList;

root.walkRules((ruleNode) => {
if (!isStandardSyntaxRule(ruleNode)) {
return;
}

const { selector, raws } = ruleNode;
if (ignoreInsideBlock) {
const { parent } = ruleNode;
const isInsideBlock = parent && parent.type !== 'root';

if (!matchesStringOrRegExp(selector, primary)) {
return;
if (isInsideBlock) {
return;
}
}

const word = (raws.selector && raws.selector.raw) || selector;
if (splitList) {
ruleNode.selectors.forEach((selector) => {
if (matchesStringOrRegExp(selector, primary)) {
report({
result,
ruleName,
message: messages.rejected(selector),
node: ruleNode,
word: selector,
});
}
});
} else {
const { selector, raws } = ruleNode;

report({
result,
ruleName,
message: messages.rejected(selector),
node: ruleNode,
word,
});
if (matchesStringOrRegExp(selector, primary)) {
const word = (raws.selector && raws.selector.raw) || selector;

report({
result,
ruleName,
message: messages.rejected(selector),
node: ruleNode,
word,
});
}
}
});
};
};
Expand Down

0 comments on commit bb10282

Please sign in to comment.