svelte2tsx 0.4.13 → 0.4.14

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 +160 -45
  2. package/index.mjs +160 -45
  3. package/package.json +2 -2
package/index.js CHANGED
@@ -1677,6 +1677,21 @@ function usesLet(node) {
1677
1677
  var _a;
1678
1678
  return (_a = node.attributes) === null || _a === void 0 ? void 0 : _a.some((attr) => attr.type === 'Let');
1679
1679
  }
1680
+ function buildTemplateString(attr, str, htmlx, leadingOverride, trailingOverride, overrideStart) {
1681
+ overrideStart = overrideStart !== null && overrideStart !== void 0 ? overrideStart : htmlx.lastIndexOf('=', attr.value[0].start);
1682
+ str.overwrite(overrideStart, attr.value[0].start, leadingOverride);
1683
+ for (const n of attr.value) {
1684
+ if (n.type == 'MustacheTag') {
1685
+ str.appendRight(n.start, '$');
1686
+ }
1687
+ }
1688
+ if (isQuote(htmlx[attr.end - 1])) {
1689
+ str.overwrite(attr.end - 1, attr.end, trailingOverride);
1690
+ }
1691
+ else {
1692
+ str.appendLeft(attr.end, trailingOverride);
1693
+ }
1694
+ }
1680
1695
 
1681
1696
  /**
1682
1697
  * use:xxx={params} ---> {...__sveltets_1_ensureAction(xxx(__sveltets_1_mapElementTag('ParentNodeName'),(params)))}
@@ -1879,21 +1894,6 @@ function handleAttribute(htmlx, str, attr, parent, preserveCase) {
1879
1894
  // We have multiple attribute values, so we build a template string out of them.
1880
1895
  buildTemplateString(attr, str, htmlx, shouldApplySlotCheck ? `={${ensureSlotStr}\`` : '={`', shouldApplySlotCheck ? '`)}' : '`}');
1881
1896
  }
1882
- function buildTemplateString(attr, str, htmlx, leadingOverride, trailingOverride) {
1883
- const equals = htmlx.lastIndexOf('=', attr.value[0].start);
1884
- str.overwrite(equals, attr.value[0].start, leadingOverride);
1885
- for (const n of attr.value) {
1886
- if (n.type == 'MustacheTag') {
1887
- str.appendRight(n.start, '$');
1888
- }
1889
- }
1890
- if (isQuote(htmlx[attr.end - 1])) {
1891
- str.overwrite(attr.end - 1, attr.end, trailingOverride);
1892
- }
1893
- else {
1894
- str.appendLeft(attr.end, trailingOverride);
1895
- }
1896
- }
1897
1897
  function sanitizeLeadingChars(attrName) {
1898
1898
  let sanitizedName = '';
1899
1899
  for (let i = 0; i < attrName.length; i++) {
@@ -1908,6 +1908,24 @@ function sanitizeLeadingChars(attrName) {
1908
1908
  return sanitizedName;
1909
1909
  }
1910
1910
 
1911
+ function extractConstTags(children) {
1912
+ const tags = [];
1913
+ for (const child of children) {
1914
+ if (child.type === 'ConstTag') {
1915
+ const constTag = child;
1916
+ tags.push((insertionPoint, str) => {
1917
+ str.appendRight(constTag.expression.left.start, 'const ');
1918
+ str.move(constTag.expression.left.start, constTag.expression.right.end, insertionPoint);
1919
+ str.appendLeft(constTag.expression.right.end, ';');
1920
+ str.overwrite(constTag.start + 1, constTag.expression.left.start - 1, '', {
1921
+ contentOnly: true
1922
+ });
1923
+ });
1924
+ }
1925
+ }
1926
+ return tags;
1927
+ }
1928
+
1911
1929
  /**
1912
1930
  * Transform {#await ...} into something JSX understands
1913
1931
  */
@@ -1973,16 +1991,24 @@ function handleAwaitThen(awaitBlock, htmlx, str, ifScope) {
1973
1991
  }
1974
1992
  if (awaitBlock.value) {
1975
1993
  str.overwrite(thenStart, awaitBlock.value.start, '__sveltets_1_awaitThen(_$$p, (');
1976
- str.overwrite(awaitBlock.value.end, thenEnd, `) => {${ifScope.addPossibleIfCondition()}<>`);
1994
+ str.overwrite(awaitBlock.value.end, thenEnd, ') => {');
1995
+ extractConstTags(awaitBlock.then.children).forEach((insertion) => {
1996
+ insertion(thenEnd, str);
1997
+ });
1998
+ str.appendRight(thenEnd, `${ifScope.addPossibleIfCondition()}<>`);
1977
1999
  }
1978
2000
  else {
1979
- const awaitThenFn = `__sveltets_1_awaitThen(_$$p, () => {${ifScope.addPossibleIfCondition()}<>`; // eslint-disable-line
2001
+ const awaitThenFn = '__sveltets_1_awaitThen(_$$p, () => {';
1980
2002
  if (thenStart === thenEnd) {
1981
2003
  str.appendLeft(thenStart, awaitThenFn);
1982
2004
  }
1983
2005
  else {
1984
2006
  str.overwrite(thenStart, thenEnd, awaitThenFn);
1985
2007
  }
2008
+ extractConstTags(awaitBlock.then.children).forEach((insertion) => {
2009
+ insertion(thenEnd, str);
2010
+ });
2011
+ str.appendRight(thenEnd, `${ifScope.addPossibleIfCondition()}<>`); // eslint-disable-line
1986
2012
  }
1987
2013
  }
