From 1c069a94576f68e8ddd46b6e67270fd3e05d40d9 Mon Sep 17 00:00:00 2001 From: Tan Li Hau Date: Thu, 20 Aug 2020 22:09:12 +0800 Subject: [PATCH 1/3] support $$slots --- packages/svelte2tsx/src/interfaces.ts | 1 + packages/svelte2tsx/src/svelte2tsx.ts | 27 +++++++++++++++++++++++++++ packages/svelte2tsx/svelte-shims.d.ts | 2 ++ 3 files changed, 30 insertions(+) diff --git a/packages/svelte2tsx/src/interfaces.ts b/packages/svelte2tsx/src/interfaces.ts index 742e323d2..d4a9d520d 100644 --- a/packages/svelte2tsx/src/interfaces.ts +++ b/packages/svelte2tsx/src/interfaces.ts @@ -8,6 +8,7 @@ export interface InstanceScriptProcessResult { events: ComponentEvents; uses$$props: boolean; uses$$restProps: boolean; + uses$$slots: boolean; getters: Set; } diff --git a/packages/svelte2tsx/src/svelte2tsx.ts b/packages/svelte2tsx/src/svelte2tsx.ts index 26ba91c8e..50b700c39 100644 --- a/packages/svelte2tsx/src/svelte2tsx.ts +++ b/packages/svelte2tsx/src/svelte2tsx.ts @@ -51,6 +51,7 @@ function AttributeValueAsJsExpression(htmlx: string, attr: Node): string { type TemplateProcessResult = { uses$$props: boolean; uses$$restProps: boolean; + uses$$slots: boolean; slots: Map>; scriptTag: Node; moduleScriptTag: Node; @@ -91,6 +92,7 @@ function processSvelteTemplate(str: MagicString): TemplateProcessResult { let uses$$props = false; let uses$$restProps = false; + let uses$$slots = false; let componentDocumentation = null; @@ -224,6 +226,11 @@ function processSvelteTemplate(str: MagicString): TemplateProcessResult { return; } + if (node.name === '$$slots') { + uses$$slots = true; + return; + } + //handle potential store if (node.name[0] == '$') { if (isDeclaration) { @@ -383,6 +390,7 @@ function processSvelteTemplate(str: MagicString): TemplateProcessResult { events: new ComponentEventsFromEventsMap(eventHandler), uses$$props, uses$$restProps, + uses$$slots, componentDocumentation, }; } @@ -408,6 +416,7 @@ function processInstanceScriptContent( const implicitTopLevelNames = new ImplicitTopLevelNames(); let uses$$props = false; let uses$$restProps = false; + let uses$$slots = false; //track if we are in a declaration scope let isDeclaration = false; @@ -607,6 +616,10 @@ function processInstanceScriptContent( uses$$restProps = true; return; } + if (ident.text === '$$slots') { + uses$$slots = true; + return; + } if (ts.isLabeledStatement(parent) && parent.label == ident) { return; @@ -821,6 +834,7 @@ function processInstanceScriptContent( events, uses$$props, uses$$restProps, + uses$$slots, getters, }; } @@ -910,6 +924,7 @@ function createRenderFunction({ isTsFile, uses$$props, uses$$restProps, + uses$$slots, }: CreateRenderFunctionPara) { const htmlx = str.original; let propsDecl = ''; @@ -921,6 +936,15 @@ function createRenderFunction({ propsDecl += ' let $$restProps = __sveltets_restPropsType();'; } + if (uses$$slots) { + propsDecl += + 'let $$slots: { ' + + Array.from(slots.keys()) + .map((name) => `${name}: any`) + .join(', ') + + ' = __sveltets_slotsType();'; + } + if (scriptTag) { //I couldn't get magicstring to let me put the script before the <> we prepend during conversion of the template to jsx, so we just close it instead const scriptTagEnd = htmlx.lastIndexOf('>', scriptTag.content.start) + 1; @@ -973,6 +997,7 @@ export function svelte2tsx( scriptTag, slots, uses$$props, + uses$$slots, uses$$restProps, events, componentDocumentation, @@ -1006,6 +1031,7 @@ export function svelte2tsx( const res = processInstanceScriptContent(str, scriptTag, events); uses$$props = uses$$props || res.uses$$props; uses$$restProps = uses$$restProps || res.uses$$restProps; + uses$$slots = uses$$slots || res.uses$$slots; ({ exportedNames, events, getters } = res); } @@ -1022,6 +1048,7 @@ export function svelte2tsx( isTsFile: options?.isTsFile, uses$$props, uses$$restProps, + uses$$slots, }); // we need to process the module script after the instance script has moved otherwise we get warnings about moving edited items diff --git a/packages/svelte2tsx/svelte-shims.d.ts b/packages/svelte2tsx/svelte-shims.d.ts index b3a4e54d9..917f54fcc 100644 --- a/packages/svelte2tsx/svelte-shims.d.ts +++ b/packages/svelte2tsx/svelte-shims.d.ts @@ -85,6 +85,7 @@ type SvelteAnimation = (node: Element, move: { from: DOMRect, t type SvelteAllProps = { [index: string]: any } type SvelteRestProps = { [index: string]: any } +type SvelteSlots = { [index: string]: any } type SvelteStore = { subscribe: (run: (value: T) => any, invalidate?: any) => any } @@ -103,6 +104,7 @@ declare function __sveltets_ctorOf(type: T): AConstructorTypeOf; declare function __sveltets_instanceOf(type: AConstructorTypeOf): T; declare function __sveltets_allPropsType(): SvelteAllProps declare function __sveltets_restPropsType(): SvelteRestProps +declare function __sveltets_slotsType(): SvelteSlots declare function __sveltets_partial( render: () => {props?: Props, events?: Events, slots?: Slots } ): () => {props?: Partial, events?: Events, slots?: Slots } From 46f1bcd030b07dc31dd2d5208d7161db2e0292c9 Mon Sep 17 00:00:00 2001 From: Tan Li Hau Date: Thu, 20 Aug 2020 22:27:26 +0800 Subject: [PATCH 2/3] add testcase --- packages/svelte2tsx/src/svelte2tsx.ts | 4 ++-- .../uses-$$restProps-script/expected.tsx | 11 +++++++++++ .../uses-$$restProps-script/input.svelte | 4 ++++ .../samples/uses-$$slots-script/expected.tsx | 14 ++++++++++++++ .../samples/uses-$$slots-script/input.svelte | 7 +++++++ .../svelte2tsx/samples/uses-$$slots/expected.tsx | 10 ++++++++++ .../svelte2tsx/samples/uses-$$slots/input.svelte | 4 ++++ 7 files changed, 52 insertions(+), 2 deletions(-) create mode 100644 packages/svelte2tsx/test/svelte2tsx/samples/uses-$$restProps/uses-$$restProps-script/expected.tsx create mode 100644 packages/svelte2tsx/test/svelte2tsx/samples/uses-$$restProps/uses-$$restProps-script/input.svelte create mode 100644 packages/svelte2tsx/test/svelte2tsx/samples/uses-$$slots-script/expected.tsx create mode 100644 packages/svelte2tsx/test/svelte2tsx/samples/uses-$$slots-script/input.svelte create mode 100644 packages/svelte2tsx/test/svelte2tsx/samples/uses-$$slots/expected.tsx create mode 100644 packages/svelte2tsx/test/svelte2tsx/samples/uses-$$slots/input.svelte diff --git a/packages/svelte2tsx/src/svelte2tsx.ts b/packages/svelte2tsx/src/svelte2tsx.ts index 50b700c39..142692bb3 100644 --- a/packages/svelte2tsx/src/svelte2tsx.ts +++ b/packages/svelte2tsx/src/svelte2tsx.ts @@ -938,11 +938,11 @@ function createRenderFunction({ if (uses$$slots) { propsDecl += - 'let $$slots: { ' + + ' let $$slots: { ' + Array.from(slots.keys()) .map((name) => `${name}: any`) .join(', ') + - ' = __sveltets_slotsType();'; + ' } = __sveltets_slotsType();'; } if (scriptTag) { diff --git a/packages/svelte2tsx/test/svelte2tsx/samples/uses-$$restProps/uses-$$restProps-script/expected.tsx b/packages/svelte2tsx/test/svelte2tsx/samples/uses-$$restProps/uses-$$restProps-script/expected.tsx new file mode 100644 index 000000000..6174fe7a2 --- /dev/null +++ b/packages/svelte2tsx/test/svelte2tsx/samples/uses-$$restProps/uses-$$restProps-script/expected.tsx @@ -0,0 +1,11 @@ +/// +<>;function render() { let $$restProps = __sveltets_restPropsType(); + + let name = $$restProps['name']; +; +() => (<>

{name}

+); +return { props: {}, slots: {}, getters: {}, events: {} }} + +export default class Input__SvelteComponent_ extends createSvelte2TsxComponent(__sveltets_partial_with_any(__sveltets_with_any_event(render))) { +} diff --git a/packages/svelte2tsx/test/svelte2tsx/samples/uses-$$restProps/uses-$$restProps-script/input.svelte b/packages/svelte2tsx/test/svelte2tsx/samples/uses-$$restProps/uses-$$restProps-script/input.svelte new file mode 100644 index 000000000..ee119262a --- /dev/null +++ b/packages/svelte2tsx/test/svelte2tsx/samples/uses-$$restProps/uses-$$restProps-script/input.svelte @@ -0,0 +1,4 @@ +

{name}

+ diff --git a/packages/svelte2tsx/test/svelte2tsx/samples/uses-$$slots-script/expected.tsx b/packages/svelte2tsx/test/svelte2tsx/samples/uses-$$slots-script/expected.tsx new file mode 100644 index 000000000..27dac9812 --- /dev/null +++ b/packages/svelte2tsx/test/svelte2tsx/samples/uses-$$slots-script/expected.tsx @@ -0,0 +1,14 @@ +/// +<>;function render() { let $$slots: { foo: any, default: any } = __sveltets_slotsType(); + + let name = $$slots['name']; +; +() => (<>

{name}

+ + + +); +return { props: {}, slots: {foo: {}, default: {}}, getters: {}, events: {} }} + +export default class Input__SvelteComponent_ extends createSvelte2TsxComponent(__sveltets_partial(__sveltets_with_any_event(render))) { +} diff --git a/packages/svelte2tsx/test/svelte2tsx/samples/uses-$$slots-script/input.svelte b/packages/svelte2tsx/test/svelte2tsx/samples/uses-$$slots-script/input.svelte new file mode 100644 index 000000000..d141d4a3e --- /dev/null +++ b/packages/svelte2tsx/test/svelte2tsx/samples/uses-$$slots-script/input.svelte @@ -0,0 +1,7 @@ +

