Skip to content

Commit 5538466

Browse files
committed
correctly split atrule preludes
1 parent e6b74da commit 5538466

File tree

4 files changed

+97
-4
lines changed

4 files changed

+97
-4
lines changed

index.js

+46-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ module.exports = function resolveNestedSelector(selector, node) {
66
if (parent.type !== 'rule' && !parentIsNestAtRule) return resolveNestedSelector(selector, parent);
77

88
var parentSelectors = (parentIsNestAtRule)
9-
? parent.params.split(',').map(function(s) { return s.trim(); })
9+
? list(parent.params)
1010
: parent.selectors;
1111

1212
var resolvedSelectors = parentSelectors.reduce(function(result, parentSelector) {
@@ -23,3 +23,48 @@ module.exports = function resolveNestedSelector(selector, node) {
2323

2424
return resolvedSelectors;
2525
}
26+
27+
// https://github.com/postcss/postcss/blob/main/lib/list.js#L1
28+
// We should not have `postcss` as a direct dependency so, we inline the same code here.
29+
function list(string) {
30+
let array = []
31+
let current = ''
32+
let split = false
33+
34+
let func = 0
35+
let inQuote = false
36+
let prevQuote = ''
37+
let escape = false
38+
39+
for (let letter of string) {
40+
if (escape) {
41+
escape = false
42+
} else if (letter === '\\') {
43+
escape = true
44+
} else if (inQuote) {
45+
if (letter === prevQuote) {
46+
inQuote = false
47+
}
48+
} else if (letter === '"' || letter === "'") {
49+
inQuote = true
50+
prevQuote = letter
51+
} else if (letter === '(') {
52+
func += 1
53+
} else if (letter === ')') {
54+
if (func > 0) func -= 1
55+
} else if (func === 0) {
56+
if (letter === ',') split = true
57+
}
58+
59+
if (split) {
60+
if (current !== '') array.push(current.trim())
61+
current = ''
62+
split = false
63+
} else {
64+
current += letter
65+
}
66+
}
67+
68+
if (current !== '') array.push(current.trim())
69+
return array
70+
}

package-lock.json

+2-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "postcss-resolve-nested-selector",
3-
"version": "0.1.2",
3+
"version": "0.1.3",
44
"description": "Resolve a nested selector in a PostCSS AST",
55
"main": "index.js",
66
"scripts": {

test/api.test.mjs

+48
Original file line numberDiff line numberDiff line change
@@ -57,3 +57,51 @@ test(async t => {
5757
['.foo:hover > b', '.foo_bar > b'],
5858
);
5959
});
60+
61+
test(async t => {
62+
const code = `.a { .b:is(:hover, :focus) & {} }`;
63+
assert.deepEqual(
64+
await util.resolveChosenSelector(code, '.b:is(:hover, :focus) &'),
65+
['.b:is(:hover, :focus) .a'],
66+
);
67+
});
68+
69+
test(async t => {
70+
const code = `.a { .b:is(:hover, :focus) & { & .c {} } }`;
71+
assert.deepEqual(
72+
await util.resolveChosenSelector(code, '& .c'),
73+
['.b:is(:hover, :focus) .a .c'],
74+
);
75+
});
76+
77+
test(async t => {
78+
const code = `.a {
79+
@nest .b:not(:hover, :focus) & {
80+
& .c {
81+
color: red;
82+
}
83+
}
84+
}`;
85+
assert.deepEqual(
86+
await util.resolveChosenSelector(code, '& .c'),
87+
['.b:not(:hover, :focus) .a .c'],
88+
);
89+
});
90+
91+
test(async t => {
92+
const code = `.a {
93+
@nest .b & , & .c , & .d & {
94+
& .e {
95+
color: red;
96+
}
97+
}
98+
}`;
99+
assert.deepEqual(
100+
await util.resolveChosenSelector(code, '& .e'),
101+
[
102+
'.a .c .e',
103+
'.a .d .a .e',
104+
'.b .a .e'
105+
],
106+
);
107+
});

0 commit comments

Comments
 (0)