0
Fork 0
mirror of https://github.com/withastro/astro.git synced 2025-03-17 23:11:29 -05:00

Merge remote-tracking branch 'origin/next' into feat/unflag-astro-env

This commit is contained in:
Florian Lefebvre 2024-08-14 14:53:16 +02:00
commit 23ea79060d
313 changed files with 7220 additions and 1834 deletions

View file

@ -0,0 +1,41 @@
---
'astro': minor
---
Deprecates the option for route-generating files to export a dynamic value for `prerender`. Only static values are now supported (e.g. `export const prerender = true` or `= false`). This allows for better treeshaking and bundling configuration in the future.
Adds a new [`"astro:route:setup"` hook](https://docs.astro.build/en/reference/integrations-reference/#astroroutesetup) to the Integrations API to allow you to dynamically set options for a route at build or request time through an integration, such as enabling [on-demand server rendering](https://docs.astro.build/en/guides/server-side-rendering/#opting-in-to-pre-rendering-in-server-mode).
To migrate from a dynamic export to the new hook, update or remove any dynamic `prerender` exports from individual routing files:
```diff
// src/pages/blog/[slug].astro
- export const prerender = import.meta.env.PRERENDER
```
Instead, create an integration with the `"astro:route:setup"` hook and update the route's `prerender` option:
```js
// astro.config.mjs
import { defineConfig } from 'astro/config';
import { loadEnv } from 'vite';
export default defineConfig({
integrations: [setPrerender()],
});
function setPrerender() {
const { PRERENDER } = loadEnv(process.env.NODE_ENV, process.cwd(), '');
return {
name: 'set-prerender',
hooks: {
'astro:route:setup': ({ route }) => {
if (route.component.endsWith('/blog/[slug].astro')) {
route.prerender = PRERENDER;
}
},
},
};
}
```

View file

@ -0,0 +1,6 @@
---
'astro': patch
'@astrojs/db': patch
---
Refactors internally to use `node:util` `parseArgs` instead of `yargs-parser`

View file

@ -0,0 +1,18 @@
---
'@astrojs/db': minor
---
Changes how type generation works
The generated `.d.ts` file is now at a new location:
```diff
- .astro/db-types.d.ts
+ .astro/integrations/astro_db/db.d.ts
```
The following line can now be removed from `src/env.d.ts`:
```diff
- /// <reference path="../.astro/db-types.d.ts" />
```

View file

@ -0,0 +1,35 @@
---
'astro': minor
---
Adds a new [`injectTypes()` utility](https://docs.astro.build/en/reference/integrations-reference/#injecttypes-options) to the Integration API and refactors how type generation works
Use `injectTypes()` in the `astro:config:done` hook to inject types into your user's project by adding a new a `*.d.ts` file.
The `filename` property will be used to generate a file at `/.astro/integrations/<normalized_integration_name>/<normalized_filename>.d.ts` and must end with `".d.ts"`.
The `content` property will create the body of the file, and must be valid TypeScript.
Additionally, `injectTypes()` returns a URL to the normalized path so you can overwrite its content later on, or manipulate it in any way you want.
```js
// my-integration/index.js
export default {
name: 'my-integration',
'astro:config:done': ({ injectTypes }) => {
injectTypes({
filename: "types.d.ts",
content: "declare module 'virtual:my-integration' {}"
})
}
};
```
Codegen has been refactored. Although `src/env.d.ts` will continue to work as is, we recommend you update it:
```diff
- /// <reference types="astro/client" />
+ /// <reference path="../.astro/types.d.ts" />
- /// <reference path="../.astro/env.d.ts" />
- /// <reference path="../.astro/actions.d.ts" />
```

View file

@ -0,0 +1,22 @@
---
"astro": minor
---
Adds a new property `meta` to Astro's [built-in `<Code />` component](https://docs.astro.build/en/reference/api-reference/#code-).
This allows you to provide a value for [Shiki's `meta` attribute](https://shiki.style/guide/transformers#meta) to pass options to transformers.
The following example passes an option to highlight lines 1 and 3 to Shiki's `tranformerMetaHighlight`:
```astro
---
// src/components/Card.astro
import { Code } from "astro:components";
import { transformerMetaHighlight } from '@shikijs/transformers';
---
<Code
code={code}
lang="js"
transformers={[transformerMetaHighlight()]}
meta="{1,3}" />
```

View file

@ -0,0 +1,7 @@
---
'create-astro': patch
'@astrojs/upgrade': patch
---
Refactors internally to use `node:util` `parseArgs` instead of `arg`

View file

@ -0,0 +1,21 @@
---
'astro': minor
---
Adds support for Intellisense features (e.g. code completion, quick hints) for your content collection entries in compatible editors under the `experimental.contentIntellisense` flag.
```js
import { defineConfig } from 'astro';
export default defineConfig({
experimental: {
contentIntellisense: true
}
})
```
When enabled, this feature will generate and add JSON schemas to the `.astro` directory in your project. These files can be used by the Astro language server to provide Intellisense inside content files (`.md`, `.mdx`, `.mdoc`).
Note that at this time, this also require enabling the `astro.content-intellisense` option in your editor, or passing the `contentIntellisense: true` initialization parameter to the Astro language server for editors using it directly.
See the [experimental content Intellisense docs](https://docs.astro.build/en/reference/configuration-reference/#experimentalcontentintellisense) for more information updates as this feature develops.

View file

@ -0,0 +1,50 @@
---
'astro': major
---
Fixes attribute rendering for non-[boolean HTML attributes](https://developer.mozilla.org/en-US/docs/Glossary/Boolean/HTML) with boolean values to match proper attribute handling in browsers.
Previously, non-boolean attributes may not have included their values when rendered to HTML. In Astro v5.0, the values are now explicitly rendered as `="true"` or `="false"`
In the following `.astro` examples, only `allowfullscreen` is a boolean attribute:
```astro
<!-- src/pages/index.astro -->
<!-- `allowfullscreen` is a boolean attribute -->
<p allowfullscreen={true}></p>
<p allowfullscreen={false}></p>
<!-- `inherit` is *not* a boolean attribute -->
<p inherit={true}></p>
<p inherit={false}></p>
<!-- `data-*` attributes are not boolean attributes -->
<p data-light={true}></p>
<p data-light={false}></p>
```
Astro v5.0 now preserves the full data attribute with its value when rendering the HTML of non-boolean attributes:
```diff
<p allowfullscreen></p>
<p></p>
<p inherit="true"></p>
- <p inherit></p>
+ <p inherit="false"></p>
- <p data-light></p>
+ <p data-light="true"></p>
- <p></p>
+ <p data-light="false"></p>
```
If you rely on attribute values, for example to locate elements or to conditionally render, update your code to match the new non-boolean attribute values:
```diff
- el.getAttribute('inherit') === ''
+ el.getAttribute('inherit') === 'false'
- el.hasAttribute('data-light')
+ el.dataset.light === 'true'
```

View file

@ -0,0 +1,107 @@
---
'astro': minor
---
Adds experimental support for the Content Layer API.
The new Content Layer API builds upon content collections, taking them beyond local files in `src/content/` and allowing you to fetch content from anywhere, including remote APIs. These new collections work alongside your existing content collections, and you can migrate them to the new API at your own pace. There are significant improvements to performance with large collections of local files.
### Getting started
To try out the new Content Layer API, enable it in your Astro config:
```js
import { defineConfig } from 'astro';
export default defineConfig({
experimental: {
contentLayer: true
}
})
```
You can then create collections in your `src/content/config.ts` using the Content Layer API.
### Loading your content
The core of the new Content Layer API is the loader, a function that fetches content from a source and caches it in a local data store. Astro 4.14 ships with built-in `glob()` and `file()` loaders to handle your local Markdown, MDX, Markdoc, and JSON files:
```ts {3,7}
// src/content/config.ts
import { defineCollection, z } from 'astro:content';
import { glob } from 'astro/loaders';
const blog = defineCollection({
// The ID is a slug generated from the path of the file relative to `base`
loader: glob({ pattern: "**/*.md", base: "./src/data/blog" }),
schema: z.object({
title: z.string(),
description: z.string(),
publishDate: z.coerce.date(),
})
});
export const collections = { blog };
```
You can then query using the existing content collections functions, and enjoy a simplified `render()` function to display your content:
```astro
---
import { getEntry, render } from 'astro:content';
const post = await getEntry('blog', Astro.params.slug);
const { Content } = await render(entry);
---
<Content />
```
### Creating a loader
You're not restricted to the built-in loaders  we hope you'll try building your own. You can fetch content from anywhere and return an array of entries:
```ts
// src/content/config.ts
const countries = defineCollection({
loader: async () => {
const response = await fetch("https://restcountries.com/v3.1/all");
const data = await response.json();
// Must return an array of entries with an id property,
// or an object with IDs as keys and entries as values
return data.map((country) => ({
id: country.cca3,
...country,
}));
},
// optionally add a schema to validate the data and make it type-safe for users
// schema: z.object...
});
export const collections = { countries };
```
For more advanced loading logic, you can define an object loader. This allows incremental updates and conditional loading, and gives full access to the data store. It also allows a loader to define its own schema, including generating it dynamically based on the source API. See the [the Content Layer API RFC](https://github.com/withastro/roadmap/blob/content-layer/proposals/0047-content-layer.md#loaders) for more details.
### Sharing your loaders
Loaders are better when they're shared. You can create a package that exports a loader and publish it to npm, and then anyone can use it on their site. We're excited to see what the community comes up with! To get started, [take a look at some examples](https://github.com/ascorbic/astro-loaders/). Here's how to load content using an RSS/Atom feed loader:
```ts
// src/content/config.ts
import { defineCollection } from "astro:content";
import { feedLoader } from "@ascorbic/feed-loader";
const podcasts = defineCollection({
loader: feedLoader({
url: "https://feeds.99percentinvisible.org/99percentinvisible",
}),
});
export const collections = { podcasts };
```
### Learn more
To find out more about using the Content Layer API, check out [the Content Layer RFC](https://github.com/withastro/roadmap/blob/content-layer/proposals/0047-content-layer.md) and [share your feedback](https://github.com/withastro/roadmap/pull/982).

View file

@ -18,7 +18,7 @@ export async function run(projectDir, outputFile) {
const outputFilePath = fileURLToPath(outputFile);
console.log('Building and benchmarking...');
await execaCommand(`node --expose-gc --max_old_space_size=256 ${astroBin} build`, {
await execaCommand(`node --expose-gc --max_old_space_size=10000 ${astroBin} build --silent`, {
cwd: root,
stdio: 'inherit',
env: {

Binary file not shown.

After

Width:  |  Height:  |  Size: 170 KiB

View file

@ -0,0 +1,63 @@
import fs from 'node:fs/promises';
import { loremIpsumMd } from './_util.js';
/**
* @param {URL} projectDir
*/
export async function run(projectDir) {
await fs.rm(projectDir, { recursive: true, force: true });
await fs.mkdir(new URL('./src/pages/blog', projectDir), { recursive: true });
await fs.mkdir(new URL('./src/content/blog', projectDir), { recursive: true });
await fs.copyFile(new URL('./image.jpg', import.meta.url), new URL('./src/image.jpg', projectDir));
const promises = [];
for (let i = 0; i < 10000; i++) {
const content = `\
# Article ${i}
${loremIpsumMd}
![image ${i}](../../image.jpg)
`;
promises.push(
fs.writeFile(new URL(`./src/content/blog/article-${i}.md`, projectDir), content, 'utf-8')
);
}
await fs.writeFile(
new URL(`./src/pages/blog/[...slug].astro`, projectDir),
`\
---
import { getCollection } from 'astro:content';
export async function getStaticPaths() {
const blogEntries = await getCollection('blog');
return blogEntries.map(entry => ({
params: { slug: entry.slug }, props: { entry },
}));
}
const { entry } = Astro.props;
const { Content } = await entry.render();
---
<h1>{entry.data.title}</h1>
<Content />
`,
'utf-8'
);
await Promise.all(promises);
await fs.writeFile(
new URL('./astro.config.js', projectDir),
`\
import { defineConfig } from 'astro/config';
export default defineConfig({
});`,
'utf-8'
);
}

View file

@ -0,0 +1,80 @@
import fs from 'node:fs/promises';
import { loremIpsumMd } from './_util.js';
/**
* @param {URL} projectDir
*/
export async function run(projectDir) {
await fs.rm(projectDir, { recursive: true, force: true });
await fs.mkdir(new URL('./src/pages/blog', projectDir), { recursive: true });
await fs.mkdir(new URL('./data/blog', projectDir), { recursive: true });
await fs.mkdir(new URL('./src/content', projectDir), { recursive: true });
await fs.copyFile(new URL('./image.jpg', import.meta.url), new URL('./image.jpg', projectDir));
const promises = [];
for (let i = 0; i < 10000; i++) {
const content = `\
# Article ${i}
${loremIpsumMd}
![image ${i}](../../image.jpg)
`;
promises.push(
fs.writeFile(new URL(`./data/blog/article-${i}.md`, projectDir), content, 'utf-8')
);
}
await fs.writeFile(
new URL(`./src/content/config.ts`, projectDir),
/*ts */ `
import { defineCollection, z } from 'astro:content';
import { glob } from 'astro/loaders';
const blog = defineCollection({
loader: glob({ pattern: '*', base: './data/blog' }),
});
export const collections = { blog }
`
);
await fs.writeFile(
new URL(`./src/pages/blog/[...slug].astro`, projectDir),
`\
---
import { getCollection, render } from 'astro:content';
export async function getStaticPaths() {
const blogEntries = await getCollection('blog');
return blogEntries.map(entry => ({
params: { slug: entry.id }, props: { entry },
}));
}
const { entry } = Astro.props;
const { Content } = await render(entry);
---
<h1>{entry.data.title}</h1>
<Content />
`,
'utf-8'
);
await Promise.all(promises);
await fs.writeFile(
new URL('./astro.config.js', projectDir),
`\
import { defineConfig } from 'astro/config';
export default defineConfig({
experimental: {
contentLayer: true
}
});`,
'utf-8'
);
}

View file

@ -0,0 +1,66 @@
import fs from 'node:fs/promises';
import { loremIpsumMd } from './_util.js';
/**
* @param {URL} projectDir
*/
export async function run(projectDir) {
await fs.rm(projectDir, { recursive: true, force: true });
await fs.mkdir(new URL('./src/pages/blog', projectDir), { recursive: true });
await fs.mkdir(new URL('./src/content/blog', projectDir), { recursive: true });
await fs.copyFile(new URL('./image.jpg', import.meta.url), new URL('./src/image.jpg', projectDir));
const promises = [];
for (let i = 0; i < 10000; i++) {
const content = `\
# Article ${i}
${loremIpsumMd}
![image ${i}](../../image.jpg)
`;
promises.push(
fs.writeFile(new URL(`./src/content/blog/article-${i}.mdx`, projectDir), content, 'utf-8')
);
}
await fs.writeFile(
new URL(`./src/pages/blog/[...slug].astro`, projectDir),
`\
---
import { getCollection } from 'astro:content';
export async function getStaticPaths() {
const blogEntries = await getCollection('blog');
return blogEntries.map(entry => ({
params: { slug: entry.slug }, props: { entry },
}));
}
const { entry } = Astro.props;
const { Content } = await entry.render();
---
<h1>{entry.data.title}</h1>
<Content />
`,
'utf-8'
);
await Promise.all(promises);
await fs.writeFile(
new URL('./astro.config.js', projectDir),
`\
import { defineConfig } from 'astro/config';
import mdx from '@astrojs/mdx';
export default defineConfig({
integrations: [mdx()],
});`,
'utf-8'
);
}

View file

@ -0,0 +1,83 @@
import fs from 'node:fs/promises';
import { loremIpsumMd } from './_util.js';
/**
* @param {URL} projectDir
*/
export async function run(projectDir) {
await fs.rm(projectDir, { recursive: true, force: true });
await fs.mkdir(new URL('./src/pages/blog', projectDir), { recursive: true });
await fs.mkdir(new URL('./data/blog', projectDir), { recursive: true });
await fs.mkdir(new URL('./src/content', projectDir), { recursive: true });
await fs.copyFile(new URL('./image.jpg', import.meta.url), new URL('./image.jpg', projectDir));
const promises = [];
for (let i = 0; i < 10000; i++) {
const content = `\
# Article ${i}
${loremIpsumMd}
![image ${i}](../../image.jpg)
`;
promises.push(
fs.writeFile(new URL(`./data/blog/article-${i}.mdx`, projectDir), content, 'utf-8')
);
}
await fs.writeFile(
new URL(`./src/content/config.ts`, projectDir),
/*ts */ `
import { defineCollection, z } from 'astro:content';
import { glob } from 'astro/loaders';
const blog = defineCollection({
loader: glob({ pattern: '*', base: './data/blog' }),
});
export const collections = { blog }
`
);
await fs.writeFile(
new URL(`./src/pages/blog/[...slug].astro`, projectDir),
`\
---
import { getCollection, render } from 'astro:content';
export async function getStaticPaths() {
const blogEntries = await getCollection('blog');
return blogEntries.map(entry => ({
params: { slug: entry.id }, props: { entry },
}));
}
const { entry } = Astro.props;
const { Content } = await render(entry);
---
<h1>{entry.data.title}</h1>
<Content />
`,
'utf-8'
);
await Promise.all(promises);
await fs.writeFile(
new URL('./astro.config.js', projectDir),
`\
import { defineConfig } from 'astro/config';
import mdx from '@astrojs/mdx';
export default defineConfig({
integrations: [mdx()],
experimental: {
contentLayer: true
}
});`,
'utf-8'
);
}

View file

@ -16,6 +16,7 @@
"markdown-table": "^3.0.3",
"mri": "^1.2.0",
"port-authority": "^2.0.1",
"pretty-bytes": "^6.1.1"
"pretty-bytes": "^6.1.1",
"sharp": "^0.33.3"
}
}

View file

@ -1,5 +1,5 @@
{
"$schema": "https://biomejs.dev/schemas/1.8.1/schema.json",
"$schema": "https://biomejs.dev/schemas/1.8.3/schema.json",
"files": {
"ignore": [
"vendor",

View file

@ -11,6 +11,6 @@
"astro": "astro"
},
"dependencies": {
"astro": "^4.13.3"
"astro": "^4.13.4"
}
}

View file

@ -1 +1 @@
/// <reference types="astro/client" />
/// <reference path="../.astro/types.d.ts" />

View file

@ -14,6 +14,6 @@
"@astrojs/mdx": "^3.1.3",
"@astrojs/rss": "^4.0.7",
"@astrojs/sitemap": "^3.1.6",
"astro": "^4.13.3"
"astro": "^4.13.4"
}
}

View file

@ -1,2 +1 @@
/// <reference path="../.astro/types.d.ts" />
/// <reference types="astro/client" />

View file

@ -15,7 +15,7 @@
],
"scripts": {},
"devDependencies": {
"astro": "^4.13.3"
"astro": "^4.13.4"
},
"peerDependencies": {
"astro": "^4.0.0"

View file

@ -12,14 +12,14 @@
"test": "vitest run"
},
"dependencies": {
"astro": "^4.13.3",
"astro": "^4.13.4",
"@astrojs/react": "^3.6.2",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"vitest": "^2.0.5"
},
"devDependencies": {
"@types/react-dom": "^18.3.0",
"@types/react": "^18.3.3"
"@types/react": "^18.3.3",
"@types/react-dom": "^18.3.0"
}
}

View file

@ -14,6 +14,6 @@
"@astrojs/alpinejs": "^0.4.0",
"@types/alpinejs": "^3.13.10",
"alpinejs": "^3.14.1",
"astro": "^4.13.3"
"astro": "^4.13.4"
}
}

View file

@ -1 +1 @@
/// <reference types="astro/client" />
/// <reference path="../.astro/types.d.ts" />

View file

@ -13,7 +13,7 @@
"dependencies": {
"@astrojs/lit": "^4.3.0",
"@webcomponents/template-shadowroot": "^0.2.1",
"astro": "^4.13.3",
"lit": "^3.1.4"
"astro": "^4.13.4",
"lit": "^3.2.0"
}
}

View file

@ -1 +1 @@
/// <reference types="astro/client" />
/// <reference path="../.astro/types.d.ts" />

View file

@ -18,12 +18,12 @@
"@astrojs/vue": "^4.5.0",
"@types/react": "^18.3.3",
"@types/react-dom": "^18.3.0",
"astro": "^4.13.3",
"astro": "^4.13.4",
"preact": "^10.23.1",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"solid-js": "^1.8.19",
"solid-js": "^1.8.20",
"svelte": "^4.2.18",
"vue": "^3.4.35"
"vue": "^3.4.37"
}
}

View file

@ -1 +1 @@
/// <reference types="astro/client" />
/// <reference path="../.astro/types.d.ts" />

View file

@ -13,7 +13,7 @@
"dependencies": {
"@astrojs/preact": "^3.5.1",
"@preact/signals": "^1.3.0",
"astro": "^4.13.3",
"astro": "^4.13.4",
"preact": "^10.23.1"
}
}

View file

@ -1 +1 @@
/// <reference types="astro/client" />
/// <reference path="../.astro/types.d.ts" />

View file

@ -14,7 +14,7 @@
"@astrojs/react": "^3.6.2",
"@types/react": "^18.3.3",
"@types/react-dom": "^18.3.0",
"astro": "^4.13.3",
"astro": "^4.13.4",
"react": "^18.3.1",
"react-dom": "^18.3.1"
}

View file

@ -1 +1 @@
/// <reference types="astro/client" />
/// <reference path="../.astro/types.d.ts" />

View file

@ -12,7 +12,7 @@
},
"dependencies": {
"@astrojs/solid-js": "^4.4.1",
"astro": "^4.13.3",
"solid-js": "^1.8.19"
"astro": "^4.13.4",
"solid-js": "^1.8.20"
}
}

