0
Fork 0
mirror of https://github.com/withastro/astro.git synced 2025-04-14 23:51:49 -05:00

Merge branch 'main' into next

This commit is contained in:
Princesseuh 2024-08-10 01:40:54 +02:00
commit 7dc0680d60
No known key found for this signature in database
GPG key ID: 105BBD6D57F2B0C0
575 changed files with 2532 additions and 2391 deletions
.changeset
.git-blame-ignore-revsREADME.mdbiome.jsoneslint.config.js
examples
basics
blog
component
container-with-vitest
framework-alpine
framework-lit
framework-multiple
framework-preact
framework-react
framework-solid
framework-svelte
framework-vue
hackernews
integration
middleware
minimal
non-html-pages
portfolio
server-islands
ssr
starlog
toolbar-app
view-transitions
with-markdoc
with-markdown-plugins
with-markdown-shiki
with-mdx
with-nanostores
with-tailwindcss
with-vitest
package.json
packages

View file

@ -1,5 +0,0 @@
---
'astro': patch
---
Deprecates `getEntryBySlug` and `getDataEntryById` functions exported by `astro:content` in favor of `getEntry`.

View file

@ -1,7 +0,0 @@
---
'astro': patch
---
Adds support for `Date()`, `Map()`, and `Set()` from action results. See [devalue](https://github.com/Rich-Harris/devalue) for a complete list of supported values.
Also fixes serialization exceptions when deploying Actions with edge middleware on Netlify and Vercel.

View file

@ -1,5 +0,0 @@
---
'astro': patch
---
Fix toolbar audit incorrectly flagging images as above the fold.

View file

@ -6,3 +6,5 @@
59e8c71786fd1c154904b3fefa7d26d88f4d92d2
# Change formatting (#10180)
062623438b5dfd66682a967edc7b7c91bd29e888
# Update to trailingComma: 'all' (#11640)
72c7ae9901de927ae8d9d5be63cbaef4f976422c

View file

@ -50,24 +50,26 @@ Join us on [Discord](https://astro.build/chat) to meet other maintainers. We'll
## Directory
| Package | Release Notes |
| ------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [astro](packages/astro) | [![astro version](https://img.shields.io/npm/v/astro.svg?label=%20)](packages/astro/CHANGELOG.md) |
| [create-astro](packages/create-astro) | [![create-astro version](https://img.shields.io/npm/v/create-astro.svg?label=%20)](packages/create-astro/CHANGELOG.md) |
| [@astrojs/react](packages/integrations/react) | [![astro version](https://img.shields.io/npm/v/@astrojs/react.svg?label=%20)](packages/integrations/react/CHANGELOG.md) |
| [@astrojs/preact](packages/integrations/preact) | [![astro version](https://img.shields.io/npm/v/@astrojs/preact.svg?label=%20)](packages/integrations/preact/CHANGELOG.md) |
| [@astrojs/solid-js](packages/integrations/solid) | [![astro version](https://img.shields.io/npm/v/@astrojs/solid-js.svg?label=%20)](packages/integrations/solid/CHANGELOG.md) |
| [@astrojs/svelte](packages/integrations/svelte) | [![astro version](https://img.shields.io/npm/v/@astrojs/svelte.svg?label=%20)](packages/integrations/svelte/CHANGELOG.md) |
| [@astrojs/vue](packages/integrations/vue) | [![astro version](https://img.shields.io/npm/v/@astrojs/vue.svg?label=%20)](packages/integrations/vue/CHANGELOG.md) |
| [@astrojs/lit](packages/integrations/lit) | [![astro version](https://img.shields.io/npm/v/@astrojs/lit.svg?label=%20)](packages/integrations/lit/CHANGELOG.md) |
| [@astrojs/node](packages/integrations/node) | [![astro version](https://img.shields.io/npm/v/@astrojs/node.svg?label=%20)](packages/integrations/node/CHANGELOG.md) |
| [@astrojs/vercel](packages/integrations/vercel) | [![astro version](https://img.shields.io/npm/v/@astrojs/vercel.svg?label=%20)](packages/integrations/vercel/CHANGELOG.md) |
| [@astrojs/cloudflare](https://github.com/withastro/adapters/blob/main/packages/cloudflare) | [![astro version](https://img.shields.io/npm/v/@astrojs/cloudflare.svg?label=%20)](https://github.com/withastro/adapters/blob/main/packages/cloudflare/CHANGELOG.md) |
| [@astrojs/partytown](packages/integrations/partytown) | [![astro version](https://img.shields.io/npm/v/@astrojs/partytown.svg?label=%20)](packages/integrations/partytown/CHANGELOG.md) |
| [@astrojs/sitemap](packages/integrations/sitemap) | [![astro version](https://img.shields.io/npm/v/@astrojs/sitemap.svg?label=%20)](packages/integrations/sitemap/CHANGELOG.md) |
| [@astrojs/tailwind](packages/integrations/tailwind) | [![astro version](https://img.shields.io/npm/v/@astrojs/tailwind.svg?label=%20)](packages/integrations/tailwind/CHANGELOG.md) |
| [@astrojs/alpinejs](packages/integrations/alpinejs) | [![astro version](https://img.shields.io/npm/v/@astrojs/alpinejs.svg?label=%20)](packages/integrations/alpinejs/CHANGELOG.md) |
| [@astrojs/mdx](packages/integrations/mdx) | [![astro version](https://img.shields.io/npm/v/@astrojs/mdx.svg?label=%20)](packages/integrations/mdx/CHANGELOG.md) |
| Package | Release Notes |
| ------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [astro](packages/astro) | [![astro version](https://img.shields.io/npm/v/astro.svg?label=%20)](packages/astro/CHANGELOG.md) |
| [create-astro](packages/create-astro) | [![create-astro version](https://img.shields.io/npm/v/create-astro.svg?label=%20)](packages/create-astro/CHANGELOG.md) |
| [@astrojs/react](packages/integrations/react) | [![@astrojs/react version](https://img.shields.io/npm/v/@astrojs/react.svg?label=%20)](packages/integrations/react/CHANGELOG.md) |
| [@astrojs/preact](packages/integrations/preact) | [![@astrojs/preact version](https://img.shields.io/npm/v/@astrojs/preact.svg?label=%20)](packages/integrations/preact/CHANGELOG.md) |
| [@astrojs/solid-js](packages/integrations/solid) | [![@astrojs/solid version](https://img.shields.io/npm/v/@astrojs/solid-js.svg?label=%20)](packages/integrations/solid/CHANGELOG.md) |
| [@astrojs/svelte](packages/integrations/svelte) | [![@astrojs/svelte version](https://img.shields.io/npm/v/@astrojs/svelte.svg?label=%20)](packages/integrations/svelte/CHANGELOG.md) |
| [@astrojs/vue](packages/integrations/vue) | [![@astrojs/vue version](https://img.shields.io/npm/v/@astrojs/vue.svg?label=%20)](packages/integrations/vue/CHANGELOG.md) |
| [@astrojs/lit](packages/integrations/lit) | [![@astrojs/lit version](https://img.shields.io/npm/v/@astrojs/lit.svg?label=%20)](packages/integrations/lit/CHANGELOG.md) |
| [@astrojs/node](packages/integrations/node) | [![@astrojs/node version](https://img.shields.io/npm/v/@astrojs/node.svg?label=%20)](packages/integrations/node/CHANGELOG.md) |
| [@astrojs/vercel](packages/integrations/vercel) | [![@astrojs/vercel version](https://img.shields.io/npm/v/@astrojs/vercel.svg?label=%20)](packages/integrations/vercel/CHANGELOG.md) |
| [@astrojs/cloudflare](https://github.com/withastro/adapters/blob/main/packages/cloudflare) | [![@astrojs/cloudflare version](https://img.shields.io/npm/v/@astrojs/cloudflare.svg?label=%20)](https://github.com/withastro/adapters/blob/main/packages/cloudflare/CHANGELOG.md) |
| [@astrojs/partytown](packages/integrations/partytown) | [![@astrojs/partytown version](https://img.shields.io/npm/v/@astrojs/partytown.svg?label=%20)](packages/integrations/partytown/CHANGELOG.md) |
| [@astrojs/sitemap](packages/integrations/sitemap) | [![@astrojs/sitemap version](https://img.shields.io/npm/v/@astrojs/sitemap.svg?label=%20)](packages/integrations/sitemap/CHANGELOG.md) |
| [@astrojs/tailwind](packages/integrations/tailwind) | [![@astrojs/tailwind version](https://img.shields.io/npm/v/@astrojs/tailwind.svg?label=%20)](packages/integrations/tailwind/CHANGELOG.md) |
| [@astrojs/alpinejs](packages/integrations/alpinejs) | [![@astrojs/alpinejs version](https://img.shields.io/npm/v/@astrojs/alpinejs.svg?label=%20)](packages/integrations/alpinejs/CHANGELOG.md) |
| [@astrojs/mdx](packages/integrations/mdx) | [![@astrojs/mdx version](https://img.shields.io/npm/v/@astrojs/mdx.svg?label=%20)](packages/integrations/mdx/CHANGELOG.md) |
| [@astrojs/db](packages/db) | [![@astrojs/db version](https://img.shields.io/npm/v/@astrojs/db.svg?label=%20)](packages/db/CHANGELOG.md) |
| [@astrojs/rss](packages/integrations/astro-rss) | [![@astrojs/rss version](https://img.shields.io/npm/v/@astrojs/rss.svg?label=%20)](packages/astro-rss/CHANGELOG.md) |
[![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/6178/badge)](https://bestpractices.coreinfrastructure.org/projects/6178)

View file

@ -29,7 +29,7 @@
"linter": { "enabled": false },
"javascript": {
"formatter": {
"trailingCommas": "es5",
"trailingCommas": "all",
"quoteStyle": "single",
"semicolons": "always"
}

View file

@ -83,10 +83,13 @@ export default [
'@typescript-eslint/no-unsafe-assignment': 'off',
'@typescript-eslint/no-unsafe-call': 'off',
'@typescript-eslint/no-unsafe-member-access': 'off',
'@typescript-eslint/no-unused-expressions': 'off',
'@typescript-eslint/only-throw-error': 'off',
'@typescript-eslint/no-unsafe-return': 'off',
'@typescript-eslint/no-unnecessary-type-assertion': 'off',
'@typescript-eslint/prefer-nullish-coalescing': 'off',
'@typescript-eslint/prefer-optional-chain': 'off',
'@typescript-eslint/prefer-promise-reject-errors': 'off',
'@typescript-eslint/prefer-string-starts-ends-with': 'off',
'@typescript-eslint/require-await': 'off',
'@typescript-eslint/restrict-plus-operands': 'off',
@ -111,6 +114,8 @@ export default [
// In some cases, using explicit letter-casing is more performant than the `i` flag
'regexp/use-ignore-case': 'off',
'regexp/prefer-regexp-exec': 'warn',
'regexp/prefer-regexp-test': 'warn',
},
},
@ -139,7 +144,6 @@ export default [
files: ['packages/**/test/*.js', 'packages/**/*.js'],
languageOptions: {
globals: {
mocha: true,
globalThis: false, // false means read-only
},
},

View file

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

View file

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

View file

@ -7,7 +7,7 @@ import { getCollection } from 'astro:content';
import FormattedDate from '../../components/FormattedDate.astro';
const posts = (await getCollection('blog')).sort(
(a, b) => b.data.pubDate.valueOf() - a.data.pubDate.valueOf()
(a, b) => b.data.pubDate.valueOf() - a.data.pubDate.valueOf(),
);
---

View file

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

View file

@ -12,8 +12,8 @@
"test": "vitest run"
},
"dependencies": {
"astro": "^4.13.1",
"@astrojs/react": "^3.6.1",
"astro": "^4.13.3",
"@astrojs/react": "^3.6.2",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"vitest": "^2.0.5"

View file

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

View file

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

View file

@ -12,13 +12,13 @@
},
"dependencies": {
"@astrojs/preact": "^3.5.1",
"@astrojs/react": "^3.6.1",
"@astrojs/solid-js": "^4.4.0",
"@astrojs/react": "^3.6.2",
"@astrojs/solid-js": "^4.4.1",
"@astrojs/svelte": "^5.7.0",
"@astrojs/vue": "^4.5.0",
"@types/react": "^18.3.3",
"@types/react-dom": "^18.3.0",
"astro": "^4.13.1",
"astro": "^4.13.3",
"preact": "^10.23.1",
"react": "^18.3.1",
"react-dom": "^18.3.1",

View file

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

View file

@ -11,10 +11,10 @@
"astro": "astro"
},
"dependencies": {
"@astrojs/react": "^3.6.1",
"@astrojs/react": "^3.6.2",
"@types/react": "^18.3.3",
"@types/react-dom": "^18.3.0",
"astro": "^4.13.1",
"astro": "^4.13.3",
"react": "^18.3.1",
"react-dom": "^18.3.1"
}

View file

@ -11,8 +11,8 @@
"astro": "astro"
},
"dependencies": {
"@astrojs/solid-js": "^4.4.0",
"astro": "^4.13.1",
"@astrojs/solid-js": "^4.4.1",
"astro": "^4.13.3",
"solid-js": "^1.8.19"
}
}

View file

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

View file

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

View file

@ -12,6 +12,6 @@
},
"dependencies": {
"@astrojs/node": "^8.3.2",
"astro": "^4.13.1"
"astro": "^4.13.3"
}
}

View file

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

View file

@ -13,7 +13,7 @@
},
"dependencies": {
"@astrojs/node": "^8.3.2",
"astro": "^4.13.1",
"astro": "^4.13.3",
"html-minifier": "^4.0.0"
},
"devDependencies": {

View file

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

View file

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

View file

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

View file

@ -9,7 +9,7 @@ import Hero from '../components/Hero.astro';
import Grid from '../components/Grid.astro';
const projects = (await getCollection('work')).sort(
(a, b) => b.data.publishDate.valueOf() - a.data.publishDate.valueOf()
(a, b) => b.data.publishDate.valueOf() - a.data.publishDate.valueOf(),
);
---

View file

@ -11,13 +11,13 @@
},
"devDependencies": {
"@astrojs/node": "^8.3.2",
"@astrojs/react": "^3.6.1",
"@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.1",
"astro": "^4.13.3",
"postcss": "^8.4.40",
"react": "^18.3.1",
"react-dom": "^18.3.1",

View file

@ -14,7 +14,7 @@
"dependencies": {
"@astrojs/node": "^8.3.2",
"@astrojs/svelte": "^5.7.0",
"astro": "^4.13.1",
"astro": "^4.13.3",
"svelte": "^4.2.18"
}
}

View file

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

View file

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

View file

@ -12,6 +12,6 @@
"devDependencies": {
"@astrojs/tailwind": "^5.1.0",
"@astrojs/node": "^8.3.2",
"astro": "^4.13.1"
"astro": "^4.13.3"
}
}

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -14,7 +14,7 @@
"@astrojs/mdx": "^3.1.3",
"@astrojs/tailwind": "^5.1.0",
"@types/canvas-confetti": "^1.6.4",
"astro": "^4.13.1",
"astro": "^4.13.3",
"autoprefixer": "^10.4.20",
"canvas-confetti": "^1.9.3",
"postcss": "^8.4.40",

View file

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

View file

@ -67,25 +67,9 @@
"prettier-plugin-astro": "^0.14.1",
"turbo": "^1.13.4",
"typescript": "~5.5.4",
"typescript-eslint": "^7.18.0"
"typescript-eslint": "^8.0.1"
},
"pnpm": {
"packageExtensions": {
"vite-svg-loader": {
"peerDependenciesMeta": {
"vue": {
"optional": true
}
}
},
"rehype-pretty-code": {
"peerDependenciesMeta": {
"shiki": {
"optional": true
}
}
}
},
"peerDependencyRules": {
"ignoreMissing": [
"rollup",

View file

@ -29,6 +29,6 @@ runHighlighterWithAstro(
<div>{helloAstro}</div>
`,
'astro'
'astro',
);
```

View file

@ -10,7 +10,7 @@ export function addAstro(Prism: typeof import('prismjs')) {
scriptLang = 'javascript';
// eslint-disable-next-line no-console
console.warn(
'Prism TypeScript language not loaded, Astro scripts will be treated as JavaScript.'
'Prism TypeScript language not loaded, Astro scripts will be treated as JavaScript.',
);
}
@ -41,7 +41,7 @@ export function addAstro(Prism: typeof import('prismjs')) {
(Prism.languages.astro as any).tag.pattern = re(
/<\/?(?:[\w.:-]+(?:<S>+(?:[\w.:$-]+(?:=(?:"(?:\\[\s\S]|[^\\"])*"|'(?:\\[\s\S]|[^\\'])*'|[^\s{'"/>=]+|<BRACES>))?|<SPREAD>))*<S>*\/?)?>/
.source
.source,
);
(Prism.languages.astro as any).tag.inside['tag'].pattern = /^<\/?[^\s>/]*/;
@ -60,7 +60,7 @@ export function addAstro(Prism: typeof import('prismjs')) {
inside: Prism.languages.astro,
},
},
(Prism.languages.astro as any).tag
(Prism.languages.astro as any).tag,
);
Prism.languages.insertBefore(
@ -80,7 +80,7 @@ export function addAstro(Prism: typeof import('prismjs')) {
alias: `language-${scriptLang}`,
},
},
(Prism.languages.astro as any).tag
(Prism.languages.astro as any).tag,
);
// The following will handle plain text inside tags

View file

@ -73,8 +73,8 @@ const rssOptionsValidator = z.object({
// eslint-disable-next-line
console.warn(
yellow(
'[RSS] Passing a glob result directly has been deprecated. Please migrate to the `pagesGlobToRssItems()` helper: https://docs.astro.build/en/guides/rss/'
)
'[RSS] Passing a glob result directly has been deprecated. Please migrate to the `pagesGlobToRssItems()` helper: https://docs.astro.build/en/guides/rss/',
),
);
return pagesGlobToRssItems(items);
}
@ -123,7 +123,7 @@ async function validateRssOptions(rssOptions: RSSOptions) {
return message;
}),
].join('\n')
].join('\n'),
);
throw formattedError;
}
@ -134,7 +134,7 @@ export function pagesGlobToRssItems(items: GlobResult): Promise<ValidatedRSSFeed
const { url, frontmatter } = await getInfo();
if (url === undefined || url === null) {
throw new Error(
`[RSS] You can only glob entries within 'src/pages/' when passing import.meta.glob() directly. Consider mapping the result to an array of RSSFeedItems. See the RSS docs for usage examples: https://docs.astro.build/en/guides/rss/#2-list-of-rss-feed-objects`
`[RSS] You can only glob entries within 'src/pages/' when passing import.meta.glob() directly. Consider mapping the result to an array of RSSFeedItems. See the RSS docs for usage examples: https://docs.astro.build/en/guides/rss/#2-list-of-rss-feed-objects`,
);
}
const parsedResult = rssSchema
@ -151,11 +151,11 @@ export function pagesGlobToRssItems(items: GlobResult): Promise<ValidatedRSSFeed
[
`[RSS] ${filePath} has invalid or missing frontmatter.\nFix the following properties:`,
...parsedResult.error.errors.map((zodError) => zodError.message),
].join('\n')
].join('\n'),
);
(formattedError as any).file = filePath;
throw formattedError;
})
}),
);
}
@ -207,7 +207,7 @@ async function generateRSS(rssOptions: ValidatedRSSOptions): Promise<string> {
if (typeof rssOptions.customData === 'string')
Object.assign(
root.rss.channel,
parser.parse(`<channel>${rssOptions.customData}</channel>`).channel
parser.parse(`<channel>${rssOptions.customData}</channel>`).channel,
);
// items
root.rss.channel.item = items.map((result) => {
@ -250,7 +250,7 @@ async function generateRSS(rssOptions: ValidatedRSSOptions): Promise<string> {
}
if (result.source) {
item.source = parser.parse(
`<source url="${result.source.url}">${result.source.title}</source>`
`<source url="${result.source.url}">${result.source.title}</source>`,
).source;
}
if (result.enclosure) {
@ -258,7 +258,7 @@ async function generateRSS(rssOptions: ValidatedRSSOptions): Promise<string> {
? result.enclosure.url
: createCanonicalURL(result.enclosure.url, rssOptions.trailingSlash, site);
item.enclosure = parser.parse(
`<enclosure url="${enclosureURL}" length="${result.enclosure.length}" type="${result.enclosure.type}"/>`
`<enclosure url="${enclosureURL}" length="${result.enclosure.length}" type="${result.enclosure.type}"/>`,
).enclosure;
}
return item;

View file

@ -5,7 +5,7 @@ import type { RSSOptions } from './index.js';
export function createCanonicalURL(
url: string,
trailingSlash?: RSSOptions['trailingSlash'],
base?: string
base?: string,
): string {
let pathname = url.replace(/\/index.html$/, ''); // index.html is not canonical
if (!getUrlExtension(url)) {
@ -28,7 +28,7 @@ export function isValidURL(url: string): boolean {
try {
new URL(url);
return true;
} catch (e) {}
} catch {}
return false;
}

View file

@ -16,7 +16,7 @@ describe('pagesGlobToRssItems', () => {
pubDate: phpFeedItem.pubDate,
description: phpFeedItem.description,
},
})
}),
),
'./posts/nested/web1.md': () =>
new Promise((resolve) =>
@ -27,7 +27,7 @@ describe('pagesGlobToRssItems', () => {
pubDate: web1FeedItem.pubDate,
description: web1FeedItem.description,
},
})
}),
),
};
@ -49,7 +49,7 @@ describe('pagesGlobToRssItems', () => {
assert.deepEqual(
items.sort((a, b) => a.pubDate - b.pubDate),
expected
expected,
);
});
@ -63,7 +63,7 @@ describe('pagesGlobToRssItems', () => {
pubDate: phpFeedItem.pubDate,
description: phpFeedItem.description,
},
})
}),
),
};
return assert.rejects(pagesGlobToRssItems(globResult));
@ -80,7 +80,7 @@ describe('pagesGlobToRssItems', () => {
pubDate: phpFeedItem.pubDate,
description: undefined,
},
})
}),
),
};
return assert.rejects(pagesGlobToRssItems(globResult));
@ -97,7 +97,7 @@ describe('pagesGlobToRssItems', () => {
pubDate: phpFeedItem.pubDate,
description: phpFeedItem.description,
},
})
}),
),
};
return assert.doesNotReject(pagesGlobToRssItems(globResult));
@ -114,7 +114,7 @@ describe('pagesGlobToRssItems', () => {
pubDate: phpFeedItem.pubDate,
description: undefined,
},
})
}),
),
};
return assert.doesNotReject(pagesGlobToRssItems(globResult));

View file

@ -191,7 +191,7 @@ describe('getRssString', () => {
pubDate: phpFeedItem.pubDate,
description: phpFeedItem.description,
},
})
}),
),
'./posts/nested/web1.md': () =>
new Promise((resolve) =>
@ -202,7 +202,7 @@ describe('getRssString', () => {
pubDate: web1FeedItem.pubDate,
description: web1FeedItem.description,
},
})
}),
),
};

View file

@ -1,5 +1,55 @@
# astro
## 4.13.3
### Patch Changes
- [#11653](https://github.com/withastro/astro/pull/11653) [`32be549`](https://github.com/withastro/astro/commit/32be5494f6d33dbe32208704405162c95a64f0bc) Thanks [@florian-lefebvre](https://github.com/florian-lefebvre)! - Updates `astro:env` docs to reflect current developments and usage guidance
- [#11658](https://github.com/withastro/astro/pull/11658) [`13b912a`](https://github.com/withastro/astro/commit/13b912a8702afb96e2d0bc20dcc1b4135ae58147) Thanks [@bholmesdev](https://github.com/bholmesdev)! - Fixes `orThrow()` type when calling an Action without an `input` validator.
- [#11603](https://github.com/withastro/astro/pull/11603) [`f31d466`](https://github.com/withastro/astro/commit/f31d4665c1cbb0918b9e00ba1431fb6f264025f7) Thanks [@bholmesdev](https://github.com/bholmesdev)! - Improves user experience when render an Action result from a form POST request:
- Removes "Confirm post resubmission?" dialog when refreshing a result.
- Removes the `?_astroAction=NAME` flag when a result is rendered.
Also improves the DX of directing to a new route on success. Actions will now redirect to the route specified in your `action` string on success, and redirect back to the previous page on error. This follows the routing convention of established backend frameworks like Laravel.
For example, say you want to redirect to a `/success` route when `actions.signup` succeeds. You can add `/success` to your `action` string like so:
```astro
<form method="POST" action={'/success' + actions.signup}></form>
```
- On success, Astro will redirect to `/success`.
- On error, Astro will redirect back to the current page.
You can retrieve the action result from either page using the `Astro.getActionResult()` function.
### Note on security
This uses a temporary cookie to forward the action result to the next page. The cookie will be deleted when that page is rendered.
**The action result is not encrypted.** In general, we recommend returning minimal data from an action handler to a) avoid leaking sensitive information, and b) avoid unexpected render issues once the temporary cookie is deleted. For example, a `login` function may return a user's session id to retrieve from your Astro frontmatter, rather than the entire user object.
## 4.13.2
### Patch Changes
- [#11648](https://github.com/withastro/astro/pull/11648) [`589d351`](https://github.com/withastro/astro/commit/589d35158da1a2136387d0ad76609f5c8535c03a) Thanks [@bholmesdev](https://github.com/bholmesdev)! - Fixes unexpected error when refreshing a POST request from a form using Actions.
- [#11600](https://github.com/withastro/astro/pull/11600) [`09ec2ca`](https://github.com/withastro/astro/commit/09ec2cadce01a9a1f9c54ac433f137348907aa56) Thanks [@ArmandPhilippot](https://github.com/ArmandPhilippot)! - Deprecates `getEntryBySlug` and `getDataEntryById` functions exported by `astro:content` in favor of `getEntry`.
- [#11593](https://github.com/withastro/astro/pull/11593) [`81d7150`](https://github.com/withastro/astro/commit/81d7150e02472430eab555dfc4f053738bf99bb6) Thanks [@bholmesdev](https://github.com/bholmesdev)! - Adds support for `Date()`, `Map()`, and `Set()` from action results. See [devalue](https://github.com/Rich-Harris/devalue) for a complete list of supported values.
Also fixes serialization exceptions when deploying Actions with edge middleware on Netlify and Vercel.
- [#11617](https://github.com/withastro/astro/pull/11617) [`196092a`](https://github.com/withastro/astro/commit/196092ae69eb1249206846ddfc162049b03f42b4) Thanks [@abubakriz](https://github.com/abubakriz)! - Fix toolbar audit incorrectly flagging images as above the fold.
- [#11634](https://github.com/withastro/astro/pull/11634) [`2716f52`](https://github.com/withastro/astro/commit/2716f52aae7194439ebb2336849ddd9e8226658a) Thanks [@bholmesdev](https://github.com/bholmesdev)! - Fixes internal server error when calling an Astro Action without arguments on Vercel.
- [#11628](https://github.com/withastro/astro/pull/11628) [`9aaf58c`](https://github.com/withastro/astro/commit/9aaf58c1339b54f2c1394e718a0f6f609f0b6342) Thanks [@madbook](https://github.com/madbook)! - Ensures consistent CSS chunk hashes across different environments
## 4.13.1
### Patch Changes
@ -1127,7 +1177,7 @@
export function Like({ postId }: { postId: string }) {
const [state, action, pending] = useActionState(
experimental_withState(actions.like),
0 // initial likes
0, // initial likes
);
return (
@ -1341,7 +1391,7 @@
{
site: 'https://example.com',
trailingSlash: 'never',
}
},
);
```
@ -1714,7 +1764,7 @@
middleware({
redirectToDefaultLocale: false,
prefixDefaultLocale: true,
})
}),
);
```
@ -1985,7 +2035,7 @@
detail: {
level: 'warning',
},
})
}),
);
```
@ -6675,7 +6725,7 @@
const hydrate = await load();
await hydrate();
},
{ once: true }
{ once: true },
);
};
@ -8970,7 +9020,7 @@
{ darkMode: true },
{
expires: '1 month',
}
},
);
const prefs = Astro.cookies.get<Prefs>('prefs').json();

View file

@ -14,7 +14,6 @@ declare namespace astroHTML.JSX {
export type Children = Child | Child[];
interface ElementChildrenAttribute {
// eslint-disable-next-line @typescript-eslint/ban-types
children: {};
}

View file

@ -52,6 +52,7 @@ async function errorNodeUnsupported() {
Node.js v${process.versions.node} is not supported by Astro!
Please upgrade Node.js to a supported version: "${engines}"\n`);
// eslint-disable-next-line @typescript-eslint/no-require-imports
const ci = typeof require !== 'undefined' ? require('ci-info') : await import('ci-info');
// Special instructions for CI environments, which may have special steps needed.
@ -65,7 +66,7 @@ Please upgrade Node.js to a supported version: "${engines}"\n`);
}
}
console.log(
`${ci.name} CI Environment Detected!\nAdditional steps may be needed to set your Node.js version:`
`${ci.name} CI Environment Detected!\nAdditional steps may be needed to set your Node.js version:`,
);
console.log(`Documentation: https://docs.astro.build/en/guides/deploy/`);
if (CI_INSTRUCTIONS[platform]) {

View file

@ -50,7 +50,7 @@ declare module 'astro:assets' {
* This is functionally equivalent to using the `<Image />` component, as the component calls this function internally.
*/
getImage: (
options: import('./dist/assets/types.js').UnresolvedImageTransform
options: import('./dist/assets/types.js').UnresolvedImageTransform,
) => Promise<import('./dist/assets/types.js').GetImageResult>;
imageConfig: import('./dist/@types/astro.js').AstroConfig['image'];
getConfiguredImageService: typeof import('./dist/assets/index.js').getConfiguredImageService;

View file

@ -53,8 +53,8 @@ const optimizedImages: GetImageResult[] = await Promise.all(
format: format,
widths: props.widths,
densities: props.densities,
})
)
}),
),
);
let resultFallbackFormat = fallbackFormat ?? defaultFallbackFormat;

View file

@ -53,7 +53,7 @@ const { fallback = 'animate' } = Astro.props;
if (supportsViewTransitions || getFallback() !== 'none') {
if (import.meta.env.DEV && window.matchMedia('(prefers-reduced-motion)').matches) {
console.warn(
`[transitions]: all view transition animations, including fallback animation, are disabled as this device has the prefer-reduced-motion setting enabled.`
`[transitions]: all view transition animations, including fallback animation, are disabled as this device has the prefer-reduced-motion setting enabled.`,
);
}
document.addEventListener('click', (ev) => {

View file

@ -17,7 +17,7 @@ export function defineConfig(config: AstroUserConfig): AstroUserConfig;
*/
export function getViteConfig(
config: ViteUserConfig,
inlineAstroConfig?: AstroInlineConfig
inlineAstroConfig?: AstroInlineConfig,
): ViteUserConfigFn;
/**

View file

@ -20,25 +20,25 @@ test.describe('Astro component HMR', () => {
const hero = page.locator('section');
await expect(hero, 'hero has background: white').toHaveCSS(
'background-color',
'rgb(255, 255, 255)'
'rgb(255, 255, 255)',
);
await expect(hero, 'hero has color: black').toHaveCSS('color', 'rgb(0, 0, 0)');
// Edit the Hero component with a new background color
await astro.editFile('./src/components/Hero.astro', (content) =>
content.replace('background: white', 'background: rgb(230, 230, 230)')
content.replace('background: white', 'background: rgb(230, 230, 230)'),
);
await expect(hero, 'background color updated').toHaveCSS(
'background-color',
'rgb(230, 230, 230)'
'rgb(230, 230, 230)',
);
});
test('hoisted scripts', async ({ page, astro }) => {
const initialLog = page.waitForEvent(
'console',
(message) => message.text() === 'Hello, Astro!'
(message) => message.text() === 'Hello, Astro!',
);
await page.goto(astro.resolveUrl('/'));
@ -49,12 +49,12 @@ test.describe('Astro component HMR', () => {
const updatedLog = page.waitForEvent(
'console',
(message) => message.text() === 'Hello, updated Astro!'
(message) => message.text() === 'Hello, updated Astro!',
);
// Edit the hoisted script on the page
await astro.editFile('./src/pages/index.astro', (content) =>
content.replace('Hello, Astro!', 'Hello, updated Astro!')
content.replace('Hello, Astro!', 'Hello, updated Astro!'),
);
await updatedLog;
@ -63,7 +63,7 @@ test.describe('Astro component HMR', () => {
test('inline scripts', async ({ page, astro }) => {
const initialLog = page.waitForEvent(
'console',
(message) => message.text() === 'Hello, inline Astro!'
(message) => message.text() === 'Hello, inline Astro!',
);
await page.goto(astro.resolveUrl('/'));
@ -71,12 +71,12 @@ test.describe('Astro component HMR', () => {
const updatedLog = page.waitForEvent(
'console',
(message) => message.text() === 'Hello, updated inline Astro!'
(message) => message.text() === 'Hello, updated inline Astro!',
);
// Edit the inline script on the page
await astro.editFile('./src/pages/index.astro', (content) =>
content.replace('Hello, inline Astro!', 'Hello, updated inline Astro!')
content.replace('Hello, inline Astro!', 'Hello, updated inline Astro!'),
);
await updatedLog;
@ -89,7 +89,7 @@ test.describe('Astro component HMR', () => {
await Promise.all([
page.waitForLoadState('networkidle'),
await astro.editFile('../_deps/astro-linked-lib/Component.astro', (content) =>
content.replace('>astro-linked-lib<', '>astro-linked-lib-update<')
content.replace('>astro-linked-lib<', '>astro-linked-lib-update<'),
),
]);
h1 = page.locator('#astro-linked-lib');
@ -103,7 +103,7 @@ test.describe('Astro component HMR', () => {
await Promise.all([
page.waitForLoadState('networkidle'),
await astro.editFile('../_deps/astro-linked-lib/Component.astro', (content) =>
content.replace('color: red', 'color: green')
content.replace('color: red', 'color: green'),
),
]);
h1 = page.locator('#astro-linked-lib');

View file

@ -35,7 +35,7 @@ test.describe('Astro Environment BASE_URL', () => {
const clientComponentBaseUrl = page.locator('id=client-component-base-url');
await expect(clientComponentBaseUrl, 'clientComponentBaseUrl equals to /blog').toHaveText(
'/blog'
'/blog',
);
});
});

View file

@ -19,7 +19,7 @@ test.describe('Content Collections', () => {
await page.goto(astro.resolveUrl('/'));
await astro.editFile('./src/components/MyComponent.astro', (original) =>
original.replace('red', 'green')
original.replace('red', 'green'),
);
const h1 = page.locator('#my-heading');

View file

@ -26,7 +26,7 @@ test.describe('CSS HMR', () => {
await expect(h).toHaveCSS('color', 'rgb(255, 0, 0)');
await astro.editFile('./src/styles/main.css', (original) =>
original.replace('--h1-color: red;', '--h1-color: green;')
original.replace('--h1-color: red;', '--h1-color: green;'),
);
await expect(h).toHaveCSS('color', 'rgb(0, 128, 0)');

View file

@ -98,7 +98,7 @@ function testClientDirectivesShared() {
const clientOptions = page.locator('#options');
await expect(clientOptions).toHaveText(
'Passed options are: {"message":"Hello! I was passed as an option"}'
'Passed options are: {"message":"Hello! I was passed as an option"}',
);
});
}

View file

@ -79,7 +79,7 @@ test.describe('Dev Toolbar - Audits', () => {
'astro:dev-toolbar:settings',
JSON.stringify({
verbose: true,
})
}),
);
});
@ -93,7 +93,7 @@ test.describe('Dev Toolbar - Audits', () => {
const badButton = page.locator('#bad-button');
let consolePromise = page.waitForEvent('console', (msg) =>
msg.text().includes('Rerunning audit lints')
msg.text().includes('Rerunning audit lints'),
);
await badButton.click({ clickCount: 5 });
await consolePromise;
@ -102,7 +102,7 @@ test.describe('Dev Toolbar - Audits', () => {
expect(
logs.filter((log) => log.includes('Rerunning audit lints because the DOM has been updated'))
.length === 1
.length === 1,
).toBe(true);
});
@ -114,7 +114,7 @@ test.describe('Dev Toolbar - Audits', () => {
'astro:dev-toolbar:settings',
JSON.stringify({
verbose: true,
})
}),
);
});
@ -153,7 +153,7 @@ test.describe('Dev Toolbar - Audits', () => {
// Make sure we only reran audits once
expect(
logs.filter((log) => log.includes('Rerunning audit lints because the DOM has been updated'))
.length === 1
.length === 1,
).toBe(true);
});

View file

@ -42,7 +42,7 @@ test.describe('Dev Toolbar', () => {
await appButton.click();
const astroAppCanvas = toolbar.locator(
'astro-dev-toolbar-app-canvas[data-app-id="astro:home"]'
'astro-dev-toolbar-app-canvas[data-app-id="astro:home"]',
);
const astroWindow = astroAppCanvas.locator('astro-dev-toolbar-window');
await expect(astroWindow).toHaveCount(1);
@ -152,7 +152,7 @@ test.describe('Dev Toolbar', () => {
const code = xrayHighlightTooltip.locator('pre > code');
await expect(code).toHaveText(
JSON.stringify({ name: `<img src='' onerror='alert(1)'>` }, undefined, 2)
JSON.stringify({ name: `<img src='' onerror='alert(1)'>` }, undefined, 2),
);
expect(isAlertCalled).toBe(false);
});
@ -264,7 +264,7 @@ test.describe('Dev Toolbar', () => {
await appButton.click();
const settingsAppCanvas = toolbar.locator(
'astro-dev-toolbar-app-canvas[data-app-id="astro:settings"]'
'astro-dev-toolbar-app-canvas[data-app-id="astro:settings"]',
);
const settingsWindow = settingsAppCanvas.locator('astro-dev-toolbar-window');
await expect(settingsWindow).toHaveCount(1);
@ -283,7 +283,7 @@ test.describe('Dev Toolbar', () => {
await appButton.click();
const settingsAppCanvas = toolbar.locator(
'astro-dev-toolbar-app-canvas[data-app-id="astro:settings"]'
'astro-dev-toolbar-app-canvas[data-app-id="astro:settings"]',
);
const settingsWindow = settingsAppCanvas.locator('astro-dev-toolbar-window');
await expect(settingsWindow).toHaveCount(1);
@ -294,7 +294,7 @@ test.describe('Dev Toolbar', () => {
await appButton.click();
const astroAppCanvas = toolbar.locator(
'astro-dev-toolbar-app-canvas[data-app-id="astro:home"]'
'astro-dev-toolbar-app-canvas[data-app-id="astro:home"]',
);
const astroWindow = astroAppCanvas.locator('astro-dev-toolbar-window');
await expect(astroWindow).toHaveCount(1);
@ -311,7 +311,7 @@ test.describe('Dev Toolbar', () => {
await appButton.click();
const settingsAppCanvas = toolbar.locator(
'astro-dev-toolbar-app-canvas[data-app-id="astro:settings"]'
'astro-dev-toolbar-app-canvas[data-app-id="astro:settings"]',
);
const settingsWindow = settingsAppCanvas.locator('astro-dev-toolbar-window');
await expect(settingsWindow).toHaveCount(1);
@ -389,7 +389,7 @@ test.describe('Dev Toolbar', () => {
await settingsAppButton.click();
const settingsAppCanvas = toolbar.locator(
'astro-dev-toolbar-app-canvas[data-app-id="astro:settings"]'
'astro-dev-toolbar-app-canvas[data-app-id="astro:settings"]',
);
const settingsWindow = settingsAppCanvas.locator('astro-dev-toolbar-window');
await expect(settingsWindow).toBeVisible();
@ -423,7 +423,7 @@ test.describe('Dev Toolbar', () => {
await settingsAppButton.click();
const settingsAppCanvas = toolbar.locator(
'astro-dev-toolbar-app-canvas[data-app-id="astro:settings"]'
'astro-dev-toolbar-app-canvas[data-app-id="astro:settings"]',
);
const settingsWindow = settingsAppCanvas.locator('astro-dev-toolbar-window');
await expect(settingsWindow).toBeVisible();

View file

@ -33,7 +33,7 @@ test.describe('Error display', () => {
// Edit the component file
await astro.editFile(
'./src/pages/astro-syntax-error.astro',
() => `<h1>No syntax error</h1>`
() => `<h1>No syntax error</h1>`,
),
]);
@ -67,15 +67,18 @@ test.describe('Error display', () => {
expect(fileLocation).toMatch(/^pages\/import-not-found\.astro/);
});
// NOTE: It's not possible to detect some JSX components if they have errors because
// their renderers' check functions run the render directly, and if a runtime error is
// thrown, it assumes that it's simply not that renderer's component and skips it
test('shows correct file path when a component has an error', async ({ page, astro }) => {
await page.goto(astro.resolveUrl('/preact-runtime-error'), { waitUntil: 'networkidle' });
await page.goto(astro.resolveUrl('/vue-runtime-error'), { waitUntil: 'networkidle' });
const { fileLocation, absoluteFileLocation } = await getErrorOverlayContent(page);
const absoluteFileUrl = 'file://' + absoluteFileLocation.replace(/:\d+:\d+$/, '');
const fileExists = astro.pathExists(absoluteFileUrl);
expect(fileExists).toBeTruthy();
expect(fileLocation).toMatch(/^preact\/PreactRuntimeError.jsx/);
expect(fileLocation).toMatch(/^vue\/VueRuntimeError.vue/);
});
test('shows correct line when a style preprocess has an error', async ({ page, astro }) => {
@ -88,7 +91,7 @@ test.describe('Error display', () => {
expect(fileExists).toBeTruthy();
const fileContent = await astro.readFile(absoluteFileUrl);
const lineNumber = absoluteFileLocation.match(/:(\d+):\d+$/)[1];
const lineNumber = /:(\d+):\d+$/.exec(absoluteFileLocation)[1];
const highlightedLine = fileContent.split('\n')[lineNumber - 1];
expect(highlightedLine).toContain(`@use '../styles/inexistent' as *;`);
@ -107,7 +110,7 @@ test.describe('Error display', () => {
// Edit the component file
astro.editFile(
'./src/components/svelte/SvelteSyntaxError.svelte',
() => `<h1>No mismatch</h1>`
() => `<h1>No mismatch</h1>`,
),
]);

View file

@ -34,7 +34,7 @@ test.describe('Scripts with dependencies', () => {
await expect(h, 'original text set').toHaveText('before');
await astro.editFile('./src/scripts/heading.js', (original) =>
original.replace('before', 'after')
original.replace('before', 'after'),
);
await expect(h, 'text changed').toHaveText('after');
@ -64,7 +64,7 @@ test.describe('Styles', () => {
await expect(h).toHaveCSS('color', 'rgb(0, 0, 255)');
await astro.editFile('./src/styles/css-external.css', (original) =>
original.replace('blue', 'red')
original.replace('blue', 'red'),
);
await expect(h).toHaveCSS('color', 'rgb(255, 0, 0)');

View file

@ -118,13 +118,13 @@ test.describe('Lit components', () => {
// Light DOM reconstructed correctly (slots are rendered alphabetically) and shadow dom content rendered
await expect(label, 'slotted text is in DOM').toHaveText(
'Framework client:only component Should not be visible Shadow dom default content should not be visible'
'Framework client:only component Should not be visible Shadow dom default content should not be visible',
);
// Projected content should be visible
await expect(
page.locator('#client-only .default'),
'slotted element is visible'
'slotted element is visible',
).toBeVisible();
await expect(page.locator('#client-only .foo1'), 'slotted element is visible').toBeVisible();
await expect(page.locator('#client-only .foo2'), 'slotted element is visible').toBeVisible();
@ -132,13 +132,13 @@ test.describe('Lit components', () => {
// Non-projected content should not be visible
await expect(
page.locator('#client-only [slot="quux"]'),
'element without slot is not visible'
'element without slot is not visible',
).toBeHidden();
// Default slot content should not be visible
await expect(
page.locator('#client-only .defaultContent'),
'element without slot is not visible'
'element without slot is not visible',
).toBeHidden();
});
@ -149,7 +149,7 @@ test.describe('Lit components', () => {
const label = counter.locator('h1');
await astro.editFile('./src/pages/index.astro', (original) =>
original.replace('Hello, client:idle!', 'Hello, updated client:idle!')
original.replace('Hello, client:idle!', 'Hello, updated client:idle!'),
);
await expect(label, 'slot text updated').toHaveText('Hello, updated client:idle!');

View file

@ -109,7 +109,7 @@ test.skip('Multiple frameworks', () => {
await expect(slot, 'initial slot content').toHaveText('Hello Preact!');
await astro.editFile('./src/pages/index.astro', (content) =>
content.replace('Hello Preact!', 'Hello Preact, updated!')
content.replace('Hello Preact!', 'Hello Preact, updated!'),
);
await expect(slot, 'slot content updated').toHaveText('Hello Preact, updated!');
@ -122,7 +122,7 @@ test.skip('Multiple frameworks', () => {
await expect(count, 'initial count updated to 0').toHaveText('0');
await astro.editFile('./src/components/ReactCounter.jsx', (content) =>
content.replace('useState(0)', 'useState(5)')
content.replace('useState(0)', 'useState(5)'),
);
await expect(count, 'initial count updated to 5').toHaveText('5');
@ -135,7 +135,7 @@ test.skip('Multiple frameworks', () => {
await expect(count, 'initial count updated to 0').toHaveText('0');
await astro.editFile('./src/components/PreactCounter.tsx', (content) =>
content.replace('useState(0)', 'useState(5)')
content.replace('useState(0)', 'useState(5)'),
);
await expect(count, 'initial count updated to 5').toHaveText('5');
@ -148,7 +148,7 @@ test.skip('Multiple frameworks', () => {
await expect(count, 'initial count updated to 0').toHaveText('0');
await astro.editFile('./src/components/SolidCounter.tsx', (content) =>
content.replace('createSignal(0)', 'createSignal(5)')
content.replace('createSignal(0)', 'createSignal(5)'),
);
await expect(count, 'initial count updated to 5').toHaveText('5');
@ -161,7 +161,7 @@ test.skip('Multiple frameworks', () => {
await expect(count, 'initial count updated to 0').toHaveText('0');
await astro.editFile('./src/components/VueCounter.vue', (content) =>
content.replace('ref(0)', 'ref(5)')
content.replace('ref(0)', 'ref(5)'),
);
await expect(count, 'initial count updated to 5').toHaveText('5');
@ -174,7 +174,7 @@ test.skip('Multiple frameworks', () => {
await expect(count, 'initial count is 0').toHaveText('0');
await astro.editFile('./src/components/SvelteCounter.svelte', (content) =>
content.replace('let count = 0;', 'let count = 5;')
content.replace('let count = 0;', 'let count = 5;'),
);
await expect(count, 'initial count updated to 5').toHaveText('5');

View file

@ -34,7 +34,7 @@ test.describe('Loading styles that are nested', () => {
await expect(header, 'should have background color').toHaveCSS(
'background-color',
'rgb(0, 0, 139)' // darkblue
'rgb(0, 0, 139)', // darkblue
);
});
});

View file

@ -40,7 +40,7 @@ async function expectUrlPrefetched(url, page, count) {
const fetchCount = reqUrls.filter((u) => u.includes(url)).length;
expect(
fetchCount,
`${url} should be prefetched ${count} time(s), but is prefetch with link ${linkCount} time(s) and with fetch ${fetchCount} time(s)`
`${url} should be prefetched ${count} time(s), but is prefetch with link ${linkCount} time(s) and with fetch ${fetchCount} time(s)`,
).toEqual(count);
}
}
@ -344,7 +344,7 @@ test.describe('Prefetch (default), Experimental ({ clientPrerender: true })', ()
expect(await scriptIsInHead(page, '?search-param=true')).toBeFalsy();
await page.locator('#prefetch-search-param').hover();
await page.waitForFunction(
() => document.querySelectorAll('script[type=speculationrules]').length === 2
() => document.querySelectorAll('script[type=speculationrules]').length === 2,
);
expect(await scriptIsInHead(page, '?search-param=true')).toBeTruthy();
});
@ -361,7 +361,7 @@ test.describe('Prefetch (default), Experimental ({ clientPrerender: true })', ()
expect(await scriptIsInHead(page, '/prefetch-hover')).toBeFalsy();
await page.locator('#prefetch-hover').hover();
await page.waitForFunction(
() => document.querySelectorAll('script[type=speculationrules]').length === 2
() => document.querySelectorAll('script[type=speculationrules]').length === 2,
);
expect(await scriptIsInHead(page, '/prefetch-hover')).toBeTruthy();
});
@ -372,7 +372,7 @@ test.describe('Prefetch (default), Experimental ({ clientPrerender: true })', ()
// Scroll down to show the element
await page.locator('#prefetch-viewport').scrollIntoViewIfNeeded();
await page.waitForFunction(
() => document.querySelectorAll('script[type=speculationrules]').length === 2
() => document.querySelectorAll('script[type=speculationrules]').length === 2,
);
expect(await scriptIsInHead(page, '/prefetch-viewport')).toBeTruthy();
});

View file

@ -134,7 +134,7 @@ export function prepareTestFactory(opts, { canReplayClicks = false } = {}) {
// Edit the component's initial count prop
await astro.editFile(pageSourceFilePath, (original) =>
original.replace('id="client-idle" {...someProps}', 'id="client-idle" count={5}')
original.replace('id="client-idle" {...someProps}', 'id="client-idle" count={5}'),
);
await expect(count, 'count prop updated').toHaveText('5', { timeout: 10000 });
@ -144,19 +144,19 @@ export function prepareTestFactory(opts, { canReplayClicks = false } = {}) {
await astro.editFile(componentFilePath, (original) =>
original.replace(
'Framework client:only component',
'Updated framework client:only component'
)
'Updated framework client:only component',
),
);
const label = page.locator('#client-only');
await expect(label, 'client:only component is visible').toBeVisible();
await expect(label, 'client:only slot text is visible').toHaveText(
'Updated framework client:only component'
'Updated framework client:only component',
);
// Edit the imported CSS file
await astro.editFile(counterCssFilePath || './src/components/Counter.css', (original) =>
original.replace('font-size: 2em;', 'font-size: 24px;')
original.replace('font-size: 2em;', 'font-size: 24px;'),
);
await expect(count, 'imported CSS updated').toHaveCSS('font-size', '24px');

View file

@ -4,7 +4,7 @@ const { test, createTests } = prepareTestFactory(
{ root: './fixtures/solid-component/' },
{
canReplayClicks: true,
}
},
);
const config = {

View file

@ -23,7 +23,7 @@ test.describe('Tailwind CSS', () => {
await expect(body, 'should have classes').toHaveClass('bg-dawn text-midnight');
await expect(body, 'should have background color').toHaveCSS(
'background-color',
'rgb(243, 233, 250)'
'rgb(243, 233, 250)',
);
await expect(body, 'should have color').toHaveCSS('color', 'rgb(49, 39, 74)');
});
@ -37,13 +37,13 @@ test.describe('Tailwind CSS', () => {
await expect(button, 'should have appearance: none').toHaveCSS('appearance', 'none');
await expect(button, 'should have appearance-none with webkit prefix').toHaveCSS(
'-webkit-appearance',
'none'
'none',
);
await expect(button, 'should have bg-purple-600').toHaveClass(/bg-purple-600/);
await expect(button, 'should have background color').toHaveCSS(
'background-color',
'rgb(147, 51, 234)'
'rgb(147, 51, 234)',
);
await expect(button, 'should have lg:py-3').toHaveClass(/lg:py-3/);
@ -58,7 +58,7 @@ test.describe('Tailwind CSS', () => {
await page.goto(astro.resolveUrl('/'));
await astro.editFile('./src/components/Button.astro', (original) =>
original.replace('bg-purple-600', 'bg-purple-400')
original.replace('bg-purple-600', 'bg-purple-400'),
);
const button = page.locator('button');
@ -66,7 +66,7 @@ test.describe('Tailwind CSS', () => {
await expect(button, 'should have bg-purple-400').toHaveClass(/bg-purple-400/);
await expect(button, 'should have background color').toHaveCSS(
'background-color',
'rgb(192, 132, 252)'
'rgb(192, 132, 252)',
);
});
});

View file

@ -84,7 +84,7 @@ export async function waitForHydrate(page, el) {
const astroIslandId = await astroIsland.last().getAttribute('uid');
await page.waitForFunction(
(selector) => document.querySelector(selector)?.hasAttribute('ssr') === false,
`astro-island[uid="${astroIslandId}"]`
`astro-island[uid="${astroIslandId}"]`,
);
}

View file

@ -35,7 +35,7 @@ function collectPreloads(page) {
mutations.forEach((mutation) =>
mutation.addedNodes.forEach((node) => {
if (node.nodeName === 'LINK' && node.rel === 'preload') preloads.push(node.href);
})
}),
);
});
observer.observe(document.head, { childList: true });
@ -132,7 +132,7 @@ test.describe('View Transitions', () => {
expect(
loads.length,
'There should be 2 page loads. The original, then going from 3 to 2'
'There should be 2 page loads. The original, then going from 3 to 2',
).toEqual(2);
});
@ -163,7 +163,7 @@ test.describe('View Transitions', () => {
expect(
loads.length,
'There should be only 2 page loads (for page one & three), but no additional loads for the hash change'
'There should be only 2 page loads (for page one & three), but no additional loads for the hash change',
).toEqual(2);
});
@ -185,7 +185,7 @@ test.describe('View Transitions', () => {
await expect(p, 'should have content').toHaveText('Page 1');
expect(
loads.length,
'There should be 3 page loads (for page one & three), and an additional loads for the back navigation'
'There should be 3 page loads (for page one & three), and an additional loads for the back navigation',
).toEqual(3);
});
@ -628,7 +628,7 @@ test.describe('View Transitions', () => {
expect(
loads.length,
'There should be only 1 page load. No additional loads for going back on same page'
'There should be only 1 page load. No additional loads for going back on same page',
).toEqual(1);
});
@ -770,7 +770,7 @@ test.describe('View Transitions', () => {
expect(
loads.length,
'There should only be the initial page load and two normal transitions'
'There should only be the initial page load and two normal transitions',
).toEqual(1);
});
@ -1030,7 +1030,7 @@ test.describe('View Transitions', () => {
expect(
loads.length,
'There should be only 1 page load. No additional loads for the form submission'
'There should be only 1 page load. No additional loads for the form submission',
).toEqual(1);
});
@ -1056,7 +1056,7 @@ test.describe('View Transitions', () => {
expect(
loads.length,
'There should be only 1 page load. No additional loads for the form submission'
'There should be only 1 page load. No additional loads for the form submission',
).toEqual(1);
});
@ -1075,7 +1075,7 @@ test.describe('View Transitions', () => {
expect(
loads.length,
'There should be only 1 page load. No additional loads for the form submission'
'There should be only 1 page load. No additional loads for the form submission',
).toEqual(1);
});
@ -1104,12 +1104,12 @@ test.describe('View Transitions', () => {
expect(
loads.length,
'There should be only 1 page load. No additional loads for the form submission'
'There should be only 1 page load. No additional loads for the form submission',
).toEqual(1);
expect(
postedEncodings,
'There should be 1 POST, with encoding set to `multipart/form-data`'
'There should be 1 POST, with encoding set to `multipart/form-data`',
).toEqual(['multipart/form-data']);
});
@ -1130,8 +1130,8 @@ test.describe('View Transitions', () => {
await page.goto(
astro.resolveUrl(
`/form-one?${new URLSearchParams({ enctype: 'application/x-www-form-urlencoded' })}`
)
`/form-one?${new URLSearchParams({ enctype: 'application/x-www-form-urlencoded' })}`,
),
);
// Submit the form
@ -1139,12 +1139,12 @@ test.describe('View Transitions', () => {
expect(
loads.length,
'There should be only 1 page load. No additional loads for the form submission'
'There should be only 1 page load. No additional loads for the form submission',
).toEqual(1);
expect(
postedEncodings,
'There should be 1 POST, with encoding set to `multipart/form-data`'
'There should be 1 POST, with encoding set to `multipart/form-data`',
).toEqual(['application/x-www-form-urlencoded']);
});
@ -1216,7 +1216,7 @@ test.describe('View Transitions', () => {
expect(
loads.length,
'There should be only 1 page load. No additional loads for the form submission'
'There should be only 1 page load. No additional loads for the form submission',
).toEqual(1);
});
@ -1333,7 +1333,7 @@ test.describe('View Transitions', () => {
expectedAnimations.add(name);
expect(page.locator(selector), 'should be escaped correctly').toHaveCSS(
'view-transition-name',
name
name,
);
};
@ -1361,36 +1361,36 @@ test.describe('View Transitions', () => {
await checkName('#thirteen', '___01____02______');
await checkName(
'#batch0',
'__00_01_02_03_04_05_06_07_08_09_0a_0b_0c_0d_0e_0f_10_11_12_13_14_15_16_17_18_19_1a_1b_1c_1d_1e_1f'
'__00_01_02_03_04_05_06_07_08_09_0a_0b_0c_0d_0e_0f_10_11_12_13_14_15_16_17_18_19_1a_1b_1c_1d_1e_1f',
);
await checkName(
'#batch1',
'__20_21_22_23_24_25_26_27_28_29_2a_2b_2c-_2e_2f0123456789_3a_3b_3c_3d_3e_3f'
'__20_21_22_23_24_25_26_27_28_29_2a_2b_2c-_2e_2f0123456789_3a_3b_3c_3d_3e_3f',
);
await checkName('#batch2', '__40ABCDEFGHIJKLMNOPQRSTUVWXYZ_5b_5c_5d_5e__');
await checkName('#batch3', '__60abcdefghijklmnopqrstuvwxyz_7b_7c_7d_7e_7f');
await checkName(
'#batch4',
'\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f'
'\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f',
);
await checkName(
'#batch5',
'\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf'
'\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf',
);
await checkName(
'#batch6',
'\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf'
'\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf',
);
await checkName(
'#batch7',
'\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff'
'\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff',
);
await page.click('#navigate');
await page.waitForTimeout(400); // yes, I dislike this, too. Might fix later.
expect(
expectedAnimations.size,
'all animations for transition:names should have been found'
'all animations for transition:names should have been found',
).toEqual(0);
});
@ -1425,7 +1425,7 @@ test.describe('View Transitions', () => {
const attributeValue = await page.$eval(
':root',
(element, attributeName) => element.getAttribute(attributeName),
'data-theme'
'data-theme',
);
expect(attributeValue).toBe('purple');
});

View file

@ -47,7 +47,7 @@ test('hmr works', async ({ page, astro }) => {
await expect(span).toHaveText('Count is 1');
await astro.editFile('./src/components/State.vue', (content) =>
content.replace('ref(1)', 'ref(2)')
content.replace('ref(1)', 'ref(2)'),
);
await expect(span).toHaveText('Count is 2');

View file

@ -1,6 +1,6 @@
{
"name": "astro",
"version": "4.13.1",
"version": "4.13.3",
"description": "Astro is a modern site builder with web best practices, performance, and DX front-of-mind.",
"type": "module",
"author": "withastro",
@ -83,9 +83,6 @@
},
"./virtual-modules/*": "./dist/virtual-modules/*"
},
"imports": {
"#astro/*": "./dist/*.js"
},
"bin": {
"astro": "astro.js"
},

View file

@ -74,8 +74,8 @@ async function benchmark({ fixtures, templates, numPosts }) {
const fixtures = formats.filter((format) => format !== 'md');
console.log(
`\n${bold('With Astro components')} ${dim(
`${numPosts} posts (${formatsToString(fixtures)})`
)}`
`${numPosts} posts (${formatsToString(fixtures)})`,
)}`,
);
process.env.ASTRO_PERFORMANCE_TEST_NAME = 'with-astro-components';
await benchmark({
@ -92,8 +92,8 @@ async function benchmark({ fixtures, templates, numPosts }) {
const fixtures = formats.filter((format) => format !== 'md');
console.log(
`\n${bold('With React components')} ${dim(
`${numPosts} posts (${formatsToString(fixtures)})`
)}`
`${numPosts} posts (${formatsToString(fixtures)})`,
)}`,
);
process.env.ASTRO_PERFORMANCE_TEST_NAME = 'with-react-components';
await benchmark({

View file

@ -23,8 +23,8 @@ export async function generatePosts({
Array.from(Array(numPosts).keys()).map((idx) => {
return fs.promises.writeFile(
`${postsDir}/post-${idx}${ext.startsWith('.') ? ext : `.${ext}`}`,
fs.readFileSync(new URL(`./templates/${template}`, import.meta.url), 'utf8')
fs.readFileSync(new URL(`./templates/${template}`, import.meta.url), 'utf8'),
);
})
}),
);
}

View file

@ -123,7 +123,7 @@ export type TransitionAnimationValue =
| TransitionDirectionalAnimations;
// Allow users to extend this for astro-jsx.d.ts
// eslint-disable-next-line @typescript-eslint/no-empty-interface
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
export interface AstroClientDirectives {}
export interface AstroBuiltinAttributes {
@ -378,7 +378,7 @@ export interface AstroGlobalPartial {
*/
glob(globStr: `${any}.astro`): Promise<AstroInstance[]>;
glob<T extends Record<string, any>>(
globStr: `${any}${MarkdowFileExtension}`
globStr: `${any}${MarkdowFileExtension}`,
): Promise<MarkdownInstance<T>[]>;
glob<T extends Record<string, any>>(globStr: `${any}.mdx`): Promise<MDXInstance<T>[]>;
glob<T extends Record<string, any>>(globStr: string): Promise<T[]>;
@ -459,7 +459,6 @@ export interface ViteUserConfig extends vite.UserConfig {
}
export interface ImageServiceConfig<T extends Record<string, any> = Record<string, any>> {
// eslint-disable-next-line @typescript-eslint/ban-types
entrypoint: 'astro/assets/services/sharp' | 'astro/assets/services/squoosh' | (string & {});
config?: T;
}
@ -1986,25 +1985,29 @@ export interface AstroUserConfig {
* @version 4.10.0
* @description
*
* Enables experimental `astro:env` features .
* Enables experimental `astro:env` features.
*
* The `astro:env` API lets you configure a type-safe schema for your environment variables, and indicate whether they should be available on the server or the client. Import and use your defined variables from the appropriate `/client` or `/server` module:
*
* ```astro
* ---
* import { APP_ID } from "astro:env/client"
* import { API_URL, API_TOKEN, getSecret } from "astro:env/server"
* const NODE_ENV = getSecret("NODE_ENV")
* import { API_URL } from "astro:env/client"
* import { API_SECRET_TOKEN } from "astro:env/server"
*
* const data = await fetch(`${API_URL}/users`, {
* method: "POST",
* method: "GET",
* headers: {
* "Content-Type": "application/json",
* "Authorization": `Bearer ${API_TOKEN}`
* "Authorization": `Bearer ${API_SECRET_TOKEN}`
* },
* body: JSON.stringify({ appId: APP_ID, nodeEnv: NODE_ENV })
* })
* ---
*
* <script>
* import { API_URL } from "astro:env/client"
*
* fetch(`${API_URL}/ping`)
* </script>
* ```
*
* To define the data type and properties of your environment variables, declare a schema in your Astro config in `experimental.env.schema`. The `envField` helper allows you define your variable as a string, number, or boolean and pass properties in an object:
@ -2042,7 +2045,7 @@ export interface AstroUserConfig {
* import { PORT } from "astro:env/server"
* ```
*
* - **Secret server variables**: These variables are not part of your final bundle and can be accessed on the server through the `astro:env/server` module. The `getSecret()` helper function can be used to retrieve secrets not specified in the schema:
* - **Secret server variables**: These variables are not part of your final bundle and can be accessed on the server through the `astro:env/server` module. The `getSecret()` helper function can be used to retrieve secrets not specified in the schema. Its implementation is provided by your adapter and defaults to `process.env`:
*
* ```js
* import { API_SECRET, getSecret } from "astro:env/server"
@ -2301,7 +2304,7 @@ export interface ContentEntryType {
contents: string;
fileUrl: URL;
viteId: string;
}
},
): rollup.LoadResult | Promise<rollup.LoadResult>;
contentModuleTypes?: string;
/**
@ -2386,7 +2389,7 @@ export type AsyncRendererComponentFn<U> = (
Component: any,
props: any,
slots: Record<string, string>,
metadata?: AstroComponentMetadata
metadata?: AstroComponentMetadata,
) => Promise<U>;
/** Generic interface for a component (Astro, Svelte, React, etc.) */
@ -2471,7 +2474,7 @@ export type GetStaticPathsResultKeyed = GetStaticPathsResult & {
* [Astro Reference](https://docs.astro.build/en/reference/api-reference/#getstaticpaths)
*/
export type GetStaticPaths = (
options: GetStaticPathsOptions
options: GetStaticPathsOptions,
) => Promise<GetStaticPathsResult> | GetStaticPathsResult;
/**
@ -2494,7 +2497,7 @@ export type GetStaticPaths = (
* ```
*/
export type InferGetStaticParamsType<T> = T extends (
opts?: GetStaticPathsOptions
opts?: GetStaticPathsOptions,
) => infer R | Promise<infer R>
? R extends Array<infer U>
? U extends { params: infer P }
@ -2527,7 +2530,7 @@ export type InferGetStaticParamsType<T> = T extends (
* ```
*/
export type InferGetStaticPropsType<T> = T extends (
opts: GetStaticPathsOptions
opts: GetStaticPathsOptions,
) => infer R | Promise<infer R>
? R extends Array<infer U>
? U extends { props: infer P }
@ -2640,7 +2643,7 @@ export type PaginateFunction = <
AdditionalPaginateParams extends Params,
>(
data: PaginateData[],
args?: PaginateOptions<AdditionalPaginateProps, AdditionalPaginateParams>
args?: PaginateOptions<AdditionalPaginateProps, AdditionalPaginateParams>,
) => {
params: Simplify<
{
@ -2756,7 +2759,7 @@ interface AstroSharedContext<
TInputSchema extends ActionInputSchema<TAccept>,
TAction extends ActionClient<unknown, TAccept, TInputSchema>,
>(
action: TAction
action: TAction,
) => ActionReturnType<TAction> | undefined;
/**
* Call action handler from the server.
@ -2770,7 +2773,7 @@ interface AstroSharedContext<
| ActionClient<TOutput, TAccept, TInputSchema>['orThrow'],
>(
action: TAction,
input: Parameters<TAction>[0]
input: Parameters<TAction>[0],
) => Promise<ActionReturnType<TAction>>;
/**
* Route parameters for this request if this is a dynamic route.
@ -3143,7 +3146,7 @@ export type RewritePayload = string | URL | Request;
export type MiddlewareNext = (rewritePayload?: RewritePayload) => Promise<Response>;
export type MiddlewareHandler = (
context: APIContext,
next: MiddlewareNext
next: MiddlewareNext,
) => Promise<Response> | Response | Promise<void> | void;
// NOTE: when updating this file with other functions,
@ -3259,7 +3262,7 @@ export interface SSRResult {
createAstro(
Astro: AstroGlobalPartial,
props: Record<string, any>,
slots: Record<string, any> | null
slots: Record<string, any> | null,
): AstroGlobal;
params: Params;
resolve: (s: string) => Promise<string>;
@ -3327,7 +3330,7 @@ export interface PreviewServerParams {
}
export type CreatePreviewServer = (
params: PreviewServerParams
params: PreviewServerParams,
) => PreviewServer | Promise<PreviewServer>;
export interface PreviewModule {
@ -3352,7 +3355,7 @@ type DirectiveOptions = {
export type ClientDirective = (
load: DirectiveLoad,
options: DirectiveOptions,
el: HTMLElement
el: HTMLElement,
) => void;
export interface ClientDirectiveConfig {
@ -3400,7 +3403,7 @@ export type DevToolbarApp = {
init?(
canvas: ShadowRoot,
app: ToolbarAppEventTarget,
server: ToolbarServerHelpers
server: ToolbarServerHelpers,
): void | Promise<void>;
beforeTogglingOff?(canvas: ShadowRoot): boolean | Promise<boolean>;
};
@ -3465,7 +3468,7 @@ declare global {
// Container types
export type ContainerImportRendererFn = (
containerRenderer: ContainerRenderer
containerRenderer: ContainerRenderer,
) => Promise<SSRLoadedRenderer>;
export type ContainerRenderer = {

View file

@ -4,3 +4,9 @@ export const ACTIONS_TYPES_FILE = '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';
export const ACTION_QUERY_PARAMS = {
actionName: '_astroAction',
actionPayload: '_astroActionPayload',
actionRedirect: '_astroActionRedirect',
};

View file

@ -31,7 +31,7 @@ export default function astroActions({
}
const stringifiedActionsImport = JSON.stringify(
viteID(new URL('./actions', params.config.srcDir))
viteID(new URL('./actions', params.config.srcDir)),
);
params.updateConfig({
vite: {
@ -75,7 +75,7 @@ export function vitePluginUserActions({ settings }: { settings: AstroSettings })
}
if (id === VIRTUAL_INTERNAL_MODULE_ID) {
const resolvedModule = await this.resolve(
`${decodeURI(new URL('actions', settings.config.srcDir).pathname)}`
`${decodeURI(new URL('actions', settings.config.srcDir).pathname)}`,
);
if (!resolvedModule) {
@ -109,7 +109,7 @@ const vitePluginActions = (fs: typeof fsMod): VitePlugin => ({
let code = await fs.promises.readFile(
new URL('../../templates/actions.mjs', import.meta.url),
'utf-8'
'utf-8',
);
if (opts?.ssr) {
code += `\nexport * from 'astro/actions/runtime/virtual/server.js';`;

View file

@ -1,11 +1,9 @@
import { yellow } from 'kleur/colors';
import type { APIContext, MiddlewareNext } from '../../@types/astro.js';
import {
ActionQueryStringInvalidError,
ActionsUsedWithForGetError,
} from '../../core/errors/errors-data.js';
import { ActionQueryStringInvalidError } from '../../core/errors/errors-data.js';
import { AstroError } from '../../core/errors/errors.js';
import { defineMiddleware } from '../../core/middleware/index.js';
import { ACTION_QUERY_PARAMS } from '../consts.js';
import { formContentTypes, hasContentType } from './utils.js';
import { getAction } from './virtual/get-action.js';
import {
@ -14,11 +12,13 @@ import {
serializeActionResult,
} from './virtual/shared.js';
export type ActionPayload = {
actionResult: SerializedActionResult;
actionName: string;
};
export type Locals = {
_actionsInternal: {
actionResult: SerializedActionResult;
actionName: string;
};
_actionPayload: ActionPayload;
};
export const onRequest = defineMiddleware(async (context, next) => {
@ -26,32 +26,34 @@ export const onRequest = defineMiddleware(async (context, next) => {
const { request } = context;
// Actions middleware may have run already after a path rewrite.
// See https://github.com/withastro/roadmap/blob/feat/reroute/proposals/0047-rerouting.md#ctxrewrite
// `_actionsInternal` is the same for every page,
// `_actionPayload` is the same for every page,
// so short circuit if already defined.
if (locals._actionsInternal) return next();
if (locals._actionPayload) return next();
const actionPayload = context.cookies.get(ACTION_QUERY_PARAMS.actionPayload)?.json();
if (actionPayload) {
if (!isActionPayload(actionPayload)) {
throw new Error('Internal: Invalid action payload in cookie.');
}
return renderResult({ context, next, ...actionPayload });
}
// Heuristic: If body is null, Astro might've reset this for prerendering.
if (import.meta.env.DEV && request.method === 'POST' && request.body === null) {
// eslint-disable-next-line no-console
console.warn(
yellow('[astro:actions]'),
'POST requests should not be sent to prerendered pages. If you\'re using Actions, disable prerendering with `export const prerender = "false".'
'POST requests should not be sent to prerendered pages. If you\'re using Actions, disable prerendering with `export const prerender = "false".',
);
return next();
}
const actionName = context.url.searchParams.get('_astroAction');
const actionName = context.url.searchParams.get(ACTION_QUERY_PARAMS.actionName);
if (context.request.method === 'POST' && actionName) {
return handlePost({ context, next, actionName });
}
if (context.request.method === 'GET' && actionName) {
throw new AstroError({
...ActionsUsedWithForGetError,
message: ActionsUsedWithForGetError.message(actionName),
});
}
if (context.request.method === 'POST') {
return handlePostLegacy({ context, next });
}
@ -59,6 +61,33 @@ export const onRequest = defineMiddleware(async (context, next) => {
return next();
});
async function renderResult({
context,
next,
actionResult,
actionName,
}: {
context: APIContext;
next: MiddlewareNext;
actionResult: SerializedActionResult;
actionName: string;
}) {
const locals = context.locals as Locals;
locals._actionPayload = { actionResult, actionName };
const response = await next();
context.cookies.delete(ACTION_QUERY_PARAMS.actionPayload);
if (actionResult.type === 'error') {
return new Response(response.body, {
status: actionResult.status,
statusText: actionResult.type,
headers: response.headers,
});
}
return response;
}
async function handlePost({
context,
next,
@ -82,35 +111,42 @@ async function handlePost({
const action = baseAction.bind(context);
const actionResult = await action(formData);
return handleResult({ context, next, actionName, actionResult });
if (context.url.searchParams.get(ACTION_QUERY_PARAMS.actionRedirect) === 'false') {
return renderResult({
context,
next,
actionName,
actionResult: serializeActionResult(actionResult),
});
}
return redirectWithResult({ context, actionName, actionResult });
}
async function handleResult({
async function redirectWithResult({
context,
next,
actionName,
actionResult,
}: {
context: APIContext;
next: MiddlewareNext;
actionName: string;
actionResult: SafeResult<any, any>;
}) {
const locals = context.locals as Locals;
locals._actionsInternal = {
context.cookies.set(ACTION_QUERY_PARAMS.actionPayload, {
actionName,
actionResult: serializeActionResult(actionResult),
};
});
const response = await next();
if (actionResult.error) {
return new Response(response.body, {
status: actionResult.error.status,
statusText: actionResult.error.type,
headers: response.headers,
});
const referer = context.request.headers.get('Referer');
if (!referer) {
throw new Error('Internal: Referer unexpectedly missing from Action POST request.');
}
return context.redirect(referer);
}
return response;
return context.redirect(context.url.pathname);
}
async function handlePostLegacy({ context, next }: { context: APIContext; next: MiddlewareNext }) {
@ -129,7 +165,7 @@ async function handlePostLegacy({ context, next }: { context: APIContext; next:
if (!formData) return next();
const actionName = formData.get('_astroAction') as string;
const actionName = formData.get(ACTION_QUERY_PARAMS.actionName) as string;
if (!actionName) return next();
const baseAction = await getAction(actionName);
@ -142,5 +178,13 @@ async function handlePostLegacy({ context, next }: { context: APIContext; next:
const action = baseAction.bind(context);
const actionResult = await action(formData);
return handleResult({ context, next, actionName, actionResult });
return redirectWithResult({ context, actionName, actionResult });
}
function isActionPayload(json: unknown): json is ActionPayload {
if (typeof json !== 'object' || json == null) return false;
if (!('actionResult' in json) || typeof json.actionResult !== 'object') return false;
if (!('actionName' in json) || typeof json.actionName !== 'string') return false;
return true;
}

View file

@ -12,7 +12,7 @@ export const POST: APIRoute = async (context) => {
const contentType = request.headers.get('Content-Type');
const contentLength = request.headers.get('Content-Length');
let args: unknown;
if (contentLength === '0') {
if (!contentType || contentLength === '0') {
args = undefined;
} else if (contentType && hasContentType(contentType, formContentTypes)) {
args = await request.clone().formData();

View file

@ -10,5 +10,5 @@ export const z = new Proxy(
get() {
throw new Error('[astro:action] `z` unexpectedly used on the client.');
},
}
},
);

View file

@ -7,7 +7,7 @@ import type { ActionAccept, ActionClient } from './server.js';
* the user's `src/actions/index.ts` file at build-time.
*/
export async function getAction(
path: string
path: string,
): Promise<ActionClient<unknown, ActionAccept, ZodType> | undefined> {
const pathKeys = path.replace('/_actions/', '').split('.');
// @ts-expect-error virtual module

View file

@ -25,7 +25,7 @@ export type ActionClient<
TInputSchema extends ActionInputSchema<TAccept> | undefined,
> = TInputSchema extends z.ZodType
? ((
input: TAccept extends 'form' ? FormData : z.input<TInputSchema>
input: TAccept extends 'form' ? FormData : z.input<TInputSchema>,
) => Promise<
SafeResult<
z.input<TInputSchema> extends ErrorInferenceObject
@ -36,10 +36,10 @@ export type ActionClient<
>) & {
queryString: string;
orThrow: (
input: TAccept extends 'form' ? FormData : z.input<TInputSchema>
input: TAccept extends 'form' ? FormData : z.input<TInputSchema>,
) => Promise<Awaited<TOutput>>;
}
: (input?: any) => Promise<SafeResult<never, Awaited<TOutput>>> & {
: ((input?: any) => Promise<SafeResult<never, Awaited<TOutput>>>) & {
orThrow: (input?: any) => Promise<Awaited<TOutput>>;
};
@ -85,7 +85,7 @@ export function defineAction<
function getFormServerHandler<TOutput, TInputSchema extends ActionInputSchema<'form'>>(
handler: ActionHandler<TInputSchema, TOutput>,
inputSchema?: TInputSchema
inputSchema?: TInputSchema,
) {
return async (unparsedInput: unknown, context: ActionAPIContext): Promise<Awaited<TOutput>> => {
if (!(unparsedInput instanceof FormData)) {
@ -107,7 +107,7 @@ function getFormServerHandler<TOutput, TInputSchema extends ActionInputSchema<'f
function getJsonServerHandler<TOutput, TInputSchema extends ActionInputSchema<'json'>>(
handler: ActionHandler<TInputSchema, TOutput>,
inputSchema?: TInputSchema
inputSchema?: TInputSchema,
) {
return async (unparsedInput: unknown, context: ActionAPIContext): Promise<Awaited<TOutput>> => {
if (unparsedInput instanceof FormData) {
@ -129,7 +129,7 @@ function getJsonServerHandler<TOutput, TInputSchema extends ActionInputSchema<'j
/** Transform form data to an object based on a Zod schema. */
export function formDataToObject<T extends z.AnyZodObject>(
formData: FormData,
schema: T
schema: T,
): Record<string, unknown> {
const obj: Record<string, unknown> = {};
for (const [key, baseValidator] of Object.entries(schema.shape)) {
@ -151,7 +151,7 @@ export function formDataToObject<T extends z.AnyZodObject>(
function handleFormDataGetAll(
key: string,
formData: FormData,
validator: z.ZodArray<z.ZodUnknown>
validator: z.ZodArray<z.ZodUnknown>,
) {
const entries = Array.from(formData.getAll(key));
const elementValidator = validator._def.type;
@ -167,7 +167,7 @@ function handleFormDataGet(
key: string,
formData: FormData,
validator: unknown,
baseValidator: unknown
baseValidator: unknown,
) {
const value = formData.get(key);
if (!value) {

View file

@ -1,7 +1,10 @@
import { parse as devalueParse, stringify as devalueStringify } from 'devalue';
import type { z } from 'zod';
import { ACTION_QUERY_PARAMS as _ACTION_QUERY_PARAMS } from '../../consts.js';
import type { ErrorInferenceObject, MaybePromise } from '../utils.js';
export const ACTION_QUERY_PARAMS = _ACTION_QUERY_PARAMS;
export const ACTION_ERROR_CODES = [
'BAD_REQUEST',
'UNAUTHORIZED',
@ -41,7 +44,7 @@ const codeToStatusMap: Record<ActionErrorCode, number> = {
const statusToCodeMap: Record<number, ActionErrorCode> = Object.entries(codeToStatusMap).reduce(
// reverse the key-value pairs
(acc, [key, value]) => ({ ...acc, [value]: key }),
{}
{},
);
// T is used for error inference with SafeInput -> isInputError.
@ -92,11 +95,11 @@ export function isActionError(error?: unknown): error is ActionError {
}
export function isInputError<T extends ErrorInferenceObject>(
error?: ActionError<T>
error?: ActionError<T>,
): error is ActionInputError<T>;
export function isInputError(error?: unknown): error is ActionInputError<ErrorInferenceObject>;
export function isInputError<T extends ErrorInferenceObject>(
error?: unknown | ActionError<T>
error?: unknown | ActionError<T>,
): error is ActionInputError<T> {
return (
typeof error === 'object' &&
@ -146,7 +149,7 @@ export class ActionInputError<T extends ErrorInferenceObject> extends ActionErro
}
export async function callSafely<TOutput>(
handler: () => MaybePromise<TOutput>
handler: () => MaybePromise<TOutput>,
): Promise<SafeResult<z.ZodType, TOutput>> {
try {
const data = await handler();
@ -166,7 +169,7 @@ export async function callSafely<TOutput>(
}
export function getActionQueryString(name: string) {
const searchParams = new URLSearchParams({ _astroAction: name });
const searchParams = new URLSearchParams({ [_ACTION_QUERY_PARAMS.actionName]: name });
return `?${searchParams.toString()}`;
}

View file

@ -3,19 +3,19 @@ import type { Locals } from './runtime/middleware.js';
import { type ActionAPIContext } from './runtime/utils.js';
import { deserializeActionResult, getActionQueryString } from './runtime/virtual/shared.js';
export function hasActionsInternal(locals: APIContext['locals']): locals is Locals {
return '_actionsInternal' in locals;
export function hasActionPayload(locals: APIContext['locals']): locals is Locals {
return '_actionPayload' in locals;
}
export function createGetActionResult(locals: APIContext['locals']): APIContext['getActionResult'] {
return (actionFn): any => {
if (
!hasActionsInternal(locals) ||
actionFn.toString() !== getActionQueryString(locals._actionsInternal.actionName)
!hasActionPayload(locals) ||
actionFn.toString() !== getActionQueryString(locals._actionPayload.actionName)
) {
return undefined;
}
return deserializeActionResult(locals._actionsInternal.actionResult);
return deserializeActionResult(locals._actionPayload.actionResult);
};
}

View file

@ -48,7 +48,7 @@ type ImageData = { data: Uint8Array; expires: number };
export async function prepareAssetsGenerationEnv(
pipeline: BuildPipeline,
totalCount: number
totalCount: number,
): Promise<AssetEnv> {
const { config, logger } = pipeline;
let useCache = true;
@ -61,7 +61,7 @@ export async function prepareAssetsGenerationEnv(
} catch (err) {
logger.warn(
null,
`An error was encountered while creating the cache directory. Proceeding without caching. Error: ${err}`
`An error was encountered while creating the cache directory. Proceeding without caching. Error: ${err}`,
);
useCache = false;
}
@ -96,7 +96,7 @@ export async function generateImagesForPath(
originalFilePath: string,
transformsAndPath: MapValue<AssetsGlobalStaticImagesList>,
env: AssetEnv,
queue: PQueue
queue: PQueue,
) {
const originalImageData = await loadImage(originalFilePath, env);
@ -119,11 +119,11 @@ export async function generateImagesForPath(
if (transformsAndPath.originalSrcPath) {
env.logger.debug(
'assets',
`Deleting ${originalFilePath} as it's not referenced outside of image processing.`
`Deleting ${originalFilePath} as it's not referenced outside of image processing.`,
);
await fs.promises.unlink(getFullImagePath(originalFilePath, env));
}
} catch (e) {
} catch {
/* No-op, it's okay if we fail to delete one of the file, we're not too picky. */
}
}
@ -131,7 +131,7 @@ export async function generateImagesForPath(
async function generateImage(
originalImage: ImageData,
filepath: string,
options: ImageTransform
options: ImageTransform,
) {
const timeStart = performance.now();
const generationData = await generateImageInternal(originalImage, filepath, options);
@ -145,7 +145,7 @@ export async function generateImagesForPath(
const count = `(${env.count.current}/${env.count.total})`;
env.logger.info(
null,
` ${green('▶')} ${filepath} ${dim(statsText)} ${dim(timeIncrease)} ${dim(count)}`
` ${green('▶')} ${filepath} ${dim(statsText)} ${dim(timeIncrease)} ${dim(count)}`,
);
env.count.current++;
}
@ -153,7 +153,7 @@ export async function generateImagesForPath(
async function generateImageInternal(
originalImage: ImageData,
filepath: string,
options: ImageTransform
options: ImageTransform,
): Promise<GenerationData> {
const isLocalImage = isESMImportedImage(options.src);
const finalFileURL = new URL('.' + filepath, env.clientRoot);
@ -177,7 +177,7 @@ export async function generateImagesForPath(
await fs.promises.unlink(cachedFileURL);
throw new Error(
`Malformed cache entry for ${filepath}, cache will be regenerated for this file.`
`Malformed cache entry for ${filepath}, cache will be regenerated for this file.`,
);
}
@ -219,7 +219,7 @@ export async function generateImagesForPath(
await imageService.transform(
originalImage.data,
{ ...options, src: originalImagePath },
env.imageConfig
env.imageConfig,
)
).data;
} catch (e) {
@ -228,7 +228,7 @@ export async function generateImagesForPath(
...AstroErrorData.CouldNotTransformImage,
message: AstroErrorData.CouldNotTransformImage.message(originalFilePath),
},
{ cause: e }
{ cause: e },
);
throw error;
@ -245,14 +245,14 @@ export async function generateImagesForPath(
JSON.stringify({
data: Buffer.from(resultData.data).toString('base64'),
expires: resultData.expires,
})
}),
);
}
}
} catch (e) {
env.logger.warn(
null,
`An error was encountered while creating the cache directory. Proceeding without caching. Error: ${e}`
`An error was encountered while creating the cache directory. Proceeding without caching. Error: ${e}`,
);
} finally {
// Write the final file

View file

@ -8,7 +8,7 @@ export async function loadRemoteImage(src: string) {
if (!res.ok) {
throw new Error(
`Failed to load remote image ${src}. The request did not return a 200 OK response. (received ${res.status}))`
`Failed to load remote image ${src}. The request did not return a 200 OK response. (received ${res.status}))`,
);
}

View file

@ -19,7 +19,7 @@ async function loadRemoteImage(src: URL, headers: Headers) {
}
return await res.arrayBuffer();
} catch (err: unknown) {
} catch {
return undefined;
}
}
@ -60,7 +60,7 @@ export const GET: APIRoute = async ({ request }) => {
const { data, format } = await imageService.transform(
new Uint8Array(inputBuffer),
transform,
imageConfig
imageConfig,
);
return new Response(data, {

View file

@ -30,7 +30,7 @@ async function loadLocalImage(src: string, url: URL) {
if (!isAbsolute(filePath) || !filePath.startsWith(assetsDirPath)) {
return undefined;
}
} catch (err: unknown) {
} catch {
return undefined;
}
}
@ -39,7 +39,7 @@ async function loadLocalImage(src: string, url: URL) {
try {
buffer = await readFile(fileUrl);
} catch (e) {
} catch {
// Fallback to try to load the file using `fetch`
try {
const sourceUrl = new URL(src, url.origin);
@ -62,7 +62,7 @@ async function loadRemoteImage(src: URL) {
}
return Buffer.from(await res.arrayBuffer());
} catch (err: unknown) {
} catch {
return undefined;
}
}
@ -83,7 +83,7 @@ export const GET: APIRoute = async ({ request }) => {
if (!transform?.src) {
const err = new Error(
'Incorrect transform returned by `parseURL`. Expected a transform with a `src` property.'
'Incorrect transform returned by `parseURL`. Expected a transform with a `src` property.',
);
console.error('Could not parse image transform from URL:', err);
return new Response('Internal Server Error', { status: 500 });
@ -122,7 +122,7 @@ export const GET: APIRoute = async ({ request }) => {
import.meta.env.DEV ? `Could not process image request: ${err}` : `Internal Server Error`,
{
status: 500,
}
},
);
}
};

View file

@ -33,7 +33,7 @@ export async function getConfiguredImageService(): Promise<ImageService> {
export async function getImage(
options: UnresolvedImageTransform,
imageConfig: AstroConfig['image']
imageConfig: AstroConfig['image'],
): Promise<GetImageResult> {
if (!options || typeof options !== 'object') {
throw new AstroError({
@ -47,7 +47,7 @@ export async function getImage(
message: AstroErrorData.ExpectedImage.message(
options.src,
'undefined',
JSON.stringify(options)
JSON.stringify(options),
),
});
}
@ -101,7 +101,7 @@ export async function getImage(
url: await service.getURL(srcSet.transform, imageConfig),
descriptor: srcSet.descriptor,
attributes: srcSet.attributes,
}))
})),
);
if (
@ -113,7 +113,7 @@ export async function getImage(
imageURL = globalThis.astroAsset.addStaticImage(
validatedOptions,
propsToHash,
originalFilePath
originalFilePath,
);
srcSets = srcSetTransforms.map((srcSet) => ({
transform: srcSet.transform,

View file

@ -47,7 +47,7 @@ interface SharedServiceProps<T extends Record<string, any> = Record<string, any>
*/
getSrcSet?: (
options: ImageTransform,
imageConfig: ImageConfig<T>
imageConfig: ImageConfig<T>,
) => UnresolvedSrcSetValue[] | Promise<UnresolvedSrcSetValue[]>;
/**
* Return any additional HTML attributes separate from `src` that your service requires to show the image properly.
@ -57,7 +57,7 @@ interface SharedServiceProps<T extends Record<string, any> = Record<string, any>
*/
getHTMLAttributes?: (
options: ImageTransform,
imageConfig: ImageConfig<T>
imageConfig: ImageConfig<T>,
) => Record<string, any> | Promise<Record<string, any>>;
/**
* Validate and return the options passed by the user.
@ -69,7 +69,7 @@ interface SharedServiceProps<T extends Record<string, any> = Record<string, any>
*/
validateOptions?: (
options: ImageTransform,
imageConfig: ImageConfig<T>
imageConfig: ImageConfig<T>,
) => ImageTransform | Promise<ImageTransform>;
}
@ -90,7 +90,7 @@ export interface LocalImageService<T extends Record<string, any> = Record<string
*/
parseURL: (
url: URL,
imageConfig: ImageConfig<T>
imageConfig: ImageConfig<T>,
) => LocalImageTransform | undefined | Promise<LocalImageTransform> | Promise<undefined>;
/**
* Performs the image transformations on the input image and returns both the binary data and
@ -99,7 +99,7 @@ export interface LocalImageService<T extends Record<string, any> = Record<string
transform: (
inputBuffer: Uint8Array,
transform: LocalImageTransform,
imageConfig: ImageConfig<T>
imageConfig: ImageConfig<T>,
) => Promise<{ data: Uint8Array; format: ImageOutputFormat }>;
/**
@ -148,7 +148,7 @@ export const baseService: Omit<LocalImageService, 'transform'> = {
message: AstroErrorData.ExpectedImage.message(
JSON.stringify(options.src),
typeof options.src,
JSON.stringify(options, (_, v) => (v === undefined ? null : v))
JSON.stringify(options, (_, v) => (v === undefined ? null : v)),
),
});
}
@ -188,7 +188,7 @@ export const baseService: Omit<LocalImageService, 'transform'> = {
message: AstroErrorData.UnsupportedImageFormat.message(
options.src.format,
options.src.src,
VALID_SUPPORTED_FORMATS
VALID_SUPPORTED_FORMATS,
),
});
}
@ -281,14 +281,14 @@ export const baseService: Omit<LocalImageService, 'transform'> = {
...densityWidths.map((width, index) => ({
maxTargetWidth: Math.min(width, maxWidth),
descriptor: `${densityValues[index]}x` as const,
}))
})),
);
} else if (widths) {
allWidths.push(
...widths.map((width) => ({
maxTargetWidth: Math.min(width, maxWidth),
descriptor: `${width}w` as const,
}))
})),
);
}

View file

@ -28,7 +28,7 @@ async function loadSharp() {
let sharpImport: typeof import('sharp');
try {
sharpImport = (await import('sharp')).default;
} catch (e) {
} catch {
throw new AstroError(AstroErrorData.MissingSharp);
}

View file

@ -31,7 +31,7 @@ const qualityTable: Record<
async function getRotationForEXIF(
inputBuffer: Uint8Array,
src?: string
src?: string,
): Promise<Operation | undefined> {
const meta = await imageMetadata(inputBuffer, src);
if (!meta) return undefined;

View file

@ -1500,7 +1500,7 @@ var Module = (function () {
wasmMemory.grow((size - buffer.byteLength + 65535) >>> 16)
updateGlobalBufferAndViews(wasmMemory.buffer)
return 1
} catch (e) {}
} catch {}
}
function _emscripten_resize_heap(requestedSize) {
var oldSize = HEAPU8.length

View file

@ -1660,7 +1660,7 @@ var Module = (function () {
wasmMemory.grow((size - buffer.byteLength + 65535) >>> 16)
updateGlobalBufferAndViews(wasmMemory.buffer)
return 1
} catch (e) {}
} catch {}
}
function _emscripten_resize_heap(requestedSize) {
var oldSize = HEAPU8.length

View file

@ -1504,7 +1504,7 @@ var Module = (function () {
wasmMemory.grow((size - buffer.byteLength + 65535) >>> 16)
updateGlobalBufferAndViews(wasmMemory.buffer)
return 1
} catch (e) {}
} catch {}
}
function _emscripten_resize_heap(requestedSize) {
var oldSize = HEAPU8.length

View file

@ -1627,7 +1627,7 @@ var Module = (function () {
wasmMemory.grow((size - buffer.byteLength + 65535) >>> 16)
updateGlobalBufferAndViews(wasmMemory.buffer)
return 1
} catch (e) {}
} catch {}
}
function _emscripten_resize_heap(requestedSize) {
var oldSize = HEAPU8.length

View file

@ -1,4 +1,3 @@
/* tslint-disable ban-types */
import { parentPort, Worker } from 'worker_threads';
function uuid() {

View file

@ -1476,7 +1476,7 @@ var Module = (function () {
wasmMemory.grow((size - buffer.byteLength + 65535) >>> 16)
updateGlobalBufferAndViews(wasmMemory.buffer)
return 1
} catch (e) {}
} catch {}
}
function _emscripten_resize_heap(requestedSize) {
var oldSize = HEAPU8.length

View file

@ -1656,7 +1656,7 @@ var Module = (function () {
wasmMemory.grow((size - buffer.byteLength + 65535) >>> 16)
updateGlobalBufferAndViews(wasmMemory.buffer)
return 1
} catch (e) {}
} catch {}
}
function _emscripten_resize_heap(requestedSize) {
var oldSize = HEAPU8.length

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