From 963ff338c081fe3d445e8f475d1f305194fd63d3 Mon Sep 17 00:00:00 2001 From: Matthew Phillips Date: Mon, 6 Feb 2023 09:44:42 -0500 Subject: [PATCH 01/11] Add additional scoping for head buffering --- packages/astro/src/content/internal.ts | 3 +- packages/astro/src/runtime/server/index.ts | 1 + packages/astro/src/runtime/server/jsx.ts | 7 +++-- .../runtime/server/render/astro/factory.ts | 6 ++-- .../runtime/server/render/astro/instance.ts | 2 ++ .../astro/src/runtime/server/render/head.ts | 8 +++-- .../astro/src/runtime/server/render/index.ts | 1 + .../astro/src/runtime/server/render/page.ts | 3 ++ .../astro/src/runtime/server/render/scope.ts | 31 +++++++++++++++++++ .../astro/src/runtime/server/render/slot.ts | 7 +++-- .../astro/src/runtime/server/render/util.ts | 6 ---- .../mdx/test/css-head-mdx.test.js | 8 +++++ .../src/components/SmallCaps.astro | 3 ++ .../css-head-mdx/src/content/posts/test.mdx | 5 +++ .../src/layouts/ContentLayout.astro | 24 ++++++++++++++ .../css-head-mdx/src/pages/posts/[post].astro | 18 +++++++++++ .../css-head-mdx/src/styles/global.css | 3 ++ 17 files changed, 118 insertions(+), 18 deletions(-) create mode 100644 packages/astro/src/runtime/server/render/scope.ts create mode 100644 packages/integrations/mdx/test/fixtures/css-head-mdx/src/components/SmallCaps.astro create mode 100644 packages/integrations/mdx/test/fixtures/css-head-mdx/src/content/posts/test.mdx create mode 100644 packages/integrations/mdx/test/fixtures/css-head-mdx/src/layouts/ContentLayout.astro create mode 100644 packages/integrations/mdx/test/fixtures/css-head-mdx/src/pages/posts/[post].astro create mode 100644 packages/integrations/mdx/test/fixtures/css-head-mdx/src/styles/global.css diff --git a/packages/astro/src/content/internal.ts b/packages/astro/src/content/internal.ts index 04280166feb3..ebfb971be44a 100644 --- a/packages/astro/src/content/internal.ts +++ b/packages/astro/src/content/internal.ts @@ -4,6 +4,7 @@ import { prependForwardSlash } from '../core/path.js'; import { createComponent, createHeadAndContent, + createScopedResult, renderComponent, renderScriptElement, renderStyleElement, @@ -169,7 +170,7 @@ async function render({ return createHeadAndContent( unescapeHTML(styles + links + scripts) as any, - renderTemplate`${renderComponent(result, 'Content', mod.Content, props, slots)}` + renderTemplate`${renderComponent(createScopedResult(result), 'Content', mod.Content, props, slots)}` ); }, propagation: 'self', diff --git a/packages/astro/src/runtime/server/index.ts b/packages/astro/src/runtime/server/index.ts index ccdfd5e1968f..b548b029e117 100644 --- a/packages/astro/src/runtime/server/index.ts +++ b/packages/astro/src/runtime/server/index.ts @@ -6,6 +6,7 @@ export { renderJSX } from './jsx.js'; export { addAttribute, createHeadAndContent, + createScopedResult, defineScriptVars, Fragment, maybeRenderHead, diff --git a/packages/astro/src/runtime/server/jsx.ts b/packages/astro/src/runtime/server/jsx.ts index 8b81a641ea35..665e4afec8fb 100644 --- a/packages/astro/src/runtime/server/jsx.ts +++ b/packages/astro/src/runtime/server/jsx.ts @@ -12,7 +12,7 @@ import { } from './index.js'; import { HTMLParts } from './render/common.js'; import type { ComponentIterable } from './render/component'; -import { ScopeFlags } from './render/util.js'; +import { createScopedResult, ScopeFlags } from './render/scope.js'; const ClientOnlyPlaceholder = 'astro-client-only'; @@ -95,8 +95,9 @@ Did you forget to import the component or is it possible there is a typo?`); props[key] = value; } } - result.scope |= ScopeFlags.JSX; - return markHTMLString(await renderToString(result, vnode.type as any, props, slots)); + const scoped = createScopedResult(result, ScopeFlags.JSX); + const html = markHTMLString(await renderToString(scoped, vnode.type as any, props, slots)); + return html; } case !vnode.type && (vnode.type as any) !== 0: return ''; diff --git a/packages/astro/src/runtime/server/render/astro/factory.ts b/packages/astro/src/runtime/server/render/astro/factory.ts index 1f85fe45c72f..7f5b912472ef 100644 --- a/packages/astro/src/runtime/server/render/astro/factory.ts +++ b/packages/astro/src/runtime/server/render/astro/factory.ts @@ -3,7 +3,7 @@ import type { HeadAndContent } from './head-and-content'; import type { RenderTemplateResult } from './render-template'; import { HTMLParts } from '../common.js'; -import { ScopeFlags } from '../util.js'; +import { addScopeFlag, createScopedResult, ScopeFlags } from '../scope.js'; import { isHeadAndContent } from './head-and-content.js'; import { renderAstroTemplateResult } from './render-template.js'; @@ -28,8 +28,8 @@ export async function renderToString( props: any, children: any ): Promise { - result.scope |= ScopeFlags.Astro; - const factoryResult = await componentFactory(result, props, children); + const scoped = createScopedResult(result, ScopeFlags.Astro); + const factoryResult = await componentFactory(scoped, props, children); if (factoryResult instanceof Response) { const response = factoryResult; diff --git a/packages/astro/src/runtime/server/render/astro/instance.ts b/packages/astro/src/runtime/server/render/astro/instance.ts index d290abcc1640..c330b1319f90 100644 --- a/packages/astro/src/runtime/server/render/astro/instance.ts +++ b/packages/astro/src/runtime/server/render/astro/instance.ts @@ -7,6 +7,7 @@ import { isPromise } from '../../util.js'; import { renderChild } from '../any.js'; import { isAPropagatingComponent } from './factory.js'; import { isHeadAndContent } from './head-and-content.js'; +import { addScopeFlag, removeScopeFlag, ScopeFlags } from '../scope.js'; type ComponentProps = Record; type ComponentSlotValue = () => ReturnType; @@ -33,6 +34,7 @@ export class AstroComponentInstance { this.props = props; this.factory = factory; this.slotValues = {}; + addScopeFlag(result, ScopeFlags.Slot); for (const name in slots) { this.slotValues[name] = slots[name](); } diff --git a/packages/astro/src/runtime/server/render/head.ts b/packages/astro/src/runtime/server/render/head.ts index 0f39fe2192a8..e3a4ae9aa9f7 100644 --- a/packages/astro/src/runtime/server/render/head.ts +++ b/packages/astro/src/runtime/server/render/head.ts @@ -1,7 +1,8 @@ import type { SSRResult } from '../../../@types/astro'; import { markHTMLString } from '../escape.js'; -import { renderElement, ScopeFlags } from './util.js'; +import { renderElement } from './util.js'; +import { ScopeFlags } from './scope.js'; // Filter out duplicate elements in our set const uniqueElements = (item: any, index: number, all: any[]) => { @@ -55,10 +56,13 @@ export function* maybeRenderHead(result: SSRResult) { // Don't render the head inside of a JSX component that's inside of an Astro component // as the Astro component will be the one to render the head. switch (result.scope) { - case ScopeFlags.JSX | ScopeFlags.Slot | ScopeFlags.Astro: { + case ScopeFlags.JSX | ScopeFlags.Slot | ScopeFlags.Astro: + // TODO Explain + case ScopeFlags.JSX | ScopeFlags.Astro | ScopeFlags.HeadBuffer: { return; } } + // This is an instruction informing the page rendering that head might need rendering. // This allows the page to deduplicate head injections. diff --git a/packages/astro/src/runtime/server/render/index.ts b/packages/astro/src/runtime/server/render/index.ts index 012b421f5784..1ec38ee6e598 100644 --- a/packages/astro/src/runtime/server/render/index.ts +++ b/packages/astro/src/runtime/server/render/index.ts @@ -16,6 +16,7 @@ export { renderHTMLElement } from './dom.js'; export { maybeRenderHead, renderHead } from './head.js'; export { renderPage } from './page.js'; export { renderSlot } from './slot.js'; +export { createScopedResult } from './scope.js'; export { renderScriptElement, renderStyleElement, renderUniqueStylesheet } from './tags.js'; export type { RenderInstruction } from './types'; export { addAttribute, defineScriptVars, voidElementNames } from './util.js'; diff --git a/packages/astro/src/runtime/server/render/page.ts b/packages/astro/src/runtime/server/render/page.ts index b949019d6967..8ae2969f5841 100644 --- a/packages/astro/src/runtime/server/render/page.ts +++ b/packages/astro/src/runtime/server/render/page.ts @@ -15,6 +15,7 @@ import { import { chunkToByteArray, encoder, HTMLParts } from './common.js'; import { renderComponent } from './component.js'; import { maybeRenderHead } from './head.js'; +import { addScopeFlag, removeScopeFlag, ScopeFlags } from './scope.js'; const needsHeadRenderingSymbol = Symbol.for('astro.needsHeadRendering'); @@ -55,6 +56,7 @@ async function iterableToHTMLBytes( // to be propagated up. async function bufferHeadContent(result: SSRResult) { const iterator = result.propagators.values(); + addScopeFlag(result, ScopeFlags.HeadBuffer); while (true) { const { value, done } = iterator.next(); if (done) { @@ -65,6 +67,7 @@ async function bufferHeadContent(result: SSRResult) { result.extraHead.push(returnValue.head); } } + removeScopeFlag(result, ScopeFlags.HeadBuffer); } export async function renderPage( diff --git a/packages/astro/src/runtime/server/render/scope.ts b/packages/astro/src/runtime/server/render/scope.ts new file mode 100644 index 000000000000..458ed19a33dc --- /dev/null +++ b/packages/astro/src/runtime/server/render/scope.ts @@ -0,0 +1,31 @@ +import type { SSRResult } from '../../../@types/astro'; + +export const ScopeFlags = { + Astro: 1 << 0, // 1 + JSX: 1 << 1, // 2 + Slot: 1 << 2, // 4 + HeadBuffer: 1 << 3, // 8 +} as const; + +type ScopeFlagValues = (typeof ScopeFlags)[keyof typeof ScopeFlags]; + +export function addScopeFlag(result: SSRResult, flag: ScopeFlagValues) { + result.scope |= flag; +} + +export function removeScopeFlag(result: SSRResult, flag: ScopeFlagValues) { + result.scope &= ~flag; +} + +export function createScopedResult(result: SSRResult, flag?: ScopeFlagValues): SSRResult { + const scopedResult = Object.create(result, { + scope: { + writable: true, + value: result.scope + } + }); + if(flag != null) { + addScopeFlag(scopedResult, flag); + } + return scopedResult; +} diff --git a/packages/astro/src/runtime/server/render/slot.ts b/packages/astro/src/runtime/server/render/slot.ts index 32d0a2dc1299..c119bea8f5d7 100644 --- a/packages/astro/src/runtime/server/render/slot.ts +++ b/packages/astro/src/runtime/server/render/slot.ts @@ -3,7 +3,7 @@ import type { RenderInstruction } from './types.js'; import { HTMLString, markHTMLString } from '../escape.js'; import { renderChild } from './any.js'; -import { ScopeFlags } from './util.js'; +import { ScopeFlags, addScopeFlag, removeScopeFlag } from './scope.js'; const slotString = Symbol.for('astro:slot-string'); @@ -27,7 +27,7 @@ export async function renderSlot( fallback?: any ): Promise { if (slotted) { - result.scope |= ScopeFlags.Slot; + addScopeFlag(result, ScopeFlags.Slot); let iterator = renderChild(slotted); let content = ''; let instructions: null | RenderInstruction[] = null; @@ -42,7 +42,8 @@ export async function renderSlot( } } // Remove the flag since we are now outside of the scope. - result.scope &= ~ScopeFlags.Slot; + removeScopeFlag(result, ScopeFlags.Slot); + return markHTMLString(new SlotString(content, instructions)); } return fallback; diff --git a/packages/astro/src/runtime/server/render/util.ts b/packages/astro/src/runtime/server/render/util.ts index 7e5ca9a5d160..a95ef16f8722 100644 --- a/packages/astro/src/runtime/server/render/util.ts +++ b/packages/astro/src/runtime/server/render/util.ts @@ -128,9 +128,3 @@ export function renderElement( } return `<${name}${internalSpreadAttributes(props, shouldEscape)}>${children}`; } - -export const ScopeFlags = { - Astro: 1 << 0, - JSX: 1 << 1, - Slot: 1 << 2, -}; diff --git a/packages/integrations/mdx/test/css-head-mdx.test.js b/packages/integrations/mdx/test/css-head-mdx.test.js index 2b1dcdfe7bcd..0c4afda1fc50 100644 --- a/packages/integrations/mdx/test/css-head-mdx.test.js +++ b/packages/integrations/mdx/test/css-head-mdx.test.js @@ -29,5 +29,13 @@ describe('Head injection w/ MDX', () => { const scripts = document.querySelectorAll('head script[type=module]'); expect(scripts).to.have.a.lengthOf(1); }); + + it('injects into the head for content collections', async () => { + const html = await fixture.readFile('/posts/test/index.html'); + const { document } = parseHTML(html); + + const links = document.querySelectorAll('head link[rel=stylesheet]'); + expect(links).to.have.a.lengthOf(1); + }); }); }); diff --git a/packages/integrations/mdx/test/fixtures/css-head-mdx/src/components/SmallCaps.astro b/packages/integrations/mdx/test/fixtures/css-head-mdx/src/components/SmallCaps.astro new file mode 100644 index 000000000000..a0bd6e1f1501 --- /dev/null +++ b/packages/integrations/mdx/test/fixtures/css-head-mdx/src/components/SmallCaps.astro @@ -0,0 +1,3 @@ +--- +--- + diff --git a/packages/integrations/mdx/test/fixtures/css-head-mdx/src/content/posts/test.mdx b/packages/integrations/mdx/test/fixtures/css-head-mdx/src/content/posts/test.mdx new file mode 100644 index 000000000000..0bb1153cab7c --- /dev/null +++ b/packages/integrations/mdx/test/fixtures/css-head-mdx/src/content/posts/test.mdx @@ -0,0 +1,5 @@ +--- +title: Testing +--- + +A test file diff --git a/packages/integrations/mdx/test/fixtures/css-head-mdx/src/layouts/ContentLayout.astro b/packages/integrations/mdx/test/fixtures/css-head-mdx/src/layouts/ContentLayout.astro new file mode 100644 index 000000000000..7b234e86859a --- /dev/null +++ b/packages/integrations/mdx/test/fixtures/css-head-mdx/src/layouts/ContentLayout.astro @@ -0,0 +1,24 @@ +--- +export interface Props { + title: string; +} + +const { title } = Astro.props; +--- + + + + + + + + + {title} + + + + + + diff --git a/packages/integrations/mdx/test/fixtures/css-head-mdx/src/pages/posts/[post].astro b/packages/integrations/mdx/test/fixtures/css-head-mdx/src/pages/posts/[post].astro new file mode 100644 index 000000000000..7d6ca0ca4d37 --- /dev/null +++ b/packages/integrations/mdx/test/fixtures/css-head-mdx/src/pages/posts/[post].astro @@ -0,0 +1,18 @@ +--- +import { getCollection } from 'astro:content'; +import Layout from '../../layouts/ContentLayout.astro'; +import SmallCaps from '../../components/SmallCaps.astro'; + +export async function getStaticPaths() { + const entries = await getCollection('posts'); + return entries.map(entry => { + return {params: { post: entry.slug }, props: { entry }, + }}); +} + +const { entry } = Astro.props; +const { Content } = await entry.render(); +--- + + + diff --git a/packages/integrations/mdx/test/fixtures/css-head-mdx/src/styles/global.css b/packages/integrations/mdx/test/fixtures/css-head-mdx/src/styles/global.css new file mode 100644 index 000000000000..e1450526f7a2 --- /dev/null +++ b/packages/integrations/mdx/test/fixtures/css-head-mdx/src/styles/global.css @@ -0,0 +1,3 @@ +html { + font-weight: bolder; +} From e27b5c5d2fdddb3703d482e797b2aa66c0b8d9a0 Mon Sep 17 00:00:00 2001 From: Matthew Phillips Date: Mon, 6 Feb 2023 11:28:28 -0500 Subject: [PATCH 02/11] Add test for direct usage of nested component --- .../integrations/mdx/test/css-head-mdx.test.js | 12 ++++++++++++ .../css-head-mdx/src/components/UsingMdx.astro | 10 ++++++++++ .../src/components/WithHoistedScripts.astro | 6 ++++++ .../css-head-mdx/src/content/blog/_styles.css | 3 +++ .../css-head-mdx/src/content/blog/using-mdx.mdx | 6 ++++++ .../src/pages/DirectContentUsage.astro | 17 +++++++++++++++++ 6 files changed, 54 insertions(+) create mode 100644 packages/integrations/mdx/test/fixtures/css-head-mdx/src/components/UsingMdx.astro create mode 100644 packages/integrations/mdx/test/fixtures/css-head-mdx/src/components/WithHoistedScripts.astro create mode 100644 packages/integrations/mdx/test/fixtures/css-head-mdx/src/content/blog/_styles.css create mode 100644 packages/integrations/mdx/test/fixtures/css-head-mdx/src/content/blog/using-mdx.mdx create mode 100644 packages/integrations/mdx/test/fixtures/css-head-mdx/src/pages/DirectContentUsage.astro diff --git a/packages/integrations/mdx/test/css-head-mdx.test.js b/packages/integrations/mdx/test/css-head-mdx.test.js index 0c4afda1fc50..f75892f7baba 100644 --- a/packages/integrations/mdx/test/css-head-mdx.test.js +++ b/packages/integrations/mdx/test/css-head-mdx.test.js @@ -37,5 +37,17 @@ describe('Head injection w/ MDX', () => { const links = document.querySelectorAll('head link[rel=stylesheet]'); expect(links).to.have.a.lengthOf(1); }); + + it.skip('injects content from a component using Content#render()', async () => { + const html = await fixture.readFile('/DirectContentUsage/index.html'); + console.log(html); + const { document } = parseHTML(html); + + const links = document.querySelectorAll('head link[rel=stylesheet]'); + expect(links).to.have.a.lengthOf(1); + + const scripts = document.querySelectorAll('head script[type=module]'); + expect(scripts).to.have.a.lengthOf(1); + }); }); }); diff --git a/packages/integrations/mdx/test/fixtures/css-head-mdx/src/components/UsingMdx.astro b/packages/integrations/mdx/test/fixtures/css-head-mdx/src/components/UsingMdx.astro new file mode 100644 index 000000000000..defbad800219 --- /dev/null +++ b/packages/integrations/mdx/test/fixtures/css-head-mdx/src/components/UsingMdx.astro @@ -0,0 +1,10 @@ +--- +import { getEntryBySlug } from 'astro:content'; + +const launchWeek = await getEntryBySlug('blog', 'using-mdx'); +const { Content } = await launchWeek.render(); + +debugger; +--- + + diff --git a/packages/integrations/mdx/test/fixtures/css-head-mdx/src/components/WithHoistedScripts.astro b/packages/integrations/mdx/test/fixtures/css-head-mdx/src/components/WithHoistedScripts.astro new file mode 100644 index 000000000000..0b8c4445f6fd --- /dev/null +++ b/packages/integrations/mdx/test/fixtures/css-head-mdx/src/components/WithHoistedScripts.astro @@ -0,0 +1,6 @@ +--- +--- + + diff --git a/packages/integrations/mdx/test/fixtures/css-head-mdx/src/content/blog/_styles.css b/packages/integrations/mdx/test/fixtures/css-head-mdx/src/content/blog/_styles.css new file mode 100644 index 000000000000..1379b29c06f0 --- /dev/null +++ b/packages/integrations/mdx/test/fixtures/css-head-mdx/src/content/blog/_styles.css @@ -0,0 +1,3 @@ +body { + color: red !important; +} diff --git a/packages/integrations/mdx/test/fixtures/css-head-mdx/src/content/blog/using-mdx.mdx b/packages/integrations/mdx/test/fixtures/css-head-mdx/src/content/blog/using-mdx.mdx new file mode 100644 index 000000000000..917fc3331288 --- /dev/null +++ b/packages/integrations/mdx/test/fixtures/css-head-mdx/src/content/blog/using-mdx.mdx @@ -0,0 +1,6 @@ +import './_styles.css'; +import WithHoistedScripts from '../../components/WithHoistedScripts.astro'; + +# Using mdx + + diff --git a/packages/integrations/mdx/test/fixtures/css-head-mdx/src/pages/DirectContentUsage.astro b/packages/integrations/mdx/test/fixtures/css-head-mdx/src/pages/DirectContentUsage.astro new file mode 100644 index 000000000000..cbf4295a7149 --- /dev/null +++ b/packages/integrations/mdx/test/fixtures/css-head-mdx/src/pages/DirectContentUsage.astro @@ -0,0 +1,17 @@ +--- +import UsingMdx from '../components/UsingMdx.astro' +--- + + + + + + + + Astro + + +

Astro

+ + + From 9bf34efd7ca8fdc40f5a1998cba472ca63d81eeb Mon Sep 17 00:00:00 2001 From: Matthew Phillips Date: Mon, 6 Feb 2023 12:03:24 -0500 Subject: [PATCH 03/11] Add special scoping for Astro.scopes.render() --- packages/astro/src/core/render/result.ts | 3 +- packages/astro/src/runtime/server/index.ts | 3 ++ .../astro/src/runtime/server/render/head.ts | 5 +++- .../astro/src/runtime/server/render/index.ts | 2 +- .../astro/src/runtime/server/render/scope.ts | 1 + .../mdx/test/css-head-mdx.test.js | 8 ++++++ .../test/fixtures/css-head-mdx/package.json | 10 +++++++ .../css-head-mdx/src/components/P.astro | 3 ++ .../src/components/UsingMdx.astro | 2 -- .../css-head-mdx/src/pages/remote.astro | 17 +++++++++++ pnpm-lock.yaml | 28 +++++++++++++++++++ 11 files changed, 77 insertions(+), 5 deletions(-) create mode 100644 packages/integrations/mdx/test/fixtures/css-head-mdx/package.json create mode 100644 packages/integrations/mdx/test/fixtures/css-head-mdx/src/components/P.astro create mode 100644 packages/integrations/mdx/test/fixtures/css-head-mdx/src/pages/remote.astro diff --git a/packages/astro/src/core/render/result.ts b/packages/astro/src/core/render/result.ts index 3a6b0bf964d6..ea360d8baff9 100644 --- a/packages/astro/src/core/render/result.ts +++ b/packages/astro/src/core/render/result.ts @@ -9,7 +9,7 @@ import type { SSRLoadedRenderer, SSRResult, } from '../../@types/astro'; -import { renderSlot, stringifyChunk } from '../../runtime/server/index.js'; +import { addScopeFlag, renderSlot, stringifyChunk, ScopeFlags } from '../../runtime/server/index.js'; import { renderJSX } from '../../runtime/server/jsx.js'; import { AstroCookies } from '../cookies/index.js'; import { AstroError, AstroErrorData } from '../errors/index.js'; @@ -89,6 +89,7 @@ class Slots { public async render(name: string, args: any[] = []) { if (!this.#slots || !this.has(name)) return; + addScopeFlag(this.#result, ScopeFlags.RenderSlot); if (!Array.isArray(args)) { warn( this.#loggingOpts, diff --git a/packages/astro/src/runtime/server/index.ts b/packages/astro/src/runtime/server/index.ts index b548b029e117..ba5c32d22c5a 100644 --- a/packages/astro/src/runtime/server/index.ts +++ b/packages/astro/src/runtime/server/index.ts @@ -5,11 +5,13 @@ export { escapeHTML, HTMLBytes, HTMLString, markHTMLString, unescapeHTML } from export { renderJSX } from './jsx.js'; export { addAttribute, + addScopeFlag, createHeadAndContent, createScopedResult, defineScriptVars, Fragment, maybeRenderHead, + removeScopeFlag, renderAstroTemplateResult as renderAstroComponent, renderComponent, renderComponentToIterable, @@ -24,6 +26,7 @@ export { renderTemplate, renderToString, renderUniqueStylesheet, + ScopeFlags, stringifyChunk, voidElementNames, } from './render/index.js'; diff --git a/packages/astro/src/runtime/server/render/head.ts b/packages/astro/src/runtime/server/render/head.ts index e3a4ae9aa9f7..ca4c17de362d 100644 --- a/packages/astro/src/runtime/server/render/head.ts +++ b/packages/astro/src/runtime/server/render/head.ts @@ -61,8 +61,11 @@ export function* maybeRenderHead(result: SSRResult) { case ScopeFlags.JSX | ScopeFlags.Astro | ScopeFlags.HeadBuffer: { return; } + case ScopeFlags.RenderSlot | ScopeFlags.Astro: + case ScopeFlags.RenderSlot | ScopeFlags.Astro | ScopeFlags.JSX: { + return; + } } - // This is an instruction informing the page rendering that head might need rendering. // This allows the page to deduplicate head injections. diff --git a/packages/astro/src/runtime/server/render/index.ts b/packages/astro/src/runtime/server/render/index.ts index 1ec38ee6e598..1686300ccb22 100644 --- a/packages/astro/src/runtime/server/render/index.ts +++ b/packages/astro/src/runtime/server/render/index.ts @@ -16,7 +16,7 @@ export { renderHTMLElement } from './dom.js'; export { maybeRenderHead, renderHead } from './head.js'; export { renderPage } from './page.js'; export { renderSlot } from './slot.js'; -export { createScopedResult } from './scope.js'; +export { createScopedResult, ScopeFlags, addScopeFlag, removeScopeFlag } from './scope.js'; export { renderScriptElement, renderStyleElement, renderUniqueStylesheet } from './tags.js'; export type { RenderInstruction } from './types'; export { addAttribute, defineScriptVars, voidElementNames } from './util.js'; diff --git a/packages/astro/src/runtime/server/render/scope.ts b/packages/astro/src/runtime/server/render/scope.ts index 458ed19a33dc..fb40d40f1675 100644 --- a/packages/astro/src/runtime/server/render/scope.ts +++ b/packages/astro/src/runtime/server/render/scope.ts @@ -5,6 +5,7 @@ export const ScopeFlags = { JSX: 1 << 1, // 2 Slot: 1 << 2, // 4 HeadBuffer: 1 << 3, // 8 + RenderSlot: 1 << 4, // 16 } as const; type ScopeFlagValues = (typeof ScopeFlags)[keyof typeof ScopeFlags]; diff --git a/packages/integrations/mdx/test/css-head-mdx.test.js b/packages/integrations/mdx/test/css-head-mdx.test.js index f75892f7baba..15c15ca55821 100644 --- a/packages/integrations/mdx/test/css-head-mdx.test.js +++ b/packages/integrations/mdx/test/css-head-mdx.test.js @@ -49,5 +49,13 @@ describe('Head injection w/ MDX', () => { const scripts = document.querySelectorAll('head script[type=module]'); expect(scripts).to.have.a.lengthOf(1); }); + + it('Using component using slots.render() API', async () => { + const html = await fixture.readFile('/remote/index.html'); + const { document } = parseHTML(html); + + const links = document.querySelectorAll('head link[rel=stylesheet]'); + expect(links).to.have.a.lengthOf(1); + }); }); }); diff --git a/packages/integrations/mdx/test/fixtures/css-head-mdx/package.json b/packages/integrations/mdx/test/fixtures/css-head-mdx/package.json new file mode 100644 index 000000000000..3c3c1e5a572d --- /dev/null +++ b/packages/integrations/mdx/test/fixtures/css-head-mdx/package.json @@ -0,0 +1,10 @@ +{ + "name": "@test/mdx-css-head-mdx", + "version": "0.0.0", + "private": true, + "dependencies": { + "astro": "workspace:*", + "@astrojs/mdx": "workspace:*", + "astro-remote": "0.2.3" + } +} diff --git a/packages/integrations/mdx/test/fixtures/css-head-mdx/src/components/P.astro b/packages/integrations/mdx/test/fixtures/css-head-mdx/src/components/P.astro new file mode 100644 index 000000000000..071e08a12d42 --- /dev/null +++ b/packages/integrations/mdx/test/fixtures/css-head-mdx/src/components/P.astro @@ -0,0 +1,3 @@ +

+ +

diff --git a/packages/integrations/mdx/test/fixtures/css-head-mdx/src/components/UsingMdx.astro b/packages/integrations/mdx/test/fixtures/css-head-mdx/src/components/UsingMdx.astro index defbad800219..1804388b0524 100644 --- a/packages/integrations/mdx/test/fixtures/css-head-mdx/src/components/UsingMdx.astro +++ b/packages/integrations/mdx/test/fixtures/css-head-mdx/src/components/UsingMdx.astro @@ -3,8 +3,6 @@ import { getEntryBySlug } from 'astro:content'; const launchWeek = await getEntryBySlug('blog', 'using-mdx'); const { Content } = await launchWeek.render(); - -debugger; --- diff --git a/packages/integrations/mdx/test/fixtures/css-head-mdx/src/pages/remote.astro b/packages/integrations/mdx/test/fixtures/css-head-mdx/src/pages/remote.astro new file mode 100644 index 000000000000..9a7b76a10283 --- /dev/null +++ b/packages/integrations/mdx/test/fixtures/css-head-mdx/src/pages/remote.astro @@ -0,0 +1,17 @@ +--- +import '../styles/global.css' +import Layout from '../layouts/One.astro'; +import Paragraph from '../components/P.astro'; +import { Markdown } from 'astro-remote' +--- + + +
+ + **Removing p component fixes the problem** + +
+
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8a83bba42ce7..8ffbfc99b3fb 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -2918,6 +2918,16 @@ importers: remark-toc: 8.0.1 vite: 4.1.1 + packages/integrations/mdx/test/fixtures/css-head-mdx: + specifiers: + '@astrojs/mdx': workspace:* + astro: workspace:* + astro-remote: 0.2.3 + dependencies: + '@astrojs/mdx': link:../../.. + astro: link:../../../../../astro + astro-remote: 0.2.3 + packages/integrations/mdx/test/fixtures/mdx-frontmatter-injection: specifiers: '@astrojs/mdx': workspace:* @@ -7837,6 +7847,14 @@ packages: astro: link:packages/astro dev: false + /astro-remote/0.2.3: + resolution: {integrity: sha512-vsY736YjWhpFgx4KUxCBdK0QJmOk0W61VQwO7v6qmfGdIxZyx6N7hBNou57w2mw68hQSe5AbRs602pi05GDMHw==} + dependencies: + he: 1.2.0 + marked: 4.2.12 + ultrahtml: 0.1.3 + dev: false + /async-sema/3.1.1: resolution: {integrity: sha512-tLRNUXati5MFePdAk8dw7Qt7DpxPB60ofAgn8WRhW6a2rcimZnYBP9oxHiv0OHy+Wz7kPMG+t4LGdt31+4EmGg==} dev: false @@ -11279,6 +11297,12 @@ packages: resolution: {integrity: sha512-Z1NL3Tb1M9wH4XESsCDEksWoKTdlUafKc4pt0GRwjUyXaCFZ+dc3g2erqB6zm3szA2IUSi7VnPI+o/9jnxh9hw==} dev: false + /marked/4.2.12: + resolution: {integrity: sha512-yr8hSKa3Fv4D3jdZmtMMPghgVt6TWbk86WQaWhDloQjRSQhMMYCAro7jP7VDJrjjdV8pxVxMssXS8B8Y5DZ5aw==} + engines: {node: '>= 12'} + hasBin: true + dev: false + /matcher/3.0.0: resolution: {integrity: sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng==} engines: {node: '>=10'} @@ -14735,6 +14759,10 @@ packages: resolution: {integrity: sha512-o0QVGuFg24FK765Qdd5kk0zU/U4dEsCtN/GSiwNI9i8xsSVtjIAOdTaVhLwZ1nrbWxFVMxNDDl+9fednsOMsBw==} dev: true + /ultrahtml/0.1.3: + resolution: {integrity: sha512-P24ulZdT9UKyQuKA1IApdAZ+F9lwruGvmKb4pG3+sMvR3CjN0pjawPnxuSABHQFB+XqnB35TVXzJPOBYjCv6Kw==} + dev: false + /unbox-primitive/1.0.2: resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} dependencies: From 50911a69427be53fdd8e6093a4213e0800dfe0d8 Mon Sep 17 00:00:00 2001 From: Matthew Phillips Date: Mon, 6 Feb 2023 15:02:41 -0500 Subject: [PATCH 04/11] Generate propagation map during the build --- packages/astro/src/core/app/index.ts | 1 + packages/astro/src/core/app/types.ts | 2 + packages/astro/src/core/build/generate.ts | 1 + packages/astro/src/core/build/internal.ts | 3 ++ .../astro/src/core/build/plugins/index.ts | 2 + .../src/core/build/plugins/plugin-ssr.ts | 1 + .../astro/src/runtime/server/render/head.ts | 7 +-- .../src/vite-plugin-head-propagation/index.ts | 53 ++++++++++++++++++- .../mdx/test/css-head-mdx.test.js | 5 +- 9 files changed, 68 insertions(+), 7 deletions(-) diff --git a/packages/astro/src/core/app/index.ts b/packages/astro/src/core/app/index.ts index 529a450f9531..615be50aa585 100644 --- a/packages/astro/src/core/app/index.ts +++ b/packages/astro/src/core/app/index.ts @@ -193,6 +193,7 @@ export class App { request, origin: url.origin, pathname, + propagation: this.#manifest.propagation, scripts, links, route: routeData, diff --git a/packages/astro/src/core/app/types.ts b/packages/astro/src/core/app/types.ts index 587c924b92de..1d30f3e385e1 100644 --- a/packages/astro/src/core/app/types.ts +++ b/packages/astro/src/core/app/types.ts @@ -4,6 +4,7 @@ import type { RouteData, SerializedRouteData, SSRLoadedRenderer, + SSRResult, } from '../../@types/astro'; export type ComponentPath = string; @@ -34,6 +35,7 @@ export interface SSRManifest { renderers: SSRLoadedRenderer[]; entryModules: Record; assets: Set; + propagation: SSRResult['propagation']; } export type SerializedSSRManifest = Omit & { diff --git a/packages/astro/src/core/build/generate.ts b/packages/astro/src/core/build/generate.ts index 1a708aab3765..f5f72dc5ab93 100644 --- a/packages/astro/src/core/build/generate.ts +++ b/packages/astro/src/core/build/generate.ts @@ -376,6 +376,7 @@ async function generatePath( origin, pathname, request: createRequest({ url, headers: new Headers(), logging, ssr }), + propagation: internals.propagation, scripts, links, route: pageData.route, diff --git a/packages/astro/src/core/build/internal.ts b/packages/astro/src/core/build/internal.ts index dc660f4949e0..87c817ad4bca 100644 --- a/packages/astro/src/core/build/internal.ts +++ b/packages/astro/src/core/build/internal.ts @@ -4,6 +4,7 @@ import type { PageBuildData, ViteID } from './types'; import { PageOptions } from '../../vite-plugin-astro/types'; import { prependForwardSlash, removeFileExtension } from '../path.js'; import { viteID } from '../util.js'; +import { SSRResult } from '../../@types/astro'; export interface BuildInternals { /** @@ -66,6 +67,7 @@ export interface BuildInternals { staticFiles: Set; // The SSR entry chunk. Kept in internals to share between ssr/client build steps ssrEntryChunk?: OutputChunk; + propagation: SSRResult['propagation']; } /** @@ -95,6 +97,7 @@ export function createBuildInternals(): BuildInternals { discoveredClientOnlyComponents: new Set(), discoveredScripts: new Set(), staticFiles: new Set(), + propagation: new Map(), }; } diff --git a/packages/astro/src/core/build/plugins/index.ts b/packages/astro/src/core/build/plugins/index.ts index cf0f9bf7c66d..9aa3e20b5801 100644 --- a/packages/astro/src/core/build/plugins/index.ts +++ b/packages/astro/src/core/build/plugins/index.ts @@ -8,6 +8,7 @@ import { pluginInternals } from './plugin-internals.js'; import { pluginPages } from './plugin-pages.js'; import { pluginPrerender } from './plugin-prerender.js'; import { pluginSSR } from './plugin-ssr.js'; +import { astroHeadPropagationBuildPlugin } from '../../../vite-plugin-head-propagation/index.js'; export function registerAllPlugins({ internals, options, register }: AstroBuildPluginContainer) { register(pluginAliasResolve(internals)); @@ -15,6 +16,7 @@ export function registerAllPlugins({ internals, options, register }: AstroBuildP register(pluginInternals(internals)); register(pluginPages(options, internals)); register(pluginCSS(options, internals)); + register(astroHeadPropagationBuildPlugin(options, internals)); register(pluginPrerender(options, internals)); register(astroConfigBuildPlugin(options, internals)); register(pluginHoistedScripts(options, internals)); diff --git a/packages/astro/src/core/build/plugins/plugin-ssr.ts b/packages/astro/src/core/build/plugins/plugin-ssr.ts index cfc58d71b345..7e62d5e3d7a8 100644 --- a/packages/astro/src/core/build/plugins/plugin-ssr.ts +++ b/packages/astro/src/core/build/plugins/plugin-ssr.ts @@ -211,6 +211,7 @@ function buildManifest( contentDir: getContentPaths(settings.config).contentDir, }, pageMap: null as any, + propagation: internals.propagation, renderers: [], entryModules, assets: staticFiles.map((s) => settings.config.base + s), diff --git a/packages/astro/src/runtime/server/render/head.ts b/packages/astro/src/runtime/server/render/head.ts index ca4c17de362d..e17e9b456116 100644 --- a/packages/astro/src/runtime/server/render/head.ts +++ b/packages/astro/src/runtime/server/render/head.ts @@ -57,12 +57,13 @@ export function* maybeRenderHead(result: SSRResult) { // as the Astro component will be the one to render the head. switch (result.scope) { case ScopeFlags.JSX | ScopeFlags.Slot | ScopeFlags.Astro: - // TODO Explain - case ScopeFlags.JSX | ScopeFlags.Astro | ScopeFlags.HeadBuffer: { + case ScopeFlags.JSX | ScopeFlags.Astro | ScopeFlags.HeadBuffer: + case ScopeFlags.JSX | ScopeFlags.Slot | ScopeFlags.Astro | ScopeFlags.HeadBuffer: { return; } case ScopeFlags.RenderSlot | ScopeFlags.Astro: - case ScopeFlags.RenderSlot | ScopeFlags.Astro | ScopeFlags.JSX: { + case ScopeFlags.RenderSlot | ScopeFlags.Astro | ScopeFlags.JSX: + case ScopeFlags.RenderSlot | ScopeFlags.Astro | ScopeFlags.JSX | ScopeFlags.HeadBuffer: { return; } } diff --git a/packages/astro/src/vite-plugin-head-propagation/index.ts b/packages/astro/src/vite-plugin-head-propagation/index.ts index ae8075e97e4f..eedefafd9ae9 100644 --- a/packages/astro/src/vite-plugin-head-propagation/index.ts +++ b/packages/astro/src/vite-plugin-head-propagation/index.ts @@ -1,8 +1,12 @@ import type { ModuleInfo } from 'rollup'; -import type { AstroSettings } from '../@types/astro'; +import type { AstroSettings, SSRResult } from '../@types/astro'; +import type { BuildInternals } from '../core/build/internal.js'; +import type { AstroBuildPlugin } from '../core/build/plugin.js'; +import type { StaticBuildOptions } from '../core/build/types'; import * as vite from 'vite'; import { getAstroMetadata } from '../vite-plugin-astro/index.js'; +import { walkParentInfos } from '../core/build/graph.js'; const injectExp = /^\/\/\s*astro-head-inject/; /** @@ -59,3 +63,50 @@ export default function configHeadPropagationVitePlugin({ }, }; } + +export function astroHeadPropagationBuildPlugin( + options: StaticBuildOptions, + internals: BuildInternals +): AstroBuildPlugin { + return { + build: 'ssr', + hooks: { + 'build:before'() { + const map: SSRResult['propagation'] = new Map(); + return { + vitePlugin: { + name: 'vite-plugin-head-propagation-build', + generateBundle(_opts, bundle) { + const appendPropagation = (info: ModuleInfo) => { + const astroMetadata = getAstroMetadata(info); + if(astroMetadata) { + astroMetadata.propagation = 'in-tree'; + map.set(info.id, 'in-tree'); + } + }; + + for(const [bundleId, output] of Object.entries(bundle)) { + if(output.type !== 'chunk') continue; + for(const [id, mod] of Object.entries(output.modules)) { + if (mod.code && injectExp.test(mod.code)) { + for(const [info] of walkParentInfos(id, this)) { + appendPropagation(info); + } + } + + const info = this.getModuleInfo(id); + if(info) { + appendPropagation(info); + } + } + } + + // Save the map to internals so it can be passed into SSR and generation + internals.propagation = map; + } + } + } + } + } + } +} diff --git a/packages/integrations/mdx/test/css-head-mdx.test.js b/packages/integrations/mdx/test/css-head-mdx.test.js index 15c15ca55821..c38f23701d34 100644 --- a/packages/integrations/mdx/test/css-head-mdx.test.js +++ b/packages/integrations/mdx/test/css-head-mdx.test.js @@ -38,16 +38,15 @@ describe('Head injection w/ MDX', () => { expect(links).to.have.a.lengthOf(1); }); - it.skip('injects content from a component using Content#render()', async () => { + it('injects content from a component using Content#render()', async () => { const html = await fixture.readFile('/DirectContentUsage/index.html'); - console.log(html); const { document } = parseHTML(html); const links = document.querySelectorAll('head link[rel=stylesheet]'); expect(links).to.have.a.lengthOf(1); const scripts = document.querySelectorAll('head script[type=module]'); - expect(scripts).to.have.a.lengthOf(1); + expect(scripts).to.have.a.lengthOf(2); }); it('Using component using slots.render() API', async () => { From bf3f2c7e997c8b9721b68cb87eebf4b506a1b4aa Mon Sep 17 00:00:00 2001 From: Matthew Phillips Date: Mon, 6 Feb 2023 15:28:38 -0500 Subject: [PATCH 05/11] Move to a maybeHead instruction --- packages/astro/package.json | 2 +- packages/astro/src/core/render/result.ts | 14 ++++++------ .../runtime/server/render/astro/instance.ts | 8 +++---- .../astro/src/runtime/server/render/common.ts | 22 +++++++++++++++++++ .../astro/src/runtime/server/render/head.ts | 17 +------------- .../astro/src/runtime/server/render/types.ts | 8 ++++++- pnpm-lock.yaml | 12 +++++----- 7 files changed, 48 insertions(+), 35 deletions(-) diff --git a/packages/astro/package.json b/packages/astro/package.json index 9b189a73bd86..26e028e056f8 100644 --- a/packages/astro/package.json +++ b/packages/astro/package.json @@ -99,7 +99,7 @@ "test:e2e:match": "playwright test -g" }, "dependencies": { - "@astrojs/compiler": "^1.0.1", + "@astrojs/compiler": "next--slot-pass", "@astrojs/language-server": "^0.28.3", "@astrojs/markdown-remark": "^2.0.1", "@astrojs/telemetry": "^2.0.0", diff --git a/packages/astro/src/core/render/result.ts b/packages/astro/src/core/render/result.ts index ea360d8baff9..8f0da82749ac 100644 --- a/packages/astro/src/core/render/result.ts +++ b/packages/astro/src/core/render/result.ts @@ -9,7 +9,7 @@ import type { SSRLoadedRenderer, SSRResult, } from '../../@types/astro'; -import { addScopeFlag, renderSlot, stringifyChunk, ScopeFlags } from '../../runtime/server/index.js'; +import { addScopeFlag, renderSlot, stringifyChunk, ScopeFlags, createScopedResult } from '../../runtime/server/index.js'; import { renderJSX } from '../../runtime/server/jsx.js'; import { AstroCookies } from '../cookies/index.js'; import { AstroError, AstroErrorData } from '../errors/index.js'; @@ -89,7 +89,7 @@ class Slots { public async render(name: string, args: any[] = []) { if (!this.#slots || !this.has(name)) return; - addScopeFlag(this.#result, ScopeFlags.RenderSlot); + const scoped = createScopedResult(this.#result, ScopeFlags.RenderSlot); if (!Array.isArray(args)) { warn( this.#loggingOpts, @@ -98,26 +98,26 @@ class Slots { ); } else if (args.length > 0) { const slotValue = this.#slots[name]; - const component = typeof slotValue === 'function' ? await slotValue() : await slotValue; + const component = typeof slotValue === 'function' ? await slotValue(scoped) : await slotValue; // Astro const expression = getFunctionExpression(component); if (expression) { const slot = expression(...args); - return await renderSlot(this.#result, slot).then((res) => + return await renderSlot(scoped, slot).then((res) => res != null ? String(res) : res ); } // JSX if (typeof component === 'function') { - return await renderJSX(this.#result, component(...args)).then((res) => + return await renderJSX(scoped, component(...args)).then((res) => res != null ? String(res) : res ); } } - const content = await renderSlot(this.#result, this.#slots[name]); - const outHTML = stringifyChunk(this.#result, content); + const content = await renderSlot(scoped, this.#slots[name]); + const outHTML = stringifyChunk(scoped, content); return outHTML; } diff --git a/packages/astro/src/runtime/server/render/astro/instance.ts b/packages/astro/src/runtime/server/render/astro/instance.ts index c330b1319f90..d99a26364339 100644 --- a/packages/astro/src/runtime/server/render/astro/instance.ts +++ b/packages/astro/src/runtime/server/render/astro/instance.ts @@ -7,10 +7,10 @@ import { isPromise } from '../../util.js'; import { renderChild } from '../any.js'; import { isAPropagatingComponent } from './factory.js'; import { isHeadAndContent } from './head-and-content.js'; -import { addScopeFlag, removeScopeFlag, ScopeFlags } from '../scope.js'; +import { createScopedResult, ScopeFlags } from '../scope.js'; type ComponentProps = Record; -type ComponentSlotValue = () => ReturnType; +type ComponentSlotValue = (result: SSRResult) => ReturnType; export type ComponentSlots = Record; export type ComponentSlotsWithValues = Record>; @@ -34,9 +34,9 @@ export class AstroComponentInstance { this.props = props; this.factory = factory; this.slotValues = {}; - addScopeFlag(result, ScopeFlags.Slot); + const scoped = createScopedResult(result, ScopeFlags.Slot); for (const name in slots) { - this.slotValues[name] = slots[name](); + this.slotValues[name] = slots[name](scoped); } } diff --git a/packages/astro/src/runtime/server/render/common.ts b/packages/astro/src/runtime/server/render/common.ts index def7dedd37e0..44946ef41174 100644 --- a/packages/astro/src/runtime/server/render/common.ts +++ b/packages/astro/src/runtime/server/render/common.ts @@ -10,6 +10,7 @@ import { } from '../scripts.js'; import { renderAllHeadContent } from './head.js'; import { isSlotString, type SlotString } from './slot.js'; +import { ScopeFlags } from './scope.js'; export const Fragment = Symbol.for('astro:fragment'); export const Renderer = Symbol.for('astro:renderer'); @@ -48,6 +49,27 @@ export function stringifyChunk(result: SSRResult, chunk: string | SlotString | R } return renderAllHeadContent(result); } + case 'maybe-head': { + const scope = instruction.scope; + switch (scope) { + // JSX with an Astro slot + case ScopeFlags.JSX | ScopeFlags.Astro: + case ScopeFlags.JSX | ScopeFlags.Slot | ScopeFlags.Astro: + case ScopeFlags.JSX | ScopeFlags.Astro | ScopeFlags.HeadBuffer: + case ScopeFlags.JSX | ScopeFlags.Slot | ScopeFlags.Astro | ScopeFlags.HeadBuffer: { + return ''; + } + + // Astro.slots.render('default') should never render head content. + case ScopeFlags.RenderSlot | ScopeFlags.Astro: + case ScopeFlags.RenderSlot | ScopeFlags.Astro | ScopeFlags.JSX: + case ScopeFlags.RenderSlot | ScopeFlags.Astro | ScopeFlags.JSX | ScopeFlags.HeadBuffer: { + return ''; + } + } + + return renderAllHeadContent(result); + } } } else { if (isSlotString(chunk as string)) { diff --git a/packages/astro/src/runtime/server/render/head.ts b/packages/astro/src/runtime/server/render/head.ts index e17e9b456116..4bd072ee7918 100644 --- a/packages/astro/src/runtime/server/render/head.ts +++ b/packages/astro/src/runtime/server/render/head.ts @@ -53,22 +53,7 @@ export function* maybeRenderHead(result: SSRResult) { return; } - // Don't render the head inside of a JSX component that's inside of an Astro component - // as the Astro component will be the one to render the head. - switch (result.scope) { - case ScopeFlags.JSX | ScopeFlags.Slot | ScopeFlags.Astro: - case ScopeFlags.JSX | ScopeFlags.Astro | ScopeFlags.HeadBuffer: - case ScopeFlags.JSX | ScopeFlags.Slot | ScopeFlags.Astro | ScopeFlags.HeadBuffer: { - return; - } - case ScopeFlags.RenderSlot | ScopeFlags.Astro: - case ScopeFlags.RenderSlot | ScopeFlags.Astro | ScopeFlags.JSX: - case ScopeFlags.RenderSlot | ScopeFlags.Astro | ScopeFlags.JSX | ScopeFlags.HeadBuffer: { - return; - } - } - // This is an instruction informing the page rendering that head might need rendering. // This allows the page to deduplicate head injections. - yield { type: 'head', result } as const; + yield { type: 'maybe-head', result, scope: result.scope } as const; } diff --git a/packages/astro/src/runtime/server/render/types.ts b/packages/astro/src/runtime/server/render/types.ts index 3aa3a16e3cef..a16ec034b32d 100644 --- a/packages/astro/src/runtime/server/render/types.ts +++ b/packages/astro/src/runtime/server/render/types.ts @@ -12,4 +12,10 @@ export type RenderHeadInstruction = { result: SSRResult; }; -export type RenderInstruction = RenderDirectiveInstruction | RenderHeadInstruction; +export type MaybeRenderHeadInstruction = { + type: 'maybe-head'; + result: SSRResult; + scope: number; +} + +export type RenderInstruction = RenderDirectiveInstruction | RenderHeadInstruction | MaybeRenderHeadInstruction; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8ffbfc99b3fb..bb4b28669089 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -375,7 +375,7 @@ importers: packages/astro: specifiers: - '@astrojs/compiler': ^1.0.1 + '@astrojs/compiler': next--slot-pass '@astrojs/language-server': ^0.28.3 '@astrojs/markdown-remark': ^2.0.1 '@astrojs/telemetry': ^2.0.0 @@ -465,7 +465,7 @@ importers: yargs-parser: ^21.0.1 zod: ^3.17.3 dependencies: - '@astrojs/compiler': 1.0.1 + '@astrojs/compiler': 0.0.0-slot-pass-20230206200849 '@astrojs/language-server': 0.28.3 '@astrojs/markdown-remark': link:../markdown/remark '@astrojs/telemetry': link:../telemetry @@ -3864,13 +3864,13 @@ packages: sisteransi: 1.0.5 dev: false + /@astrojs/compiler/0.0.0-slot-pass-20230206200849: + resolution: {integrity: sha512-1jl/e96lIO6+5GNDUb49bwAOh170uk7/VJ2PQTdBOw0Xwo0sK/JA8xC0z/ySsEuQ/5nJ8Lo7yZW1KPro9qIbPw==} + dev: false + /@astrojs/compiler/0.31.4: resolution: {integrity: sha512-6bBFeDTtPOn4jZaiD3p0f05MEGQL9pw2Zbfj546oFETNmjJFWO3nzHz6/m+P53calknCvyVzZ5YhoBLIvzn5iw==} - /@astrojs/compiler/1.0.1: - resolution: {integrity: sha512-77aacobLKcL98NmhK3OBS5EHIrX9gs1ckB/vGSIdkVZuB7u51V4jh05I6W0tSvG7/86tALv6QtHTRZ8rLhFTbQ==} - dev: false - /@astrojs/language-server/0.28.3: resolution: {integrity: sha512-fPovAX/X46eE2w03jNRMpQ7W9m2mAvNt4Ay65lD9wl1Z5vIQYxlg7Enp9qP225muTr4jSVB5QiLumFJmZMAaVA==} hasBin: true From 1181f3e200bd756ae6d9e1fff16eefd892e3311d Mon Sep 17 00:00:00 2001 From: Matthew Phillips Date: Mon, 6 Feb 2023 15:43:17 -0500 Subject: [PATCH 06/11] Properly serialize for SSR --- packages/astro/src/core/app/common.ts | 2 ++ packages/astro/src/core/app/types.ts | 4 +++- packages/astro/src/core/build/plugins/plugin-ssr.ts | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/astro/src/core/app/common.ts b/packages/astro/src/core/app/common.ts index 2da98f1c6022..4b14321762af 100644 --- a/packages/astro/src/core/app/common.ts +++ b/packages/astro/src/core/app/common.ts @@ -14,10 +14,12 @@ export function deserializeManifest(serializedManifest: SerializedSSRManifest): } const assets = new Set(serializedManifest.assets); + const propagation = new Map(serializedManifest.propagation); return { ...serializedManifest, assets, + propagation, routes, }; } diff --git a/packages/astro/src/core/app/types.ts b/packages/astro/src/core/app/types.ts index 1d30f3e385e1..cf85d0387bce 100644 --- a/packages/astro/src/core/app/types.ts +++ b/packages/astro/src/core/app/types.ts @@ -1,6 +1,7 @@ import type { MarkdownRenderingOptions } from '@astrojs/markdown-remark'; import type { ComponentInstance, + PropagationHint, RouteData, SerializedRouteData, SSRLoadedRenderer, @@ -38,9 +39,10 @@ export interface SSRManifest { propagation: SSRResult['propagation']; } -export type SerializedSSRManifest = Omit & { +export type SerializedSSRManifest = Omit & { routes: SerializedRouteInfo[]; assets: string[]; + propagation: readonly [string, PropagationHint][]; }; export type AdapterCreateExports = ( diff --git a/packages/astro/src/core/build/plugins/plugin-ssr.ts b/packages/astro/src/core/build/plugins/plugin-ssr.ts index 7e62d5e3d7a8..d4536b92c8ab 100644 --- a/packages/astro/src/core/build/plugins/plugin-ssr.ts +++ b/packages/astro/src/core/build/plugins/plugin-ssr.ts @@ -211,7 +211,7 @@ function buildManifest( contentDir: getContentPaths(settings.config).contentDir, }, pageMap: null as any, - propagation: internals.propagation, + propagation: Array.from(internals.propagation), renderers: [], entryModules, assets: staticFiles.map((s) => settings.config.base + s), From 56a7c040204d15b85074cce844d926786fd76dbc Mon Sep 17 00:00:00 2001 From: Matthew Phillips Date: Mon, 6 Feb 2023 15:46:10 -0500 Subject: [PATCH 07/11] More conservative scoping --- packages/astro/src/runtime/server/render/astro/instance.ts | 6 +++--- packages/astro/src/runtime/server/render/common.ts | 1 - packages/astro/src/runtime/server/render/page.ts | 7 +++---- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/packages/astro/src/runtime/server/render/astro/instance.ts b/packages/astro/src/runtime/server/render/astro/instance.ts index d99a26364339..45fdd6d50a02 100644 --- a/packages/astro/src/runtime/server/render/astro/instance.ts +++ b/packages/astro/src/runtime/server/render/astro/instance.ts @@ -40,14 +40,14 @@ export class AstroComponentInstance { } } - async init() { - this.returnValue = this.factory(this.result, this.props, this.slotValues); + async init(result: SSRResult) { + this.returnValue = this.factory(result, this.props, this.slotValues); return this.returnValue; } async *render() { if (this.returnValue === undefined) { - await this.init(); + await this.init(this.result); } let value: AstroFactoryReturnValue | undefined = this.returnValue; diff --git a/packages/astro/src/runtime/server/render/common.ts b/packages/astro/src/runtime/server/render/common.ts index 44946ef41174..604844b01b09 100644 --- a/packages/astro/src/runtime/server/render/common.ts +++ b/packages/astro/src/runtime/server/render/common.ts @@ -53,7 +53,6 @@ export function stringifyChunk(result: SSRResult, chunk: string | SlotString | R const scope = instruction.scope; switch (scope) { // JSX with an Astro slot - case ScopeFlags.JSX | ScopeFlags.Astro: case ScopeFlags.JSX | ScopeFlags.Slot | ScopeFlags.Astro: case ScopeFlags.JSX | ScopeFlags.Astro | ScopeFlags.HeadBuffer: case ScopeFlags.JSX | ScopeFlags.Slot | ScopeFlags.Astro | ScopeFlags.HeadBuffer: { diff --git a/packages/astro/src/runtime/server/render/page.ts b/packages/astro/src/runtime/server/render/page.ts index 8ae2969f5841..a9c1af77bb9c 100644 --- a/packages/astro/src/runtime/server/render/page.ts +++ b/packages/astro/src/runtime/server/render/page.ts @@ -15,7 +15,7 @@ import { import { chunkToByteArray, encoder, HTMLParts } from './common.js'; import { renderComponent } from './component.js'; import { maybeRenderHead } from './head.js'; -import { addScopeFlag, removeScopeFlag, ScopeFlags } from './scope.js'; +import { addScopeFlag, createScopedResult, removeScopeFlag, ScopeFlags } from './scope.js'; const needsHeadRenderingSymbol = Symbol.for('astro.needsHeadRendering'); @@ -56,18 +56,17 @@ async function iterableToHTMLBytes( // to be propagated up. async function bufferHeadContent(result: SSRResult) { const iterator = result.propagators.values(); - addScopeFlag(result, ScopeFlags.HeadBuffer); + const scoped = createScopedResult(result, ScopeFlags.HeadBuffer); while (true) { const { value, done } = iterator.next(); if (done) { break; } - const returnValue = await value.init(); + const returnValue = await value.init(scoped); if (isHeadAndContent(returnValue)) { result.extraHead.push(returnValue.head); } } - removeScopeFlag(result, ScopeFlags.HeadBuffer); } export async function renderPage( From 6e8169dd69812c4b43de1e65647c793ab2bd89cc Mon Sep 17 00:00:00 2001 From: Matthew Phillips Date: Mon, 6 Feb 2023 16:08:11 -0500 Subject: [PATCH 08/11] Maybe had should honor result._metadata.hasRenderedHead --- packages/astro/src/runtime/server/render/common.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/astro/src/runtime/server/render/common.ts b/packages/astro/src/runtime/server/render/common.ts index 604844b01b09..5283eaa12b14 100644 --- a/packages/astro/src/runtime/server/render/common.ts +++ b/packages/astro/src/runtime/server/render/common.ts @@ -50,6 +50,10 @@ export function stringifyChunk(result: SSRResult, chunk: string | SlotString | R return renderAllHeadContent(result); } case 'maybe-head': { + if (result._metadata.hasRenderedHead) { + return ''; + } + const scope = instruction.scope; switch (scope) { // JSX with an Astro slot From c44c8bf7e0b792c8fd7f13a17ce7b2a28abda46b Mon Sep 17 00:00:00 2001 From: Matthew Phillips Date: Mon, 6 Feb 2023 16:37:56 -0500 Subject: [PATCH 09/11] Properly type slots --- packages/astro/src/core/render/result.ts | 8 +++--- packages/astro/src/runtime/server/index.ts | 3 +-- .../src/runtime/server/render/astro/index.ts | 2 +- .../runtime/server/render/astro/instance.ts | 10 +++---- .../src/runtime/server/render/component.ts | 4 +-- .../astro/src/runtime/server/render/index.ts | 4 +-- .../astro/src/runtime/server/render/slot.ts | 27 +++++++++++-------- 7 files changed, 29 insertions(+), 29 deletions(-) diff --git a/packages/astro/src/core/render/result.ts b/packages/astro/src/core/render/result.ts index 8f0da82749ac..5aa42b258a95 100644 --- a/packages/astro/src/core/render/result.ts +++ b/packages/astro/src/core/render/result.ts @@ -9,7 +9,7 @@ import type { SSRLoadedRenderer, SSRResult, } from '../../@types/astro'; -import { addScopeFlag, renderSlot, stringifyChunk, ScopeFlags, createScopedResult } from '../../runtime/server/index.js'; +import { renderSlot, stringifyChunk, ScopeFlags, createScopedResult, ComponentSlots } from '../../runtime/server/index.js'; import { renderJSX } from '../../runtime/server/jsx.js'; import { AstroCookies } from '../cookies/index.js'; import { AstroError, AstroErrorData } from '../errors/index.js'; @@ -55,10 +55,10 @@ function getFunctionExpression(slot: any) { class Slots { #result: SSRResult; - #slots: Record | null; + #slots: ComponentSlots | null; #loggingOpts: LogOptions; - constructor(result: SSRResult, slots: Record | null, logging: LogOptions) { + constructor(result: SSRResult, slots: ComponentSlots | null, logging: LogOptions) { this.#result = result; this.#slots = slots; this.#loggingOpts = logging; @@ -110,7 +110,7 @@ class Slots { } // JSX if (typeof component === 'function') { - return await renderJSX(scoped, component(...args)).then((res) => + return await renderJSX(scoped, (component as any)(...args)).then((res) => res != null ? String(res) : res ); } diff --git a/packages/astro/src/runtime/server/index.ts b/packages/astro/src/runtime/server/index.ts index ba5c32d22c5a..aa9da8696b00 100644 --- a/packages/astro/src/runtime/server/index.ts +++ b/packages/astro/src/runtime/server/index.ts @@ -33,9 +33,8 @@ export { export type { AstroComponentFactory, AstroComponentInstance, - AstroComponentSlots, - AstroComponentSlotsWithValues, RenderInstruction, + ComponentSlots } from './render/index.js'; import { markHTMLString } from './escape.js'; diff --git a/packages/astro/src/runtime/server/render/astro/index.ts b/packages/astro/src/runtime/server/render/astro/index.ts index 03d97b14875c..cbddf7876e8e 100644 --- a/packages/astro/src/runtime/server/render/astro/index.ts +++ b/packages/astro/src/runtime/server/render/astro/index.ts @@ -1,7 +1,7 @@ export type { AstroComponentFactory } from './factory'; export { isAstroComponentFactory, renderToString } from './factory.js'; export { createHeadAndContent, isHeadAndContent } from './head-and-content.js'; -export type { AstroComponentInstance, ComponentSlots, ComponentSlotsWithValues } from './instance'; +export type { AstroComponentInstance } from './instance'; export { createAstroComponentInstance, isAstroComponentInstance } from './instance.js'; export { isRenderTemplateResult, diff --git a/packages/astro/src/runtime/server/render/astro/instance.ts b/packages/astro/src/runtime/server/render/astro/instance.ts index 45fdd6d50a02..171cc1a546de 100644 --- a/packages/astro/src/runtime/server/render/astro/instance.ts +++ b/packages/astro/src/runtime/server/render/astro/instance.ts @@ -1,6 +1,6 @@ import type { SSRResult } from '../../../../@types/astro'; import type { AstroComponentFactory, AstroFactoryReturnValue } from './factory.js'; -import type { renderTemplate } from './render-template.js'; +import type { ComponentSlots } from '../slot.js'; import { HydrationDirectiveProps } from '../../hydration.js'; import { isPromise } from '../../util.js'; @@ -10,9 +10,6 @@ import { isHeadAndContent } from './head-and-content.js'; import { createScopedResult, ScopeFlags } from '../scope.js'; type ComponentProps = Record; -type ComponentSlotValue = (result: SSRResult) => ReturnType; -export type ComponentSlots = Record; -export type ComponentSlotsWithValues = Record>; const astroComponentInstanceSym = Symbol.for('astro.componentInstance'); @@ -21,7 +18,7 @@ export class AstroComponentInstance { private readonly result: SSRResult; private readonly props: ComponentProps; - private readonly slotValues: ComponentSlotsWithValues; + private readonly slotValues: ComponentSlots; private readonly factory: AstroComponentFactory; private returnValue: ReturnType | undefined; constructor( @@ -36,7 +33,8 @@ export class AstroComponentInstance { this.slotValues = {}; const scoped = createScopedResult(result, ScopeFlags.Slot); for (const name in slots) { - this.slotValues[name] = slots[name](scoped); + const value = slots[name](scoped); + this.slotValues[name] = () => value; } } diff --git a/packages/astro/src/runtime/server/render/component.ts b/packages/astro/src/runtime/server/render/component.ts index 034e796677a2..36aec94cfbae 100644 --- a/packages/astro/src/runtime/server/render/component.ts +++ b/packages/astro/src/runtime/server/render/component.ts @@ -17,7 +17,7 @@ import { } from './astro/index.js'; import { Fragment, Renderer, stringifyChunk } from './common.js'; import { componentIsHTMLElement, renderHTMLElement } from './dom.js'; -import { renderSlot, renderSlots } from './slot.js'; +import { ComponentSlots, renderSlot, renderSlots } from './slot.js'; import { formatList, internalSpreadAttributes, renderElement, voidElementNames } from './util.js'; const rendererAliases = new Map([['solid', 'solid-js']]); @@ -330,7 +330,7 @@ function sanitizeElementName(tag: string) { return tag.trim().split(unsafe)[0].trim(); } -async function renderFragmentComponent(result: SSRResult, slots: any = {}) { +async function renderFragmentComponent(result: SSRResult, slots: ComponentSlots = {}) { const children = await renderSlot(result, slots?.default); if (children == null) { return children; diff --git a/packages/astro/src/runtime/server/render/index.ts b/packages/astro/src/runtime/server/render/index.ts index 1686300ccb22..092feb86b258 100644 --- a/packages/astro/src/runtime/server/render/index.ts +++ b/packages/astro/src/runtime/server/render/index.ts @@ -1,8 +1,6 @@ export type { AstroComponentFactory, AstroComponentInstance, - ComponentSlots as AstroComponentSlots, - ComponentSlotsWithValues as AstroComponentSlotsWithValues, } from './astro/index'; export { createHeadAndContent, @@ -15,7 +13,7 @@ export { renderComponent, renderComponentToIterable } from './component.js'; export { renderHTMLElement } from './dom.js'; export { maybeRenderHead, renderHead } from './head.js'; export { renderPage } from './page.js'; -export { renderSlot } from './slot.js'; +export { renderSlot, type ComponentSlots } from './slot.js'; export { createScopedResult, ScopeFlags, addScopeFlag, removeScopeFlag } from './scope.js'; export { renderScriptElement, renderStyleElement, renderUniqueStylesheet } from './tags.js'; export type { RenderInstruction } from './types'; diff --git a/packages/astro/src/runtime/server/render/slot.ts b/packages/astro/src/runtime/server/render/slot.ts index c119bea8f5d7..eb9762f94bcf 100644 --- a/packages/astro/src/runtime/server/render/slot.ts +++ b/packages/astro/src/runtime/server/render/slot.ts @@ -1,9 +1,13 @@ import type { SSRResult } from '../../../@types/astro.js'; import type { RenderInstruction } from './types.js'; +import type { renderTemplate } from './astro/render-template.js'; import { HTMLString, markHTMLString } from '../escape.js'; import { renderChild } from './any.js'; -import { ScopeFlags, addScopeFlag, removeScopeFlag } from './scope.js'; +import { ScopeFlags, addScopeFlag, removeScopeFlag, createScopedResult } from './scope.js'; + +export type ComponentSlots = Record; +export type ComponentSlotValue = (result: SSRResult) => ReturnType; const slotString = Symbol.for('astro:slot-string'); @@ -23,12 +27,12 @@ export function isSlotString(str: string): str is any { export async function renderSlot( result: SSRResult, - slotted: string, - fallback?: any + slotted: ComponentSlotValue, + fallback?: ComponentSlotValue ): Promise { if (slotted) { - addScopeFlag(result, ScopeFlags.Slot); - let iterator = renderChild(slotted); + const scoped = createScopedResult(result, ScopeFlags.Slot); + let iterator = renderChild(slotted(scoped)); let content = ''; let instructions: null | RenderInstruction[] = null; for await (const chunk of iterator) { @@ -41,12 +45,13 @@ export async function renderSlot( content += chunk; } } - // Remove the flag since we are now outside of the scope. - removeScopeFlag(result, ScopeFlags.Slot); - return markHTMLString(new SlotString(content, instructions)); } - return fallback; + + if(fallback) { + return renderSlot(result, fallback); + } + return ''; } interface RenderSlotsResult { @@ -54,13 +59,13 @@ interface RenderSlotsResult { children: Record; } -export async function renderSlots(result: SSRResult, slots: any = {}): Promise { +export async function renderSlots(result: SSRResult, slots: ComponentSlots = {}): Promise { let slotInstructions: RenderSlotsResult['slotInstructions'] = null; let children: RenderSlotsResult['children'] = {}; if (slots) { await Promise.all( Object.entries(slots).map(([key, value]) => - renderSlot(result, value as string).then((output: any) => { + renderSlot(result, value).then((output: any) => { if (output.instructions) { if (slotInstructions === null) { slotInstructions = []; From 8b3afc5269b6cd391e843f9da1dcfdde2d955d89 Mon Sep 17 00:00:00 2001 From: Matthew Phillips Date: Mon, 6 Feb 2023 16:53:41 -0500 Subject: [PATCH 10/11] Allow template result to be passed --- packages/astro/src/core/render/result.ts | 2 +- packages/astro/src/runtime/server/render/slot.ts | 11 ++++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/packages/astro/src/core/render/result.ts b/packages/astro/src/core/render/result.ts index 5aa42b258a95..e236b35a4bc5 100644 --- a/packages/astro/src/core/render/result.ts +++ b/packages/astro/src/core/render/result.ts @@ -103,7 +103,7 @@ class Slots { // Astro const expression = getFunctionExpression(component); if (expression) { - const slot = expression(...args); + const slot = () => expression(...args); return await renderSlot(scoped, slot).then((res) => res != null ? String(res) : res ); diff --git a/packages/astro/src/runtime/server/render/slot.ts b/packages/astro/src/runtime/server/render/slot.ts index eb9762f94bcf..aac133e6ef6f 100644 --- a/packages/astro/src/runtime/server/render/slot.ts +++ b/packages/astro/src/runtime/server/render/slot.ts @@ -4,10 +4,11 @@ import type { renderTemplate } from './astro/render-template.js'; import { HTMLString, markHTMLString } from '../escape.js'; import { renderChild } from './any.js'; -import { ScopeFlags, addScopeFlag, removeScopeFlag, createScopedResult } from './scope.js'; +import { ScopeFlags, createScopedResult } from './scope.js'; +type RenderTemplateResult = ReturnType; export type ComponentSlots = Record; -export type ComponentSlotValue = (result: SSRResult) => ReturnType; +export type ComponentSlotValue = (result: SSRResult) => RenderTemplateResult; const slotString = Symbol.for('astro:slot-string'); @@ -27,12 +28,12 @@ export function isSlotString(str: string): str is any { export async function renderSlot( result: SSRResult, - slotted: ComponentSlotValue, - fallback?: ComponentSlotValue + slotted: ComponentSlotValue | RenderTemplateResult, + fallback?: ComponentSlotValue | RenderTemplateResult ): Promise { if (slotted) { const scoped = createScopedResult(result, ScopeFlags.Slot); - let iterator = renderChild(slotted(scoped)); + let iterator = renderChild(typeof slotted === 'function' ? slotted(scoped) : slotted); let content = ''; let instructions: null | RenderInstruction[] = null; for await (const chunk of iterator) { From f3459001b244e778a0a19ccf75dd3a3d6dea102c Mon Sep 17 00:00:00 2001 From: Matthew Phillips Date: Mon, 6 Feb 2023 17:10:31 -0500 Subject: [PATCH 11/11] Add changeset --- .changeset/pretty-bananas-own.md | 10 ++++++++++ packages/astro/package.json | 2 +- packages/astro/src/core/compile/compile.ts | 1 + pnpm-lock.yaml | 12 ++++++------ 4 files changed, 18 insertions(+), 7 deletions(-) create mode 100644 .changeset/pretty-bananas-own.md diff --git a/.changeset/pretty-bananas-own.md b/.changeset/pretty-bananas-own.md new file mode 100644 index 000000000000..322ce96e24c8 --- /dev/null +++ b/.changeset/pretty-bananas-own.md @@ -0,0 +1,10 @@ +--- +'astro': patch +--- + +Fix MDX related head placement bugs + +This fixes a variety of head content placement bugs (such as page ``) related to MDX, especially when used in content collections. Issues fixed: + +- Head content being placed in the body instead of the head. +- Head content missing when rendering an MDX component from within a nested Astro component. diff --git a/packages/astro/package.json b/packages/astro/package.json index 26e028e056f8..35b83d5a9341 100644 --- a/packages/astro/package.json +++ b/packages/astro/package.json @@ -99,7 +99,7 @@ "test:e2e:match": "playwright test -g" }, "dependencies": { - "@astrojs/compiler": "next--slot-pass", + "@astrojs/compiler": "^1.1.0", "@astrojs/language-server": "^0.28.3", "@astrojs/markdown-remark": "^2.0.1", "@astrojs/telemetry": "^2.0.0", diff --git a/packages/astro/src/core/compile/compile.ts b/packages/astro/src/core/compile/compile.ts index 7e8dc8a31927..a0199a2fb703 100644 --- a/packages/astro/src/core/compile/compile.ts +++ b/packages/astro/src/core/compile/compile.ts @@ -42,6 +42,7 @@ export async function compile({ sourcemap: 'both', internalURL: 'astro/server/index.js', astroGlobalArgs: JSON.stringify(astroConfig.site), + resultScopedSlot: true, preprocessStyle: createStylePreprocessor({ filename, viteConfig, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index bb4b28669089..aa398911206f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -375,7 +375,7 @@ importers: packages/astro: specifiers: - '@astrojs/compiler': next--slot-pass + '@astrojs/compiler': ^1.1.0 '@astrojs/language-server': ^0.28.3 '@astrojs/markdown-remark': ^2.0.1 '@astrojs/telemetry': ^2.0.0 @@ -465,7 +465,7 @@ importers: yargs-parser: ^21.0.1 zod: ^3.17.3 dependencies: - '@astrojs/compiler': 0.0.0-slot-pass-20230206200849 + '@astrojs/compiler': 1.1.0 '@astrojs/language-server': 0.28.3 '@astrojs/markdown-remark': link:../markdown/remark '@astrojs/telemetry': link:../telemetry @@ -3864,13 +3864,13 @@ packages: sisteransi: 1.0.5 dev: false - /@astrojs/compiler/0.0.0-slot-pass-20230206200849: - resolution: {integrity: sha512-1jl/e96lIO6+5GNDUb49bwAOh170uk7/VJ2PQTdBOw0Xwo0sK/JA8xC0z/ySsEuQ/5nJ8Lo7yZW1KPro9qIbPw==} - dev: false - /@astrojs/compiler/0.31.4: resolution: {integrity: sha512-6bBFeDTtPOn4jZaiD3p0f05MEGQL9pw2Zbfj546oFETNmjJFWO3nzHz6/m+P53calknCvyVzZ5YhoBLIvzn5iw==} + /@astrojs/compiler/1.1.0: + resolution: {integrity: sha512-C4kTwirys+HafufMqaxCbML2wqkGaXJM+5AekXh/v1IIOnMIdcEON9GBYsG6qa8aAmLhZ58aUZGPhzcA3Dx7Uw==} + dev: false + /@astrojs/language-server/0.28.3: resolution: {integrity: sha512-fPovAX/X46eE2w03jNRMpQ7W9m2mAvNt4Ay65lD9wl1Z5vIQYxlg7Enp9qP225muTr4jSVB5QiLumFJmZMAaVA==} hasBin: true