Skip to content

Commit

Permalink
correctly split atrule preludes
Browse files Browse the repository at this point in the history
  • Loading branch information
romainmenke committed Jul 23, 2024
1 parent e6b74da commit 5538466
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 4 deletions.
47 changes: 46 additions & 1 deletion index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ module.exports = function resolveNestedSelector(selector, node) {
if (parent.type !== 'rule' && !parentIsNestAtRule) return resolveNestedSelector(selector, parent);

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

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

return resolvedSelectors;
}

// https://github.com/postcss/postcss/blob/main/lib/list.js#L1
// We should not have `postcss` as a direct dependency so, we inline the same code here.
function list(string) {
let array = []
let current = ''
let split = false

let func = 0
let inQuote = false
let prevQuote = ''
let escape = false

for (let letter of string) {
if (escape) {
escape = false
} else if (letter === '\\') {
escape = true
} else if (inQuote) {
if (letter === prevQuote) {
inQuote = false
}
} else if (letter === '"' || letter === "'") {
inQuote = true
prevQuote = letter
} else if (letter === '(') {
func += 1
} else if (letter === ')') {
if (func > 0) func -= 1
} else if (func === 0) {
if (letter === ',') split = true
}

if (split) {
if (current !== '') array.push(current.trim())
current = ''
split = false
} else {
current += letter
}
}

if (current !== '') array.push(current.trim())
return array
}
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "postcss-resolve-nested-selector",
"version": "0.1.2",
"version": "0.1.3",
"description": "Resolve a nested selector in a PostCSS AST",
"main": "index.js",
"scripts": {
Expand Down
48 changes: 48 additions & 0 deletions test/api.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,51 @@ test(async t => {
['.foo:hover > b', '.foo_bar > b'],
);
});

test(async t => {
const code = `.a { .b:is(:hover, :focus) & {} }`;
assert.deepEqual(
await util.resolveChosenSelector(code, '.b:is(:hover, :focus) &'),
['.b:is(:hover, :focus) .a'],
);
});

test(async t => {
const code = `.a { .b:is(:hover, :focus) & { & .c {} } }`;
assert.deepEqual(
await util.resolveChosenSelector(code, '& .c'),
['.b:is(:hover, :focus) .a .c'],
);
});

test(async t => {
const code = `.a {
@nest .b:not(:hover, :focus) & {
& .c {
color: red;
}
}
}`;
assert.deepEqual(
await util.resolveChosenSelector(code, '& .c'),
['.b:not(:hover, :focus) .a .c'],
);
});

test(async t => {
const code = `.a {
@nest .b & , & .c , & .d & {
& .e {
color: red;
}
}
}`;
assert.deepEqual(
await util.resolveChosenSelector(code, '& .e'),
[
'.a .c .e',
'.a .d .a .e',
'.b .a .e'
],
);
});

0 comments on commit 5538466

Please sign in to comment.