View file

@ -1 +1 @@
/// <reference types="astro/client" />
/// <reference path="../.astro/types.d.ts" />

View file

@ -12,7 +12,7 @@
},
"dependencies": {
"@astrojs/svelte": "^5.7.0",
"astro": "^4.13.3",
"astro": "^4.13.4",
"svelte": "^4.2.18"
}
}

View file

@ -1 +1 @@
/// <reference types="astro/client" />
/// <reference path="../.astro/types.d.ts" />

View file

@ -12,7 +12,7 @@
},
"dependencies": {
"@astrojs/vue": "^4.5.0",
"astro": "^4.13.3",
"vue": "^3.4.35"
"astro": "^4.13.4",
"vue": "^3.4.37"
}
}

View file

@ -1 +1 @@
/// <reference types="astro/client" />
/// <reference path="../.astro/types.d.ts" />

View file

@ -11,7 +11,7 @@
"astro": "astro"
},
"dependencies": {
"@astrojs/node": "^8.3.2",
"astro": "^4.13.3"
"@astrojs/node": "^8.3.3",
"astro": "^4.13.4"
}
}

View file

@ -1 +1 @@
/// <reference types="astro/client" />
/// <reference path="../.astro/types.d.ts" />

View file

@ -15,7 +15,7 @@
],
"scripts": {},
"devDependencies": {
"astro": "^4.13.3"
"astro": "^4.13.4"
},
"peerDependencies": {
"astro": "^4.0.0"

View file

@ -12,8 +12,8 @@
"server": "node dist/server/entry.mjs"
},
"dependencies": {
"@astrojs/node": "^8.3.2",
"astro": "^4.13.3",
"@astrojs/node": "^8.3.3",
"astro": "^4.13.4",
"html-minifier": "^4.0.0"
},
"devDependencies": {

View file

@ -1,4 +1,4 @@
/// <reference types="astro/client" />
/// <reference path="../.astro/types.d.ts" />
declare namespace App {
interface Locals {
user: {

View file

@ -11,6 +11,6 @@
"astro": "astro"
},
"dependencies": {
"astro": "^4.13.3"
"astro": "^4.13.4"
}
}

View file

@ -1 +1 @@
/// <reference types="astro/client" />
/// <reference path="../.astro/types.d.ts" />

View file

@ -11,6 +11,6 @@
"astro": "astro"
},
"dependencies": {
"astro": "^4.13.3"
"astro": "^4.13.4"
}
}

