diff --git a/.changeset/famous-parents-turn.md b/.changeset/famous-parents-turn.md new file mode 100644 index 000000000000..38f9e1f9dff4 --- /dev/null +++ b/.changeset/famous-parents-turn.md @@ -0,0 +1,5 @@ +--- +'svelte': minor +--- + +feat: allow snippets to be exported from module scripts diff --git a/documentation/docs/03-template-syntax/06-snippet.md b/documentation/docs/03-template-syntax/06-snippet.md index 4bbc970c5d5c..fd8cd78d6e4e 100644 --- a/documentation/docs/03-template-syntax/06-snippet.md +++ b/documentation/docs/03-template-syntax/06-snippet.md @@ -246,6 +246,20 @@ We can tighten things up further by declaring a generic, so that `data` and `row ``` +## Exporting snippets + +Snippets declared at the top level of a `.svelte` file can be exported from a ` + +{#snippet add(a, b)} + {a} + {b} = {a + b} +{/snippet} +``` + ## Programmatic snippets Snippets can be created programmatically with the [`createRawSnippet`](svelte#createRawSnippet) API. This is intended for advanced use cases. diff --git a/documentation/docs/98-reference/.generated/compile-errors.md b/documentation/docs/98-reference/.generated/compile-errors.md index 77166097a219..e1925324e6ed 100644 --- a/documentation/docs/98-reference/.generated/compile-errors.md +++ b/documentation/docs/98-reference/.generated/compile-errors.md @@ -400,6 +400,12 @@ Expected token %token% Expected whitespace ``` +### export_undefined + +``` +`%name%` is not defined +``` + ### global_reference_invalid ``` @@ -694,6 +700,30 @@ Cannot use `` syntax and `{@render ...}` tags in the same component. Migra Cannot use explicit children snippet at the same time as implicit children content. Remove either the non-whitespace content or the children snippet block ``` +### snippet_invalid_export + +``` +An exported snippet can only reference things declared in a ` + + + +{#snippet greeting(name)} +

{message} {name}!

+{/snippet} +``` + +...because `greeting` references `message`, which is defined in the second ` + + + +{#snippet greeting(name)} +

{message} {name}!

+{/snippet} +``` + +...because `greeting` references `message`, which is defined in the second ` diff --git a/packages/svelte/tests/runtime-runes/samples/snippet-hoisted-module-2/Child.svelte b/packages/svelte/tests/runtime-runes/samples/snippet-hoisted-module-2/Child.svelte new file mode 100644 index 000000000000..902386fd7e68 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/snippet-hoisted-module-2/Child.svelte @@ -0,0 +1,13 @@ + + +{#snippet one()} + {@render two()} +{/snippet} + +{#snippet two()} + {message} +{/snippet} diff --git a/packages/svelte/tests/runtime-runes/samples/snippet-hoisted-module-2/_config.js b/packages/svelte/tests/runtime-runes/samples/snippet-hoisted-module-2/_config.js new file mode 100644 index 000000000000..55ab126f8980 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/snippet-hoisted-module-2/_config.js @@ -0,0 +1,8 @@ +import { test } from '../../test'; + +export default test({ + compileOptions: { + dev: true // Render in dev mode to check that the validation error is not thrown + }, + html: `hello` +}); diff --git a/packages/svelte/tests/runtime-runes/samples/snippet-hoisted-module-2/main.svelte b/packages/svelte/tests/runtime-runes/samples/snippet-hoisted-module-2/main.svelte new file mode 100644 index 000000000000..11b7297397ea --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/snippet-hoisted-module-2/main.svelte @@ -0,0 +1,5 @@ + + +{@render one()} diff --git a/packages/svelte/tests/runtime-runes/samples/snippet-hoisted-module/Child.svelte b/packages/svelte/tests/runtime-runes/samples/snippet-hoisted-module/Child.svelte new file mode 100644 index 000000000000..ffa1c12b349c --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/snippet-hoisted-module/Child.svelte @@ -0,0 +1,9 @@ + + +{#snippet foo(a, b)} + Hello world {a + b} +{/snippet} diff --git a/packages/svelte/tests/runtime-runes/samples/snippet-hoisted-module/_config.js b/packages/svelte/tests/runtime-runes/samples/snippet-hoisted-module/_config.js new file mode 100644 index 000000000000..be8d22b4e862 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/snippet-hoisted-module/_config.js @@ -0,0 +1,8 @@ +import { test } from '../../test'; + +export default test({ + compileOptions: { + dev: true // Render in dev mode to check that the validation error is not thrown + }, + html: `Hello world 3` +}); diff --git a/packages/svelte/tests/runtime-runes/samples/snippet-hoisted-module/main.svelte b/packages/svelte/tests/runtime-runes/samples/snippet-hoisted-module/main.svelte new file mode 100644 index 000000000000..80e9df514b70 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/snippet-hoisted-module/main.svelte @@ -0,0 +1,5 @@ + + +{@render foo(1, 2)} diff --git a/packages/svelte/tests/snapshot/samples/bind-component-snippet/_expected/client/index.svelte.js b/packages/svelte/tests/snapshot/samples/bind-component-snippet/_expected/client/index.svelte.js index 58ccf7ed7fda..bcddb6f658c8 100644 --- a/packages/svelte/tests/snapshot/samples/bind-component-snippet/_expected/client/index.svelte.js +++ b/packages/svelte/tests/snapshot/samples/bind-component-snippet/_expected/client/index.svelte.js @@ -2,17 +2,17 @@ import "svelte/internal/disclose-version"; import * as $ from "svelte/internal/client"; import TextInput from './Child.svelte'; -var root = $.template(` `, 1); +const snippet = ($$anchor) => { + $.next(); -export default function Bind_component_snippet($$anchor) { - const snippet = ($$anchor) => { - $.next(); + var text = $.text("Something"); - var text = $.text("Something"); + $.append($$anchor, text); +}; - $.append($$anchor, text); - }; +var root = $.template(` `, 1); +export default function Bind_component_snippet($$anchor) { let value = $.state(''); const _snippet = snippet; var fragment = root(); diff --git a/packages/svelte/tests/snapshot/samples/bind-component-snippet/_expected/server/index.svelte.js b/packages/svelte/tests/snapshot/samples/bind-component-snippet/_expected/server/index.svelte.js index b645d055702c..d223a3150269 100644 --- a/packages/svelte/tests/snapshot/samples/bind-component-snippet/_expected/server/index.svelte.js +++ b/packages/svelte/tests/snapshot/samples/bind-component-snippet/_expected/server/index.svelte.js @@ -1,14 +1,13 @@ import * as $ from "svelte/internal/server"; import TextInput from './Child.svelte'; +function snippet($$payload) { + $$payload.out += `Something`; +} + export default function Bind_component_snippet($$payload) { let value = ''; const _snippet = snippet; - - function snippet($$payload) { - $$payload.out += `Something`; - } - let $$settled = true; let $$inner_payload;