Skip to content

Commit 36ece1c

Browse files
authored
fix: don't wrap pseudo classes inside :global(...) with another :global(...) (#14267)
fixes #14088
1 parent 4a85c41 commit 36ece1c

File tree

4 files changed

+44
-11
lines changed

4 files changed

+44
-11
lines changed

.changeset/hot-ladybugs-clap.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: don't wrap pseudo classes inside `:global(...)` with another `:global(...)` during migration

packages/svelte/src/compiler/migrate/index.js

Lines changed: 35 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,10 @@ class MigrationError extends Error {
4040
*/
4141
function migrate_css(state) {
4242
if (!state.analysis.css.ast?.start) return;
43-
let code = state.str
43+
const css_contents = state.str
4444
.snip(state.analysis.css.ast.start, /** @type {number} */ (state.analysis.css.ast?.end))
4545
.toString();
46+
let code = css_contents;
4647
let starting = 0;
4748

4849
// since we already blank css we can't work directly on `state.str` so we will create a copy that we can update
@@ -56,23 +57,28 @@ function migrate_css(state) {
5657
) {
5758
let start = code.indexOf('(') + 1;
5859
let is_global = false;
60+
5961
const global_str = ':global';
6062
const next_global = code.indexOf(global_str);
6163
const str_between = code.substring(start, next_global);
6264
if (!str_between.trim()) {
6365
is_global = true;
6466
start += global_str.length;
67+
} else {
68+
const prev_global = css_contents.lastIndexOf(global_str, starting);
69+
if (prev_global > -1) {
70+
const end =
71+
find_closing_parenthesis(css_contents.indexOf('(', prev_global) + 1, css_contents) -
72+
starting;
73+
if (end > start) {
74+
starting += end;
75+
code = code.substring(end);
76+
continue;
77+
}
78+
}
6579
}
66-
let parenthesis = 1;
67-
let end = start;
68-
let char = code[end];
69-
// find the closing parenthesis
70-
while (parenthesis !== 0 && char) {
71-
if (char === '(') parenthesis++;
72-
if (char === ')') parenthesis--;
73-
end++;
74-
char = code[end];
75-
}
80+
81+
const end = find_closing_parenthesis(start, code);
7682
if (start && end) {
7783
if (!is_global && !code.startsWith(':not')) {
7884
str.prependLeft(starting + start, ':global(');
@@ -89,6 +95,24 @@ function migrate_css(state) {
8995
state.str.update(state.analysis.css.ast?.start, state.analysis.css.ast?.end, str.toString());
9096
}
9197

98+
/**
99+
* @param {number} start
100+
* @param {string} code
101+
*/
102+
function find_closing_parenthesis(start, code) {
103+
let parenthesis = 1;
104+
let end = start;
105+
let char = code[end];
106+
// find the closing parenthesis
107+
while (parenthesis !== 0 && char) {
108+
if (char === '(') parenthesis++;
109+
if (char === ')') parenthesis--;
110+
end++;
111+
char = code[end];
112+
}
113+
return end;
114+
}
115+
92116
/**
93117
* Does a best-effort migration of Svelte code towards using runes, event attributes and render tags.
94118
* May throw an error if the code is too complex to migrate automatically.

packages/svelte/tests/migrate/samples/is-not-where-has/input.svelte

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ what if i'm talking about `:has()` in my blog?
4747
div :where(:global(.class:is(span:has(* > *)))){}
4848
div :is(:global(.class:is(span:is(:hover)), .x)){}
4949
50+
:global(button:has(.is-active)){}
51+
5052
div{
5153
p:has(&){
5254

packages/svelte/tests/migrate/samples/is-not-where-has/output.svelte

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ what if i'm talking about `:has()` in my blog?
4747
div :where(:global(.class:is(span:has(* > *)))){}
4848
div :is(:global(.class:is(span:is(:hover)), .x)){}
4949
50+
:global(button:has(.is-active)){}
51+
5052
div{
5153
p:has(:global(&)){
5254

0 commit comments

Comments
 (0)