svelte2tsx 0.7.29 → 0.7.31
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/index.js +116 -39
- package/index.mjs +116 -39
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -1673,10 +1673,10 @@ function parseHtmlx(htmlx, parse, options) {
|
|
|
1673
1673
|
const verbatimElements = findVerbatimElements(htmlx);
|
|
1674
1674
|
const deconstructed = blankVerbatimContent(htmlx, verbatimElements);
|
|
1675
1675
|
//extract the html content parsed as htmlx this excludes our script and style tags
|
|
1676
|
-
const parsingCode = options.emitOnTemplateError
|
|
1676
|
+
const parsingCode = options.emitOnTemplateError && !options.svelte5Plus
|
|
1677
1677
|
? blankPossiblyErrorOperatorOrPropertyAccess(deconstructed)
|
|
1678
1678
|
: deconstructed;
|
|
1679
|
-
const htmlxAst = parse(parsingCode).html;
|
|
1679
|
+
const htmlxAst = parse(parsingCode, options.svelte5Plus ? { loose: options.emitOnTemplateError } : undefined).html;
|
|
1680
1680
|
//restore our script and style tags as nodes to maintain validity with HTMLx
|
|
1681
1681
|
for (const s of verbatimElements) {
|
|
1682
1682
|
htmlxAst.children.push(s);
|
|
@@ -1760,8 +1760,7 @@ function handleActionDirective(attr, element) {
|
|
|
1760
1760
|
* you may need to find a different way because MagicString does not allow us to move a range
|
|
1761
1761
|
* that goes from `start` to `end` to the `end` position.
|
|
1762
1762
|
*/
|
|
1763
|
-
function transform(str, start, end,
|
|
1764
|
-
transformations) {
|
|
1763
|
+
function transform(str, start, end, transformations) {
|
|
1765
1764
|
var _a, _b;
|
|
1766
1765
|
const moves = [];
|
|
1767
1766
|
let appendPosition = end;
|
|
@@ -1853,6 +1852,10 @@ transformations) {
|
|
|
1853
1852
|
}
|
|
1854
1853
|
}
|
|
1855
1854
|
for (let i = deletePos; i < moves.length; i++) {
|
|
1855
|
+
// Can happen when there's not enough space left at the end of an unfininished element/component tag.
|
|
1856
|
+
// Better to leave potentially slightly disarranged code than fail loudly
|
|
1857
|
+
if (moves[i][1] >= end && moves[i][0] <= end)
|
|
1858
|
+
break;
|
|
1856
1859
|
str.move(moves[i][0], moves[i][1], end);
|
|
1857
1860
|
}
|
|
1858
1861
|
}
|
|
@@ -1936,6 +1939,22 @@ function isTypescriptNode(node) {
|
|
|
1936
1939
|
node.type === 'TSSatisfiesExpression' ||
|
|
1937
1940
|
node.type === 'TSNonNullExpression');
|
|
1938
1941
|
}
|
|
1942
|
+
/**
|
|
1943
|
+
* Returns `true` if the given block is implicitly closed, which could be the case in loose parsing mode.
|
|
1944
|
+
* E.g.:
|
|
1945
|
+
* ```html
|
|
1946
|
+
* <div>
|
|
1947
|
+
* {#if x}
|
|
1948
|
+
* </div>
|
|
1949
|
+
* ```
|
|
1950
|
+
* @param end
|
|
1951
|
+
* @param block
|
|
1952
|
+
* @returns
|
|
1953
|
+
*/
|
|
1954
|
+
function isImplicitlyClosedBlock(end, block) {
|
|
1955
|
+
var _a, _b;
|
|
1956
|
+
return end < ((_b = (_a = block.children[block.children.length - 1]) === null || _a === void 0 ? void 0 : _a.end) !== null && _b !== void 0 ? _b : block.expression.end);
|
|
1957
|
+
}
|
|
1939
1958
|
|
|
1940
1959
|
/**
|
|
1941
1960
|
* animate:xxx(yyy) ---> __sveltets_2_ensureAnimation(xxx(svelte.mapElementTag('..'),__sveltets_2_AnimationMove,(yyy)));
|
|
@@ -2124,7 +2143,7 @@ class Element {
|
|
|
2124
2143
|
this.endTransformation.push('}');
|
|
2125
2144
|
}
|
|
2126
2145
|
if (this.isSelfclosing) {
|
|
2127
|
-
transform(this.str, this.startTagStart, this.startTagEnd,
|
|
2146
|
+
transform(this.str, this.startTagStart, this.startTagEnd, [
|
|
2128
2147
|
// Named slot transformations go first inside a outer block scope because
|
|
2129
2148
|
// <div let:xx {x} /> means "use the x of let:x", and without a separate
|
|
2130
2149
|
// block scope this would give a "used before defined" error
|
|
@@ -2137,7 +2156,7 @@ class Element {
|
|
|
2137
2156
|
]);
|
|
2138
2157
|
}
|
|
2139
2158
|
else {
|
|
2140
|
-
transform(this.str, this.startTagStart, this.startTagEnd,
|
|
2159
|
+
transform(this.str, this.startTagStart, this.startTagEnd, [
|
|
2141
2160
|
...slotLetTransformation,
|
|
2142
2161
|
...this.actionsTransformation,
|
|
2143
2162
|
...this.getStartTransformation(),
|
|
@@ -2149,7 +2168,7 @@ class Element {
|
|
|
2149
2168
|
.lastIndexOf(`</${this.node.name}`);
|
|
2150
2169
|
// tagEndIdx === -1 happens in situations of unclosed tags like `<p>fooo <p>anothertag</p>`
|
|
2151
2170
|
const endStart = tagEndIdx === -1 ? this.node.end : tagEndIdx + this.node.start;
|
|
2152
|
-
transform(this.str, endStart, this.node.end, this.
|
|
2171
|
+
transform(this.str, endStart, this.node.end, this.endTransformation);
|
|
2153
2172
|
}
|
|
2154
2173
|
}
|
|
2155
2174
|
getStartTransformation() {
|
|
@@ -2406,7 +2425,7 @@ class InlineComponent {
|
|
|
2406
2425
|
: '';
|
|
2407
2426
|
if (this.isSelfclosing) {
|
|
2408
2427
|
this.endTransformation.push('}');
|
|
2409
|
-
transform(this.str, this.startTagStart, this.startTagEnd,
|
|
2428
|
+
transform(this.str, this.startTagStart, this.startTagEnd, [
|
|
2410
2429
|
// Named slot transformations go first inside a outer block scope because
|
|
2411
2430
|
// <Comp let:xx {x} /> means "use the x of let:x", and without a separate
|
|
2412
2431
|
// block scope this would give a "used before defined" error
|
|
@@ -2421,15 +2440,23 @@ class InlineComponent {
|
|
|
2421
2440
|
]);
|
|
2422
2441
|
}
|
|
2423
2442
|
else {
|
|
2424
|
-
|
|
2443
|
+
let endStart = this.str.original
|
|
2425
2444
|
.substring(this.node.start, this.node.end)
|
|
2426
|
-
.lastIndexOf(`</${this.node.name}`)
|
|
2427
|
-
if (
|
|
2445
|
+
.lastIndexOf(`</${this.node.name}`);
|
|
2446
|
+
if (endStart === -1) {
|
|
2447
|
+
// Can happen in loose parsing mode when there's no closing tag
|
|
2448
|
+
endStart = this.node.end;
|
|
2449
|
+
this.startTagEnd = this.node.end - 1;
|
|
2450
|
+
}
|
|
2451
|
+
else {
|
|
2452
|
+
endStart += this.node.start;
|
|
2453
|
+
}
|
|
2454
|
+
if (!this.node.name.startsWith('svelte:') && endStart !== this.node.end) {
|
|
2428
2455
|
// Ensure the end tag is mapped, too. </Component> -> Component}
|
|
2429
2456
|
this.endTransformation.push([endStart + 2, endStart + this.node.name.length + 2]);
|
|
2430
2457
|
}
|
|
2431
2458
|
this.endTransformation.push('}');
|
|
2432
|
-
transform(this.str, this.startTagStart, this.startTagEnd,
|
|
2459
|
+
transform(this.str, this.startTagStart, this.startTagEnd, [
|
|
2433
2460
|
// See comment above why this goes first
|
|
2434
2461
|
...namedSlotLetTransformation,
|
|
2435
2462
|
...this.startTransformation,
|
|
@@ -2439,7 +2466,7 @@ class InlineComponent {
|
|
|
2439
2466
|
snippetPropVariablesDeclaration,
|
|
2440
2467
|
...defaultSlotLetTransformation
|
|
2441
2468
|
]);
|
|
2442
|
-
transform(this.str, endStart, this.node.end, this.
|
|
2469
|
+
transform(this.str, endStart, this.node.end, this.endTransformation);
|
|
2443
2470
|
}
|
|
2444
2471
|
}
|
|
2445
2472
|
computeStartTagEnd() {
|
|
@@ -2568,7 +2595,14 @@ function handleAttribute(str, attr, parent, preserveCase, svelte5Plus, element)
|
|
|
2568
2595
|
const attributeName = [];
|
|
2569
2596
|
if (attributeValueIsOfType(attr.value, 'AttributeShorthand')) {
|
|
2570
2597
|
// For the attribute shorthand, the name will be the mapped part
|
|
2571
|
-
|
|
2598
|
+
let [start, end] = [attr.value[0].start, attr.value[0].end];
|
|
2599
|
+
if (start === end) {
|
|
2600
|
+
// Loose parsing mode, we have an empty attribute value, e.g. {}
|
|
2601
|
+
// For proper intellisense we need to make this a non-empty expression.
|
|
2602
|
+
start--;
|
|
2603
|
+
str.overwrite(start, end, ' ', { contentOnly: true });
|
|
2604
|
+
}
|
|
2605
|
+
addAttribute([[start, end]]);
|
|
2572
2606
|
return;
|
|
2573
2607
|
}
|
|
2574
2608
|
else {
|
|
@@ -2640,7 +2674,14 @@ function handleAttribute(str, attr, parent, preserveCase, svelte5Plus, element)
|
|
|
2640
2674
|
addAttribute(attributeName, attributeValue);
|
|
2641
2675
|
}
|
|
2642
2676
|
else if (attrVal.type == 'MustacheTag') {
|
|
2643
|
-
|
|
2677
|
+
let [start, end] = rangeWithTrailingPropertyAccess(str.original, attrVal.expression);
|
|
2678
|
+
if (start === end) {
|
|
2679
|
+
// Loose parsing mode, we have an empty attribute value, e.g. attr={}
|
|
2680
|
+
// For proper intellisense we need to make this a non-empty expression.
|
|
2681
|
+
start--;
|
|
2682
|
+
str.overwrite(start, end, ' ', { contentOnly: true });
|
|
2683
|
+
}
|
|
2684
|
+
attributeValue.push([start, end]);
|
|
2644
2685
|
addAttribute(attributeName, attributeValue);
|
|
2645
2686
|
}
|
|
2646
2687
|
return;
|
|
@@ -2726,7 +2767,7 @@ function handleAwait(str, awaitBlock) {
|
|
|
2726
2767
|
transforms.push('}');
|
|
2727
2768
|
}
|
|
2728
2769
|
transforms.push('}');
|
|
2729
|
-
transform(str, awaitBlock.start, awaitBlock.end,
|
|
2770
|
+
transform(str, awaitBlock.start, awaitBlock.end, transforms);
|
|
2730
2771
|
}
|
|
2731
2772
|
|
|
2732
2773
|
/**
|
|
@@ -2919,17 +2960,18 @@ function handleDebug(str, debugBlock) {
|
|
|
2919
2960
|
* `ensureArray` will error that there are more args than expected
|
|
2920
2961
|
*/
|
|
2921
2962
|
function handleEach(str, eachBlock) {
|
|
2922
|
-
var _a;
|
|
2923
|
-
const startEnd = str.original.indexOf('}', ((_a = eachBlock.key) === null || _a === void 0 ? void 0 : _a.end) || eachBlock.context.end) + 1;
|
|
2963
|
+
var _a, _b, _c;
|
|
2964
|
+
const startEnd = str.original.indexOf('}', ((_a = eachBlock.key) === null || _a === void 0 ? void 0 : _a.end) || ((_b = eachBlock.context) === null || _b === void 0 ? void 0 : _b.end) || eachBlock.expression.end) + 1;
|
|
2924
2965
|
let transforms;
|
|
2925
2966
|
// {#each true, [1,2]} is valid but for (const x of true, [1,2]) is not if not wrapped with braces
|
|
2926
2967
|
const containsComma = str.original
|
|
2927
2968
|
.substring(eachBlock.expression.start, eachBlock.expression.end)
|
|
2928
2969
|
.includes(',');
|
|
2929
2970
|
const expressionEnd = getEnd(eachBlock.expression);
|
|
2930
|
-
const contextEnd = getEnd(eachBlock.context);
|
|
2931
|
-
const arrayAndItemVarTheSame =
|
|
2932
|
-
str.original.substring(eachBlock.
|
|
2971
|
+
const contextEnd = eachBlock.context && getEnd(eachBlock.context);
|
|
2972
|
+
const arrayAndItemVarTheSame = !!eachBlock.context &&
|
|
2973
|
+
str.original.substring(eachBlock.expression.start, expressionEnd) ===
|
|
2974
|
+
str.original.substring(eachBlock.context.start, contextEnd);
|
|
2933
2975
|
if (arrayAndItemVarTheSame) {
|
|
2934
2976
|
transforms = [
|
|
2935
2977
|
`{ const $$_each = __sveltets_2_ensureArray(${containsComma ? '(' : ''}`,
|
|
@@ -2942,21 +2984,21 @@ function handleEach(str, eachBlock) {
|
|
|
2942
2984
|
else {
|
|
2943
2985
|
transforms = [
|
|
2944
2986
|
'for(let ',
|
|
2945
|
-
[eachBlock.context.start, contextEnd],
|
|
2987
|
+
eachBlock.context ? [eachBlock.context.start, contextEnd] : '$$each_item',
|
|
2946
2988
|
` of __sveltets_2_ensureArray(${containsComma ? '(' : ''}`,
|
|
2947
2989
|
[eachBlock.expression.start, eachBlock.expression.end],
|
|
2948
|
-
`${containsComma ? ')' : ''})){`
|
|
2990
|
+
`${containsComma ? ')' : ''})){${eachBlock.context ? '' : '$$each_item;'}`
|
|
2949
2991
|
];
|
|
2950
2992
|
}
|
|
2951
2993
|
if (eachBlock.index) {
|
|
2952
|
-
const indexStart = str.original.indexOf(eachBlock.index, eachBlock.context.end);
|
|
2994
|
+
const indexStart = str.original.indexOf(eachBlock.index, ((_c = eachBlock.context) === null || _c === void 0 ? void 0 : _c.end) || eachBlock.expression.end);
|
|
2953
2995
|
const indexEnd = indexStart + eachBlock.index.length;
|
|
2954
2996
|
transforms.push('let ', [indexStart, indexEnd], ' = 1;');
|
|
2955
2997
|
}
|
|
2956
2998
|
if (eachBlock.key) {
|
|
2957
2999
|
transforms.push([eachBlock.key.start, eachBlock.key.end], ';');
|
|
2958
3000
|
}
|
|
2959
|
-
transform(str, eachBlock.start, startEnd,
|
|
3001
|
+
transform(str, eachBlock.start, startEnd, transforms);
|
|
2960
3002
|
const endEach = str.original.lastIndexOf('{', eachBlock.end - 1);
|
|
2961
3003
|
// {/each} -> } or {:else} -> }
|
|
2962
3004
|
if (eachBlock.else) {
|
|
@@ -2965,12 +3007,20 @@ function handleEach(str, eachBlock) {
|
|
|
2965
3007
|
str.overwrite(elseStart, elseEnd + 1, '}' + (arrayAndItemVarTheSame ? '}' : ''), {
|
|
2966
3008
|
contentOnly: true
|
|
2967
3009
|
});
|
|
2968
|
-
|
|
3010
|
+
if (!isImplicitlyClosedBlock(endEach, eachBlock)) {
|
|
3011
|
+
str.remove(endEach, eachBlock.end);
|
|
3012
|
+
}
|
|
2969
3013
|
}
|
|
2970
3014
|
else {
|
|
2971
|
-
|
|
2972
|
-
|
|
2973
|
-
|
|
3015
|
+
const closing = '}' + (arrayAndItemVarTheSame ? '}' : '');
|
|
3016
|
+
if (isImplicitlyClosedBlock(endEach, eachBlock)) {
|
|
3017
|
+
str.prependLeft(eachBlock.end, closing);
|
|
3018
|
+
}
|
|
3019
|
+
else {
|
|
3020
|
+
str.overwrite(endEach, eachBlock.end, closing, {
|
|
3021
|
+
contentOnly: true
|
|
3022
|
+
});
|
|
3023
|
+
}
|
|
2974
3024
|
}
|
|
2975
3025
|
}
|
|
2976
3026
|
|
|
@@ -3014,9 +3064,14 @@ function handleIf(str, ifBlock) {
|
|
|
3014
3064
|
const expressionEnd = withTrailingPropertyAccess(str.original, ifBlock.expression.end);
|
|
3015
3065
|
const end = str.original.indexOf('}', expressionEnd);
|
|
3016
3066
|
str.overwrite(expressionEnd, end + 1, '){');
|
|
3017
|
-
// {/if} -> }
|
|
3018
3067
|
const endif = str.original.lastIndexOf('{', ifBlock.end - 1);
|
|
3019
|
-
|
|
3068
|
+
if (isImplicitlyClosedBlock(endif, ifBlock)) {
|
|
3069
|
+
str.prependLeft(ifBlock.end, '}');
|
|
3070
|
+
}
|
|
3071
|
+
else {
|
|
3072
|
+
// {/if} -> }
|
|
3073
|
+
str.overwrite(endif, ifBlock.end, '}');
|
|
3074
|
+
}
|
|
3020
3075
|
}
|
|
3021
3076
|
/**
|
|
3022
3077
|
* {:else} ---> } else {
|
|
@@ -3046,7 +3101,9 @@ function handleKey(str, keyBlock) {
|
|
|
3046
3101
|
str.overwrite(expressionEnd, end + 1, '; ');
|
|
3047
3102
|
// {/key} ->
|
|
3048
3103
|
const endKey = str.original.lastIndexOf('{', keyBlock.end - 1);
|
|
3049
|
-
|
|
3104
|
+
if (!isImplicitlyClosedBlock(endKey, keyBlock)) {
|
|
3105
|
+
str.overwrite(endKey, keyBlock.end, '', { contentOnly: true });
|
|
3106
|
+
}
|
|
3050
3107
|
}
|
|
3051
3108
|
|
|
3052
3109
|
/**
|
|
@@ -3244,9 +3301,14 @@ function handleSnippet(str, snippetBlock, component) {
|
|
|
3244
3301
|
const afterSnippet = isImplicitProp
|
|
3245
3302
|
? `};return __sveltets_2_any(0)}`
|
|
3246
3303
|
: `};return __sveltets_2_any(0)};`;
|
|
3247
|
-
|
|
3248
|
-
|
|
3249
|
-
}
|
|
3304
|
+
if (isImplicitlyClosedBlock(endSnippet, snippetBlock)) {
|
|
3305
|
+
str.prependLeft(snippetBlock.end, afterSnippet);
|
|
3306
|
+
}
|
|
3307
|
+
else {
|
|
3308
|
+
str.overwrite(endSnippet, snippetBlock.end, afterSnippet, {
|
|
3309
|
+
contentOnly: true
|
|
3310
|
+
});
|
|
3311
|
+
}
|
|
3250
3312
|
const lastParameter = (_a = snippetBlock.parameters) === null || _a === void 0 ? void 0 : _a.at(-1);
|
|
3251
3313
|
const startEnd = str.original.indexOf('}', (_d = (_c = (_b = lastParameter === null || lastParameter === void 0 ? void 0 : lastParameter.typeAnnotation) === null || _b === void 0 ? void 0 : _b.end) !== null && _c !== void 0 ? _c : lastParameter === null || lastParameter === void 0 ? void 0 : lastParameter.end) !== null && _d !== void 0 ? _d : snippetBlock.expression.end) + 1;
|
|
3252
3314
|
let parameters;
|
|
@@ -3259,7 +3321,22 @@ function handleSnippet(str, snippetBlock, component) {
|
|
|
3259
3321
|
// inner async function for potential #await blocks
|
|
3260
3322
|
const afterParameters = ` => { async ()${IGNORE_POSITION_COMMENT} => {`;
|
|
3261
3323
|
if (isImplicitProp) {
|
|
3262
|
-
|
|
3324
|
+
/** Can happen in loose parsing mode, e.g. code is currently `{#snippet }` */
|
|
3325
|
+
const emptyId = snippetBlock.expression.start === snippetBlock.expression.end;
|
|
3326
|
+
if (emptyId) {
|
|
3327
|
+
// Give intellisense a way to map into the right position for implicit prop completion
|
|
3328
|
+
str.overwrite(snippetBlock.start, snippetBlock.expression.start - 1, '', {
|
|
3329
|
+
contentOnly: true
|
|
3330
|
+
});
|
|
3331
|
+
str.overwrite(snippetBlock.expression.start - 1, snippetBlock.expression.start, ' ', {
|
|
3332
|
+
contentOnly: true
|
|
3333
|
+
});
|
|
3334
|
+
}
|
|
3335
|
+
else {
|
|
3336
|
+
str.overwrite(snippetBlock.start, snippetBlock.expression.start, '', {
|
|
3337
|
+
contentOnly: true
|
|
3338
|
+
});
|
|
3339
|
+
}
|
|
3263
3340
|
const transforms = ['('];
|
|
3264
3341
|
if (parameters) {
|
|
3265
3342
|
transforms.push(parameters);
|
|
@@ -3275,10 +3352,10 @@ function handleSnippet(str, snippetBlock, component) {
|
|
|
3275
3352
|
transforms.push(')' + afterParameters);
|
|
3276
3353
|
transforms.push([startEnd, snippetBlock.end]);
|
|
3277
3354
|
if (component instanceof InlineComponent) {
|
|
3278
|
-
component.addImplicitSnippetProp([snippetBlock.expression.start, snippetBlock.expression.end], transforms);
|
|
3355
|
+
component.addImplicitSnippetProp([snippetBlock.expression.start - (emptyId ? 1 : 0), snippetBlock.expression.end], transforms);
|
|
3279
3356
|
}
|
|
3280
3357
|
else {
|
|
3281
|
-
component.addAttribute([[snippetBlock.expression.start, snippetBlock.expression.end]], transforms);
|
|
3358
|
+
component.addAttribute([[snippetBlock.expression.start - (emptyId ? 1 : 0), snippetBlock.expression.end]], transforms);
|
|
3282
3359
|
}
|
|
3283
3360
|
}
|
|
3284
3361
|
else {
|
|
@@ -3293,7 +3370,7 @@ function handleSnippet(str, snippetBlock, component) {
|
|
|
3293
3370
|
}
|
|
3294
3371
|
transforms.push(')', surroundWithIgnoreComments(`: ReturnType<import('svelte').Snippet>`), // shows up nicely preserved on hover, other alternatives don't
|
|
3295
3372
|
afterParameters);
|
|
3296
|
-
transform(str, snippetBlock.start, startEnd,
|
|
3373
|
+
transform(str, snippetBlock.start, startEnd, transforms);
|
|
3297
3374
|
}
|
|
3298
3375
|
}
|
|
3299
3376
|
function handleImplicitChildren(componentNode, component) {
|
package/index.mjs
CHANGED
|
@@ -1653,10 +1653,10 @@ function parseHtmlx(htmlx, parse, options) {
|
|
|
1653
1653
|
const verbatimElements = findVerbatimElements(htmlx);
|
|
1654
1654
|
const deconstructed = blankVerbatimContent(htmlx, verbatimElements);
|
|
1655
1655
|
//extract the html content parsed as htmlx this excludes our script and style tags
|
|
1656
|
-
const parsingCode = options.emitOnTemplateError
|
|
1656
|
+
const parsingCode = options.emitOnTemplateError && !options.svelte5Plus
|
|
1657
1657
|
? blankPossiblyErrorOperatorOrPropertyAccess(deconstructed)
|
|
1658
1658
|
: deconstructed;
|
|
1659
|
-
const htmlxAst = parse(parsingCode).html;
|
|
1659
|
+
const htmlxAst = parse(parsingCode, options.svelte5Plus ? { loose: options.emitOnTemplateError } : undefined).html;
|
|
1660
1660
|
//restore our script and style tags as nodes to maintain validity with HTMLx
|
|
1661
1661
|
for (const s of verbatimElements) {
|
|
1662
1662
|
htmlxAst.children.push(s);
|
|
@@ -1740,8 +1740,7 @@ function handleActionDirective(attr, element) {
|
|
|
1740
1740
|
* you may need to find a different way because MagicString does not allow us to move a range
|
|
1741
1741
|
* that goes from `start` to `end` to the `end` position.
|
|
1742
1742
|
*/
|
|
1743
|
-
function transform(str, start, end,
|
|
1744
|
-
transformations) {
|
|
1743
|
+
function transform(str, start, end, transformations) {
|
|
1745
1744
|
var _a, _b;
|
|
1746
1745
|
const moves = [];
|
|
1747
1746
|
let appendPosition = end;
|
|
@@ -1833,6 +1832,10 @@ transformations) {
|
|
|
1833
1832
|
}
|
|
1834
1833
|
}
|
|
1835
1834
|
for (let i = deletePos; i < moves.length; i++) {
|
|
1835
|
+
// Can happen when there's not enough space left at the end of an unfininished element/component tag.
|
|
1836
|
+
// Better to leave potentially slightly disarranged code than fail loudly
|
|
1837
|
+
if (moves[i][1] >= end && moves[i][0] <= end)
|
|
1838
|
+
break;
|
|
1836
1839
|
str.move(moves[i][0], moves[i][1], end);
|
|
1837
1840
|
}
|
|
1838
1841
|
}
|
|
@@ -1916,6 +1919,22 @@ function isTypescriptNode(node) {
|
|
|
1916
1919
|
node.type === 'TSSatisfiesExpression' ||
|
|
1917
1920
|
node.type === 'TSNonNullExpression');
|
|
1918
1921
|
}
|
|
1922
|
+
/**
|
|
1923
|
+
* Returns `true` if the given block is implicitly closed, which could be the case in loose parsing mode.
|
|
1924
|
+
* E.g.:
|
|
1925
|
+
* ```html
|
|
1926
|
+
* <div>
|
|
1927
|
+
* {#if x}
|
|
1928
|
+
* </div>
|
|
1929
|
+
* ```
|
|
1930
|
+
* @param end
|
|
1931
|
+
* @param block
|
|
1932
|
+
* @returns
|
|
1933
|
+
*/
|
|
1934
|
+
function isImplicitlyClosedBlock(end, block) {
|
|
1935
|
+
var _a, _b;
|
|
1936
|
+
return end < ((_b = (_a = block.children[block.children.length - 1]) === null || _a === void 0 ? void 0 : _a.end) !== null && _b !== void 0 ? _b : block.expression.end);
|
|
1937
|
+
}
|
|
1919
1938
|
|
|
1920
1939
|
/**
|
|
1921
1940
|
* animate:xxx(yyy) ---> __sveltets_2_ensureAnimation(xxx(svelte.mapElementTag('..'),__sveltets_2_AnimationMove,(yyy)));
|
|
@@ -2104,7 +2123,7 @@ class Element {
|
|
|
2104
2123
|
this.endTransformation.push('}');
|
|
2105
2124
|
}
|
|
2106
2125
|
if (this.isSelfclosing) {
|
|
2107
|
-
transform(this.str, this.startTagStart, this.startTagEnd,
|
|
2126
|
+
transform(this.str, this.startTagStart, this.startTagEnd, [
|
|
2108
2127
|
// Named slot transformations go first inside a outer block scope because
|
|
2109
2128
|
// <div let:xx {x} /> means "use the x of let:x", and without a separate
|
|
2110
2129
|
// block scope this would give a "used before defined" error
|
|
@@ -2117,7 +2136,7 @@ class Element {
|
|
|
2117
2136
|
]);
|
|
2118
2137
|
}
|
|
2119
2138
|
else {
|
|
2120
|
-
transform(this.str, this.startTagStart, this.startTagEnd,
|
|
2139
|
+
transform(this.str, this.startTagStart, this.startTagEnd, [
|
|
2121
2140
|
...slotLetTransformation,
|
|
2122
2141
|
...this.actionsTransformation,
|
|
2123
2142
|
...this.getStartTransformation(),
|
|
@@ -2129,7 +2148,7 @@ class Element {
|
|
|
2129
2148
|
.lastIndexOf(`</${this.node.name}`);
|
|
2130
2149
|
// tagEndIdx === -1 happens in situations of unclosed tags like `<p>fooo <p>anothertag</p>`
|
|
2131
2150
|
const endStart = tagEndIdx === -1 ? this.node.end : tagEndIdx + this.node.start;
|
|
2132
|
-
transform(this.str, endStart, this.node.end, this.
|
|
2151
|
+
transform(this.str, endStart, this.node.end, this.endTransformation);
|
|
2133
2152
|
}
|
|
2134
2153
|
}
|
|
2135
2154
|
getStartTransformation() {
|
|
@@ -2386,7 +2405,7 @@ class InlineComponent {
|
|
|
2386
2405
|
: '';
|
|
2387
2406
|
if (this.isSelfclosing) {
|
|
2388
2407
|
this.endTransformation.push('}');
|
|
2389
|
-
transform(this.str, this.startTagStart, this.startTagEnd,
|
|
2408
|
+
transform(this.str, this.startTagStart, this.startTagEnd, [
|
|
2390
2409
|
// Named slot transformations go first inside a outer block scope because
|
|
2391
2410
|
// <Comp let:xx {x} /> means "use the x of let:x", and without a separate
|
|
2392
2411
|
// block scope this would give a "used before defined" error
|
|
@@ -2401,15 +2420,23 @@ class InlineComponent {
|
|
|
2401
2420
|
]);
|
|
2402
2421
|
}
|
|
2403
2422
|
else {
|
|
2404
|
-
|
|
2423
|
+
let endStart = this.str.original
|
|
2405
2424
|
.substring(this.node.start, this.node.end)
|
|
2406
|
-
.lastIndexOf(`</${this.node.name}`)
|
|
2407
|
-
if (
|
|
2425
|
+
.lastIndexOf(`</${this.node.name}`);
|
|
2426
|
+
if (endStart === -1) {
|
|
2427
|
+
// Can happen in loose parsing mode when there's no closing tag
|
|
2428
|
+
endStart = this.node.end;
|
|
2429
|
+
this.startTagEnd = this.node.end - 1;
|
|
2430
|
+
}
|
|
2431
|
+
else {
|
|
2432
|
+
endStart += this.node.start;
|
|
2433
|
+
}
|
|
2434
|
+
if (!this.node.name.startsWith('svelte:') && endStart !== this.node.end) {
|
|
2408
2435
|
// Ensure the end tag is mapped, too. </Component> -> Component}
|
|
2409
2436
|
this.endTransformation.push([endStart + 2, endStart + this.node.name.length + 2]);
|
|
2410
2437
|
}
|
|
2411
2438
|
this.endTransformation.push('}');
|
|
2412
|
-
transform(this.str, this.startTagStart, this.startTagEnd,
|
|
2439
|
+
transform(this.str, this.startTagStart, this.startTagEnd, [
|
|
2413
2440
|
// See comment above why this goes first
|
|
2414
2441
|
...namedSlotLetTransformation,
|
|
2415
2442
|
...this.startTransformation,
|
|
@@ -2419,7 +2446,7 @@ class InlineComponent {
|
|
|
2419
2446
|
snippetPropVariablesDeclaration,
|
|
2420
2447
|
...defaultSlotLetTransformation
|
|
2421
2448
|
]);
|
|
2422
|
-
transform(this.str, endStart, this.node.end, this.
|
|
2449
|
+
transform(this.str, endStart, this.node.end, this.endTransformation);
|
|
2423
2450
|
}
|
|
2424
2451
|
}
|
|
2425
2452
|
computeStartTagEnd() {
|
|
@@ -2548,7 +2575,14 @@ function handleAttribute(str, attr, parent, preserveCase, svelte5Plus, element)
|
|
|
2548
2575
|
const attributeName = [];
|
|
2549
2576
|
if (attributeValueIsOfType(attr.value, 'AttributeShorthand')) {
|
|
2550
2577
|
// For the attribute shorthand, the name will be the mapped part
|
|
2551
|
-
|
|
2578
|
+
let [start, end] = [attr.value[0].start, attr.value[0].end];
|
|
2579
|
+
if (start === end) {
|
|
2580
|
+
// Loose parsing mode, we have an empty attribute value, e.g. {}
|
|
2581
|
+
// For proper intellisense we need to make this a non-empty expression.
|
|
2582
|
+
start--;
|
|
2583
|
+
str.overwrite(start, end, ' ', { contentOnly: true });
|
|
2584
|
+
}
|
|
2585
|
+
addAttribute([[start, end]]);
|
|
2552
2586
|
return;
|
|
2553
2587
|
}
|
|
2554
2588
|
else {
|
|
@@ -2620,7 +2654,14 @@ function handleAttribute(str, attr, parent, preserveCase, svelte5Plus, element)
|
|
|
2620
2654
|
addAttribute(attributeName, attributeValue);
|
|
2621
2655
|
}
|
|
2622
2656
|
else if (attrVal.type == 'MustacheTag') {
|
|
2623
|
-
|
|
2657
|
+
let [start, end] = rangeWithTrailingPropertyAccess(str.original, attrVal.expression);
|
|
2658
|
+
if (start === end) {
|
|
2659
|
+
// Loose parsing mode, we have an empty attribute value, e.g. attr={}
|
|
2660
|
+
// For proper intellisense we need to make this a non-empty expression.
|
|
2661
|
+
start--;
|
|
2662
|
+
str.overwrite(start, end, ' ', { contentOnly: true });
|
|
2663
|
+
}
|
|
2664
|
+
attributeValue.push([start, end]);
|
|
2624
2665
|
addAttribute(attributeName, attributeValue);
|
|
2625
2666
|
}
|
|
2626
2667
|
return;
|
|
@@ -2706,7 +2747,7 @@ function handleAwait(str, awaitBlock) {
|
|
|
2706
2747
|
transforms.push('}');
|
|
2707
2748
|
}
|
|
2708
2749
|
transforms.push('}');
|
|
2709
|
-
transform(str, awaitBlock.start, awaitBlock.end,
|
|
2750
|
+
transform(str, awaitBlock.start, awaitBlock.end, transforms);
|
|
2710
2751
|
}
|
|
2711
2752
|
|
|
2712
2753
|
/**
|
|
@@ -2899,17 +2940,18 @@ function handleDebug(str, debugBlock) {
|
|
|
2899
2940
|
* `ensureArray` will error that there are more args than expected
|
|
2900
2941
|
*/
|
|
2901
2942
|
function handleEach(str, eachBlock) {
|
|
2902
|
-
var _a;
|
|
2903
|
-
const startEnd = str.original.indexOf('}', ((_a = eachBlock.key) === null || _a === void 0 ? void 0 : _a.end) || eachBlock.context.end) + 1;
|
|
2943
|
+
var _a, _b, _c;
|
|
2944
|
+
const startEnd = str.original.indexOf('}', ((_a = eachBlock.key) === null || _a === void 0 ? void 0 : _a.end) || ((_b = eachBlock.context) === null || _b === void 0 ? void 0 : _b.end) || eachBlock.expression.end) + 1;
|
|
2904
2945
|
let transforms;
|
|
2905
2946
|
// {#each true, [1,2]} is valid but for (const x of true, [1,2]) is not if not wrapped with braces
|
|
2906
2947
|
const containsComma = str.original
|
|
2907
2948
|
.substring(eachBlock.expression.start, eachBlock.expression.end)
|
|
2908
2949
|
.includes(',');
|
|
2909
2950
|
const expressionEnd = getEnd(eachBlock.expression);
|
|
2910
|
-
const contextEnd = getEnd(eachBlock.context);
|
|
2911
|
-
const arrayAndItemVarTheSame =
|
|
2912
|
-
str.original.substring(eachBlock.
|
|
2951
|
+
const contextEnd = eachBlock.context && getEnd(eachBlock.context);
|
|
2952
|
+
const arrayAndItemVarTheSame = !!eachBlock.context &&
|
|
2953
|
+
str.original.substring(eachBlock.expression.start, expressionEnd) ===
|
|
2954
|
+
str.original.substring(eachBlock.context.start, contextEnd);
|
|
2913
2955
|
if (arrayAndItemVarTheSame) {
|
|
2914
2956
|
transforms = [
|
|
2915
2957
|
`{ const $$_each = __sveltets_2_ensureArray(${containsComma ? '(' : ''}`,
|
|
@@ -2922,21 +2964,21 @@ function handleEach(str, eachBlock) {
|
|
|
2922
2964
|
else {
|
|
2923
2965
|
transforms = [
|
|
2924
2966
|
'for(let ',
|
|
2925
|
-
[eachBlock.context.start, contextEnd],
|
|
2967
|
+
eachBlock.context ? [eachBlock.context.start, contextEnd] : '$$each_item',
|
|
2926
2968
|
` of __sveltets_2_ensureArray(${containsComma ? '(' : ''}`,
|
|
2927
2969
|
[eachBlock.expression.start, eachBlock.expression.end],
|
|
2928
|
-
`${containsComma ? ')' : ''})){`
|
|
2970
|
+
`${containsComma ? ')' : ''})){${eachBlock.context ? '' : '$$each_item;'}`
|
|
2929
2971
|
];
|
|
2930
2972
|
}
|
|
2931
2973
|
if (eachBlock.index) {
|
|
2932
|
-
const indexStart = str.original.indexOf(eachBlock.index, eachBlock.context.end);
|
|
2974
|
+
const indexStart = str.original.indexOf(eachBlock.index, ((_c = eachBlock.context) === null || _c === void 0 ? void 0 : _c.end) || eachBlock.expression.end);
|
|
2933
2975
|
const indexEnd = indexStart + eachBlock.index.length;
|
|
2934
2976
|
transforms.push('let ', [indexStart, indexEnd], ' = 1;');
|
|
2935
2977
|
}
|
|
2936
2978
|
if (eachBlock.key) {
|
|
2937
2979
|
transforms.push([eachBlock.key.start, eachBlock.key.end], ';');
|
|
2938
2980
|
}
|
|
2939
|
-
transform(str, eachBlock.start, startEnd,
|
|
2981
|
+
transform(str, eachBlock.start, startEnd, transforms);
|
|
2940
2982
|
const endEach = str.original.lastIndexOf('{', eachBlock.end - 1);
|
|
2941
2983
|
// {/each} -> } or {:else} -> }
|
|
2942
2984
|
if (eachBlock.else) {
|
|
@@ -2945,12 +2987,20 @@ function handleEach(str, eachBlock) {
|
|
|
2945
2987
|
str.overwrite(elseStart, elseEnd + 1, '}' + (arrayAndItemVarTheSame ? '}' : ''), {
|
|
2946
2988
|
contentOnly: true
|
|
2947
2989
|
});
|
|
2948
|
-
|
|
2990
|
+
if (!isImplicitlyClosedBlock(endEach, eachBlock)) {
|
|
2991
|
+
str.remove(endEach, eachBlock.end);
|
|
2992
|
+
}
|
|
2949
2993
|
}
|
|
2950
2994
|
else {
|
|
2951
|
-
|
|
2952
|
-
|
|
2953
|
-
|
|
2995
|
+
const closing = '}' + (arrayAndItemVarTheSame ? '}' : '');
|
|
2996
|
+
if (isImplicitlyClosedBlock(endEach, eachBlock)) {
|
|
2997
|
+
str.prependLeft(eachBlock.end, closing);
|
|
2998
|
+
}
|
|
2999
|
+
else {
|
|
3000
|
+
str.overwrite(endEach, eachBlock.end, closing, {
|
|
3001
|
+
contentOnly: true
|
|
3002
|
+
});
|
|
3003
|
+
}
|
|
2954
3004
|
}
|
|
2955
3005
|
}
|
|
2956
3006
|
|
|
@@ -2994,9 +3044,14 @@ function handleIf(str, ifBlock) {
|
|
|
2994
3044
|
const expressionEnd = withTrailingPropertyAccess(str.original, ifBlock.expression.end);
|
|
2995
3045
|
const end = str.original.indexOf('}', expressionEnd);
|
|
2996
3046
|
str.overwrite(expressionEnd, end + 1, '){');
|
|
2997
|
-
// {/if} -> }
|
|
2998
3047
|
const endif = str.original.lastIndexOf('{', ifBlock.end - 1);
|
|
2999
|
-
|
|
3048
|
+
if (isImplicitlyClosedBlock(endif, ifBlock)) {
|
|
3049
|
+
str.prependLeft(ifBlock.end, '}');
|
|
3050
|
+
}
|
|
3051
|
+
else {
|
|
3052
|
+
// {/if} -> }
|
|
3053
|
+
str.overwrite(endif, ifBlock.end, '}');
|
|
3054
|
+
}
|
|
3000
3055
|
}
|
|
3001
3056
|
/**
|
|
3002
3057
|
* {:else} ---> } else {
|
|
@@ -3026,7 +3081,9 @@ function handleKey(str, keyBlock) {
|
|
|
3026
3081
|
str.overwrite(expressionEnd, end + 1, '; ');
|
|
3027
3082
|
// {/key} ->
|
|
3028
3083
|
const endKey = str.original.lastIndexOf('{', keyBlock.end - 1);
|
|
3029
|
-
|
|
3084
|
+
if (!isImplicitlyClosedBlock(endKey, keyBlock)) {
|
|
3085
|
+
str.overwrite(endKey, keyBlock.end, '', { contentOnly: true });
|
|
3086
|
+
}
|
|
3030
3087
|
}
|
|
3031
3088
|
|
|
3032
3089
|
/**
|
|
@@ -3224,9 +3281,14 @@ function handleSnippet(str, snippetBlock, component) {
|
|
|
3224
3281
|
const afterSnippet = isImplicitProp
|
|
3225
3282
|
? `};return __sveltets_2_any(0)}`
|
|
3226
3283
|
: `};return __sveltets_2_any(0)};`;
|
|
3227
|
-
|
|
3228
|
-
|
|
3229
|
-
}
|
|
3284
|
+
if (isImplicitlyClosedBlock(endSnippet, snippetBlock)) {
|
|
3285
|
+
str.prependLeft(snippetBlock.end, afterSnippet);
|
|
3286
|
+
}
|
|
3287
|
+
else {
|
|
3288
|
+
str.overwrite(endSnippet, snippetBlock.end, afterSnippet, {
|
|
3289
|
+
contentOnly: true
|
|
3290
|
+
});
|
|
3291
|
+
}
|
|
3230
3292
|
const lastParameter = (_a = snippetBlock.parameters) === null || _a === void 0 ? void 0 : _a.at(-1);
|
|
3231
3293
|
const startEnd = str.original.indexOf('}', (_d = (_c = (_b = lastParameter === null || lastParameter === void 0 ? void 0 : lastParameter.typeAnnotation) === null || _b === void 0 ? void 0 : _b.end) !== null && _c !== void 0 ? _c : lastParameter === null || lastParameter === void 0 ? void 0 : lastParameter.end) !== null && _d !== void 0 ? _d : snippetBlock.expression.end) + 1;
|
|
3232
3294
|
let parameters;
|
|
@@ -3239,7 +3301,22 @@ function handleSnippet(str, snippetBlock, component) {
|
|
|
3239
3301
|
// inner async function for potential #await blocks
|
|
3240
3302
|
const afterParameters = ` => { async ()${IGNORE_POSITION_COMMENT} => {`;
|
|
3241
3303
|
if (isImplicitProp) {
|
|
3242
|
-
|
|
3304
|
+
/** Can happen in loose parsing mode, e.g. code is currently `{#snippet }` */
|
|
3305
|
+
const emptyId = snippetBlock.expression.start === snippetBlock.expression.end;
|
|
3306
|
+
if (emptyId) {
|
|
3307
|
+
// Give intellisense a way to map into the right position for implicit prop completion
|
|
3308
|
+
str.overwrite(snippetBlock.start, snippetBlock.expression.start - 1, '', {
|
|
3309
|
+
contentOnly: true
|
|
3310
|
+
});
|
|
3311
|
+
str.overwrite(snippetBlock.expression.start - 1, snippetBlock.expression.start, ' ', {
|
|
3312
|
+
contentOnly: true
|
|
3313
|
+
});
|
|
3314
|
+
}
|
|
3315
|
+
else {
|
|
3316
|
+
str.overwrite(snippetBlock.start, snippetBlock.expression.start, '', {
|
|
3317
|
+
contentOnly: true
|
|
3318
|
+
});
|
|
3319
|
+
}
|
|
3243
3320
|
const transforms = ['('];
|
|
3244
3321
|
if (parameters) {
|
|
3245
3322
|
transforms.push(parameters);
|
|
@@ -3255,10 +3332,10 @@ function handleSnippet(str, snippetBlock, component) {
|
|
|
3255
3332
|
transforms.push(')' + afterParameters);
|
|
3256
3333
|
transforms.push([startEnd, snippetBlock.end]);
|
|
3257
3334
|
if (component instanceof InlineComponent) {
|
|
3258
|
-
component.addImplicitSnippetProp([snippetBlock.expression.start, snippetBlock.expression.end], transforms);
|
|
3335
|
+
component.addImplicitSnippetProp([snippetBlock.expression.start - (emptyId ? 1 : 0), snippetBlock.expression.end], transforms);
|
|
3259
3336
|
}
|
|
3260
3337
|
else {
|
|
3261
|
-
component.addAttribute([[snippetBlock.expression.start, snippetBlock.expression.end]], transforms);
|
|
3338
|
+
component.addAttribute([[snippetBlock.expression.start - (emptyId ? 1 : 0), snippetBlock.expression.end]], transforms);
|
|
3262
3339
|
}
|
|
3263
3340
|
}
|
|
3264
3341
|
else {
|
|
@@ -3273,7 +3350,7 @@ function handleSnippet(str, snippetBlock, component) {
|
|
|
3273
3350
|
}
|
|
3274
3351
|
transforms.push(')', surroundWithIgnoreComments(`: ReturnType<import('svelte').Snippet>`), // shows up nicely preserved on hover, other alternatives don't
|
|
3275
3352
|
afterParameters);
|
|
3276
|
-
transform(str, snippetBlock.start, startEnd,
|
|
3353
|
+
transform(str, snippetBlock.start, startEnd, transforms);
|
|
3277
3354
|
}
|
|
3278
3355
|
}
|
|
3279
3356
|
function handleImplicitChildren(componentNode, component) {
|