Skip to content

Commit

Permalink
Add ignoreAfterCombinators: [] to selector-max-universal (#6275)
Browse files Browse the repository at this point in the history
  • Loading branch information
fpetrakov committed Aug 18, 2022
1 parent 8cb1829 commit 92d8399
Show file tree
Hide file tree
Showing 3 changed files with 147 additions and 6 deletions.
21 changes: 21 additions & 0 deletions lib/rules/selector-max-universal/README.md
Expand Up @@ -74,3 +74,24 @@ The following patterns are _not_ considered problems:
/* `*` is inside `:not()`, so it is evaluated separately */
* > * .foo:not(*) {}
```

## Optional secondary options

### `ignoreAfterCombinators: ["array", "of", "combinators"]`

Ignore universal selectors that come after one of the specified combinators.

Given:

```json
[">", "+"]
```

For example, with `2`.

The following pattern is _not_ considered a problem:

<!-- prettier-ignore -->
```css
* * > * {}
```
100 changes: 100 additions & 0 deletions lib/rules/selector-max-universal/__tests__/index.js
Expand Up @@ -186,6 +186,18 @@ testRule({
code: '* { @media print { * {} } }',
description: 'media query: nested',
},
{
code: '* + * {}',
description: 'adjacent sibling combinator compound selector',
},
{
code: '* > * {}',
description: 'child combinator compound selector',
},
{
code: '* ~ * {}',
description: 'general sibling combinator compound selector',
},
],

reject: [
Expand All @@ -198,6 +210,35 @@ testRule({
endLine: 1,
endColumn: 6,
},
{
code: '* + * + * {}',
description:
'adjacent sibling combinator compound selector: greater than max universal selectors',
message: messages.expected('* + * + *', 2),
line: 1,
column: 1,
endLine: 1,
endColumn: 10,
},
{
code: '* > * > * {}',
description: 'child combinator compound selector: greater than max universal selectors',
message: messages.expected('* > * > *', 2),
line: 1,
column: 1,
endLine: 1,
endColumn: 10,
},
{
code: '* ~ * ~ * {}',
description:
'general sibling combinator compound selector: greater than max universal selectors',
message: messages.expected('* ~ * ~ *', 2),
line: 1,
column: 1,
endLine: 1,
endColumn: 10,
},
{
code: '*, \n* * * {}',
description: 'multiple selectors: greater than max universal selectors',
Expand Down Expand Up @@ -228,6 +269,65 @@ testRule({
],
});

testRule({
ruleName,
config: [1, { ignoreAfterCombinators: ['>'] }],

accept: [
{
code: '*.foo {}',
},
{
code: '*.foo > * {}',
},
],

reject: [
{
code: '*.foo * {}',
message: messages.expected('*.foo *', 1),
line: 1,
column: 1,
endLine: 1,
endColumn: 8,
},
],
});

testRule({
ruleName,
config: [0, { ignoreAfterCombinators: ['~', '+', '>', ' '] }],

accept: [
{
code: '.foo {}',
},
{
code: '.foo * {}',
},
{
code: '.foo ~ * {}',
},
{
code: '.foo + * {}',
},
{
code: '.foo > * {}',
},
],

reject: [
{
code: '* {}',
message: messages.expected('*', 0),
line: 1,
column: 1,
endLine: 1,
endColumn: 2,
},
],
});

testRule({
ruleName,
config: [0],
Expand Down
32 changes: 26 additions & 6 deletions lib/rules/selector-max-universal/index.js
Expand Up @@ -8,6 +8,8 @@ const resolvedNestedSelector = require('postcss-resolve-nested-selector');
const ruleMessages = require('../../utils/ruleMessages');
const selectorParser = require('postcss-selector-parser');
const validateOptions = require('../../utils/validateOptions');
const optionsMatches = require('../../utils/optionsMatches');
const { isString } = require('../../utils/validateTypes');

const ruleName = 'selector-max-universal';

Expand All @@ -23,12 +25,23 @@ const meta = {
};

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

if (!validOptions) {
return;
Expand All @@ -46,7 +59,14 @@ const rule = (primary) => {
checkSelector(childNode, ruleNode);
}

if (childNode.type === 'universal') total += 1;
const prevChildNode = childNode.prev();
const prevChildNodeValue = prevChildNode && prevChildNode.value;

if (childNode.type === 'universal') {
if (!optionsMatches(secondaryOptions, 'ignoreAfterCombinators', prevChildNodeValue)) {
total += 1;
}
}

return total;
}, 0);
Expand Down

0 comments on commit 92d8399

Please sign in to comment.