svelte2tsx 0.7.50 → 0.7.51

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.
Files changed (3) hide show
  1. package/index.js +217 -43
  2. package/index.mjs +217 -43
  3. package/package.json +1 -1
package/index.js CHANGED
@@ -1668,6 +1668,7 @@ function blankVerbatimContent(htmlx, verbatimElements) {
1668
1668
  return output;
1669
1669
  }
1670
1670
  function parseHtmlx(htmlx, parse, options) {
1671
+ var _a, _b;
1671
1672
  //Svelte tries to parse style and script tags which doesn't play well with typescript, so we blank them out.
1672
1673
  //HTMLx spec says they should just be retained after processing as is, so this is fine
1673
1674
  const verbatimElements = findVerbatimElements(htmlx);
@@ -1676,7 +1677,9 @@ function parseHtmlx(htmlx, parse, options) {
1676
1677
  const parsingCode = options.emitOnTemplateError && !options.svelte5Plus
1677
1678
  ? blankPossiblyErrorOperatorOrPropertyAccess(deconstructed)
1678
1679
  : deconstructed;
1679
- const htmlxAst = parse(parsingCode, options.svelte5Plus ? { loose: options.emitOnTemplateError } : undefined).html;
1680
+ const parsed = parse(parsingCode, options.svelte5Plus ? { loose: options.emitOnTemplateError } : undefined);
1681
+ const htmlxAst = parsed.html;
1682
+ htmlxAst._comments = (_b = (_a = parsed._comments) !== null && _a !== void 0 ? _a : parsed.comments) !== null && _b !== void 0 ? _b : [];
1680
1683
  //restore our script and style tags as nodes to maintain validity with HTMLx
1681
1684
  for (const s of verbatimElements) {
1682
1685
  htmlxAst.children.push(s);
@@ -1740,11 +1743,125 @@ function blankPossiblyErrorOperatorOrPropertyAccess(htmlx) {
1740
1743
  return htmlx;
1741
1744
  }
1742
1745
 
1746
+ /**
1747
+ * Removes comment altogether as it's unimportant for the output
1748
+ */
1749
+ function handleComment(str, node) {
1750
+ str.overwrite(node.start, node.end, '', { contentOnly: true });
1751
+ }
1752
+ /**
1753
+ * Handles comments that are directly before an element start tag and output them into the generated code as leading comments for the given node.
1754
+ * @param str The MagicString instance to operate on
1755
+ * @param node The node above which should be searched for a comment
1756
+ * @param ast The full Svelte AST
1757
+ */
1758
+ function handleLeadingStartComment(str, node, ast) {
1759
+ var _a, _b;
1760
+ const comments = (_a = ast._comments) !== null && _a !== void 0 ? _a : [];
1761
+ if (!comments.length || ((_b = node.leadingComments) === null || _b === void 0 ? void 0 : _b.length)) {
1762
+ return;
1763
+ }
1764
+ const leadingComments = [];
1765
+ let searchEnd = node.start;
1766
+ for (let i = comments.length - 1; i >= 0; i--) {
1767
+ const comment = comments[i];
1768
+ if (comment.end > searchEnd) {
1769
+ continue;
1770
+ }
1771
+ if (!/^\s*$/.test(str.original.slice(comment.end, searchEnd))) {
1772
+ break;
1773
+ }
1774
+ leadingComments.unshift(comment);
1775
+ searchEnd = comment.start;
1776
+ }
1777
+ if (leadingComments.length) {
1778
+ for (const leading of leadingComments) {
1779
+ if (/\n[ \t]*$/.test(str.original.slice(Math.max(leading.start - 100, 0), leading.start))) {
1780
+ leading.newline = true;
1781
+ }
1782
+ }
1783
+ node.leadingComments = leadingComments;
1784
+ }
1785
+ }
1786
+ /**
1787
+ * Handles comments that are directly after the last node inside an element/component start tag
1788
+ * and output them into the generated code as trailing comments for the given node.
1789
+ */
1790
+ function handleTrailingEndComment(str, node, parent, ast) {
1791
+ var _a, _b;
1792
+ const comments = (_a = ast._comments) !== null && _a !== void 0 ? _a : [];
1793
+ const attributes = parent.attributes;
1794
+ if (!comments.length || ((_b = node.trailingComments) === null || _b === void 0 ? void 0 : _b.length) || !(attributes === null || attributes === void 0 ? void 0 : attributes.length)) {
1795
+ return;
1796
+ }
1797
+ if (attributes[attributes.length - 1] !== node) {
1798
+ return;
1799
+ }
1800
+ const tag_end = str.original.indexOf('>', node.end);
1801
+ if (tag_end < 0) {
1802
+ return;
1803
+ }
1804
+ const trailingComments = [];
1805
+ let searchStart = node.end;
1806
+ for (const comment of comments) {
1807
+ if (comment.start < searchStart) {
1808
+ continue;
1809
+ }
1810
+ if (comment.end > tag_end) {
1811
+ break;
1812
+ }
1813
+ if (!/^\s*$/.test(str.original.slice(searchStart, comment.start))) {
1814
+ break;
1815
+ }
1816
+ trailingComments.push(comment);
1817
+ searchStart = comment.end;
1818
+ }
1819
+ if (!trailingComments.length) {
1820
+ return;
1821
+ }
1822
+ if (!/^\s*\/?\s*$/.test(str.original.slice(searchStart, tag_end))) {
1823
+ return;
1824
+ }
1825
+ for (const trailing of trailingComments) {
1826
+ if (/\n[ \t]*$/.test(str.original.slice(Math.max(trailing.start - 100, 0), trailing.start))) {
1827
+ trailing.newline = true;
1828
+ }
1829
+ }
1830
+ node.trailingComments = trailingComments;
1831
+ }
1832
+ function getLeadingCommentTransformation(node) {
1833
+ var _a;
1834
+ if (!((_a = node.leadingComments) === null || _a === void 0 ? void 0 : _a.length)) {
1835
+ return [];
1836
+ }
1837
+ const transformations = [];
1838
+ for (const comment of node.leadingComments) {
1839
+ if (comment.newline)
1840
+ transformations.push('\n');
1841
+ transformations.push([comment.start, comment.end]);
1842
+ }
1843
+ transformations.push('\n');
1844
+ return transformations;
1845
+ }
1846
+ function getTrailingCommentTransformation(node) {
1847
+ var _a;
1848
+ if (!((_a = node.trailingComments) === null || _a === void 0 ? void 0 : _a.length)) {
1849
+ return [];
1850
+ }
1851
+ const transformations = [];
1852
+ for (const comment of node.trailingComments) {
1853
+ transformations.push(comment.newline ? '\n' : ' ');
1854
+ transformations.push([comment.start, comment.end]);
1855
+ }
1856
+ transformations.push('\n');
1857
+ return transformations;
1858
+ }
1859
+
1743
1860
  /**
1744
1861
  * use:xxx={params} ---> __sveltets_2_ensureAction(xxx(svelte.mapElementTag('ParentNodeName'),(params)));
1745
1862
  */
1746
1863
  function handleActionDirective(attr, element) {
1747
- element.addAction(attr);
1864
+ element.addAction(attr, getLeadingCommentTransformation(attr), getTrailingCommentTransformation(attr));
1748
1865
  }
1749
1866
 
1750
1867
  /**
@@ -1960,7 +2077,9 @@ function isImplicitlyClosedBlock(end, block) {
1960
2077
  * animate:xxx(yyy) ---> __sveltets_2_ensureAnimation(xxx(svelte.mapElementTag('..'),__sveltets_2_AnimationMove,(yyy)));
1961
2078
  */
1962
2079
  function handleAnimateDirective(str, attr, element) {
2080
+ const trailingComments = getTrailingCommentTransformation(attr);
1963
2081
  const transformations = [
2082
+ ...getLeadingCommentTransformation(attr),
1964
2083
  '__sveltets_2_ensureAnimation(',
1965
2084
  getDirectiveNameStartEndIdx(str, attr),
1966
2085
  `(${element.typingsNamespace}.mapElementTag('${element.tagName}'),__sveltets_2_AnimationMove`
@@ -1968,7 +2087,7 @@ function handleAnimateDirective(str, attr, element) {
1968
2087
  if (attr.expression) {
1969
2088
  transformations.push(',(', rangeWithTrailingPropertyAccess(str.original, attr.expression), ')');
1970
2089
  }
1971
- transformations.push('));');
2090
+ transformations.push('));', ...trailingComments);
1972
2091
  element.appendToStartEnd(transformations);
1973
2092
  }
1974
2093
 
@@ -2104,17 +2223,17 @@ class Element {
2104
2223
  this.slotLetsTransformation = this.slotLetsTransformation || [['default'], []];
2105
2224
  this.slotLetsTransformation[1].push(...transformation, ',');
2106
2225
  }
2107
- addAction(attr) {
2226
+ addAction(attr, leadingComments = [], trailingComments = []) {
2108
2227
  const id = `$$action_${this.actionIdentifiers.length}`;
2109
2228
  this.actionIdentifiers.push(id);
2110
2229
  if (!this.actionsTransformation.length) {
2111
2230
  this.actionsTransformation.push('{');
2112
2231
  }
2113
- this.actionsTransformation.push(`const ${id} = __sveltets_2_ensureAction(`, getDirectiveNameStartEndIdx(this.str, attr), `(${this.typingsNamespace}.mapElementTag('${this.tagName}')`);
2232
+ this.actionsTransformation.push(...leadingComments, `const ${id} = __sveltets_2_ensureAction(`, getDirectiveNameStartEndIdx(this.str, attr), `(${this.typingsNamespace}.mapElementTag('${this.tagName}')`);
2114
2233
  if (attr.expression) {
2115
2234
  this.actionsTransformation.push(',(', rangeWithTrailingPropertyAccess(this.str.original, attr.expression), ')');
2116
2235
  }
2117
- this.actionsTransformation.push('));');
2236
+ this.actionsTransformation.push('));', ...trailingComments);
2118
2237
  }
2119
2238
  /**
2120
2239
  * Add something right after the start tag end.
@@ -2394,8 +2513,8 @@ class InlineComponent {
2394
2513
  * @param name Event name
2395
2514
  * @param expression Event handler, if present
2396
2515
  */
2397
- addEvent([nameStart, nameEnd], expression) {
2398
- this.eventsTransformation.push(`${this.name}.$on(`, surroundWith(this.str, [nameStart, nameEnd], '"', '"'), ', ', expression ? expression : '() => {}', ');');
2516
+ addEvent([nameStart, nameEnd], expression, leadingComments = [], trailingComments = []) {
2517
+ this.eventsTransformation.push(...leadingComments, `${this.name}.$on(`, surroundWith(this.str, [nameStart, nameEnd], '"', '"'), ', ', expression ? expression : '() => {}', ');', ...trailingComments);
2399
2518
  }
2400
2519
  /**
2401
2520
  * Handle the slot of `<... slot=".." />`
@@ -2622,7 +2741,8 @@ function handleAttribute(str, attr, parent, preserveCase, svelte5Plus, element)
2622
2741
  }
2623
2742
  };
2624
2743
  // Handle attribute name
2625
- const attributeName = [];
2744
+ const attributeName = getLeadingCommentTransformation(attr);
2745
+ const trailingComments = getTrailingCommentTransformation(attr);
2626
2746
  if (attributeValueIsOfType(attr.value, 'AttributeShorthand')) {
2627
2747
  // For the attribute shorthand, the name will be the mapped part
2628
2748
  let [start, end] = [attr.value[0].start, attr.value[0].end];
@@ -2632,7 +2752,7 @@ function handleAttribute(str, attr, parent, preserveCase, svelte5Plus, element)
2632
2752
  start--;
2633
2753
  str.overwrite(start, end, ' ', { contentOnly: true });
2634
2754
  }
2635
- addAttribute([[start, end]]);
2755
+ addAttribute([[start, end], ...trailingComments]);
2636
2756
  return;
2637
2757
  }
2638
2758
  else {
@@ -2655,13 +2775,13 @@ function handleAttribute(str, attr, parent, preserveCase, svelte5Plus, element)
2655
2775
  // Handle attribute value
2656
2776
  const attributeValue = [];
2657
2777
  if (attr.value === true) {
2658
- attributeValue.push(attr.name === 'popover' ? '""' : 'true');
2778
+ attributeValue.push(attr.name === 'popover' ? '""' : 'true', ...trailingComments);
2659
2779
  addAttribute(attributeName, attributeValue);
2660
2780
  return;
2661
2781
  }
2662
2782
  if (attr.value.length == 0) {
2663
2783
  // shouldn't happen
2664
- addAttribute(attributeName, ['""']);
2784
+ addAttribute(attributeName, ['""', ...trailingComments]);
2665
2785
  return;
2666
2786
  }
2667
2787
  //handle single value
@@ -2701,6 +2821,7 @@ function handleAttribute(str, attr, parent, preserveCase, svelte5Plus, element)
2701
2821
  if (!needsNumberConversion) {
2702
2822
  attributeValue.push(quote);
2703
2823
  }
2824
+ attributeValue.push(...trailingComments);
2704
2825
  addAttribute(attributeName, attributeValue);
2705
2826
  }
2706
2827
  else if (attrVal.type == 'MustacheTag') {
@@ -2711,7 +2832,7 @@ function handleAttribute(str, attr, parent, preserveCase, svelte5Plus, element)
2711
2832
  start--;
2712
2833
  str.overwrite(start, end, ' ', { contentOnly: true });
2713
2834
  }
2714
- attributeValue.push([start, end]);
2835
+ attributeValue.push([start, end], ...trailingComments);
2715
2836
  addAttribute(attributeName, attributeValue);
2716
2837
  }
2717
2838
  return;
@@ -2722,7 +2843,7 @@ function handleAttribute(str, attr, parent, preserveCase, svelte5Plus, element)
2722
2843
  str.appendRight(n.start, '$');
2723
2844
  }
2724
2845
  }
2725
- attributeValue.push('`', [attr.value[0].start, attr.value[attr.value.length - 1].end], '`');
2846
+ attributeValue.push('`', [attr.value[0].start, attr.value[attr.value.length - 1].end], '`', ...trailingComments);
2726
2847
  addAttribute(attributeName, attributeValue);
2727
2848
  }
2728
2849
  function attributeValueIsOfType(value, type) {
@@ -2842,6 +2963,8 @@ const supportsBindThis = [
2842
2963
  function handleBinding(str, attr, parent, element, preserveBind, isSvelte5Plus, emitJsDoc, isTsFile) {
2843
2964
  const isGetSetBinding = attr.expression.type === 'SequenceExpression';
2844
2965
  const [get, set] = isGetSetBinding ? attr.expression.expressions : [];
2966
+ const leadingComments = getLeadingCommentTransformation(attr);
2967
+ const trailingComments = getTrailingCommentTransformation(attr);
2845
2968
  // bind this
2846
2969
  if (attr.name === 'this' && supportsBindThis.includes(parent.type)) {
2847
2970
  // bind:this is effectively only works bottom up - the variable is updated by the element, not
@@ -2850,10 +2973,16 @@ function handleBinding(str, attr, parent, element, preserveBind, isSvelte5Plus,
2850
2973
  // the value becomes null, but we don't add it to the clause because it would introduce
2851
2974
  // worse DX for the 99% use case, and because null !== undefined which others might use to type the declaration.
2852
2975
  if (isGetSetBinding) {
2853
- element.appendToStartEnd(['(', [set.start, getEnd(set)], `)(${element.name});`]);
2976
+ element.appendToStartEnd([
2977
+ ...leadingComments,
2978
+ '(',
2979
+ [set.start, getEnd(set)],
2980
+ `)(${element.name});`,
2981
+ ...trailingComments
2982
+ ]);
2854
2983
  }
2855
2984
  else {
2856
- appendOneWayBinding(attr, ` = ${element.name}`, element);
2985
+ appendOneWayBinding(attr, ` = ${element.name}`, element, leadingComments, trailingComments);
2857
2986
  }
2858
2987
  return;
2859
2988
  }
@@ -2861,12 +2990,12 @@ function handleBinding(str, attr, parent, element, preserveBind, isSvelte5Plus,
2861
2990
  // bind group on input
2862
2991
  if (element instanceof Element && attr.name == 'group' && parent.name == 'input') {
2863
2992
  // add reassignment to force TS to widen the type of the declaration (in case it's never reassigned anywhere else)
2864
- appendOneWayBinding(attr, ' = __sveltets_2_any(null)', element);
2993
+ appendOneWayBinding(attr, ' = __sveltets_2_any(null)', element, leadingComments, trailingComments);
2865
2994
  return;
2866
2995
  }
2867
2996
  // one way binding
2868
2997
  if (oneWayBindingAttributes.has(attr.name) && element instanceof Element) {
2869
- appendOneWayBinding(attr, `= ${element.name}.${attr.name}`, element);
2998
+ appendOneWayBinding(attr, `= ${element.name}.${attr.name}`, element, leadingComments, trailingComments);
2870
2999
  return;
2871
3000
  }
2872
3001
  // one way binding whose property is not on the element
@@ -2877,8 +3006,10 @@ function handleBinding(str, attr, parent, element, preserveBind, isSvelte5Plus,
2877
3006
  ? `null as ${bindingType}`
2878
3007
  : `/** @type {${bindingType}} */ (null)`;
2879
3008
  element.appendToStartEnd([
3009
+ ...leadingComments,
2880
3010
  [attr.expression.start, getEnd(attr.expression)],
2881
- `= ${surroundWithIgnoreComments(bindingValue)};`
3011
+ `= ${surroundWithIgnoreComments(bindingValue)};`,
3012
+ ...trailingComments
2882
3013
  ]);
2883
3014
  return;
2884
3015
  }
@@ -2893,12 +3024,18 @@ function handleBinding(str, attr, parent, element, preserveBind, isSvelte5Plus,
2893
3024
  const name = preserveBind && element instanceof Element
2894
3025
  ? // HTML typings - preserve the bind: prefix
2895
3026
  isShorthand
2896
- ? [`"${str.original.substring(attr.start, attr.end)}"`]
2897
- : ['"', [attr.start, str.original.lastIndexOf('=', attr.expression.start)], '"']
3027
+ ? [...leadingComments, `"${str.original.substring(attr.start, attr.end)}"`]
3028
+ : [
3029
+ ...leadingComments,
3030
+ '"',
3031
+ [attr.start, str.original.lastIndexOf('=', attr.expression.start)],
3032
+ '"'
3033
+ ]
2898
3034
  : // Other typings - remove the bind: prefix
2899
3035
  isShorthand
2900
- ? [[attr.expression.start, attr.expression.end]]
3036
+ ? [...leadingComments, [attr.expression.start, attr.expression.end]]
2901
3037
  : [
3038
+ ...leadingComments,
2902
3039
  [
2903
3040
  attr.start + 'bind:'.length,
2904
3041
  str.original.lastIndexOf('=', attr.expression.start)
@@ -2906,7 +3043,7 @@ function handleBinding(str, attr, parent, element, preserveBind, isSvelte5Plus,
2906
3043
  ];
2907
3044
  const value = isShorthand
2908
3045
  ? preserveBind && element instanceof Element
2909
- ? [rangeWithTrailingPropertyAccess(str.original, attr.expression)]
3046
+ ? [rangeWithTrailingPropertyAccess(str.original, attr.expression), ...trailingComments]
2910
3047
  : undefined
2911
3048
  : isGetSetBinding
2912
3049
  ? [
@@ -2914,9 +3051,13 @@ function handleBinding(str, attr, parent, element, preserveBind, isSvelte5Plus,
2914
3051
  [get.start, get.end],
2915
3052
  ',',
2916
3053
  rangeWithTrailingPropertyAccess(str.original, set),
2917
- ')'
3054
+ ')',
3055
+ ...trailingComments
2918
3056
  ]
2919
- : [rangeWithTrailingPropertyAccess(str.original, attr.expression)];
3057
+ : [rangeWithTrailingPropertyAccess(str.original, attr.expression), ...trailingComments];
3058
+ if (!value) {
3059
+ name.push(...trailingComments);
3060
+ }
2920
3061
  if (isSvelte5Plus && element instanceof InlineComponent) {
2921
3062
  // To check if property is actually bindable
2922
3063
  element.appendToStartEnd([`${element.name}.$$bindings = '${attr.name}';`]);
@@ -2928,13 +3069,15 @@ function handleBinding(str, attr, parent, element, preserveBind, isSvelte5Plus,
2928
3069
  element.addProp(name, value);
2929
3070
  }
2930
3071
  }
2931
- function appendOneWayBinding(attr, assignment, element) {
3072
+ function appendOneWayBinding(attr, assignment, element, leadingComments, trailingComments) {
2932
3073
  const expression = attr.expression;
2933
3074
  const end = getEnd(expression);
2934
3075
  const hasTypeAnnotation = expression.typeAnnotation || isTypescriptNode(expression);
2935
3076
  const array = [
3077
+ ...leadingComments,
2936
3078
  [expression.start, end],
2937
- assignment + (hasTypeAnnotation ? '' : ';')
3079
+ assignment + (hasTypeAnnotation ? '' : ';'),
3080
+ ...trailingComments
2938
3081
  ];
2939
3082
  if (hasTypeAnnotation) {
2940
3083
  array.push([end, expression.end], ';');
@@ -2949,13 +3092,6 @@ function handleClassDirective(str, attr, element) {
2949
3092
  element.appendToStartEnd([rangeWithTrailingPropertyAccess(str.original, attr.expression), ';']);
2950
3093
  }
2951
3094
 
2952
- /**
2953
- * Removes comment altogether as it's unimportant for the output
2954
- */
2955
- function handleComment(str, node) {
2956
- str.overwrite(node.start, node.end, '', { contentOnly: true });
2957
- }
2958
-
2959
3095
  /**
2960
3096
  * `{@const x = y}` --> `const x = y;`
2961
3097
  *
@@ -3075,18 +3211,23 @@ function handleEventHandler(str, attr, element) {
3075
3211
  const nameStart = str.original.indexOf(':', attr.start) + 1;
3076
3212
  // If there's no expression, it's event bubbling (on:click)
3077
3213
  const nameEnd = nameStart + attr.name.length;
3214
+ const leadingComments = getLeadingCommentTransformation(attr);
3215
+ const trailingComments = getTrailingCommentTransformation(attr);
3078
3216
  if (element instanceof Element) {
3079
3217
  // Prefix with "on:" for better mapping.
3080
3218
  // Surround with quotes because event name could contain invalid prop chars.
3081
3219
  surroundWith(str, [nameStart, nameEnd], '"on:', '"');
3082
- element.addAttribute([[nameStart, nameEnd]], attr.expression
3083
- ? [rangeWithTrailingPropertyAccess(str.original, attr.expression)]
3084
- : ['undefined']);
3220
+ element.addAttribute([...leadingComments, [nameStart, nameEnd]], attr.expression
3221
+ ? [
3222
+ rangeWithTrailingPropertyAccess(str.original, attr.expression),
3223
+ ...trailingComments
3224
+ ]
3225
+ : ['undefined', ...trailingComments]);
3085
3226
  }
3086
3227
  else {
3087
3228
  element.addEvent([nameStart, nameEnd], attr.expression
3088
3229
  ? rangeWithTrailingPropertyAccess(str.original, attr.expression)
3089
- : undefined);
3230
+ : undefined, leadingComments, trailingComments);
3090
3231
  }
3091
3232
  }
3092
3233
 
@@ -3180,18 +3321,22 @@ function handleLet(str, node, parent, preserveCase, svelte5Plus, element) {
3180
3321
  expression: node.expression
3181
3322
  }
3182
3323
  ]
3183
- : true
3324
+ : true,
3325
+ leadingComments: node.leadingComments,
3326
+ trailingComments: node.trailingComments
3184
3327
  }, parent, preserveCase, svelte5Plus, element);
3185
3328
  }
3186
3329
  }
3187
3330
  }
3188
3331
  function addSlotLet(node, element) {
3189
3332
  const letTransformation = [
3333
+ ...getLeadingCommentTransformation(node),
3190
3334
  [node.start + 'let:'.length, node.start + 'let:'.length + node.name.length]
3191
3335
  ];
3192
3336
  if (node.expression) {
3193
3337
  letTransformation.push(':', [node.expression.start, node.expression.end]);
3194
3338
  }
3339
+ letTransformation.push(...getTrailingCommentTransformation(node));
3195
3340
  element.addSlotLet(letTransformation);
3196
3341
  }
3197
3342
 
@@ -3229,7 +3374,11 @@ function handleRawHtml(str, node) {
3229
3374
  * `{...xx}` -> `...x`
3230
3375
  */
3231
3376
  function handleSpread(node, element) {
3232
- const transformation = [[node.start + 1, node.end - 1]];
3377
+ const transformation = [
3378
+ ...getLeadingCommentTransformation(node),
3379
+ [node.start + 1, node.end - 1],
3380
+ ...getTrailingCommentTransformation(node)
3381
+ ];
3233
3382
  if (element instanceof Element) {
3234
3383
  element.addAttribute(transformation);
3235
3384
  }
@@ -3310,7 +3459,9 @@ function handleText(str, node, parent) {
3310
3459
  * transition|modifier:xxx(yyy) ---> __sveltets_2_ensureTransition(xxx(svelte.mapElementTag('..'),(yyy)));
3311
3460
  */
3312
3461
  function handleTransitionDirective(str, attr, element) {
3462
+ const trailingComments = getTrailingCommentTransformation(attr);
3313
3463
  const transformations = [
3464
+ ...getLeadingCommentTransformation(attr),
3314
3465
  '__sveltets_2_ensureTransition(',
3315
3466
  getDirectiveNameStartEndIdx(str, attr),
3316
3467
  `(${element.typingsNamespace}.mapElementTag('${element.tagName}')`
@@ -3318,7 +3469,7 @@ function handleTransitionDirective(str, attr, element) {
3318
3469
  if (attr.expression) {
3319
3470
  transformations.push(',(', rangeWithTrailingPropertyAccess(str.original, attr.expression), ')');
3320
3471
  }
3321
- transformations.push('));');
3472
+ transformations.push('));', ...trailingComments);
3322
3473
  element.appendToStartEnd(transformations);
3323
3474
  }
3324
3475
 
@@ -4888,12 +5039,17 @@ function checkIfDeclarationInstantiatedEventDispatcher(node, eventDispatcherImpo
4888
5039
  * {@attach xxx} ---> [Symbol()]: xxx
4889
5040
  */
4890
5041
  function handleAttachTag(tag, element) {
5042
+ const transformation = [...getLeadingCommentTransformation(tag), '[Symbol("@attach")]'];
5043
+ const value = [
5044
+ [tag.expression.start, tag.expression.end],
5045
+ ...getTrailingCommentTransformation(tag)
5046
+ ];
4891
5047
  // element.addAttachment(attr);
4892
5048
  if (element instanceof InlineComponent) {
4893
- element.addProp(['[Symbol("@attach")]'], [[tag.expression.start, tag.expression.end]]);
5049
+ element.addProp(transformation, value);
4894
5050
  }
4895
5051
  else {
4896
- element.addAttribute(['[Symbol("@attach")]'], [[tag.expression.start, tag.expression.end]]);
5052
+ element.addAttribute(transformation, value);
4897
5053
  }
4898
5054
  }
4899
5055
 
@@ -5241,6 +5397,8 @@ function convertHtmlxToJsx(str, ast, tags, options = { svelte5Plus: false }) {
5241
5397
  handleRenderTag(str, node);
5242
5398
  break;
5243
5399
  case 'AttachTag':
5400
+ handleLeadingStartComment(str, node, ast);
5401
+ handleTrailingEndComment(str, node, parent, ast);
5244
5402
  handleAttachTag(node, element);
5245
5403
  break;
5246
5404
  case 'InlineComponent':
@@ -5293,6 +5451,8 @@ function convertHtmlxToJsx(str, ast, tags, options = { svelte5Plus: false }) {
5293
5451
  handleComment(str, node);
5294
5452
  break;
5295
5453
  case 'Binding':
5454
+ handleLeadingStartComment(str, node, ast);
5455
+ handleTrailingEndComment(str, node, parent, ast);
5296
5456
  handleBinding(str, node, parent, element, options.typingsNamespace === 'svelteHTML', options.svelte5Plus, emitJsDoc, isTsFile);
5297
5457
  break;
5298
5458
  case 'Class':
@@ -5302,28 +5462,42 @@ function convertHtmlxToJsx(str, ast, tags, options = { svelte5Plus: false }) {
5302
5462
  handleStyleDirective(str, node, element);
5303
5463
  break;
5304
5464
  case 'Action':
5465
+ handleLeadingStartComment(str, node, ast);
5466
+ handleTrailingEndComment(str, node, parent, ast);
5305
5467
  stores.handleDirective(node, str);
5306
5468
  handleActionDirective(node, element);
5307
5469
  break;
5308
5470
  case 'Transition':
5471
+ handleLeadingStartComment(str, node, ast);
5472
+ handleTrailingEndComment(str, node, parent, ast);
5309
5473
  stores.handleDirective(node, str);
5310
5474
  handleTransitionDirective(str, node, element);
5311
5475
  break;
5312
5476
  case 'Animation':
5477
+ handleLeadingStartComment(str, node, ast);
5478
+ handleTrailingEndComment(str, node, parent, ast);
5313
5479
  stores.handleDirective(node, str);
5314
5480
  handleAnimateDirective(str, node, element);
5315
5481
  break;
5316
5482
  case 'Attribute':
5483
+ handleLeadingStartComment(str, node, ast);
5484
+ handleTrailingEndComment(str, node, parent, ast);
5317
5485
  handleAttribute(str, node, parent, preserveAttributeCase, options.svelte5Plus, element);
5318
5486
  break;
5319
5487
  case 'Spread':
5488
+ handleLeadingStartComment(str, node, ast);
5489
+ handleTrailingEndComment(str, node, parent, ast);
5320
5490
  handleSpread(node, element);
5321
5491
  break;
5322
5492
  case 'EventHandler':
5493
+ handleLeadingStartComment(str, node, ast);
5494
+ handleTrailingEndComment(str, node, parent, ast);
5323
5495
  eventHandler.handleEventHandler(node, parent);
5324
5496
  handleEventHandler(str, node, element);
5325
5497
  break;
5326
5498
  case 'Let':
5499
+ handleLeadingStartComment(str, node, ast);
5500
+ handleTrailingEndComment(str, node, parent, ast);
5327
5501
  handleLet(str, node, parent, preserveAttributeCase, options.svelte5Plus, element);
5328
5502
  break;
5329
5503
  case 'Text':
package/index.mjs CHANGED
@@ -1648,6 +1648,7 @@ function blankVerbatimContent(htmlx, verbatimElements) {
1648
1648
  return output;
1649
1649
  }
1650
1650
  function parseHtmlx(htmlx, parse, options) {
1651
+ var _a, _b;
1651
1652
  //Svelte tries to parse style and script tags which doesn't play well with typescript, so we blank them out.
1652
1653
  //HTMLx spec says they should just be retained after processing as is, so this is fine
1653
1654
  const verbatimElements = findVerbatimElements(htmlx);
@@ -1656,7 +1657,9 @@ function parseHtmlx(htmlx, parse, options) {
1656
1657
  const parsingCode = options.emitOnTemplateError && !options.svelte5Plus
1657
1658
  ? blankPossiblyErrorOperatorOrPropertyAccess(deconstructed)
1658
1659
  : deconstructed;
1659
- const htmlxAst = parse(parsingCode, options.svelte5Plus ? { loose: options.emitOnTemplateError } : undefined).html;
1660
+ const parsed = parse(parsingCode, options.svelte5Plus ? { loose: options.emitOnTemplateError } : undefined);
1661
+ const htmlxAst = parsed.html;
1662
+ htmlxAst._comments = (_b = (_a = parsed._comments) !== null && _a !== void 0 ? _a : parsed.comments) !== null && _b !== void 0 ? _b : [];
1660
1663
  //restore our script and style tags as nodes to maintain validity with HTMLx
1661
1664
  for (const s of verbatimElements) {
1662
1665
  htmlxAst.children.push(s);
@@ -1720,11 +1723,125 @@ function blankPossiblyErrorOperatorOrPropertyAccess(htmlx) {
1720
1723
  return htmlx;
1721
1724
  }
1722
1725
 
1726
+ /**
1727
+ * Removes comment altogether as it's unimportant for the output
1728
+ */
1729
+ function handleComment(str, node) {
1730
+ str.overwrite(node.start, node.end, '', { contentOnly: true });
1731
+ }
1732
+ /**
1733
+ * Handles comments that are directly before an element start tag and output them into the generated code as leading comments for the given node.
1734
+ * @param str The MagicString instance to operate on
1735
+ * @param node The node above which should be searched for a comment
1736
+ * @param ast The full Svelte AST
1737
+ */
1738
+ function handleLeadingStartComment(str, node, ast) {
1739
+ var _a, _b;
1740
+ const comments = (_a = ast._comments) !== null && _a !== void 0 ? _a : [];
1741
+ if (!comments.length || ((_b = node.leadingComments) === null || _b === void 0 ? void 0 : _b.length)) {
1742
+ return;
1743
+ }
1744
+ const leadingComments = [];
1745
+ let searchEnd = node.start;
1746
+ for (let i = comments.length - 1; i >= 0; i--) {
1747
+ const comment = comments[i];
1748
+ if (comment.end > searchEnd) {
1749
+ continue;
1750
+ }
1751
+ if (!/^\s*$/.test(str.original.slice(comment.end, searchEnd))) {
1752
+ break;
1753
+ }
1754
+ leadingComments.unshift(comment);
1755
+ searchEnd = comment.start;
1756
+ }
1757
+ if (leadingComments.length) {
1758
+ for (const leading of leadingComments) {
1759
+ if (/\n[ \t]*$/.test(str.original.slice(Math.max(leading.start - 100, 0), leading.start))) {
1760
+ leading.newline = true;
1761
+ }
1762
+ }
1763
+ node.leadingComments = leadingComments;
1764
+ }
1765
+ }
1766
+ /**
1767
+ * Handles comments that are directly after the last node inside an element/component start tag
1768
+ * and output them into the generated code as trailing comments for the given node.
1769
+ */
1770
+ function handleTrailingEndComment(str, node, parent, ast) {
1771
+ var _a, _b;
1772
+ const comments = (_a = ast._comments) !== null && _a !== void 0 ? _a : [];
1773
+ const attributes = parent.attributes;
1774
+ if (!comments.length || ((_b = node.trailingComments) === null || _b === void 0 ? void 0 : _b.length) || !(attributes === null || attributes === void 0 ? void 0 : attributes.length)) {
1775
+ return;
1776
+ }
1777
+ if (attributes[attributes.length - 1] !== node) {
1778
+ return;
1779
+ }
1780
+ const tag_end = str.original.indexOf('>', node.end);
1781
+ if (tag_end < 0) {
1782
+ return;
1783
+ }
1784
+ const trailingComments = [];
1785
+ let searchStart = node.end;
1786
+ for (const comment of comments) {
1787
+ if (comment.start < searchStart) {
1788
+ continue;
1789
+ }
1790
+ if (comment.end > tag_end) {
1791
+ break;
1792
+ }
1793
+ if (!/^\s*$/.test(str.original.slice(searchStart, comment.start))) {
1794
+ break;
1795
+ }
1796
+ trailingComments.push(comment);
1797
+ searchStart = comment.end;
1798
+ }
1799
+ if (!trailingComments.length) {
1800
+ return;
1801
+ }
1802
+ if (!/^\s*\/?\s*$/.test(str.original.slice(searchStart, tag_end))) {
1803
+ return;
1804
+ }
1805
+ for (const trailing of trailingComments) {
1806
+ if (/\n[ \t]*$/.test(str.original.slice(Math.max(trailing.start - 100, 0), trailing.start))) {
1807
+ trailing.newline = true;
1808
+ }
1809
+ }
1810
+ node.trailingComments = trailingComments;
1811
+ }
1812
+ function getLeadingCommentTransformation(node) {
1813
+ var _a;
1814
+ if (!((_a = node.leadingComments) === null || _a === void 0 ? void 0 : _a.length)) {
1815
+ return [];
1816
+ }
1817
+ const transformations = [];
1818
+ for (const comment of node.leadingComments) {
1819
+ if (comment.newline)
1820
+ transformations.push('\n');
1821
+ transformations.push([comment.start, comment.end]);
1822
+ }
1823
+ transformations.push('\n');
1824
+ return transformations;
1825
+ }
1826
+ function getTrailingCommentTransformation(node) {
1827
+ var _a;
1828
+ if (!((_a = node.trailingComments) === null || _a === void 0 ? void 0 : _a.length)) {
1829
+ return [];
1830
+ }
1831
+ const transformations = [];
1832
+ for (const comment of node.trailingComments) {
1833
+ transformations.push(comment.newline ? '\n' : ' ');
1834
+ transformations.push([comment.start, comment.end]);
1835
+ }
1836
+ transformations.push('\n');
1837
+ return transformations;
1838
+ }
1839
+
1723
1840
  /**
1724
1841
  * use:xxx={params} ---> __sveltets_2_ensureAction(xxx(svelte.mapElementTag('ParentNodeName'),(params)));
1725
1842
  */
1726
1843
  function handleActionDirective(attr, element) {
1727
- element.addAction(attr);
1844
+ element.addAction(attr, getLeadingCommentTransformation(attr), getTrailingCommentTransformation(attr));
1728
1845
  }
1729
1846
 
1730
1847
  /**
@@ -1940,7 +2057,9 @@ function isImplicitlyClosedBlock(end, block) {
1940
2057
  * animate:xxx(yyy) ---> __sveltets_2_ensureAnimation(xxx(svelte.mapElementTag('..'),__sveltets_2_AnimationMove,(yyy)));
1941
2058
  */
1942
2059
  function handleAnimateDirective(str, attr, element) {
2060
+ const trailingComments = getTrailingCommentTransformation(attr);
1943
2061
  const transformations = [
2062
+ ...getLeadingCommentTransformation(attr),
1944
2063
  '__sveltets_2_ensureAnimation(',
1945
2064
  getDirectiveNameStartEndIdx(str, attr),
1946
2065
  `(${element.typingsNamespace}.mapElementTag('${element.tagName}'),__sveltets_2_AnimationMove`
@@ -1948,7 +2067,7 @@ function handleAnimateDirective(str, attr, element) {
1948
2067
  if (attr.expression) {
1949
2068
  transformations.push(',(', rangeWithTrailingPropertyAccess(str.original, attr.expression), ')');
1950
2069
  }
1951
- transformations.push('));');
2070
+ transformations.push('));', ...trailingComments);
1952
2071
  element.appendToStartEnd(transformations);
1953
2072
  }
1954
2073
 
@@ -2084,17 +2203,17 @@ class Element {
2084
2203
  this.slotLetsTransformation = this.slotLetsTransformation || [['default'], []];
2085
2204
  this.slotLetsTransformation[1].push(...transformation, ',');
2086
2205
  }
2087
- addAction(attr) {
2206
+ addAction(attr, leadingComments = [], trailingComments = []) {
2088
2207
  const id = `$$action_${this.actionIdentifiers.length}`;
2089
2208
  this.actionIdentifiers.push(id);
2090
2209
  if (!this.actionsTransformation.length) {
2091
2210
  this.actionsTransformation.push('{');
2092
2211
  }
2093
- this.actionsTransformation.push(`const ${id} = __sveltets_2_ensureAction(`, getDirectiveNameStartEndIdx(this.str, attr), `(${this.typingsNamespace}.mapElementTag('${this.tagName}')`);
2212
+ this.actionsTransformation.push(...leadingComments, `const ${id} = __sveltets_2_ensureAction(`, getDirectiveNameStartEndIdx(this.str, attr), `(${this.typingsNamespace}.mapElementTag('${this.tagName}')`);
2094
2213
  if (attr.expression) {
2095
2214
  this.actionsTransformation.push(',(', rangeWithTrailingPropertyAccess(this.str.original, attr.expression), ')');
2096
2215
  }
2097
- this.actionsTransformation.push('));');
2216
+ this.actionsTransformation.push('));', ...trailingComments);
2098
2217
  }
2099
2218
  /**
2100
2219
  * Add something right after the start tag end.
@@ -2374,8 +2493,8 @@ class InlineComponent {
2374
2493
  * @param name Event name
2375
2494
  * @param expression Event handler, if present
2376
2495
  */
2377
- addEvent([nameStart, nameEnd], expression) {
2378
- this.eventsTransformation.push(`${this.name}.$on(`, surroundWith(this.str, [nameStart, nameEnd], '"', '"'), ', ', expression ? expression : '() => {}', ');');
2496
+ addEvent([nameStart, nameEnd], expression, leadingComments = [], trailingComments = []) {
2497
+ this.eventsTransformation.push(...leadingComments, `${this.name}.$on(`, surroundWith(this.str, [nameStart, nameEnd], '"', '"'), ', ', expression ? expression : '() => {}', ');', ...trailingComments);
2379
2498
  }
2380
2499
  /**
2381
2500
  * Handle the slot of `<... slot=".." />`
@@ -2602,7 +2721,8 @@ function handleAttribute(str, attr, parent, preserveCase, svelte5Plus, element)
2602
2721
  }
2603
2722
  };
2604
2723
  // Handle attribute name
2605
- const attributeName = [];
2724
+ const attributeName = getLeadingCommentTransformation(attr);
2725
+ const trailingComments = getTrailingCommentTransformation(attr);
2606
2726
  if (attributeValueIsOfType(attr.value, 'AttributeShorthand')) {
2607
2727
  // For the attribute shorthand, the name will be the mapped part
2608
2728
  let [start, end] = [attr.value[0].start, attr.value[0].end];
@@ -2612,7 +2732,7 @@ function handleAttribute(str, attr, parent, preserveCase, svelte5Plus, element)
2612
2732
  start--;
2613
2733
  str.overwrite(start, end, ' ', { contentOnly: true });
2614
2734
  }
2615
- addAttribute([[start, end]]);
2735
+ addAttribute([[start, end], ...trailingComments]);
2616
2736
  return;
2617
2737
  }
2618
2738
  else {
@@ -2635,13 +2755,13 @@ function handleAttribute(str, attr, parent, preserveCase, svelte5Plus, element)
2635
2755
  // Handle attribute value
2636
2756
  const attributeValue = [];
2637
2757
  if (attr.value === true) {
2638
- attributeValue.push(attr.name === 'popover' ? '""' : 'true');
2758
+ attributeValue.push(attr.name === 'popover' ? '""' : 'true', ...trailingComments);
2639
2759
  addAttribute(attributeName, attributeValue);
2640
2760
  return;
2641
2761
  }
2642
2762
  if (attr.value.length == 0) {
2643
2763
  // shouldn't happen
2644
- addAttribute(attributeName, ['""']);
2764
+ addAttribute(attributeName, ['""', ...trailingComments]);
2645
2765
  return;
2646
2766
  }
2647
2767
  //handle single value
@@ -2681,6 +2801,7 @@ function handleAttribute(str, attr, parent, preserveCase, svelte5Plus, element)
2681
2801
  if (!needsNumberConversion) {
2682
2802
  attributeValue.push(quote);
2683
2803
  }
2804
+ attributeValue.push(...trailingComments);
2684
2805
  addAttribute(attributeName, attributeValue);
2685
2806
  }
2686
2807
  else if (attrVal.type == 'MustacheTag') {
@@ -2691,7 +2812,7 @@ function handleAttribute(str, attr, parent, preserveCase, svelte5Plus, element)
2691
2812
  start--;
2692
2813
  str.overwrite(start, end, ' ', { contentOnly: true });
2693
2814
  }
2694
- attributeValue.push([start, end]);
2815
+ attributeValue.push([start, end], ...trailingComments);
2695
2816
  addAttribute(attributeName, attributeValue);
2696
2817
  }
2697
2818
  return;
@@ -2702,7 +2823,7 @@ function handleAttribute(str, attr, parent, preserveCase, svelte5Plus, element)
2702
2823
  str.appendRight(n.start, '$');
2703
2824
  }
2704
2825
  }
2705
- attributeValue.push('`', [attr.value[0].start, attr.value[attr.value.length - 1].end], '`');
2826
+ attributeValue.push('`', [attr.value[0].start, attr.value[attr.value.length - 1].end], '`', ...trailingComments);
2706
2827
  addAttribute(attributeName, attributeValue);
2707
2828
  }
2708
2829
  function attributeValueIsOfType(value, type) {
@@ -2822,6 +2943,8 @@ const supportsBindThis = [
2822
2943
  function handleBinding(str, attr, parent, element, preserveBind, isSvelte5Plus, emitJsDoc, isTsFile) {
2823
2944
  const isGetSetBinding = attr.expression.type === 'SequenceExpression';
2824
2945
  const [get, set] = isGetSetBinding ? attr.expression.expressions : [];
2946
+ const leadingComments = getLeadingCommentTransformation(attr);
2947
+ const trailingComments = getTrailingCommentTransformation(attr);
2825
2948
  // bind this
2826
2949
  if (attr.name === 'this' && supportsBindThis.includes(parent.type)) {
2827
2950
  // bind:this is effectively only works bottom up - the variable is updated by the element, not
@@ -2830,10 +2953,16 @@ function handleBinding(str, attr, parent, element, preserveBind, isSvelte5Plus,
2830
2953
  // the value becomes null, but we don't add it to the clause because it would introduce
2831
2954
  // worse DX for the 99% use case, and because null !== undefined which others might use to type the declaration.
2832
2955
  if (isGetSetBinding) {
2833
- element.appendToStartEnd(['(', [set.start, getEnd(set)], `)(${element.name});`]);
2956
+ element.appendToStartEnd([
2957
+ ...leadingComments,
2958
+ '(',
2959
+ [set.start, getEnd(set)],
2960
+ `)(${element.name});`,
2961
+ ...trailingComments
2962
+ ]);
2834
2963
  }
2835
2964
  else {
2836
- appendOneWayBinding(attr, ` = ${element.name}`, element);
2965
+ appendOneWayBinding(attr, ` = ${element.name}`, element, leadingComments, trailingComments);
2837
2966
  }
2838
2967
  return;
2839
2968
  }
@@ -2841,12 +2970,12 @@ function handleBinding(str, attr, parent, element, preserveBind, isSvelte5Plus,
2841
2970
  // bind group on input
2842
2971
  if (element instanceof Element && attr.name == 'group' && parent.name == 'input') {
2843
2972
  // add reassignment to force TS to widen the type of the declaration (in case it's never reassigned anywhere else)
2844
- appendOneWayBinding(attr, ' = __sveltets_2_any(null)', element);
2973
+ appendOneWayBinding(attr, ' = __sveltets_2_any(null)', element, leadingComments, trailingComments);
2845
2974
  return;
2846
2975
  }
2847
2976
  // one way binding
2848
2977
  if (oneWayBindingAttributes.has(attr.name) && element instanceof Element) {
2849
- appendOneWayBinding(attr, `= ${element.name}.${attr.name}`, element);
2978
+ appendOneWayBinding(attr, `= ${element.name}.${attr.name}`, element, leadingComments, trailingComments);
2850
2979
  return;
2851
2980
  }
2852
2981
  // one way binding whose property is not on the element
@@ -2857,8 +2986,10 @@ function handleBinding(str, attr, parent, element, preserveBind, isSvelte5Plus,
2857
2986
  ? `null as ${bindingType}`
2858
2987
  : `/** @type {${bindingType}} */ (null)`;
2859
2988
  element.appendToStartEnd([
2989
+ ...leadingComments,
2860
2990
  [attr.expression.start, getEnd(attr.expression)],
2861
- `= ${surroundWithIgnoreComments(bindingValue)};`
2991
+ `= ${surroundWithIgnoreComments(bindingValue)};`,
2992
+ ...trailingComments
2862
2993
  ]);
2863
2994
  return;
2864
2995
  }
@@ -2873,12 +3004,18 @@ function handleBinding(str, attr, parent, element, preserveBind, isSvelte5Plus,
2873
3004
  const name = preserveBind && element instanceof Element
2874
3005
  ? // HTML typings - preserve the bind: prefix
2875
3006
  isShorthand
2876
- ? [`"${str.original.substring(attr.start, attr.end)}"`]
2877
- : ['"', [attr.start, str.original.lastIndexOf('=', attr.expression.start)], '"']
3007
+ ? [...leadingComments, `"${str.original.substring(attr.start, attr.end)}"`]
3008
+ : [
3009
+ ...leadingComments,
3010
+ '"',
3011
+ [attr.start, str.original.lastIndexOf('=', attr.expression.start)],
3012
+ '"'
3013
+ ]
2878
3014
  : // Other typings - remove the bind: prefix
2879
3015
  isShorthand
2880
- ? [[attr.expression.start, attr.expression.end]]
3016
+ ? [...leadingComments, [attr.expression.start, attr.expression.end]]
2881
3017
  : [
3018
+ ...leadingComments,
2882
3019
  [
2883
3020
  attr.start + 'bind:'.length,
2884
3021
  str.original.lastIndexOf('=', attr.expression.start)
@@ -2886,7 +3023,7 @@ function handleBinding(str, attr, parent, element, preserveBind, isSvelte5Plus,
2886
3023
  ];
2887
3024
  const value = isShorthand
2888
3025
  ? preserveBind && element instanceof Element
2889
- ? [rangeWithTrailingPropertyAccess(str.original, attr.expression)]
3026
+ ? [rangeWithTrailingPropertyAccess(str.original, attr.expression), ...trailingComments]
2890
3027
  : undefined
2891
3028
  : isGetSetBinding
2892
3029
  ? [
@@ -2894,9 +3031,13 @@ function handleBinding(str, attr, parent, element, preserveBind, isSvelte5Plus,
2894
3031
  [get.start, get.end],
2895
3032
  ',',
2896
3033
  rangeWithTrailingPropertyAccess(str.original, set),
2897
- ')'
3034
+ ')',
3035
+ ...trailingComments
2898
3036
  ]
2899
- : [rangeWithTrailingPropertyAccess(str.original, attr.expression)];
3037
+ : [rangeWithTrailingPropertyAccess(str.original, attr.expression), ...trailingComments];
3038
+ if (!value) {
3039
+ name.push(...trailingComments);
3040
+ }
2900
3041
  if (isSvelte5Plus && element instanceof InlineComponent) {
2901
3042
  // To check if property is actually bindable
2902
3043
  element.appendToStartEnd([`${element.name}.$$bindings = '${attr.name}';`]);
@@ -2908,13 +3049,15 @@ function handleBinding(str, attr, parent, element, preserveBind, isSvelte5Plus,
2908
3049
  element.addProp(name, value);
2909
3050
  }
2910
3051
  }
2911
- function appendOneWayBinding(attr, assignment, element) {
3052
+ function appendOneWayBinding(attr, assignment, element, leadingComments, trailingComments) {
2912
3053
  const expression = attr.expression;
2913
3054
  const end = getEnd(expression);
2914
3055
  const hasTypeAnnotation = expression.typeAnnotation || isTypescriptNode(expression);
2915
3056
  const array = [
3057
+ ...leadingComments,
2916
3058
  [expression.start, end],
2917
- assignment + (hasTypeAnnotation ? '' : ';')
3059
+ assignment + (hasTypeAnnotation ? '' : ';'),
3060
+ ...trailingComments
2918
3061
  ];
2919
3062
  if (hasTypeAnnotation) {
2920
3063
  array.push([end, expression.end], ';');
@@ -2929,13 +3072,6 @@ function handleClassDirective(str, attr, element) {
2929
3072
  element.appendToStartEnd([rangeWithTrailingPropertyAccess(str.original, attr.expression), ';']);
2930
3073
  }
2931
3074
 
2932
- /**
2933
- * Removes comment altogether as it's unimportant for the output
2934
- */
2935
- function handleComment(str, node) {
2936
- str.overwrite(node.start, node.end, '', { contentOnly: true });
2937
- }
2938
-
2939
3075
  /**
2940
3076
  * `{@const x = y}` --> `const x = y;`
2941
3077
  *
@@ -3055,18 +3191,23 @@ function handleEventHandler(str, attr, element) {
3055
3191
  const nameStart = str.original.indexOf(':', attr.start) + 1;
3056
3192
  // If there's no expression, it's event bubbling (on:click)
3057
3193
  const nameEnd = nameStart + attr.name.length;
3194
+ const leadingComments = getLeadingCommentTransformation(attr);
3195
+ const trailingComments = getTrailingCommentTransformation(attr);
3058
3196
  if (element instanceof Element) {
3059
3197
  // Prefix with "on:" for better mapping.
3060
3198
  // Surround with quotes because event name could contain invalid prop chars.
3061
3199
  surroundWith(str, [nameStart, nameEnd], '"on:', '"');
3062
- element.addAttribute([[nameStart, nameEnd]], attr.expression
3063
- ? [rangeWithTrailingPropertyAccess(str.original, attr.expression)]
3064
- : ['undefined']);
3200
+ element.addAttribute([...leadingComments, [nameStart, nameEnd]], attr.expression
3201
+ ? [
3202
+ rangeWithTrailingPropertyAccess(str.original, attr.expression),
3203
+ ...trailingComments
3204
+ ]
3205
+ : ['undefined', ...trailingComments]);
3065
3206
  }
3066
3207
  else {
3067
3208
  element.addEvent([nameStart, nameEnd], attr.expression
3068
3209
  ? rangeWithTrailingPropertyAccess(str.original, attr.expression)
3069
- : undefined);
3210
+ : undefined, leadingComments, trailingComments);
3070
3211
  }
3071
3212
  }
3072
3213
 
@@ -3160,18 +3301,22 @@ function handleLet(str, node, parent, preserveCase, svelte5Plus, element) {
3160
3301
  expression: node.expression
3161
3302
  }
3162
3303
  ]
3163
- : true
3304
+ : true,
3305
+ leadingComments: node.leadingComments,
3306
+ trailingComments: node.trailingComments
3164
3307
  }, parent, preserveCase, svelte5Plus, element);
3165
3308
  }
3166
3309
  }
3167
3310
  }
3168
3311
  function addSlotLet(node, element) {
3169
3312
  const letTransformation = [
3313
+ ...getLeadingCommentTransformation(node),
3170
3314
  [node.start + 'let:'.length, node.start + 'let:'.length + node.name.length]
3171
3315
  ];
3172
3316
  if (node.expression) {
3173
3317
  letTransformation.push(':', [node.expression.start, node.expression.end]);
3174
3318
  }
3319
+ letTransformation.push(...getTrailingCommentTransformation(node));
3175
3320
  element.addSlotLet(letTransformation);
3176
3321
  }
3177
3322
 
@@ -3209,7 +3354,11 @@ function handleRawHtml(str, node) {
3209
3354
  * `{...xx}` -> `...x`
3210
3355
  */
3211
3356
  function handleSpread(node, element) {
3212
- const transformation = [[node.start + 1, node.end - 1]];
3357
+ const transformation = [
3358
+ ...getLeadingCommentTransformation(node),
3359
+ [node.start + 1, node.end - 1],
3360
+ ...getTrailingCommentTransformation(node)
3361
+ ];
3213
3362
  if (element instanceof Element) {
3214
3363
  element.addAttribute(transformation);
3215
3364
  }
@@ -3290,7 +3439,9 @@ function handleText(str, node, parent) {
3290
3439
  * transition|modifier:xxx(yyy) ---> __sveltets_2_ensureTransition(xxx(svelte.mapElementTag('..'),(yyy)));
3291
3440
  */
3292
3441
  function handleTransitionDirective(str, attr, element) {
3442
+ const trailingComments = getTrailingCommentTransformation(attr);
3293
3443
  const transformations = [
3444
+ ...getLeadingCommentTransformation(attr),
3294
3445
  '__sveltets_2_ensureTransition(',
3295
3446
  getDirectiveNameStartEndIdx(str, attr),
3296
3447
  `(${element.typingsNamespace}.mapElementTag('${element.tagName}')`
@@ -3298,7 +3449,7 @@ function handleTransitionDirective(str, attr, element) {
3298
3449
  if (attr.expression) {
3299
3450
  transformations.push(',(', rangeWithTrailingPropertyAccess(str.original, attr.expression), ')');
3300
3451
  }
3301
- transformations.push('));');
3452
+ transformations.push('));', ...trailingComments);
3302
3453
  element.appendToStartEnd(transformations);
3303
3454
  }
3304
3455
 
@@ -4868,12 +5019,17 @@ function checkIfDeclarationInstantiatedEventDispatcher(node, eventDispatcherImpo
4868
5019
  * {@attach xxx} ---> [Symbol()]: xxx
4869
5020
  */
4870
5021
  function handleAttachTag(tag, element) {
5022
+ const transformation = [...getLeadingCommentTransformation(tag), '[Symbol("@attach")]'];
5023
+ const value = [
5024
+ [tag.expression.start, tag.expression.end],
5025
+ ...getTrailingCommentTransformation(tag)
5026
+ ];
4871
5027
  // element.addAttachment(attr);
4872
5028
  if (element instanceof InlineComponent) {
4873
- element.addProp(['[Symbol("@attach")]'], [[tag.expression.start, tag.expression.end]]);
5029
+ element.addProp(transformation, value);
4874
5030
  }
4875
5031
  else {
4876
- element.addAttribute(['[Symbol("@attach")]'], [[tag.expression.start, tag.expression.end]]);
5032
+ element.addAttribute(transformation, value);
4877
5033
  }
4878
5034
  }
4879
5035
 
@@ -5221,6 +5377,8 @@ function convertHtmlxToJsx(str, ast, tags, options = { svelte5Plus: false }) {
5221
5377
  handleRenderTag(str, node);
5222
5378
  break;
5223
5379
  case 'AttachTag':
5380
+ handleLeadingStartComment(str, node, ast);
5381
+ handleTrailingEndComment(str, node, parent, ast);
5224
5382
  handleAttachTag(node, element);
5225
5383
  break;
5226
5384
  case 'InlineComponent':
@@ -5273,6 +5431,8 @@ function convertHtmlxToJsx(str, ast, tags, options = { svelte5Plus: false }) {
5273
5431
  handleComment(str, node);
5274
5432
  break;
5275
5433
  case 'Binding':
5434
+ handleLeadingStartComment(str, node, ast);
5435
+ handleTrailingEndComment(str, node, parent, ast);
5276
5436
  handleBinding(str, node, parent, element, options.typingsNamespace === 'svelteHTML', options.svelte5Plus, emitJsDoc, isTsFile);
5277
5437
  break;
5278
5438
  case 'Class':
@@ -5282,28 +5442,42 @@ function convertHtmlxToJsx(str, ast, tags, options = { svelte5Plus: false }) {
5282
5442
  handleStyleDirective(str, node, element);
5283
5443
  break;
5284
5444
  case 'Action':
5445
+ handleLeadingStartComment(str, node, ast);
5446
+ handleTrailingEndComment(str, node, parent, ast);
5285
5447
  stores.handleDirective(node, str);
5286
5448
  handleActionDirective(node, element);
5287
5449
  break;
5288
5450
  case 'Transition':
5451
+ handleLeadingStartComment(str, node, ast);
5452
+ handleTrailingEndComment(str, node, parent, ast);
5289
5453
  stores.handleDirective(node, str);
5290
5454
  handleTransitionDirective(str, node, element);
5291
5455
  break;
5292
5456
  case 'Animation':
5457
+ handleLeadingStartComment(str, node, ast);
5458
+ handleTrailingEndComment(str, node, parent, ast);
5293
5459
  stores.handleDirective(node, str);
5294
5460
  handleAnimateDirective(str, node, element);
5295
5461
  break;
5296
5462
  case 'Attribute':
5463
+ handleLeadingStartComment(str, node, ast);
5464
+ handleTrailingEndComment(str, node, parent, ast);
5297
5465
  handleAttribute(str, node, parent, preserveAttributeCase, options.svelte5Plus, element);
5298
5466
  break;
5299
5467
  case 'Spread':
5468
+ handleLeadingStartComment(str, node, ast);
5469
+ handleTrailingEndComment(str, node, parent, ast);
5300
5470
  handleSpread(node, element);
5301
5471
  break;
5302
5472
  case 'EventHandler':
5473
+ handleLeadingStartComment(str, node, ast);
5474
+ handleTrailingEndComment(str, node, parent, ast);
5303
5475
  eventHandler.handleEventHandler(node, parent);
5304
5476
  handleEventHandler(str, node, element);
5305
5477
  break;
5306
5478
  case 'Let':
5479
+ handleLeadingStartComment(str, node, ast);
5480
+ handleTrailingEndComment(str, node, parent, ast);
5307
5481
  handleLet(str, node, parent, preserveAttributeCase, options.svelte5Plus, element);
5308
5482
  break;
5309
5483
  case 'Text':
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "svelte2tsx",
3
- "version": "0.7.50",
3
+ "version": "0.7.51",
4
4
  "description": "Convert Svelte components to TSX for type checking",
5
5
  "author": "The Svelte Community",
6
6
  "license": "MIT",