Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(feat) support const tag in if block in the old transformation #1478

Merged
merged 4 commits into from May 13, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
@@ -0,0 +1,46 @@
[
{
"range": {
"start": { "line": 21, "character": 19 },
"end": { "line": 21, "character": 26 }
},
"severity": 1,
"source": "ts",
"message": "Property 'toFixed' does not exist on type 'string'. Did you mean 'fixed'?",
"code": 2551,
"tags": []
},
{
"range": {
"start": { "line": 21, "character": 40 },
"end": { "line": 21, "character": 47 }
},
"severity": 1,
"source": "ts",
"message": "Property 'toFixed' does not exist on type 'string'. Did you mean 'fixed'?",
"code": 2551,
"tags": []
},
{
"range": {
"start": { "line": 23, "character": 11 },
"end": { "line": 23, "character": 20 }
},
"severity": 1,
"source": "ts",
"message": "Property 'substring' does not exist on type 'number'.",
"code": 2339,
"tags": []
},
{
"range": {
"start": { "line": 25, "character": 11 },
"end": { "line": 25, "character": 18 }
},
"severity": 1,
"source": "ts",
"message": "Property 'toFixed' does not exist on type 'boolean'.",
"code": 2339,
"tags": []
}
]
@@ -0,0 +1,46 @@
[
{
"range": {
"start": { "line": 21, "character": 19 },
"end": { "line": 21, "character": 26 }
},
"severity": 1,
"source": "ts",
"message": "Property 'toFixed' does not exist on type 'string'. Did you mean 'fixed'?",
"code": 2551,
"tags": []
},
{
"range": {
"start": { "line": 21, "character": 40 },
"end": { "line": 21, "character": 47 }
},
"severity": 1,
"source": "ts",
"message": "Property 'toFixed' does not exist on type 'string'. Did you mean 'fixed'?",
"code": 2551,
"tags": []
},
{
"range": {
"start": { "line": 23, "character": 11 },
"end": { "line": 23, "character": 20 }
},
"severity": 1,
"source": "ts",
"message": "Property 'substring' does not exist on type 'number'.",
"code": 2339,
"tags": []
},
{
"range": {
"start": { "line": 25, "character": 11 },
"end": { "line": 25, "character": 18 }
},
"severity": 1,
"source": "ts",
"message": "Property 'toFixed' does not exist on type 'boolean'.",
"code": 2339,
"tags": []
}
]
@@ -0,0 +1,27 @@
<script lang="ts">
let value: string | number | boolean;
</script>

