diff options
Diffstat (limited to 'packages/integrations/svelte/server.js')
-rw-r--r-- | packages/integrations/svelte/server.js | 48 |
1 files changed, 42 insertions, 6 deletions
diff --git a/packages/integrations/svelte/server.js b/packages/integrations/svelte/server.js index 9878d3b59..ac133dced 100644 --- a/packages/integrations/svelte/server.js +++ b/packages/integrations/svelte/server.js @@ -1,5 +1,13 @@ +import { createRawSnippet } from 'svelte'; +import { render } from 'svelte/server'; + function check(Component) { - return Component['render'] && Component['$$render']; + if (typeof Component !== 'function') return false; + // Svelte 5 generated components always accept a `$$payload` prop. + // This assumes that the SSR build does not minify it (which Astro enforces by default). + // This isn't the best check, but the only other option otherwise is to try to render the + // component, which is taxing. We'll leave it as a last resort for the future for now. + return Component.toString().includes('$$payload'); } function needsHydration(metadata) { @@ -9,16 +17,44 @@ function needsHydration(metadata) { async function renderToStaticMarkup(Component, props, slotted, metadata) { const tagName = needsHydration(metadata) ? 'astro-slot' : 'astro-static-slot'; - const slots = {}; + + let children = undefined; + let $$slots = undefined; + const renderProps = {}; + for (const [key, value] of Object.entries(slotted)) { - slots[key] = () => - `<${tagName}${key === 'default' ? '' : ` name="${key}"`}>${value}</${tagName}>`; + // Legacy slot support + $$slots ??= {}; + if (key === 'default') { + $$slots.default = true; + children = createRawSnippet(() => ({ + render: () => `<${tagName}>${value}</${tagName}>`, + })); + } else { + $$slots[key] = createRawSnippet(() => ({ + render: () => `<${tagName} name="${key}">${value}</${tagName}>`, + })); + } + // @render support for Svelte ^5.0 + const slotName = key === 'default' ? 'children' : key; + renderProps[slotName] = createRawSnippet(() => ({ + render: () => `<${tagName}${key !== 'default' ? ` name="${key}"` : ''}>${value}</${tagName}>`, + })); } - const { html } = Component.render(props, { $$slots: slots }); - return { html }; + + const result = render(Component, { + props: { + ...props, + children, + $$slots, + ...renderProps, + }, + }); + return { html: result.body }; } export default { + name: '@astrojs/svelte', check, renderToStaticMarkup, supportsAstroStaticSlot: true, |