svelte 4.2.1 → 4.2.3

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.cjs CHANGED
@@ -15558,7 +15558,7 @@ var compiler_warnings = {
15558
15558
  a11y_click_events_have_key_events: {
15559
15559
  code: 'a11y-click-events-have-key-events',
15560
15560
  message:
15561
- 'A11y: visible, non-interactive elements with an on:click event must be accompanied by an on:keydown, on:keyup, or on:keypress event.'
15561
+ 'A11y: visible, non-interactive elements with an on:click event must be accompanied by a keyboard event handler. Consider whether an interactive element such as <button type="button"> or <a> might be more appropriate. See https://svelte.dev/docs/accessibility-warnings#a11y-click-events-have-key-events for more details.'
15562
15562
  },
15563
15563
  a11y_missing_content: /** @param {string} name */ (name) => ({
15564
15564
  code: 'a11y-missing-content',
@@ -15707,7 +15707,7 @@ function is_dynamic$1(variable) {
15707
15707
  return false;
15708
15708
  }
15709
15709
 
15710
- function nodes_match(a, b) {
15710
+ function nodes_match(a, b, ignoreKeys = []) {
15711
15711
  if (!!a !== !!b) return false;
15712
15712
  if (Array.isArray(a) !== Array.isArray(b)) return false;
15713
15713
 
@@ -15717,8 +15717,12 @@ function nodes_match(a, b) {
15717
15717
  return a.every((child, i) => nodes_match(child, b[i]));
15718
15718
  }
15719
15719
 
15720
- const a_keys = Object.keys(a).sort();
15721
- const b_keys = Object.keys(b).sort();
15720
+ const a_keys = Object.keys(a)
15721
+ .sort()
15722
+ .filter((key) => !ignoreKeys.includes(key));
15723
+ const b_keys = Object.keys(b)
15724
+ .sort()
15725
+ .filter((key) => !ignoreKeys.includes(key));
15722
15726
 
15723
15727
  if (a_keys.length !== b_keys.length) return false;
15724
15728
 
@@ -15789,7 +15793,7 @@ function invalidate(renderer, scope, node, names, main_execution_context = false
15789
15793
  if (
15790
15794
  node.type === 'AssignmentExpression' &&
15791
15795
  node.operator === '=' &&
15792
- nodes_match(node.left, node.right) &&
15796
+ nodes_match(node.left, node.right, ['trailingComments', 'leadingComments']) &&
15793
15797
  tail.length === 0
15794
15798
  ) {
15795
15799
  return get_invalidated(head, node);
@@ -31491,8 +31495,8 @@ class AttributeWrapper extends BaseAttributeWrapper {
31491
31495
  this.parent.has_dynamic_value = true;
31492
31496
  }
31493
31497
  }
31494
- if (this.parent.node.namespace == namespaces.foreign) {
31495
- // leave attribute case alone for elements in the "foreign" namespace
31498
+ if (this.parent.node.namespace == namespaces.foreign || this.parent.node.name.includes('-')) {
31499
+ // leave attribute case alone for elements in the "foreign" namespace and for custom elements
31496
31500
  this.name = this.node.name;
31497
31501
  this.metadata = this.get_metadata();
31498
31502
  this.is_indirectly_bound_value = false;
@@ -41029,6 +41033,13 @@ class Chunk {
41029
41033
  this.end = index;
41030
41034
 
41031
41035
  if (this.edited) {
41036
+ // after split we should save the edit content record into the correct chunk
41037
+ // to make sure sourcemap correct
41038
+ // For example:
41039
+ // ' test'.trim()
41040
+ // split -> ' ' + 'test'
41041
+ // ✔️ edit -> '' + 'test'
41042
+ // ✖️ edit -> 'test' + ''
41032
41043
  // TODO is this block necessary?...
41033
41044
  newChunk.edit('', false);
41034
41045
  this.content = '';
@@ -41057,6 +41068,10 @@ class Chunk {
41057
41068
  if (trimmed.length) {
41058
41069
  if (trimmed !== this.content) {
41059
41070
  this.split(this.start + trimmed.length).edit('', undefined, true);
41071
+ if (this.edited) {
41072
+ // save the change, if it has been edited
41073
+ this.edit(trimmed, this.storeName, true);
41074
+ }
41060
41075
  }
41061
41076
  return true;
41062
41077
  } else {
@@ -41075,7 +41090,11 @@ class Chunk {
41075
41090
 
41076
41091
  if (trimmed.length) {
41077
41092
  if (trimmed !== this.content) {
41078
- this.split(this.end - trimmed.length);
41093
+ const newChunk = this.split(this.end - trimmed.length);
41094
+ if (this.edited) {
41095
+ // save the change, if it has been edited
41096
+ newChunk.edit(trimmed, this.storeName, true);
41097
+ }
41079
41098
  this.edit('', undefined, true);
41080
41099
  }
41081
41100
  return true;
@@ -41088,7 +41107,7 @@ class Chunk {
41088
41107
  }
41089
41108
  }
41090
41109
 
41091
- function getBtoa () {
41110
+ function getBtoa() {
41092
41111
  if (typeof window !== 'undefined' && typeof window.btoa === 'function') {
41093
41112
  return (str) => window.btoa(unescape(encodeURIComponent(str)));
41094
41113
  } else if (typeof Buffer === 'function') {
@@ -41201,6 +41220,8 @@ function getLocator(source) {
41201
41220
  };
41202
41221
  }
41203
41222
 
41223
+ const wordRegex = /\w/;
41224
+
41204
41225
  class Mappings {
41205
41226
  constructor(hires) {
41206
41227
  this.hires = hires;
@@ -41213,26 +41234,64 @@ class Mappings {
41213
41234
 
41214
41235
  addEdit(sourceIndex, content, loc, nameIndex) {
41215
41236
  if (content.length) {
41237
+ let contentLineEnd = content.indexOf('\n', 0);
41238
+ let previousContentLineEnd = -1;
41239
+ while (contentLineEnd >= 0) {
41240
+ const segment = [this.generatedCodeColumn, sourceIndex, loc.line, loc.column];
41241
+ if (nameIndex >= 0) {
41242
+ segment.push(nameIndex);
41243
+ }
41244
+ this.rawSegments.push(segment);
41245
+
41246
+ this.generatedCodeLine += 1;
41247
+ this.raw[this.generatedCodeLine] = this.rawSegments = [];
41248
+ this.generatedCodeColumn = 0;
41249
+
41250
+ previousContentLineEnd = contentLineEnd;
41251
+ contentLineEnd = content.indexOf('\n', contentLineEnd + 1);
41252
+ }
41253
+
41216
41254
  const segment = [this.generatedCodeColumn, sourceIndex, loc.line, loc.column];
41217
41255
  if (nameIndex >= 0) {
41218
41256
  segment.push(nameIndex);
41219
41257
  }
41220
41258
  this.rawSegments.push(segment);
41259
+
41260
+ this.advance(content.slice(previousContentLineEnd + 1));
41221
41261
  } else if (this.pending) {
41222
41262
  this.rawSegments.push(this.pending);
41263
+ this.advance(content);
41223
41264
  }
41224
41265
 
41225
- this.advance(content);
41226
41266
  this.pending = null;
41227
41267
  }
41228
41268
 
41229
41269
  addUneditedChunk(sourceIndex, chunk, original, loc, sourcemapLocations) {
41230
41270
  let originalCharIndex = chunk.start;
41231
41271
  let first = true;
41272
+ // when iterating each char, check if it's in a word boundary
41273
+ let charInHiresBoundary = false;
41232
41274
 
41233
41275
  while (originalCharIndex < chunk.end) {
41234
41276
  if (this.hires || first || sourcemapLocations.has(originalCharIndex)) {
41235
- this.rawSegments.push([this.generatedCodeColumn, sourceIndex, loc.line, loc.column]);
41277
+ const segment = [this.generatedCodeColumn, sourceIndex, loc.line, loc.column];
41278
+
41279
+ if (this.hires === 'boundary') {
41280
+ // in hires "boundary", group segments per word boundary than per char
41281
+ if (wordRegex.test(original[originalCharIndex])) {
41282
+ // for first char in the boundary found, start the boundary by pushing a segment
41283
+ if (!charInHiresBoundary) {
41284
+ this.rawSegments.push(segment);
41285
+ charInHiresBoundary = true;
41286
+ }
41287
+ } else {
41288
+ // for non-word char, end the boundary by pushing a segment
41289
+ this.rawSegments.push(segment);
41290
+ charInHiresBoundary = false;
41291
+ }
41292
+ } else {
41293
+ this.rawSegments.push(segment);
41294
+ }
41236
41295
  }
41237
41296
 
41238
41297
  if (original[originalCharIndex] === '\n') {
@@ -41405,7 +41464,7 @@ class MagicString {
41405
41464
  sourceIndex,
41406
41465
  chunk.content,
41407
41466
  loc,
41408
- chunk.storeName ? names.indexOf(chunk.original) : -1
41467
+ chunk.storeName ? names.indexOf(chunk.original) : -1,
41409
41468
  );
41410
41469
  } else {
41411
41470
  mappings.addUneditedChunk(sourceIndex, chunk, this.original, loc, this.sourcemapLocations);
@@ -41416,11 +41475,13 @@ class MagicString {
41416
41475
 
41417
41476
  return {
41418
41477
  file: options.file ? options.file.split(/[/\\]/).pop() : undefined,
41419
- sources: [options.source ? getRelativePath(options.file || '', options.source) : (options.file || '')],
41478
+ sources: [
41479
+ options.source ? getRelativePath(options.file || '', options.source) : options.file || '',
41480
+ ],
41420
41481
  sourcesContent: options.includeContent ? [this.original] : undefined,
41421
41482
  names,
41422
41483
  mappings: mappings.raw,
41423
- x_google_ignoreList: this.ignoreList ? [sourceIndex] : undefined
41484
+ x_google_ignoreList: this.ignoreList ? [sourceIndex] : undefined,
41424
41485
  };
41425
41486
  }
41426
41487
 
@@ -41534,14 +41595,14 @@ class MagicString {
41534
41595
 
41535
41596
  insert() {
41536
41597
  throw new Error(
41537
- 'magicString.insert(...) is deprecated. Use prependRight(...) or appendLeft(...)'
41598
+ 'magicString.insert(...) is deprecated. Use prependRight(...) or appendLeft(...)',
41538
41599
  );
41539
41600
  }
41540
41601
 
41541
41602
  insertLeft(index, content) {
41542
41603
  if (!warned.insertLeft) {
41543
41604
  console.warn(
41544
- 'magicString.insertLeft(...) is deprecated. Use magicString.appendLeft(...) instead'
41605
+ 'magicString.insertLeft(...) is deprecated. Use magicString.appendLeft(...) instead',
41545
41606
  ); // eslint-disable-line no-console
41546
41607
  warned.insertLeft = true;
41547
41608
  }
@@ -41552,7 +41613,7 @@ class MagicString {
41552
41613
  insertRight(index, content) {
41553
41614
  if (!warned.insertRight) {
41554
41615
  console.warn(
41555
- 'magicString.insertRight(...) is deprecated. Use magicString.prependRight(...) instead'
41616
+ 'magicString.insertRight(...) is deprecated. Use magicString.prependRight(...) instead',
41556
41617
  ); // eslint-disable-line no-console
41557
41618
  warned.insertRight = true;
41558
41619
  }
@@ -41611,7 +41672,7 @@ class MagicString {
41611
41672
  if (end > this.original.length) throw new Error('end is out of bounds');
41612
41673
  if (start === end)
41613
41674
  throw new Error(
41614
- 'Cannot overwrite a zero-length range – use appendLeft or prependRight instead'
41675
+ 'Cannot overwrite a zero-length range – use appendLeft or prependRight instead',
41615
41676
  );
41616
41677
 
41617
41678
  this._split(start);
@@ -41620,7 +41681,7 @@ class MagicString {
41620
41681
  if (options === true) {
41621
41682
  if (!warned.storeName) {
41622
41683
  console.warn(
41623
- 'The final argument to magicString.overwrite(...) should be an options object. See https://github.com/rich-harris/magic-string'
41684
+ 'The final argument to magicString.overwrite(...) should be an options object. See https://github.com/rich-harris/magic-string',
41624
41685
  ); // eslint-disable-line no-console
41625
41686
  warned.storeName = true;
41626
41687
  }
@@ -41842,7 +41903,7 @@ class MagicString {
41842
41903
  // zero-length edited chunks are a special case (overlapping replacements)
41843
41904
  const loc = getLocator(this.original)(index);
41844
41905
  throw new Error(
41845
- `Cannot split a chunk that has already been edited (${loc.line}:${loc.column} – "${chunk.original}")`
41906
+ `Cannot split a chunk that has already been edited (${loc.line}:${loc.column} – "${chunk.original}")`,
41846
41907
  );
41847
41908
  }
41848
41909
 
@@ -42001,7 +42062,7 @@ class MagicString {
42001
42062
  this.overwrite(
42002
42063
  match.index,
42003
42064
  match.index + match[0].length,
42004
- getReplacement(match, this.original)
42065
+ getReplacement(match, this.original),
42005
42066
  );
42006
42067
  });
42007
42068
  } else {
@@ -42010,7 +42071,7 @@ class MagicString {
42010
42071
  this.overwrite(
42011
42072
  match.index,
42012
42073
  match.index + match[0].length,
42013
- getReplacement(match, this.original)
42074
+ getReplacement(match, this.original),
42014
42075
  );
42015
42076
  }
42016
42077
  return this;
@@ -42056,7 +42117,7 @@ class MagicString {
42056
42117
 
42057
42118
  if (!searchValue.global) {
42058
42119
  throw new TypeError(
42059
- 'MagicString.prototype.replaceAll called with a non-global RegExp argument'
42120
+ 'MagicString.prototype.replaceAll called with a non-global RegExp argument',
42060
42121
  );
42061
42122
  }
42062
42123
 
@@ -43575,7 +43636,7 @@ function is_used_as_reference(node, parent) {
43575
43636
  * https://svelte.dev/docs/svelte-compiler#svelte-version
43576
43637
  * @type {string}
43577
43638
  */
43578
- const VERSION = '4.2.1';
43639
+ const VERSION = '4.2.3';
43579
43640
 
43580
43641
  const regex_leading_directory_separator = /^[/\\]/;
43581
43642
  const regex_starts_with_term_export = /^Export/;
package/elements.d.ts CHANGED
@@ -486,7 +486,7 @@ export interface HTMLAttributes<T extends EventTarget> extends AriaAttributes, D
486
486
  accesskey?: string | undefined | null;
487
487
  autofocus?: boolean | undefined | null;
488
488
  class?: string | undefined | null;
489
- contenteditable?: Booleanish | 'inherit' | undefined | null;
489
+ contenteditable?: Booleanish | 'inherit' | 'plaintext-only' | undefined | null;
490
490
  contextmenu?: string | undefined | null;
491
491
  dir?: string | undefined | null;
492
492
  draggable?: Booleanish | undefined | null;
@@ -1405,6 +1405,7 @@ export interface SVGAttributes<T extends EventTarget> extends AriaAttributes, DO
1405
1405
  'text-rendering'?: number | string | undefined | null;
1406
1406
  to?: number | string | undefined | null;
1407
1407
  transform?: string | undefined | null;
1408
+ 'transform-origin'?: string | undefined | null;
1408
1409
  u1?: number | string | undefined | null;
1409
1410
  u2?: number | string | undefined | null;
1410
1411
  'underline-position'?: number | string | undefined | null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "svelte",
3
- "version": "4.2.1",
3
+ "version": "4.2.3",
4
4
  "description": "Cybernetically enhanced web apps",
5
5
  "type": "module",
6
6
  "module": "src/runtime/index.js",
@@ -102,7 +102,7 @@
102
102
  "estree-walker": "^3.0.3",
103
103
  "is-reference": "^3.0.1",
104
104
  "locate-character": "^3.0.0",
105
- "magic-string": "^0.30.0",
105
+ "magic-string": "^0.30.4",
106
106
  "periscopic": "^3.1.0"
107
107
  },
108
108
  "devDependencies": {
@@ -119,7 +119,7 @@
119
119
  "esbuild": "^0.18.11",
120
120
  "eslint-plugin-lube": "^0.1.7",
121
121
  "happy-dom": "^9.20.3",
122
- "jsdom": "^21.1.2",
122
+ "jsdom": "22.0.0",
123
123
  "kleur": "^4.1.5",
124
124
  "rollup": "^3.26.2",
125
125
  "source-map": "^0.7.4",
@@ -271,7 +271,7 @@ export default {
271
271
  a11y_click_events_have_key_events: {
272
272
  code: 'a11y-click-events-have-key-events',
273
273
  message:
274
- 'A11y: visible, non-interactive elements with an on:click event must be accompanied by an on:keydown, on:keyup, or on:keypress event.'
274
+ 'A11y: visible, non-interactive elements with an on:click event must be accompanied by a keyboard event handler. Consider whether an interactive element such as <button type="button"> or <a> might be more appropriate. See https://svelte.dev/docs/accessibility-warnings#a11y-click-events-have-key-events for more details.'
275
275
  },
276
276
  a11y_missing_content: /** @param {string} name */ (name) => ({
277
277
  code: 'a11y-missing-content',
@@ -50,7 +50,7 @@ export function invalidate(renderer, scope, node, names, main_execution_context
50
50
  if (
51
51
  node.type === 'AssignmentExpression' &&
52
52
  node.operator === '=' &&
53
- nodes_match(node.left, node.right) &&
53
+ nodes_match(node.left, node.right, ['trailingComments', 'leadingComments']) &&
54
54
  tail.length === 0
55
55
  ) {
56
56
  return get_invalidated(head, node);
@@ -103,8 +103,8 @@ export default class AttributeWrapper extends BaseAttributeWrapper {
103
103
  this.parent.has_dynamic_value = true;
104
104
  }
105
105
  }
106
- if (this.parent.node.namespace == namespaces.foreign) {
107
- // leave attribute case alone for elements in the "foreign" namespace
106
+ if (this.parent.node.namespace == namespaces.foreign || this.parent.node.name.includes('-')) {
107
+ // leave attribute case alone for elements in the "foreign" namespace and for custom elements
108
108
  this.name = this.node.name;
109
109
  this.metadata = this.get_metadata();
110
110
  this.is_indirectly_bound_value = false;
@@ -1,4 +1,4 @@
1
- export function nodes_match(a, b) {
1
+ export function nodes_match(a, b, ignoreKeys = []) {
2
2
  if (!!a !== !!b) return false;
3
3
  if (Array.isArray(a) !== Array.isArray(b)) return false;
4
4
 
@@ -8,8 +8,12 @@ export function nodes_match(a, b) {
8
8
  return a.every((child, i) => nodes_match(child, b[i]));
9
9
  }
10
10
 
11
- const a_keys = Object.keys(a).sort();
12
- const b_keys = Object.keys(b).sort();
11
+ const a_keys = Object.keys(a)
12
+ .sort()
13
+ .filter((key) => !ignoreKeys.includes(key));
14
+ const b_keys = Object.keys(b)
15
+ .sort()
16
+ .filter((key) => !ignoreKeys.includes(key));
13
17
 
14
18
  if (a_keys.length !== b_keys.length) return false;
15
19
 
@@ -50,7 +50,7 @@ export interface ActionReturn<
50
50
  * // ...
51
51
  * }
52
52
  * ```
53
- * `Action<HTMLDivElement>` and `Action<HTMLDiveElement, undefined>` both signal that the action accepts no parameters.
53
+ * `Action<HTMLDivElement>` and `Action<HTMLDivElement, undefined>` both signal that the action accepts no parameters.
54
54
  *
55
55
  * You can return an object with methods `update` and `destroy` from the function and type which additional attributes and events it has.
56
56
  * See interface `ActionReturn` for more details.
@@ -480,7 +480,10 @@ export function set_custom_element_data_map(node, data_map) {
480
480
  /**
481
481
  * @returns {void} */
482
482
  export function set_custom_element_data(node, prop, value) {
483
- if (prop in node) {
483
+ const lower = prop.toLowerCase(); // for backwards compatibility with existing behavior we do lowercase first
484
+ if (lower in node) {
485
+ node[lower] = typeof node[lower] === 'boolean' && value === '' ? true : value;
486
+ } else if (prop in node) {
484
487
  node[prop] = typeof node[prop] === 'boolean' && value === '' ? true : value;
485
488
  } else {
486
489
  attr(node, prop, value);
@@ -804,6 +807,9 @@ export function claim_html_tag(nodes, is_svg) {
804
807
  detach(html_tag_nodes[0]);
805
808
  detach(html_tag_nodes[html_tag_nodes.length - 1]);
806
809
  const claimed_nodes = html_tag_nodes.slice(1, html_tag_nodes.length - 1);
810
+ if (claimed_nodes.length === 0) {
811
+ return new HtmlTagHydration(is_svg);
812
+ }
807
813
  for (const n of claimed_nodes) {
808
814
  n.claim_order = nodes.claim_info.total_claimed;
809
815
  nodes.claim_info.total_claimed += 1;
@@ -6,5 +6,5 @@
6
6
  * https://svelte.dev/docs/svelte-compiler#svelte-version
7
7
  * @type {string}
8
8
  */
9
- export const VERSION = '4.2.1';
9
+ export const VERSION = '4.2.3';
10
10
  export const PUBLIC_VERSION = '4';
package/types/index.d.ts CHANGED
@@ -1348,7 +1348,7 @@ declare module 'svelte/action' {
1348
1348
  * // ...
1349
1349
  * }
1350
1350
  * ```
1351
- * `Action<HTMLDivElement>` and `Action<HTMLDiveElement, undefined>` both signal that the action accepts no parameters.
1351
+ * `Action<HTMLDivElement>` and `Action<HTMLDivElement, undefined>` both signal that the action accepts no parameters.
1352
1352
  *
1353
1353
  * You can return an object with methods `update` and `destroy` from the function and type which additional attributes and events it has.
1354
1354
  * See interface `ActionReturn` for more details.