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:
commit
7dc0680d60
575 changed files with 2532 additions and 2391 deletions
.changeset
.git-blame-ignore-revsREADME.mdbiome.jsoneslint.config.jsexamples
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
packages
astro-prism
astro-rss
astro
CHANGELOG.mdastro-jsx.d.tsastro.jsclient.d.ts
components
config.d.tse2e
astro-component.test.jsastro-envs.test.jscontent-collections.test.jscss.test.jscustom-client-directives.test.jsdev-toolbar-audits.test.jsdev-toolbar.test.jserrors.test.jshmr.test.jslit-component.test.jsmultiple-frameworks.test.jsnested-styles.test.jsprefetch.test.jsshared-component-tests.jssolid-component.test.jstailwindcss.test.jstest-utils.jsview-transitions.test.jsvue-component.test.js
package.jsonperformance
src
|
@ -1,5 +0,0 @@
|
|||
---
|
||||
'astro': patch
|
||||
---
|
||||
|
||||
Deprecates `getEntryBySlug` and `getDataEntryById` functions exported by `astro:content` in favor of `getEntry`.
|
|
@ -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.
|
|
@ -1,5 +0,0 @@
|
|||
---
|
||||
'astro': patch
|
||||
---
|
||||
|
||||
Fix toolbar audit incorrectly flagging images as above the fold.
|
|
@ -6,3 +6,5 @@
|
|||
59e8c71786fd1c154904b3fefa7d26d88f4d92d2
|
||||
# Change formatting (#10180)
|
||||
062623438b5dfd66682a967edc7b7c91bd29e888
|
||||
# Update to trailingComma: 'all' (#11640)
|
||||
72c7ae9901de927ae8d9d5be63cbaef4f976422c
|
||||
|
|
38
README.md
38
README.md
|
@ -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) | [](packages/astro/CHANGELOG.md) |
|
||||
| [create-astro](packages/create-astro) | [](packages/create-astro/CHANGELOG.md) |
|
||||
| [@astrojs/react](packages/integrations/react) | [](packages/integrations/react/CHANGELOG.md) |
|
||||
| [@astrojs/preact](packages/integrations/preact) | [](packages/integrations/preact/CHANGELOG.md) |
|
||||
| [@astrojs/solid-js](packages/integrations/solid) | [](packages/integrations/solid/CHANGELOG.md) |
|
||||
| [@astrojs/svelte](packages/integrations/svelte) | [](packages/integrations/svelte/CHANGELOG.md) |
|
||||
| [@astrojs/vue](packages/integrations/vue) | [](packages/integrations/vue/CHANGELOG.md) |
|
||||
| [@astrojs/lit](packages/integrations/lit) | [](packages/integrations/lit/CHANGELOG.md) |
|
||||
| [@astrojs/node](packages/integrations/node) | [](packages/integrations/node/CHANGELOG.md) |
|
||||
| [@astrojs/vercel](packages/integrations/vercel) | [](packages/integrations/vercel/CHANGELOG.md) |
|
||||
| [@astrojs/cloudflare](https://github.com/withastro/adapters/blob/main/packages/cloudflare) | [](https://github.com/withastro/adapters/blob/main/packages/cloudflare/CHANGELOG.md) |
|
||||
| [@astrojs/partytown](packages/integrations/partytown) | [](packages/integrations/partytown/CHANGELOG.md) |
|
||||
| [@astrojs/sitemap](packages/integrations/sitemap) | [](packages/integrations/sitemap/CHANGELOG.md) |
|
||||
| [@astrojs/tailwind](packages/integrations/tailwind) | [](packages/integrations/tailwind/CHANGELOG.md) |
|
||||
| [@astrojs/alpinejs](packages/integrations/alpinejs) | [](packages/integrations/alpinejs/CHANGELOG.md) |
|
||||
| [@astrojs/mdx](packages/integrations/mdx) | [](packages/integrations/mdx/CHANGELOG.md) |
|
||||
| Package | Release Notes |
|
||||
| ------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| [astro](packages/astro) | [](packages/astro/CHANGELOG.md) |
|
||||
| [create-astro](packages/create-astro) | [](packages/create-astro/CHANGELOG.md) |
|
||||
| [@astrojs/react](packages/integrations/react) | [](packages/integrations/react/CHANGELOG.md) |
|
||||
| [@astrojs/preact](packages/integrations/preact) | [](packages/integrations/preact/CHANGELOG.md) |
|
||||
| [@astrojs/solid-js](packages/integrations/solid) | [](packages/integrations/solid/CHANGELOG.md) |
|
||||
| [@astrojs/svelte](packages/integrations/svelte) | [](packages/integrations/svelte/CHANGELOG.md) |
|
||||
| [@astrojs/vue](packages/integrations/vue) | [](packages/integrations/vue/CHANGELOG.md) |
|
||||
| [@astrojs/lit](packages/integrations/lit) | [](packages/integrations/lit/CHANGELOG.md) |
|
||||
| [@astrojs/node](packages/integrations/node) | [](packages/integrations/node/CHANGELOG.md) |
|
||||
| [@astrojs/vercel](packages/integrations/vercel) | [](packages/integrations/vercel/CHANGELOG.md) |
|
||||
| [@astrojs/cloudflare](https://github.com/withastro/adapters/blob/main/packages/cloudflare) | [](https://github.com/withastro/adapters/blob/main/packages/cloudflare/CHANGELOG.md) |
|
||||
| [@astrojs/partytown](packages/integrations/partytown) | [](packages/integrations/partytown/CHANGELOG.md) |
|
||||
| [@astrojs/sitemap](packages/integrations/sitemap) | [](packages/integrations/sitemap/CHANGELOG.md) |
|
||||
| [@astrojs/tailwind](packages/integrations/tailwind) | [](packages/integrations/tailwind/CHANGELOG.md) |
|
||||
| [@astrojs/alpinejs](packages/integrations/alpinejs) | [](packages/integrations/alpinejs/CHANGELOG.md) |
|
||||
| [@astrojs/mdx](packages/integrations/mdx) | [](packages/integrations/mdx/CHANGELOG.md) |
|
||||
| [@astrojs/db](packages/db) | [](packages/db/CHANGELOG.md) |
|
||||
| [@astrojs/rss](packages/integrations/astro-rss) | [](packages/astro-rss/CHANGELOG.md) |
|
||||
|
||||
[](https://bestpractices.coreinfrastructure.org/projects/6178)
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
"linter": { "enabled": false },
|
||||
"javascript": {
|
||||
"formatter": {
|
||||
"trailingCommas": "es5",
|
||||
"trailingCommas": "all",
|
||||
"quoteStyle": "single",
|
||||
"semicolons": "always"
|
||||
}
|
||||
|
|
|
@ -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
|
||||
},
|
||||
},
|
||||
|
|
|
@ -11,6 +11,6 @@
|
|||
"astro": "astro"
|
||||
},
|
||||
"dependencies": {
|
||||
"astro": "^4.13.1"
|
||||
"astro": "^4.13.3"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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(),
|
||||
);
|
||||
---
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
],
|
||||
"scripts": {},
|
||||
"devDependencies": {
|
||||
"astro": "^4.13.1"
|
||||
"astro": "^4.13.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"astro": "^4.0.0"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"@astrojs/svelte": "^5.7.0",
|
||||
"astro": "^4.13.1",
|
||||
"astro": "^4.13.3",
|
||||
"svelte": "^4.2.18"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"@astrojs/vue": "^4.5.0",
|
||||
"astro": "^4.13.1",
|
||||
"astro": "^4.13.3",
|
||||
"vue": "^3.4.35"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,6 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"@astrojs/node": "^8.3.2",
|
||||
"astro": "^4.13.1"
|
||||
"astro": "^4.13.3"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
],
|
||||
"scripts": {},
|
||||
"devDependencies": {
|
||||
"astro": "^4.13.1"
|
||||
"astro": "^4.13.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"astro": "^4.0.0"
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"@astrojs/node": "^8.3.2",
|
||||
"astro": "^4.13.1",
|
||||
"astro": "^4.13.3",
|
||||
"html-minifier": "^4.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
|
|
@ -11,6 +11,6 @@
|
|||
"astro": "astro"
|
||||
},
|
||||
"dependencies": {
|
||||
"astro": "^4.13.1"
|
||||
"astro": "^4.13.3"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,6 @@
|
|||
"astro": "astro"
|
||||
},
|
||||
"dependencies": {
|
||||
"astro": "^4.13.1"
|
||||
"astro": "^4.13.3"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,6 @@
|
|||
"astro": "astro"
|
||||
},
|
||||
"dependencies": {
|
||||
"astro": "^4.13.1"
|
||||
"astro": "^4.13.3"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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(),
|
||||
);
|
||||
---
|
||||
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
"astro": "astro"
|
||||
},
|
||||
"dependencies": {
|
||||
"astro": "^4.13.1",
|
||||
"astro": "^4.13.3",
|
||||
"sass": "^1.77.8",
|
||||
"sharp": "^0.33.3"
|
||||
}
|
||||
|
|
|
@ -15,6 +15,6 @@
|
|||
"./app": "./dist/app.js"
|
||||
},
|
||||
"devDependencies": {
|
||||
"astro": "^4.13.1"
|
||||
"astro": "^4.13.3"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,6 @@
|
|||
"devDependencies": {
|
||||
"@astrojs/tailwind": "^5.1.0",
|
||||
"@astrojs/node": "^8.3.2",
|
||||
"astro": "^4.13.1"
|
||||
"astro": "^4.13.3"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,6 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"@astrojs/markdoc": "^0.11.3",
|
||||
"astro": "^4.13.1"
|
||||
"astro": "^4.13.3"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -11,6 +11,6 @@
|
|||
"astro": "astro"
|
||||
},
|
||||
"dependencies": {
|
||||
"astro": "^4.13.1"
|
||||
"astro": "^4.13.3"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
"test": "vitest"
|
||||
},
|
||||
"dependencies": {
|
||||
"astro": "^4.13.1",
|
||||
"astro": "^4.13.3",
|
||||
"vitest": "^2.0.5"
|
||||
}
|
||||
}
|
||||
|
|
18
package.json
18
package.json
|
@ -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",
|
||||
|
|
|
@ -29,6 +29,6 @@ runHighlighterWithAstro(
|
|||
|
||||
<div>{helloAstro}</div>
|
||||
`,
|
||||
'astro'
|
||||
'astro',
|
||||
);
|
||||
```
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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,
|
||||
},
|
||||
})
|
||||
}),
|
||||
),
|
||||
};
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
1
packages/astro/astro-jsx.d.ts
vendored
1
packages/astro/astro-jsx.d.ts
vendored
|
@ -14,7 +14,6 @@ declare namespace astroHTML.JSX {
|
|||
export type Children = Child | Child[];
|
||||
|
||||
interface ElementChildrenAttribute {
|
||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||
children: {};
|
||||
}
|
||||
|
||||
|
|
|
@ -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]) {
|
||||
|
|
2
packages/astro/client.d.ts
vendored
2
packages/astro/client.d.ts
vendored
|
@ -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;
|
||||
|
|
|
@ -53,8 +53,8 @@ const optimizedImages: GetImageResult[] = await Promise.all(
|
|||
format: format,
|
||||
widths: props.widths,
|
||||
densities: props.densities,
|
||||
})
|
||||
)
|
||||
}),
|
||||
),
|
||||
);
|
||||
|
||||
let resultFallbackFormat = fallbackFormat ?? defaultFallbackFormat;
|
||||
|
|
|
@ -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) => {
|
||||
|
|
2
packages/astro/config.d.ts
vendored
2
packages/astro/config.d.ts
vendored
|
@ -17,7 +17,7 @@ export function defineConfig(config: AstroUserConfig): AstroUserConfig;
|
|||
*/
|
||||
export function getViteConfig(
|
||||
config: ViteUserConfig,
|
||||
inlineAstroConfig?: AstroInlineConfig
|
||||
inlineAstroConfig?: AstroInlineConfig,
|
||||
): ViteUserConfigFn;
|
||||
|
||||
/**
|
||||
|
|
|
@ -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');
|
||||
|
|
|
@ -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',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -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');
|
||||
|
|
|
@ -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)');
|
||||
|
|
|
@ -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"}',
|
||||
);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
});
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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>`,
|
||||
),
|
||||
]);
|
||||
|
||||
|
|
|
@ -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)');
|
||||
|
|
|
@ -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!');
|
||||
|
|
|
@ -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');
|
||||
|
|
|
@ -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
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -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();
|
||||
});
|
||||
|
|
|
@ -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');
|
||||
|
|
|
@ -4,7 +4,7 @@ const { test, createTests } = prepareTestFactory(
|
|||
{ root: './fixtures/solid-component/' },
|
||||
{
|
||||
canReplayClicks: true,
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
const config = {
|
||||
|
|
|
@ -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)',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -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}"]`,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -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');
|
||||
});
|
||||
|
|
|
@ -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');
|
||||
|
|
|
@ -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"
|
||||
},
|
||||
|
|
|
@ -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({
|
||||
|
|
|
@ -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'),
|
||||
);
|
||||
})
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
|
|
@ -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 = {
|
||||
|
|
|
@ -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',
|
||||
};
|
||||
|
|
|
@ -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';`;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -10,5 +10,5 @@ export const z = new Proxy(
|
|||
get() {
|
||||
throw new Error('[astro:action] `z` unexpectedly used on the client.');
|
||||
},
|
||||
}
|
||||
},
|
||||
);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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()}`;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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}))`,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -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, {
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
}))
|
||||
})),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
/* tslint-disable ban-types */
|
||||
import { parentPort, Worker } from 'worker_threads';
|
||||
|
||||
function uuid() {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
Loading…
Add table
Reference in a new issue