Skip to content

Commit 3c6977a

Browse files
authored
fix: improve style parser whitespace handling (#10077)
allow whitespace, allow comments fixes #10073
1 parent 570884e commit 3c6977a

File tree

5 files changed

+110
-12
lines changed

5 files changed

+110
-12
lines changed

.changeset/dry-eggs-retire.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: improve style parser whitespace handling

packages/svelte/src/compiler/phases/1-parse/read/style.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ const REGEX_COMBINATOR_WHITESPACE = /^\s*(\+|~|>|\|\|)\s*/;
77
const REGEX_COMBINATOR = /^(\+|~|>|\|\|)/;
88
const REGEX_PERCENTAGE = /^\d+(\.\d+)?%/;
99
const REGEX_NTH_OF =
10-
/^\s*(even|odd|\+?(\d+|\d*n(\s*[+-]\s*\d+)?)|-\d*n(\s*\+\s*\d+))(\s*(?=[,)])|\s+of\s+)/;
10+
/^(even|odd|\+?(\d+|\d*n(\s*[+-]\s*\d+)?)|-\d*n(\s*\+\s*\d+))((?=\s*[,)])|\s+of\s+)/;
1111
const REGEX_WHITESPACE_OR_COLON = /[\s:]/;
1212
const REGEX_BRACE_OR_SEMICOLON = /[{;]/;
1313
const REGEX_LEADING_HYPHEN_OR_DIGIT = /-?\d/;
@@ -153,6 +153,8 @@ function read_selector_list(parser, inside_pseudo_class = false) {
153153
/** @type {import('#compiler').Css.Selector[]} */
154154
const children = [];
155155

156+
allow_comment_or_whitespace(parser);
157+
156158
const start = parser.index;
157159

158160
while (parser.index < parser.template.length) {
@@ -286,9 +288,10 @@ function read_selector(parser, inside_pseudo_class = false) {
286288
});
287289
} else if (inside_pseudo_class && parser.match_regex(REGEX_NTH_OF)) {
288290
// nth of matcher must come before combinator matcher to prevent collision else the '+' in '+2n-1' would be parsed as a combinator
291+
289292
children.push({
290293
type: 'Nth',
291-
value: /** @type {string} */ (parser.read(REGEX_NTH_OF)),
294+
value: /**@type {string} */ (parser.read(REGEX_NTH_OF)),
292295
start,
293296
end: parser.index
294297
});

packages/svelte/tests/parser-modern/samples/css-nth-syntax/output.json

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -495,19 +495,19 @@
495495
"name": "nth-child",
496496
"args": {
497497
"type": "SelectorList",
498-
"start": 476,
499-
"end": 491,
498+
"start": 485,
499+
"end": 486,
500500
"children": [
501501
{
502502
"type": "Selector",
503-
"start": 476,
504-
"end": 491,
503+
"start": 485,
504+
"end": 486,
505505
"children": [
506506
{
507507
"type": "Nth",
508-
"value": "\n n\n ",
509-
"start": 476,
510-
"end": 491
508+
"value": "n",
509+
"start": 485,
510+
"end": 486
511511
}
512512
]
513513
}

packages/svelte/tests/parser-modern/samples/css-pseudo-classes/input.svelte

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,10 @@
1515
::slotted(.content) {
1616
color: red;
1717
}
18+
:is( /*button*/
19+
button, /*p after h1*/
20+
h1 + p
21+
){
22+
color: red;
23+
}
1824
</style>

packages/svelte/tests/parser-modern/samples/css-pseudo-classes/output.json

Lines changed: 87 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"css": {
33
"type": "Style",
44
"start": 0,
5-
"end": 313,
5+
"end": 386,
66
"attributes": [],
77
"children": [
88
{
@@ -225,12 +225,96 @@
225225
},
226226
"start": 266,
227227
"end": 304
228+
},
229+
{
230+
"type": "Rule",
231+
"prelude": {
232+
"type": "SelectorList",
233+
"start": 306,
234+
"end": 359,
235+
"children": [
236+
{
237+
"type": "Selector",
238+
"start": 306,
239+
"end": 359,
240+
"children": [
241+
{
242+
"type": "PseudoClassSelector",
243+
"name": "is",
244+
"args": {
245+
"type": "SelectorList",
246+
"start": 324,
247+
"end": 355,
248+
"children": [
249+
{
250+
"type": "Selector",
251+
"start": 324,
252+
"end": 330,
253+
"children": [
254+
{
255+
"type": "TypeSelector",
256+
"name": "button",
257+
"start": 324,
258+
"end": 330
259+
}
260+
]
261+
},
262+
{
263+
"type": "Selector",
264+
"start": 349,
265+
"end": 355,
266+
"children": [
267+
{
268+
"type": "TypeSelector",
269+
"name": "h1",
270+
"start": 349,
271+
"end": 351
272+
},
273+
{
274+
"type": "Combinator",
275+
"name": "+",
276+
"start": 352,
277+
"end": 353
278+
},
279+
{
280+
"type": "TypeSelector",
281+
"name": "p",
282+
"start": 354,
283+
"end": 355
284+
}
285+
]
286+
}
287+
]
288+
},
289+
"start": 306,
290+
"end": 359
291+
}
292+
]
293+
}
294+
]
295+
},
296+
"block": {
297+
"type": "Block",
298+
"start": 359,
299+
"end": 377,
300+
"children": [
301+
{
302+
"type": "Declaration",
303+
"start": 363,
304+
"end": 373,
305+
"property": "color",
306+
"value": "red"
307+
}
308+
]
309+
},
310+
"start": 306,
311+
"end": 377
228312
}
229313
],
230314
"content": {
231315
"start": 7,
232-
"end": 305,
233-
"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"
316+
"end": 378,
317+
"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\t:is( /*button*/\n\t\tbutton, /*p after h1*/\n\t\th1 + p\n\t\t){\n\t\tcolor: red;\n\t}\n"
234318
}
235319
},
236320
"js": [],

0 commit comments

Comments
 (0)