Skip to content

Commit db20058

Browse files
authored
(feat) support const tag in if block in the old transformation (#1478)
#1470
1 parent f11c429 commit db20058

File tree

7 files changed

+244
-18
lines changed

7 files changed

+244
-18
lines changed
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
[
2+
{
3+
"range": {
4+
"start": { "line": 21, "character": 19 },
5+
"end": { "line": 21, "character": 26 }
6+
},
7+
"severity": 1,
8+
"source": "ts",
9+
"message": "Property 'toFixed' does not exist on type 'string'. Did you mean 'fixed'?",
10+
"code": 2551,
11+
"tags": []
12+
},
13+
{
14+
"range": {
15+
"start": { "line": 21, "character": 40 },
16+
"end": { "line": 21, "character": 47 }
17+
},
18+
"severity": 1,
19+
"source": "ts",
20+
"message": "Property 'toFixed' does not exist on type 'string'. Did you mean 'fixed'?",
21+
"code": 2551,
22+
"tags": []
23+
},
24+
{
25+
"range": {
26+
"start": { "line": 23, "character": 11 },
27+
"end": { "line": 23, "character": 20 }
28+
},
29+
"severity": 1,
30+
"source": "ts",
31+
"message": "Property 'substring' does not exist on type 'number'.",
32+
"code": 2339,
33+
"tags": []
34+
},
35+
{
36+
"range": {
37+
"start": { "line": 25, "character": 11 },
38+
"end": { "line": 25, "character": 18 }
39+
},
40+
"severity": 1,
41+
"source": "ts",
42+
"message": "Property 'toFixed' does not exist on type 'boolean'.",
43+
"code": 2339,
44+
"tags": []
45+
}
46+
]
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
[
2+
{
3+
"range": {
4+
"start": { "line": 21, "character": 19 },
5+
"end": { "line": 21, "character": 26 }
6+
},
7+
"severity": 1,
8+
"source": "ts",
9+
"message": "Property 'toFixed' does not exist on type 'string'. Did you mean 'fixed'?",
10+
"code": 2551,
11+
"tags": []
12+
},
13+
{
14+
"range": {
15+
"start": { "line": 21, "character": 40 },
16+
"end": { "line": 21, "character": 47 }
17+
},
18+
"severity": 1,
19+
"source": "ts",
20+
"message": "Property 'toFixed' does not exist on type 'string'. Did you mean 'fixed'?",
21+
"code": 2551,
22+
"tags": []
23+
},
24+
{
25+
"range": {
26+
"start": { "line": 23, "character": 11 },
27+
"end": { "line": 23, "character": 20 }
28+
},
29+
"severity": 1,
30+
"source": "ts",
31+
"message": "Property 'substring' does not exist on type 'number'.",
32+
"code": 2339,
33+
"tags": []
34+
},
35+
{
36+
"range": {
37+
"start": { "line": 25, "character": 11 },
38+
"end": { "line": 25, "character": 18 }
39+
},
40+
"severity": 1,
41+
"source": "ts",
42+
"message": "Property 'toFixed' does not exist on type 'boolean'.",
43+
"code": 2339,
44+
"tags": []
45+
}
46+
]
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<script lang="ts">
2+
let value: string | number | boolean;
3+
</script>
4+
5+
<!-- valid -->
6+
{#if typeof value === 'string'}
7+
{@const valueStr = value}
8+
{@const valueStr2 = valueStr}
9+
10+
<div>{valueStr.substring(0)}{valueStr2.substring(0)}</div>
11+
12+
<button on:click={() => {valueStr.substring(0)}}></button>
13+
{:else if typeof value === 'number'}
14+
{value.toFixed()}
15+
{/if}
16+
17+
<!-- invalid -->
18+
{#if typeof value === 'string'}
19+
{@const valueStr = value}
20+
{@const valueStr2 = valueStr}
21+
22+
<div>{valueStr.toFixed()}{valueStr2.toFixed()}</div>
23+
{:else if typeof value === 'number'}
24+
{value.substring(0)}
25+
{:else}
26+
{value.toFixed()}
27+
{/if}

packages/svelte2tsx/src/htmlxtojsx/nodes/if-else.ts

Lines changed: 63 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import MagicString from 'magic-string';
22
import { IfScope } from './if-scope';
33
import { BaseNode } from '../../interfaces';
44
import { withTrailingPropertyAccess } from '../utils/node-utils';
5+
import { extractConstTags } from './const-tag';
56

67
/**
78
* {# if ...}...{/if} ---> {() => {if(...){<>...</>}}}
@@ -13,33 +14,58 @@ export function handleIf(
1314
ifScope: IfScope
1415
): void {
1516
const endIf = htmlx.lastIndexOf('{', ifBlock.end - 1);
17+
const constTags = extractConstTags(ifBlock.children);
18+
const ifConditionEnd = htmlx.indexOf('}', ifBlock.expression.end) + 1;
19+
const hasConstTags = !!constTags.length;
20+
const endIIFE = createEndIIFE(hasConstTags);
21+
const startIIFE = createStartIIFE(hasConstTags);
22+
23+
if (hasConstTags) {
24+
// {@const hi = exp} <div>{hi}> -> {(() => { const hi = exp; return <> <div>{hi}<div></> })}
25+
26+
constTags.forEach((constTag) => {
27+
constTag(ifConditionEnd, str);
28+
});
29+
30+
str.appendRight(ifConditionEnd, 'return <>');
31+
32+
if (ifBlock.else) {
33+
// {:else} -> </>})()}</> : <>
34+
const elseWord = htmlx.lastIndexOf(':else', ifBlock.else.start);
35+
const elseStart = htmlx.lastIndexOf('{', elseWord);
36+
str.appendLeft(elseStart, endIIFE);
37+
}
38+
}
1639

1740
if (ifBlock.elseif) {
1841
// {:else if expr} -> : (expr) ? <>
42+
// {:else if expr}{@const ...} -> : (expr) ? <>{(() => {const ...; return <>
1943
const elseIfStart = htmlx.lastIndexOf('{', ifBlock.expression.start);
20-
const elseIfConditionEnd = htmlx.indexOf('}', ifBlock.expression.end) + 1;
21-
str.overwrite(elseIfStart, ifBlock.expression.start, '</> : (', { contentOnly: true });
44+
str.overwrite(elseIfStart, ifBlock.expression.start, '</> : (', {
45+
contentOnly: true
46+
});
2247
str.overwrite(
2348
withTrailingPropertyAccess(str.original, ifBlock.expression.end),
24-
elseIfConditionEnd,
25-
') ? <>'
49+
ifConditionEnd,
50+
') ? <>' + startIIFE
2651
);
2752

2853
ifScope.addElseIf(ifBlock.expression, str);
2954

3055
if (!ifBlock.else) {
31-
str.appendLeft(endIf, '</> : <>');
56+
str.appendLeft(endIf, endIIFE + '</> : <>');
3257
}
3358
return;
3459
}
3560

3661
// {#if expr} -> {(expr) ? <>
62+
// {#if expr}{@const ...} -> {(expr) ? <>{(() => {const ...; return <>
3763
str.overwrite(ifBlock.start, ifBlock.expression.start, '{(', { contentOnly: true });
38-
const end = htmlx.indexOf('}', ifBlock.expression.end);
64+
3965
str.overwrite(
4066
withTrailingPropertyAccess(str.original, ifBlock.expression.end),
41-
end + 1,
42-
') ? <>',
67+
ifConditionEnd,
68+
') ? <>' + startIIFE,
4369
{ contentOnly: true }
4470
);
4571

@@ -50,12 +76,24 @@ export function handleIf(
5076
str.overwrite(endIf, ifBlock.end, '</> }', { contentOnly: true });
5177
} else {
5278
// {/if} -> </> : <></>}
53-
str.overwrite(endIf, ifBlock.end, '</> : <></>}', { contentOnly: true });
79+
// {@const ...} -> </>})()}</> : <></>}
80+
str.overwrite(endIf, ifBlock.end, endIIFE + '</> : <></>}', {
81+
contentOnly: true
82+
});
5483
}
5584
}
5685

86+
function createStartIIFE(hasConstTags: boolean) {
87+
return hasConstTags ? '{(() => {' : '';
88+
}
89+
90+
function createEndIIFE(hasConstTags: boolean) {
91+
return hasConstTags ? '</>})()}' : '';
92+
}
93+
5794
/**
5895
* {:else} ---> </> : <>
96+
* {:else} {@const ...} -> </> : <>{(() => { const ...; return<>
5997
*/
6098
export function handleElse(
6199
htmlx: string,
@@ -70,10 +108,25 @@ export function handleElse(
70108
) {
71109
return;
72110
}
111+
73112
const elseEnd = htmlx.lastIndexOf('}', elseBlock.start);
74113
const elseword = htmlx.lastIndexOf(':else', elseEnd);
75114
const elseStart = htmlx.lastIndexOf('{', elseword);
76-
str.overwrite(elseStart, elseEnd + 1, '</> : <>');
115+
const constTags = extractConstTags(elseBlock.children);
116+
const hasConstTags = !!constTags.length;
117+
118+
str.overwrite(elseStart, elseEnd + 1, '</> : <>' + createStartIIFE(hasConstTags));
77119

78120
ifScope.addElse();
121+
122+
if (!hasConstTags) {
123+
return;
124+
}
125+
126+
constTags.forEach((constTag) => {
127+
constTag(elseEnd + 1, str);
128+
});
129+
130+
str.appendRight(elseEnd + 1, 'return <>');
131+
str.appendLeft(elseBlock.end, createEndIIFE(true));
79132
}
Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,28 @@
1-
<>{(name == "world") ? <>
2-
{@const hello = name}
1+
<>{(name == "world") ? <>{(() => {const hello = name;return <>
2+
{ }
33
<h1>Hello {hello}</h1>
4-
</> : (true) ? <>
5-
{@const hello = name}
4+
</>})()}</> : (true) ? <>{(() => {const hello = name;return <>
5+
{ }
66
<h1>Hello {hello}</h1>
7-
</> : <>
8-
{@const hello = name}
7+
</>})()}</> : <>{(() => {const hello = name;return <>
8+
{ }
99
<h1>Hello {hello}</h1>
10-
</> }</>
10+
</>})()}</> }
11+
12+
{(typeof a === 'string') ? <>{(() => {const aStr = a;const aStr2 = aStr;return <>
13+
{ }
14+
{ }
15+
16+
{a}
17+
</>})()}</> : (typeof a === 'number') ? <>{(() => {const aNum = a;return <>
18+
{ }
19+
</>})()}</> : <></> }
20+
21+
{(typeof a === 'string') ? <>{(() => {const aStr = a;return <>
22+
{ }
23+
</>})()}</> : <></>}
24+
25+
{(typeof a === 'string') ? <>{(() => {const aStr = a;return <>
26+
{ }
27+
</>})()}</> : <>
28+
</> }</>

packages/svelte2tsx/test/htmlx2jsx/samples/if-block-const/expectedv2.js

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,22 @@ if(name == "world"){
77
}else{
88
const hello = name;
99
{ svelteHTML.createElement("h1", {}); hello; }
10-
}
10+
}
11+
12+
if(typeof a === 'string'){
13+
const aStr = a;
14+
const aStr2 = aStr;
15+
16+
a;
17+
} else if (typeof a === 'number'){
18+
const aNum = a;
19+
}
20+
21+
if(typeof a === 'string'){
22+
const aStr = a;
23+
}
24+
25+
if(typeof a === 'string'){
26+
const aStr = a;
27+
}else{
28+
}

packages/svelte2tsx/test/htmlx2jsx/samples/if-block-const/input.svelte

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,21 @@
88
{@const hello = name}
99
<h1>Hello {hello}</h1>
1010
{/if}
11+
12+
{#if typeof a === 'string'}
13+
{@const aStr = a}
14+
{@const aStr2 = aStr}
15+
16+
{a}
17+
{:else if typeof a === 'number'}
18+
{@const aNum = a}
19+
{/if}
20+
21+
{#if typeof a === 'string'}
22+
{@const aStr = a}
23+
{/if}
24+
25+
{#if typeof a === 'string'}
26+
{@const aStr = a}
27+
{:else}
28+
{/if}

0 commit comments

Comments
 (0)