1988
2014
  function handleAwaitCatch(awaitBlock, htmlx, str, ifScope) {
@@ -1994,12 +2020,20 @@ function handleAwaitCatch(awaitBlock, htmlx, str, ifScope) {
1994
2020
  // {#await ... catch ...}
1995
2021
  const catchBegin = htmlx.indexOf('}', awaitBlock.error.end) + 1;
1996
2022
  str.overwrite(awaitBlock.expression.end, awaitBlock.error.start, '); __sveltets_1_awaitThen(_$$p, () => {}, (');
1997
- str.overwrite(awaitBlock.error.end, catchBegin, ') => {<>');
2023
+ str.overwrite(awaitBlock.error.end, catchBegin, ') => {');
2024
+ extractConstTags(awaitBlock.catch.children).forEach((insertion) => {
2025
+ insertion(catchBegin, str);
2026
+ });
2027
+ str.appendRight(catchBegin, '<>');
1998
2028
  }
1999
2029
  else {
2000
2030
  // {#await ... catch}
2001
2031
  const catchBegin = htmlx.indexOf('}', awaitBlock.expression.end) + 1;
2002
- str.overwrite(awaitBlock.expression.end, catchBegin, '); __sveltets_1_awaitThen(_$$p, () => {}, () => {<>');
2032
+ str.overwrite(awaitBlock.expression.end, catchBegin, '); __sveltets_1_awaitThen(_$$p, () => {}, () => {');
2033
+ extractConstTags(awaitBlock.catch.children).forEach((insertion) => {
2034
+ insertion(catchBegin, str);
2035
+ });
2036
+ str.appendRight(catchBegin, '<>');
2003
2037
  }
2004
2038
  }
2005
2039
  else {
@@ -2012,7 +2046,11 @@ function handleAwaitCatch(awaitBlock, htmlx, str, ifScope) {
2012
2046
  const errorEnd = awaitBlock.error ? awaitBlock.error.end : errorStart;
2013
2047
  const catchEnd = htmlx.indexOf('}', errorEnd) + 1;
2014
2048
  str.overwrite(catchStart, errorStart, '</>}, (');
2015
- str.overwrite(errorEnd, catchEnd, `) => {${ifScope.addPossibleIfCondition()}<>`);
2049
+ str.overwrite(errorEnd, catchEnd, ') => {');
2050
+ extractConstTags(awaitBlock.catch.children).forEach((insertion) => {
2051
+ insertion(catchEnd, str);
2052
+ });
2053
+ str.appendRight(catchEnd, `${ifScope.addPossibleIfCondition()}<>`);
2016
2054
  }
2017
2055
  }
2018
2056
 
