svelte2tsx 0.6.25 → 0.6.27
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.d.ts +5 -0
- package/index.js +251 -57
- package/index.mjs +252 -58
- package/package.json +2 -2
- package/svelte-shims-v4.d.ts +5 -0
package/index.d.ts
CHANGED
|
@@ -79,6 +79,11 @@ export function svelte2tsx(
|
|
|
79
79
|
* The Svelte parser to use. Defaults to the one bundled with `svelte2tsx`.
|
|
80
80
|
*/
|
|
81
81
|
parse?: typeof import('svelte/compiler').parse;
|
|
82
|
+
/**
|
|
83
|
+
* The VERSION from 'svelte/compiler'. Defaults to the one bundled with `svelte2tsx`.
|
|
84
|
+
* Transpiled output may vary between versions.
|
|
85
|
+
*/
|
|
86
|
+
version?: string;
|
|
82
87
|
}
|
|
83
88
|
): SvelteCompiledToTsx
|
|
84
89
|
|
package/index.js
CHANGED
|
@@ -1479,8 +1479,11 @@ function parseAttributes(str, start) {
|
|
|
1479
1479
|
}
|
|
1480
1480
|
return attrs;
|
|
1481
1481
|
}
|
|
1482
|
+
// Regex ensures that attributes with > characters in them still result in the content being matched correctly
|
|
1483
|
+
const scriptRegex = /(<!--[^]*?-->)|(<script((?:\s+[^=>'"\/]+=(?:"[^"]*"|'[^']*'|[^>\s]+)|\s+[^=>'"\/]+)*\s*)>)([\S\s]*?)<\/script>/g;
|
|
1484
|
+
const styleRegex = /(<!--[^]*?-->)|(<style((?:\s+[^=>'"\/]+=(?:"[^"]*"|'[^']*'|[^>\s]+)|\s+[^=>'"\/]+)*\s*)>)([\S\s]*?)<\/style>/g;
|
|
1482
1485
|
function extractTag(htmlx, tag) {
|
|
1483
|
-
const exp =
|
|
1486
|
+
const exp = tag === 'script' ? scriptRegex : styleRegex;
|
|
1484
1487
|
const matches = [];
|
|
1485
1488
|
let match = null;
|
|
1486
1489
|
while ((match = exp.exec(htmlx)) != null) {
|
|
@@ -1677,9 +1680,12 @@ transformations) {
|
|
|
1677
1680
|
str.move(moves[i][0], moves[i][1], end);
|
|
1678
1681
|
}
|
|
1679
1682
|
let removeStart = start;
|
|
1680
|
-
|
|
1683
|
+
const sortedMoves = [...moves].sort((t1, t2) => t1[0] - t2[0]);
|
|
1684
|
+
for (const transformation of sortedMoves) {
|
|
1681
1685
|
if (removeStart < transformation[0]) {
|
|
1682
|
-
if (deletePos !== moves.length &&
|
|
1686
|
+
if (deletePos !== moves.length &&
|
|
1687
|
+
removeStart > deleteDest &&
|
|
1688
|
+
!(removeStart < end && transformation[0] >= end)) {
|
|
1683
1689
|
str.move(removeStart, transformation[0], end);
|
|
1684
1690
|
}
|
|
1685
1691
|
if (transformation[0] < end) {
|
|
@@ -1692,7 +1698,8 @@ transformations) {
|
|
|
1692
1698
|
if (removeStart > end) {
|
|
1693
1699
|
// Reset the end to the last transformation before the end if there were transformations after the end
|
|
1694
1700
|
// so we still delete the correct range afterwards
|
|
1695
|
-
|
|
1701
|
+
let idx = sortedMoves.findIndex((m) => m[0] > end) - 1;
|
|
1702
|
+
removeStart = (_b = (_a = sortedMoves[idx]) === null || _a === void 0 ? void 0 : _a[1]) !== null && _b !== void 0 ? _b : end;
|
|
1696
1703
|
}
|
|
1697
1704
|
if (removeStart < end) {
|
|
1698
1705
|
// Completely delete the first character afterwards. This makes the mapping more correct,
|
|
@@ -2388,7 +2395,9 @@ function handleAttribute(str, attr, parent, preserveCase, element) {
|
|
|
2388
2395
|
* lowercase the attribute name to make it adhere to our intrinsic elements definition
|
|
2389
2396
|
*/
|
|
2390
2397
|
const transformAttributeCase = (name) => {
|
|
2391
|
-
if (!preserveCase &&
|
|
2398
|
+
if (!preserveCase &&
|
|
2399
|
+
!svgAttributes.find((x) => x == name) &&
|
|
2400
|
+
!(element instanceof Element && element.tagName.includes('-'))) {
|
|
2392
2401
|
return name.toLowerCase();
|
|
2393
2402
|
}
|
|
2394
2403
|
else {
|
|
@@ -2440,9 +2449,10 @@ function handleAttribute(str, attr, parent, preserveCase, element) {
|
|
|
2440
2449
|
addAttribute(attributeName, [[attrVal.start - 1, attrVal.end + 1]]);
|
|
2441
2450
|
return;
|
|
2442
2451
|
}
|
|
2443
|
-
const
|
|
2444
|
-
|
|
2445
|
-
str.original
|
|
2452
|
+
const lastCharIndex = attrVal.end - 1;
|
|
2453
|
+
const hasBrackets = str.original[lastCharIndex] === '}' ||
|
|
2454
|
+
((str.original[lastCharIndex] === '"' || str.original[lastCharIndex] === "'") &&
|
|
2455
|
+
str.original[lastCharIndex - 1] === '}');
|
|
2446
2456
|
const needsNumberConversion = !hasBrackets &&
|
|
2447
2457
|
parent.type === 'Element' &&
|
|
2448
2458
|
numberOnlyAttributes.has(attr.name.toLowerCase()) &&
|
|
@@ -2644,7 +2654,12 @@ function handleBinding(str, attr, parent, element, preserveBind) {
|
|
|
2644
2654
|
: // Other typings - remove the bind: prefix
|
|
2645
2655
|
isShorthand
|
|
2646
2656
|
? [[attr.expression.start, attr.expression.end]]
|
|
2647
|
-
: [
|
|
2657
|
+
: [
|
|
2658
|
+
[
|
|
2659
|
+
attr.start + 'bind:'.length,
|
|
2660
|
+
str.original.lastIndexOf('=', attr.expression.start)
|
|
2661
|
+
]
|
|
2662
|
+
];
|
|
2648
2663
|
const value = isShorthand
|
|
2649
2664
|
? preserveBind && element instanceof Element
|
|
2650
2665
|
? [rangeWithTrailingPropertyAccess(str.original, attr.expression)]
|
|
@@ -2725,21 +2740,23 @@ function handleEach(str, eachBlock) {
|
|
|
2725
2740
|
const containsComma = str.original
|
|
2726
2741
|
.substring(eachBlock.expression.start, eachBlock.expression.end)
|
|
2727
2742
|
.includes(',');
|
|
2728
|
-
const
|
|
2729
|
-
|
|
2743
|
+
const expressionEnd = getEnd(eachBlock.expression, str);
|
|
2744
|
+
const contextEnd = getEnd(eachBlock.context, str);
|
|
2745
|
+
const arrayAndItemVarTheSame = str.original.substring(eachBlock.expression.start, expressionEnd) ===
|
|
2746
|
+
str.original.substring(eachBlock.context.start, contextEnd);
|
|
2730
2747
|
if (arrayAndItemVarTheSame) {
|
|
2731
2748
|
transforms = [
|
|
2732
2749
|
`{ const $$_each = __sveltets_2_ensureArray(${containsComma ? '(' : ''}`,
|
|
2733
2750
|
[eachBlock.expression.start, eachBlock.expression.end],
|
|
2734
2751
|
`${containsComma ? ')' : ''}); for(let `,
|
|
2735
|
-
[eachBlock.context.start,
|
|
2752
|
+
[eachBlock.context.start, contextEnd],
|
|
2736
2753
|
' of $$_each){'
|
|
2737
2754
|
];
|
|
2738
2755
|
}
|
|
2739
2756
|
else {
|
|
2740
2757
|
transforms = [
|
|
2741
2758
|
'for(let ',
|
|
2742
|
-
[eachBlock.context.start,
|
|
2759
|
+
[eachBlock.context.start, contextEnd],
|
|
2743
2760
|
` of __sveltets_2_ensureArray(${containsComma ? '(' : ''}`,
|
|
2744
2761
|
[eachBlock.expression.start, eachBlock.expression.end],
|
|
2745
2762
|
`${containsComma ? ')' : ''})){`
|
|
@@ -2770,6 +2787,14 @@ function handleEach(str, eachBlock) {
|
|
|
2770
2787
|
});
|
|
2771
2788
|
}
|
|
2772
2789
|
}
|
|
2790
|
+
/**
|
|
2791
|
+
* Get the end of the node, excluding the type annotation
|
|
2792
|
+
*/
|
|
2793
|
+
function getEnd(node, str) {
|
|
2794
|
+
return node.typeAnnotation
|
|
2795
|
+
? str.original.lastIndexOf(':', node.typeAnnotation.start)
|
|
2796
|
+
: node.end;
|
|
2797
|
+
}
|
|
2773
2798
|
|
|
2774
2799
|
/**
|
|
2775
2800
|
* Transform on:xxx={yyy}
|
|
@@ -3034,14 +3059,15 @@ function handleTransitionDirective(str, attr, element) {
|
|
|
3034
3059
|
* }
|
|
3035
3060
|
* ```
|
|
3036
3061
|
*/
|
|
3037
|
-
function handleSnippet(str, snippetBlock,
|
|
3062
|
+
function handleSnippet(str, snippetBlock, component) {
|
|
3038
3063
|
var _a;
|
|
3039
3064
|
const endSnippet = str.original.lastIndexOf('{', snippetBlock.end - 1);
|
|
3040
|
-
|
|
3065
|
+
// Return something to silence the "snippet type not assignable to return type void" error
|
|
3066
|
+
str.overwrite(endSnippet, snippetBlock.end, 'return __sveltets_2_any(0)}', {
|
|
3041
3067
|
contentOnly: true
|
|
3042
3068
|
});
|
|
3043
3069
|
const startEnd = str.original.indexOf('}', ((_a = snippetBlock.context) === null || _a === void 0 ? void 0 : _a.end) || snippetBlock.expression.end) + 1;
|
|
3044
|
-
if (
|
|
3070
|
+
if (component !== undefined) {
|
|
3045
3071
|
str.overwrite(snippetBlock.start, snippetBlock.expression.start, '', { contentOnly: true });
|
|
3046
3072
|
const transforms = ['('];
|
|
3047
3073
|
if (snippetBlock.context) {
|
|
@@ -3056,13 +3082,20 @@ function handleSnippet(str, snippetBlock, element) {
|
|
|
3056
3082
|
}
|
|
3057
3083
|
transforms.push(') => {');
|
|
3058
3084
|
transforms.push([startEnd, snippetBlock.end]);
|
|
3059
|
-
|
|
3085
|
+
component.addProp([[snippetBlock.expression.start, snippetBlock.expression.end]], transforms);
|
|
3060
3086
|
}
|
|
3061
3087
|
else {
|
|
3088
|
+
const generic = snippetBlock.context
|
|
3089
|
+
? snippetBlock.context.typeAnnotation
|
|
3090
|
+
? `<${str.original.slice(snippetBlock.context.typeAnnotation.start, snippetBlock.context.typeAnnotation.end)}>`
|
|
3091
|
+
: // slap any on to it to silence "implicit any" errors; JSDoc people can't add types to snippets
|
|
3092
|
+
'<any>'
|
|
3093
|
+
: '';
|
|
3094
|
+
const typeAnnotation = surroundWithIgnoreComments(`: import('svelte').Snippet${generic}`);
|
|
3062
3095
|
const transforms = [
|
|
3063
|
-
'
|
|
3096
|
+
'var ',
|
|
3064
3097
|
[snippetBlock.expression.start, snippetBlock.expression.end],
|
|
3065
|
-
' = ('
|
|
3098
|
+
typeAnnotation + ' = ('
|
|
3066
3099
|
];
|
|
3067
3100
|
if (snippetBlock.context) {
|
|
3068
3101
|
transforms.push([snippetBlock.context.start, snippetBlock.context.end]);
|
|
@@ -3071,17 +3104,53 @@ function handleSnippet(str, snippetBlock, element) {
|
|
|
3071
3104
|
transform(str, snippetBlock.start, startEnd, startEnd, transforms);
|
|
3072
3105
|
}
|
|
3073
3106
|
}
|
|
3107
|
+
function handleImplicitChildren(componentNode, component) {
|
|
3108
|
+
var _a;
|
|
3109
|
+
if (((_a = componentNode.children) === null || _a === void 0 ? void 0 : _a.length) === 0) {
|
|
3110
|
+
return;
|
|
3111
|
+
}
|
|
3112
|
+
let hasSlot = false;
|
|
3113
|
+
for (const child of componentNode.children) {
|
|
3114
|
+
if (child.type === 'SvelteSelf' ||
|
|
3115
|
+
child.type === 'InlineComponent' ||
|
|
3116
|
+
child.type === 'Element' ||
|
|
3117
|
+
child.type === 'SlotTemplate') {
|
|
3118
|
+
if (child.attributes.some((a) => {
|
|
3119
|
+
var _a;
|
|
3120
|
+
return a.type === 'Attribute' &&
|
|
3121
|
+
a.name === 'slot' &&
|
|
3122
|
+
((_a = a.value[0]) === null || _a === void 0 ? void 0 : _a.data) !== 'default';
|
|
3123
|
+
})) {
|
|
3124
|
+
continue;
|
|
3125
|
+
}
|
|
3126
|
+
}
|
|
3127
|
+
if (child.type === 'Text' && child.data.trim() === '') {
|
|
3128
|
+
continue;
|
|
3129
|
+
}
|
|
3130
|
+
if (child.type !== 'SnippetBlock') {
|
|
3131
|
+
hasSlot = true;
|
|
3132
|
+
break;
|
|
3133
|
+
}
|
|
3134
|
+
}
|
|
3135
|
+
if (!hasSlot) {
|
|
3136
|
+
return;
|
|
3137
|
+
}
|
|
3138
|
+
// it's enough to fake a children prop, we don't need to actually move the content inside (which would also reset control flow)
|
|
3139
|
+
component.addProp(['children'], ['() => { return __sveltets_2_any(0); }']);
|
|
3140
|
+
}
|
|
3074
3141
|
|
|
3075
3142
|
/**
|
|
3076
3143
|
* `{@render foo(x)}` --> `;foo(x);`
|
|
3077
3144
|
*/
|
|
3078
3145
|
function handleRenderTag(str, renderTag) {
|
|
3079
|
-
str.overwrite(renderTag.start, renderTag.expression.start, ';', {
|
|
3146
|
+
str.overwrite(renderTag.start, renderTag.expression.start, ';__sveltets_2_ensureSnippet(', {
|
|
3147
|
+
contentOnly: true
|
|
3148
|
+
});
|
|
3080
3149
|
if (renderTag.argument) {
|
|
3081
|
-
str.overwrite(withTrailingPropertyAccess(str.original, renderTag.argument.end), renderTag.end, ');');
|
|
3150
|
+
str.overwrite(withTrailingPropertyAccess(str.original, renderTag.argument.end), renderTag.end, '));');
|
|
3082
3151
|
}
|
|
3083
3152
|
else {
|
|
3084
|
-
str.overwrite(withTrailingPropertyAccess(str.original, renderTag.expression.end), renderTag.end, '();');
|
|
3153
|
+
str.overwrite(withTrailingPropertyAccess(str.original, renderTag.expression.end), renderTag.end, '());');
|
|
3085
3154
|
}
|
|
3086
3155
|
}
|
|
3087
3156
|
|
|
@@ -3096,11 +3165,12 @@ function stripDoctype(str) {
|
|
|
3096
3165
|
* Walks the HTMLx part of the Svelte component
|
|
3097
3166
|
* and converts it to JSX
|
|
3098
3167
|
*/
|
|
3099
|
-
function convertHtmlxToJsx(str, ast, onWalk = null, onLeave = null, options = {}) {
|
|
3168
|
+
function convertHtmlxToJsx(str, ast, onWalk = null, onLeave = null, options = { svelte5Plus: false }) {
|
|
3100
3169
|
str.original;
|
|
3101
3170
|
options = { preserveAttributeCase: false, ...options };
|
|
3102
3171
|
options.typingsNamespace = options.typingsNamespace || 'svelteHTML';
|
|
3103
3172
|
stripDoctype(str);
|
|
3173
|
+
const rootSnippets = [];
|
|
3104
3174
|
let element;
|
|
3105
3175
|
walk(ast, {
|
|
3106
3176
|
enter: (estreeTypedNode, estreeTypedParent, prop, index) => {
|
|
@@ -3125,6 +3195,10 @@ function convertHtmlxToJsx(str, ast, onWalk = null, onLeave = null, options = {}
|
|
|
3125
3195
|
estreeTypedParent.type === 'InlineComponent'
|
|
3126
3196
|
? element
|
|
3127
3197
|
: undefined);
|
|
3198
|
+
if (!element) {
|
|
3199
|
+
// root snippet -> move to instance script
|
|
3200
|
+
rootSnippets.push([node.start, node.end]);
|
|
3201
|
+
}
|
|
3128
3202
|
break;
|
|
3129
3203
|
case 'MustacheTag':
|
|
3130
3204
|
handleMustacheTag(str, node, parent);
|
|
@@ -3149,6 +3223,9 @@ function convertHtmlxToJsx(str, ast, onWalk = null, onLeave = null, options = {}
|
|
|
3149
3223
|
else {
|
|
3150
3224
|
element = new InlineComponent(str, node);
|
|
3151
3225
|
}
|
|
3226
|
+
if (options.svelte5Plus) {
|
|
3227
|
+
handleImplicitChildren(node, element);
|
|
3228
|
+
}
|
|
3152
3229
|
break;
|
|
3153
3230
|
case 'Element':
|
|
3154
3231
|
case 'Options':
|
|
@@ -3253,6 +3330,7 @@ function convertHtmlxToJsx(str, ast, onWalk = null, onLeave = null, options = {}
|
|
|
3253
3330
|
}
|
|
3254
3331
|
}
|
|
3255
3332
|
});
|
|
3333
|
+
return rootSnippets;
|
|
3256
3334
|
}
|
|
3257
3335
|
|
|
3258
3336
|
/**
|
|
@@ -4255,10 +4333,11 @@ function is$$PropsDeclaration(node) {
|
|
|
4255
4333
|
return isInterfaceOrTypeDeclaration(node) && node.name.text === '$$Props';
|
|
4256
4334
|
}
|
|
4257
4335
|
class ExportedNames {
|
|
4258
|
-
constructor(str, astOffset, basename) {
|
|
4336
|
+
constructor(str, astOffset, basename, isTsFile) {
|
|
4259
4337
|
this.str = str;
|
|
4260
4338
|
this.astOffset = astOffset;
|
|
4261
4339
|
this.basename = basename;
|
|
4340
|
+
this.isTsFile = isTsFile;
|
|
4262
4341
|
/**
|
|
4263
4342
|
* Uses the `$$Props` type
|
|
4264
4343
|
*/
|
|
@@ -4349,16 +4428,89 @@ class ExportedNames {
|
|
|
4349
4428
|
this.$props.generic = node.initializer.typeArguments[0].getText();
|
|
4350
4429
|
}
|
|
4351
4430
|
else {
|
|
4352
|
-
|
|
4353
|
-
|
|
4354
|
-
|
|
4355
|
-
|
|
4356
|
-
|
|
4357
|
-
|
|
4358
|
-
|
|
4431
|
+
if (!this.isTsFile) {
|
|
4432
|
+
const text = node.getSourceFile().getFullText();
|
|
4433
|
+
let comments = (_b = ts
|
|
4434
|
+
.getLeadingCommentRanges(text, node.pos)) === null || _b === void 0 ? void 0 : _b.map((c) => text.substring(c.pos, c.end)).find((c) => c.includes('@type'));
|
|
4435
|
+
if (!comments) {
|
|
4436
|
+
comments = (_c = ts
|
|
4437
|
+
.getLeadingCommentRanges(text, node.parent.pos)) === null || _c === void 0 ? void 0 : _c.map((c) => text.substring(c.pos, c.end)).find((c) => c.includes('@type'));
|
|
4438
|
+
}
|
|
4439
|
+
// We don't bother extracting the type, we just use the comment as-is
|
|
4440
|
+
this.$props.comment = comments || '';
|
|
4441
|
+
}
|
|
4442
|
+
if (this.$props.comment) {
|
|
4443
|
+
return;
|
|
4444
|
+
}
|
|
4445
|
+
if (internalHelpers.isKitRouteFile(this.basename)) {
|
|
4446
|
+
const kitType = this.basename.includes('layout')
|
|
4447
|
+
? `{ data: import('./$types.js').LayoutData, form: import('./$types.js').ActionData, children: import('svelte').Snippet }`
|
|
4448
|
+
: `{ data: import('./$types.js').PageData, form: import('./$types.js').ActionData }`;
|
|
4449
|
+
if (this.isTsFile) {
|
|
4450
|
+
this.$props.generic = kitType;
|
|
4451
|
+
preprendStr(this.str, node.initializer.expression.end + this.astOffset, surroundWithIgnoreComments(`<${kitType}>`));
|
|
4452
|
+
}
|
|
4453
|
+
else {
|
|
4454
|
+
this.$props.comment = `/** @type {${kitType}} */`;
|
|
4455
|
+
preprendStr(this.str, node.pos + this.astOffset, this.$props.comment);
|
|
4456
|
+
}
|
|
4457
|
+
}
|
|
4458
|
+
else {
|
|
4459
|
+
// Do a best-effort to extract the props from the object literal
|
|
4460
|
+
let propsStr = '';
|
|
4461
|
+
let withUnknown = false;
|
|
4462
|
+
let props = [];
|
|
4463
|
+
if (ts.isObjectBindingPattern(node.name)) {
|
|
4464
|
+
for (const element of node.name.elements) {
|
|
4465
|
+
if (!ts.isIdentifier(element.name) || !!element.dotDotDotToken) {
|
|
4466
|
+
withUnknown = true;
|
|
4467
|
+
}
|
|
4468
|
+
else {
|
|
4469
|
+
if (element.initializer) {
|
|
4470
|
+
const type = ts.isAsExpression(element.initializer)
|
|
4471
|
+
? element.initializer.type.getText()
|
|
4472
|
+
: ts.isStringLiteral(element.initializer)
|
|
4473
|
+
? 'string'
|
|
4474
|
+
: ts.isNumericLiteral(element.initializer)
|
|
4475
|
+
? 'number'
|
|
4476
|
+
: element.initializer.kind === ts.SyntaxKind.TrueKeyword ||
|
|
4477
|
+
element.initializer.kind === ts.SyntaxKind.FalseKeyword
|
|
4478
|
+
? 'boolean'
|
|
4479
|
+
: ts.isIdentifier(element.initializer)
|
|
4480
|
+
? `typeof ${element.initializer.text}`
|
|
4481
|
+
: 'unknown';
|
|
4482
|
+
props.push(`${element.name.text}?: ${type}`);
|
|
4483
|
+
}
|
|
4484
|
+
else {
|
|
4485
|
+
props.push(`${element.name.text}: unknown`);
|
|
4486
|
+
}
|
|
4487
|
+
}
|
|
4488
|
+
}
|
|
4489
|
+
}
|
|
4490
|
+
if (props.length > 0) {
|
|
4491
|
+
propsStr =
|
|
4492
|
+
`{ ${props.join(', ')} }` +
|
|
4493
|
+
(withUnknown ? ' & Record<string, unknown>' : '');
|
|
4494
|
+
}
|
|
4495
|
+
else if (withUnknown) {
|
|
4496
|
+
propsStr = 'Record<string, unknown>';
|
|
4497
|
+
}
|
|
4498
|
+
else {
|
|
4499
|
+
propsStr = 'Record<string, never>';
|
|
4500
|
+
}
|
|
4501
|
+
if (this.isTsFile) {
|
|
4502
|
+
this.$props.generic = propsStr;
|
|
4503
|
+
if (props.length > 0 || withUnknown) {
|
|
4504
|
+
preprendStr(this.str, node.initializer.expression.end + this.astOffset, surroundWithIgnoreComments(`<${propsStr}>`));
|
|
4505
|
+
}
|
|
4506
|
+
}
|
|
4507
|
+
else {
|
|
4508
|
+
this.$props.comment = `/** @type {${propsStr}} */`;
|
|
4509
|
+
if (props.length > 0 || withUnknown) {
|
|
4510
|
+
preprendStr(this.str, node.pos + this.astOffset, this.$props.comment);
|
|
4511
|
+
}
|
|
4512
|
+
}
|
|
4359
4513
|
}
|
|
4360
|
-
// We don't bother extracting the type, we just use the comment as-is
|
|
4361
|
-
this.$props.comment = comments || '';
|
|
4362
4514
|
}
|
|
4363
4515
|
}
|
|
4364
4516
|
removeExport(start, end) {
|
|
@@ -4511,6 +4663,14 @@ class ExportedNames {
|
|
|
4511
4663
|
});
|
|
4512
4664
|
}
|
|
4513
4665
|
}
|
|
4666
|
+
addImplicitChildrenExport(hasAttributes) {
|
|
4667
|
+
if (this.exports.has('children'))
|
|
4668
|
+
return;
|
|
4669
|
+
this.exports.set('children', {
|
|
4670
|
+
isLet: true,
|
|
4671
|
+
implicitChildren: hasAttributes ? 'attributes' : 'empty'
|
|
4672
|
+
});
|
|
4673
|
+
}
|
|
4514
4674
|
/**
|
|
4515
4675
|
* Adds export to map
|
|
4516
4676
|
*/
|
|
@@ -4570,7 +4730,7 @@ class ExportedNames {
|
|
|
4570
4730
|
* @param isTsFile Whether this is a TypeScript file or not.
|
|
4571
4731
|
* @param uses$$propsOr$$restProps whether the file references the $$props or $$restProps variable
|
|
4572
4732
|
*/
|
|
4573
|
-
createPropsStr(
|
|
4733
|
+
createPropsStr(uses$$propsOr$$restProps) {
|
|
4574
4734
|
const names = Array.from(this.exports.entries());
|
|
4575
4735
|
if (this.$props.generic) {
|
|
4576
4736
|
const others = names.filter(([, { isLet }]) => !isLet);
|
|
@@ -4606,11 +4766,11 @@ class ExportedNames {
|
|
|
4606
4766
|
}
|
|
4607
4767
|
if (names.length === 0 && !uses$$propsOr$$restProps) {
|
|
4608
4768
|
// Necessary, because {} roughly equals to any
|
|
4609
|
-
return isTsFile
|
|
4769
|
+
return this.isTsFile
|
|
4610
4770
|
? '{} as Record<string, never>'
|
|
4611
4771
|
: '/** @type {Record<string, never>} */ ({})';
|
|
4612
4772
|
}
|
|
4613
|
-
const dontAddTypeDef = !isTsFile || names.every(([_, value]) => !value.type && value.required);
|
|
4773
|
+
const dontAddTypeDef = !this.isTsFile || names.every(([_, value]) => !value.type && value.required);
|
|
4614
4774
|
const returnElements = this.createReturnElements(names, dontAddTypeDef);
|
|
4615
4775
|
if (dontAddTypeDef) {
|
|
4616
4776
|
// Only `typeof` exports -> omit the `as {...}` completely.
|
|
@@ -4622,12 +4782,22 @@ class ExportedNames {
|
|
|
4622
4782
|
}
|
|
4623
4783
|
createReturnElements(names, dontAddTypeDef) {
|
|
4624
4784
|
return names.map(([key, value]) => {
|
|
4785
|
+
if (value.implicitChildren) {
|
|
4786
|
+
return `children?: ${value.implicitChildren === 'empty'
|
|
4787
|
+
? '__sveltets_2_snippet()'
|
|
4788
|
+
: '$$implicit_children'}`;
|
|
4789
|
+
}
|
|
4625
4790
|
// Important to not use shorthand props for rename functionality
|
|
4626
4791
|
return `${dontAddTypeDef && value.doc ? `\n${value.doc}` : ''}${value.identifierText || key}: ${key}`;
|
|
4627
4792
|
});
|
|
4628
4793
|
}
|
|
4629
4794
|
createReturnElementsType(names) {
|
|
4630
4795
|
return names.map(([key, value]) => {
|
|
4796
|
+
if (value.implicitChildren) {
|
|
4797
|
+
return `children?: ${value.implicitChildren === 'empty'
|
|
4798
|
+
? `import('svelte').Snippet`
|
|
4799
|
+
: 'typeof $$implicit_children'}`;
|
|
4800
|
+
}
|
|
4631
4801
|
const identifier = `${value.doc ? `\n${value.doc}` : ''}${value.identifierText || key}${value.required ? '' : '?'}`;
|
|
4632
4802
|
if (!value.type) {
|
|
4633
4803
|
return `${identifier}: typeof ${key}`;
|
|
@@ -4643,6 +4813,9 @@ class ExportedNames {
|
|
|
4643
4813
|
getExportsMap() {
|
|
4644
4814
|
return this.exports;
|
|
4645
4815
|
}
|
|
4816
|
+
uses$propsRune() {
|
|
4817
|
+
return !!this.$props.generic || !!this.$props.comment;
|
|
4818
|
+
}
|
|
4646
4819
|
}
|
|
4647
4820
|
|
|
4648
4821
|
function isMember(parent, prop) {
|
|
@@ -5588,12 +5761,12 @@ class InterfacesAndTypes {
|
|
|
5588
5761
|
}
|
|
5589
5762
|
}
|
|
5590
5763
|
|
|
5591
|
-
function processInstanceScriptContent(str, script, events, implicitStoreValues, mode, hasModuleScript, basename) {
|
|
5764
|
+
function processInstanceScriptContent(str, script, events, implicitStoreValues, mode, hasModuleScript, isTSFile, basename) {
|
|
5592
5765
|
const htmlx = str.original;
|
|
5593
5766
|
const scriptContent = htmlx.substring(script.content.start, script.content.end);
|
|
5594
5767
|
const tsAst = ts.createSourceFile('component.ts.svelte', scriptContent, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS);
|
|
5595
5768
|
const astOffset = script.content.start;
|
|
5596
|
-
const exportedNames = new ExportedNames(str, astOffset, basename);
|
|
5769
|
+
const exportedNames = new ExportedNames(str, astOffset, basename, isTSFile);
|
|
5597
5770
|
const generics = new Generics(str, astOffset, script);
|
|
5598
5771
|
const interfacesAndTypes = new InterfacesAndTypes();
|
|
5599
5772
|
const implicitTopLevelNames = new ImplicitTopLevelNames(str, astOffset);
|
|
@@ -6042,7 +6215,7 @@ function classNameFromFilename(filename, appendSuffix) {
|
|
|
6042
6215
|
}
|
|
6043
6216
|
}
|
|
6044
6217
|
|
|
6045
|
-
function createRenderFunction({ str, scriptTag, scriptDestination, slots, events, exportedNames,
|
|
6218
|
+
function createRenderFunction({ str, scriptTag, scriptDestination, rootSnippets, slots, events, exportedNames, uses$$props, uses$$restProps, uses$$slots, uses$$SlotsInterface, generics, svelte5Plus, mode }) {
|
|
6046
6219
|
const htmlx = str.original;
|
|
6047
6220
|
let propsDecl = '';
|
|
6048
6221
|
if (uses$$props) {
|
|
@@ -6089,6 +6262,9 @@ function createRenderFunction({ str, scriptTag, scriptDestination, slots, events
|
|
|
6089
6262
|
str.overwrite(scriptTag.start + 1, scriptTagEnd, `function render${generics.toDefinitionString(true)}() {${propsDecl}\n`);
|
|
6090
6263
|
}
|
|
6091
6264
|
const scriptEndTagStart = htmlx.lastIndexOf('<', scriptTag.end - 1);
|
|
6265
|
+
for (const rootSnippet of rootSnippets) {
|
|
6266
|
+
str.move(rootSnippet[0], rootSnippet[1], scriptEndTagStart);
|
|
6267
|
+
}
|
|
6092
6268
|
// wrap template with callback
|
|
6093
6269
|
str.overwrite(scriptEndTagStart, scriptTag.end, `${slotsDeclaration};\nasync () => {`, {
|
|
6094
6270
|
contentOnly: true
|
|
@@ -6102,22 +6278,32 @@ function createRenderFunction({ str, scriptTag, scriptDestination, slots, events
|
|
|
6102
6278
|
: '{' +
|
|
6103
6279
|
Array.from(slots.entries())
|
|
6104
6280
|
.map(([name, attrs]) => {
|
|
6105
|
-
|
|
6106
|
-
.map(([exportName, expr]) => exportName.startsWith('__spread__')
|
|
6107
|
-
? `...${expr}`
|
|
6108
|
-
: `${exportName}:${expr}`)
|
|
6109
|
-
.join(', ');
|
|
6110
|
-
return `'${name}': {${attrsAsString}}`;
|
|
6281
|
+
return `'${name}': {${slotAttributesToString(attrs)}}`;
|
|
6111
6282
|
})
|
|
6112
6283
|
.join(', ') +
|
|
6113
6284
|
'}';
|
|
6114
|
-
const
|
|
6285
|
+
const needsImplicitChildrenProp = svelte5Plus &&
|
|
6286
|
+
!exportedNames.uses$propsRune() &&
|
|
6287
|
+
slots.has('default') &&
|
|
6288
|
+
!exportedNames.getExportsMap().has('default');
|
|
6289
|
+
if (needsImplicitChildrenProp) {
|
|
6290
|
+
exportedNames.addImplicitChildrenExport(slots.get('default').size > 0);
|
|
6291
|
+
}
|
|
6292
|
+
const returnString = `${needsImplicitChildrenProp && slots.get('default').size > 0
|
|
6293
|
+
? `\nlet $$implicit_children = __sveltets_2_snippet({${slotAttributesToString(slots.get('default'))}});`
|
|
6294
|
+
: ''}` +
|
|
6295
|
+
`\nreturn { props: ${exportedNames.createPropsStr(uses$$props || uses$$restProps)}` +
|
|
6115
6296
|
`, slots: ${slotsAsDef}` +
|
|
6116
6297
|
`, events: ${events.toDefString()} }}`;
|
|
6117
6298
|
// wrap template with callback
|
|
6118
6299
|
str.append('};');
|
|
6119
6300
|
str.append(returnString);
|
|
6120
6301
|
}
|
|
6302
|
+
function slotAttributesToString(attrs) {
|
|
6303
|
+
return Array.from(attrs.entries())
|
|
6304
|
+
.map(([exportName, expr]) => exportName.startsWith('__spread__') ? `...${expr}` : `${exportName}:${expr}`)
|
|
6305
|
+
.join(', ');
|
|
6306
|
+
}
|
|
6121
6307
|
|
|
6122
6308
|
function processSvelteTemplate(str, parse, options) {
|
|
6123
6309
|
const { htmlxAst, tags } = parseHtmlx(str.original, parse, options);
|
|
@@ -6303,9 +6489,10 @@ function processSvelteTemplate(str, parse, options) {
|
|
|
6303
6489
|
break;
|
|
6304
6490
|
}
|
|
6305
6491
|
};
|
|
6306
|
-
convertHtmlxToJsx(str, htmlxAst, onHtmlxWalk, onHtmlxLeave, {
|
|
6492
|
+
const rootSnippets = convertHtmlxToJsx(str, htmlxAst, onHtmlxWalk, onHtmlxLeave, {
|
|
6307
6493
|
preserveAttributeCase: (options === null || options === void 0 ? void 0 : options.namespace) == 'foreign',
|
|
6308
|
-
typingsNamespace: options.typingsNamespace
|
|
6494
|
+
typingsNamespace: options.typingsNamespace,
|
|
6495
|
+
svelte5Plus: options.svelte5Plus
|
|
6309
6496
|
});
|
|
6310
6497
|
// resolve scripts
|
|
6311
6498
|
const { scriptTag, moduleScriptTag } = scripts.getTopLevelScriptTags();
|
|
@@ -6318,6 +6505,7 @@ function processSvelteTemplate(str, parse, options) {
|
|
|
6318
6505
|
htmlAst: htmlxAst,
|
|
6319
6506
|
moduleScriptTag,
|
|
6320
6507
|
scriptTag,
|
|
6508
|
+
rootSnippets,
|
|
6321
6509
|
slots: slotHandler.getSlotDef(),
|
|
6322
6510
|
events: new ComponentEvents(eventHandler, tags.some((tag) => { var _a; return (_a = tag.attributes) === null || _a === void 0 ? void 0 : _a.some((a) => a.name === 'strictEvents'); }), str),
|
|
6323
6511
|
uses$$props,
|
|
@@ -6330,10 +6518,15 @@ function processSvelteTemplate(str, parse, options) {
|
|
|
6330
6518
|
}
|
|
6331
6519
|
function svelte2tsx(svelte, options = { parse: compiler.parse }) {
|
|
6332
6520
|
options.mode = options.mode || 'ts';
|
|
6521
|
+
options.version = options.version || compiler.VERSION;
|
|
6333
6522
|
const str = new MagicString(svelte);
|
|
6334
6523
|
const basename = path.basename(options.filename || '');
|
|
6524
|
+
const svelte5Plus = Number(options.version[0]) > 4;
|
|
6335
6525
|
// process the htmlx as a svelte template
|
|
6336
|
-
let { htmlAst, moduleScriptTag, scriptTag, slots, uses$$props, uses$$slots, uses$$restProps, events, componentDocumentation, resolvedStores, usesAccessors } = processSvelteTemplate(str, options.parse || compiler.parse,
|
|
6526
|
+
let { htmlAst, moduleScriptTag, scriptTag, rootSnippets, slots, uses$$props, uses$$slots, uses$$restProps, events, componentDocumentation, resolvedStores, usesAccessors } = processSvelteTemplate(str, options.parse || compiler.parse, {
|
|
6527
|
+
...options,
|
|
6528
|
+
svelte5Plus
|
|
6529
|
+
});
|
|
6337
6530
|
/* Rearrange the script tags so that module is first, and instance second followed finally by the template
|
|
6338
6531
|
* This is a bit convoluted due to some trouble I had with magic string. A simple str.move(start,end,0) for each script wasn't enough
|
|
6339
6532
|
* since if the module script was already at 0, it wouldn't move (which is fine) but would mean the order would be swapped when the script tag tried to move to 0
|
|
@@ -6355,7 +6548,7 @@ function svelte2tsx(svelte, options = { parse: compiler.parse }) {
|
|
|
6355
6548
|
: instanceScriptTarget;
|
|
6356
6549
|
const implicitStoreValues = new ImplicitStoreValues(resolvedStores, renderFunctionStart);
|
|
6357
6550
|
//move the instance script and process the content
|
|
6358
|
-
let exportedNames = new ExportedNames(str, 0, basename);
|
|
6551
|
+
let exportedNames = new ExportedNames(str, 0, basename, options === null || options === void 0 ? void 0 : options.isTsFile);
|
|
6359
6552
|
let generics = new Generics(str, 0, { attributes: [] });
|
|
6360
6553
|
let uses$$SlotsInterface = false;
|
|
6361
6554
|
if (scriptTag) {
|
|
@@ -6364,7 +6557,7 @@ function svelte2tsx(svelte, options = { parse: compiler.parse }) {
|
|
|
6364
6557
|
str.move(scriptTag.start, scriptTag.end, instanceScriptTarget);
|
|
6365
6558
|
}
|
|
6366
6559
|
const res = processInstanceScriptContent(str, scriptTag, events, implicitStoreValues, options.mode,
|
|
6367
|
-
/**hasModuleScripts */ !!moduleScriptTag, basename);
|
|
6560
|
+
/**hasModuleScripts */ !!moduleScriptTag, options === null || options === void 0 ? void 0 : options.isTsFile, basename);
|
|
6368
6561
|
uses$$props = uses$$props || res.uses$$props;
|
|
6369
6562
|
uses$$restProps = uses$$restProps || res.uses$$restProps;
|
|
6370
6563
|
uses$$slots = uses$$slots || res.uses$$slots;
|
|
@@ -6375,15 +6568,16 @@ function svelte2tsx(svelte, options = { parse: compiler.parse }) {
|
|
|
6375
6568
|
str,
|
|
6376
6569
|
scriptTag,
|
|
6377
6570
|
scriptDestination: instanceScriptTarget,
|
|
6571
|
+
rootSnippets,
|
|
6378
6572
|
slots,
|
|
6379
6573
|
events,
|
|
6380
6574
|
exportedNames,
|
|
6381
|
-
isTsFile: options === null || options === void 0 ? void 0 : options.isTsFile,
|
|
6382
6575
|
uses$$props,
|
|
6383
6576
|
uses$$restProps,
|
|
6384
6577
|
uses$$slots,
|
|
6385
6578
|
uses$$SlotsInterface,
|
|
6386
6579
|
generics,
|
|
6580
|
+
svelte5Plus,
|
|
6387
6581
|
mode: options.mode
|
|
6388
6582
|
});
|
|
6389
6583
|
// we need to process the module script after the instance script has moved otherwise we get warnings about moving edited items
|
|
@@ -6490,13 +6684,13 @@ function loadTsconfig(config, svelteMap) {
|
|
|
6490
6684
|
return {
|
|
6491
6685
|
options: {
|
|
6492
6686
|
...options,
|
|
6493
|
-
noEmit: false,
|
|
6687
|
+
noEmit: false, // Set to true in case of jsconfig, force false, else nothing is emitted
|
|
6494
6688
|
moduleResolution:
|
|
6495
6689
|
// NodeJS: up to 4.9, Node10: since 5.0
|
|
6496
|
-
(_a = ts.ModuleResolutionKind.NodeJs) !== null && _a !== void 0 ? _a : ts.ModuleResolutionKind.Node10,
|
|
6497
|
-
declaration: true,
|
|
6498
|
-
emitDeclarationOnly: true,
|
|
6499
|
-
declarationDir: config.declarationDir,
|
|
6690
|
+
(_a = ts.ModuleResolutionKind.NodeJs) !== null && _a !== void 0 ? _a : ts.ModuleResolutionKind.Node10, // Classic if not set, which gives wrong results
|
|
6691
|
+
declaration: true, // Needed for d.ts file generation
|
|
6692
|
+
emitDeclarationOnly: true, // We only want d.ts file generation
|
|
6693
|
+
declarationDir: config.declarationDir, // Where to put the declarations
|
|
6500
6694
|
allowNonTsExtensions: true
|
|
6501
6695
|
},
|
|
6502
6696
|
filenames
|
package/index.mjs
CHANGED
|
@@ -3,7 +3,7 @@ import ts from 'typescript';
|
|
|
3
3
|
import * as path from 'path';
|
|
4
4
|
import path__default from 'path';
|
|
5
5
|
import { pascalCase } from 'pascal-case';
|
|
6
|
-
import { parse } from 'svelte/compiler';
|
|
6
|
+
import { VERSION, parse } from 'svelte/compiler';
|
|
7
7
|
|
|
8
8
|
const comma = ','.charCodeAt(0);
|
|
9
9
|
const semicolon = ';'.charCodeAt(0);
|
|
@@ -1459,8 +1459,11 @@ function parseAttributes(str, start) {
|
|
|
1459
1459
|
}
|
|
1460
1460
|
return attrs;
|
|
1461
1461
|
}
|
|
1462
|
+
// Regex ensures that attributes with > characters in them still result in the content being matched correctly
|
|
1463
|
+
const scriptRegex = /(<!--[^]*?-->)|(<script((?:\s+[^=>'"\/]+=(?:"[^"]*"|'[^']*'|[^>\s]+)|\s+[^=>'"\/]+)*\s*)>)([\S\s]*?)<\/script>/g;
|
|
1464
|
+
const styleRegex = /(<!--[^]*?-->)|(<style((?:\s+[^=>'"\/]+=(?:"[^"]*"|'[^']*'|[^>\s]+)|\s+[^=>'"\/]+)*\s*)>)([\S\s]*?)<\/style>/g;
|
|
1462
1465
|
function extractTag(htmlx, tag) {
|
|
1463
|
-
const exp =
|
|
1466
|
+
const exp = tag === 'script' ? scriptRegex : styleRegex;
|
|
1464
1467
|
const matches = [];
|
|
1465
1468
|
let match = null;
|
|
1466
1469
|
while ((match = exp.exec(htmlx)) != null) {
|
|
@@ -1657,9 +1660,12 @@ transformations) {
|
|
|
1657
1660
|
str.move(moves[i][0], moves[i][1], end);
|
|
1658
1661
|
}
|
|
1659
1662
|
let removeStart = start;
|
|
1660
|
-
|
|
1663
|
+
const sortedMoves = [...moves].sort((t1, t2) => t1[0] - t2[0]);
|
|
1664
|
+
for (const transformation of sortedMoves) {
|
|
1661
1665
|
if (removeStart < transformation[0]) {
|
|
1662
|
-
if (deletePos !== moves.length &&
|
|
1666
|
+
if (deletePos !== moves.length &&
|
|
1667
|
+
removeStart > deleteDest &&
|
|
1668
|
+
!(removeStart < end && transformation[0] >= end)) {
|
|
1663
1669
|
str.move(removeStart, transformation[0], end);
|
|
1664
1670
|
}
|
|
1665
1671
|
if (transformation[0] < end) {
|
|
@@ -1672,7 +1678,8 @@ transformations) {
|
|
|
1672
1678
|
if (removeStart > end) {
|
|
1673
1679
|
// Reset the end to the last transformation before the end if there were transformations after the end
|
|
1674
1680
|
// so we still delete the correct range afterwards
|
|
1675
|
-
|
|
1681
|
+
let idx = sortedMoves.findIndex((m) => m[0] > end) - 1;
|
|
1682
|
+
removeStart = (_b = (_a = sortedMoves[idx]) === null || _a === void 0 ? void 0 : _a[1]) !== null && _b !== void 0 ? _b : end;
|
|
1676
1683
|
}
|
|
1677
1684
|
if (removeStart < end) {
|
|
1678
1685
|
// Completely delete the first character afterwards. This makes the mapping more correct,
|
|
@@ -2368,7 +2375,9 @@ function handleAttribute(str, attr, parent, preserveCase, element) {
|
|
|
2368
2375
|
* lowercase the attribute name to make it adhere to our intrinsic elements definition
|
|
2369
2376
|
*/
|
|
2370
2377
|
const transformAttributeCase = (name) => {
|
|
2371
|
-
if (!preserveCase &&
|
|
2378
|
+
if (!preserveCase &&
|
|
2379
|
+
!svgAttributes.find((x) => x == name) &&
|
|
2380
|
+
!(element instanceof Element && element.tagName.includes('-'))) {
|
|
2372
2381
|
return name.toLowerCase();
|
|
2373
2382
|
}
|
|
2374
2383
|
else {
|
|
@@ -2420,9 +2429,10 @@ function handleAttribute(str, attr, parent, preserveCase, element) {
|
|
|
2420
2429
|
addAttribute(attributeName, [[attrVal.start - 1, attrVal.end + 1]]);
|
|
2421
2430
|
return;
|
|
2422
2431
|
}
|
|
2423
|
-
const
|
|
2424
|
-
|
|
2425
|
-
str.original
|
|
2432
|
+
const lastCharIndex = attrVal.end - 1;
|
|
2433
|
+
const hasBrackets = str.original[lastCharIndex] === '}' ||
|
|
2434
|
+
((str.original[lastCharIndex] === '"' || str.original[lastCharIndex] === "'") &&
|
|
2435
|
+
str.original[lastCharIndex - 1] === '}');
|
|
2426
2436
|
const needsNumberConversion = !hasBrackets &&
|
|
2427
2437
|
parent.type === 'Element' &&
|
|
2428
2438
|
numberOnlyAttributes.has(attr.name.toLowerCase()) &&
|
|
@@ -2624,7 +2634,12 @@ function handleBinding(str, attr, parent, element, preserveBind) {
|
|
|
2624
2634
|
: // Other typings - remove the bind: prefix
|
|
2625
2635
|
isShorthand
|
|
2626
2636
|
? [[attr.expression.start, attr.expression.end]]
|
|
2627
|
-
: [
|
|
2637
|
+
: [
|
|
2638
|
+
[
|
|
2639
|
+
attr.start + 'bind:'.length,
|
|
2640
|
+
str.original.lastIndexOf('=', attr.expression.start)
|
|
2641
|
+
]
|
|
2642
|
+
];
|
|
2628
2643
|
const value = isShorthand
|
|
2629
2644
|
? preserveBind && element instanceof Element
|
|
2630
2645
|
? [rangeWithTrailingPropertyAccess(str.original, attr.expression)]
|
|
@@ -2705,21 +2720,23 @@ function handleEach(str, eachBlock) {
|
|
|
2705
2720
|
const containsComma = str.original
|
|
2706
2721
|
.substring(eachBlock.expression.start, eachBlock.expression.end)
|
|
2707
2722
|
.includes(',');
|
|
2708
|
-
const
|
|
2709
|
-
|
|
2723
|
+
const expressionEnd = getEnd(eachBlock.expression, str);
|
|
2724
|
+
const contextEnd = getEnd(eachBlock.context, str);
|
|
2725
|
+
const arrayAndItemVarTheSame = str.original.substring(eachBlock.expression.start, expressionEnd) ===
|
|
2726
|
+
str.original.substring(eachBlock.context.start, contextEnd);
|
|
2710
2727
|
if (arrayAndItemVarTheSame) {
|
|
2711
2728
|
transforms = [
|
|
2712
2729
|
`{ const $$_each = __sveltets_2_ensureArray(${containsComma ? '(' : ''}`,
|
|
2713
2730
|
[eachBlock.expression.start, eachBlock.expression.end],
|
|
2714
2731
|
`${containsComma ? ')' : ''}); for(let `,
|
|
2715
|
-
[eachBlock.context.start,
|
|
2732
|
+
[eachBlock.context.start, contextEnd],
|
|
2716
2733
|
' of $$_each){'
|
|
2717
2734
|
];
|
|
2718
2735
|
}
|
|
2719
2736
|
else {
|
|
2720
2737
|
transforms = [
|
|
2721
2738
|
'for(let ',
|
|
2722
|
-
[eachBlock.context.start,
|
|
2739
|
+
[eachBlock.context.start, contextEnd],
|
|
2723
2740
|
` of __sveltets_2_ensureArray(${containsComma ? '(' : ''}`,
|
|
2724
2741
|
[eachBlock.expression.start, eachBlock.expression.end],
|
|
2725
2742
|
`${containsComma ? ')' : ''})){`
|
|
@@ -2750,6 +2767,14 @@ function handleEach(str, eachBlock) {
|
|
|
2750
2767
|
});
|
|
2751
2768
|
}
|
|
2752
2769
|
}
|
|
2770
|
+
/**
|
|
2771
|
+
* Get the end of the node, excluding the type annotation
|
|
2772
|
+
*/
|
|
2773
|
+
function getEnd(node, str) {
|
|
2774
|
+
return node.typeAnnotation
|
|
2775
|
+
? str.original.lastIndexOf(':', node.typeAnnotation.start)
|
|
2776
|
+
: node.end;
|
|
2777
|
+
}
|
|
2753
2778
|
|
|
2754
2779
|
/**
|
|
2755
2780
|
* Transform on:xxx={yyy}
|
|
@@ -3014,14 +3039,15 @@ function handleTransitionDirective(str, attr, element) {
|
|
|
3014
3039
|
* }
|
|
3015
3040
|
* ```
|
|
3016
3041
|
*/
|
|
3017
|
-
function handleSnippet(str, snippetBlock,
|
|
3042
|
+
function handleSnippet(str, snippetBlock, component) {
|
|
3018
3043
|
var _a;
|
|
3019
3044
|
const endSnippet = str.original.lastIndexOf('{', snippetBlock.end - 1);
|
|
3020
|
-
|
|
3045
|
+
// Return something to silence the "snippet type not assignable to return type void" error
|
|
3046
|
+
str.overwrite(endSnippet, snippetBlock.end, 'return __sveltets_2_any(0)}', {
|
|
3021
3047
|
contentOnly: true
|
|
3022
3048
|
});
|
|
3023
3049
|
const startEnd = str.original.indexOf('}', ((_a = snippetBlock.context) === null || _a === void 0 ? void 0 : _a.end) || snippetBlock.expression.end) + 1;
|
|
3024
|
-
if (
|
|
3050
|
+
if (component !== undefined) {
|
|
3025
3051
|
str.overwrite(snippetBlock.start, snippetBlock.expression.start, '', { contentOnly: true });
|
|
3026
3052
|
const transforms = ['('];
|
|
3027
3053
|
if (snippetBlock.context) {
|
|
@@ -3036,13 +3062,20 @@ function handleSnippet(str, snippetBlock, element) {
|
|
|
3036
3062
|
}
|
|
3037
3063
|
transforms.push(') => {');
|
|
3038
3064
|
transforms.push([startEnd, snippetBlock.end]);
|
|
3039
|
-
|
|
3065
|
+
component.addProp([[snippetBlock.expression.start, snippetBlock.expression.end]], transforms);
|
|
3040
3066
|
}
|
|
3041
3067
|
else {
|
|
3068
|
+
const generic = snippetBlock.context
|
|
3069
|
+
? snippetBlock.context.typeAnnotation
|
|
3070
|
+
? `<${str.original.slice(snippetBlock.context.typeAnnotation.start, snippetBlock.context.typeAnnotation.end)}>`
|
|
3071
|
+
: // slap any on to it to silence "implicit any" errors; JSDoc people can't add types to snippets
|
|
3072
|
+
'<any>'
|
|
3073
|
+
: '';
|
|
3074
|
+
const typeAnnotation = surroundWithIgnoreComments(`: import('svelte').Snippet${generic}`);
|
|
3042
3075
|
const transforms = [
|
|
3043
|
-
'
|
|
3076
|
+
'var ',
|
|
3044
3077
|
[snippetBlock.expression.start, snippetBlock.expression.end],
|
|
3045
|
-
' = ('
|
|
3078
|
+
typeAnnotation + ' = ('
|
|
3046
3079
|
];
|
|
3047
3080
|
if (snippetBlock.context) {
|
|
3048
3081
|
transforms.push([snippetBlock.context.start, snippetBlock.context.end]);
|
|
@@ -3051,17 +3084,53 @@ function handleSnippet(str, snippetBlock, element) {
|
|
|
3051
3084
|
transform(str, snippetBlock.start, startEnd, startEnd, transforms);
|
|
3052
3085
|
}
|
|
3053
3086
|
}
|
|
3087
|
+
function handleImplicitChildren(componentNode, component) {
|
|
3088
|
+
var _a;
|
|
3089
|
+
if (((_a = componentNode.children) === null || _a === void 0 ? void 0 : _a.length) === 0) {
|
|
3090
|
+
return;
|
|
3091
|
+
}
|
|
3092
|
+
let hasSlot = false;
|
|
3093
|
+
for (const child of componentNode.children) {
|
|
3094
|
+
if (child.type === 'SvelteSelf' ||
|
|
3095
|
+
child.type === 'InlineComponent' ||
|
|
3096
|
+
child.type === 'Element' ||
|
|
3097
|
+
child.type === 'SlotTemplate') {
|
|
3098
|
+
if (child.attributes.some((a) => {
|
|
3099
|
+
var _a;
|
|
3100
|
+
return a.type === 'Attribute' &&
|
|
3101
|
+
a.name === 'slot' &&
|
|
3102
|
+
((_a = a.value[0]) === null || _a === void 0 ? void 0 : _a.data) !== 'default';
|
|
3103
|
+
})) {
|
|
3104
|
+
continue;
|
|
3105
|
+
}
|
|
3106
|
+
}
|
|
3107
|
+
if (child.type === 'Text' && child.data.trim() === '') {
|
|
3108
|
+
continue;
|
|
3109
|
+
}
|
|
3110
|
+
if (child.type !== 'SnippetBlock') {
|
|
3111
|
+
hasSlot = true;
|
|
3112
|
+
break;
|
|
3113
|
+
}
|
|
3114
|
+
}
|
|
3115
|
+
if (!hasSlot) {
|
|
3116
|
+
return;
|
|
3117
|
+
}
|
|
3118
|
+
// it's enough to fake a children prop, we don't need to actually move the content inside (which would also reset control flow)
|
|
3119
|
+
component.addProp(['children'], ['() => { return __sveltets_2_any(0); }']);
|
|
3120
|
+
}
|
|
3054
3121
|
|
|
3055
3122
|
/**
|
|
3056
3123
|
* `{@render foo(x)}` --> `;foo(x);`
|
|
3057
3124
|
*/
|
|
3058
3125
|
function handleRenderTag(str, renderTag) {
|
|
3059
|
-
str.overwrite(renderTag.start, renderTag.expression.start, ';', {
|
|
3126
|
+
str.overwrite(renderTag.start, renderTag.expression.start, ';__sveltets_2_ensureSnippet(', {
|
|
3127
|
+
contentOnly: true
|
|
3128
|
+
});
|
|
3060
3129
|
if (renderTag.argument) {
|
|
3061
|
-
str.overwrite(withTrailingPropertyAccess(str.original, renderTag.argument.end), renderTag.end, ');');
|
|
3130
|
+
str.overwrite(withTrailingPropertyAccess(str.original, renderTag.argument.end), renderTag.end, '));');
|
|
3062
3131
|
}
|
|
3063
3132
|
else {
|
|
3064
|
-
str.overwrite(withTrailingPropertyAccess(str.original, renderTag.expression.end), renderTag.end, '();');
|
|
3133
|
+
str.overwrite(withTrailingPropertyAccess(str.original, renderTag.expression.end), renderTag.end, '());');
|
|
3065
3134
|
}
|
|
3066
3135
|
}
|
|
3067
3136
|
|
|
@@ -3076,11 +3145,12 @@ function stripDoctype(str) {
|
|
|
3076
3145
|
* Walks the HTMLx part of the Svelte component
|
|
3077
3146
|
* and converts it to JSX
|
|
3078
3147
|
*/
|
|
3079
|
-
function convertHtmlxToJsx(str, ast, onWalk = null, onLeave = null, options = {}) {
|
|
3148
|
+
function convertHtmlxToJsx(str, ast, onWalk = null, onLeave = null, options = { svelte5Plus: false }) {
|
|
3080
3149
|
str.original;
|
|
3081
3150
|
options = { preserveAttributeCase: false, ...options };
|
|
3082
3151
|
options.typingsNamespace = options.typingsNamespace || 'svelteHTML';
|
|
3083
3152
|
stripDoctype(str);
|
|
3153
|
+
const rootSnippets = [];
|
|
3084
3154
|
let element;
|
|
3085
3155
|
walk(ast, {
|
|
3086
3156
|
enter: (estreeTypedNode, estreeTypedParent, prop, index) => {
|
|
@@ -3105,6 +3175,10 @@ function convertHtmlxToJsx(str, ast, onWalk = null, onLeave = null, options = {}
|
|
|
3105
3175
|
estreeTypedParent.type === 'InlineComponent'
|
|
3106
3176
|
? element
|
|
3107
3177
|
: undefined);
|
|
3178
|
+
if (!element) {
|
|
3179
|
+
// root snippet -> move to instance script
|
|
3180
|
+
rootSnippets.push([node.start, node.end]);
|
|
3181
|
+
}
|
|
3108
3182
|
break;
|
|
3109
3183
|
case 'MustacheTag':
|
|
3110
3184
|
handleMustacheTag(str, node, parent);
|
|
@@ -3129,6 +3203,9 @@ function convertHtmlxToJsx(str, ast, onWalk = null, onLeave = null, options = {}
|
|
|
3129
3203
|
else {
|
|
3130
3204
|
element = new InlineComponent(str, node);
|
|
3131
3205
|
}
|
|
3206
|
+
if (options.svelte5Plus) {
|
|
3207
|
+
handleImplicitChildren(node, element);
|
|
3208
|
+
}
|
|
3132
3209
|
break;
|
|
3133
3210
|
case 'Element':
|
|
3134
3211
|
case 'Options':
|
|
@@ -3233,6 +3310,7 @@ function convertHtmlxToJsx(str, ast, onWalk = null, onLeave = null, options = {}
|
|
|
3233
3310
|
}
|
|
3234
3311
|
}
|
|
3235
3312
|
});
|
|
3313
|
+
return rootSnippets;
|
|
3236
3314
|
}
|
|
3237
3315
|
|
|
3238
3316
|
/**
|
|
@@ -4235,10 +4313,11 @@ function is$$PropsDeclaration(node) {
|
|
|
4235
4313
|
return isInterfaceOrTypeDeclaration(node) && node.name.text === '$$Props';
|
|
4236
4314
|
}
|
|
4237
4315
|
class ExportedNames {
|
|
4238
|
-
constructor(str, astOffset, basename) {
|
|
4316
|
+
constructor(str, astOffset, basename, isTsFile) {
|
|
4239
4317
|
this.str = str;
|
|
4240
4318
|
this.astOffset = astOffset;
|
|
4241
4319
|
this.basename = basename;
|
|
4320
|
+
this.isTsFile = isTsFile;
|
|
4242
4321
|
/**
|
|
4243
4322
|
* Uses the `$$Props` type
|
|
4244
4323
|
*/
|
|
@@ -4329,16 +4408,89 @@ class ExportedNames {
|
|
|
4329
4408
|
this.$props.generic = node.initializer.typeArguments[0].getText();
|
|
4330
4409
|
}
|
|
4331
4410
|
else {
|
|
4332
|
-
|
|
4333
|
-
|
|
4334
|
-
|
|
4335
|
-
|
|
4336
|
-
|
|
4337
|
-
|
|
4338
|
-
|
|
4411
|
+
if (!this.isTsFile) {
|
|
4412
|
+
const text = node.getSourceFile().getFullText();
|
|
4413
|
+
let comments = (_b = ts
|
|
4414
|
+
.getLeadingCommentRanges(text, node.pos)) === null || _b === void 0 ? void 0 : _b.map((c) => text.substring(c.pos, c.end)).find((c) => c.includes('@type'));
|
|
4415
|
+
if (!comments) {
|
|
4416
|
+
comments = (_c = ts
|
|
4417
|
+
.getLeadingCommentRanges(text, node.parent.pos)) === null || _c === void 0 ? void 0 : _c.map((c) => text.substring(c.pos, c.end)).find((c) => c.includes('@type'));
|
|
4418
|
+
}
|
|
4419
|
+
// We don't bother extracting the type, we just use the comment as-is
|
|
4420
|
+
this.$props.comment = comments || '';
|
|
4421
|
+
}
|
|
4422
|
+
if (this.$props.comment) {
|
|
4423
|
+
return;
|
|
4424
|
+
}
|
|
4425
|
+
if (internalHelpers.isKitRouteFile(this.basename)) {
|
|
4426
|
+
const kitType = this.basename.includes('layout')
|
|
4427
|
+
? `{ data: import('./$types.js').LayoutData, form: import('./$types.js').ActionData, children: import('svelte').Snippet }`
|
|
4428
|
+
: `{ data: import('./$types.js').PageData, form: import('./$types.js').ActionData }`;
|
|
4429
|
+
if (this.isTsFile) {
|
|
4430
|
+
this.$props.generic = kitType;
|
|
4431
|
+
preprendStr(this.str, node.initializer.expression.end + this.astOffset, surroundWithIgnoreComments(`<${kitType}>`));
|
|
4432
|
+
}
|
|
4433
|
+
else {
|
|
4434
|
+
this.$props.comment = `/** @type {${kitType}} */`;
|
|
4435
|
+
preprendStr(this.str, node.pos + this.astOffset, this.$props.comment);
|
|
4436
|
+
}
|
|
4437
|
+
}
|
|
4438
|
+
else {
|
|
4439
|
+
// Do a best-effort to extract the props from the object literal
|
|
4440
|
+
let propsStr = '';
|
|
4441
|
+
let withUnknown = false;
|
|
4442
|
+
let props = [];
|
|
4443
|
+
if (ts.isObjectBindingPattern(node.name)) {
|
|
4444
|
+
for (const element of node.name.elements) {
|
|
4445
|
+
if (!ts.isIdentifier(element.name) || !!element.dotDotDotToken) {
|
|
4446
|
+
withUnknown = true;
|
|
4447
|
+
}
|
|
4448
|
+
else {
|
|
4449
|
+
if (element.initializer) {
|
|
4450
|
+
const type = ts.isAsExpression(element.initializer)
|
|
4451
|
+
? element.initializer.type.getText()
|
|
4452
|
+
: ts.isStringLiteral(element.initializer)
|
|
4453
|
+
? 'string'
|
|
4454
|
+
: ts.isNumericLiteral(element.initializer)
|
|
4455
|
+
? 'number'
|
|
4456
|
+
: element.initializer.kind === ts.SyntaxKind.TrueKeyword ||
|
|
4457
|
+
element.initializer.kind === ts.SyntaxKind.FalseKeyword
|
|
4458
|
+
? 'boolean'
|
|
4459
|
+
: ts.isIdentifier(element.initializer)
|
|
4460
|
+
? `typeof ${element.initializer.text}`
|
|
4461
|
+
: 'unknown';
|
|
4462
|
+
props.push(`${element.name.text}?: ${type}`);
|
|
4463
|
+
}
|
|
4464
|
+
else {
|
|
4465
|
+
props.push(`${element.name.text}: unknown`);
|
|
4466
|
+
}
|
|
4467
|
+
}
|
|
4468
|
+
}
|
|
4469
|
+
}
|
|
4470
|
+
if (props.length > 0) {
|
|
4471
|
+
propsStr =
|
|
4472
|
+
`{ ${props.join(', ')} }` +
|
|
4473
|
+
(withUnknown ? ' & Record<string, unknown>' : '');
|
|
4474
|
+
}
|
|
4475
|
+
else if (withUnknown) {
|
|
4476
|
+
propsStr = 'Record<string, unknown>';
|
|
4477
|
+
}
|
|
4478
|
+
else {
|
|
4479
|
+
propsStr = 'Record<string, never>';
|
|
4480
|
+
}
|
|
4481
|
+
if (this.isTsFile) {
|
|
4482
|
+
this.$props.generic = propsStr;
|
|
4483
|
+
if (props.length > 0 || withUnknown) {
|
|
4484
|
+
preprendStr(this.str, node.initializer.expression.end + this.astOffset, surroundWithIgnoreComments(`<${propsStr}>`));
|
|
4485
|
+
}
|
|
4486
|
+
}
|
|
4487
|
+
else {
|
|
4488
|
+
this.$props.comment = `/** @type {${propsStr}} */`;
|
|
4489
|
+
if (props.length > 0 || withUnknown) {
|
|
4490
|
+
preprendStr(this.str, node.pos + this.astOffset, this.$props.comment);
|
|
4491
|
+
}
|
|
4492
|
+
}
|
|
4339
4493
|
}
|
|
4340
|
-
// We don't bother extracting the type, we just use the comment as-is
|
|
4341
|
-
this.$props.comment = comments || '';
|
|
4342
4494
|
}
|
|
4343
4495
|
}
|
|
4344
4496
|
removeExport(start, end) {
|
|
@@ -4491,6 +4643,14 @@ class ExportedNames {
|
|
|
4491
4643
|
});
|
|
4492
4644
|
}
|
|
4493
4645
|
}
|
|
4646
|
+
addImplicitChildrenExport(hasAttributes) {
|
|
4647
|
+
if (this.exports.has('children'))
|
|
4648
|
+
return;
|
|
4649
|
+
this.exports.set('children', {
|
|
4650
|
+
isLet: true,
|
|
4651
|
+
implicitChildren: hasAttributes ? 'attributes' : 'empty'
|
|
4652
|
+
});
|
|
4653
|
+
}
|
|
4494
4654
|
/**
|
|
4495
4655
|
* Adds export to map
|
|
4496
4656
|
*/
|
|
@@ -4550,7 +4710,7 @@ class ExportedNames {
|
|
|
4550
4710
|
* @param isTsFile Whether this is a TypeScript file or not.
|
|
4551
4711
|
* @param uses$$propsOr$$restProps whether the file references the $$props or $$restProps variable
|
|
4552
4712
|
*/
|
|
4553
|
-
createPropsStr(
|
|
4713
|
+
createPropsStr(uses$$propsOr$$restProps) {
|
|
4554
4714
|
const names = Array.from(this.exports.entries());
|
|
4555
4715
|
if (this.$props.generic) {
|
|
4556
4716
|
const others = names.filter(([, { isLet }]) => !isLet);
|
|
@@ -4586,11 +4746,11 @@ class ExportedNames {
|
|
|
4586
4746
|
}
|
|
4587
4747
|
if (names.length === 0 && !uses$$propsOr$$restProps) {
|
|
4588
4748
|
// Necessary, because {} roughly equals to any
|
|
4589
|
-
return isTsFile
|
|
4749
|
+
return this.isTsFile
|
|
4590
4750
|
? '{} as Record<string, never>'
|
|
4591
4751
|
: '/** @type {Record<string, never>} */ ({})';
|
|
4592
4752
|
}
|
|
4593
|
-
const dontAddTypeDef = !isTsFile || names.every(([_, value]) => !value.type && value.required);
|
|
4753
|
+
const dontAddTypeDef = !this.isTsFile || names.every(([_, value]) => !value.type && value.required);
|
|
4594
4754
|
const returnElements = this.createReturnElements(names, dontAddTypeDef);
|
|
4595
4755
|
if (dontAddTypeDef) {
|
|
4596
4756
|
// Only `typeof` exports -> omit the `as {...}` completely.
|
|
@@ -4602,12 +4762,22 @@ class ExportedNames {
|
|
|
4602
4762
|
}
|
|
4603
4763
|
createReturnElements(names, dontAddTypeDef) {
|
|
4604
4764
|
return names.map(([key, value]) => {
|
|
4765
|
+
if (value.implicitChildren) {
|
|
4766
|
+
return `children?: ${value.implicitChildren === 'empty'
|
|
4767
|
+
? '__sveltets_2_snippet()'
|
|
4768
|
+
: '$$implicit_children'}`;
|
|
4769
|
+
}
|
|
4605
4770
|
// Important to not use shorthand props for rename functionality
|
|
4606
4771
|
return `${dontAddTypeDef && value.doc ? `\n${value.doc}` : ''}${value.identifierText || key}: ${key}`;
|
|
4607
4772
|
});
|
|
4608
4773
|
}
|
|
4609
4774
|
createReturnElementsType(names) {
|
|
4610
4775
|
return names.map(([key, value]) => {
|
|
4776
|
+
if (value.implicitChildren) {
|
|
4777
|
+
return `children?: ${value.implicitChildren === 'empty'
|
|
4778
|
+
? `import('svelte').Snippet`
|
|
4779
|
+
: 'typeof $$implicit_children'}`;
|
|
4780
|
+
}
|
|
4611
4781
|
const identifier = `${value.doc ? `\n${value.doc}` : ''}${value.identifierText || key}${value.required ? '' : '?'}`;
|
|
4612
4782
|
if (!value.type) {
|
|
4613
4783
|
return `${identifier}: typeof ${key}`;
|
|
@@ -4623,6 +4793,9 @@ class ExportedNames {
|
|
|
4623
4793
|
getExportsMap() {
|
|
4624
4794
|
return this.exports;
|
|
4625
4795
|
}
|
|
4796
|
+
uses$propsRune() {
|
|
4797
|
+
return !!this.$props.generic || !!this.$props.comment;
|
|
4798
|
+
}
|
|
4626
4799
|
}
|
|
4627
4800
|
|
|
4628
4801
|
function isMember(parent, prop) {
|
|
@@ -5568,12 +5741,12 @@ class InterfacesAndTypes {
|
|
|
5568
5741
|
}
|
|
5569
5742
|
}
|
|
5570
5743
|
|
|
5571
|
-
function processInstanceScriptContent(str, script, events, implicitStoreValues, mode, hasModuleScript, basename) {
|
|
5744
|
+
function processInstanceScriptContent(str, script, events, implicitStoreValues, mode, hasModuleScript, isTSFile, basename) {
|
|
5572
5745
|
const htmlx = str.original;
|
|
5573
5746
|
const scriptContent = htmlx.substring(script.content.start, script.content.end);
|
|
5574
5747
|
const tsAst = ts.createSourceFile('component.ts.svelte', scriptContent, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS);
|
|
5575
5748
|
const astOffset = script.content.start;
|
|
5576
|
-
const exportedNames = new ExportedNames(str, astOffset, basename);
|
|
5749
|
+
const exportedNames = new ExportedNames(str, astOffset, basename, isTSFile);
|
|
5577
5750
|
const generics = new Generics(str, astOffset, script);
|
|
5578
5751
|
const interfacesAndTypes = new InterfacesAndTypes();
|
|
5579
5752
|
const implicitTopLevelNames = new ImplicitTopLevelNames(str, astOffset);
|
|
@@ -6022,7 +6195,7 @@ function classNameFromFilename(filename, appendSuffix) {
|
|
|
6022
6195
|
}
|
|
6023
6196
|
}
|
|
6024
6197
|
|
|
6025
|
-
function createRenderFunction({ str, scriptTag, scriptDestination, slots, events, exportedNames,
|
|
6198
|
+
function createRenderFunction({ str, scriptTag, scriptDestination, rootSnippets, slots, events, exportedNames, uses$$props, uses$$restProps, uses$$slots, uses$$SlotsInterface, generics, svelte5Plus, mode }) {
|
|
6026
6199
|
const htmlx = str.original;
|
|
6027
6200
|
let propsDecl = '';
|
|
6028
6201
|
if (uses$$props) {
|
|
@@ -6069,6 +6242,9 @@ function createRenderFunction({ str, scriptTag, scriptDestination, slots, events
|
|
|
6069
6242
|
str.overwrite(scriptTag.start + 1, scriptTagEnd, `function render${generics.toDefinitionString(true)}() {${propsDecl}\n`);
|
|
6070
6243
|
}
|
|
6071
6244
|
const scriptEndTagStart = htmlx.lastIndexOf('<', scriptTag.end - 1);
|
|
6245
|
+
for (const rootSnippet of rootSnippets) {
|
|
6246
|
+
str.move(rootSnippet[0], rootSnippet[1], scriptEndTagStart);
|
|
6247
|
+
}
|
|
6072
6248
|
// wrap template with callback
|
|
6073
6249
|
str.overwrite(scriptEndTagStart, scriptTag.end, `${slotsDeclaration};\nasync () => {`, {
|
|
6074
6250
|
contentOnly: true
|
|
@@ -6082,22 +6258,32 @@ function createRenderFunction({ str, scriptTag, scriptDestination, slots, events
|
|
|
6082
6258
|
: '{' +
|
|
6083
6259
|
Array.from(slots.entries())
|
|
6084
6260
|
.map(([name, attrs]) => {
|
|
6085
|
-
|
|
6086
|
-
.map(([exportName, expr]) => exportName.startsWith('__spread__')
|
|
6087
|
-
? `...${expr}`
|
|
6088
|
-
: `${exportName}:${expr}`)
|
|
6089
|
-
.join(', ');
|
|
6090
|
-
return `'${name}': {${attrsAsString}}`;
|
|
6261
|
+
return `'${name}': {${slotAttributesToString(attrs)}}`;
|
|
6091
6262
|
})
|
|
6092
6263
|
.join(', ') +
|
|
6093
6264
|
'}';
|
|
6094
|
-
const
|
|
6265
|
+
const needsImplicitChildrenProp = svelte5Plus &&
|
|
6266
|
+
!exportedNames.uses$propsRune() &&
|
|
6267
|
+
slots.has('default') &&
|
|
6268
|
+
!exportedNames.getExportsMap().has('default');
|
|
6269
|
+
if (needsImplicitChildrenProp) {
|
|
6270
|
+
exportedNames.addImplicitChildrenExport(slots.get('default').size > 0);
|
|
6271
|
+
}
|
|
6272
|
+
const returnString = `${needsImplicitChildrenProp && slots.get('default').size > 0
|
|
6273
|
+
? `\nlet $$implicit_children = __sveltets_2_snippet({${slotAttributesToString(slots.get('default'))}});`
|
|
6274
|
+
: ''}` +
|
|
6275
|
+
`\nreturn { props: ${exportedNames.createPropsStr(uses$$props || uses$$restProps)}` +
|
|
6095
6276
|
`, slots: ${slotsAsDef}` +
|
|
6096
6277
|
`, events: ${events.toDefString()} }}`;
|
|
6097
6278
|
// wrap template with callback
|
|
6098
6279
|
str.append('};');
|
|
6099
6280
|
str.append(returnString);
|
|
6100
6281
|
}
|
|
6282
|
+
function slotAttributesToString(attrs) {
|
|
6283
|
+
return Array.from(attrs.entries())
|
|
6284
|
+
.map(([exportName, expr]) => exportName.startsWith('__spread__') ? `...${expr}` : `${exportName}:${expr}`)
|
|
6285
|
+
.join(', ');
|
|
6286
|
+
}
|
|
6101
6287
|
|
|
6102
6288
|
function processSvelteTemplate(str, parse, options) {
|
|
6103
6289
|
const { htmlxAst, tags } = parseHtmlx(str.original, parse, options);
|
|
@@ -6283,9 +6469,10 @@ function processSvelteTemplate(str, parse, options) {
|
|
|
6283
6469
|
break;
|
|
6284
6470
|
}
|
|
6285
6471
|
};
|
|
6286
|
-
convertHtmlxToJsx(str, htmlxAst, onHtmlxWalk, onHtmlxLeave, {
|
|
6472
|
+
const rootSnippets = convertHtmlxToJsx(str, htmlxAst, onHtmlxWalk, onHtmlxLeave, {
|
|
6287
6473
|
preserveAttributeCase: (options === null || options === void 0 ? void 0 : options.namespace) == 'foreign',
|
|
6288
|
-
typingsNamespace: options.typingsNamespace
|
|
6474
|
+
typingsNamespace: options.typingsNamespace,
|
|
6475
|
+
svelte5Plus: options.svelte5Plus
|
|
6289
6476
|
});
|
|
6290
6477
|
// resolve scripts
|
|
6291
6478
|
const { scriptTag, moduleScriptTag } = scripts.getTopLevelScriptTags();
|
|
@@ -6298,6 +6485,7 @@ function processSvelteTemplate(str, parse, options) {
|
|
|
6298
6485
|
htmlAst: htmlxAst,
|
|
6299
6486
|
moduleScriptTag,
|
|
6300
6487
|
scriptTag,
|
|
6488
|
+
rootSnippets,
|
|
6301
6489
|
slots: slotHandler.getSlotDef(),
|
|
6302
6490
|
events: new ComponentEvents(eventHandler, tags.some((tag) => { var _a; return (_a = tag.attributes) === null || _a === void 0 ? void 0 : _a.some((a) => a.name === 'strictEvents'); }), str),
|
|
6303
6491
|
uses$$props,
|
|
@@ -6310,10 +6498,15 @@ function processSvelteTemplate(str, parse, options) {
|
|
|
6310
6498
|
}
|
|
6311
6499
|
function svelte2tsx(svelte, options = { parse }) {
|
|
6312
6500
|
options.mode = options.mode || 'ts';
|
|
6501
|
+
options.version = options.version || VERSION;
|
|
6313
6502
|
const str = new MagicString(svelte);
|
|
6314
6503
|
const basename = path__default.basename(options.filename || '');
|
|
6504
|
+
const svelte5Plus = Number(options.version[0]) > 4;
|
|
6315
6505
|
// process the htmlx as a svelte template
|
|
6316
|
-
let { htmlAst, moduleScriptTag, scriptTag, slots, uses$$props, uses$$slots, uses$$restProps, events, componentDocumentation, resolvedStores, usesAccessors } = processSvelteTemplate(str, options.parse || parse,
|
|
6506
|
+
let { htmlAst, moduleScriptTag, scriptTag, rootSnippets, slots, uses$$props, uses$$slots, uses$$restProps, events, componentDocumentation, resolvedStores, usesAccessors } = processSvelteTemplate(str, options.parse || parse, {
|
|
6507
|
+
...options,
|
|
6508
|
+
svelte5Plus
|
|
6509
|
+
});
|
|
6317
6510
|
/* Rearrange the script tags so that module is first, and instance second followed finally by the template
|
|
6318
6511
|
* This is a bit convoluted due to some trouble I had with magic string. A simple str.move(start,end,0) for each script wasn't enough
|
|
6319
6512
|
* since if the module script was already at 0, it wouldn't move (which is fine) but would mean the order would be swapped when the script tag tried to move to 0
|
|
@@ -6335,7 +6528,7 @@ function svelte2tsx(svelte, options = { parse }) {
|
|
|
6335
6528
|
: instanceScriptTarget;
|
|
6336
6529
|
const implicitStoreValues = new ImplicitStoreValues(resolvedStores, renderFunctionStart);
|
|
6337
6530
|
//move the instance script and process the content
|
|
6338
|
-
let exportedNames = new ExportedNames(str, 0, basename);
|
|
6531
|
+
let exportedNames = new ExportedNames(str, 0, basename, options === null || options === void 0 ? void 0 : options.isTsFile);
|
|
6339
6532
|
let generics = new Generics(str, 0, { attributes: [] });
|
|
6340
6533
|
let uses$$SlotsInterface = false;
|
|
6341
6534
|
if (scriptTag) {
|
|
@@ -6344,7 +6537,7 @@ function svelte2tsx(svelte, options = { parse }) {
|
|
|
6344
6537
|
str.move(scriptTag.start, scriptTag.end, instanceScriptTarget);
|
|
6345
6538
|
}
|
|
6346
6539
|
const res = processInstanceScriptContent(str, scriptTag, events, implicitStoreValues, options.mode,
|
|
6347
|
-
/**hasModuleScripts */ !!moduleScriptTag, basename);
|
|
6540
|
+
/**hasModuleScripts */ !!moduleScriptTag, options === null || options === void 0 ? void 0 : options.isTsFile, basename);
|
|
6348
6541
|
uses$$props = uses$$props || res.uses$$props;
|
|
6349
6542
|
uses$$restProps = uses$$restProps || res.uses$$restProps;
|
|
6350
6543
|
uses$$slots = uses$$slots || res.uses$$slots;
|
|
@@ -6355,15 +6548,16 @@ function svelte2tsx(svelte, options = { parse }) {
|
|
|
6355
6548
|
str,
|
|
6356
6549
|
scriptTag,
|
|
6357
6550
|
scriptDestination: instanceScriptTarget,
|
|
6551
|
+
rootSnippets,
|
|
6358
6552
|
slots,
|
|
6359
6553
|
events,
|
|
6360
6554
|
exportedNames,
|
|
6361
|
-
isTsFile: options === null || options === void 0 ? void 0 : options.isTsFile,
|
|
6362
6555
|
uses$$props,
|
|
6363
6556
|
uses$$restProps,
|
|
6364
6557
|
uses$$slots,
|
|
6365
6558
|
uses$$SlotsInterface,
|
|
6366
6559
|
generics,
|
|
6560
|
+
svelte5Plus,
|
|
6367
6561
|
mode: options.mode
|
|
6368
6562
|
});
|
|
6369
6563
|
// we need to process the module script after the instance script has moved otherwise we get warnings about moving edited items
|
|
@@ -6470,13 +6664,13 @@ function loadTsconfig(config, svelteMap) {
|
|
|
6470
6664
|
return {
|
|
6471
6665
|
options: {
|
|
6472
6666
|
...options,
|
|
6473
|
-
noEmit: false,
|
|
6667
|
+
noEmit: false, // Set to true in case of jsconfig, force false, else nothing is emitted
|
|
6474
6668
|
moduleResolution:
|
|
6475
6669
|
// NodeJS: up to 4.9, Node10: since 5.0
|
|
6476
|
-
(_a = ts.ModuleResolutionKind.NodeJs) !== null && _a !== void 0 ? _a : ts.ModuleResolutionKind.Node10,
|
|
6477
|
-
declaration: true,
|
|
6478
|
-
emitDeclarationOnly: true,
|
|
6479
|
-
declarationDir: config.declarationDir,
|
|
6670
|
+
(_a = ts.ModuleResolutionKind.NodeJs) !== null && _a !== void 0 ? _a : ts.ModuleResolutionKind.Node10, // Classic if not set, which gives wrong results
|
|
6671
|
+
declaration: true, // Needed for d.ts file generation
|
|
6672
|
+
emitDeclarationOnly: true, // We only want d.ts file generation
|
|
6673
|
+
declarationDir: config.declarationDir, // Where to put the declarations
|
|
6480
6674
|
allowNonTsExtensions: true
|
|
6481
6675
|
},
|
|
6482
6676
|
filenames
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "svelte2tsx",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.27",
|
|
4
4
|
"description": "Convert Svelte components to TSX for type checking",
|
|
5
5
|
"author": "David Pershouse",
|
|
6
6
|
"license": "MIT",
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"svelte": "~3.57.0",
|
|
41
41
|
"tiny-glob": "^0.2.6",
|
|
42
42
|
"tslib": "^2.4.0",
|
|
43
|
-
"typescript": "^5.
|
|
43
|
+
"typescript": "^5.3.2"
|
|
44
44
|
},
|
|
45
45
|
"peerDependencies": {
|
|
46
46
|
"svelte": "^3.55 || ^4.0.0-next.0 || ^4.0 || ^5.0.0-next.0",
|
package/svelte-shims-v4.d.ts
CHANGED
|
@@ -145,6 +145,11 @@ declare function __sveltets_2_nonNullable<T>(type: T): NonNullable<T>;
|
|
|
145
145
|
|
|
146
146
|
declare function __sveltets_2_cssProp(prop: Record<string, any>): {};
|
|
147
147
|
|
|
148
|
+
// @ts-ignore Svelte v3/v4 don't have this
|
|
149
|
+
declare function __sveltets_2_ensureSnippet(val: ReturnType<import('svelte').Snippet>): any;
|
|
150
|
+
// @ts-ignore Svelte v3/v4 don't have this
|
|
151
|
+
declare function __sveltets_2_snippet<T = void>(t: T): import('svelte').Snippet<T>;
|
|
152
|
+
|
|
148
153
|
/** @internal PRIVATE API, DO NOT USE */
|
|
149
154
|
type __sveltets_2_SvelteAnimationReturnType = {
|
|
150
155
|
delay?: number,
|