{name}

+ + + + \ No newline at end of file diff --git a/packages/svelte2tsx/test/svelte2tsx/samples/uses-$$slots/expected.tsx b/packages/svelte2tsx/test/svelte2tsx/samples/uses-$$slots/expected.tsx new file mode 100644 index 000000000..83df0c584 --- /dev/null +++ b/packages/svelte2tsx/test/svelte2tsx/samples/uses-$$slots/expected.tsx @@ -0,0 +1,10 @@ +/// +<>;function render() { let $$slots: { foo: any, default: any } = __sveltets_slotsType(); +<>

{$$slots['name']}

+ + + +return { props: {}, slots: {foo: {}, default: {}}, getters: {}, events: {} }} + +export default class Input__SvelteComponent_ extends createSvelte2TsxComponent(__sveltets_partial(__sveltets_with_any_event(render))) { +} \ No newline at end of file diff --git a/packages/svelte2tsx/test/svelte2tsx/samples/uses-$$slots/input.svelte b/packages/svelte2tsx/test/svelte2tsx/samples/uses-$$slots/input.svelte new file mode 100644 index 000000000..9412f8fac --- /dev/null +++ b/packages/svelte2tsx/test/svelte2tsx/samples/uses-$$slots/input.svelte @@ -0,0 +1,4 @@ +