View file

@ -1 +1 @@
/// <reference types="astro/client" />
/// <reference path="../.astro/types.d.ts" />

View file

@ -11,6 +11,6 @@
"astro": "astro"
},
"dependencies": {
"astro": "^4.13.3"
"astro": "^4.13.4"
}
}

View file

@ -1,2 +1 @@
/// <reference path="../.astro/types.d.ts" />
/// <reference types="astro/client" />

View file

@ -10,17 +10,17 @@
"astro": "astro"
},
"devDependencies": {
"@astrojs/node": "^8.3.2",
"@astrojs/node": "^8.3.3",
"@astrojs/react": "^3.6.2",
"@astrojs/tailwind": "^5.1.0",
"@fortawesome/fontawesome-free": "^6.6.0",
"@tailwindcss/forms": "^0.5.7",
"@types/react": "^18.3.3",
"@types/react-dom": "^18.3.0",
"astro": "^4.13.3",
"postcss": "^8.4.40",
"astro": "^4.13.4",
"postcss": "^8.4.41",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"tailwindcss": "^3.4.7"
"tailwindcss": "^3.4.9"
}
}

View file

@ -12,9 +12,9 @@
"server": "node dist/server/entry.mjs"
},
"dependencies": {
"@astrojs/node": "^8.3.2",
"@astrojs/node": "^8.3.3",
"@astrojs/svelte": "^5.7.0",
"astro": "^4.13.3",
"astro": "^4.13.4",
"svelte": "^4.2.18"
}
}

