svelte 5.56.7 → 5.56.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/compiler/index.js +1 -1
- package/package.json +1 -1
- package/src/compiler/index.js +2 -1
- package/src/compiler/phases/1-parse/index.js +4 -0
- package/src/compiler/phases/1-parse/read/style.js +59 -23
- package/src/compiler/phases/2-analyze/css/css-analyze.js +3 -0
- package/src/compiler/phases/2-analyze/css/css-warn.js +3 -0
- package/src/compiler/phases/3-transform/css/index.js +3 -0
- package/src/compiler/print/index.js +305 -176
- package/src/internal/client/dom/blocks/boundary.js +55 -34
- package/src/internal/client/dom/blocks/each.js +6 -2
- package/src/internal/client/dom/elements/bindings/select.js +4 -2
- package/src/version.js +1 -1
- package/types/index.d.ts +10 -0
- package/types/index.d.ts.map +1 -1
package/package.json
CHANGED
package/src/compiler/index.js
CHANGED
|
@@ -50,6 +50,9 @@ export class Parser {
|
|
|
50
50
|
/** */
|
|
51
51
|
index = 0;
|
|
52
52
|
|
|
53
|
+
/** @type {AST.CSS.CSSComment[]} */
|
|
54
|
+
css_comments = [];
|
|
55
|
+
|
|
53
56
|
/**
|
|
54
57
|
* Creates a minimal parser instance for CSS-only parsing.
|
|
55
58
|
* Skips Svelte component parsing setup.
|
|
@@ -61,6 +64,7 @@ export class Parser {
|
|
|
61
64
|
parser.template = source;
|
|
62
65
|
parser.index = 0;
|
|
63
66
|
parser.loose = false;
|
|
67
|
+
parser.css_comments = [];
|
|
64
68
|
return parser;
|
|
65
69
|
}
|
|
66
70
|
|
|
@@ -24,6 +24,7 @@ const REGEX_HTML_COMMENT_CLOSE = /-->/;
|
|
|
24
24
|
*/
|
|
25
25
|
export default function read_style(parser, start, attributes) {
|
|
26
26
|
const content_start = parser.index;
|
|
27
|
+
parser.css_comments = [];
|
|
27
28
|
const children = read_body(parser, (p) => p.match('</style') || p.index >= p.template.length);
|
|
28
29
|
const content_end = parser.index;
|
|
29
30
|
|
|
@@ -36,6 +37,7 @@ export default function read_style(parser, start, attributes) {
|
|
|
36
37
|
end: parser.index,
|
|
37
38
|
attributes,
|
|
38
39
|
children,
|
|
40
|
+
comments: parser.css_comments,
|
|
39
41
|
content: {
|
|
40
42
|
start: content_start,
|
|
41
43
|
end: content_end,
|
|
@@ -229,18 +231,22 @@ function read_selector(parser, inside_pseudo_class = false) {
|
|
|
229
231
|
end: parser.index
|
|
230
232
|
});
|
|
231
233
|
} else if (parser.eat('::')) {
|
|
234
|
+
const name = read_identifier(parser);
|
|
235
|
+
/** @type {AST.CSS.SelectorList | null} */
|
|
236
|
+
let args = null;
|
|
237
|
+
|
|
238
|
+
if (parser.eat('(')) {
|
|
239
|
+
args = read_selector_list(parser, true);
|
|
240
|
+
parser.eat(')', true);
|
|
241
|
+
}
|
|
242
|
+
|
|
232
243
|
relative_selector.selectors.push({
|
|
233
244
|
type: 'PseudoElementSelector',
|
|
234
|
-
name
|
|
245
|
+
name,
|
|
235
246
|
start,
|
|
236
|
-
end: parser.index
|
|
247
|
+
end: parser.index,
|
|
248
|
+
...(args && { args })
|
|
237
249
|
});
|
|
238
|
-
// We read the inner selectors of a pseudo element to ensure it parses correctly,
|
|
239
|
-
// but we don't do anything with the result.
|
|
240
|
-
if (parser.eat('(')) {
|
|
241
|
-
read_selector_list(parser, true);
|
|
242
|
-
parser.eat(')', true);
|
|
243
|
-
}
|
|
244
250
|
} else if (parser.eat(':')) {
|
|
245
251
|
const name = read_identifier(parser);
|
|
246
252
|
|
|
@@ -323,7 +329,7 @@ function read_selector(parser, inside_pseudo_class = false) {
|
|
|
323
329
|
}
|
|
324
330
|
|
|
325
331
|
const index = parser.index;
|
|
326
|
-
allow_comment_or_whitespace(parser);
|
|
332
|
+
allow_comment_or_whitespace(parser, false);
|
|
327
333
|
|
|
328
334
|
if (parser.match(',') || (inside_pseudo_class ? parser.match(')') : parser.match('{'))) {
|
|
329
335
|
// rewind, so we know whether to continue building the selector list
|
|
@@ -449,7 +455,7 @@ function read_block_item(parser) {
|
|
|
449
455
|
// read ahead to understand whether we're dealing with a declaration or a nested rule.
|
|
450
456
|
// this involves some duplicated work, but avoids a try-catch that would disguise errors
|
|
451
457
|
const start = parser.index;
|
|
452
|
-
read_value(parser);
|
|
458
|
+
read_value(parser, false);
|
|
453
459
|
const char = parser.template[parser.index];
|
|
454
460
|
parser.index = start;
|
|
455
461
|
|
|
@@ -492,10 +498,13 @@ function read_declaration(parser) {
|
|
|
492
498
|
|
|
493
499
|
/**
|
|
494
500
|
* @param {Parser} parser
|
|
501
|
+
* @param {boolean} [capture_comments]
|
|
495
502
|
* @returns {string}
|
|
496
503
|
*/
|
|
497
|
-
function read_value(parser) {
|
|
504
|
+
function read_value(parser, capture_comments = true) {
|
|
498
505
|
let value = '';
|
|
506
|
+
/** @type {AST.CSS.CSSComment[]} */
|
|
507
|
+
const value_comments = [];
|
|
499
508
|
let escaped = false;
|
|
500
509
|
let in_url = false;
|
|
501
510
|
|
|
@@ -523,6 +532,13 @@ function read_value(parser) {
|
|
|
523
532
|
} else if (char === '(' && value.slice(-3) === 'url') {
|
|
524
533
|
in_url = true;
|
|
525
534
|
} else if ((char === ';' || char === '{' || char === '}') && !in_url && !quote_mark) {
|
|
535
|
+
const leading_whitespace = value.length - value.trimStart().length;
|
|
536
|
+
for (const comment of value_comments) {
|
|
537
|
+
comment.position = Math.max(
|
|
538
|
+
0,
|
|
539
|
+
/** @type {number} */ (comment.position) - leading_whitespace
|
|
540
|
+
);
|
|
541
|
+
}
|
|
526
542
|
return value.trim();
|
|
527
543
|
} else if (
|
|
528
544
|
char === '/' &&
|
|
@@ -530,13 +546,11 @@ function read_value(parser) {
|
|
|
530
546
|
!quote_mark &&
|
|
531
547
|
parser.template[parser.index + 1] === '*'
|
|
532
548
|
) {
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
}
|
|
539
|
-
parser.index++;
|
|
549
|
+
const comment = read_comment(parser);
|
|
550
|
+
if (capture_comments) {
|
|
551
|
+
comment.position = value.length;
|
|
552
|
+
parser.css_comments.push(comment);
|
|
553
|
+
value_comments.push(comment);
|
|
540
554
|
}
|
|
541
555
|
continue;
|
|
542
556
|
}
|
|
@@ -624,13 +638,16 @@ function read_identifier(parser) {
|
|
|
624
638
|
return identifier;
|
|
625
639
|
}
|
|
626
640
|
|
|
627
|
-
/**
|
|
628
|
-
|
|
641
|
+
/**
|
|
642
|
+
* @param {Parser} parser
|
|
643
|
+
* @param {boolean} [capture_comments]
|
|
644
|
+
*/
|
|
645
|
+
function allow_comment_or_whitespace(parser, capture_comments = true) {
|
|
629
646
|
parser.allow_whitespace();
|
|
630
647
|
while (parser.match('/*') || parser.match('<!--')) {
|
|
631
|
-
if (parser.
|
|
632
|
-
parser
|
|
633
|
-
parser.
|
|
648
|
+
if (parser.match('/*')) {
|
|
649
|
+
const comment = read_comment(parser);
|
|
650
|
+
if (capture_comments) parser.css_comments.push(comment);
|
|
634
651
|
}
|
|
635
652
|
|
|
636
653
|
if (parser.eat('<!--')) {
|
|
@@ -642,6 +659,25 @@ function allow_comment_or_whitespace(parser) {
|
|
|
642
659
|
}
|
|
643
660
|
}
|
|
644
661
|
|
|
662
|
+
/**
|
|
663
|
+
* @param {Parser} parser
|
|
664
|
+
* @returns {AST.CSS.CSSComment}
|
|
665
|
+
*/
|
|
666
|
+
function read_comment(parser) {
|
|
667
|
+
const start = parser.index;
|
|
668
|
+
parser.eat('/*', true);
|
|
669
|
+
const value = parser.read_until(REGEX_COMMENT_CLOSE);
|
|
670
|
+
parser.eat('*/', true);
|
|
671
|
+
const end = parser.index;
|
|
672
|
+
|
|
673
|
+
return {
|
|
674
|
+
type: 'CSSComment',
|
|
675
|
+
value,
|
|
676
|
+
start,
|
|
677
|
+
end
|
|
678
|
+
};
|
|
679
|
+
}
|
|
680
|
+
|
|
645
681
|
/**
|
|
646
682
|
* Parse standalone CSS content (not wrapped in `<style>`).
|
|
647
683
|
* @param {Parser} parser
|
|
@@ -374,6 +374,9 @@ const visitors = {
|
|
|
374
374
|
if (node.name === 'is' || node.name === 'where' || node.name === 'has' || node.name === 'not') {
|
|
375
375
|
context.next();
|
|
376
376
|
}
|
|
377
|
+
},
|
|
378
|
+
PseudoElementSelector() {
|
|
379
|
+
// Functional pseudo-element arguments are not scoped as selectors.
|
|
377
380
|
}
|
|
378
381
|
};
|
|
379
382
|
|