From 45b41d98f50dc9f76a5004a8b3346f393f1a6cb6 Mon Sep 17 00:00:00 2001 From: Nacho Vazquez Date: Fri, 3 Feb 2023 12:19:44 -0300 Subject: [PATCH 01/11] fix: use the root of the project as the functions location (#6075) * fix: use the root of the project as the functions location * test: add test to check where the functions folder is added --- .changeset/honest-beds-flow.md | 5 +++++ packages/integrations/cloudflare/src/index.ts | 2 +- .../integrations/cloudflare/test/directory.test.js | 11 ++++++----- 3 files changed, 12 insertions(+), 6 deletions(-) create mode 100644 .changeset/honest-beds-flow.md diff --git a/.changeset/honest-beds-flow.md b/.changeset/honest-beds-flow.md new file mode 100644 index 000000000000..ddf54699f9fc --- /dev/null +++ b/.changeset/honest-beds-flow.md @@ -0,0 +1,5 @@ +--- +'@astrojs/cloudflare': patch +--- + +Uses config root path as location for Cloudflare Pages Functions diff --git a/packages/integrations/cloudflare/src/index.ts b/packages/integrations/cloudflare/src/index.ts index 3433cf46d70e..7ba1cc63148a 100644 --- a/packages/integrations/cloudflare/src/index.ts +++ b/packages/integrations/cloudflare/src/index.ts @@ -203,7 +203,7 @@ export default function createIntegration(args?: Options): AstroIntegration { } if (isModeDirectory) { - const functionsUrl = new URL(`file://${process.cwd()}/functions/`); + const functionsUrl = new URL('functions', _config.root); await fs.promises.mkdir(functionsUrl, { recursive: true }); const directoryUrl = new URL('[[path]].js', functionsUrl); await fs.promises.rename(finalBuildUrl, directoryUrl); diff --git a/packages/integrations/cloudflare/test/directory.test.js b/packages/integrations/cloudflare/test/directory.test.js index 7c299f526685..e5b5205745cf 100644 --- a/packages/integrations/cloudflare/test/directory.test.js +++ b/packages/integrations/cloudflare/test/directory.test.js @@ -1,20 +1,21 @@ -import { loadFixture, runCLI } from './test-utils.js'; +import { loadFixture } from './test-utils.js'; import { expect } from 'chai'; -import * as cheerio from 'cheerio'; import cloudflare from '../dist/index.js'; +/** @type {import('./test-utils').Fixture} */ describe('mode: "directory"', () => { - /** @type {import('./test-utils').Fixture} */ let fixture; before(async () => { fixture = await loadFixture({ root: './fixtures/basics/', + output: 'server', adapter: cloudflare({ mode: 'directory' }), }); + await fixture.build(); }); - it('Builds', async () => { - await fixture.build(); + it('generates functions folder inside the project root', async () => { + expect(await fixture.pathExists('../functions')).to.be.true; }); }); From db2c59fc18820af49a1c4f8d0bf5052abb694530 Mon Sep 17 00:00:00 2001 From: Obinna Ekwuno Date: Fri, 3 Feb 2023 17:52:11 +0000 Subject: [PATCH 02/11] Update open with codesandbox link to use synced sandboxes (#6105) --- examples/basics/README.md | 2 +- examples/blog/README.md | 2 +- examples/component/README.md | 2 +- examples/deno/README.md | 2 +- examples/docs/README.md | 2 +- examples/framework-alpine/README.md | 2 +- examples/framework-lit/README.md | 2 +- examples/framework-multiple/README.md | 2 +- examples/framework-preact/README.md | 2 +- examples/framework-react/README.md | 2 +- examples/framework-solid/README.md | 2 +- examples/framework-svelte/README.md | 2 +- examples/framework-vue/README.md | 2 +- examples/hackernews/README.md | 2 +- examples/integration/README.md | 2 +- examples/minimal/README.md | 2 +- examples/non-html-pages/README.md | 2 +- examples/portfolio/README.md | 2 +- examples/with-markdown-plugins/README.md | 2 +- examples/with-markdown-shiki/README.md | 2 +- examples/with-mdx/README.md | 2 +- examples/with-nanostores/README.md | 2 +- examples/with-tailwindcss/README.md | 2 +- examples/with-vite-plugin-pwa/README.md | 2 +- examples/with-vitest/README.md | 2 +- 25 files changed, 25 insertions(+), 25 deletions(-) diff --git a/examples/basics/README.md b/examples/basics/README.md index ff315bae0e4c..b2c29bad781f 100644 --- a/examples/basics/README.md +++ b/examples/basics/README.md @@ -5,7 +5,7 @@ npm create astro@latest -- --template basics ``` [![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/withastro/astro/tree/latest/examples/basics) -[![Open with CodeSandbox](https://assets.codesandbox.io/github/button-edit-lime.svg)](https://codesandbox.io/s/github/withastro/astro/tree/latest/examples/basics) +[![Open with CodeSandbox](https://assets.codesandbox.io/github/button-edit-lime.svg)](https://codesandbox.io/p/sandbox/github/withastro/astro/tree/latest/examples/basics) > πŸ§‘β€πŸš€ **Seasoned astronaut?** Delete this file. Have fun! diff --git a/examples/blog/README.md b/examples/blog/README.md index c788fa653695..ac5417c0d425 100644 --- a/examples/blog/README.md +++ b/examples/blog/README.md @@ -5,7 +5,7 @@ npm create astro@latest -- --template blog ``` [![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/withastro/astro/tree/latest/examples/blog) -[![Open with CodeSandbox](https://assets.codesandbox.io/github/button-edit-lime.svg)](https://codesandbox.io/s/github/withastro/astro/tree/latest/examples/blog) +[![Open with CodeSandbox](https://assets.codesandbox.io/github/button-edit-lime.svg)](https://codesandbox.io/p/sandbox/github/withastro/astro/tree/latest/examples/blog) > πŸ§‘β€πŸš€ **Seasoned astronaut?** Delete this file. Have fun! diff --git a/examples/component/README.md b/examples/component/README.md index 7675f5f7f79f..b09f5e3c6b83 100644 --- a/examples/component/README.md +++ b/examples/component/README.md @@ -7,7 +7,7 @@ npm create astro@latest -- --template component ``` [![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/withastro/astro/tree/latest/examples/non-html-pages) -[![Open with CodeSandbox](https://assets.codesandbox.io/github/button-edit-lime.svg)](https://codesandbox.io/s/github/withastro/astro/tree/latest/examples/non-html-pages) +[![Open with CodeSandbox](https://assets.codesandbox.io/github/button-edit-lime.svg)](https://codesandbox.io/p/sandbox/github/withastro/astro/tree/latest/examples/non-html-pages) ## πŸš€ Project Structure diff --git a/examples/deno/README.md b/examples/deno/README.md index c7d480b7806a..db3470a73b24 100644 --- a/examples/deno/README.md +++ b/examples/deno/README.md @@ -1,7 +1,7 @@ # Astro Starter Kit: Deno [![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/withastro/astro/tree/latest/examples/deno) -[![Open with CodeSandbox](https://assets.codesandbox.io/github/button-edit-lime.svg)](https://codesandbox.io/s/github/withastro/astro/tree/latest/examples/deno) +[![Open with CodeSandbox](https://assets.codesandbox.io/github/button-edit-lime.svg)](https://codesandbox.io/p/sandbox/github/withastro/astro/tree/latest/examples/deno) ``` npm create astro@latest -- --template deno diff --git a/examples/docs/README.md b/examples/docs/README.md index 0c4bad02837b..1ba63a9e6767 100644 --- a/examples/docs/README.md +++ b/examples/docs/README.md @@ -5,7 +5,7 @@ npm create astro@latest -- --template docs ``` [![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/withastro/astro/tree/latest/examples/docs) -[![Open with CodeSandbox](https://assets.codesandbox.io/github/button-edit-lime.svg)](https://codesandbox.io/s/github/withastro/astro/tree/latest/examples/docs) +[![Open with CodeSandbox](https://assets.codesandbox.io/github/button-edit-lime.svg)](https://codesandbox.io/p/sandbox/github/withastro/astro/tree/latest/examples/docs) > πŸ§‘β€πŸš€ **Seasoned astronaut?** Delete this file. Have fun! diff --git a/examples/framework-alpine/README.md b/examples/framework-alpine/README.md index 559aa0ebd28e..4b0314343dfd 100644 --- a/examples/framework-alpine/README.md +++ b/examples/framework-alpine/README.md @@ -5,7 +5,7 @@ npm create astro@latest -- --template framework-alpine ``` [![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/withastro/astro/tree/latest/examples/framework-alpine) -[![Open with CodeSandbox](https://assets.codesandbox.io/github/button-edit-lime.svg)](https://codesandbox.io/s/github/withastro/astro/tree/latest/examples/framework-alpine) +[![Open with CodeSandbox](https://assets.codesandbox.io/github/button-edit-lime.svg)](https://codesandbox.io/p/sandbox/github/withastro/astro/tree/latest/examples/framework-alpine) This example showcases Astro working with [AlpineJS](https://alpinejs.dev/). diff --git a/examples/framework-lit/README.md b/examples/framework-lit/README.md index c1dfebbd2f6d..618b5e24d150 100644 --- a/examples/framework-lit/README.md +++ b/examples/framework-lit/README.md @@ -5,6 +5,6 @@ npm create astro@latest -- --template framework-lit ``` [![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/withastro/astro/tree/latest/examples/framework-lit) -[![Open with CodeSandbox](https://assets.codesandbox.io/github/button-edit-lime.svg)](https://codesandbox.io/s/github/withastro/astro/tree/latest/examples/framework-lit) +[![Open with CodeSandbox](https://assets.codesandbox.io/github/button-edit-lime.svg)](https://codesandbox.io/p/sandbox/github/withastro/astro/tree/latest/examples/framework-lit) This example showcases Astro working with [Lit](https://lit.dev/). \ No newline at end of file diff --git a/examples/framework-multiple/README.md b/examples/framework-multiple/README.md index 89efd74ae050..f07077dbf8fa 100644 --- a/examples/framework-multiple/README.md +++ b/examples/framework-multiple/README.md @@ -5,7 +5,7 @@ npm create astro@latest -- --template framework-multiple ``` [![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/withastro/astro/tree/latest/examples/framework-multiple) -[![Open with CodeSandbox](https://assets.codesandbox.io/github/button-edit-lime.svg)](https://codesandbox.io/s/github/withastro/astro/tree/latest/examples/framework-multiple) +[![Open with CodeSandbox](https://assets.codesandbox.io/github/button-edit-lime.svg)](https://codesandbox.io/p/sandbox/github/withastro/astro/tree/latest/examples/framework-multiple) This example showcases Astro's built-in support for multiple frameworks ([React](https://reactjs.org), [Preact](https://preactjs.com), [Svelte](https://svelte.dev), and [Vue (`v3.x`)](https://v3.vuejs.org/)). diff --git a/examples/framework-preact/README.md b/examples/framework-preact/README.md index 9adc4881c685..0c7c8d13074f 100644 --- a/examples/framework-preact/README.md +++ b/examples/framework-preact/README.md @@ -5,7 +5,7 @@ npm create astro@latest -- --template framework-preact ``` [![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/withastro/astro/tree/latest/examples/framework-preact) -[![Open with CodeSandbox](https://assets.codesandbox.io/github/button-edit-lime.svg)](https://codesandbox.io/s/github/withastro/astro/tree/latest/examples/framework-preact) +[![Open with CodeSandbox](https://assets.codesandbox.io/github/button-edit-lime.svg)](https://codesandbox.io/p/sandbox/github/withastro/astro/tree/latest/examples/framework-preact) This example showcases Astro working with [Preact](https://preactjs.com). diff --git a/examples/framework-react/README.md b/examples/framework-react/README.md index 0df421989f50..52cfb908d034 100644 --- a/examples/framework-react/README.md +++ b/examples/framework-react/README.md @@ -5,7 +5,7 @@ npm create astro@latest -- --template framework-react ``` [![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/withastro/astro/tree/latest/examples/framework-react) -[![Open with CodeSandbox](https://assets.codesandbox.io/github/button-edit-lime.svg)](https://codesandbox.io/s/github/withastro/astro/tree/latest/examples/framework-react) +[![Open with CodeSandbox](https://assets.codesandbox.io/github/button-edit-lime.svg)](https://codesandbox.io/p/sandbox/github/withastro/astro/tree/latest/examples/framework-react) This example showcases Astro working with [React](https://reactjs.org/). diff --git a/examples/framework-solid/README.md b/examples/framework-solid/README.md index b68f558cf360..928a8e572c59 100644 --- a/examples/framework-solid/README.md +++ b/examples/framework-solid/README.md @@ -5,7 +5,7 @@ npm create astro@latest -- --template framework-solid ``` [![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/withastro/astro/tree/latest/examples/framework-solid) -[![Open with CodeSandbox](https://assets.codesandbox.io/github/button-edit-lime.svg)](https://codesandbox.io/s/github/withastro/astro/tree/latest/examples/framework-solid) +[![Open with CodeSandbox](https://assets.codesandbox.io/github/button-edit-lime.svg)](https://codesandbox.io/p/sandbox/github/withastro/astro/tree/latest/examples/framework-solid) This example showcases Astro working with [Solid](https://www.solidjs.com/). diff --git a/examples/framework-svelte/README.md b/examples/framework-svelte/README.md index 4b873b0ddbf9..da0d051c4ea6 100644 --- a/examples/framework-svelte/README.md +++ b/examples/framework-svelte/README.md @@ -5,6 +5,6 @@ npm create astro@latest -- --template framework-svelte ``` [![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/withastro/astro/tree/latest/examples/framework-svelte) -[![Open with CodeSandbox](https://assets.codesandbox.io/github/button-edit-lime.svg)](https://codesandbox.io/s/github/withastro/astro/tree/latest/examples/framework-svelte) +[![Open with CodeSandbox](https://assets.codesandbox.io/github/button-edit-lime.svg)](https://codesandbox.io/p/sandbox/github/withastro/astro/tree/latest/examples/framework-svelte) This example showcases Astro working with [Svelte](https://svelte.dev/). diff --git a/examples/framework-vue/README.md b/examples/framework-vue/README.md index 40c39838febb..7d2f635e64cc 100644 --- a/examples/framework-vue/README.md +++ b/examples/framework-vue/README.md @@ -5,7 +5,7 @@ npm create astro@latest -- --template framework-vue ``` [![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/withastro/astro/tree/latest/examples/framework-vue) -[![Open with CodeSandbox](https://assets.codesandbox.io/github/button-edit-lime.svg)](https://codesandbox.io/s/github/withastro/astro/tree/latest/examples/framework-vue) +[![Open with CodeSandbox](https://assets.codesandbox.io/github/button-edit-lime.svg)](https://codesandbox.io/p/sandbox/github/withastro/astro/tree/latest/examples/framework-vue) This example showcases Astro working with [Vue](https://v3.vuejs.org/). diff --git a/examples/hackernews/README.md b/examples/hackernews/README.md index 718369e87a80..e2d15dda57b4 100644 --- a/examples/hackernews/README.md +++ b/examples/hackernews/README.md @@ -5,7 +5,7 @@ npm create astro@latest -- --template hackernews ``` [![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/withastro/astro/tree/latest/examples/hackernews) -[![Open with CodeSandbox](https://assets.codesandbox.io/github/button-edit-lime.svg)](https://codesandbox.io/s/github/withastro/astro/tree/latest/examples/hackernews) +[![Open with CodeSandbox](https://assets.codesandbox.io/github/button-edit-lime.svg)](https://codesandbox.io/p/sandbox/github/withastro/astro/tree/latest/examples/hackernews) > πŸ§‘β€πŸš€ **Seasoned astronaut?** Delete this file. Have fun! diff --git a/examples/integration/README.md b/examples/integration/README.md index eeeb5afa52ad..42cc04413189 100644 --- a/examples/integration/README.md +++ b/examples/integration/README.md @@ -7,7 +7,7 @@ npm create astro@latest -- --template integration ``` [![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/withastro/astro/tree/latest/examples/integration) -[![Open with CodeSandbox](https://assets.codesandbox.io/github/button-edit-lime.svg)](https://codesandbox.io/s/github/withastro/astro/tree/latest/examples/integration) +[![Open with CodeSandbox](https://assets.codesandbox.io/github/button-edit-lime.svg)](https://codesandbox.io/p/sandbox/github/withastro/astro/tree/latest/examples/integration) ## πŸš€ Project Structure diff --git a/examples/minimal/README.md b/examples/minimal/README.md index 097699e77e7e..e14d3255bb80 100644 --- a/examples/minimal/README.md +++ b/examples/minimal/README.md @@ -5,7 +5,7 @@ npm create astro@latest -- --template minimal ``` [![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/withastro/astro/tree/latest/examples/minimal) -[![Open with CodeSandbox](https://assets.codesandbox.io/github/button-edit-lime.svg)](https://codesandbox.io/s/github/withastro/astro/tree/latest/examples/minimal) +[![Open with CodeSandbox](https://assets.codesandbox.io/github/button-edit-lime.svg)](https://codesandbox.io/p/sandbox/github/withastro/astro/tree/latest/examples/minimal) > πŸ§‘β€πŸš€ **Seasoned astronaut?** Delete this file. Have fun! diff --git a/examples/non-html-pages/README.md b/examples/non-html-pages/README.md index d8d77463b9fc..35487a0f9470 100644 --- a/examples/non-html-pages/README.md +++ b/examples/non-html-pages/README.md @@ -9,7 +9,7 @@ npm create astro@latest -- --template non-html-pages ``` [![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/withastro/astro/tree/latest/examples/non-html-pages) -[![Open with CodeSandbox](https://assets.codesandbox.io/github/button-edit-lime.svg)](https://codesandbox.io/s/github/withastro/astro/tree/latest/examples/non-html-pages) +[![Open with CodeSandbox](https://assets.codesandbox.io/github/button-edit-lime.svg)](https://codesandbox.io/p/sandbox/github/withastro/astro/tree/latest/examples/non-html-pages) > πŸ§‘β€πŸš€ **Seasoned astronaut?** Delete this file. Have fun! diff --git a/examples/portfolio/README.md b/examples/portfolio/README.md index b35d89d0b496..8774a8ff5209 100644 --- a/examples/portfolio/README.md +++ b/examples/portfolio/README.md @@ -5,7 +5,7 @@ npm create astro@latest -- --template portfolio ``` [![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/withastro/astro/tree/latest/examples/portfolio) -[![Open with CodeSandbox](https://assets.codesandbox.io/github/button-edit-lime.svg)](https://codesandbox.io/s/github/withastro/astro/tree/latest/examples/portfolio) +[![Open with CodeSandbox](https://assets.codesandbox.io/github/button-edit-lime.svg)](https://codesandbox.io/p/sandbox/github/withastro/astro/tree/latest/examples/portfolio) > πŸ§‘β€πŸš€ **Seasoned astronaut?** Delete this file. Have fun! diff --git a/examples/with-markdown-plugins/README.md b/examples/with-markdown-plugins/README.md index 83d12f3f477c..bdb657bcd434 100644 --- a/examples/with-markdown-plugins/README.md +++ b/examples/with-markdown-plugins/README.md @@ -5,6 +5,6 @@ npm create astro@latest -- --template with-markdown-plugins ``` [![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/withastro/astro/tree/latest/examples/with-markdown-plugins) -[![Open with CodeSandbox](https://assets.codesandbox.io/github/button-edit-lime.svg)](https://codesandbox.io/s/github/withastro/astro/tree/latest/examples/with-markdown-plugins) +[![Open with CodeSandbox](https://assets.codesandbox.io/github/button-edit-lime.svg)](https://codesandbox.io/p/sandbox/github/withastro/astro/tree/latest/examples/with-markdown-plugins) This example showcases Astro's [built-in Markdown support](https://docs.astro.build/en/guides/markdown-content/) with additional, user-provided plugins. diff --git a/examples/with-markdown-shiki/README.md b/examples/with-markdown-shiki/README.md index b22ad2ac530c..89afac7dd613 100644 --- a/examples/with-markdown-shiki/README.md +++ b/examples/with-markdown-shiki/README.md @@ -5,7 +5,7 @@ npm create astro@latest -- --template with-markdown-shiki ``` [![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/withastro/astro/tree/latest/examples/with-markdown-shiki) -[![Open with CodeSandbox](https://assets.codesandbox.io/github/button-edit-lime.svg)](https://codesandbox.io/s/github/withastro/astro/tree/latest/examples/with-markdown-shiki) +[![Open with CodeSandbox](https://assets.codesandbox.io/github/button-edit-lime.svg)](https://codesandbox.io/p/sandbox/github/withastro/astro/tree/latest/examples/with-markdown-shiki) This example showcases Astro's [built-in Markdown support](https://docs.astro.build/en/guides/markdown-content/). diff --git a/examples/with-mdx/README.md b/examples/with-mdx/README.md index 49ddf947a0dc..7cbadbfb7d27 100644 --- a/examples/with-mdx/README.md +++ b/examples/with-mdx/README.md @@ -5,6 +5,6 @@ npm create astro@latest -- --template with-mdx ``` [![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/withastro/astro/tree/latest/examples/with-mdx) -[![Open with CodeSandbox](https://assets.codesandbox.io/github/button-edit-lime.svg)](https://codesandbox.io/s/github/withastro/astro/tree/latest/examples/with-mdx) +[![Open with CodeSandbox](https://assets.codesandbox.io/github/button-edit-lime.svg)](https://codesandbox.io/p/sandbox/github/withastro/astro/tree/latest/examples/with-mdx) This example showcases using [`@astrojs/mdx`](https://www.npmjs.com/package/@astrojs/mdx) to author content using [MDX](https://mdxjs.com/). diff --git a/examples/with-nanostores/README.md b/examples/with-nanostores/README.md index 9297bb608c3c..2fa317c43ca7 100644 --- a/examples/with-nanostores/README.md +++ b/examples/with-nanostores/README.md @@ -5,6 +5,6 @@ npm create astro@latest -- --template with-nanostores ``` [![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/withastro/astro/tree/latest/examples/with-nanostores) -[![Open with CodeSandbox](https://assets.codesandbox.io/github/button-edit-lime.svg)](https://codesandbox.io/s/github/withastro/astro/tree/latest/examples/with-nanostores) +[![Open with CodeSandbox](https://assets.codesandbox.io/github/button-edit-lime.svg)](https://codesandbox.io/p/sandbox/github/withastro/astro/tree/latest/examples/with-nanostores) This example showcases using [`nanostores`](https://github.com/nanostores/nanostores) to provide shared state between components of any framework. [**Read our documentation on sharing state**](https://docs.astro.build/en/core-concepts/sharing-state/) for a complete breakdown of this project, along with guides to use React, Vue, Svelte, or Solid! diff --git a/examples/with-tailwindcss/README.md b/examples/with-tailwindcss/README.md index 3eec5faec18b..4944c313335d 100644 --- a/examples/with-tailwindcss/README.md +++ b/examples/with-tailwindcss/README.md @@ -5,7 +5,7 @@ npm create astro@latest -- --template with-tailwindcss ``` [![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/withastro/astro/tree/latest/examples/with-tailwindcss) -[![Open with CodeSandbox](https://assets.codesandbox.io/github/button-edit-lime.svg)](https://codesandbox.io/s/github/withastro/astro/tree/latest/examples/with-tailwindcss) +[![Open with CodeSandbox](https://assets.codesandbox.io/github/button-edit-lime.svg)](https://codesandbox.io/p/sandbox/github/withastro/astro/tree/latest/examples/with-tailwindcss) Astro comes with [Tailwind](https://tailwindcss.com) support out of the box. This example showcases how to style your Astro project with Tailwind. diff --git a/examples/with-vite-plugin-pwa/README.md b/examples/with-vite-plugin-pwa/README.md index 7abd4e9ea61e..f8f792eb3fa7 100644 --- a/examples/with-vite-plugin-pwa/README.md +++ b/examples/with-vite-plugin-pwa/README.md @@ -5,7 +5,7 @@ npm create astro@latest -- --template with-vite-plugin-pwa ``` [![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/withastro/astro/tree/latest/examples/with-vite-plugin-pwa) -[![Open with CodeSandbox](https://assets.codesandbox.io/github/button-edit-lime.svg)](https://codesandbox.io/s/github/withastro/astro/tree/latest/examples/with-vite-plugin-pwa) +[![Open with CodeSandbox](https://assets.codesandbox.io/github/button-edit-lime.svg)](https://codesandbox.io/p/sandbox/github/withastro/astro/tree/latest/examples/with-vite-plugin-pwa) > πŸ§‘β€πŸš€ **Seasoned astronaut?** Delete this file. Have fun! diff --git a/examples/with-vitest/README.md b/examples/with-vitest/README.md index 94b63ee4ecef..103cdbb6107e 100644 --- a/examples/with-vitest/README.md +++ b/examples/with-vitest/README.md @@ -5,6 +5,6 @@ npm create astro@latest -- --template with-vitest ``` [![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/withastro/astro/tree/latest/examples/with-vitest) -[![Open with CodeSandbox](https://assets.codesandbox.io/github/button-edit-lime.svg)](https://codesandbox.io/s/github/withastro/astro/tree/latest/examples/with-vitest) +[![Open with CodeSandbox](https://assets.codesandbox.io/github/button-edit-lime.svg)](https://codesandbox.io/p/sandbox/github/withastro/astro/tree/latest/examples/with-vitest) This example showcases Astro working with [Vitest](https://vitest.dev/). From bf8d7366acb57e1b21181cc40fff55a821d8119e Mon Sep 17 00:00:00 2001 From: Ben Holmes Date: Fri, 3 Feb 2023 15:52:05 -0500 Subject: [PATCH 03/11] [Content collections] Load content config with full Vite setup (#6092) * feat: use vite dev server for content config * refactor: improve export naming * chore: update `sync` to spin up server * refactor: run sync before build in cli * fix: move sync call to build setup * chore: clean up attachContent... types * chore: remove unneeded comment * chore: changeset * fix: attachContentServerListeners in unit tests * fix: allow forced contentDirExists * chore: update schema signature * fix: move content listeners to unit test * chore remove contentDirExists flag; unused * chore: stub weird unit test fix --- .changeset/friendly-bobcats-warn.md | 5 + packages/astro/src/cli/sync/index.ts | 21 +- packages/astro/src/content/index.ts | 3 +- .../astro/src/content/server-listeners.ts | 73 +++++++ packages/astro/src/content/types-generator.ts | 7 +- packages/astro/src/content/utils.ts | 23 +-- .../content/vite-plugin-content-imports.ts | 129 ++++++++++++ .../src/content/vite-plugin-content-server.ts | 195 ------------------ packages/astro/src/core/build/index.ts | 7 + packages/astro/src/core/create-vite.ts | 4 +- packages/astro/src/core/dev/dev.ts | 3 + .../units/dev/collections-renderentry.test.js | 52 +++-- 12 files changed, 286 insertions(+), 236 deletions(-) create mode 100644 .changeset/friendly-bobcats-warn.md create mode 100644 packages/astro/src/content/server-listeners.ts create mode 100644 packages/astro/src/content/vite-plugin-content-imports.ts delete mode 100644 packages/astro/src/content/vite-plugin-content-server.ts diff --git a/.changeset/friendly-bobcats-warn.md b/.changeset/friendly-bobcats-warn.md new file mode 100644 index 000000000000..54251cc3ebca --- /dev/null +++ b/.changeset/friendly-bobcats-warn.md @@ -0,0 +1,5 @@ +--- +'astro': patch +--- + +Ensure vite config (aliases, custom modules, etc) is respected when loading the content collection config diff --git a/packages/astro/src/cli/sync/index.ts b/packages/astro/src/cli/sync/index.ts index 92cd05651a9b..775bc8d68992 100644 --- a/packages/astro/src/cli/sync/index.ts +++ b/packages/astro/src/cli/sync/index.ts @@ -1,9 +1,12 @@ import { dim } from 'kleur/colors'; import type fsMod from 'node:fs'; import { performance } from 'node:perf_hooks'; +import { createServer } from 'vite'; import type { AstroSettings } from '../../@types/astro'; -import { contentObservable, createContentTypesGenerator } from '../../content/index.js'; +import { createContentTypesGenerator } from '../../content/index.js'; +import { globalContentConfigObserver } from '../../content/utils.js'; import { getTimeStat } from '../../core/build/util.js'; +import { createVite } from '../../core/create-vite.js'; import { AstroError, AstroErrorData } from '../../core/errors/index.js'; import { info, LogOptions } from '../../core/logger/core.js'; import { setUpEnvTs } from '../../vite-plugin-inject-env-ts/index.js'; @@ -13,13 +16,25 @@ export async function sync( { logging, fs }: { logging: LogOptions; fs: typeof fsMod } ): Promise<0 | 1> { const timerStart = performance.now(); + // Needed to load content config + const tempViteServer = await createServer( + await createVite( + { + server: { middlewareMode: true, hmr: false }, + optimizeDeps: { entries: [] }, + logLevel: 'silent', + }, + { settings, logging, mode: 'build', fs } + ) + ); try { const contentTypesGenerator = await createContentTypesGenerator({ - contentConfigObserver: contentObservable({ status: 'loading' }), + contentConfigObserver: globalContentConfigObserver, logging, fs, settings, + viteServer: tempViteServer, }); const typesResult = await contentTypesGenerator.init(); if (typesResult.typesGenerated === false) { @@ -32,6 +47,8 @@ export async function sync( } } catch (e) { throw new AstroError(AstroErrorData.GenerateContentTypesError); + } finally { + await tempViteServer.close(); } info(logging, 'content', `Types generated ${dim(getTimeStat(timerStart, performance.now()))}`); diff --git a/packages/astro/src/content/index.ts b/packages/astro/src/content/index.ts index a2eae67ed532..36f810de6f7e 100644 --- a/packages/astro/src/content/index.ts +++ b/packages/astro/src/content/index.ts @@ -4,5 +4,6 @@ export { astroContentAssetPropagationPlugin, astroContentProdBundlePlugin, } from './vite-plugin-content-assets.js'; -export { astroContentServerPlugin } from './vite-plugin-content-server.js'; +export { astroContentImportPlugin } from './vite-plugin-content-imports.js'; +export { attachContentServerListeners } from './server-listeners.js'; export { astroContentVirtualModPlugin } from './vite-plugin-content-virtual-mod.js'; diff --git a/packages/astro/src/content/server-listeners.ts b/packages/astro/src/content/server-listeners.ts new file mode 100644 index 000000000000..a6417b7f4331 --- /dev/null +++ b/packages/astro/src/content/server-listeners.ts @@ -0,0 +1,73 @@ +import { cyan } from 'kleur/colors'; +import { pathToFileURL } from 'node:url'; +import type fsMod from 'node:fs'; +import type { ViteDevServer } from 'vite'; +import type { AstroSettings } from '../@types/astro.js'; +import { info, LogOptions } from '../core/logger/core.js'; +import { appendForwardSlash } from '../core/path.js'; +import { createContentTypesGenerator } from './types-generator.js'; +import { globalContentConfigObserver, getContentPaths } from './utils.js'; + +interface ContentServerListenerParams { + fs: typeof fsMod; + logging: LogOptions; + settings: AstroSettings; + viteServer: ViteDevServer; +} + +export async function attachContentServerListeners({ + viteServer, + fs, + logging, + settings, +}: ContentServerListenerParams) { + const contentPaths = getContentPaths(settings.config); + + if (fs.existsSync(contentPaths.contentDir)) { + info( + logging, + 'content', + `Watching ${cyan( + contentPaths.contentDir.href.replace(settings.config.root.href, '') + )} for changes` + ); + await attachListeners(); + } else { + viteServer.watcher.on('addDir', contentDirListener); + async function contentDirListener(dir: string) { + if (appendForwardSlash(pathToFileURL(dir).href) === contentPaths.contentDir.href) { + info(logging, 'content', `Content dir found. Watching for changes`); + await attachListeners(); + viteServer.watcher.removeListener('addDir', contentDirListener); + } + } + } + + async function attachListeners() { + const contentGenerator = await createContentTypesGenerator({ + fs, + settings, + logging, + viteServer, + contentConfigObserver: globalContentConfigObserver, + }); + await contentGenerator.init(); + info(logging, 'content', 'Types generated'); + + viteServer.watcher.on('add', (entry) => { + contentGenerator.queueEvent({ name: 'add', entry }); + }); + viteServer.watcher.on('addDir', (entry) => + contentGenerator.queueEvent({ name: 'addDir', entry }) + ); + viteServer.watcher.on('change', (entry) => + contentGenerator.queueEvent({ name: 'change', entry }) + ); + viteServer.watcher.on('unlink', (entry) => { + contentGenerator.queueEvent({ name: 'unlink', entry }); + }); + viteServer.watcher.on('unlinkDir', (entry) => + contentGenerator.queueEvent({ name: 'unlinkDir', entry }) + ); + } +} diff --git a/packages/astro/src/content/types-generator.ts b/packages/astro/src/content/types-generator.ts index b6f359b2cd85..da0e84dcc23f 100644 --- a/packages/astro/src/content/types-generator.ts +++ b/packages/astro/src/content/types-generator.ts @@ -3,7 +3,7 @@ import { cyan } from 'kleur/colors'; import type fsMod from 'node:fs'; import * as path from 'node:path'; import { fileURLToPath, pathToFileURL } from 'node:url'; -import { normalizePath } from 'vite'; +import { normalizePath, ViteDevServer } from 'vite'; import type { AstroSettings } from '../@types/astro.js'; import { info, LogOptions, warn } from '../core/logger/core.js'; import { appendForwardSlash, isRelativePath } from '../core/path.js'; @@ -32,6 +32,8 @@ type CreateContentGeneratorParams = { contentConfigObserver: ContentObservable; logging: LogOptions; settings: AstroSettings; + /** This is required for loading the content config */ + viteServer: ViteDevServer; fs: typeof fsMod; }; @@ -44,6 +46,7 @@ export async function createContentTypesGenerator({ fs, logging, settings, + viteServer, }: CreateContentGeneratorParams) { const contentTypes: ContentTypes = {}; const contentPaths = getContentPaths(settings.config); @@ -113,7 +116,7 @@ export async function createContentTypesGenerator({ } if (fileType === 'config') { contentConfigObserver.set({ status: 'loading' }); - const config = await loadContentConfig({ fs, settings }); + const config = await loadContentConfig({ fs, settings, viteServer }); if (config) { contentConfigObserver.set({ status: 'loaded', config }); } else { diff --git a/packages/astro/src/content/utils.ts b/packages/astro/src/content/utils.ts index 5a3279f93f09..ff6930723ebd 100644 --- a/packages/astro/src/content/utils.ts +++ b/packages/astro/src/content/utils.ts @@ -205,34 +205,32 @@ export function parseFrontmatter(fileContents: string, filePath: string) { } } +/** + * The content config is loaded separately from other `src/` files. + * This global observable lets dependent plugins (like the content flag plugin) + * subscribe to changes during dev server updates. + */ +export const globalContentConfigObserver = contentObservable({ status: 'init' }); + export async function loadContentConfig({ fs, settings, + viteServer, }: { fs: typeof fsMod; settings: AstroSettings; + viteServer: ViteDevServer; }): Promise { const contentPaths = getContentPaths(settings.config); - const tempConfigServer: ViteDevServer = await createServer({ - root: fileURLToPath(settings.config.root), - server: { middlewareMode: true, hmr: false }, - optimizeDeps: { entries: [] }, - clearScreen: false, - appType: 'custom', - logLevel: 'silent', - plugins: [astroContentVirtualModPlugin({ settings })], - }); let unparsedConfig; if (!fs.existsSync(contentPaths.config)) { return undefined; } try { const configPathname = fileURLToPath(contentPaths.config); - unparsedConfig = await tempConfigServer.ssrLoadModule(configPathname); + unparsedConfig = await viteServer.ssrLoadModule(configPathname); } catch (e) { throw e; - } finally { - await tempConfigServer.close(); } const config = contentConfigParser.safeParse(unparsedConfig); if (config.success) { @@ -243,6 +241,7 @@ export async function loadContentConfig({ } type ContentCtx = + | { status: 'init' } | { status: 'loading' } | { status: 'error' } | { status: 'loaded'; config: ContentConfig }; diff --git a/packages/astro/src/content/vite-plugin-content-imports.ts b/packages/astro/src/content/vite-plugin-content-imports.ts new file mode 100644 index 000000000000..5ba8c9b1ca3a --- /dev/null +++ b/packages/astro/src/content/vite-plugin-content-imports.ts @@ -0,0 +1,129 @@ +import * as devalue from 'devalue'; +import { pathToFileURL } from 'url'; +import type { Plugin } from 'vite'; +import type fsMod from 'node:fs'; +import { AstroSettings } from '../@types/astro.js'; +import { contentFileExts, CONTENT_FLAG } from './consts.js'; +import { + ContentConfig, + globalContentConfigObserver, + getContentPaths, + getEntryData, + getEntryInfo, + getEntrySlug, + parseFrontmatter, +} from './utils.js'; +import { escapeViteEnvReferences, getFileInfo } from '../vite-plugin-utils/index.js'; +import { getEntryType } from './types-generator.js'; +import { AstroError } from '../core/errors/errors.js'; +import { AstroErrorData } from '../core/errors/errors-data.js'; + +function isContentFlagImport(viteId: string) { + const { pathname, searchParams } = new URL(viteId, 'file://'); + return searchParams.has(CONTENT_FLAG) && contentFileExts.some((ext) => pathname.endsWith(ext)); +} + +export function astroContentImportPlugin({ + fs, + settings, +}: { + fs: typeof fsMod; + settings: AstroSettings; +}): Plugin { + const contentPaths = getContentPaths(settings.config); + + return { + name: 'astro:content-imports', + async load(id) { + const { fileId } = getFileInfo(id, settings.config); + if (isContentFlagImport(id)) { + const observable = globalContentConfigObserver.get(); + + // Content config should be loaded before this plugin is used + if (observable.status === 'init') { + throw new AstroError({ + ...AstroErrorData.UnknownContentCollectionError, + message: 'Content config failed to load.', + }); + } + + let contentConfig: ContentConfig | undefined = + observable.status === 'loaded' ? observable.config : undefined; + if (observable.status === 'loading') { + // Wait for config to load + contentConfig = await new Promise((resolve) => { + const unsubscribe = globalContentConfigObserver.subscribe((ctx) => { + if (ctx.status === 'loaded') { + resolve(ctx.config); + unsubscribe(); + } else if (ctx.status === 'error') { + resolve(undefined); + unsubscribe(); + } + }); + }); + } + const rawContents = await fs.promises.readFile(fileId, 'utf-8'); + const { + content: body, + data: unparsedData, + matter: rawData = '', + } = parseFrontmatter(rawContents, fileId); + const entryInfo = getEntryInfo({ + entry: pathToFileURL(fileId), + contentDir: contentPaths.contentDir, + }); + if (entryInfo instanceof Error) return; + + const _internal = { filePath: fileId, rawData }; + const partialEntry = { data: unparsedData, body, _internal, ...entryInfo }; + // TODO: move slug calculation to the start of the build + // to generate a performant lookup map for `getEntryBySlug` + const slug = getEntrySlug(partialEntry); + + const collectionConfig = contentConfig?.collections[entryInfo.collection]; + const data = collectionConfig + ? await getEntryData(partialEntry, collectionConfig) + : unparsedData; + + const code = escapeViteEnvReferences(` +export const id = ${JSON.stringify(entryInfo.id)}; +export const collection = ${JSON.stringify(entryInfo.collection)}; +export const slug = ${JSON.stringify(slug)}; +export const body = ${JSON.stringify(body)}; +export const data = ${devalue.uneval(data) /* TODO: reuse astro props serializer */}; +export const _internal = { + filePath: ${JSON.stringify(fileId)}, + rawData: ${JSON.stringify(rawData)}, +}; +`); + return { code }; + } + }, + configureServer(viteServer) { + viteServer.watcher.on('all', async (event, entry) => { + if ( + ['add', 'unlink', 'change'].includes(event) && + getEntryType(entry, contentPaths) === 'config' + ) { + // Content modules depend on config, so we need to invalidate them. + for (const modUrl of viteServer.moduleGraph.urlToModuleMap.keys()) { + if (isContentFlagImport(modUrl)) { + const mod = await viteServer.moduleGraph.getModuleByUrl(modUrl); + if (mod) { + viteServer.moduleGraph.invalidateModule(mod); + } + } + } + } + }); + }, + async transform(code, id) { + if (isContentFlagImport(id)) { + // Escape before Rollup internal transform. + // Base on MUCH trial-and-error, inspired by MDX integration 2-step transform. + return { code: escapeViteEnvReferences(code) }; + } + }, + }; +} diff --git a/packages/astro/src/content/vite-plugin-content-server.ts b/packages/astro/src/content/vite-plugin-content-server.ts deleted file mode 100644 index a0399b94e56b..000000000000 --- a/packages/astro/src/content/vite-plugin-content-server.ts +++ /dev/null @@ -1,195 +0,0 @@ -import * as devalue from 'devalue'; -import { cyan } from 'kleur/colors'; -import fsMod from 'node:fs'; -import { pathToFileURL } from 'node:url'; -import type { Plugin } from 'vite'; -import type { AstroSettings } from '../@types/astro.js'; -import { info, LogOptions } from '../core/logger/core.js'; -import { appendForwardSlash } from '../core/path.js'; -import { escapeViteEnvReferences, getFileInfo } from '../vite-plugin-utils/index.js'; -import { contentFileExts, CONTENT_FLAG } from './consts.js'; -import { createContentTypesGenerator, getEntryType } from './types-generator.js'; -import { - ContentConfig, - contentObservable, - getContentPaths, - getEntryData, - getEntryInfo, - getEntrySlug, - parseFrontmatter, -} from './utils.js'; - -interface AstroContentServerPluginParams { - fs: typeof fsMod; - logging: LogOptions; - settings: AstroSettings; - mode: string; -} - -export function astroContentServerPlugin({ - fs, - settings, - logging, - mode, -}: AstroContentServerPluginParams): Plugin[] { - const contentPaths = getContentPaths(settings.config); - const contentConfigObserver = contentObservable({ status: 'loading' }); - - async function initContentGenerator() { - const contentGenerator = await createContentTypesGenerator({ - fs, - settings, - logging, - contentConfigObserver, - }); - await contentGenerator.init(); - return contentGenerator; - } - - return [ - { - name: 'astro-content-server-plugin', - async config(viteConfig) { - // Production build type gen - if (fs.existsSync(contentPaths.contentDir) && viteConfig.build?.ssr === true) { - await initContentGenerator(); - } - }, - async configureServer(viteServer) { - if (mode !== 'dev') return; - - // Dev server type gen - if (fs.existsSync(contentPaths.contentDir)) { - info( - logging, - 'content', - `Watching ${cyan( - contentPaths.contentDir.href.replace(settings.config.root.href, '') - )} for changes` - ); - await attachListeners(); - } else { - viteServer.watcher.on('addDir', contentDirListener); - async function contentDirListener(dir: string) { - if (appendForwardSlash(pathToFileURL(dir).href) === contentPaths.contentDir.href) { - info(logging, 'content', `Content dir found. Watching for changes`); - await attachListeners(); - viteServer.watcher.removeListener('addDir', contentDirListener); - } - } - } - - async function attachListeners() { - const contentGenerator = await initContentGenerator(); - info(logging, 'content', 'Types generated'); - - viteServer.watcher.on('add', (entry) => { - contentGenerator.queueEvent({ name: 'add', entry }); - }); - viteServer.watcher.on('addDir', (entry) => - contentGenerator.queueEvent({ name: 'addDir', entry }) - ); - viteServer.watcher.on('change', (entry) => - contentGenerator.queueEvent({ name: 'change', entry }) - ); - viteServer.watcher.on('unlink', (entry) => { - contentGenerator.queueEvent({ name: 'unlink', entry }); - }); - viteServer.watcher.on('unlinkDir', (entry) => - contentGenerator.queueEvent({ name: 'unlinkDir', entry }) - ); - } - }, - }, - { - name: 'astro-content-flag-plugin', - async load(id) { - const { fileId } = getFileInfo(id, settings.config); - if (isContentFlagImport(id)) { - const observable = contentConfigObserver.get(); - let contentConfig: ContentConfig | undefined = - observable.status === 'loaded' ? observable.config : undefined; - if (observable.status === 'loading') { - // Wait for config to load - contentConfig = await new Promise((resolve) => { - const unsubscribe = contentConfigObserver.subscribe((ctx) => { - if (ctx.status === 'loaded') { - resolve(ctx.config); - unsubscribe(); - } else if (ctx.status === 'error') { - resolve(undefined); - unsubscribe(); - } - }); - }); - } - const rawContents = await fs.promises.readFile(fileId, 'utf-8'); - const { - content: body, - data: unparsedData, - matter: rawData = '', - } = parseFrontmatter(rawContents, fileId); - const entryInfo = getEntryInfo({ - entry: pathToFileURL(fileId), - contentDir: contentPaths.contentDir, - }); - if (entryInfo instanceof Error) return; - - const _internal = { filePath: fileId, rawData }; - const partialEntry = { data: unparsedData, body, _internal, ...entryInfo }; - // TODO: move slug calculation to the start of the build - // to generate a performant lookup map for `getEntryBySlug` - const slug = getEntrySlug(partialEntry); - - const collectionConfig = contentConfig?.collections[entryInfo.collection]; - const data = collectionConfig - ? await getEntryData(partialEntry, collectionConfig) - : unparsedData; - - const code = escapeViteEnvReferences(` -export const id = ${JSON.stringify(entryInfo.id)}; -export const collection = ${JSON.stringify(entryInfo.collection)}; -export const slug = ${JSON.stringify(slug)}; -export const body = ${JSON.stringify(body)}; -export const data = ${devalue.uneval(data) /* TODO: reuse astro props serializer */}; -export const _internal = { - filePath: ${JSON.stringify(fileId)}, - rawData: ${JSON.stringify(rawData)}, -}; -`); - return { code }; - } - }, - configureServer(viteServer) { - viteServer.watcher.on('all', async (event, entry) => { - if ( - ['add', 'unlink', 'change'].includes(event) && - getEntryType(entry, contentPaths) === 'config' - ) { - // Content modules depend on config, so we need to invalidate them. - for (const modUrl of viteServer.moduleGraph.urlToModuleMap.keys()) { - if (isContentFlagImport(modUrl)) { - const mod = await viteServer.moduleGraph.getModuleByUrl(modUrl); - if (mod) { - viteServer.moduleGraph.invalidateModule(mod); - } - } - } - } - }); - }, - async transform(code, id) { - if (isContentFlagImport(id)) { - // Escape before Rollup internal transform. - // Base on MUCH trial-and-error, inspired by MDX integration 2-step transform. - return { code: escapeViteEnvReferences(code) }; - } - }, - }, - ]; -} - -function isContentFlagImport(viteId: string) { - const { pathname, searchParams } = new URL(viteId, 'file://'); - return searchParams.has(CONTENT_FLAG) && contentFileExts.some((ext) => pathname.endsWith(ext)); -} diff --git a/packages/astro/src/core/build/index.ts b/packages/astro/src/core/build/index.ts index 967723cc5587..a2baa460958c 100644 --- a/packages/astro/src/core/build/index.ts +++ b/packages/astro/src/core/build/index.ts @@ -80,6 +80,13 @@ class AstroBuilder { { settings: this.settings, logging, mode: 'build' } ); await runHookConfigDone({ settings: this.settings, logging }); + + const { sync } = await import('../../cli/sync/index.js'); + const syncRet = await sync(this.settings, { logging, fs }); + if (syncRet !== 0) { + return process.exit(syncRet); + } + return { viteConfig }; } diff --git a/packages/astro/src/core/create-vite.ts b/packages/astro/src/core/create-vite.ts index 9708466c9215..5ebd05f55874 100644 --- a/packages/astro/src/core/create-vite.ts +++ b/packages/astro/src/core/create-vite.ts @@ -7,7 +7,7 @@ import * as vite from 'vite'; import { crawlFrameworkPkgs } from 'vitefu'; import { astroContentAssetPropagationPlugin, - astroContentServerPlugin, + astroContentImportPlugin, astroContentVirtualModPlugin, } from '../content/index.js'; import astroPostprocessVitePlugin from '../vite-plugin-astro-postprocess/index.js'; @@ -105,7 +105,7 @@ export async function createVite( astroScannerPlugin({ settings }), astroInjectEnvTsPlugin({ settings, logging, fs }), astroContentVirtualModPlugin({ settings }), - astroContentServerPlugin({ fs, settings, logging, mode }), + astroContentImportPlugin({ fs, settings }), astroContentAssetPropagationPlugin({ mode }), ], publicDir: fileURLToPath(settings.config.publicDir), diff --git a/packages/astro/src/core/dev/dev.ts b/packages/astro/src/core/dev/dev.ts index 9682ac796fb6..4fcac87fafd1 100644 --- a/packages/astro/src/core/dev/dev.ts +++ b/packages/astro/src/core/dev/dev.ts @@ -5,6 +5,7 @@ import { performance } from 'perf_hooks'; import * as vite from 'vite'; import yargs from 'yargs-parser'; import type { AstroSettings } from '../../@types/astro'; +import { attachContentServerListeners } from '../../content/index.js'; import { info, LogOptions, warn } from '../logger/core.js'; import * as msg from '../messages.js'; import { startContainer } from './container.js'; @@ -71,6 +72,8 @@ export default async function dev( warn(options.logging, null, msg.fsStrictWarning()); } + await attachContentServerListeners(restart.container); + return { address: devServerAddressInfo, get watcher() { diff --git a/packages/astro/test/units/dev/collections-renderentry.test.js b/packages/astro/test/units/dev/collections-renderentry.test.js index fa720f97b84c..730ec194f6d6 100644 --- a/packages/astro/test/units/dev/collections-renderentry.test.js +++ b/packages/astro/test/units/dev/collections-renderentry.test.js @@ -5,11 +5,19 @@ import { runInContainer } from '../../../dist/core/dev/index.js'; import { createFsWithFallback, createRequestAndResponse } from '../test-utils.js'; import { isWindows } from '../../test-utils.js'; import mdx from '../../../../integrations/mdx/dist/index.js'; +import { attachContentServerListeners } from '../../../dist/content/server-listeners.js'; const root = new URL('../../fixtures/content/', import.meta.url); const describe = isWindows ? global.describe.skip : global.describe; +async function runInContainerWithContentListeners(params, callback) { + return await runInContainer(params, async (container) => { + await attachContentServerListeners(container); + await callback(container); + }); +} + describe('Content Collections - render()', () => { it('can be called in a page component', async () => { const fs = createFsWithFallback( @@ -18,10 +26,10 @@ describe('Content Collections - render()', () => { import { z, defineCollection } from 'astro:content'; const blog = defineCollection({ - schema: { + schema: z.object({ title: z.string(), description: z.string().max(60, 'For SEO purposes, keep descriptions short!'), - }, + }), }); export const collections = { blog }; @@ -40,7 +48,7 @@ describe('Content Collections - render()', () => { root ); - await runInContainer( + await runInContainerWithContentListeners( { fs, root, @@ -71,18 +79,18 @@ describe('Content Collections - render()', () => { it('can be used in a layout component', async () => { const fs = createFsWithFallback( { - '/src/content/config.ts': ` - import { z, defineCollection } from 'astro:content'; - - const blog = defineCollection({ - schema: { - title: z.string(), - description: z.string().max(60, 'For SEO purposes, keep descriptions short!'), - }, - }); - - export const collections = { blog }; - `, + // Loading the content config with `astro:content` oddly + // causes this test to fail. Spoof a different src/content entry + // to ensure `existsSync` checks pass. + // TODO: revisit after addressing this issue + // https://github.com/withastro/astro/issues/6121 + '/src/content/blog/promo/launch-week.mdx': `--- +title: Launch Week +description: Astro is launching this week! +--- +# Launch Week +- [x] Launch Astro +- [ ] Celebrate`, '/src/components/Layout.astro': ` --- import { getCollection } from 'astro:content'; @@ -113,7 +121,7 @@ describe('Content Collections - render()', () => { root ); - await runInContainer( + await runInContainerWithContentListeners( { fs, root, @@ -148,10 +156,10 @@ describe('Content Collections - render()', () => { import { z, defineCollection } from 'astro:content'; const blog = defineCollection({ - schema: { + schema: z.object({ title: z.string(), description: z.string().max(60, 'For SEO purposes, keep descriptions short!'), - }, + }), }); export const collections = { blog }; @@ -184,7 +192,7 @@ describe('Content Collections - render()', () => { root ); - await runInContainer( + await runInContainerWithContentListeners( { fs, root, @@ -219,10 +227,10 @@ describe('Content Collections - render()', () => { import { z, defineCollection } from 'astro:content'; const blog = defineCollection({ - schema: { + schema: z.object({ title: z.string(), description: z.string().max(60, 'For SEO purposes, keep descriptions short!'), - }, + }), }); export const collections = { blog }; @@ -249,7 +257,7 @@ describe('Content Collections - render()', () => { root ); - await runInContainer( + await runInContainerWithContentListeners( { fs, root, From f7f4721231c5a6ab4bae39d05abe1243f936415e Mon Sep 17 00:00:00 2001 From: bholmesdev Date: Fri, 3 Feb 2023 20:53:53 +0000 Subject: [PATCH 04/11] [ci] format --- packages/astro/src/content/index.ts | 2 +- packages/astro/src/content/server-listeners.ts | 4 ++-- packages/astro/src/content/utils.ts | 3 +-- .../astro/src/content/vite-plugin-content-imports.ts | 12 ++++++------ 4 files changed, 10 insertions(+), 11 deletions(-) diff --git a/packages/astro/src/content/index.ts b/packages/astro/src/content/index.ts index 36f810de6f7e..30936fb626aa 100644 --- a/packages/astro/src/content/index.ts +++ b/packages/astro/src/content/index.ts @@ -1,3 +1,4 @@ +export { attachContentServerListeners } from './server-listeners.js'; export { createContentTypesGenerator } from './types-generator.js'; export { contentObservable, getContentPaths, getDotAstroTypeReference } from './utils.js'; export { @@ -5,5 +6,4 @@ export { astroContentProdBundlePlugin, } from './vite-plugin-content-assets.js'; export { astroContentImportPlugin } from './vite-plugin-content-imports.js'; -export { attachContentServerListeners } from './server-listeners.js'; export { astroContentVirtualModPlugin } from './vite-plugin-content-virtual-mod.js'; diff --git a/packages/astro/src/content/server-listeners.ts b/packages/astro/src/content/server-listeners.ts index a6417b7f4331..f0513d07fa15 100644 --- a/packages/astro/src/content/server-listeners.ts +++ b/packages/astro/src/content/server-listeners.ts @@ -1,12 +1,12 @@ import { cyan } from 'kleur/colors'; -import { pathToFileURL } from 'node:url'; import type fsMod from 'node:fs'; +import { pathToFileURL } from 'node:url'; import type { ViteDevServer } from 'vite'; import type { AstroSettings } from '../@types/astro.js'; import { info, LogOptions } from '../core/logger/core.js'; import { appendForwardSlash } from '../core/path.js'; import { createContentTypesGenerator } from './types-generator.js'; -import { globalContentConfigObserver, getContentPaths } from './utils.js'; +import { getContentPaths, globalContentConfigObserver } from './utils.js'; interface ContentServerListenerParams { fs: typeof fsMod; diff --git a/packages/astro/src/content/utils.ts b/packages/astro/src/content/utils.ts index ff6930723ebd..a2c4631896dc 100644 --- a/packages/astro/src/content/utils.ts +++ b/packages/astro/src/content/utils.ts @@ -3,12 +3,11 @@ import matter from 'gray-matter'; import type fsMod from 'node:fs'; import path from 'node:path'; import { fileURLToPath } from 'node:url'; -import { createServer, ErrorPayload as ViteErrorPayload, normalizePath, ViteDevServer } from 'vite'; +import { ErrorPayload as ViteErrorPayload, normalizePath, ViteDevServer } from 'vite'; import { z } from 'zod'; import { AstroConfig, AstroSettings } from '../@types/astro.js'; import { AstroError, AstroErrorData } from '../core/errors/index.js'; import { CONTENT_TYPES_FILE } from './consts.js'; -import { astroContentVirtualModPlugin } from './vite-plugin-content-virtual-mod.js'; export const collectionConfigParser = z.object({ schema: z.any().optional(), diff --git a/packages/astro/src/content/vite-plugin-content-imports.ts b/packages/astro/src/content/vite-plugin-content-imports.ts index 5ba8c9b1ca3a..66d20d7031ae 100644 --- a/packages/astro/src/content/vite-plugin-content-imports.ts +++ b/packages/astro/src/content/vite-plugin-content-imports.ts @@ -1,22 +1,22 @@ import * as devalue from 'devalue'; +import type fsMod from 'node:fs'; import { pathToFileURL } from 'url'; import type { Plugin } from 'vite'; -import type fsMod from 'node:fs'; import { AstroSettings } from '../@types/astro.js'; +import { AstroErrorData } from '../core/errors/errors-data.js'; +import { AstroError } from '../core/errors/errors.js'; +import { escapeViteEnvReferences, getFileInfo } from '../vite-plugin-utils/index.js'; import { contentFileExts, CONTENT_FLAG } from './consts.js'; +import { getEntryType } from './types-generator.js'; import { ContentConfig, - globalContentConfigObserver, getContentPaths, getEntryData, getEntryInfo, getEntrySlug, + globalContentConfigObserver, parseFrontmatter, } from './utils.js'; -import { escapeViteEnvReferences, getFileInfo } from '../vite-plugin-utils/index.js'; -import { getEntryType } from './types-generator.js'; -import { AstroError } from '../core/errors/errors.js'; -import { AstroErrorData } from '../core/errors/errors-data.js'; function isContentFlagImport(viteId: string) { const { pathname, searchParams } = new URL(viteId, 'file://'); From 9f22ac3d097ef2cb3b2bbe5343b8a8a49d83425d Mon Sep 17 00:00:00 2001 From: Ben Holmes Date: Fri, 3 Feb 2023 16:48:34 -0500 Subject: [PATCH 05/11] [Content collections] Fix "underscore to ignore" warnings (#6122) * refactor: fix underscore check * fix: add "ignore list" to always silence log * fix: hide log on file deleted * refactor: move getEntryType to util * test: getEntryType unit * fix: handle all unsupported cases * chore: changeset --- .changeset/grumpy-bees-worry.md | 5 ++ packages/astro/src/content/types-generator.ts | 45 +++++--------- packages/astro/src/content/utils.ts | 37 ++++++++++- .../content/vite-plugin-content-imports.ts | 2 +- .../get-entry-type.test.js | 62 +++++++++++++++++++ 5 files changed, 117 insertions(+), 34 deletions(-) create mode 100644 .changeset/grumpy-bees-worry.md create mode 100644 packages/astro/test/units/content-collections/get-entry-type.test.js diff --git a/.changeset/grumpy-bees-worry.md b/.changeset/grumpy-bees-worry.md new file mode 100644 index 000000000000..bab88ad25eba --- /dev/null +++ b/.changeset/grumpy-bees-worry.md @@ -0,0 +1,5 @@ +--- +'astro': patch +--- + +Content collections: Fix accidental "use underscore to ignore" logs for `.DS_Store` files and underscored directory names. diff --git a/packages/astro/src/content/types-generator.ts b/packages/astro/src/content/types-generator.ts index da0e84dcc23f..50f8088ded2c 100644 --- a/packages/astro/src/content/types-generator.ts +++ b/packages/astro/src/content/types-generator.ts @@ -6,8 +6,8 @@ import { fileURLToPath, pathToFileURL } from 'node:url'; import { normalizePath, ViteDevServer } from 'vite'; import type { AstroSettings } from '../@types/astro.js'; import { info, LogOptions, warn } from '../core/logger/core.js'; -import { appendForwardSlash, isRelativePath } from '../core/path.js'; -import { contentFileExts, CONTENT_TYPES_FILE } from './consts.js'; +import { isRelativePath } from '../core/path.js'; +import { CONTENT_TYPES_FILE } from './consts.js'; import { ContentConfig, ContentObservable, @@ -16,6 +16,7 @@ import { getContentPaths, getEntryInfo, getEntrySlug, + getEntryType, loadContentConfig, NoCollectionError, parseFrontmatter, @@ -111,7 +112,7 @@ export async function createContentTypesGenerator({ return { shouldGenerateTypes: true }; } const fileType = getEntryType(fileURLToPath(event.entry), contentPaths); - if (fileType === 'generated-types') { + if (fileType === 'ignored') { return { shouldGenerateTypes: false }; } if (fileType === 'config') { @@ -125,22 +126,21 @@ export async function createContentTypesGenerator({ return { shouldGenerateTypes: true }; } - if (fileType === 'unknown') { + if (fileType === 'unsupported') { + // Avoid warning if file was deleted. + if (event.name === 'unlink') { + return { shouldGenerateTypes: false }; + } const entryInfo = getEntryInfo({ entry: event.entry, contentDir: contentPaths.contentDir, - // Allow underscore `_` files outside collection directories + // Skip invalid file check. We already know it’s invalid. allowFilesOutsideCollection: true, }); - if (entryInfo.id.startsWith('_') && (event.name === 'add' || event.name === 'change')) { - // Silently ignore `_` files. - return { shouldGenerateTypes: false }; - } else { - return { - shouldGenerateTypes: false, - error: new UnsupportedFileTypeError(entryInfo.id), - }; - } + return { + shouldGenerateTypes: false, + error: new UnsupportedFileTypeError(entryInfo.id), + }; } const entryInfo = getEntryInfo({ entry: event.entry, @@ -289,23 +289,6 @@ function removeEntry(contentTypes: ContentTypes, collectionKey: string, entryKey delete contentTypes[collectionKey][entryKey]; } -export function getEntryType( - entryPath: string, - paths: ContentPaths -): 'content' | 'config' | 'unknown' | 'generated-types' { - const { dir: rawDir, ext, base } = path.parse(entryPath); - const dir = appendForwardSlash(pathToFileURL(rawDir).href); - if ((contentFileExts as readonly string[]).includes(ext)) { - return 'content'; - } else if (new URL(base, dir).href === paths.config.href) { - return 'config'; - } else if (new URL(base, dir).href === new URL(CONTENT_TYPES_FILE, paths.cacheDir).href) { - return 'generated-types'; - } else { - return 'unknown'; - } -} - async function writeContentFiles({ fs, contentPaths, diff --git a/packages/astro/src/content/utils.ts b/packages/astro/src/content/utils.ts index a2c4631896dc..a1ddba757037 100644 --- a/packages/astro/src/content/utils.ts +++ b/packages/astro/src/content/utils.ts @@ -2,12 +2,13 @@ import { slug as githubSlug } from 'github-slugger'; import matter from 'gray-matter'; import type fsMod from 'node:fs'; import path from 'node:path'; -import { fileURLToPath } from 'node:url'; +import { fileURLToPath, pathToFileURL } from 'node:url'; import { ErrorPayload as ViteErrorPayload, normalizePath, ViteDevServer } from 'vite'; import { z } from 'zod'; import { AstroConfig, AstroSettings } from '../@types/astro.js'; import { AstroError, AstroErrorData } from '../core/errors/index.js'; -import { CONTENT_TYPES_FILE } from './consts.js'; +import { appendForwardSlash } from '../core/path.js'; +import { contentFileExts, CONTENT_TYPES_FILE } from './consts.js'; export const collectionConfigParser = z.object({ schema: z.any().optional(), @@ -158,6 +159,38 @@ export function getEntryInfo({ return res; } +export function getEntryType( + entryPath: string, + paths: Pick +): 'content' | 'config' | 'ignored' | 'unsupported' { + const { dir: rawDir, ext, base } = path.parse(entryPath); + const dir = appendForwardSlash(pathToFileURL(rawDir).href); + const fileUrl = new URL(base, dir); + + if (hasUnderscoreInPath(fileUrl) || isOnIgnoreList(fileUrl)) { + return 'ignored'; + } else if ((contentFileExts as readonly string[]).includes(ext)) { + return 'content'; + } else if (fileUrl.href === paths.config.href) { + return 'config'; + } else { + return 'unsupported'; + } +} + +function isOnIgnoreList(fileUrl: URL) { + const { base } = path.parse(fileURLToPath(fileUrl)); + return ['.DS_Store'].includes(base); +} + +function hasUnderscoreInPath(fileUrl: URL): boolean { + const parts = fileUrl.pathname.split('/'); + for (const part of parts) { + if (part.startsWith('_')) return true; + } + return false; +} + const flattenErrorPath = (errorPath: (string | number)[]) => errorPath.join('.'); const errorMap: z.ZodErrorMap = (error, ctx) => { diff --git a/packages/astro/src/content/vite-plugin-content-imports.ts b/packages/astro/src/content/vite-plugin-content-imports.ts index 66d20d7031ae..7c7e8f65c6c7 100644 --- a/packages/astro/src/content/vite-plugin-content-imports.ts +++ b/packages/astro/src/content/vite-plugin-content-imports.ts @@ -7,7 +7,7 @@ import { AstroErrorData } from '../core/errors/errors-data.js'; import { AstroError } from '../core/errors/errors.js'; import { escapeViteEnvReferences, getFileInfo } from '../vite-plugin-utils/index.js'; import { contentFileExts, CONTENT_FLAG } from './consts.js'; -import { getEntryType } from './types-generator.js'; +import { getEntryType } from './utils.js'; import { ContentConfig, getContentPaths, diff --git a/packages/astro/test/units/content-collections/get-entry-type.test.js b/packages/astro/test/units/content-collections/get-entry-type.test.js new file mode 100644 index 000000000000..3248a88f617e --- /dev/null +++ b/packages/astro/test/units/content-collections/get-entry-type.test.js @@ -0,0 +1,62 @@ +import { getEntryType } from '../../../dist/content/utils.js'; +import { expect } from 'chai'; +import { fileURLToPath } from 'node:url'; + +describe('Content Collections - getEntryType', () => { + const contentDir = new URL('src/content/', import.meta.url); + const contentPaths = { + config: new URL('src/content/config.ts', import.meta.url), + }; + + it('Returns "content" for Markdown files', () => { + for (const entryPath of ['blog/first-post.md', 'blog/first-post.mdx']) { + const entry = fileURLToPath(new URL(entryPath, contentDir)); + const type = getEntryType(entry, contentPaths); + expect(type).to.equal('content'); + } + }); + + it('Returns "content" for Markdown files in nested directories', () => { + for (const entryPath of ['blog/2021/01/01/index.md', 'blog/2021/01/01/index.mdx']) { + const entry = fileURLToPath(new URL(entryPath, contentDir)); + const type = getEntryType(entry, contentPaths); + expect(type).to.equal('content'); + } + }); + + it('Returns "config" for config files', () => { + const entry = fileURLToPath(contentPaths.config); + const type = getEntryType(entry, contentPaths); + expect(type).to.equal('config'); + }); + + it('Returns "unsupported" for non-Markdown files', () => { + const entry = fileURLToPath(new URL('blog/robots.txt', contentDir)); + const type = getEntryType(entry, contentPaths); + expect(type).to.equal('unsupported'); + }); + + it('Returns "ignored" for .DS_Store', () => { + const entry = fileURLToPath(new URL('blog/.DS_Store', contentDir)); + const type = getEntryType(entry, contentPaths); + expect(type).to.equal('ignored'); + }); + + it('Returns "ignored" for unsupported files using an underscore', () => { + const entry = fileURLToPath(new URL('blog/_draft-robots.txt', contentDir)); + const type = getEntryType(entry, contentPaths); + expect(type).to.equal('ignored'); + }); + + it('Returns "ignored" when using underscore on file name', () => { + const entry = fileURLToPath(new URL('blog/_first-post.md', contentDir)); + const type = getEntryType(entry, contentPaths); + expect(type).to.equal('ignored'); + }); + + it('Returns "ignored" when using underscore on directory name', () => { + const entry = fileURLToPath(new URL('blog/_draft/first-post.md', contentDir)); + const type = getEntryType(entry, contentPaths); + expect(type).to.equal('ignored'); + }); +}); From 4f150e80b1eede998efdfd5973a780d7fd5ce3b6 Mon Sep 17 00:00:00 2001 From: bholmesdev Date: Fri, 3 Feb 2023 21:50:51 +0000 Subject: [PATCH 06/11] [ci] format --- packages/astro/src/content/vite-plugin-content-imports.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/astro/src/content/vite-plugin-content-imports.ts b/packages/astro/src/content/vite-plugin-content-imports.ts index 7c7e8f65c6c7..9621de0b4a1e 100644 --- a/packages/astro/src/content/vite-plugin-content-imports.ts +++ b/packages/astro/src/content/vite-plugin-content-imports.ts @@ -7,13 +7,13 @@ import { AstroErrorData } from '../core/errors/errors-data.js'; import { AstroError } from '../core/errors/errors.js'; import { escapeViteEnvReferences, getFileInfo } from '../vite-plugin-utils/index.js'; import { contentFileExts, CONTENT_FLAG } from './consts.js'; -import { getEntryType } from './utils.js'; import { ContentConfig, getContentPaths, getEntryData, getEntryInfo, getEntrySlug, + getEntryType, globalContentConfigObserver, parseFrontmatter, } from './utils.js'; From f20a85b642994f240d8c94260fc55ffa1fd14294 Mon Sep 17 00:00:00 2001 From: "Fred K. Schott" Date: Fri, 3 Feb 2023 15:34:09 -0800 Subject: [PATCH 07/11] Fix outdated error message in paginate() function (#6124) * Update paginate.ts * Create gorgeous-mails-sniff.md --- .changeset/gorgeous-mails-sniff.md | 5 +++++ packages/astro/src/core/render/paginate.ts | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 .changeset/gorgeous-mails-sniff.md diff --git a/.changeset/gorgeous-mails-sniff.md b/.changeset/gorgeous-mails-sniff.md new file mode 100644 index 000000000000..32986063a993 --- /dev/null +++ b/.changeset/gorgeous-mails-sniff.md @@ -0,0 +1,5 @@ +--- +"astro": patch +--- + +Fix outdated error message in `paginate()` function. diff --git a/packages/astro/src/core/render/paginate.ts b/packages/astro/src/core/render/paginate.ts index f9da47a26a5d..7bb5eca77a75 100644 --- a/packages/astro/src/core/render/paginate.ts +++ b/packages/astro/src/core/render/paginate.ts @@ -24,7 +24,7 @@ export function generatePaginateFunction(routeMatch: RouteData): PaginateFunctio includesFirstPageNumber = true; } else { throw new Error( - `[paginate()] page number param \`${paramName}\` not found in your filepath.\nRename your file to \`[...page].astro\` or customize the param name via the \`paginate([], {param: '...'}\` option.` + `[paginate()] page number param \`${paramName}\` not found in your filepath.\nRename your file to \`[page].astro\` or \`[...page].astro\`.` ); } const lastPage = Math.max(1, Math.ceil(data.length / pageSize)); From 61d47d25c696c739bc3be5199bc73670a50c71eb Mon Sep 17 00:00:00 2001 From: Malte Ehrlen <42444300+malteehrlen@users.noreply.github.com> Date: Sat, 4 Feb 2023 04:54:39 +0200 Subject: [PATCH 08/11] fix example Card component style (#6123) * fix example Card component style Card component has uneven border on hover, and in some cases the border is visible even when not hovering * Delete neat-taxis-thank.md --------- Co-authored-by: Nate Moore --- examples/basics/src/components/Card.astro | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/examples/basics/src/components/Card.astro b/examples/basics/src/components/Card.astro index ee57d4df4010..c68fa2ab3448 100644 --- a/examples/basics/src/components/Card.astro +++ b/examples/basics/src/components/Card.astro @@ -23,11 +23,11 @@ const { href, title, body } = Astro.props; .link-card { list-style: none; display: flex; - padding: 0.15rem; + padding: 0.25rem; background-color: white; - background-image: var(--accent-gradient); + background-image: none; background-size: 400%; - border-radius: 0.5rem; + border-radius: 0.6rem; background-position: 100%; transition: background-position 0.6s cubic-bezier(0.22, 1, 0.36, 1); box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -2px rgba(0, 0, 0, 0.1); @@ -55,6 +55,7 @@ const { href, title, body } = Astro.props; } .link-card:is(:hover, :focus-within) { background-position: 0; + background-image: var(--accent-gradient); } .link-card:is(:hover, :focus-within) h2 { color: rgb(var(--accent)); From 4595dd66001026164830efca323698bec3c61949 Mon Sep 17 00:00:00 2001 From: Erika <3019731+Princesseuh@users.noreply.github.com> Date: Mon, 6 Feb 2023 16:16:34 +0100 Subject: [PATCH 09/11] fix(webapi): Attempt to polyfill with undici imports directly (#6065) --- packages/webapi/src/ponyfill.ts | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/packages/webapi/src/ponyfill.ts b/packages/webapi/src/ponyfill.ts index 429951e152c1..25c880fda6a0 100644 --- a/packages/webapi/src/ponyfill.ts +++ b/packages/webapi/src/ponyfill.ts @@ -15,7 +15,7 @@ import { WritableStreamDefaultController, WritableStreamDefaultWriter, } from 'node:stream/web' -import * as undici from 'undici' +import { fetch, File, Headers, Request, Response } from 'undici' import { URLPattern } from 'urlpattern-polyfill' import { cancelAnimationFrame, @@ -71,12 +71,6 @@ import { initWindow, Window } from './lib/Window' import { alert } from './lib/Alert' -const fetch = undici.fetch -const Headers = undici.Headers -const Response = undici.Response -const Request = undici.Request -const File = undici.File - export { ByteLengthQueuingStrategy, CanvasRenderingContext2D, From 2189170be523f74f244e84ccab22c655219773ce Mon Sep 17 00:00:00 2001 From: Matthew Phillips Date: Mon, 6 Feb 2023 10:42:08 -0500 Subject: [PATCH 10/11] Fix hoisted script propagation in content collection pages (#6119) * chore: unskip * chore: stray console logs * chore: clarify analyzer comments * wip: store propagated scripts separately * Implement getting hoisted scripts for propagation * Add changeset * fix * oops * update based on code review --------- Co-authored-by: bholmesdev --- .changeset/shaggy-pianos-sleep.md | 5 + packages/astro/src/content/index.ts | 1 - .../src/content/vite-plugin-content-assets.ts | 116 +++++++++++++----- packages/astro/src/core/build/graph.ts | 2 +- packages/astro/src/core/build/page-data.ts | 6 +- .../astro/src/core/build/plugins/index.ts | 2 +- .../src/core/build/plugins/plugin-analyzer.ts | 76 +++++++++--- .../src/core/build/plugins/plugin-css.ts | 4 +- packages/astro/src/core/build/static-build.ts | 5 +- packages/astro/src/core/build/types.ts | 3 +- .../test/content-collections-render.test.js | 6 +- 11 files changed, 169 insertions(+), 57 deletions(-) create mode 100644 .changeset/shaggy-pianos-sleep.md diff --git a/.changeset/shaggy-pianos-sleep.md b/.changeset/shaggy-pianos-sleep.md new file mode 100644 index 000000000000..47375cf56682 --- /dev/null +++ b/.changeset/shaggy-pianos-sleep.md @@ -0,0 +1,5 @@ +--- +'astro': patch +--- + +Fix hoisted script propagation in content collection pages diff --git a/packages/astro/src/content/index.ts b/packages/astro/src/content/index.ts index 30936fb626aa..818e87e35417 100644 --- a/packages/astro/src/content/index.ts +++ b/packages/astro/src/content/index.ts @@ -3,7 +3,6 @@ export { createContentTypesGenerator } from './types-generator.js'; export { contentObservable, getContentPaths, getDotAstroTypeReference } from './utils.js'; export { astroContentAssetPropagationPlugin, - astroContentProdBundlePlugin, } from './vite-plugin-content-assets.js'; export { astroContentImportPlugin } from './vite-plugin-content-imports.js'; export { astroContentVirtualModPlugin } from './vite-plugin-content-virtual-mod.js'; diff --git a/packages/astro/src/content/vite-plugin-content-assets.ts b/packages/astro/src/content/vite-plugin-content-assets.ts index 89e417a3c5bc..7610d9f9d0db 100644 --- a/packages/astro/src/content/vite-plugin-content-assets.ts +++ b/packages/astro/src/content/vite-plugin-content-assets.ts @@ -1,4 +1,5 @@ import { pathToFileURL } from 'url'; +import npath from 'node:path'; import type { Plugin } from 'vite'; import { moduleIsTopLevelPage, walkParentInfos } from '../core/build/graph.js'; import { BuildInternals, getPageDataByViteID } from '../core/build/internal.js'; @@ -14,6 +15,8 @@ import { SCRIPTS_PLACEHOLDER, STYLES_PLACEHOLDER, } from './consts.js'; +import type { RollupOutput, OutputChunk, StaticBuildOptions } from '../core/build/types'; +import { prependForwardSlash } from '../core/path.js'; function isPropagatedAsset(viteId: string): boolean { const url = new URL(viteId, 'file://'); @@ -73,42 +76,95 @@ export function astroContentAssetPropagationPlugin({ mode }: { mode: string }): }; } -export function astroContentProdBundlePlugin({ internals }: { internals: BuildInternals }): Plugin { - return { - name: 'astro:content-prod-bundle', - async generateBundle(_options, bundle) { - for (const [_, chunk] of Object.entries(bundle)) { - if (chunk.type === 'chunk' && chunk.code.includes(LINKS_PLACEHOLDER)) { - for (const id of Object.keys(chunk.modules)) { - for (const [pageInfo, depth, order] of walkParentInfos(id, this)) { - if (moduleIsTopLevelPage(pageInfo)) { - const pageViteID = pageInfo.id; - const pageData = getPageDataByViteID(internals, pageViteID); - if (!pageData) continue; - const entryCss = pageData.contentCollectionCss?.get(id); - if (!entryCss) continue; - chunk.code = chunk.code.replace( - JSON.stringify(LINKS_PLACEHOLDER), - JSON.stringify([...entryCss]) - ); - } - } - } - } - } - }, - }; -} - -export function astroConfigBuildPlugin(internals: BuildInternals): AstroBuildPlugin { +export function astroConfigBuildPlugin(options: StaticBuildOptions, internals: BuildInternals): AstroBuildPlugin { + let ssrPluginContext: any = undefined; return { build: 'ssr', hooks: { - 'build:before': () => { + 'build:before': ({ build }) => { return { - vitePlugin: astroContentProdBundlePlugin({ internals }), + vitePlugin: { + name: 'astro:content-build-plugin', + generateBundle() { + if(build === 'ssr') { + ssrPluginContext = this; + } + } + }, }; }, + 'build:post': ({ ssrOutputs, clientOutputs, mutate }) => { + const outputs = ssrOutputs.flatMap(o => o.output); + for (const chunk of outputs) { + if ( + chunk.type === 'chunk' && + (chunk.code.includes(LINKS_PLACEHOLDER) || chunk.code.includes(SCRIPTS_PLACEHOLDER)) + ) { + let entryCSS = new Set(); + let entryScripts = new Set(); + + for (const id of Object.keys(chunk.modules)) { + for (const [pageInfo] of walkParentInfos(id, ssrPluginContext)) { + if (moduleIsTopLevelPage(pageInfo)) { + const pageViteID = pageInfo.id; + const pageData = getPageDataByViteID(internals, pageViteID); + if (!pageData) continue; + + const _entryCss = pageData.propagatedStyles?.get(id); + const _entryScripts = pageData.propagatedScripts?.get(id); + if(_entryCss) { + for(const value of _entryCss) { + entryCSS.add(value); + } + } + if(_entryScripts) { + for(const value of _entryScripts) { + entryScripts.add(value); + } + } + } + } + } + + let newCode = chunk.code; + if (entryCSS.size) { + newCode = newCode.replace( + JSON.stringify(LINKS_PLACEHOLDER), + JSON.stringify([...entryCSS]) + ); + } + if (entryScripts.size) { + const entryFileNames = new Set(); + for(const output of clientOutputs) { + for(const clientChunk of output.output) { + if(clientChunk.type !== 'chunk') continue; + for(const [id] of Object.entries(clientChunk.modules)) { + if(entryScripts.has(id)) { + entryFileNames.add(clientChunk.fileName); + } + } + } + } + newCode = newCode.replace( + JSON.stringify(SCRIPTS_PLACEHOLDER), + JSON.stringify( + [...entryFileNames].map((src) => ({ + props: { + src: prependForwardSlash(npath.posix.join( + options.settings.config.base, + src + )), + type: 'module' + }, + children: '', + })) + ) + ); + } + mutate(chunk, 'server', newCode); + } + } + } }, }; } diff --git a/packages/astro/src/core/build/graph.ts b/packages/astro/src/core/build/graph.ts index 5edb07a710e2..a0ae053d5f1a 100644 --- a/packages/astro/src/core/build/graph.ts +++ b/packages/astro/src/core/build/graph.ts @@ -40,7 +40,7 @@ export function moduleIsTopLevelPage(info: ModuleInfo): boolean { // This could be a .astro page, a .markdown or a .md (or really any file extension for markdown files) page. export function* getTopLevelPages( id: string, - ctx: { getModuleInfo: GetModuleInfo } + ctx: { getModuleInfo: GetModuleInfo }, ): Generator<[ModuleInfo, number, number], void, unknown> { for (const res of walkParentInfos(id, ctx)) { if (moduleIsTopLevelPage(res[0])) { diff --git a/packages/astro/src/core/build/page-data.ts b/packages/astro/src/core/build/page-data.ts index 1a03b934b597..71de5da4b91d 100644 --- a/packages/astro/src/core/build/page-data.ts +++ b/packages/astro/src/core/build/page-data.ts @@ -54,7 +54,8 @@ export async function collectPagesData( route, moduleSpecifier: '', css: new Map(), - contentCollectionCss: new Map(), + propagatedStyles: new Map(), + propagatedScripts: new Map(), hoistedScript: undefined, }; @@ -76,7 +77,8 @@ export async function collectPagesData( route, moduleSpecifier: '', css: new Map(), - contentCollectionCss: new Map(), + propagatedStyles: new Map(), + propagatedScripts: new Map(), hoistedScript: undefined, }; } diff --git a/packages/astro/src/core/build/plugins/index.ts b/packages/astro/src/core/build/plugins/index.ts index 29591185da7b..cf0f9bf7c66d 100644 --- a/packages/astro/src/core/build/plugins/index.ts +++ b/packages/astro/src/core/build/plugins/index.ts @@ -16,7 +16,7 @@ export function registerAllPlugins({ internals, options, register }: AstroBuildP register(pluginPages(options, internals)); register(pluginCSS(options, internals)); register(pluginPrerender(options, internals)); - register(astroConfigBuildPlugin(internals)); + register(astroConfigBuildPlugin(options, internals)); register(pluginHoistedScripts(options, internals)); register(pluginSSR(options, internals)); } diff --git a/packages/astro/src/core/build/plugins/plugin-analyzer.ts b/packages/astro/src/core/build/plugins/plugin-analyzer.ts index 6fd2ef7b2638..df7faebf09cd 100644 --- a/packages/astro/src/core/build/plugins/plugin-analyzer.ts +++ b/packages/astro/src/core/build/plugins/plugin-analyzer.ts @@ -4,14 +4,29 @@ import type { PluginMetadata as AstroPluginMetadata } from '../../../vite-plugin import type { BuildInternals } from '../internal.js'; import type { AstroBuildPlugin } from '../plugin.js'; -import { prependForwardSlash } from '../../path.js'; -import { getTopLevelPages } from '../graph.js'; +import { prependForwardSlash } from '../../../core/path.js'; +import { getTopLevelPages, moduleIsTopLevelPage, walkParentInfos } from '../graph.js'; import { getPageDataByViteID, trackClientOnlyPageDatas } from '../internal.js'; +import { PROPAGATED_ASSET_FLAG } from '../../../content/consts.js'; + +function isPropagatedAsset(id: string) { + try { + return new URL('file://' + id).searchParams.has(PROPAGATED_ASSET_FLAG) + } catch { + return false; + } +} export function vitePluginAnalyzer(internals: BuildInternals): VitePlugin { function hoistedScriptScanner() { const uniqueHoistedIds = new Map(); - const pageScripts = new Map>(); + const pageScripts = new Map< + string, + { + hoistedSet: Set; + propagatedMapByImporter: Map>; + } + >(); return { scan(this: PluginContext, scripts: AstroPluginMetadata['astro']['scripts'], from: string) { @@ -22,13 +37,36 @@ export function vitePluginAnalyzer(internals: BuildInternals): VitePlugin { } if (hoistedScripts.size) { - for (const [pageInfo] of getTopLevelPages(from, this)) { - const pageId = pageInfo.id; - for (const hid of hoistedScripts) { - if (pageScripts.has(pageId)) { - pageScripts.get(pageId)?.add(hid); - } else { - pageScripts.set(pageId, new Set([hid])); + for (const [parentInfo] of walkParentInfos(from, this, function until(importer) { + return isPropagatedAsset(importer); + })) { + if (isPropagatedAsset(parentInfo.id)) { + for (const [nestedParentInfo] of walkParentInfos(from, this)) { + if (moduleIsTopLevelPage(nestedParentInfo)) { + for (const hid of hoistedScripts) { + if (!pageScripts.has(nestedParentInfo.id)) { + pageScripts.set(nestedParentInfo.id, { + hoistedSet: new Set(), + propagatedMapByImporter: new Map(), + }); + } + const entry = pageScripts.get(nestedParentInfo.id)!; + if (!entry.propagatedMapByImporter.has(parentInfo.id)) { + entry.propagatedMapByImporter.set(parentInfo.id, new Set()); + } + entry.propagatedMapByImporter.get(parentInfo.id)!.add(hid); + } + } + } + } else if (moduleIsTopLevelPage(parentInfo)) { + for (const hid of hoistedScripts) { + if (!pageScripts.has(parentInfo.id)) { + pageScripts.set(parentInfo.id, { + hoistedSet: new Set(), + propagatedMapByImporter: new Map(), + }); + } + pageScripts.get(parentInfo.id)?.hoistedSet.add(hid); } } } @@ -36,14 +74,14 @@ export function vitePluginAnalyzer(internals: BuildInternals): VitePlugin { }, finalize() { - for (const [pageId, hoistedScripts] of pageScripts) { + for (const [pageId, { hoistedSet, propagatedMapByImporter }] of pageScripts) { const pageData = getPageDataByViteID(internals, pageId); if (!pageData) continue; const { component } = pageData; const astroModuleId = prependForwardSlash(component); - const uniqueHoistedId = JSON.stringify(Array.from(hoistedScripts).sort()); + const uniqueHoistedId = JSON.stringify(Array.from(hoistedSet).sort()); let moduleId: string; // If we're already tracking this set of hoisted scripts, get the unique id @@ -56,13 +94,23 @@ export function vitePluginAnalyzer(internals: BuildInternals): VitePlugin { } internals.discoveredScripts.add(moduleId); + pageData.propagatedScripts = propagatedMapByImporter; + + // Add propagated scripts to client build, + // but DON'T add to pages -> hoisted script map. + for (const propagatedScripts of propagatedMapByImporter.values()) { + for (const propagatedScript of propagatedScripts) { + internals.discoveredScripts.add(propagatedScript); + } + } + // Make sure to track that this page uses this set of hoisted scripts if (internals.hoistedScriptIdToPagesMap.has(moduleId)) { const pages = internals.hoistedScriptIdToPagesMap.get(moduleId); pages!.add(astroModuleId); } else { internals.hoistedScriptIdToPagesMap.set(moduleId, new Set([astroModuleId])); - internals.hoistedScriptIdToHoistedMap.set(moduleId, hoistedScripts); + internals.hoistedScriptIdToHoistedMap.set(moduleId, hoistedSet); } } }, @@ -132,7 +180,7 @@ export function pluginAnalyzer(internals: BuildInternals): AstroBuildPlugin { return { vitePlugin: vitePluginAnalyzer(internals), }; - }, + } }, }; } diff --git a/packages/astro/src/core/build/plugins/plugin-css.ts b/packages/astro/src/core/build/plugins/plugin-css.ts index acd59746a9df..0d57cfb5e668 100644 --- a/packages/astro/src/core/build/plugins/plugin-css.ts +++ b/packages/astro/src/core/build/plugins/plugin-css.ts @@ -176,8 +176,8 @@ export function rollupPluginAstroBuildCSS(options: PluginOptions): VitePlugin[] if (pageData) { for (const css of meta.importedCss) { const existingCss = - pageData.contentCollectionCss.get(pageInfo.id) ?? new Set(); - pageData.contentCollectionCss.set( + pageData.propagatedStyles.get(pageInfo.id) ?? new Set(); + pageData.propagatedStyles.set( pageInfo.id, new Set([...existingCss, css]) ); diff --git a/packages/astro/src/core/build/static-build.ts b/packages/astro/src/core/build/static-build.ts index 4e3238978003..0dcfa6a51782 100644 --- a/packages/astro/src/core/build/static-build.ts +++ b/packages/astro/src/core/build/static-build.ts @@ -245,9 +245,12 @@ async function runPostBuildHooks( clientReturn: Awaited> ) { const mutations = await container.runPostHook(ssrReturn, clientReturn); + const config = container.options.settings.config; const buildConfig = container.options.settings.config.build; for (const [fileName, mutation] of mutations) { - const root = mutation.build === 'server' ? buildConfig.server : buildConfig.client; + const root = config.output === 'server' ? + mutation.build === 'server' ? buildConfig.server : buildConfig.client : + config.outDir; const fileURL = new URL(fileName, root); await fs.promises.mkdir(new URL('./', fileURL), { recursive: true }); await fs.promises.writeFile(fileURL, mutation.code, 'utf-8'); diff --git a/packages/astro/src/core/build/types.ts b/packages/astro/src/core/build/types.ts index 151398c54952..f34089bc1914 100644 --- a/packages/astro/src/core/build/types.ts +++ b/packages/astro/src/core/build/types.ts @@ -21,7 +21,8 @@ export interface PageBuildData { route: RouteData; moduleSpecifier: string; css: Map; - contentCollectionCss: Map>; + propagatedStyles: Map>; + propagatedScripts: Map>; hoistedScript: { type: 'inline' | 'external'; value: string } | undefined; } export type AllPagesData = Record; diff --git a/packages/astro/test/content-collections-render.test.js b/packages/astro/test/content-collections-render.test.js index da14a4765f05..ad45e58a4c61 100644 --- a/packages/astro/test/content-collections-render.test.js +++ b/packages/astro/test/content-collections-render.test.js @@ -46,7 +46,7 @@ describe('Content Collections - render()', () => { // Includes hoisted script expect( [...allScripts].find((script) => - $(script).text().includes('document.querySelector("#update-me")') + $(script).attr('src')?.includes('WithScripts') ), '`WithScripts.astro` hoisted script missing from head.' ).to.not.be.undefined; @@ -55,9 +55,7 @@ describe('Content Collections - render()', () => { expect($('script[data-is-inline]')).to.have.a.lengthOf(1); }); - // TODO: Script bleed isn't solved for prod builds. - // Tackling in separate PR. - it.skip('Excludes component scripts for non-rendered entries', async () => { + it('Excludes component scripts for non-rendered entries', async () => { const html = await fixture.readFile('/index.html'); const $ = cheerio.load(html); From 91dc0f401545bef49f19193029349fc01c811b1d Mon Sep 17 00:00:00 2001 From: matthewp Date: Mon, 6 Feb 2023 15:43:56 +0000 Subject: [PATCH 11/11] [ci] format --- packages/astro/src/content/index.ts | 4 +- .../src/content/vite-plugin-content-assets.ts | 46 +++++++++---------- packages/astro/src/core/build/graph.ts | 2 +- .../src/core/build/plugins/plugin-analyzer.ts | 6 +-- packages/astro/src/core/build/static-build.ts | 9 ++-- .../test/content-collections-render.test.js | 4 +- 6 files changed, 35 insertions(+), 36 deletions(-) diff --git a/packages/astro/src/content/index.ts b/packages/astro/src/content/index.ts index 818e87e35417..f12106b0aa31 100644 --- a/packages/astro/src/content/index.ts +++ b/packages/astro/src/content/index.ts @@ -1,8 +1,6 @@ export { attachContentServerListeners } from './server-listeners.js'; export { createContentTypesGenerator } from './types-generator.js'; export { contentObservable, getContentPaths, getDotAstroTypeReference } from './utils.js'; -export { - astroContentAssetPropagationPlugin, -} from './vite-plugin-content-assets.js'; +export { astroContentAssetPropagationPlugin } from './vite-plugin-content-assets.js'; export { astroContentImportPlugin } from './vite-plugin-content-imports.js'; export { astroContentVirtualModPlugin } from './vite-plugin-content-virtual-mod.js'; diff --git a/packages/astro/src/content/vite-plugin-content-assets.ts b/packages/astro/src/content/vite-plugin-content-assets.ts index 7610d9f9d0db..74378f4e0f50 100644 --- a/packages/astro/src/content/vite-plugin-content-assets.ts +++ b/packages/astro/src/content/vite-plugin-content-assets.ts @@ -1,11 +1,13 @@ -import { pathToFileURL } from 'url'; import npath from 'node:path'; +import { pathToFileURL } from 'url'; import type { Plugin } from 'vite'; import { moduleIsTopLevelPage, walkParentInfos } from '../core/build/graph.js'; import { BuildInternals, getPageDataByViteID } from '../core/build/internal.js'; import { AstroBuildPlugin } from '../core/build/plugin.js'; +import type { StaticBuildOptions } from '../core/build/types'; import type { ModuleLoader } from '../core/module-loader/loader.js'; import { createViteLoader } from '../core/module-loader/vite.js'; +import { prependForwardSlash } from '../core/path.js'; import { getStylesForURL } from '../core/render/dev/css.js'; import { getScriptsForURL } from '../core/render/dev/scripts.js'; import { @@ -15,8 +17,6 @@ import { SCRIPTS_PLACEHOLDER, STYLES_PLACEHOLDER, } from './consts.js'; -import type { RollupOutput, OutputChunk, StaticBuildOptions } from '../core/build/types'; -import { prependForwardSlash } from '../core/path.js'; function isPropagatedAsset(viteId: string): boolean { const url = new URL(viteId, 'file://'); @@ -76,7 +76,10 @@ export function astroContentAssetPropagationPlugin({ mode }: { mode: string }): }; } -export function astroConfigBuildPlugin(options: StaticBuildOptions, internals: BuildInternals): AstroBuildPlugin { +export function astroConfigBuildPlugin( + options: StaticBuildOptions, + internals: BuildInternals +): AstroBuildPlugin { let ssrPluginContext: any = undefined; return { build: 'ssr', @@ -86,15 +89,15 @@ export function astroConfigBuildPlugin(options: StaticBuildOptions, internals: B vitePlugin: { name: 'astro:content-build-plugin', generateBundle() { - if(build === 'ssr') { + if (build === 'ssr') { ssrPluginContext = this; } - } + }, }, }; }, 'build:post': ({ ssrOutputs, clientOutputs, mutate }) => { - const outputs = ssrOutputs.flatMap(o => o.output); + const outputs = ssrOutputs.flatMap((o) => o.output); for (const chunk of outputs) { if ( chunk.type === 'chunk' && @@ -109,16 +112,16 @@ export function astroConfigBuildPlugin(options: StaticBuildOptions, internals: B const pageViteID = pageInfo.id; const pageData = getPageDataByViteID(internals, pageViteID); if (!pageData) continue; - + const _entryCss = pageData.propagatedStyles?.get(id); const _entryScripts = pageData.propagatedScripts?.get(id); - if(_entryCss) { - for(const value of _entryCss) { + if (_entryCss) { + for (const value of _entryCss) { entryCSS.add(value); } } - if(_entryScripts) { - for(const value of _entryScripts) { + if (_entryScripts) { + for (const value of _entryScripts) { entryScripts.add(value); } } @@ -135,11 +138,11 @@ export function astroConfigBuildPlugin(options: StaticBuildOptions, internals: B } if (entryScripts.size) { const entryFileNames = new Set(); - for(const output of clientOutputs) { - for(const clientChunk of output.output) { - if(clientChunk.type !== 'chunk') continue; - for(const [id] of Object.entries(clientChunk.modules)) { - if(entryScripts.has(id)) { + for (const output of clientOutputs) { + for (const clientChunk of output.output) { + if (clientChunk.type !== 'chunk') continue; + for (const [id] of Object.entries(clientChunk.modules)) { + if (entryScripts.has(id)) { entryFileNames.add(clientChunk.fileName); } } @@ -150,11 +153,8 @@ export function astroConfigBuildPlugin(options: StaticBuildOptions, internals: B JSON.stringify( [...entryFileNames].map((src) => ({ props: { - src: prependForwardSlash(npath.posix.join( - options.settings.config.base, - src - )), - type: 'module' + src: prependForwardSlash(npath.posix.join(options.settings.config.base, src)), + type: 'module', }, children: '', })) @@ -164,7 +164,7 @@ export function astroConfigBuildPlugin(options: StaticBuildOptions, internals: B mutate(chunk, 'server', newCode); } } - } + }, }, }; } diff --git a/packages/astro/src/core/build/graph.ts b/packages/astro/src/core/build/graph.ts index a0ae053d5f1a..5edb07a710e2 100644 --- a/packages/astro/src/core/build/graph.ts +++ b/packages/astro/src/core/build/graph.ts @@ -40,7 +40,7 @@ export function moduleIsTopLevelPage(info: ModuleInfo): boolean { // This could be a .astro page, a .markdown or a .md (or really any file extension for markdown files) page. export function* getTopLevelPages( id: string, - ctx: { getModuleInfo: GetModuleInfo }, + ctx: { getModuleInfo: GetModuleInfo } ): Generator<[ModuleInfo, number, number], void, unknown> { for (const res of walkParentInfos(id, ctx)) { if (moduleIsTopLevelPage(res[0])) { diff --git a/packages/astro/src/core/build/plugins/plugin-analyzer.ts b/packages/astro/src/core/build/plugins/plugin-analyzer.ts index df7faebf09cd..ff2ac3bbc8cb 100644 --- a/packages/astro/src/core/build/plugins/plugin-analyzer.ts +++ b/packages/astro/src/core/build/plugins/plugin-analyzer.ts @@ -4,14 +4,14 @@ import type { PluginMetadata as AstroPluginMetadata } from '../../../vite-plugin import type { BuildInternals } from '../internal.js'; import type { AstroBuildPlugin } from '../plugin.js'; +import { PROPAGATED_ASSET_FLAG } from '../../../content/consts.js'; import { prependForwardSlash } from '../../../core/path.js'; import { getTopLevelPages, moduleIsTopLevelPage, walkParentInfos } from '../graph.js'; import { getPageDataByViteID, trackClientOnlyPageDatas } from '../internal.js'; -import { PROPAGATED_ASSET_FLAG } from '../../../content/consts.js'; function isPropagatedAsset(id: string) { try { - return new URL('file://' + id).searchParams.has(PROPAGATED_ASSET_FLAG) + return new URL('file://' + id).searchParams.has(PROPAGATED_ASSET_FLAG); } catch { return false; } @@ -180,7 +180,7 @@ export function pluginAnalyzer(internals: BuildInternals): AstroBuildPlugin { return { vitePlugin: vitePluginAnalyzer(internals), }; - } + }, }, }; } diff --git a/packages/astro/src/core/build/static-build.ts b/packages/astro/src/core/build/static-build.ts index 0dcfa6a51782..aef8a1aabab7 100644 --- a/packages/astro/src/core/build/static-build.ts +++ b/packages/astro/src/core/build/static-build.ts @@ -248,9 +248,12 @@ async function runPostBuildHooks( const config = container.options.settings.config; const buildConfig = container.options.settings.config.build; for (const [fileName, mutation] of mutations) { - const root = config.output === 'server' ? - mutation.build === 'server' ? buildConfig.server : buildConfig.client : - config.outDir; + const root = + config.output === 'server' + ? mutation.build === 'server' + ? buildConfig.server + : buildConfig.client + : config.outDir; const fileURL = new URL(fileName, root); await fs.promises.mkdir(new URL('./', fileURL), { recursive: true }); await fs.promises.writeFile(fileURL, mutation.code, 'utf-8'); diff --git a/packages/astro/test/content-collections-render.test.js b/packages/astro/test/content-collections-render.test.js index ad45e58a4c61..8410487c62a4 100644 --- a/packages/astro/test/content-collections-render.test.js +++ b/packages/astro/test/content-collections-render.test.js @@ -45,9 +45,7 @@ describe('Content Collections - render()', () => { // Includes hoisted script expect( - [...allScripts].find((script) => - $(script).attr('src')?.includes('WithScripts') - ), + [...allScripts].find((script) => $(script).attr('src')?.includes('WithScripts')), '`WithScripts.astro` hoisted script missing from head.' ).to.not.be.undefined;