View file

@ -1 +1 @@
/// <reference types="astro/client" />
/// <reference path="../.astro/types.d.ts" />

View file

@ -10,7 +10,7 @@
"astro": "astro"
},
"dependencies": {
"astro": "^4.13.3",
"astro": "^4.13.4",
"sass": "^1.77.8",
"sharp": "^0.33.3"
}

View file

@ -15,6 +15,6 @@
"./app": "./dist/app.js"
},
"devDependencies": {
"astro": "^4.13.3"
"astro": "^4.13.4"
}
}

View file

@ -11,7 +11,7 @@
},
"devDependencies": {
"@astrojs/tailwind": "^5.1.0",
"@astrojs/node": "^8.3.2",
"astro": "^4.13.3"
"@astrojs/node": "^8.3.3",
"astro": "^4.13.4"
}
}

View file

@ -12,6 +12,6 @@
},
"dependencies": {
"@astrojs/markdoc": "^0.11.3",
"astro": "^4.13.3"
"astro": "^4.13.4"
}
}

View file

@ -1,2 +1 @@
/// <reference path="../.astro/types.d.ts" />
/// <reference types="astro/client" />

View file

@ -12,7 +12,7 @@
},
"dependencies": {
"@astrojs/markdown-remark": "^5.2.0",
"astro": "^4.13.3",
"astro": "^4.13.4",
"hast-util-select": "^6.0.2",
"rehype-autolink-headings": "^7.1.0",
"rehype-slug": "^6.0.0",

View file

@ -1 +1 @@
/// <reference types="astro/client" />
/// <reference path="../.astro/types.d.ts" />

View file

@ -11,6 +11,6 @@
"astro": "astro"
},
"dependencies": {
"astro": "^4.13.3"
"astro": "^4.13.4"
}
}

View file

@ -1 +1 @@
/// <reference types="astro/client" />
/// <reference path="../.astro/types.d.ts" />

View file

@ -13,7 +13,7 @@
"dependencies": {
"@astrojs/mdx": "^3.1.3",
"@astrojs/preact": "^3.5.1",
"astro": "^4.13.3",
"astro": "^4.13.4",
"preact": "^10.23.1"
}
}

View file

@ -1 +1 @@
/// <reference types="astro/client" />
/// <reference path="../.astro/types.d.ts" />

View file

@ -13,8 +13,8 @@
"dependencies": {
"@astrojs/preact": "^3.5.1",
"@nanostores/preact": "^0.5.2",
"astro": "^4.13.3",
"nanostores": "^0.11.0",
"astro": "^4.13.4",
"nanostores": "^0.11.2",
"preact": "^10.23.1"
}
}

View file

@ -1 +1 @@
/// <reference types="astro/client" />
/// <reference path="../.astro/types.d.ts" />

View file

@ -14,10 +14,10 @@
"@astrojs/mdx": "^3.1.3",
"@astrojs/tailwind": "^5.1.0",
"@types/canvas-confetti": "^1.6.4",
"astro": "^4.13.3",
"astro": "^4.13.4",
"autoprefixer": "^10.4.20",
"canvas-confetti": "^1.9.3",
"postcss": "^8.4.40",
"tailwindcss": "^3.4.7"
"postcss": "^8.4.41",
"tailwindcss": "^3.4.9"
}
}

View file

@ -1 +1 @@
/// <reference types="astro/client" />
/// <reference path="../.astro/types.d.ts" />

View file

@ -12,7 +12,7 @@
"test": "vitest"
},
"dependencies": {
"astro": "^4.13.3",
"astro": "^4.13.4",
"vitest": "^2.0.5"
}
}

View file

