Skip to content

Commit 28c8d2b

Browse files
authored
fix: do not comment out unused selectors that are inside an unused selector (#13746)
fixes #13680
1 parent 2efae79 commit 28c8d2b

File tree

5 files changed

+51
-23
lines changed

5 files changed

+51
-23
lines changed

.changeset/moody-kids-brake.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'svelte': patch
3+
---
4+
5+
fix: do not comment out unused selectors that are inside an unused selector

packages/svelte/src/compiler/phases/3-transform/css/index.js

Lines changed: 22 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -159,34 +159,37 @@ const visitors = {
159159
next();
160160
},
161161
SelectorList(node, { state, next, path }) {
162-
let pruning = false;
163-
let last = node.children[0].start;
162+
// Only add comments if we're not inside a complex selector that itself is unused
163+
if (!path.find((n) => n.type === 'ComplexSelector' && !n.metadata.used)) {
164+
let pruning = false;
165+
let last = node.children[0].start;
164166

165-
for (let i = 0; i < node.children.length; i += 1) {
166-
const selector = node.children[i];
167+
for (let i = 0; i < node.children.length; i += 1) {
168+
const selector = node.children[i];
167169

168-
if (selector.metadata.used === pruning) {
169-
if (pruning) {
170-
let i = selector.start;
171-
while (state.code.original[i] !== ',') i--;
170+
if (selector.metadata.used === pruning) {
171+
if (pruning) {
172+
let i = selector.start;
173+
while (state.code.original[i] !== ',') i--;
172174

173-
state.code.overwrite(i, i + 1, '*/');
174-
} else {
175-
if (i === 0) {
176-
state.code.prependRight(selector.start, '/* (unused) ');
175+
state.code.overwrite(i, i + 1, '*/');
177176
} else {
178-
state.code.overwrite(last, selector.start, ' /* (unused) ');
177+
if (i === 0) {
178+
state.code.prependRight(selector.start, '/* (unused) ');
179+
} else {
180+
state.code.overwrite(last, selector.start, ' /* (unused) ');
181+
}
179182
}
183+
184+
pruning = !pruning;
180185
}
181186

182-
pruning = !pruning;
187+
last = selector.end;
183188
}
184189

185-
last = selector.end;
186-
}
187-
188-
if (pruning) {
189-
state.code.appendLeft(last, '*/');
190+
if (pruning) {
191+
state.code.appendLeft(last, '*/');
192+
}
190193
}
191194

192195
// if we're in a `:is(...)` or whatever, keep existing specificity bump state

packages/svelte/tests/css/samples/has/_config.js

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -86,18 +86,32 @@ export default test({
8686
line: 81
8787
}
8888
},
89+
{
90+
code: 'css_unused_selector',
91+
message: 'Unused CSS selector ".unused:has(.unused)"',
92+
start: {
93+
line: 84,
94+
column: 1,
95+
character: 934
96+
},
97+
end: {
98+
line: 84,
99+
column: 21,
100+
character: 954
101+
}
102+
},
89103
{
90104
code: 'css_unused_selector',
91105
message: 'Unused CSS selector "x:has(> z)"',
92106
start: {
93-
line: 88,
107+
line: 91,
94108
column: 1,
95-
character: 968
109+
character: 1021
96110
},
97111
end: {
98-
line: 88,
112+
line: 91,
99113
column: 11,
100-
character: 978
114+
character: 1031
101115
}
102116
}
103117
]

packages/svelte/tests/css/samples/has/expected.css

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,9 @@
7575
/* (unused) .unused x:has(y) {
7676
color: red;
7777
}*/
78+
/* (unused) .unused:has(.unused)*/ x.svelte-xyz:has(y:where(.svelte-xyz)) {
79+
color: green;
80+
}
7881

7982
x.svelte-xyz:has(> y:where(.svelte-xyz)) {
8083
color: green;

packages/svelte/tests/css/samples/has/input.svelte

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,9 @@
8181
.unused x:has(y) {
8282
color: red;
8383
}
84+
.unused:has(.unused), x:has(y) {
85+
color: green;
86+
}
8487
8588
x:has(> y) {
8689
color: green;

0 commit comments

Comments
 (0)