From 0d5e05af56663b61bdf1076aa6afccd0cd2e80b9 Mon Sep 17 00:00:00 2001 From: navorite Date: Tue, 2 Jan 2024 16:13:26 +0200 Subject: [PATCH 1/2] fix: improve pseudo elements parsing --- .../src/compiler/phases/1-parse/read/style.js | 14 ++++---------- packages/svelte/src/compiler/types/css.d.ts | 1 + .../css-psuedo-element-selector/input.svelte | 5 +++++ 3 files changed, 10 insertions(+), 10 deletions(-) create mode 100644 packages/svelte/tests/parser-modern/samples/css-psuedo-element-selector/input.svelte diff --git a/packages/svelte/src/compiler/phases/1-parse/read/style.js b/packages/svelte/src/compiler/phases/1-parse/read/style.js index 8b1d78544636..7de95e80910b 100644 --- a/packages/svelte/src/compiler/phases/1-parse/read/style.js +++ b/packages/svelte/src/compiler/phases/1-parse/read/style.js @@ -219,28 +219,22 @@ function read_selector(parser, inside_pseudo_class = false) { start, end: parser.index }); - } else if (parser.eat('::')) { - children.push({ - type: 'PseudoElementSelector', - name: read_identifier(parser), - start, - end: parser.index - }); } else if (parser.eat(':')) { + const psuedo_element = parser.eat(':'); + const name = read_identifier(parser); - /** @type {null | import('#compiler').Css.SelectorList} */ let args = null; if (parser.eat('(')) { args = read_selector_list(parser, true); parser.eat(')', true); - } else if (name === 'global') { + } else if (!psuedo_element && name === 'global') { error(parser.index, 'invalid-css-global-selector'); } children.push({ - type: 'PseudoClassSelector', + type: psuedo_element ? 'PseudoElementSelector' : 'PseudoClassSelector', name, args, start, diff --git a/packages/svelte/src/compiler/types/css.d.ts b/packages/svelte/src/compiler/types/css.d.ts index 49a3fc514379..8d91c01a1bf3 100644 --- a/packages/svelte/src/compiler/types/css.d.ts +++ b/packages/svelte/src/compiler/types/css.d.ts @@ -54,6 +54,7 @@ export interface AttributeSelector extends BaseNode { export interface PseudoElementSelector extends BaseNode { type: 'PseudoElementSelector'; name: string; + args: SelectorList | null; } export interface PseudoClassSelector extends BaseNode { diff --git a/packages/svelte/tests/parser-modern/samples/css-psuedo-element-selector/input.svelte b/packages/svelte/tests/parser-modern/samples/css-psuedo-element-selector/input.svelte new file mode 100644 index 000000000000..a511a7305fce --- /dev/null +++ b/packages/svelte/tests/parser-modern/samples/css-psuedo-element-selector/input.svelte @@ -0,0 +1,5 @@ + From 6d1a676bff00ae0c1a1c1af44aa499a60777c33c Mon Sep 17 00:00:00 2001 From: navorite Date: Tue, 2 Jan 2024 16:15:24 +0200 Subject: [PATCH 2/2] changeset and test output --- .changeset/metal-beers-learn.md | 5 + .../css-psuedo-element-selector/output.json | 91 +++++++++++++++++++ 2 files changed, 96 insertions(+) create mode 100644 .changeset/metal-beers-learn.md create mode 100644 packages/svelte/tests/parser-modern/samples/css-psuedo-element-selector/output.json diff --git a/.changeset/metal-beers-learn.md b/.changeset/metal-beers-learn.md new file mode 100644 index 000000000000..87ea21a097b5 --- /dev/null +++ b/.changeset/metal-beers-learn.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +fix: improve pseudo elements parsing diff --git a/packages/svelte/tests/parser-modern/samples/css-psuedo-element-selector/output.json b/packages/svelte/tests/parser-modern/samples/css-psuedo-element-selector/output.json new file mode 100644 index 000000000000..1e981f9f8e6d --- /dev/null +++ b/packages/svelte/tests/parser-modern/samples/css-psuedo-element-selector/output.json @@ -0,0 +1,91 @@ +{ + "css": { + "type": "Style", + "start": 0, + "end": 165, + "attributes": [], + "children": [ + { + "type": "Rule", + "prelude": { + "type": "SelectorList", + "start": 9, + "end": 38, + "children": [ + { + "type": "Selector", + "start": 9, + "end": 38, + "children": [ + { + "type": "PseudoClassSelector", + "name": "root", + "args": null, + "start": 9, + "end": 14 + }, + { + "type": "PseudoElementSelector", + "name": "view-transition-old", + "args": { + "type": "SelectorList", + "start": 36, + "end": 37, + "children": [ + { + "type": "Selector", + "start": 36, + "end": 37, + "children": [ + { + "type": "TypeSelector", + "name": "*", + "start": 36, + "end": 37 + } + ] + } + ] + }, + "start": 14, + "end": 38 + } + ] + } + ] + }, + "block": { + "type": "Block", + "start": 39, + "end": 156, + "children": [ + { + "type": "Declaration", + "start": 42, + "end": 153, + "property": "animation", + "value": "90ms cubic-bezier(0.4, 0, 1, 1) both fade-out, 300ms cubic-bezier(0.4, 0, 0.2, 1) both slide-to-left" + } + ] + }, + "start": 9, + "end": 156 + } + ], + "content": { + "start": 7, + "end": 157, + "styles": "\n\t:root::view-transition-old(*) {\n\tanimation: 90ms cubic-bezier(0.4, 0, 1, 1) both fade-out, 300ms cubic-bezier(0.4, 0, 0.2, 1) both slide-to-left;\n}\n" + } + }, + "js": [], + "start": null, + "end": null, + "type": "Root", + "fragment": { + "type": "Fragment", + "nodes": [], + "transparent": false + }, + "options": null +} \ No newline at end of file