@ -52,13 +52,13 @@
"astro-benchmark": "workspace:*"
},
"devDependencies": {
"@astrojs/check": "^0.9.1",
"@biomejs/biome": "1.8.1",
"@astrojs/check": "^0.9.2",
"@biomejs/biome": "1.8.3",
"@changesets/changelog-github": "^0.5.0",
"@changesets/cli": "^2.27.7",
"@types/node": "^18.17.8",
"esbuild": "^0.21.5",
"eslint": "^9.8.0",
"eslint": "^9.9.0",
"eslint-plugin-no-only-tests": "^3.1.0",
"eslint-plugin-regexp": "^2.6.0",
"globby": "^14.0.2",

View file

@ -1,5 +1,21 @@
# astro
## 4.13.4
### Patch Changes
- [#11678](https://github.com/withastro/astro/pull/11678) [`34da907`](https://github.com/withastro/astro/commit/34da907f3b4fb411024e6d28fdb291fa78116950) Thanks [@ematipico](https://github.com/ematipico)! - Fixes a case where omitting a semicolon and line ending with carriage return - CRLF - in the `prerender` option could throw an error.
- [#11535](https://github.com/withastro/astro/pull/11535) [`932bd2e`](https://github.com/withastro/astro/commit/932bd2eb07f1d7cb2c91e7e7d31fe84c919e302b) Thanks [@matthewp](https://github.com/matthewp)! - Encrypt server island props
Server island props are now encrypted with a key generated at build-time. This is intended to prevent accidentally leaking secrets caused by exposing secrets through prop-passing. This is not intended to allow a server island to be trusted to skip authentication, or to protect against any other vulnerabilities other than secret leakage.
See the RFC for an explanation: https://github.com/withastro/roadmap/blob/server-islands/proposals/server-islands.md#props-serialization
- [#11655](https://github.com/withastro/astro/pull/11655) [`dc0a297`](https://github.com/withastro/astro/commit/dc0a297e2a4bea3db8310cc98c51b2f94ede5fde) Thanks [@billy-le](https://github.com/billy-le)! - Fixes Astro Actions `input` validation when using `default` values with a form input.
- [#11689](https://github.com/withastro/astro/pull/11689) [`c7bda4c`](https://github.com/withastro/astro/commit/c7bda4cd672864babc3cebd19a2dd2e1af85c087) Thanks [@ematipico](https://github.com/ematipico)! - Fixes an issue in the Astro actions, where the size of the generated cookie was exceeding the size permitted by the `Set-Cookie` header.
## 4.13.3
### Patch Changes
@ -7562,7 +7578,7 @@
## 2.0.0
> **Note**
> This is a detailed changelog of all changes in Astro v2.
> This is a detailed changelog of all changes in Astro v2.
> See our [upgrade guide](https://docs.astro.build/en/guides/upgrade-to/v2/) for an overview of steps needed to upgrade an existing project.
### Major Changes

View file

@ -23,6 +23,13 @@ interface Props extends Omit<HTMLAttributes<'pre'>, 'lang'> {
* @default "plaintext"
*/
lang?: BuiltinLanguage | SpecialLanguage | LanguageRegistration;
/**
* A metastring to pass to the highlighter.
* Allows passing information to transformers: https://shiki.style/guide/transformers#meta
*
* @default undefined
*/
meta?: string;
/**
* The styling theme.
* Supports all themes listed here: https://shiki.style/themes
@ -72,6 +79,7 @@ interface Props extends Omit<HTMLAttributes<'pre'>, 'lang'> {
const {
code,
lang = 'plaintext',
meta,
theme = 'github-dark',
themes = {},
defaultColor = 'light',
@ -110,6 +118,7 @@ const highlighter = await getCachedHighlighter({
const html = await highlighter.highlight(code, typeof lang === 'string' ? lang : lang.name, {
inline,
meta,
attributes: rest as any,
});
---

View file

@ -10,7 +10,7 @@
"astro": "astro"
},
"dependencies": {
"@astrojs/check": "^0.9.1",
"@astrojs/check": "^0.9.2",
"@astrojs/db": "workspace:*",
"@astrojs/node": "workspace:*",
"@astrojs/react": "workspace:*",

View file

@ -10,7 +10,7 @@
"astro": "astro"
},
"dependencies": {
"@astrojs/check": "^0.9.1",
"@astrojs/check": "^0.9.2",
"@astrojs/db": "workspace:*",
"@astrojs/node": "workspace:*",
"@astrojs/react": "workspace:*",

View file

@ -5,6 +5,6 @@
"dependencies": {
"@astrojs/vue": "workspace:*",
"astro": "workspace:*",
"vue": "^3.4.35"
"vue": "^3.4.37"
}
}

View file

@ -14,8 +14,8 @@
"preact": "^10.23.1",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"solid-js": "^1.8.19",
"solid-js": "^1.8.20",
"svelte": "^4.2.18",
"vue": "^3.4.35"
"vue": "^3.4.37"
}
}

View file

@ -13,8 +13,8 @@
"react": "^18.3.1",
"react-dom": "^18.3.1",
"sass": "^1.77.8",
"solid-js": "^1.8.19",
"solid-js": "^1.8.20",
"svelte": "^4.2.18",
"vue": "^3.4.35"
"vue": "^3.4.37"
}
}

View file

@ -6,6 +6,6 @@
"@astrojs/lit": "workspace:*",
"@webcomponents/template-shadowroot": "^0.2.1",
"astro": "workspace:*",
"lit": "^3.1.4"
"lit": "^3.2.0"
}
}

View file

@ -13,12 +13,12 @@
},
"dependencies": {
"@webcomponents/template-shadowroot": "^0.2.1",
"lit": "^3.1.4",
"lit": "^3.2.0",
"preact": "^10.23.1",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"solid-js": "^1.8.19",
"solid-js": "^1.8.20",
"svelte": "^4.2.18",
"vue": "^3.4.35"
"vue": "^3.4.37"
}
}

View file

@ -14,8 +14,8 @@
"preact": "^10.23.1",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"solid-js": "^1.8.19",
"solid-js": "^1.8.20",
"svelte": "^4.2.18",
"vue": "^3.4.35"
"vue": "^3.4.37"
}
}

View file

@ -14,8 +14,8 @@
"preact": "^10.23.1",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"solid-js": "^1.8.19",
"solid-js": "^1.8.20",
"svelte": "^4.2.18",
"vue": "^3.4.35"
"vue": "^3.4.37"
}
}

View file

@ -14,8 +14,8 @@
"preact": "^10.23.1",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"solid-js": "^1.8.19",
"solid-js": "^1.8.20",
"svelte": "^4.2.18",
"vue": "^3.4.35"
"vue": "^3.4.37"
}
}

View file

@ -14,8 +14,8 @@
"preact": "^10.23.1",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"solid-js": "^1.8.19",
"solid-js": "^1.8.20",
"svelte": "^4.2.18",
"vue": "^3.4.35"
"vue": "^3.4.37"
}
}

View file

@ -14,8 +14,8 @@
"preact": "^10.23.1",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"solid-js": "^1.8.19",
"solid-js": "^1.8.20",
"svelte": "^4.2.18",
"vue": "^3.4.35"
"vue": "^3.4.37"
}
}

View file

@ -14,9 +14,9 @@
"preact": "^10.23.1",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"solid-js": "^1.8.19",
"solid-js": "^1.8.20",
"svelte": "^4.2.18",
"vue": "^3.4.35"
"vue": "^3.4.37"
},
"scripts": {
"dev": "astro dev"

View file

@ -1,4 +1,6 @@
---
const { secret } = Astro.props;
---
<h2 id="island">I am an island</h2>
<slot />
<h3 id="secret">{secret}</h3>

View file

@ -8,7 +8,7 @@ import Self from '../components/Self.astro';
<!-- Head Stuff -->
</head>
<body>
<Island server:defer>
<Island server:defer secret="test">
<h3 id="children">children</h3>
</Island>
<Self server:defer />

View file

@ -7,6 +7,6 @@
"astro": "workspace:*"
},
"devDependencies": {
"solid-js": "^1.8.19"
"solid-js": "^1.8.20"
}
}

View file

@ -6,6 +6,6 @@
"@astrojs/mdx": "workspace:*",
"@astrojs/solid-js": "workspace:*",
"astro": "workspace:*",
"solid-js": "^1.8.19"
"solid-js": "^1.8.20"
}
}

View file

@ -7,6 +7,6 @@
"astro": "workspace:*"
},
"devDependencies": {
"solid-js": "^1.8.19"
"solid-js": "^1.8.20"
}
}

View file

@ -6,7 +6,7 @@
"@astrojs/tailwind": "workspace:*",
"astro": "workspace:*",
"autoprefixer": "^10.4.20",
"postcss": "^8.4.40",
"tailwindcss": "^3.4.7"
"postcss": "^8.4.41",
"tailwindcss": "^3.4.9"
}
}

View file

@ -11,6 +11,6 @@
"react": "^18.3.1",
"react-dom": "^18.3.1",
"svelte": "^4.2.18",
"vue": "^3.4.35"
"vue": "^3.4.37"
}
}

View file

@ -6,6 +6,6 @@
"@astrojs/mdx": "workspace:*",
"@astrojs/vue": "workspace:*",
"astro": "workspace:*",
"vue": "^3.4.35"
"vue": "^3.4.37"
}
}

View file

@ -38,6 +38,12 @@ test.describe('Server islands', () => {
await expect(el, 'element rendered').toBeVisible();
});
test('Props are encrypted', async ({ page, astro }) => {
await page.goto(astro.resolveUrl('/base/'));
let el = page.locator('#secret');
await expect(el).toHaveText('test');
});
test('Self imported module can server defer', async ({ page, astro }) => {
await page.goto(astro.resolveUrl('/base/'));
let el = page.locator('.now');
@ -69,5 +75,11 @@ test.describe('Server islands', () => {
await expect(el, 'element rendered').toBeVisible();
await expect(el, 'should have content').toHaveText('I am an island');
});
test('Props are encrypted', async ({ page, astro }) => {
await page.goto(astro.resolveUrl('/'));
let el = page.locator('#secret');
await expect(el).toHaveText('test');
});
});
});

View file

@ -1,6 +1,6 @@
{
"name": "astro",
"version": "4.13.3",
"version": "4.13.4",
"description": "Astro is a modern site builder with web best practices, performance, and DX front-of-mind.",
"type": "module",
"author": "withastro",
@ -68,6 +68,7 @@
"./assets/services/sharp": "./dist/assets/services/sharp.js",
"./assets/services/squoosh": "./dist/assets/services/squoosh.js",
"./assets/services/noop": "./dist/assets/services/noop.js",
"./loaders": "./dist/content/loaders/index.js",
"./content/runtime": "./dist/content/runtime.js",
"./content/runtime-assets": "./dist/content/runtime-assets.js",
"./debug": "./components/Debug.astro",
@ -122,7 +123,7 @@
"test:node": "astro-scripts test \"test/**/*.test.js\""
},
"dependencies": {
"@astrojs/compiler": "^2.10.1",
"@astrojs/compiler": "^2.10.2",
"@astrojs/internal-helpers": "workspace:*",
"@astrojs/markdown-remark": "workspace:*",
"@astrojs/telemetry": "workspace:*",
@ -132,6 +133,8 @@
"@babel/plugin-transform-react-jsx": "^7.25.2",
"@babel/traverse": "^7.25.3",
"@babel/types": "^7.25.2",
"@rollup/pluginutils": "^5.1.0",
"@oslojs/encoding": "^0.4.1",
"@types/babel__core": "^7.20.5",
"@types/cookie": "^0.6.0",
"acorn": "^8.12.1",
@ -162,7 +165,9 @@
"js-yaml": "^4.1.0",
"kleur": "^4.1.5",
"magic-string": "^0.30.11",
"micromatch": "^4.0.7",
"mrmime": "^2.0.0",
"neotraverse": "^0.6.9",
"ora": "^8.0.1",
"p-limit": "^6.1.0",
"p-queue": "^8.0.1",
@ -177,19 +182,20 @@
"tsconfck": "^3.1.1",
"unist-util-visit": "^5.0.0",
"vfile": "^6.0.2",
"vite": "^5.3.5",
"vite": "^5.4.0",
"vitefu": "^0.2.5",
"which-pm": "^3.0.0",
"yargs-parser": "^21.1.1",
"xxhash-wasm": "^1.0.2",
"zod": "^3.23.8",
"zod-to-json-schema": "^3.23.2"
"zod-to-json-schema": "^3.23.2",
"zod-to-ts": "^1.2.0"
},
"optionalDependencies": {
"sharp": "^0.33.3"
},
"devDependencies": {
"@astrojs/check": "^0.9.1",
"@playwright/test": "^1.45.3",
"@astrojs/check": "^0.9.2",
"@playwright/test": "^1.46.0",
"@types/aria-query": "^5.0.4",
"@types/babel__generator": "^7.6.8",
"@types/babel__traverse": "^7.20.6",
@ -203,11 +209,11 @@
"@types/html-escaper": "^3.0.2",
"@types/http-cache-semantics": "^4.0.4",
"@types/js-yaml": "^4.0.9",
"@types/micromatch": "^4.0.9",
"@types/prompts": "^2.4.9",
"@types/semver": "^7.5.8",
"@types/yargs-parser": "^21.0.3",
"astro-scripts": "workspace:*",
"cheerio": "1.0.0-rc.12",
"cheerio": "1.0.0",
"eol": "^0.9.1",
"expect-type": "^0.19.0",
"mdast-util-mdx": "^3.0.0",
@ -221,7 +227,7 @@
"remark-code-titles": "^0.1.2",
"rollup": "^4.20.0",
"sass": "^1.77.8",
"undici": "^6.19.5",
"undici": "^6.19.7",
"unified": "^11.0.5"
},
"engines": {

View file

@ -1,8 +1,8 @@
/* eslint-disable no-console */
import { fileURLToPath } from 'node:url';
import { parseArgs } from 'node:util';
import { bold, cyan, dim } from 'kleur/colors';
import yargs from 'yargs-parser';
import { loadFixture } from '../test/test-utils.js';
import { generatePosts } from './scripts/generate-posts.mjs';
@ -40,7 +40,7 @@ async function benchmark({ fixtures, templates, numPosts }) {
// Test the build performance for content collections across multiple file types (md, mdx, mdoc)
(async function benchmarkAll() {
try {
const flags = yargs(process.argv.slice(2));
const { values: flags } = parseArgs({ strict: false });
const test = Array.isArray(flags.test)
? flags.test
: typeof flags.test === 'string'

View file

@ -11,8 +11,6 @@
"author": "",
"license": "ISC",
"devDependencies": {
"@types/yargs-parser": "^21.0.3",
"kleur": "^4.1.5",
"yargs-parser": "^21.1.1"
"kleur": "^4.1.5"
}
}

View file

@ -1,5 +1,3 @@
import type { OutgoingHttpHeaders } from 'node:http';
import type { AddressInfo } from 'node:net';
import type {
MarkdownHeading,
MarkdownVFile,
@ -9,6 +7,8 @@ import type {
ShikiConfig,
} from '@astrojs/markdown-remark';
import type * as babel from '@babel/core';
import type { OutgoingHttpHeaders } from 'node:http';
import type { AddressInfo } from 'node:net';
import type * as rollup from 'rollup';
import type * as vite from 'vite';
import type {
@ -18,6 +18,7 @@ import type {
ActionReturnType,
} from '../actions/runtime/virtual/server.js';
import type { RemotePattern } from '../assets/utils/remotePattern.js';
import type { DataEntry, RenderedContent } from '../content/data-store.js';
import type { AssetsPrefix, SSRManifest, SerializedSSRManifest } from '../core/app/types.js';
import type { PageBuildData } from '../core/build/types.js';
import type { AstroConfigType } from '../core/config/index.js';
@ -78,7 +79,7 @@ export type {
UnresolvedImageTransform,
} from '../assets/types.js';
export type { RemotePattern } from '../assets/utils/remotePattern.js';
export type { SSRManifest, AssetsPrefix } from '../core/app/types.js';
export type { AssetsPrefix, SSRManifest } from '../core/app/types.js';
export type {
AstroCookieGetOptions,
AstroCookieSetOptions,
@ -123,6 +124,7 @@ export type TransitionAnimationValue =
| TransitionDirectionalAnimations;
// Allow users to extend this for astro-jsx.d.ts
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
export interface AstroClientDirectives {}
@ -2111,6 +2113,225 @@ export interface AstroUserConfig {
* For a complete overview, and to give feedback on this experimental API, see the [Server Islands RFC](https://github.com/withastro/roadmap/pull/963).
*/
serverIslands?: boolean;
/**
* @docs
* @name experimental.contentIntellisense
* @type {boolean}
* @default `false`
* @version 4.14.0
* @description
*
* Enables Intellisense features (e.g. code completion, quick hints) for your content collection entries in compatible editors.
*
* When enabled, this feature will generate and add JSON schemas to the `.astro` directory in your project. These files can be used by the Astro language server to provide Intellisense inside content files (`.md`, `.mdx`, `.mdoc`).
*
* ```js
* {
* experimental: {
* contentIntellisense: true,
* },
* }
* ```
*
* To use this feature with the Astro VS Code extension, you must also enable the `astro.content-intellisense` option in your VS Code settings. For editors using the Astro language server directly, pass the `contentIntellisense: true` initialization parameter to enable this feature.
*/
contentIntellisense?: boolean;
/**
* @docs
* @name experimental.contentLayer
* @type {boolean}
* @default `false`
* @version 4.14.0
* @description
*
* The Content Layer API is a new way to handle content and data in Astro. It is similar to and builds upon [content collections](/en/guides/content-collections/), taking them beyond local files in `src/content/` and allowing you to fetch content from anywhere, including remote APIs, by adding a `loader` to your collection.
*
* Your existing content collections can be [migrated to the Content Layer API](#migrating-a-content-collection-to-content-layer) with a few small changes. However, it is not necessary to update all your collections at once to add a new collection powered by the Content Layer API. You may have collections using both the existing and new APIs defined in `src/content/config.ts` at the same time.
*
* The Content Layer API is designed to be more powerful and more performant, helping sites scale to thousands of pages. Data is cached between builds and updated incrementally. Markdown parsing is also 5-10 times faster, with similar scale reductions in memory, and MDX is 2-3 times faster.
*
* To enable, add the `contentLayer` flag to the `experimental` object in your Astro config:
*
* ```js
* // astro.config.mjs
* {
* experimental: {
* contentLayer: true,
* }
* }
* ```
*
* #### Fetching data with a `loader`
*
* The Content Layer API allows you to fetch your content from outside of the `src/content/` folder (whether stored locally in your project or remotely), and uses a `loader` property to retrieve your data.
*
* The `loader` is defined in the collection's schema and returns an array of entries. Astro provides two built-in loader functions (`glob()` and `file()`) for fetching your local content, as well as access to the API to [construct your own loader and fetch remote data](#creating-a-loader).
*
* The `glob()` loader creates entries from directories of Markdown, MDX, Markdoc, or JSON files from anywhere on the filesystem. It accepts a `pattern` of entry files to match, and a `base` file path of where your files are located. Use this when you have one file per entry.
*
* The `file()` loader creates multiple entries from a single local file. Use this when all your entries are stored in an array of objects.
*
* ```ts {3,8,19}
* // src/content/config.ts
* import { defineCollection, z } from 'astro:content';
* import { glob, file } from 'astro/loaders';
*
* const blog = defineCollection({
* // By default the ID is a slug generated from
* // the path of the file relative to `base`
* loader: glob({ pattern: "**\/*.md", base: "./src/data/blog" }),
* schema: z.object({
* title: z.string(),
* description: z.string(),
* pubDate: z.coerce.date(),
* updatedDate: z.coerce.date().optional(),
* })
* });
*
* const dogs = defineCollection({
* // The path is relative to the project root, or an absolute path.
* loader: file("src/data/dogs.json"),
* schema: z.object({
* id: z.string(),
* breed: z.string(),
* temperament: z.array(z.string()),
* }),
* });
*
* export const collections = { blog, dogs };
* ```
*
* #### Querying and rendering with the Content Layer API
*
* The collection can be [queried in the same way as content collections](/en/guides/content-collections/#querying-collections):
*
* ```ts
* // src/pages/index.astro
* import { getCollection, getEntry } from 'astro:content';
*
* // Get all entries from a collection.
* // Requires the name of the collection as an argument.
* const allBlogPosts = await getCollection('blog');
*
* // Get a single entry from a collection.
* // Requires the name of the collection and ID
* const labradorData = await getEntry('dogs', 'labrador-retriever');
* ```
*
* Entries generated from Markdown, MDX or Markdoc can be rendered directly to a page using the `render()` function.
*
* :::note
* The syntax for rendering collection entries is different from current content collections syntax.
* :::
*
* ```astro title="src/pages/[slug].astro"
* ---
* import { getEntry, render } from 'astro:content';
*
* const post = await getEntry('blog', Astro.params.slug);
*
* const { Content, headings } = await render(entry);
* ---
*
* <Content />
* ```
*
* #### Creating a loader
*
* With the Content Layer API, you can build loaders to load or generate content from anywhere.
*
* For example, you can create a loader that fetches collection entries from a remote API.
*
* ```ts
* // src/content/config.ts
* const countries = defineCollection({
* loader: async () => {
* const response = await fetch("https://restcountries.com/v3.1/all");
* const data = await response.json();
* // Must return an array of entries with an id property,
* // or an object with IDs as keys and entries as values
* return data.map((country) => ({
* id: country.cca3,
* ...country,
* }));
* },
* // optionally add a schema
* // schema: z.object...
* });
*
* export const collections = { countries };
* ```
*
* For more advanced loading logic, you can define an object loader. This allows incremental updates and conditional loading, and gives full access to the data store. See the API in [the Content Layer API RFC](https://github.com/withastro/roadmap/blob/content-layer/proposals/0047-content-layer.md#loaders).
*
* #### Migrating an existing content collection to use the Content Layer API
*
* You can convert an existing content collection with Markdown, MDX, Markdoc, or JSON entries to use the Content Layer API.
*
* 1. **Move the collection folder out of `src/content/`** (e.g. to `src/data/`). All collections located in the `src/content/` folder will use the existing Content Collections API.
*
* **Do not move the existing `src/content/config.ts` file**. This file will define all collections, using either API.
*
* 2. **Edit the collection definition**. Your updated collection requires a `loader`, and the option to select a collection `type` is no longer available.
*
* ```diff
* // src/content/config.ts
* import { defineCollection, z } from 'astro:content';
* + import { glob } from 'astro/loaders';
*
* const blog = defineCollection({
* // For content layer you no longer define a `type`
* - type: 'content',
* + loader: glob({ pattern: "**\/*.md", base: "./src/data/blog" }),
* schema: z.object({
* title: z.string(),
* description: z.string(),
* pubDate: z.coerce.date(),
* updatedDate: z.coerce.date().optional(),
* }),
* });
* ```
*
* 3. **Change references from `slug` to `id`**. Content layer collections do not have a `slug` field. Instead, all updated collections will have an `id`.
*
* ```diff
* // src/pages/index.astro
* ---
* export async function getStaticPaths() {
* const posts = await getCollection('blog');
* return posts.map((post) => ({
* - params: { slug: post.slug },
* + params: { slug: post.id },
* props: post,
* }));
* }
* ---
* ```
*
* 4. **Switch to the new `render()` function**. Entries no longer have a `render()` method, as they are now serializable plain objects. Instead, import the `render()` function from `astro:content`.
*
* ```diff
* // src/pages/index.astro
* ---
* - import { getEntry } from 'astro:content';
* + import { getEntry, render } from 'astro:content';
*
* const post = await getEntry('blog', params.slug);
*
* - const { Content, headings } = await post.render();
* + const { Content, headings } = await render(post);
* ---
*
* <Content />
* ```
*
* #### Learn more
*
* For a complete overview and the full API reference, see [the Content Layer API RFC](https://github.com/withastro/roadmap/blob/content-layer/proposals/0047-content-layer.md) and [share your feedback](https://github.com/withastro/roadmap/pull/982).
*/
contentLayer?: boolean;
};
}
@ -2151,6 +2372,21 @@ export interface ResolvedInjectedRoute extends InjectedRoute {
resolvedEntryPoint?: URL;
}
export interface RouteOptions {
/**
* The path to this route relative to the project root. The slash is normalized as forward slash
* across all OS.
* @example "src/pages/blog/[...slug].astro"
*/
readonly component: string;
/**
* Whether this route should be prerendered. If the route has an explicit `prerender` export,
* the value will be passed here. Otherwise, it's undefined and will fallback to a prerender
* default depending on the `output` option.
*/
prerender?: boolean;
}
/**
* Resolved Astro Config
* Config with user settings along with all defaults filled in.
@ -2192,6 +2428,10 @@ export interface AstroInlineOnlyConfig {
* @default "info"
*/
logLevel?: LoggerLevel;
/**
* Clear the content layer cache, forcing a rebuild of all content entries.
*/
force?: boolean;
/**
* @internal for testing only, use `logLevel` instead.
*/
@ -2220,6 +2460,8 @@ export type DataEntryModule = {
};
};
export type ContentEntryRenderFuction = (entry: DataEntry) => Promise<RenderedContent>;
export interface ContentEntryType {
extensions: string[];
getEntryInfo(params: {
@ -2235,6 +2477,8 @@ export interface ContentEntryType {
},
): rollup.LoadResult | Promise<rollup.LoadResult>;
contentModuleTypes?: string;
getRenderFunction?(settings: AstroSettings): Promise<ContentEntryRenderFuction>;
/**
* Handle asset propagation for rendered content to avoid bleed.
* Ex. MDX content can import styles and scripts, so `handlePropagation` should be true.
@ -2267,7 +2511,7 @@ export type GetDataEntryInfoReturnType = { data: Record<string, unknown>; rawDat
export interface AstroAdapterFeatures {
/**
* Creates and edge function that will communiate with the Astro middleware
* Creates an edge function that will communiate with the Astro middleware
*/
edgeMiddleware: boolean;
/**
@ -2276,6 +2520,11 @@ export interface AstroAdapterFeatures {
functionPerRoute: boolean;
}
export interface InjectedType {
filename: string;
content: string;
}
export interface AstroSettings {
config: AstroConfig;
adapter: AstroAdapter | undefined;
@ -2311,6 +2560,7 @@ export interface AstroSettings {
latestAstroVersion: string | undefined;
serverIslandMap: NonNullable<SSRManifest['serverIslandMap']>;
serverIslandNameMap: NonNullable<SSRManifest['serverIslandNameMap']>;
injectedTypes: Array<InjectedType>;
}
export type AsyncRendererComponentFn<U> = (
@ -3012,6 +3262,7 @@ declare global {
'astro:config:done': (options: {
config: AstroConfig;
setAdapter: (adapter: AstroAdapter) => void;
injectTypes: (injectedType: InjectedType) => URL;
logger: AstroIntegrationLogger;
}) => void | Promise<void>;
'astro:server:setup': (options: {
@ -3056,6 +3307,10 @@ declare global {
logger: AstroIntegrationLogger;
cacheManifest: boolean;
}) => void | Promise<void>;
'astro:route:setup': (options: {
route: RouteOptions;
logger: AstroIntegrationLogger;
}) => void | Promise<void>;
}
}
}
@ -3211,6 +3466,7 @@ export interface SSRResult {
cookies: AstroCookies | undefined;
serverIslandNameMap: Map<string, string>;
trailingSlash: AstroConfig['trailingSlash'];
key: Promise<CryptoKey>;
_metadata: SSRMetadata;
}

View file

@ -1,6 +1,6 @@
export const VIRTUAL_MODULE_ID = 'astro:actions';
export const RESOLVED_VIRTUAL_MODULE_ID = '\0' + VIRTUAL_MODULE_ID;
export const ACTIONS_TYPES_FILE = 'actions.d.ts';
export const ACTIONS_TYPES_FILE = 'astro/actions.d.ts';
export const VIRTUAL_INTERNAL_MODULE_ID = 'astro:internal-actions';
export const RESOLVED_VIRTUAL_INTERNAL_MODULE_ID = '\0astro:internal-actions';
export const NOOP_ACTIONS = '\0noop-actions';

View file

@ -30,9 +30,6 @@ export default function astroActions({
throw error;
}
const stringifiedActionsImport = JSON.stringify(
viteID(new URL('./actions', params.config.srcDir)),
);
params.updateConfig({
vite: {
plugins: [vitePluginUserActions({ settings }), vitePluginActions(fs)],
@ -49,11 +46,18 @@ export default function astroActions({
entrypoint: 'astro/actions/runtime/middleware.js',
order: 'post',
});
},
'astro:config:done': (params) => {
const stringifiedActionsImport = JSON.stringify(
viteID(new URL('./actions', params.config.srcDir)),
);
settings.injectedTypes.push({
filename: ACTIONS_TYPES_FILE,
content: `declare module "astro:actions" {
type Actions = typeof import(${stringifiedActionsImport})["server"];
await typegen({
stringifiedActionsImport,
root: params.config.root,
fs,
export const actions: Actions;
}`,
});
},
},
@ -119,24 +123,3 @@ const vitePluginActions = (fs: typeof fsMod): VitePlugin => ({
return code;
},
});
async function typegen({
stringifiedActionsImport,
root,
fs,
}: {
stringifiedActionsImport: string;
root: URL;
fs: typeof fsMod;
}) {
const content = `declare module "astro:actions" {
type Actions = typeof import(${stringifiedActionsImport})["server"];
export const actions: Actions;
}`;
const dotAstroDir = new URL('.astro/', root);
await fs.promises.mkdir(dotAstroDir, { recursive: true });
await fs.promises.writeFile(new URL(ACTIONS_TYPES_FILE, dotAstroDir), content);
}

Some files were not shown because too many files have changed in this diff Show more