Skip to content

Commit 3dc02fa

Browse files
authored
postcss-is-pseudo-class : fix edge case with compounds (#1101)
1 parent eda35c4 commit 3dc02fa

14 files changed

+93
-8
lines changed

plugins/postcss-is-pseudo-class/.tape.mjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ postcssTape(plugin)({
1919
},
2020
'basic:oncomplex:warning': {
2121
message: "warns on complex selectors",
22-
warnings: 8,
22+
warnings: 9,
2323
options: {
2424
onComplexSelector: 'warning'
2525
}

plugins/postcss-is-pseudo-class/CHANGELOG.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,18 @@
11
# Changes to PostCSS Is Pseudo Class
22

3+
### Unreleased (patch)
4+
5+
- Fix substitution when selectors have mixed types for compound selectors where one of two parts is a `:is()` pseudo class.
6+
7+
```diff
8+
header:is(.a .b) {}
9+
10+
/* becomes : */
11+
12+
- header.a .b {}
13+
+ .a header.b {}
14+
```
15+
316
### 4.0.0
417

518
_July 3, 2023_

plugins/postcss-is-pseudo-class/dist/index.cjs

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

plugins/postcss-is-pseudo-class/dist/index.mjs

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
export default function splitSelectors(selectors: Array<string>, pluginOptions: {
22
specificityMatchingName: string;
3-
}, recursionDepth?: number): any[];
3+
}, recursionDepth?: number): Array<string>;

plugins/postcss-is-pseudo-class/src/split-selectors/complex/is-in-compound.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,12 @@ export function isInCompoundWithOneOtherElement(selector): boolean {
4747
}
4848
}
4949

50-
selector.nodes[isPseudoIndex].append(selector.nodes[simpleSelectorIndex].clone());
51-
selector.nodes[isPseudoIndex].replaceWith(...selector.nodes[isPseudoIndex].nodes);
50+
if (selector.nodes[simpleSelectorIndex].type === 'combinator') {
51+
return false;
52+
}
53+
54+
selector.nodes[isPseudoIndex].nodes[0].append(selector.nodes[simpleSelectorIndex].clone());
55+
selector.nodes[isPseudoIndex].replaceWith(...selector.nodes[isPseudoIndex].nodes[0].nodes);
5256
selector.nodes[simpleSelectorIndex].remove();
5357

5458
return true;

plugins/postcss-is-pseudo-class/src/split-selectors/split-selectors.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { selectorSpecificity } from '@csstools/selector-specificity';
44
// splitSelectors handles the forgiving list behavior of ":is".
55
// After created all combinations it wraps the individual selectors in ":-csstools-matches".
66
// This makes it easy to recursively resolve all ":is" selectors without infinite loops.
7-
export default function splitSelectors(selectors: Array<string>, pluginOptions: { specificityMatchingName: string }, recursionDepth = 0) {
7+
export default function splitSelectors(selectors: Array<string>, pluginOptions: { specificityMatchingName: string }, recursionDepth = 0): Array<string> {
88
const specificityMatchingNameId = ':not(#' + pluginOptions.specificityMatchingName + ')';
99
const specificityMatchingNameClass = ':not(.' + pluginOptions.specificityMatchingName + ')';
1010
const specificityMatchingNameTag = ':not(' + pluginOptions.specificityMatchingName + ')';
@@ -15,7 +15,11 @@ export default function splitSelectors(selectors: Array<string>, pluginOptions:
1515
}
1616

1717
let foundNestedIs = false;
18-
const replacements = [];
18+
const replacements: Array<Array<{
19+
start: number,
20+
end: number,
21+
option: string,
22+
}>> = [];
1923

2024
const selectorAST = parser().astSync(selector);
2125
selectorAST.walkPseudos((pseudo) => {

plugins/postcss-is-pseudo-class/test/basic.css

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,3 +153,11 @@ foo[baz=":is(.some, .other)"], .ok {
153153
:is(input, button):is(:hover, :focus) {
154154
to-clone: 1;
155155
}
156+
157+
header:is(.a .b) {
158+
color: green;
159+
}
160+
161+
>:is(.a .b) {
162+
color: green;
163+
}

plugins/postcss-is-pseudo-class/test/basic.does-not-exist.expect.css

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,3 +261,11 @@ h1.a, h2.a, h3.a, h4.a, h5.a, h6.a, .a h1, .a h2, .a h3, .a h4, .a h5, .a h6 {
261261
input:hover, input:focus, button:hover, button:focus {
262262
to-clone: 1;
263263
}
264+
265+
.a header.b {
266+
color: green;
267+
}
268+
269+
>:is(.a .b) {
270+
color: green;
271+
}

plugins/postcss-is-pseudo-class/test/basic.expect.css

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,3 +261,11 @@ h1.a, h2.a, h3.a, h4.a, h5.a, h6.a, .a h1, .a h2, .a h3, .a h4, .a h5, .a h6 {
261261
input:hover, input:focus, button:hover, button:focus {
262262
to-clone: 1;
263263
}
264+
265+
.a header.b {
266+
color: green;
267+
}
268+
269+
>:is(.a .b) {
270+
color: green;
271+
}

plugins/postcss-is-pseudo-class/test/basic.oncomplex.no-warning.expect.css

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,3 +261,11 @@ h1.a, h2.a, h3.a, h4.a, h5.a, h6.a, .a h1, .a h2, .a h3, .a h4, .a h5, .a h6 {
261261
input:hover, input:focus, button:hover, button:focus {
262262
to-clone: 1;
263263
}
264+
265+
.a header.b {
266+
color: green;
267+
}
268+
269+
>:is(.a .b) {
270+
color: green;
271+
}

plugins/postcss-is-pseudo-class/test/basic.oncomplex.warning.expect.css

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,3 +261,11 @@ h1.a, h2.a, h3.a, h4.a, h5.a, h6.a, .a h1, .a h2, .a h3, .a h4, .a h5, .a h6 {
261261
input:hover, input:focus, button:hover, button:focus {
262262
to-clone: 1;
263263
}
264+
265+
.a header.b {
266+
color: green;
267+
}
268+
269+
>:is(.a .b) {
270+
color: green;
271+
}

plugins/postcss-is-pseudo-class/test/basic.preserve.expect.css

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -401,3 +401,15 @@ input:hover, input:focus, button:hover, button:focus {
401401
:is(input, button):is(:hover, :focus) {
402402
to-clone: 1;
403403
}
404+
405+
.a header.b {
406+
color: green;
407+
}
408+
409+
header:is(.a .b) {
410+
color: green;
411+
}
412+
413+
>:is(.a .b) {
414+
color: green;
415+
}

plugins/postcss-is-pseudo-class/test/basic.with-cloned-declarations.expect.css

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -403,3 +403,15 @@ input:hover, input:focus, button:hover, button:focus {
403403
cloned: 1;
404404
to-clone: 1;
405405
}
406+
407+
.a header.b {
408+
color: green;
409+
}
410+
411+
header:is(.a .b) {
412+
color: green;
413+
}
414+
415+
>:is(.a .b) {
416+
color: green;
417+
}

0 commit comments

Comments
 (0)