fix: allow `:global(..)` in compound selectors (#10266)

Someone could programmatically add a class to an element and Svelte doesn't see it, so having global be part of a modifier is necessary so that Svelte doesn't mark it as unused
fixes #10210
pull/10267/head
Simon H 8 months ago committed by GitHub
parent 6b0bd8b23a
commit 036e88f1f7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -0,0 +1,5 @@
---
"svelte": patch
---
fix: allow `:global(..)` in compound selectors

@ -100,7 +100,7 @@ const css = {
`:global(...) can be at the start or end of a selector sequence, but not in the middle`,
'invalid-css-global-selector': () => `:global(...) must contain exactly one selector`,
'invalid-css-global-selector-list': () =>
`:global(...) cannot be used to modify a selector, or be modified by another selector`,
`:global(...) must not contain type or universal selectors when used in a compound selector`,
'invalid-css-selector': () => `Invalid selector`,
'invalid-css-identifier': () => 'Expected a valid CSS identifier'
};
@ -447,19 +447,6 @@ const errors = {
// code: 'illegal-variable-declaration',
// message: 'Cannot declare same variable name which is imported inside <script context="module">'
// },
// css_invalid_global_selector: {
// code: 'css-invalid-global-selector',
// message: ':global(...) must contain a single selector'
// },
// css_invalid_global_selector_position: {
// code: 'css-invalid-global-selector-position',
// message:
// ':global(...) not at the start of a selector sequence should not contain type or universal selectors'
// },
// css_invalid_selector: /** @param {string} selector */ (selector) => ({
// code: 'css-invalid-selector',
// message: `Invalid selector "${selector}"`
// }),
// invalid_directive_value: {
// code: 'invalid-directive-value',
// message:

@ -177,18 +177,15 @@ export default class Selector {
validate_global_compound_selector() {
for (const block of this.blocks) {
if (block.selectors.length === 1) continue;
for (let i = 0; i < block.selectors.length; i++) {
const selector = block.selectors[i];
if (
selector.type === 'PseudoClassSelector' &&
selector.name === 'global' &&
block.selectors.length !== 1 &&
(i === block.selectors.length - 1 ||
block.selectors
.slice(i + 1)
.some((s) => s.type !== 'PseudoElementSelector' && s.type !== 'PseudoClassSelector'))
) {
error(selector, 'invalid-css-global-selector-list');
if (selector.type === 'PseudoClassSelector' && selector.name === 'global') {
const child = selector.args?.children[0].children[0];
if (child?.type === 'TypeSelector' && !/[.:#]/.test(child.name[0])) {
error(selector, 'invalid-css-global-selector-list');
}
}
}
}

@ -0,0 +1,5 @@
import { test } from '../../test';
export default test({
warnings: []
});

@ -0,0 +1,9 @@
div.svelte-xyz.blue {
color: blue;
}
span.blue.x.svelte-xyz {
color: blue;
}
span.x.svelte-xyz.bg {
background: red;
}

@ -0,0 +1,2 @@
<div class="svelte-xyz">someone could programmatically add a class to this, so having global be part of a modifier is necessary</div>
<span class="x svelte-xyz">-</span>

@ -0,0 +1,14 @@
<div>someone could programmatically add a class to this, so having global be part of a modifier is necessary</div>
<span class="x">-</span>
<style>
div:global(.blue) {
color: blue;
}
span:global(.blue).x {
color: blue;
}
span.x:global(.bg) {
background: red;
}
</style>

@ -1,7 +1,7 @@
[
{
"code": "invalid-css-global-selector-list",
"message": ":global(...) cannot be used to modify a selector, or be modified by another selector",
"message": ":global(...) must not contain type or universal selectors when used in a compound selector",
"start": {
"line": 2,
"column": 5

@ -1,7 +1,7 @@
[
{
"code": "invalid-css-global-selector-list",
"message": ":global(...) cannot be used to modify a selector, or be modified by another selector",
"message": ":global(...) must not contain type or universal selectors when used in a compound selector",
"start": {
"line": 2,
"column": 5

@ -76,7 +76,7 @@ Assignments to destructured parts of a `@const` declaration are no longer allowe
### Stricter CSS `:global` selector validation
Previously, a selector like `.foo :global(bar).baz` was valid. In Svelte 5, this is a validation error instead. The reason is that in this selector the resulting CSS would be equivalent to one without `:global` - in other words, `:global` is ignored in this case.
Previously, a compound selector starting with a global modifier which has universal or type selectors (like `:global(span).foo`) was valid. In Svelte 5, this is a validation error instead. The reason is that in this selector the resulting CSS would be equivalent to one without `:global` - in other words, `:global` is ignored in this case.
### CSS hash position no longer deterministic

Loading…
Cancel
Save