diff options
author | 2023-04-06 18:33:47 -0400 | |
---|---|---|
committer | 2023-04-06 18:33:47 -0400 | |
commit | a98f6f418c92261a06ef79624a8c86e288c21eab (patch) | |
tree | cd069e8afd2b41ae037f8cd1d23dbfb435f9b1c4 | |
parent | e0ee7765d0159913aca5fd1bc83c953be3afcf2e (diff) | |
download | astro-a98f6f418c92261a06ef79624a8c86e288c21eab.tar.gz astro-a98f6f418c92261a06ef79624a8c86e288c21eab.tar.zst astro-a98f6f418c92261a06ef79624a8c86e288c21eab.zip |
Prevent body head content injection in MDX when using layout (#6779)
7 files changed, 63 insertions, 0 deletions
diff --git a/.changeset/smart-files-flow.md b/.changeset/smart-files-flow.md new file mode 100644 index 000000000..e0f9020ab --- /dev/null +++ b/.changeset/smart-files-flow.md @@ -0,0 +1,6 @@ +--- +'astro': patch +'@astrojs/mdx': patch +--- + +Prevent body head content injection in MDX when using layout diff --git a/packages/astro/src/runtime/server/render/page.ts b/packages/astro/src/runtime/server/render/page.ts index ac05abb88..c8e07a4e7 100644 --- a/packages/astro/src/runtime/server/render/page.ts +++ b/packages/astro/src/runtime/server/render/page.ts @@ -76,6 +76,8 @@ export async function renderPage( route?: RouteData | undefined ): Promise<Response> { if (!isAstroComponentFactory(componentFactory)) { + result._metadata.headInTree = + result.componentMetadata.get((componentFactory as any).moduleId)?.containsHead ?? false; const pageProps: Record<string, any> = { ...(props ?? {}), 'server:root': true }; let output: ComponentIterable; diff --git a/packages/integrations/mdx/src/index.ts b/packages/integrations/mdx/src/index.ts index 195b678b8..e284dd4c3 100644 --- a/packages/integrations/mdx/src/index.ts +++ b/packages/integrations/mdx/src/index.ts @@ -160,6 +160,7 @@ export default function mdx(partialMdxOptions: Partial<MdxOptions> = {}): AstroI // Ensures styles and scripts are injected into a `<head>` // When a layout is not applied code += `\nContent[Symbol.for('astro.needsHeadRendering')] = !Boolean(frontmatter.layout);`; + code += `\nContent.moduleId = ${JSON.stringify(id)};` if (command === 'dev') { // TODO: decline HMR updates until we have a stable approach diff --git a/packages/integrations/mdx/test/css-head-mdx.test.js b/packages/integrations/mdx/test/css-head-mdx.test.js index 781e4d62d..f4ece38d9 100644 --- a/packages/integrations/mdx/test/css-head-mdx.test.js +++ b/packages/integrations/mdx/test/css-head-mdx.test.js @@ -81,5 +81,18 @@ describe('Head injection w/ MDX', () => { const bodyLinks = $('body link[rel=stylesheet]'); expect(bodyLinks).to.have.a.lengthOf(0); }); + + it('Injection caused by delayed slots', async () => { + const html = await fixture.readFile('/componentwithtext/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/BasicBlock.astro b/packages/integrations/mdx/test/fixtures/css-head-mdx/src/components/BasicBlock.astro new file mode 100644 index 000000000..95660b6b9 --- /dev/null +++ b/packages/integrations/mdx/test/fixtures/css-head-mdx/src/components/BasicBlock.astro @@ -0,0 +1,14 @@ +--- +const { inlineStyle, title, display = 'horizontal' } = Astro.props; +const lineEnding = display === 'horizontal' ? ', ' : '<br>'; +--- + +{title && <h2 set:html={title} />} +<address style={inlineStyle}> + <span class="name">some name</span><Fragment set:html={lineEnding} /> + line 1<Fragment set:html={lineEnding} /> + line 2<Fragment set:html={lineEnding} /> + line 3<Fragment set:html={lineEnding} /> + line 4<Fragment set:html={lineEnding} /> + line 5 +</address> diff --git a/packages/integrations/mdx/test/fixtures/css-head-mdx/src/layouts/DocumentLayout.astro b/packages/integrations/mdx/test/fixtures/css-head-mdx/src/layouts/DocumentLayout.astro new file mode 100644 index 000000000..a09a1c218 --- /dev/null +++ b/packages/integrations/mdx/test/fixtures/css-head-mdx/src/layouts/DocumentLayout.astro @@ -0,0 +1,15 @@ +--- +// Extend the BaseLayout, adding space for a banner at the top of the page +// after the main heading, then the detail for the actual page +import ContentLayout from './ContentLayout.astro'; +const { frontmatter } = Astro.props; +--- + +<ContentLayout> + <div class="content-container"> + <article id="main-content" class="pad-z5 flow"> + <h1 set:html={frontmatter.pageHeading ? frontmatter.pageHeading : frontmatter.title} /> + <slot /> + </article> + </div> +</ContentLayout> diff --git a/packages/integrations/mdx/test/fixtures/css-head-mdx/src/pages/componentwithtext.mdx b/packages/integrations/mdx/test/fixtures/css-head-mdx/src/pages/componentwithtext.mdx new file mode 100644 index 000000000..2c6f3032f --- /dev/null +++ b/packages/integrations/mdx/test/fixtures/css-head-mdx/src/pages/componentwithtext.mdx @@ -0,0 +1,12 @@ +--- +layout: ../layouts/DocumentLayout.astro +title: blah blah +--- + +import BasicBlock from '../components/BasicBlock.astro'; + +Some text for a paragraph. + +<BasicBlock title="This causes css in wrong place." /> + +Some other text. |