Skip to content

Commit 6ad02b5

Browse files
authored
Fix Svelte 5 slots change (#11490)
* Fix Svelte 5 slots change * Use alternative * Fix Svelte 5 slots
1 parent 7c9ed71 commit 6ad02b5

4 files changed

Lines changed: 26 additions & 33 deletions

File tree

.changeset/nine-carpets-doubt.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@astrojs/svelte': minor
3+
---
4+
5+
Bumps Svelte 5 peer dependency to `^5.0.0-next.190` and support the latest slots/snippets API
Lines changed: 9 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,4 @@
1-
import { hydrate, mount, unmount } from 'svelte';
2-
import { add_snippet_symbol } from 'svelte/internal/client';
3-
4-
// Allow a slot to be rendered as a snippet (dev validation only)
5-
const tagSlotAsSnippet = import.meta.env.DEV ? add_snippet_symbol : (s) => s;
1+
import { createRawSnippet, hydrate, mount, unmount } from 'svelte';
62

73
export default (element) => {
84
return async (Component, props, slotted, { client }) => {
@@ -11,11 +7,16 @@ export default (element) => {
117
let children = undefined;
128
let $$slots = undefined;
139
for (const [key, value] of Object.entries(slotted)) {
10+
$$slots ??= {};
1411
if (key === 'default') {
15-
children = createSlotDefinition(key, value);
12+
$$slots.default = true;
13+
children = createRawSnippet(() => ({
14+
render: () => `<astro-slot>${value}</astro-slot>`,
15+
}));
1616
} else {
17-
$$slots ??= {};
18-
$$slots[key] = createSlotDefinition(key, value);
17+
$$slots[key] = createRawSnippet(() => ({
18+
render: () => `<astro-slot name="${key}">${value}</astro-slot>`,
19+
}));
1920
}
2021
}
2122

@@ -33,18 +34,3 @@ export default (element) => {
3334
element.addEventListener('astro:unmount', () => unmount(component), { once: true });
3435
};
3536
};
36-
37-
function createSlotDefinition(key, children) {
38-
/**
39-
* @param {Comment} $$anchor A comment node for slots in Svelte 5
40-
*/
41-
const fn = ($$anchor, _$$slotProps) => {
42-
const parent = $$anchor.parentNode;
43-
const el = document.createElement('div');
44-
el.innerHTML = `<astro-slot${
45-
key === 'default' ? '' : ` name="${key}"`
46-
}>${children}</astro-slot>`;
47-
parent.insertBefore(el.children[0], $$anchor);
48-
};
49-
return tagSlotAsSnippet(fn);
50-
}

packages/integrations/svelte/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@
6161
},
6262
"peerDependencies": {
6363
"astro": "^4.0.0",
64-
"svelte": "^4.0.0 || ^5.0.0-next.90",
64+
"svelte": "^4.0.0 || ^5.0.0-next.190",
6565
"typescript": "^5.3.3"
6666
},
6767
"engines": {

packages/integrations/svelte/server-v5.js

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
1-
import { add_snippet_symbol } from 'svelte/internal/server';
1+
import { createRawSnippet } from 'svelte';
22
import { render } from 'svelte/server';
33

4-
// Allow a slot to be rendered as a snippet (dev validation only)
5-
const tagSlotAsSnippet = import.meta.env.DEV ? add_snippet_symbol : (s) => s;
6-
74
function check(Component) {
85
// Svelte 5 generated components always accept these two props
96
const str = Component.toString();
@@ -21,22 +18,27 @@ async function renderToStaticMarkup(Component, props, slotted, metadata) {
2118
let children = undefined;
2219
let $$slots = undefined;
2320
for (const [key, value] of Object.entries(slotted)) {
21+
$$slots ??= {};
2422
if (key === 'default') {
25-
children = tagSlotAsSnippet(() => `<${tagName}>${value}</${tagName}>`);
23+
$$slots.default = true;
24+
children = createRawSnippet(() => ({
25+
render: () => `<${tagName}>${value}</${tagName}>`,
26+
}));
2627
} else {
27-
$$slots ??= {};
28-
$$slots[key] = tagSlotAsSnippet(() => `<${tagName} name="${key}">${value}</${tagName}>`);
28+
$$slots[key] = createRawSnippet(() => ({
29+
render: () => `<${tagName} name="${key}">${value}</${tagName}>`,
30+
}));
2931
}
3032
}
3133

32-
const { html } = render(Component, {
34+
const result = render(Component, {
3335
props: {
3436
...props,
3537
children,
3638
$$slots,
3739
},
3840
});
39-
return { html };
41+
return { html: result.body };
4042
}
4143

4244
export default {

0 commit comments

Comments
 (0)