diff options
Diffstat (limited to 'packages/astro')
19 files changed, 58 insertions, 39 deletions
diff --git a/packages/astro/e2e/fixtures/preact-component/src/components/Layout.astro b/packages/astro/e2e/fixtures/preact-component/src/components/Layout.astro new file mode 100644 index 000000000..3c3cf4e4d --- /dev/null +++ b/packages/astro/e2e/fixtures/preact-component/src/components/Layout.astro @@ -0,0 +1,4 @@ +<html> + <head><title>Preact component</title></head> + <body><slot></slot></body> +</html> diff --git a/packages/astro/e2e/fixtures/preact-component/src/pages/markdown.md b/packages/astro/e2e/fixtures/preact-component/src/pages/markdown.md index c05e2ae52..7c521de77 100644 --- a/packages/astro/e2e/fixtures/preact-component/src/pages/markdown.md +++ b/packages/astro/e2e/fixtures/preact-component/src/pages/markdown.md @@ -1,4 +1,5 @@ --- +layout: ../components/Layout.astro setup: | import Counter from '../components/Counter.jsx'; import PreactComponent from '../components/JSXComponent.jsx'; diff --git a/packages/astro/e2e/fixtures/react-component/src/components/Layout.astro b/packages/astro/e2e/fixtures/react-component/src/components/Layout.astro new file mode 100644 index 000000000..7c166b532 --- /dev/null +++ b/packages/astro/e2e/fixtures/react-component/src/components/Layout.astro @@ -0,0 +1,4 @@ +<html> + <head><title>React component</title></head> + <body><slot></slot></body> +</html> diff --git a/packages/astro/e2e/fixtures/react-component/src/pages/markdown.md b/packages/astro/e2e/fixtures/react-component/src/pages/markdown.md index 5461fc48a..fbc685a5b 100644 --- a/packages/astro/e2e/fixtures/react-component/src/pages/markdown.md +++ b/packages/astro/e2e/fixtures/react-component/src/pages/markdown.md @@ -1,4 +1,5 @@ --- +layout: ../components/Layout.astro setup: | import Counter from '../components/Counter.jsx'; import ReactComponent from '../components/JSXComponent.jsx'; diff --git a/packages/astro/e2e/fixtures/solid-component/src/components/Layout.astro b/packages/astro/e2e/fixtures/solid-component/src/components/Layout.astro new file mode 100644 index 000000000..63e0ff449 --- /dev/null +++ b/packages/astro/e2e/fixtures/solid-component/src/components/Layout.astro @@ -0,0 +1,4 @@ +<html> + <head><title>Solid component</title></head> + <body><slot></slot></body> +</html> diff --git a/packages/astro/e2e/fixtures/solid-component/src/pages/markdown.md b/packages/astro/e2e/fixtures/solid-component/src/pages/markdown.md index 22d546481..21a779c9d 100644 --- a/packages/astro/e2e/fixtures/solid-component/src/pages/markdown.md +++ b/packages/astro/e2e/fixtures/solid-component/src/pages/markdown.md @@ -1,4 +1,5 @@ --- +layout: ../components/Layout.astro setup: | import Counter from '../components/Counter.jsx'; import SolidComponent from '../components/SolidComponent.jsx'; diff --git a/packages/astro/e2e/fixtures/svelte-component/src/components/Layout.astro b/packages/astro/e2e/fixtures/svelte-component/src/components/Layout.astro new file mode 100644 index 000000000..63e0ff449 --- /dev/null +++ b/packages/astro/e2e/fixtures/svelte-component/src/components/Layout.astro @@ -0,0 +1,4 @@ +<html> + <head><title>Solid component</title></head> + <body><slot></slot></body> +</html> diff --git a/packages/astro/e2e/fixtures/svelte-component/src/pages/markdown.md b/packages/astro/e2e/fixtures/svelte-component/src/pages/markdown.md index 0030bccd1..ebc4d8795 100644 --- a/packages/astro/e2e/fixtures/svelte-component/src/pages/markdown.md +++ b/packages/astro/e2e/fixtures/svelte-component/src/pages/markdown.md @@ -1,4 +1,5 @@ --- +layout: ../components/Layout.astro setup: | import Counter from '../components/Counter.svelte'; import SvelteComponent from '../components/SvelteComponent.svelte'; diff --git a/packages/astro/e2e/fixtures/vue-component/src/components/Layout.astro b/packages/astro/e2e/fixtures/vue-component/src/components/Layout.astro new file mode 100644 index 000000000..285bc56e2 --- /dev/null +++ b/packages/astro/e2e/fixtures/vue-component/src/components/Layout.astro @@ -0,0 +1,4 @@ +<html> + <head><title>Vue component</title></head> + <body><slot></slot></body> +</html> diff --git a/packages/astro/e2e/fixtures/vue-component/src/pages/markdown.md b/packages/astro/e2e/fixtures/vue-component/src/pages/markdown.md index 22698931a..3ae0470af 100644 --- a/packages/astro/e2e/fixtures/vue-component/src/pages/markdown.md +++ b/packages/astro/e2e/fixtures/vue-component/src/pages/markdown.md @@ -1,4 +1,5 @@ --- +layout: ../components/Layout.astro setup: | import Counter from '../components/Counter.vue'; import VueComponent from '../components/VueComponent.vue'; diff --git a/packages/astro/package.json b/packages/astro/package.json index d145c4979..326e64fa6 100644 --- a/packages/astro/package.json +++ b/packages/astro/package.json @@ -78,7 +78,7 @@ "test:e2e:match": "playwright test -g" }, "dependencies": { - "@astrojs/compiler": "^0.16.1", + "@astrojs/compiler": "^0.17.0", "@astrojs/language-server": "^0.13.4", "@astrojs/markdown-remark": "^0.11.3", "@astrojs/prism": "0.4.1", diff --git a/packages/astro/src/@types/astro.ts b/packages/astro/src/@types/astro.ts index d2ef92365..48cac0d12 100644 --- a/packages/astro/src/@types/astro.ts +++ b/packages/astro/src/@types/astro.ts @@ -1004,7 +1004,6 @@ export interface SSRElement { export interface SSRMetadata { renderers: SSRLoadedRenderer[]; pathname: string; - needsHydrationStyles: boolean; } export interface SSRResult { diff --git a/packages/astro/src/core/render/core.ts b/packages/astro/src/core/render/core.ts index 48d362924..32641c020 100644 --- a/packages/astro/src/core/render/core.ts +++ b/packages/astro/src/core/render/core.ts @@ -161,12 +161,6 @@ export async function render( } let html = page.html; - // handle final head injection if it hasn't happened already - if (html.indexOf('<!--astro:head:injected-->') == -1) { - html = (await renderHead(result)) + html; - } - // cleanup internal state flags - html = html.replace('<!--astro:head:injected-->', ''); // inject <!doctype html> if missing (TODO: is a more robust check needed for comments, etc.?) if (!/<!doctype html/i.test(html)) { diff --git a/packages/astro/src/core/render/result.ts b/packages/astro/src/core/render/result.ts index 05ec344b9..457efe44a 100644 --- a/packages/astro/src/core/render/result.ts +++ b/packages/astro/src/core/render/result.ts @@ -221,7 +221,6 @@ ${extra}` }, resolve, _metadata: { - needsHydrationStyles: false, renderers, pathname, }, diff --git a/packages/astro/src/runtime/server/index.ts b/packages/astro/src/runtime/server/index.ts index 1b78d7171..322e212df 100644 --- a/packages/astro/src/runtime/server/index.ts +++ b/packages/astro/src/runtime/server/index.ts @@ -344,7 +344,6 @@ If you're still stuck, please open an issue on GitHub or join us at https://astr { renderer: renderer!, result, astroId, props }, metadata as Required<AstroComponentMetadata> ); - result._metadata.needsHydrationStyles = true; // Render template if not all astro fragments are provided. let unrenderedSlots: string[] = []; @@ -590,16 +589,6 @@ Update your code to remove this warning.`); return handler.call(mod, proxy, request); } -async function replaceHeadInjection(result: SSRResult, html: string): Promise<string> { - let template = html; - // <!--astro:head--> injected by compiler - // Must be handled at the end of the rendering process - if (template.indexOf('<!--astro:head-->') > -1) { - template = template.replace('<!--astro:head-->', await renderHead(result)); - } - return template; -} - // Calls a component and renders it into a string of HTML export async function renderToString( result: SSRResult, @@ -627,8 +616,7 @@ export async function renderPage( const response = await componentFactory(result, props, children); if (isAstroComponent(response)) { - let template = await renderAstroComponent(response); - const html = await replaceHeadInjection(result, template); + let html = await renderAstroComponent(response); return { type: 'html', html, @@ -660,37 +648,36 @@ const uniqueElements = (item: any, index: number, all: any[]) => { ); }; -// Renders a page to completion by first calling the factory callback, waiting for its result, and then appending -// styles and scripts into the head. +const alreadyHeadRenderedResults = new WeakSet<SSRResult>(); export async function renderHead(result: SSRResult): Promise<string> { + alreadyHeadRenderedResults.add(result); const styles = Array.from(result.styles) .filter(uniqueElements) .map((style) => renderElement('style', style)); - let needsHydrationStyles = result._metadata.needsHydrationStyles; const scripts = Array.from(result.scripts) .filter(uniqueElements) .map((script, i) => { - if ('data-astro-component-hydration' in script.props) { - needsHydrationStyles = true; - } return renderElement('script', script); }); - if (needsHydrationStyles) { - styles.push( - renderElement('style', { - props: {}, - children: 'astro-island, astro-slot { display: contents; }', - }) - ); - } const links = Array.from(result.links) .filter(uniqueElements) .map((link) => renderElement('link', link, false)); return markHTMLString( - links.join('\n') + styles.join('\n') + scripts.join('\n') + '\n' + '<!--astro:head:injected-->' + links.join('\n') + styles.join('\n') + scripts.join('\n') ); } +// This function is called by Astro components that do not contain a <head> component +// This accomodates the fact that using a <head> is optional in Astro, so this +// is called before a component's first non-head HTML element. If the head was +// already injected it is a noop. +export function maybeRenderHead(result: SSRResult): string | Promise<string> { + if(alreadyHeadRenderedResults.has(result)) { + return ''; + } + return renderHead(result); +} + export async function renderAstroComponent(component: InstanceType<typeof AstroComponent>) { let template = []; diff --git a/packages/astro/src/runtime/server/scripts.ts b/packages/astro/src/runtime/server/scripts.ts index 0446ed2c7..4fe7b9057 100644 --- a/packages/astro/src/runtime/server/scripts.ts +++ b/packages/astro/src/runtime/server/scripts.ts @@ -59,7 +59,7 @@ export function getPrescripts(type: PrescriptType, directive: string): string { // deps to be loaded immediately. switch (type) { case 'both': - return `<script>${getDirectiveScriptText(directive) + islandScript}</script>`; + return `<style>astro-island,astro-slot{display:contents}</style><script>${getDirectiveScriptText(directive) + islandScript}</script>`; case 'directive': return `<script>${getDirectiveScriptText(directive)}</script>`; } diff --git a/packages/astro/test/0-css.test.js b/packages/astro/test/0-css.test.js index e1b317f32..4b2862470 100644 --- a/packages/astro/test/0-css.test.js +++ b/packages/astro/test/0-css.test.js @@ -65,7 +65,7 @@ describe('CSS', function () { it('Using hydrated components adds astro-island styles', async () => { const inline = $('style').html(); - expect(inline).to.include('display: contents'); + expect(inline).to.include('display:contents'); }); it('<style lang="sass">', async () => { diff --git a/packages/astro/test/astro-partial-html.test.js b/packages/astro/test/astro-partial-html.test.js index 5ae2929ce..484adc21c 100644 --- a/packages/astro/test/astro-partial-html.test.js +++ b/packages/astro/test/astro-partial-html.test.js @@ -40,4 +40,10 @@ describe('Partial HTML', async () => { const allInjectedStyles = $('style[data-astro-injected]').text().replace(/\s*/g, ''); expect(allInjectedStyles).to.match(/h1{color:red;}/); }); + + it('pages with a head, injection happens inside', async () => { + const html = await fixture.fetch('/with-head').then((res) => res.text()); + const $ = cheerio.load(html); + expect($('style')).to.have.lengthOf(1); + }); }); diff --git a/packages/astro/test/fixtures/astro-partial-html/src/pages/with-head.astro b/packages/astro/test/fixtures/astro-partial-html/src/pages/with-head.astro new file mode 100644 index 000000000..fbbcecd1e --- /dev/null +++ b/packages/astro/test/fixtures/astro-partial-html/src/pages/with-head.astro @@ -0,0 +1,9 @@ +<html> + <head> + <title>testing</title> + <style>body { color: blue; }</style> + </head> + <body> + <h1>testing</h1> + </body> +</html> |