fix: handle pseudo class elements with content (#10055)

closes #9398 (the other things in that issue are already addressed)
closes #10019
pull/10056/head
Simon H 11 months ago committed by GitHub
parent 6d65b2f8ad
commit e46a71e8a3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -0,0 +1,5 @@
---
'svelte': patch
---
fix: improve pseudo class parsing

@ -0,0 +1,5 @@
---
'svelte': patch
---
fix: allow pseudo classes after `:global(..)`

@ -227,6 +227,12 @@ function read_selector(parser, inside_pseudo_class = false) {
start, start,
end: parser.index end: parser.index
}); });
// We read the inner selectors of a pseudo element to ensure it parses correctly,
// but we don't do anything with the result.
if (parser.eat('(')) {
read_selector_list(parser, true);
parser.eat(')', true);
}
} else if (parser.eat(':')) { } else if (parser.eat(':')) {
const name = read_identifier(parser); const name = read_identifier(parser);

@ -184,7 +184,9 @@ export default class Selector {
selector.name === 'global' && selector.name === 'global' &&
block.selectors.length !== 1 && block.selectors.length !== 1 &&
(i === block.selectors.length - 1 || (i === block.selectors.length - 1 ||
block.selectors.slice(i + 1).some((s) => s.type !== 'PseudoElementSelector')) block.selectors
.slice(i + 1)
.some((s) => s.type !== 'PseudoElementSelector' && s.type !== 'PseudoClassSelector'))
) { ) {
error(selector, 'invalid-css-global-selector-list'); error(selector, 'invalid-css-global-selector-list');
} }

@ -0,0 +1,18 @@
<style>
/* test that all these are parsed correctly */
::view-transition-old(x-y) {
color: red;
}
:global(::view-transition-old(x-y)) {
color: red;
}
::highlight(rainbow-color-1) {
color: red;
}
custom-element::part(foo) {
color: red;
}
::slotted(.content) {
color: red;
}
</style>

@ -0,0 +1,246 @@
{
"css": {
"type": "Style",
"start": 0,
"end": 313,
"attributes": [],
"children": [
{
"type": "Rule",
"prelude": {
"type": "SelectorList",
"start": 60,
"end": 86,
"children": [
{
"type": "Selector",
"start": 60,
"end": 86,
"children": [
{
"type": "PseudoElementSelector",
"name": "view-transition-old",
"start": 60,
"end": 81
}
]
}
]
},
"block": {
"type": "Block",
"start": 88,
"end": 109,
"children": [
{
"type": "Declaration",
"start": 92,
"end": 102,
"property": "color",
"value": "red"
}
]
},
"start": 60,
"end": 109
},
{
"type": "Rule",
"prelude": {
"type": "SelectorList",
"start": 111,
"end": 146,
"children": [
{
"type": "Selector",
"start": 111,
"end": 146,
"children": [
{
"type": "PseudoClassSelector",
"name": "global",
"args": {
"type": "SelectorList",
"start": 119,
"end": 145,
"children": [
{
"type": "Selector",
"start": 119,
"end": 145,
"children": [
{
"type": "PseudoElementSelector",
"name": "view-transition-old",
"start": 119,
"end": 140
}
]
}
]
},
"start": 111,
"end": 146
}
]
}
]
},
"block": {
"type": "Block",
"start": 148,
"end": 169,
"children": [
{
"type": "Declaration",
"start": 152,
"end": 162,
"property": "color",
"value": "red"
}
]
},
"start": 111,
"end": 169
},
{
"type": "Rule",
"prelude": {
"type": "SelectorList",
"start": 171,
"end": 199,
"children": [
{
"type": "Selector",
"start": 171,
"end": 199,
"children": [
{
"type": "PseudoElementSelector",
"name": "highlight",
"start": 171,
"end": 182
}
]
}
]
},
"block": {
"type": "Block",
"start": 200,
"end": 218,
"children": [
{
"type": "Declaration",
"start": 204,
"end": 214,
"property": "color",
"value": "red"
}
]
},
"start": 171,
"end": 218
},
{
"type": "Rule",
"prelude": {
"type": "SelectorList",
"start": 220,
"end": 245,
"children": [
{
"type": "Selector",
"start": 220,
"end": 245,
"children": [
{
"type": "TypeSelector",
"name": "custom-element",
"start": 220,
"end": 234
},
{
"type": "PseudoElementSelector",
"name": "part",
"start": 234,
"end": 240
}
]
}
]
},
"block": {
"type": "Block",
"start": 246,
"end": 264,
"children": [
{
"type": "Declaration",
"start": 250,
"end": 260,
"property": "color",
"value": "red"
}
]
},
"start": 220,
"end": 264
},
{
"type": "Rule",
"prelude": {
"type": "SelectorList",
"start": 266,
"end": 285,
"children": [
{
"type": "Selector",
"start": 266,
"end": 285,
"children": [
{
"type": "PseudoElementSelector",
"name": "slotted",
"start": 266,
"end": 275
}
]
}
]
},
"block": {
"type": "Block",
"start": 286,
"end": 304,
"children": [
{
"type": "Declaration",
"start": 290,
"end": 300,
"property": "color",
"value": "red"
}
]
},
"start": 266,
"end": 304
}
],
"content": {
"start": 7,
"end": 305,
"styles": "\n /* test that all these are parsed correctly */\n\t::view-transition-old(x-y) {\n\t\tcolor: red;\n }\n\t:global(::view-transition-old(x-y)) {\n\t\tcolor: red;\n }\n\t::highlight(rainbow-color-1) {\n\t\tcolor: red;\n\t}\n\tcustom-element::part(foo) {\n\t\tcolor: red;\n\t}\n\t::slotted(.content) {\n\t\tcolor: red;\n\t}\n"
}
},
"js": [],
"start": null,
"end": null,
"type": "Root",
"fragment": {
"type": "Fragment",
"nodes": [],
"transparent": false
},
"options": null
}

@ -3,11 +3,11 @@
"code": "invalid-css-global-placement", "code": "invalid-css-global-placement",
"message": ":global(...) can be at the start or end of a selector sequence, but not in the middle", "message": ":global(...) can be at the start or end of a selector sequence, but not in the middle",
"start": { "start": {
"line": 2, "line": 5,
"column": 6 "column": 6
}, },
"end": { "end": {
"line": 2, "line": 5,
"column": 19 "column": 19
} }
} }

@ -1,4 +1,7 @@
<style> <style>
.foo :global(.bar):first-child {
color: red;
}
.foo :global(.bar):first-child .baz { .foo :global(.bar):first-child .baz {
color: red; color: red;
} }

Loading…
Cancel
Save