@@ -2120,14 +2158,23 @@ function handleComment(str, node) {
2120
2158
 
2121
2159
  const shadowedPropsSymbol = Symbol('shadowedProps');
2122
2160
  /**
2123
- * Transforms the usage of a slot (let:xx)
2161
+ * Transforms the usage of a slot (slot="xxx")
2162
+ * - transforms let:xx, {@const xx}
2124
2163
  */
2125
2164
  function handleSlot(htmlx, str, slotEl, component, slotName, ifScope, templateScope) {
2126
2165
  var _a;
2127
2166
  //collect "let" definitions
2128
2167
  const slotElIsComponent = slotEl === component;
2129
- let hasMoved = false;
2168
+ let hasMovedLet = false;
2130
2169
  let slotDefInsertionPoint;
2170
+ // lazily calculate insertion point only when needed
2171
+ const calculateSlotDefInsertionPoint = () => {
2172
+ slotDefInsertionPoint =
2173
+ slotDefInsertionPoint ||
2174
+ (slotElIsComponent
2175
+ ? htmlx.lastIndexOf('>', slotEl.children[0].start) + 1
2176
+ : slotEl.start);
2177
+ };
2131
2178
  for (const attr of slotEl.attributes) {
2132
2179
  if (attr.type != 'Let') {
2133
2180
  continue;
@@ -2137,19 +2184,15 @@ function handleSlot(htmlx, str, slotEl, component, slotName, ifScope, templateSc
2137
2184
  str.remove(attr.start, attr.end);
2138
2185
  continue;
2139
2186
  }
2140
- slotDefInsertionPoint =
2141
- slotDefInsertionPoint ||
2142
- (slotElIsComponent
2143
- ? htmlx.lastIndexOf('>', slotEl.children[0].start) + 1
2144
- : slotEl.start);
2187
+ calculateSlotDefInsertionPoint();
2145
2188
  str.move(attr.start, attr.end, slotDefInsertionPoint);
2146
2189
  //remove let:
2147
2190
  str.remove(attr.start, attr.start + 'let:'.length);
2148
- if (hasMoved) {
2191
+ if (hasMovedLet) {
2149
2192
  str.appendRight(attr.start + 'let:'.length, ', ');
2150
2193
  }
2151
2194
  templateScope.inits.add(((_a = attr.expression) === null || _a === void 0 ? void 0 : _a.name) || attr.name);
2152
- hasMoved = true;
2195
+ hasMovedLet = true;
2153
2196
  if (attr.expression) {
2154
2197
  //overwrite the = as a :
2155
2198
  const equalSign = htmlx.lastIndexOf('=', attr.expression.start);
@@ -2158,13 +2201,34 @@ function handleSlot(htmlx, str, slotEl, component, slotName, ifScope, templateSc
2158
2201
  str.remove(attr.expression.end, attr.end);
2159
2202
  }
2160
2203
  }
2161
- if (!hasMoved) {
2204
+ const hasConstTag = slotEl.children.some((child) => child.type === 'ConstTag');
2205
+ if (!hasMovedLet && !hasConstTag) {
2162
2206
  return;
2163
2207
  }
2208
+ calculateSlotDefInsertionPoint();
2164
2209
  const { singleSlotDef, constRedeclares } = getSingleSlotDefAndConstsRedeclaration(component, slotName, str.original, ifScope, slotElIsComponent);
2165
2210
  const prefix = constRedeclares ? `() => {${constRedeclares}` : '';
2166
- str.appendLeft(slotDefInsertionPoint, `{${prefix}() => { let {`);
2167
- str.appendRight(slotDefInsertionPoint, `} = ${singleSlotDef}` + `;${ifScope.addPossibleIfCondition()}<>`);
2211
+ str.appendLeft(slotDefInsertionPoint, `{${prefix}() => { `);
2212
+ if (hasMovedLet) {
2213
+ str.appendLeft(slotDefInsertionPoint, 'let {');
2214
+ str.appendRight(slotDefInsertionPoint, `} = ${singleSlotDef};`);
2215
+ }
2216
+ if (hasConstTag) {
2217
+ // unable to move multiple codes to the same place while insert code in between
2218
+ // NOTE: cheat by move to `slotDefInsertionPoint + 1` position
2219
+ // then copy the character in str[slotDefInsertionPoint...slotDefInsertionPoint + 1] to the back
2220
+ // and comment out the original str[slotDefInsertionPoint...slotDefInsertionPoint + 1]
2221
+ str.appendRight(slotDefInsertionPoint, '/*');
2222
+ extractConstTags(slotEl.children).forEach((insertion) => {
2223
+ insertion(slotDefInsertionPoint + 1, str);
2224
+ });
2225
+ str.appendRight(slotDefInsertionPoint + 1, `${ifScope.addPossibleIfCondition()}<>`);
2226
+ str.appendRight(slotDefInsertionPoint + 1, str.original.slice(slotDefInsertionPoint, slotDefInsertionPoint + 1));
2227
+ str.appendLeft(slotDefInsertionPoint + 1, '*/');
2228
+ }
2229
+ else {
2230
+ str.appendRight(slotDefInsertionPoint, `${ifScope.addPossibleIfCondition()}<>`);
2231
+ }
2168
2232
  const closeSlotDefInsertionPoint = slotElIsComponent
2169
2233
  ? htmlx.lastIndexOf('<', slotEl.end - 1)
2170
2234
  : slotEl.end;
@@ -2250,7 +2314,11 @@ function handleEach(htmlx, str, eachBlock, ifScope) {
2250
2314
  const idxLoc = htmlx.indexOf(eachBlock.index, contextEnd);
2251
2315
  contextEnd = idxLoc + eachBlock.index.length;
2252
2316
  }
2253
- str.prependLeft(contextEnd, ') =>');
2317
+ const constTags = extractConstTags(eachBlock.children);
2318
+ str.prependLeft(contextEnd, ') =>' + (constTags.length ? ' {' : ''));
2319
+ constTags.forEach((insertion) => {
2320
+ insertion(contextEnd, str);
2321
+ });
2254
2322
  if (eachBlock.key) {
2255
2323
  const endEachStart = htmlx.indexOf('}', eachBlock.key.end);
2256
2324
  str.overwrite(endEachStart, endEachStart + 1, ` && ${ifScope.addPossibleIfCondition()}<>`);
@@ -2260,8 +2328,8 @@ function handleEach(htmlx, str, eachBlock, ifScope) {
2260
2328
  str.overwrite(endEachStart, endEachStart + 1, ` ${ifScope.addPossibleIfCondition()}<>`);
2261
2329
  }
2262
2330
  const endEach = htmlx.lastIndexOf('{', eachBlock.end - 1);
2263
- const suffix = constRedeclares ? '</>)}}}' : '</>)}';
2264
- // {/each} -> </>)} or {:else} -> </>)}
2331
+ const suffix = '</>' + (constTags.length ? '}' : '') + (constRedeclares ? ')}}}' : ')}');
2332
+ // {/each} -> </>})} or {:else} -> </>})}
2265
2333
  if (eachBlock.else) {
2266
2334
  const elseEnd = htmlx.lastIndexOf('}', eachBlock.else.start);
2267
2335
  const elseStart = htmlx.lastIndexOf('{', elseEnd);
@@ -2679,6 +2747,40 @@ function handleRawHtml(htmlx, str, rawBlock) {
2679
2747
  str.remove(tokenStart, tokenStart + '@html'.length);
2680
2748
  }
2681
2749
 
2750
+ /**
2751
+ * style:xx ---> __sveltets_1_ensureType(String, xx);
2752
+ * style:xx={yy} ---> __sveltets_1_ensureType(String, yy);
2753
+ * style:xx="yy" ---> __sveltets_1_ensureType(String, "yy");
2754
+ * style:xx="a{b}" ---> __sveltets_1_ensureType(String, `a${b}`);
2755
+ */
2756
+ function handleStyleDirective(str, style) {
2757
+ const htmlx = str.original;
2758
+ if (style.value === true || style.value.length === 0) {
2759
+ str.overwrite(style.start, htmlx.indexOf(':', style.start) + 1, '{...__sveltets_1_ensureType(String, ');
2760
+ str.appendLeft(style.end, ')}');
2761
+ return;
2762
+ }
2763
+ if (style.value.length > 1) {
2764
+ buildTemplateString(style, str, htmlx, '{...__sveltets_1_ensureType(String, `', '`)}', style.start);
2765
+ return;
2766
+ }
2767
+ const styleVal = style.value[0];
2768
+ if (styleVal.type === 'Text') {
2769
+ str.overwrite(style.start, styleVal.start, '{...__sveltets_1_ensureType(String, "');
2770
+ if (styleVal.end === style.end) {
2771
+ str.appendLeft(style.end, '")}');
2772
+ }
2773
+ else {
2774
+ str.overwrite(styleVal.end, style.end, '")}');
2775
+ }
2776
+ }
2777
+ else {
2778
+ // MustacheTag
2779
+ str.overwrite(style.start, styleVal.start + 1, '{...__sveltets_1_ensureType(String, ');
2780
+ str.overwrite(styleVal.end - 1, style.end, ')}');
2781
+ }
2782
+ }
2783
+
2682
2784
  /**
2683
2785
  * `<svelte:window>...</svelte:window>` ----> `<sveltewindow>...</sveltewindow>`
2684
2786
  * (same for :head, :body, :options, :fragment)
@@ -2770,7 +2872,7 @@ class TemplateScopeManager {
2770
2872
  eachEnter(node) {
2771
2873
  this.value = this.value.child();
2772
2874
  if (node.context) {
2773
- this.handleScope(node.context);
2875
+ this.handleScope(node.context, node.children);
2774
2876
  }
2775
2877
  if (node.index) {
2776
2878
  this.value.inits.add(node.index);
@@ -2782,12 +2884,13 @@ class TemplateScopeManager {
2782
2884
  }
2783
2885
  }
2784
2886
  awaitEnter(node) {
2887
+ var _a;
2785
2888
  this.value = this.value.child();
2786
2889
  if (node.value) {
2787
- this.handleScope(node.value);
2890
+ this.handleScope(node.value, (_a = node.then) === null || _a === void 0 ? void 0 : _a.children);
2788
2891
  }
2789
2892
  if (node.error) {
2790
- this.handleScope(node.error);
2893
+ this.handleScope(node.error, []);
2791
2894
  }
2792
2895
  }
2793
2896
  awaitPendingEnter(node, parent) {
@@ -2805,7 +2908,7 @@ class TemplateScopeManager {
2805
2908
  // scope into account.
2806
2909
  this.value.inits.clear();
2807
2910
  if (parent.value) {
2808
- this.handleScope(parent.value);
2911
+ this.handleScope(parent.value, node.children);
2809
2912
  }
2810
2913
  }
2811
2914
  awaitCatchEnter(node, parent) {
@@ -2816,7 +2919,7 @@ class TemplateScopeManager {
2816
2919
  // scope into account.
2817
2920
  this.value.inits.clear();
2818
2921
  if (parent.error) {
2819
- this.handleScope(parent.error);
2922
+ this.handleScope(parent.error, node.children);
2820
2923
  }
2821
2924
  }
2822
2925
  awaitLeave() {
@@ -2828,8 +2931,11 @@ class TemplateScopeManager {
2828
2931
  }
2829
2932
  }
2830
2933
  componentOrSlotTemplateOrElementEnter(node) {
2831
- if (usesLet(node)) {
2934
+ var _a;
2935
+ const hasConstTags = (_a = node.children) === null || _a === void 0 ? void 0 : _a.some((child) => child.type === 'ConstTag');
2936
+ if (usesLet(node) || hasConstTags) {
2832
2937
  this.value = this.value.child();
2938
+ this.handleScope({}, node.children);
2833
2939
  }
2834
2940
  }
2835
2941
  componentOrSlotTemplateOrElementLeave(node) {
@@ -2837,7 +2943,7 @@ class TemplateScopeManager {
2837
2943
  this.value = this.value.parent;
2838
2944
  }
2839
2945
  }
2840
- handleScope(identifierDef) {
2946
+ handleScope(identifierDef, children) {
2841
2947
  if (isIdentifier(identifierDef)) {
2842
2948
  this.value.inits.add(identifierDef.name);
2843
2949
  }
@@ -2846,6 +2952,14 @@ class TemplateScopeManager {
2846
2952
  const identifiers = extract_identifiers(identifierDef);
2847
2953
  identifiers.forEach((id) => this.value.inits.add(id.name));
2848
2954
  }
2955
+ if (children === null || children === void 0 ? void 0 : children.length) {
2956
+ children.forEach((child) => {
2957
+ if (child.type === 'ConstTag') {
2958
+ const identifiers = extract_identifiers(child.expression.left);
2959
+ identifiers.forEach((id) => this.value.inits.add(id.name));
2960
+ }
2961
+ });
2962
+ }
2849
2963
  }
2850
2964
  }
2851
2965
 
@@ -2961,6 +3075,9 @@ function convertHtmlxToJsx(str, ast, onWalk = null, onLeave = null, options = {}
2961
3075
  case 'Class':
2962
3076
  handleClassDirective(str, node);
2963
3077
  break;
3078
+ case 'StyleDirective':
3079
+ handleStyleDirective(str, node);
3080
+ break;
2964
3081
  case 'Action':
2965
3082
  handleActionDirective(htmlx, str, node, parent);
2966
3083
  break;
@@ -2991,9 +3108,7 @@ function convertHtmlxToJsx(str, ast, onWalk = null, onLeave = null, options = {}
2991
3108
  case 'SlotTemplate':
2992
3109
  handleSvelteTag(htmlx, str, node);
2993
3110
  templateScopeManager.componentOrSlotTemplateOrElementEnter(node);
2994
- if (usesLet(node)) {
2995
- handleSlot(htmlx, str, node, parent, getSlotName(node) || 'default', ifScope, templateScopeManager.value);
2996
- }
3111
+ handleSlot(htmlx, str, node, parent, getSlotName(node) || 'default', ifScope, templateScopeManager.value);
2997
3112
  break;
2998
3113
  case 'Text':
2999
3114
  handleText(str, node);
package/index.mjs CHANGED
@@ -1647,6 +1647,21 @@ function usesLet(node) {
1647
1647
  var _a;
1648
1648
  return (_a = node.attributes) === null || _a === void 0 ? void 0 : _a.some((attr) => attr.type === 'Let');
1649
1649
  }
1650
+ function buildTemplateString(attr, str, htmlx, leadingOverride, trailingOverride, overrideStart) {
1651
+ overrideStart = overrideStart !== null && overrideStart !== void 0 ? overrideStart : htmlx.lastIndexOf('=', attr.value[0].start);
1652
+ str.overwrite(overrideStart, attr.value[0].start, leadingOverride);
1653
+ for (const n of attr.value) {
1654
+ if (n.type == 'MustacheTag') {
1655
+ str.appendRight(n.start, '$');
1656
+ }
1657
+ }
1658
+ if (isQuote(htmlx[attr.end - 1])) {
1659
+ str.overwrite(attr.end - 1, attr.end, trailingOverride);
1660
+ }
1661
+ else {
1662
+ str.appendLeft(attr.end, trailingOverride);
1663
+ }
1664
+ }
1650
1665
 
1651
1666
  /**
1652
1667
  * use:xxx={params} ---> {...__sveltets_1_ensureAction(xxx(__sveltets_1_mapElementTag('ParentNodeName'),(params)))}
@@ -1849,21 +1864,6 @@ function handleAttribute(htmlx, str, attr, parent, preserveCase) {
1849
1864
  // We have multiple attribute values, so we build a template string out of them.
1850
1865
  buildTemplateString(attr, str, htmlx, shouldApplySlotCheck ? `={${ensureSlotStr}\`` : '={`', shouldApplySlotCheck ? '`)}' : '`}');
1851
1866
  }
1852
- function buildTemplateString(attr, str, htmlx, leadingOverride, trailingOverride) {
1853
- const equals = htmlx.lastIndexOf('=', attr.value[0].start);
1854
- str.overwrite(equals, attr.value[0].start, leadingOverride);
1855
- for (const n of attr.value) {
1856
- if (n.type == 'MustacheTag') {
1857
- str.appendRight(n.start, '$');
1858
- }
1859
- }
1860
- if (isQuote(htmlx[attr.end - 1])) {
1861
- str.overwrite(attr.end - 1, attr.end, trailingOverride);
1862
- }
1863
- else {
1864
- str.appendLeft(attr.end, trailingOverride);
1865
- }
1866
- }
1867
1867
  function sanitizeLeadingChars(attrName) {
1868
1868
  let sanitizedName = '';
1869
1869
  for (let i = 0; i < attrName.length; i++) {
@@ -1878,6 +1878,24 @@ function sanitizeLeadingChars(attrName) {
1878
1878
  return sanitizedName;
1879
1879
  }
1880
1880
 
1881
+ function extractConstTags(children) {
1882
+ const tags = [];
1883
+ for (const child of children) {
1884
+ if (child.type === 'ConstTag') {
1885
+ const constTag = child;
1886
+ tags.push((insertionPoint, str) => {
1887
+ str.appendRight(constTag.expression.left.start, 'const ');
1888
+ str.move(constTag.expression.left.start, constTag.expression.right.end, insertionPoint);
1889
+ str.appendLeft(constTag.expression.right.end, ';');
1890
+ str.overwrite(constTag.start + 1, constTag.expression.left.start - 1, '', {
1891
+ contentOnly: true
1892
+ });
1893
+ });
1894
+ }
1895
+ }
1896
+ return tags;
1897
+ }
1898
+
1881
1899
  /**
1882
1900
  * Transform {#await ...} into something JSX understands
1883
1901
  */
@@ -1943,16 +1961,24 @@ function handleAwaitThen(awaitBlock, htmlx, str, ifScope) {
1943
1961
  }
1944
1962
  if (awaitBlock.value) {
1945
1963
  str.overwrite(thenStart, awaitBlock.value.start, '__sveltets_1_awaitThen(_$$p, (');
1946
- str.overwrite(awaitBlock.value.end, thenEnd, `) => {${ifScope.addPossibleIfCondition()}<>`);
1964
+ str.overwrite(awaitBlock.value.end, thenEnd, ') => {');
1965
+ extractConstTags(awaitBlock.then.children).forEach((insertion) => {
1966
+ insertion(thenEnd, str);
1967
+ });
1968
+ str.appendRight(thenEnd, `${ifScope.addPossibleIfCondition()}<>`);
1947
1969
  }
1948
1970
  else {
1949
- const awaitThenFn = `__sveltets_1_awaitThen(_$$p, () => {${ifScope.addPossibleIfCondition()}<>`; // eslint-disable-line
1971
+ const awaitThenFn = '__sveltets_1_awaitThen(_$$p, () => {';
1950
1972
  if (thenStart === thenEnd) {
1951
1973
  str.appendLeft(thenStart, awaitThenFn);
1952
1974
  }
1953
1975
  else {
1954
1976
  str.overwrite(thenStart, thenEnd, awaitThenFn);
1955
1977
  }
1978
+ extractConstTags(awaitBlock.then.children).forEach((insertion) => {
1979
+ insertion(thenEnd, str);
1980
+ });
1981
+ str.appendRight(thenEnd, `${ifScope.addPossibleIfCondition()}<>`); // eslint-disable-line
1956
1982
  }
1957
1983
  }
1958
1984
  function handleAwaitCatch(awaitBlock, htmlx, str, ifScope) {
@@ -1964,12 +1990,20 @@ function handleAwaitCatch(awaitBlock, htmlx, str, ifScope) {
1964
1990
  // {#await ... catch ...}
1965
1991
  const catchBegin = htmlx.indexOf('}', awaitBlock.error.end) + 1;
1966
1992
  str.overwrite(awaitBlock.expression.end, awaitBlock.error.start, '); __sveltets_1_awaitThen(_$$p, () => {}, (');
1967
- str.overwrite(awaitBlock.error.end, catchBegin, ') => {<>');
1993
+ str.overwrite(awaitBlock.error.end, catchBegin, ') => {');
1994
+ extractConstTags(awaitBlock.catch.children).forEach((insertion) => {
1995
+ insertion(catchBegin, str);
1996
+ });
1997
+ str.appendRight(catchBegin, '<>');
1968
1998
  }
1969
1999
  else {
1970
2000
  // {#await ... catch}
1971
2001
  const catchBegin = htmlx.indexOf('}', awaitBlock.expression.end) + 1;
1972
- str.overwrite(awaitBlock.expression.end, catchBegin, '); __sveltets_1_awaitThen(_$$p, () => {}, () => {<>');
2002
+ str.overwrite(awaitBlock.expression.end, catchBegin, '); __sveltets_1_awaitThen(_$$p, () => {}, () => {');
2003
+ extractConstTags(awaitBlock.catch.children).forEach((insertion) => {
2004
+ insertion(catchBegin, str);
2005
+ });
2006
+ str.appendRight(catchBegin, '<>');
1973
2007
  }
1974
2008
  }
1975
2009
  else {
@@ -1982,7 +2016,11 @@ function handleAwaitCatch(awaitBlock, htmlx, str, ifScope) {
1982
2016
  const errorEnd = awaitBlock.error ? awaitBlock.error.end : errorStart;
1983
2017
  const catchEnd = htmlx.indexOf('}', errorEnd) + 1;
1984
2018
  str.overwrite(catchStart, errorStart, '</>}, (');
1985
- str.overwrite(errorEnd, catchEnd, `) => {${ifScope.addPossibleIfCondition()}<>`);
2019
+ str.overwrite(errorEnd, catchEnd, ') => {');
2020
+ extractConstTags(awaitBlock.catch.children).forEach((insertion) => {
2021
+ insertion(catchEnd, str);
2022
+ });
2023
+ str.appendRight(catchEnd, `${ifScope.addPossibleIfCondition()}<>`);
1986
2024
  }
1987
2025
  }
1988
2026
 
@@ -2090,14 +2128,23 @@ function handleComment(str, node) {
2090
2128
 
2091
2129
  const shadowedPropsSymbol = Symbol('shadowedProps');
2092
2130
  /**
2093
- * Transforms the usage of a slot (let:xx)
2131
+ * Transforms the usage of a slot (slot="xxx")
2132
+ * - transforms let:xx, {@const xx}
2094
2133
  */
2095
2134
  function handleSlot(htmlx, str, slotEl, component, slotName, ifScope, templateScope) {
2096
2135
  var _a;
2097
2136
  //collect "let" definitions
2098
2137
  const slotElIsComponent = slotEl === component;
2099
- let hasMoved = false;
2138
+ let hasMovedLet = false;
2100
2139
  let slotDefInsertionPoint;
2140
+ // lazily calculate insertion point only when needed
2141
+ const calculateSlotDefInsertionPoint = () => {
2142
+ slotDefInsertionPoint =
2143
+ slotDefInsertionPoint ||
2144
+ (slotElIsComponent
2145
+ ? htmlx.lastIndexOf('>', slotEl.children[0].start) + 1
2146
+ : slotEl.start);
2147
+ };
2101
2148
  for (const attr of slotEl.attributes) {
2102
2149
  if (attr.type != 'Let') {
2103
2150
  continue;
@@ -2107,19 +2154,15 @@ function handleSlot(htmlx, str, slotEl, component, slotName, ifScope, templateSc
2107
2154
  str.remove(attr.start, attr.end);
2108
2155
  continue;
2109
2156
  }
2110
- slotDefInsertionPoint =
2111
- slotDefInsertionPoint ||
2112
- (slotElIsComponent
2113
- ? htmlx.lastIndexOf('>', slotEl.children[0].start) + 1
2114
- : slotEl.start);
2157
+ calculateSlotDefInsertionPoint();
2115
2158
  str.move(attr.start, attr.end, slotDefInsertionPoint);
2116
2159
  //remove let:
2117
2160
  str.remove(attr.start, attr.start + 'let:'.length);
2118
- if (hasMoved) {
2161
+ if (hasMovedLet) {
2119
2162
  str.appendRight(attr.start + 'let:'.length, ', ');
2120
2163
  }
2121
2164
  templateScope.inits.add(((_a = attr.expression) === null || _a === void 0 ? void 0 : _a.name) || attr.name);
2122
- hasMoved = true;
2165
+ hasMovedLet = true;
2123
2166
  if (attr.expression) {
2124
2167
  //overwrite the = as a :
2125
2168
  const equalSign = htmlx.lastIndexOf('=', attr.expression.start);
@@ -2128,13 +2171,34 @@ function handleSlot(htmlx, str, slotEl, component, slotName, ifScope, templateSc
2128
2171
  str.remove(attr.expression.end, attr.end);
2129
2172
  }
2130
2173
  }
2131
- if (!hasMoved) {
2174
+ const hasConstTag = slotEl.children.some((child) => child.type === 'ConstTag');
2175
+ if (!hasMovedLet && !hasConstTag) {
2132
2176
  return;
2133
2177
  }
2178
+ calculateSlotDefInsertionPoint();
2134
2179
  const { singleSlotDef, constRedeclares } = getSingleSlotDefAndConstsRedeclaration(component, slotName, str.original, ifScope, slotElIsComponent);
2135
2180
  const prefix = constRedeclares ? `() => {${constRedeclares}` : '';
2136
- str.appendLeft(slotDefInsertionPoint, `{${prefix}() => { let {`);
2137
- str.appendRight(slotDefInsertionPoint, `} = ${singleSlotDef}` + `;${ifScope.addPossibleIfCondition()}<>`);
2181
+ str.appendLeft(slotDefInsertionPoint, `{${prefix}() => { `);
2182
+ if (hasMovedLet) {
2183
+ str.appendLeft(slotDefInsertionPoint, 'let {');
2184
+ str.appendRight(slotDefInsertionPoint, `} = ${singleSlotDef};`);
2185
+ }
2186
+ if (hasConstTag) {
2187
+ // unable to move multiple codes to the same place while insert code in between
2188
+ // NOTE: cheat by move to `slotDefInsertionPoint + 1` position
2189
+ // then copy the character in str[slotDefInsertionPoint...slotDefInsertionPoint + 1] to the back
2190
+ // and comment out the original str[slotDefInsertionPoint...slotDefInsertionPoint + 1]
2191
+ str.appendRight(slotDefInsertionPoint, '/*');
2192
+ extractConstTags(slotEl.children).forEach((insertion) => {
2193
+ insertion(slotDefInsertionPoint + 1, str);
2194
+ });
2195
+ str.appendRight(slotDefInsertionPoint + 1, `${ifScope.addPossibleIfCondition()}<>`);
2196
+ str.appendRight(slotDefInsertionPoint + 1, str.original.slice(slotDefInsertionPoint, slotDefInsertionPoint + 1));
2197
+ str.appendLeft(slotDefInsertionPoint + 1, '*/');
2198
+ }
2199
+ else {
2200
+ str.appendRight(slotDefInsertionPoint, `${ifScope.addPossibleIfCondition()}<>`);
2201
+ }
2138
2202
  const closeSlotDefInsertionPoint = slotElIsComponent
2139
2203
  ? htmlx.lastIndexOf('<', slotEl.end - 1)
2140
2204
  : slotEl.end;
@@ -2220,7 +2284,11 @@ function handleEach(htmlx, str, eachBlock, ifScope) {
2220
2284
  const idxLoc = htmlx.indexOf(eachBlock.index, contextEnd);
2221
2285
  contextEnd = idxLoc + eachBlock.index.length;
2222
2286
  }
2223
- str.prependLeft(contextEnd, ') =>');
2287
+ const constTags = extractConstTags(eachBlock.children);
2288
+ str.prependLeft(contextEnd, ') =>' + (constTags.length ? ' {' : ''));
2289
+ constTags.forEach((insertion) => {
2290
+ insertion(contextEnd, str);
2291
+ });
2224
2292
  if (eachBlock.key) {
2225
2293
  const endEachStart = htmlx.indexOf('}', eachBlock.key.end);
2226
2294
  str.overwrite(endEachStart, endEachStart + 1, ` && ${ifScope.addPossibleIfCondition()}<>`);
@@ -2230,8 +2298,8 @@ function handleEach(htmlx, str, eachBlock, ifScope) {
2230
2298
  str.overwrite(endEachStart, endEachStart + 1, ` ${ifScope.addPossibleIfCondition()}<>`);
2231
2299
  }
2232
2300
  const endEach = htmlx.lastIndexOf('{', eachBlock.end - 1);
2233
- const suffix = constRedeclares ? '</>)}}}' : '</>)}';
2234
- // {/each} -> </>)} or {:else} -> </>)}
2301
+ const suffix = '</>' + (constTags.length ? '}' : '') + (constRedeclares ? ')}}}' : ')}');
2302
+ // {/each} -> </>})} or {:else} -> </>})}
2235
2303
  if (eachBlock.else) {
2236
2304
  const elseEnd = htmlx.lastIndexOf('}', eachBlock.else.start);
2237
2305
  const elseStart = htmlx.lastIndexOf('{', elseEnd);
@@ -2649,6 +2717,40 @@ function handleRawHtml(htmlx, str, rawBlock) {
2649
2717
  str.remove(tokenStart, tokenStart + '@html'.length);
2650
2718
  }
2651
2719
 
2720
+ /**
2721
+ * style:xx ---> __sveltets_1_ensureType(String, xx);
2722
+ * style:xx={yy} ---> __sveltets_1_ensureType(String, yy);
2723
+ * style:xx="yy" ---> __sveltets_1_ensureType(String, "yy");
2724
+ * style:xx="a{b}" ---> __sveltets_1_ensureType(String, `a${b}`);
2725
+ */
2726
+ function handleStyleDirective(str, style) {
2727
+ const htmlx = str.original;
2728
+ if (style.value === true || style.value.length === 0) {
2729
+ str.overwrite(style.start, htmlx.indexOf(':', style.start) + 1, '{...__sveltets_1_ensureType(String, ');
2730
+ str.appendLeft(style.end, ')}');
2731
+ return;
2732
+ }
2733
+ if (style.value.length > 1) {
2734
+ buildTemplateString(style, str, htmlx, '{...__sveltets_1_ensureType(String, `', '`)}', style.start);
2735
+ return;
2736
+ }
2737
+ const styleVal = style.value[0];
2738
+ if (styleVal.type === 'Text') {
2739
+ str.overwrite(style.start, styleVal.start, '{...__sveltets_1_ensureType(String, "');
2740
+ if (styleVal.end === style.end) {
2741
+ str.appendLeft(style.end, '")}');
2742
+ }
2743
+ else {
2744
+ str.overwrite(styleVal.end, style.end, '")}');
2745
+ }
2746
+ }
2747
+ else {
2748
+ // MustacheTag
2749
+ str.overwrite(style.start, styleVal.start + 1, '{...__sveltets_1_ensureType(String, ');
2750
+ str.overwrite(styleVal.end - 1, style.end, ')}');
2751
+ }
2752
+ }
2753
+
2652
2754
  /**
2653
2755
  * `<svelte:window>...</svelte:window>` ----> `<sveltewindow>...</sveltewindow>`
2654
2756
  * (same for :head, :body, :options, :fragment)
@@ -2740,7 +2842,7 @@ class TemplateScopeManager {
2740
2842
  eachEnter(node) {
2741
2843
  this.value = this.value.child();
2742
2844
  if (node.context) {
2743
- this.handleScope(node.context);
2845
+ this.handleScope(node.context, node.children);
2744
2846
  }
2745
2847
  if (node.index) {
2746
2848
  this.value.inits.add(node.index);
@@ -2752,12 +2854,13 @@ class TemplateScopeManager {
2752
2854
  }
2753
2855
  }
2754
2856
  awaitEnter(node) {
2857
+ var _a;
2755
2858
  this.value = this.value.child();
2756
2859
  if (node.value) {
2757
- this.handleScope(node.value);
2860
+ this.handleScope(node.value, (_a = node.then) === null || _a === void 0 ? void 0 : _a.children);
2758
2861
  }
2759
2862
  if (node.error) {
2760
- this.handleScope(node.error);
2863
+ this.handleScope(node.error, []);
2761
2864
  }
2762
2865
  }
2763
2866
  awaitPendingEnter(node, parent) {
@@ -2775,7 +2878,7 @@ class TemplateScopeManager {
2775
2878
  // scope into account.
2776
2879
  this.value.inits.clear();
2777
2880
  if (parent.value) {
2778
- this.handleScope(parent.value);
2881
+ this.handleScope(parent.value, node.children);
2779
2882
  }
2780
2883
  }
2781
2884
  awaitCatchEnter(node, parent) {
@@ -2786,7 +2889,7 @@ class TemplateScopeManager {
2786
2889
  // scope into account.
2787
2890
  this.value.inits.clear();
2788
2891
  if (parent.error) {
2789
- this.handleScope(parent.error);
2892
+ this.handleScope(parent.error, node.children);
2790
2893
  }
2791
2894
  }
2792
2895
  awaitLeave() {
@@ -2798,8 +2901,11 @@ class TemplateScopeManager {
2798
2901
  }
2799
2902
  }
2800
2903
  componentOrSlotTemplateOrElementEnter(node) {
2801
- if (usesLet(node)) {
2904
+ var _a;
2905
+ const hasConstTags = (_a = node.children) === null || _a === void 0 ? void 0 : _a.some((child) => child.type === 'ConstTag');
2906
+ if (usesLet(node) || hasConstTags) {
2802
2907
  this.value = this.value.child();
2908
+ this.handleScope({}, node.children);
2803
2909
  }
2804
2910
  }
2805
2911
  componentOrSlotTemplateOrElementLeave(node) {
@@ -2807,7 +2913,7 @@ class TemplateScopeManager {
2807
2913
  this.value = this.value.parent;
2808
2914
  }
2809
2915
  }
2810
- handleScope(identifierDef) {
2916
+ handleScope(identifierDef, children) {
2811
2917
  if (isIdentifier(identifierDef)) {
2812
2918
  this.value.inits.add(identifierDef.name);
2813
2919
  }
@@ -2816,6 +2922,14 @@ class TemplateScopeManager {
2816
2922
  const identifiers = extract_identifiers(identifierDef);
2817
2923
  identifiers.forEach((id) => this.value.inits.add(id.name));
2818
2924
  }
2925
+ if (children === null || children === void 0 ? void 0 : children.length) {
2926
+ children.forEach((child) => {
2927
+ if (child.type === 'ConstTag') {
2928
+ const identifiers = extract_identifiers(child.expression.left);
2929
+ identifiers.forEach((id) => this.value.inits.add(id.name));
2930
+ }
2931
+ });
2932
+ }
2819
2933
  }
2820
2934
  }
2821
2935
 
@@ -2931,6 +3045,9 @@ function convertHtmlxToJsx(str, ast, onWalk = null, onLeave = null, options = {}
2931
3045
  case 'Class':
2932
3046
  handleClassDirective(str, node);
2933
3047
  break;
3048
+ case 'StyleDirective':
3049
+ handleStyleDirective(str, node);
3050
+ break;
2934
3051
  case 'Action':
2935
3052
  handleActionDirective(htmlx, str, node, parent);
2936
3053
  break;
@@ -2961,9 +3078,7 @@ function convertHtmlxToJsx(str, ast, onWalk = null, onLeave = null, options = {}
2961
3078
  case 'SlotTemplate':
2962
3079
  handleSvelteTag(htmlx, str, node);
2963
3080
  templateScopeManager.componentOrSlotTemplateOrElementEnter(node);
2964
- if (usesLet(node)) {
2965
- handleSlot(htmlx, str, node, parent, getSlotName(node) || 'default', ifScope, templateScopeManager.value);
2966
- }
3081
+ handleSlot(htmlx, str, node, parent, getSlotName(node) || 'default', ifScope, templateScopeManager.value);
2967
3082
  break;
2968
3083
  case 'Text':
2969
3084
  handleText(str, node);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "svelte2tsx",
3
- "version": "0.4.13",
3
+ "version": "0.4.14",
4
4
  "description": "Convert Svelte components to TSX for type checking",
5
5
  "author": "David Pershouse",
6
6
  "license": "MIT",
@@ -34,7 +34,7 @@
34
34
  "source-map": "^0.6.1",
35
35
  "source-map-support": "^0.5.16",
36
36
  "sourcemap-codec": "^1.4.8",
37
- "svelte": "~3.44.3",
37
+ "svelte": "~3.46.1",
38
38
  "tiny-glob": "^0.2.6",
39
39
  "tslib": "^1.10.0",
40
40
  "typescript": "^4.5.3"