diff --git a/packages/astro/src/runtime/server/render/astro/head-and-content.ts b/packages/astro/src/runtime/server/render/astro/head-and-content.ts index fbadcb6f1..d895d9dd6 100644 --- a/packages/astro/src/runtime/server/render/astro/head-and-content.ts +++ b/packages/astro/src/runtime/server/render/astro/head-and-content.ts @@ -12,10 +12,7 @@ export function isHeadAndContent(obj: unknown): obj is HeadAndContent { return typeof obj === 'object' && !!(obj as any)[headAndContentSym]; } -export function createHeadAndContent( - head: string, - content: RenderTemplateResult -): HeadAndContent { +export function createHeadAndContent(head: string, content: RenderTemplateResult): HeadAndContent { return { [headAndContentSym]: true, head, diff --git a/packages/astro/src/runtime/server/render/common.ts b/packages/astro/src/runtime/server/render/common.ts index c9d17b64c..9b1aa1453 100644 --- a/packages/astro/src/runtime/server/render/common.ts +++ b/packages/astro/src/runtime/server/render/common.ts @@ -2,13 +2,13 @@ import type { SSRResult } from '../../../@types/astro'; import type { RenderInstruction } from './types.js'; import { HTMLBytes, markHTMLString } from '../escape.js'; -import { renderAllHeadContent } from './head.js'; import { determineIfNeedsHydrationScript, determinesIfNeedsDirectiveScript, getPrescripts, PrescriptType, } from '../scripts.js'; +import { renderAllHeadContent } from './head.js'; import { isSlotString, type SlotString } from './slot.js'; export const Fragment = Symbol.for('astro:fragment'); @@ -21,15 +21,15 @@ export const decoder = new TextDecoder(); // These directive instructions bubble all the way up to renderPage so that we // can ensure they are added only once, and as soon as possible. export function stringifyChunk(result: SSRResult, chunk: string | SlotString | RenderInstruction) { - if(typeof (chunk as any).type === 'string') { + if (typeof (chunk as any).type === 'string') { const instruction = chunk as RenderInstruction; - switch(instruction.type) { + switch (instruction.type) { case 'directive': { const { hydration } = instruction; let needsHydrationScript = hydration && determineIfNeedsHydrationScript(result); let needsDirectiveScript = hydration && determinesIfNeedsDirectiveScript(result, hydration.directive); - + let prescriptType: PrescriptType = needsHydrationScript ? 'both' : needsDirectiveScript @@ -43,8 +43,8 @@ export function stringifyChunk(result: SSRResult, chunk: string | SlotString | R } } case 'head': { - if(result._metadata.hasRenderedHead) { - return ''; + if (result._metadata.hasRenderedHead) { + return ''; } return renderAllHeadContent(result); } diff --git a/packages/astro/src/runtime/server/render/head.ts b/packages/astro/src/runtime/server/render/head.ts index 83c2c173b..ade6a7355 100644 --- a/packages/astro/src/runtime/server/render/head.ts +++ b/packages/astro/src/runtime/server/render/head.ts @@ -39,7 +39,7 @@ export function renderAllHeadContent(result: SSRResult) { return markHTMLString(content); } -export function * renderHead(result: SSRResult) { +export function* renderHead(result: SSRResult) { yield { type: 'head', result } as const; } diff --git a/packages/astro/src/runtime/server/render/types.ts b/packages/astro/src/runtime/server/render/types.ts index 3744037a0..3aa3a16e3 100644 --- a/packages/astro/src/runtime/server/render/types.ts +++ b/packages/astro/src/runtime/server/render/types.ts @@ -10,6 +10,6 @@ export type RenderDirectiveInstruction = { export type RenderHeadInstruction = { type: 'head'; result: SSRResult; -} +}; export type RenderInstruction = RenderDirectiveInstruction | RenderHeadInstruction; diff --git a/packages/astro/test/units/render/head.test.js b/packages/astro/test/units/render/head.test.js index 30ce69781..103c84fda 100644 --- a/packages/astro/test/units/render/head.test.js +++ b/packages/astro/test/units/render/head.test.js @@ -7,7 +7,7 @@ import { renderSlot, maybeRenderHead, renderHead, - Fragment + Fragment, } from '../../../dist/runtime/server/index.js'; import { createBasicEnvironment, @@ -41,41 +41,63 @@ describe('core/render', () => { ${renderSlot(result, slots['default'])} `; - }) + }); const PageLayout = createComponent((result, _props, slots) => { - return render`${renderComponent(result, 'Layout', BaseLayout, {}, { - 'default': () => render` + return render`${renderComponent( + result, + 'Layout', + BaseLayout, + {}, + { + default: () => render` ${maybeRenderHead(result)}
${renderSlot(result, slots['default'])}
`, - 'head': () => render` - ${renderComponent(result, 'Fragment', Fragment, { slot: 'head' }, { - 'default': () => render`${renderSlot(result, slots['head'])}` - })} - ` - })} + head: () => render` + ${renderComponent( + result, + 'Fragment', + Fragment, + { slot: 'head' }, + { + default: () => render`${renderSlot(result, slots['head'])}`, + } + )} + `, + } + )} `; }); const Page = createComponent((result, _props) => { - return render`${renderComponent(result, 'PageLayout', PageLayout, {}, { - 'default': () => render`${maybeRenderHead(result)}
hello world
`, - 'head': () => render` - ${renderComponent(result, 'Fragment', Fragment, {slot: 'head'}, { - 'default': () => render`` - })} - ` - })}`; + return render`${renderComponent( + result, + 'PageLayout', + PageLayout, + {}, + { + default: () => render`${maybeRenderHead(result)}
hello world
`, + head: () => render` + ${renderComponent( + result, + 'Fragment', + Fragment, + { slot: 'head' }, + { + default: () => render``, + } + )} + `, + } + )}`; }); const ctx = createRenderContext({ request: new Request('http://example.com/'), - links: [ - { name: 'link', props: {rel:'stylesheet', href:'/main.css'}, children: '' } - ] + links: [{ name: 'link', props: { rel: 'stylesheet', href: '/main.css' }, children: '' }], }); const PageModule = createAstroModule(Page); @@ -97,41 +119,63 @@ describe('core/render', () => { ${renderSlot(result, slots['default'])} `; - }) + }); const PageLayout = createComponent((result, _props, slots) => { - return render`${renderComponent(result, 'Layout', BaseLayout, {}, { - 'default': () => render` + return render`${renderComponent( + result, + 'Layout', + BaseLayout, + {}, + { + default: () => render` ${maybeRenderHead(result)}
${renderSlot(result, slots['default'])}
`, - 'head': () => render` - ${renderComponent(result, 'Fragment', Fragment, { slot: 'head' }, { - 'default': () => render`${renderSlot(result, slots['head'])}` - })} - ` - })} + head: () => render` + ${renderComponent( + result, + 'Fragment', + Fragment, + { slot: 'head' }, + { + default: () => render`${renderSlot(result, slots['head'])}`, + } + )} + `, + } + )} `; }); const Page = createComponent((result, _props) => { - return render`${renderComponent(result, 'PageLayout', PageLayout, {}, { - 'default': () => render`${maybeRenderHead(result)}
hello world
`, - 'head': () => render` - ${renderComponent(result, 'Fragment', Fragment, {slot: 'head'}, { - 'default': () => render`` - })} - ` - })}`; + return render`${renderComponent( + result, + 'PageLayout', + PageLayout, + {}, + { + default: () => render`${maybeRenderHead(result)}
hello world
`, + head: () => render` + ${renderComponent( + result, + 'Fragment', + Fragment, + { slot: 'head' }, + { + default: () => render``, + } + )} + `, + } + )}`; }); const ctx = createRenderContext({ request: new Request('http://example.com/'), - links: [ - { name: 'link', props: {rel:'stylesheet', href:'/main.css'}, children: '' } - ] + links: [{ name: 'link', props: { rel: 'stylesheet', href: '/main.css' }, children: '' }], }); const PageModule = createAstroModule(Page); @@ -147,26 +191,36 @@ describe('core/render', () => { it('Multi-level layouts and head injection, without any content in layouts', async () => { const BaseLayout = createComponent((result, _props, slots) => { return render`${renderSlot(result, slots['default'])}`; - }) + }); const PageLayout = createComponent((result, _props, slots) => { - return render`${renderComponent(result, 'Layout', BaseLayout, {}, { - 'default': () => render`${renderSlot(result, slots['default'])} `, - })} + return render`${renderComponent( + result, + 'Layout', + BaseLayout, + {}, + { + default: () => render`${renderSlot(result, slots['default'])} `, + } + )} `; }); const Page = createComponent((result, _props) => { - return render`${renderComponent(result, 'PageLayout', PageLayout, {}, { - 'default': () => render`${maybeRenderHead(result)}
hello world
`, - })}`; + return render`${renderComponent( + result, + 'PageLayout', + PageLayout, + {}, + { + default: () => render`${maybeRenderHead(result)}
hello world
`, + } + )}`; }); const ctx = createRenderContext({ request: new Request('http://example.com/'), - links: [ - { name: 'link', props: {rel:'stylesheet', href:'/main.css'}, children: '' } - ] + links: [{ name: 'link', props: { rel: 'stylesheet', href: '/main.css' }, children: '' }], }); const PageModule = createAstroModule(Page);