svelte 5.56.8 → 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/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "svelte",
3
3
  "description": "Cybernetically enhanced web apps",
4
4
  "license": "MIT",
5
- "version": "5.56.8",
5
+ "version": "5.56.9",
6
6
  "type": "module",
7
7
  "types": "./types/index.d.ts",
8
8
  "engines": {
@@ -141,7 +141,8 @@ export function parseCss(source) {
141
141
  type: 'StyleSheetFile',
142
142
  start: 0,
143
143
  end: source.length,
144
- children
144
+ children,
145
+ comments: parser.css_comments
145
146
  };
146
147
  }
147
148
 
@@ -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: read_identifier(parser),
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
- parser.index += 2;
534
- while (parser.index < parser.template.length) {
535
- if (parser.template[parser.index] === '*' && parser.template[parser.index + 1] === '/') {
536
- parser.index += 2;
537
- break;
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
- /** @param {Parser} parser */
628
- function allow_comment_or_whitespace(parser) {
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.eat('/*')) {
632
- parser.read_until(REGEX_COMMENT_CLOSE);
633
- parser.eat('*/', true);
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
@@ -312,6 +312,9 @@ const css_visitors = {
312
312
  }
313
313
 
314
314
  context.next();
315
+ },
316
+ PseudoElementSelector() {
317
+ // Don't analyse these
315
318
  }
316
319
  };
317
320
 
@@ -23,6 +23,9 @@ const visitors = {
23
23
  context.next();
24
24
  }
25
25
  },
26
+ PseudoElementSelector() {
27
+ // Don't analyse these
28
+ },
26
29
  ComplexSelector(node, context) {
27
30
  if (
28
31
  !node.metadata.used &&
@@ -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