From 6ad02b590279ea845398c6cc4edb0681f8049db6 Mon Sep 17 00:00:00 2001 From: Bjorn Lu Date: Thu, 18 Jul 2024 21:32:39 +0800 Subject: [PATCH] Fix Svelte 5 slots change (#11490) * Fix Svelte 5 slots change * Use alternative * Fix Svelte 5 slots --- .changeset/nine-carpets-doubt.md | 5 ++++ packages/integrations/svelte/client-v5.js | 32 +++++++---------------- packages/integrations/svelte/package.json | 2 +- packages/integrations/svelte/server-v5.js | 20 +++++++------- 4 files changed, 26 insertions(+), 33 deletions(-) create mode 100644 .changeset/nine-carpets-doubt.md diff --git a/.changeset/nine-carpets-doubt.md b/.changeset/nine-carpets-doubt.md new file mode 100644 index 000000000000..5abe918afe65 --- /dev/null +++ b/.changeset/nine-carpets-doubt.md @@ -0,0 +1,5 @@ +--- +'@astrojs/svelte': minor +--- + +Bumps Svelte 5 peer dependency to `^5.0.0-next.190` and support the latest slots/snippets API diff --git a/packages/integrations/svelte/client-v5.js b/packages/integrations/svelte/client-v5.js index 755a6aa5381e..fda68ee54878 100644 --- a/packages/integrations/svelte/client-v5.js +++ b/packages/integrations/svelte/client-v5.js @@ -1,8 +1,4 @@ -import { hydrate, mount, unmount } from 'svelte'; -import { add_snippet_symbol } from 'svelte/internal/client'; - -// Allow a slot to be rendered as a snippet (dev validation only) -const tagSlotAsSnippet = import.meta.env.DEV ? add_snippet_symbol : (s) => s; +import { createRawSnippet, hydrate, mount, unmount } from 'svelte'; export default (element) => { return async (Component, props, slotted, { client }) => { @@ -11,11 +7,16 @@ export default (element) => { let children = undefined; let $$slots = undefined; for (const [key, value] of Object.entries(slotted)) { + $$slots ??= {}; if (key === 'default') { - children = createSlotDefinition(key, value); + $$slots.default = true; + children = createRawSnippet(() => ({ + render: () => `${value}`, + })); } else { - $$slots ??= {}; - $$slots[key] = createSlotDefinition(key, value); + $$slots[key] = createRawSnippet(() => ({ + render: () => `${value}`, + })); } } @@ -33,18 +34,3 @@ export default (element) => { element.addEventListener('astro:unmount', () => unmount(component), { once: true }); }; }; - -function createSlotDefinition(key, children) { - /** - * @param {Comment} $$anchor A comment node for slots in Svelte 5 - */ - const fn = ($$anchor, _$$slotProps) => { - const parent = $$anchor.parentNode; - const el = document.createElement('div'); - el.innerHTML = `${children}`; - parent.insertBefore(el.children[0], $$anchor); - }; - return tagSlotAsSnippet(fn); -} diff --git a/packages/integrations/svelte/package.json b/packages/integrations/svelte/package.json index 7d544328aca7..521daae536e3 100644 --- a/packages/integrations/svelte/package.json +++ b/packages/integrations/svelte/package.json @@ -61,7 +61,7 @@ }, "peerDependencies": { "astro": "^4.0.0", - "svelte": "^4.0.0 || ^5.0.0-next.90", + "svelte": "^4.0.0 || ^5.0.0-next.190", "typescript": "^5.3.3" }, "engines": { diff --git a/packages/integrations/svelte/server-v5.js b/packages/integrations/svelte/server-v5.js index 04a24eff2474..acffd10dfef0 100644 --- a/packages/integrations/svelte/server-v5.js +++ b/packages/integrations/svelte/server-v5.js @@ -1,9 +1,6 @@ -import { add_snippet_symbol } from 'svelte/internal/server'; +import { createRawSnippet } from 'svelte'; import { render } from 'svelte/server'; -// Allow a slot to be rendered as a snippet (dev validation only) -const tagSlotAsSnippet = import.meta.env.DEV ? add_snippet_symbol : (s) => s; - function check(Component) { // Svelte 5 generated components always accept these two props const str = Component.toString(); @@ -21,22 +18,27 @@ async function renderToStaticMarkup(Component, props, slotted, metadata) { let children = undefined; let $$slots = undefined; for (const [key, value] of Object.entries(slotted)) { + $$slots ??= {}; if (key === 'default') { - children = tagSlotAsSnippet(() => `<${tagName}>${value}`); + $$slots.default = true; + children = createRawSnippet(() => ({ + render: () => `<${tagName}>${value}`, + })); } else { - $$slots ??= {}; - $$slots[key] = tagSlotAsSnippet(() => `<${tagName} name="${key}">${value}`); + $$slots[key] = createRawSnippet(() => ({ + render: () => `<${tagName} name="${key}">${value}`, + })); } } - const { html } = render(Component, { + const result = render(Component, { props: { ...props, children, $$slots, }, }); - return { html }; + return { html: result.body }; } export default {