Skip to content

Commit 22b5193

Browse files
author
7nik
committed
fix: correctly look for sibling elements inside blocks and components
1 parent e9cc7dc commit 22b5193

File tree

5 files changed

+105
-61
lines changed

5 files changed

+105
-61
lines changed

.changeset/curly-balloons-relate.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: correctly look for sibling elements inside blocks and components

packages/svelte/src/compiler/phases/2-analyze/css/css-prune.js

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -638,19 +638,26 @@ function get_following_sibling_elements(element, include_self) {
638638
/** @type {Array<Compiler.AST.RegularElement | Compiler.AST.SvelteElement>} */
639639
const siblings = [];
640640

641-
// ...then walk them, starting from the node after the one
642-
// containing the element in question
641+
// ...then walk them, starting from the node containing the element in question
642+
// skipping nodes that appears before the element
643643

644644
const seen = new Set();
645+
let skip = true;
645646

646647
/** @param {Compiler.AST.SvelteNode} node */
647648
function get_siblings(node) {
648649
walk(node, null, {
649650
RegularElement(node) {
650-
siblings.push(node);
651+
if (node === element) {
652+
skip = false;
653+
if (include_self) siblings.push(node);
654+
} else if (!skip) siblings.push(node);
651655
},
652656
SvelteElement(node) {
653-
siblings.push(node);
657+
if (node === element) {
658+
skip = false;
659+
if (include_self) siblings.push(node);
660+
} else if (!skip) siblings.push(node);
654661
},
655662
RenderTag(node) {
656663
for (const snippet of node.metadata.snippets) {
@@ -663,14 +670,10 @@ function get_following_sibling_elements(element, include_self) {
663670
});
664671
}
665672

666-
for (const node of nodes.slice(nodes.indexOf(start) + 1)) {
673+
for (const node of nodes.slice(nodes.indexOf(start))) {
667674
get_siblings(node);
668675
}
669676

670-
if (include_self) {
671-
siblings.push(element);
672-
}
673-
674677
return siblings;
675678
}
676679

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

Lines changed: 66 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -6,182 +6,196 @@ export default test({
66
code: 'css_unused_selector',
77
message: 'Unused CSS selector ".unused:has(y)"',
88
start: {
9-
line: 31,
9+
line: 33,
1010
column: 1,
11-
character: 308
11+
character: 330
1212
},
1313
end: {
14-
line: 31,
14+
line: 33,
1515
column: 15,
16-
character: 322
16+
character: 344
1717
}
1818
},
1919
{
2020
code: 'css_unused_selector',
2121
message: 'Unused CSS selector ".unused:has(:global(y))"',
2222
start: {
23-
line: 34,
23+
line: 36,
2424
column: 1,
25-
character: 343
25+
character: 365
2626
},
2727
end: {
28-
line: 34,
28+
line: 36,
2929
column: 24,
30-
character: 366
30+
character: 388
3131
}
3232
},
3333
{
3434
code: 'css_unused_selector',
3535
message: 'Unused CSS selector "x:has(.unused)"',
3636
start: {
37-
line: 37,
37+
line: 39,
3838
column: 1,
39-
character: 387
39+
character: 409
4040
},
4141
end: {
42-
line: 37,
42+
line: 39,
4343
column: 15,
44-
character: 401
44+
character: 423
4545
}
4646
},
4747
{
4848
code: 'css_unused_selector',
4949
message: 'Unused CSS selector ":global(.foo):has(.unused)"',
5050
start: {
51-
line: 40,
51+
line: 42,
5252
column: 1,
53-
character: 422
53+
character: 444
5454
},
5555
end: {
56-
line: 40,
56+
line: 42,
5757
column: 27,
58-
character: 448
58+
character: 470
5959
}
6060
},
6161
{
6262
code: 'css_unused_selector',
6363
message: 'Unused CSS selector "x:has(y):has(.unused)"',
6464
start: {
65-
line: 50,
65+
line: 52,
6666
column: 1,
67-
character: 556
67+
character: 578
6868
},
6969
end: {
70-
line: 50,
70+
line: 52,
7171
column: 22,
72-
character: 577
72+
character: 599
7373
}
7474
},
7575
{
7676
code: 'css_unused_selector',
7777
message: 'Unused CSS selector ".unused"',
7878
start: {
79-
line: 69,
79+
line: 71,
8080
column: 2,
81-
character: 782
81+
character: 804
8282
},
8383
end: {
84-
line: 69,
84+
line: 71,
8585
column: 9,
86-
character: 789
86+
character: 811
8787
}
8888
},
8989
{
9090
code: 'css_unused_selector',
9191
message: 'Unused CSS selector ".unused x:has(y)"',
9292
start: {
93-
line: 85,
93+
line: 87,
9494
column: 1,
95-
character: 936
95+
character: 958
9696
},
9797
end: {
98-
line: 85,
98+
line: 87,
9999
column: 17,
100-
character: 952
100+
character: 974
101101
}
102102
},
103103
{
104104
code: 'css_unused_selector',
105105
message: 'Unused CSS selector ".unused:has(.unused)"',
106106
start: {
107-
line: 88,
107+
line: 90,
108108
column: 1,
109-
character: 973
109+
character: 995
110110
},
111111
end: {
112-
line: 88,
112+
line: 90,
113113
column: 21,
114-
character: 993
114+
character: 1015
115115
}
116116
},
117117
{
118118
code: 'css_unused_selector',
119119
message: 'Unused CSS selector "x:has(> z)"',
120120
start: {
121-
line: 98,
121+
line: 100,
122122
column: 1,
123-
character: 1093
123+
character: 1115
124124
},
125125
end: {
126-
line: 98,
126+
line: 100,
127127
column: 11,
128-
character: 1103
128+
character: 1125
129129
}
130130
},
131131
{
132132
code: 'css_unused_selector',
133133
message: 'Unused CSS selector "x:has(> d)"',
134134
start: {
135-
line: 101,
135+
line: 103,
136136
column: 1,
137-
character: 1124
137+
character: 1146
138138
},
139139
end: {
140-
line: 101,
140+
line: 103,
141141
column: 11,
142-
character: 1134
142+
character: 1156
143143
}
144144
},
145145
{
146146
code: 'css_unused_selector',
147147
message: 'Unused CSS selector "x:has(~ y)"',
148148
start: {
149-
line: 121,
149+
line: 123,
150150
column: 1,
151-
character: 1326
151+
character: 1348
152152
},
153153
end: {
154-
line: 121,
154+
line: 123,
155155
column: 11,
156-
character: 1336
156+
character: 1358
157+
}
158+
},
159+
{
160+
code: 'css_unused_selector',
161+
message: 'Unused CSS selector "f:has(~ d)"',
162+
start: {
163+
line: 133,
164+
column: 1,
165+
character: 1446
166+
},
167+
end: {
168+
line: 133,
169+
column: 11,
170+
character: 1456
157171
}
158172
},
159173
{
160174
code: 'css_unused_selector',
161175
message: 'Unused CSS selector ":has(.unused)"',
162176
start: {
163-
line: 129,
177+
line: 141,
164178
column: 2,
165-
character: 1409
179+
character: 1529
166180
},
167181
end: {
168-
line: 129,
182+
line: 141,
169183
column: 15,
170-
character: 1422
184+
character: 1542
171185
}
172186
},
173187
{
174188
code: 'css_unused_selector',
175189
message: 'Unused CSS selector "&:has(.unused)"',
176190
start: {
177-
line: 135,
191+
line: 147,
178192
column: 2,
179-
character: 1480
193+
character: 1600
180194
},
181195
end: {
182-
line: 135,
196+
line: 147,
183197
column: 16,
184-
character: 1494
198+
character: 1614
185199
}
186200
}
187201
]

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,16 @@
112112
color: red;
113113
}*/
114114

115+
d.svelte-xyz:has(+ e:where(.svelte-xyz)) {
116+
color: green;
117+
}
118+
d.svelte-xyz:has(~ f:where(.svelte-xyz)) {
119+
color: green;
120+
}
121+
/* (unused) f:has(~ d) {
122+
color: red;
123+
}*/
124+
115125
.foo {
116126
.svelte-xyz:has(x:where(.svelte-xyz)) {
117127
color: green;

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
<z></z>
44
{#if foo}
55
<d></d>
6+
<e></e>
7+
<f></f>
68
{/if}
79
</y>
810
</x>
@@ -122,6 +124,16 @@
122124
color: red;
123125
}
124126
127+
d:has(+ e) {
128+
color: green;
129+
}
130+
d:has(~ f) {
131+
color: green;
132+
}
133+
f:has(~ d) {
134+
color: red;
135+
}
136+
125137
:global(.foo) {
126138
:has(x) {
127139
color: green;

0 commit comments

Comments
 (0)