diff --git a/.changeset/eight-cameras-itch.md b/.changeset/eight-cameras-itch.md
new file mode 100644
index 000000000000..4499c5a46e27
--- /dev/null
+++ b/.changeset/eight-cameras-itch.md
@@ -0,0 +1,5 @@
+---
+'astro': patch
+---
+
+Fix head injection in body with slots.render() and head buffering
diff --git a/packages/astro/src/runtime/server/render/common.ts b/packages/astro/src/runtime/server/render/common.ts
index 6bcd72cc54d4..a33ed435d87f 100644
--- a/packages/astro/src/runtime/server/render/common.ts
+++ b/packages/astro/src/runtime/server/render/common.ts
@@ -72,13 +72,22 @@ export function stringifyChunk(result: SSRResult, chunk: string | SlotString | R
}
// If the current scope is with Astro.slots.render()
- case ScopeFlags.Slot: {
+ case ScopeFlags.Slot:
+ case ScopeFlags.Slot | ScopeFlags.HeadBuffer: {
if (hasScopeFlag(result, ScopeFlags.RenderSlot)) {
return '';
}
break;
}
+ // Nested element inside of JSX during head buffering phase
+ case ScopeFlags.HeadBuffer: {
+ if(hasScopeFlag(result, ScopeFlags.JSX | ScopeFlags.HeadBuffer)) {
+ return "";
+ }
+ break;
+ }
+
// Astro.slots.render() should never render head content.
case ScopeFlags.RenderSlot | ScopeFlags.Astro:
case ScopeFlags.RenderSlot | ScopeFlags.Astro | ScopeFlags.JSX:
diff --git a/packages/astro/test/fixtures/head-injection/src/components/UsesSlotRender.astro b/packages/astro/test/fixtures/head-injection/src/components/UsesSlotRender.astro
new file mode 100644
index 000000000000..35d127cd5ef2
--- /dev/null
+++ b/packages/astro/test/fixtures/head-injection/src/components/UsesSlotRender.astro
@@ -0,0 +1,7 @@
+---
+import SlotRenderComponent from "./SlotRenderComponent.astro";
+---
+
+
+
Paragraph.
+
diff --git a/packages/astro/test/fixtures/head-injection/src/pages/with-render-slot-in-head-buffer.astro b/packages/astro/test/fixtures/head-injection/src/pages/with-render-slot-in-head-buffer.astro
new file mode 100644
index 000000000000..5cd5c6261b5b
--- /dev/null
+++ b/packages/astro/test/fixtures/head-injection/src/pages/with-render-slot-in-head-buffer.astro
@@ -0,0 +1,7 @@
+---
+import Layout from "../components/Layout.astro";
+import UsesSlotRender from "../components/UsesSlotRender.astro"
+---
+
+
+
diff --git a/packages/astro/test/head-injection.test.js b/packages/astro/test/head-injection.test.js
index d06a6eed0f87..d86272712c89 100644
--- a/packages/astro/test/head-injection.test.js
+++ b/packages/astro/test/head-injection.test.js
@@ -50,6 +50,14 @@ describe('Head injection', () => {
expect($('head link[rel=stylesheet]')).to.have.a.lengthOf(2);
expect($('body link[rel=stylesheet]')).to.have.a.lengthOf(0);
});
+
+ it('Using slots in Astro.slots.render() inside head buffering', async () => {
+ const html = await fixture.readFile('/with-render-slot-in-head-buffer/index.html');
+ const $ = cheerio.load(html);
+
+ expect($('head link[rel=stylesheet]')).to.have.a.lengthOf(2);
+ expect($('body link[rel=stylesheet]')).to.have.a.lengthOf(0);
+ });
});
});
});
diff --git a/packages/integrations/mdx/test/css-head-mdx.test.js b/packages/integrations/mdx/test/css-head-mdx.test.js
index bb2c7c0effe5..781e4d62d51d 100644
--- a/packages/integrations/mdx/test/css-head-mdx.test.js
+++ b/packages/integrations/mdx/test/css-head-mdx.test.js
@@ -69,5 +69,17 @@ describe('Head injection w/ MDX', () => {
const bodyLinks = $('body link[rel=stylesheet]');
expect(bodyLinks).to.have.a.lengthOf(0);
});
+
+ it('JSX component rendering Astro children within head buffering phase', async () => {
+ const html = await fixture.readFile('/posts/using-component/index.html');
+ // Using cheerio here because linkedom doesn't support head tag injection
+ const $ = cheerio.load(html);
+
+ const headLinks = $('head link[rel=stylesheet]');
+ expect(headLinks).to.have.a.lengthOf(1);
+
+ const bodyLinks = $('body link[rel=stylesheet]');
+ expect(bodyLinks).to.have.a.lengthOf(0);
+ });
});
});
diff --git a/packages/integrations/mdx/test/fixtures/css-head-mdx/src/components/BaseHead.astro b/packages/integrations/mdx/test/fixtures/css-head-mdx/src/components/BaseHead.astro
new file mode 100644
index 000000000000..19f517789607
--- /dev/null
+++ b/packages/integrations/mdx/test/fixtures/css-head-mdx/src/components/BaseHead.astro
@@ -0,0 +1,11 @@
+---
+const { title } = Astro.props;
+---
+
+
+
+
+
{title}
+
diff --git a/packages/integrations/mdx/test/fixtures/css-head-mdx/src/components/GenericComponent.astro b/packages/integrations/mdx/test/fixtures/css-head-mdx/src/components/GenericComponent.astro
new file mode 100644
index 000000000000..ebcd3ff35944
--- /dev/null
+++ b/packages/integrations/mdx/test/fixtures/css-head-mdx/src/components/GenericComponent.astro
@@ -0,0 +1 @@
+just a generic component
diff --git a/packages/integrations/mdx/test/fixtures/css-head-mdx/src/components/MDXWrapper.astro b/packages/integrations/mdx/test/fixtures/css-head-mdx/src/components/MDXWrapper.astro
new file mode 100644
index 000000000000..fbd530e1462e
--- /dev/null
+++ b/packages/integrations/mdx/test/fixtures/css-head-mdx/src/components/MDXWrapper.astro
@@ -0,0 +1,9 @@
+---
+import Component from "./GenericComponent.astro";
+---
+
+
+
+
+
+
diff --git a/packages/integrations/mdx/test/fixtures/css-head-mdx/src/content/posts/using-component.mdx b/packages/integrations/mdx/test/fixtures/css-head-mdx/src/content/posts/using-component.mdx
new file mode 100644
index 000000000000..fa550fb041f3
--- /dev/null
+++ b/packages/integrations/mdx/test/fixtures/css-head-mdx/src/content/posts/using-component.mdx
@@ -0,0 +1,13 @@
+---
+title: testing
+---
+import MDXWrapper from "../../components/MDXWrapper.astro";
+
+
+