<!-- valid -->
{#if typeof value === 'string'}
{@const valueStr = value}
{@const valueStr2 = valueStr}

<div>{valueStr.substring(0)}{valueStr2.substring(0)}</div>

<button on:click={() => {valueStr.substring(0)}}></button>
{:else if typeof value === 'number'}
{value.toFixed()}
{/if}

<!-- invalid -->
{#if typeof value === 'string'}
{@const valueStr = value}
{@const valueStr2 = valueStr}

<div>{valueStr.toFixed()}{valueStr2.toFixed()}</div>
{:else if typeof value === 'number'}
{value.substring(0)}
{:else}
{value.toFixed()}
{/if}
73 changes: 63 additions & 10 deletions packages/svelte2tsx/src/htmlxtojsx/nodes/if-else.ts
Expand Up @@ -2,6 +2,7 @@ import MagicString from 'magic-string';
import { IfScope } from './if-scope';
import { BaseNode } from '../../interfaces';
import { withTrailingPropertyAccess } from '../utils/node-utils';
import { extractConstTags } from './const-tag';

/**
* {# if ...}...{/if} ---> {() => {if(...){<>...</>}}}
Expand All @@ -13,33 +14,58 @@ export function handleIf(
ifScope: IfScope
): void {
const endIf = htmlx.lastIndexOf('{', ifBlock.end - 1);
const constTags = extractConstTags(ifBlock.children);
const ifConditionEnd = htmlx.indexOf('}', ifBlock.expression.end) + 1;
const hasConstTags = !!constTags.length;
const endIIFE = createEndIIFE(hasConstTags);
const startIIFE = createStartIIFE(hasConstTags);

if (hasConstTags) {
// {@const hi = exp} <div>{hi}> -> {(() => { const hi = exp; return <> <div>{hi}<div></> })}

constTags.forEach((constTag) => {
constTag(ifConditionEnd, str);
});

str.appendRight(ifConditionEnd, 'return <>');

if (ifBlock.else) {
// {:else} -> </>})()}</> : <>
const elseWord = htmlx.lastIndexOf(':else', ifBlock.else.start);
const elseStart = htmlx.lastIndexOf('{', elseWord);
str.appendLeft(elseStart, endIIFE);
}
}

if (ifBlock.elseif) {
// {:else if expr} -> : (expr) ? <>
// {:else if expr}{@const ...} -> : (expr) ? <>{(() => {const ...; return <>
const elseIfStart = htmlx.lastIndexOf('{', ifBlock.expression.start);
const elseIfConditionEnd = htmlx.indexOf('}', ifBlock.expression.end) + 1;
str.overwrite(elseIfStart, ifBlock.expression.start, '</> : (', { contentOnly: true });
str.overwrite(elseIfStart, ifBlock.expression.start, '</> : (', {
contentOnly: true
});
str.overwrite(
withTrailingPropertyAccess(str.original, ifBlock.expression.end),
elseIfConditionEnd,
') ? <>'
ifConditionEnd,
') ? <>' + startIIFE
);

ifScope.addElseIf(ifBlock.expression, str);

if (!ifBlock.else) {
str.appendLeft(endIf, '</> : <>');
str.appendLeft(endIf, endIIFE + '</> : <>');
}
return;
}

// {#if expr} -> {(expr) ? <>
// {#if expr}{@const ...} -> {(expr) ? <>{(() => {const ...; return <>
str.overwrite(ifBlock.start, ifBlock.expression.start, '{(', { contentOnly: true });
const end = htmlx.indexOf('}', ifBlock.expression.end);

str.overwrite(
withTrailingPropertyAccess(str.original, ifBlock.expression.end),
end + 1,
') ? <>',
ifConditionEnd,
') ? <>' + startIIFE,
{ contentOnly: true }
);

Expand All @@ -50,12 +76,24 @@ export function handleIf(
str.overwrite(endIf, ifBlock.end, '</> }', { contentOnly: true });
} else {
// {/if} -> </> : <></>}
str.overwrite(endIf, ifBlock.end, '</> : <></>}', { contentOnly: true });
// {@const ...} -> </>})()}</> : <></>}
str.overwrite(endIf, ifBlock.end, endIIFE + '</> : <></>}', {
contentOnly: true
});
}
}

function createStartIIFE(hasConstTags: boolean) {
return hasConstTags ? '{(() => {' : '';
}

function createEndIIFE(hasConstTags: boolean) {
return hasConstTags ? '</>})()}' : '';
}

/**
* {:else} ---> </> : <>
* {:else} {@const ...} -> </> : <>{(() => { const ...; return<>
*/
export function handleElse(
htmlx: string,
Expand All @@ -70,10 +108,25 @@ export function handleElse(
) {
return;
}

const elseEnd = htmlx.lastIndexOf('}', elseBlock.start);
const elseword = htmlx.lastIndexOf(':else', elseEnd);
const elseStart = htmlx.lastIndexOf('{', elseword);
str.overwrite(elseStart, elseEnd + 1, '</> : <>');
const constTags = extractConstTags(elseBlock.children);
const hasConstTags = !!constTags.length;

str.overwrite(elseStart, elseEnd + 1, '</> : <>' + createStartIIFE(hasConstTags));

ifScope.addElse();

if (!hasConstTags) {
return;
}

constTags.forEach((constTag) => {
constTag(elseEnd + 1, str);
});

str.appendRight(elseEnd + 1, 'return <>');
str.appendLeft(elseBlock.end, createEndIIFE(true));
}
@@ -1,10 +1,28 @@
<>{(name == "world") ? <>
{@const hello = name}
<>{(name == "world") ? <>{(() => {const hello = name;return <>
{ }
<h1>Hello {hello}</h1>
</> : (true) ? <>
{@const hello = name}
</>})()}</> : (true) ? <>{(() => {const hello = name;return <>
{ }
<h1>Hello {hello}</h1>
</> : <>
{@const hello = name}
</>})()}</> : <>{(() => {const hello = name;return <>
{ }
<h1>Hello {hello}</h1>
</> }</>
</>})()}</> }

{(typeof a === 'string') ? <>{(() => {const aStr = a;const aStr2 = aStr;return <>
{ }
{ }

{a}
</>})()}</> : (typeof a === 'number') ? <>{(() => {const aNum = a;return <>
{ }
</>})()}</> : <></> }

{(typeof a === 'string') ? <>{(() => {const aStr = a;return <>
{ }
</>})()}</> : <></>}

{(typeof a === 'string') ? <>{(() => {const aStr = a;return <>
{ }
</>})()}</> : <>
</> }</>
Expand Up @@ -7,4 +7,22 @@ if(name == "world"){
}else{
const hello = name;
{ svelteHTML.createElement("h1", {}); hello; }
}
}

if(typeof a === 'string'){
const aStr = a;
const aStr2 = aStr;

a;
} else if (typeof a === 'number'){
const aNum = a;
}

if(typeof a === 'string'){
const aStr = a;
}

if(typeof a === 'string'){
const aStr = a;
}else{
}
Expand Up @@ -8,3 +8,21 @@
{@const hello = name}
<h1>Hello {hello}</h1>
{/if}

{#if typeof a === 'string'}
{@const aStr = a}
{@const aStr2 = aStr}

{a}
{:else if typeof a === 'number'}
{@const aNum = a}
{/if}

{#if typeof a === 'string'}
{@const aStr = a}
{/if}

{#if typeof a === 'string'}
{@const aStr = a}
{:else}
{/if}