{$$slots['name']}

+ + + \ No newline at end of file From a6ccbaa6060bebb3762d3d342040f87658b0eca5 Mon Sep 17 00:00:00 2001 From: Simon Holthausen Date: Thu, 20 Aug 2020 18:16:29 +0200 Subject: [PATCH 3/3] refine $$slots generation, tidy up tests We cannot use type annotations in the transformation because the user could be using JS only and would get "type annotations can only be used in TS files" errors. --- packages/svelte2tsx/src/svelte2tsx.ts | 6 +++--- packages/svelte2tsx/svelte-shims.d.ts | 2 +- .../uses-$$restProps-script/expected.tsx | 11 ----------- .../uses-$$restProps-script/input.svelte | 4 ---- .../samples/uses-$$slots-script/expected.tsx | 6 +++--- .../samples/uses-$$slots-script/input.svelte | 2 +- .../test/svelte2tsx/samples/uses-$$slots/expected.tsx | 2 +- 7 files changed, 9 insertions(+), 24 deletions(-) delete mode 100644 packages/svelte2tsx/test/svelte2tsx/samples/uses-$$restProps/uses-$$restProps-script/expected.tsx delete mode 100644 packages/svelte2tsx/test/svelte2tsx/samples/uses-$$restProps/uses-$$restProps-script/input.svelte diff --git a/packages/svelte2tsx/src/svelte2tsx.ts b/packages/svelte2tsx/src/svelte2tsx.ts index 142692bb3..83757768e 100644 --- a/packages/svelte2tsx/src/svelte2tsx.ts +++ b/packages/svelte2tsx/src/svelte2tsx.ts @@ -938,11 +938,11 @@ function createRenderFunction({ if (uses$$slots) { propsDecl += - ' let $$slots: { ' + + ' let $$slots = __sveltets_slotsType({' + Array.from(slots.keys()) - .map((name) => `${name}: any`) + .map((name) => `${name}: ''`) .join(', ') + - ' } = __sveltets_slotsType();'; + '});'; } if (scriptTag) { diff --git a/packages/svelte2tsx/svelte-shims.d.ts b/packages/svelte2tsx/svelte-shims.d.ts index 917f54fcc..2bd7180b8 100644 --- a/packages/svelte2tsx/svelte-shims.d.ts +++ b/packages/svelte2tsx/svelte-shims.d.ts @@ -104,7 +104,7 @@ declare function __sveltets_ctorOf(type: T): AConstructorTypeOf; declare function __sveltets_instanceOf(type: AConstructorTypeOf): T; declare function __sveltets_allPropsType(): SvelteAllProps declare function __sveltets_restPropsType(): SvelteRestProps -declare function __sveltets_slotsType(): SvelteSlots +declare function __sveltets_slotsType(slots: Slots): Record; declare function __sveltets_partial( render: () => {props?: Props, events?: Events, slots?: Slots } ): () => {props?: Partial, events?: Events, slots?: Slots } diff --git a/packages/svelte2tsx/test/svelte2tsx/samples/uses-$$restProps/uses-$$restProps-script/expected.tsx b/packages/svelte2tsx/test/svelte2tsx/samples/uses-$$restProps/uses-$$restProps-script/expected.tsx deleted file mode 100644 index 6174fe7a2..000000000 --- a/packages/svelte2tsx/test/svelte2tsx/samples/uses-$$restProps/uses-$$restProps-script/expected.tsx +++ /dev/null @@ -1,11 +0,0 @@ -/// -<>;function render() { let $$restProps = __sveltets_restPropsType(); - - let name = $$restProps['name']; -; -() => (<>

{name}

-); -return { props: {}, slots: {}, getters: {}, events: {} }} - -export default class Input__SvelteComponent_ extends createSvelte2TsxComponent(__sveltets_partial_with_any(__sveltets_with_any_event(render))) { -} diff --git a/packages/svelte2tsx/test/svelte2tsx/samples/uses-$$restProps/uses-$$restProps-script/input.svelte b/packages/svelte2tsx/test/svelte2tsx/samples/uses-$$restProps/uses-$$restProps-script/input.svelte deleted file mode 100644 index ee119262a..000000000 --- a/packages/svelte2tsx/test/svelte2tsx/samples/uses-$$restProps/uses-$$restProps-script/input.svelte +++ /dev/null @@ -1,4 +0,0 @@ -

{name}

- diff --git a/packages/svelte2tsx/test/svelte2tsx/samples/uses-$$slots-script/expected.tsx b/packages/svelte2tsx/test/svelte2tsx/samples/uses-$$slots-script/expected.tsx index 27dac9812..9c3fd99e7 100644 --- a/packages/svelte2tsx/test/svelte2tsx/samples/uses-$$slots-script/expected.tsx +++ b/packages/svelte2tsx/test/svelte2tsx/samples/uses-$$slots-script/expected.tsx @@ -1,11 +1,11 @@ /// -<>;function render() { let $$slots: { foo: any, default: any } = __sveltets_slotsType(); +<>;function render() { let $$slots = __sveltets_slotsType({foo: '', default: ''}); let name = $$slots['name']; ; -() => (<>

{name}

- +() => (<> +

{name}

); return { props: {}, slots: {foo: {}, default: {}}, getters: {}, events: {} }} diff --git a/packages/svelte2tsx/test/svelte2tsx/samples/uses-$$slots-script/input.svelte b/packages/svelte2tsx/test/svelte2tsx/samples/uses-$$slots-script/input.svelte index d141d4a3e..feed3be0e 100644 --- a/packages/svelte2tsx/test/svelte2tsx/samples/uses-$$slots-script/input.svelte +++ b/packages/svelte2tsx/test/svelte2tsx/samples/uses-$$slots-script/input.svelte @@ -1,7 +1,7 @@ -

{name}

+

{name}

\ No newline at end of file diff --git a/packages/svelte2tsx/test/svelte2tsx/samples/uses-$$slots/expected.tsx b/packages/svelte2tsx/test/svelte2tsx/samples/uses-$$slots/expected.tsx index 83df0c584..28a81cd1e 100644 --- a/packages/svelte2tsx/test/svelte2tsx/samples/uses-$$slots/expected.tsx +++ b/packages/svelte2tsx/test/svelte2tsx/samples/uses-$$slots/expected.tsx @@ -1,5 +1,5 @@ /// -<>;function render() { let $$slots: { foo: any, default: any } = __sveltets_slotsType(); +<>;function render() { let $$slots = __sveltets_slotsType({foo: '', default: ''}); <>

{$$slots['name']}