summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Edward Brunetiere <57622377+P4tt4te@users.noreply.github.com> 2025-03-18 10:32:07 +0100
committerGravatar GitHub <noreply@github.com> 2025-03-18 09:32:07 +0000
commitdefad33140dccde324b9357bc6331f7e5cdec266 (patch)
treebe4ac16548c94ef2364f30a78d8cad3a8bc29a5d
parent7783dbf8117650c60d7633b43f0d42da487aa2b1 (diff)
downloadastro-defad33140dccde324b9357bc6331f7e5cdec266.tar.gz
astro-defad33140dccde324b9357bc6331f7e5cdec266.tar.zst
astro-defad33140dccde324b9357bc6331f7e5cdec266.zip
fix: renderToString function not render properly nested slots when they are components (#13432)
* Fix/render to string slots (#1) * add force HTMLString with local tests * remove local test & logs * remove test counter in basic exemple * re-add test & create SlotString instead of HTMLString * add test of a nested rendered component inside renderToString slots function * add changeset on astro package * Apply suggestions from code review --------- Co-authored-by: Emanuele Stoppa <my.burning@gmail.com> Co-authored-by: ematipico <602478+ematipico@users.noreply.github.com>
-rw-r--r--.changeset/wide-carrots-dream.md5
-rw-r--r--examples/container-with-vitest/src/components/CounterLight.astro9
-rw-r--r--examples/container-with-vitest/test/Card.test.ts14
-rw-r--r--packages/astro/src/container/index.ts13
4 files changed, 41 insertions, 0 deletions
diff --git a/.changeset/wide-carrots-dream.md b/.changeset/wide-carrots-dream.md
new file mode 100644
index 000000000..b0e30081e
--- /dev/null
+++ b/.changeset/wide-carrots-dream.md
@@ -0,0 +1,5 @@
+---
+'astro': patch
+---
+
+Fix an issue in the Container API, where the `renderToString` function doesn't render adequately nested slots when they are components.
diff --git a/examples/container-with-vitest/src/components/CounterLight.astro b/examples/container-with-vitest/src/components/CounterLight.astro
new file mode 100644
index 000000000..7cee23bbe
--- /dev/null
+++ b/examples/container-with-vitest/src/components/CounterLight.astro
@@ -0,0 +1,9 @@
+---
+interface Props {
+ count?: number;
+}
+
+let { count = 0 } = Astro.props;
+---
+
+<p id="counter">{count}</p>
diff --git a/examples/container-with-vitest/test/Card.test.ts b/examples/container-with-vitest/test/Card.test.ts
index 26d766d1a..119087a36 100644
--- a/examples/container-with-vitest/test/Card.test.ts
+++ b/examples/container-with-vitest/test/Card.test.ts
@@ -1,6 +1,7 @@
import { experimental_AstroContainer as AstroContainer } from 'astro/container';
import { expect, test } from 'vitest';
import Card from '../src/components/Card.astro';
+import CounterLight from '../src/components/CounterLight.astro';
test('Card with slots', async () => {
const container = await AstroContainer.create();
@@ -13,3 +14,16 @@ test('Card with slots', async () => {
expect(result).toContain('This is a card');
expect(result).toContain('Card content');
});
+
+test('Card with nested CounterLight', async () => {
+ const container = await AstroContainer.create();
+ const counterLight = await container.renderToString(CounterLight, { props: { count: 1 } });
+ const result = await container.renderToString(Card, {
+ slots: {
+ default: counterLight,
+ },
+ });
+
+ expect(result).toContain('This is a card');
+ expect(result).toContain(counterLight);
+});
diff --git a/packages/astro/src/container/index.ts b/packages/astro/src/container/index.ts
index 0a1b854d1..3943ad57b 100644
--- a/packages/astro/src/container/index.ts
+++ b/packages/astro/src/container/index.ts
@@ -26,6 +26,7 @@ import type {
SSRResult,
} from '../types/public/internal.js';
import { ContainerPipeline } from './pipeline.js';
+import { SlotString } from '../runtime/server/render/slot.js';
/** Public type, used for integrations to define a renderer for the container API */
export type ContainerRenderer = {
@@ -474,6 +475,10 @@ export class experimental_AstroContainer {
component: AstroComponentFactory,
options: ContainerRenderOptions = {},
): Promise<string> {
+ if (options.slots) {
+ options.slots = markAllSlotsAsSlotString(options.slots);
+ }
+
const response = await this.renderToResponse(component, options);
return await response.text();
}
@@ -588,3 +593,11 @@ export class experimental_AstroContainer {
function isNamedRenderer(renderer: any): renderer is NamedSSRLoadedRendererValue {
return !!renderer?.name;
}
+
+function markAllSlotsAsSlotString(slots: Record<string, any>): Record<string, any> {
+ const markedSlots: Record<string, any> = {};
+ for (const slotName in slots) {
+ markedSlots[slotName] = new SlotString(slots[slotName], null);
+ }
+ return markedSlots;
+}