mirror of
https://github.com/withastro/astro.git
synced 2025-04-07 23:41:43 -05:00
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>
This commit is contained in:
parent
7783dbf811
commit
defad33140
4 changed files with 41 additions and 0 deletions
5
.changeset/wide-carrots-dream.md
Normal file
5
.changeset/wide-carrots-dream.md
Normal file
|
@ -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.
|
|
@ -0,0 +1,9 @@
|
|||
---
|
||||
interface Props {
|
||||
count?: number;
|
||||
}
|
||||
|
||||
let { count = 0 } = Astro.props;
|
||||
---
|
||||
|
||||
<p id="counter">{count}</p>
|
|
@ -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);
|
||||
});
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue