0
Fork 0
mirror of https://github.com/withastro/astro.git synced 2025-01-06 22:10:10 -05:00

fix(runtime): check head+content component before throwing an error (#11141)

* fix(runtime): check head+content component before throwing an error

* add test
This commit is contained in:
Emanuele Stoppa 2024-05-29 07:29:26 -04:00 committed by GitHub
parent 6b97634396
commit 19df89f87c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 83 additions and 1 deletions

View file

@ -0,0 +1,13 @@
---
"astro": patch
---
Fixes an internal error that prevented the `AstroContainer` to render the `Content` component.
You can now write code similar to the following to render content collections:
```js
const entry = await getEntry(collection, slug);
const { Content } = await entry.render();
const content = await container.renderToString(Content);
```

View file

@ -148,6 +148,25 @@ async function callComponentAsTemplateResultOrResponse(
if (factoryResult instanceof Response) { if (factoryResult instanceof Response) {
return factoryResult; return factoryResult;
}
// we check if the component we attempt to render is a head+content
else if (isHeadAndContent(factoryResult)) {
// we make sure that content is valid template result
if (!isRenderTemplateResult(factoryResult.content)) {
throw new AstroError({
...AstroErrorData.OnlyResponseCanBeReturned,
message: AstroErrorData.OnlyResponseCanBeReturned.message(
route?.route,
typeof factoryResult
),
location: {
file: route?.component,
},
});
}
// return the content
return factoryResult.content;
} else if (!isRenderTemplateResult(factoryResult)) { } else if (!isRenderTemplateResult(factoryResult)) {
throw new AstroError({ throw new AstroError({
...AstroErrorData.OnlyResponseCanBeReturned, ...AstroErrorData.OnlyResponseCanBeReturned,
@ -158,7 +177,7 @@ async function callComponentAsTemplateResultOrResponse(
}); });
} }
return isHeadAndContent(factoryResult) ? factoryResult.content : factoryResult; return factoryResult;
} }
// Recursively calls component instances that might have head content // Recursively calls component instances that might have head content

View file

@ -9,6 +9,8 @@ import {
renderComponent, renderComponent,
renderHead, renderHead,
renderSlot, renderSlot,
createHeadAndContent,
renderTemplate
} from '../dist/runtime/server/index.js'; } from '../dist/runtime/server/index.js';
const BaseLayout = createComponent((result, _props, slots) => { const BaseLayout = createComponent((result, _props, slots) => {
@ -140,6 +142,54 @@ describe('Container', () => {
assert.match(result, /Bar name/); assert.match(result, /Bar name/);
}); });
it('Renders content and head component', async () => {
const Page = createComponent(
(result, _props, slots) => {
return createHeadAndContent(
'',
renderTemplate`${renderComponent(
result,
'BaseLayout',
BaseLayout,
{},
{
default: () => render`
${maybeRenderHead(result)}
${renderSlot(result, slots['custom-name'])}
${renderSlot(result, slots['foo-name'])}
`,
head: () => render`
${renderComponent(
result,
'Fragment',
Fragment,
{ slot: 'head' },
{
default: () => render`<meta charset="utf-8">`,
}
)}
`,
}
)}`
);
},
'Component2.astro',
undefined
);
const container = await experimental_AstroContainer.create();
const result = await container.renderToString(Page, {
slots: {
'custom-name': 'Custom name',
'foo-name': 'Bar name',
},
});
assert.match(result, /Custom name/);
assert.match(result, /Bar name/);
});
it('Renders props', async () => { it('Renders props', async () => {
const Page = createComponent( const Page = createComponent(
(result, props, _slots) => { (result, props, _slots) => {