astro 6.0.7 → 6.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/client.d.ts +30 -40
- package/dist/actions/runtime/server.d.ts +3 -1
- package/dist/actions/runtime/server.js +39 -8
- package/dist/assets/build/generate.js +17 -19
- package/dist/assets/build/remote.d.ts +4 -4
- package/dist/assets/build/remote.js +12 -10
- package/dist/assets/fonts/infra/dev-font-file-id-generator.js +4 -1
- package/dist/assets/fonts/vite-plugin-fonts.js +8 -0
- package/dist/assets/services/sharp.d.ts +21 -2
- package/dist/assets/services/sharp.js +54 -12
- package/dist/assets/vite-plugin-assets.js +4 -1
- package/dist/cli/add/index.js +54 -0
- package/dist/cli/infra/build-time-astro-version-provider.js +1 -1
- package/dist/content/content-layer.js +3 -3
- package/dist/content/index.d.ts +1 -1
- package/dist/content/index.js +2 -3
- package/dist/content/runtime.d.ts +2 -0
- package/dist/content/runtime.js +2 -1
- package/dist/content/types-generator.js +4 -0
- package/dist/content/utils.d.ts +0 -1
- package/dist/content/utils.js +1 -10
- package/dist/core/app/dev/app.d.ts +5 -0
- package/dist/core/app/dev/app.js +7 -0
- package/dist/core/app/entrypoints/virtual/dev.js +4 -0
- package/dist/core/app/node.js +5 -4
- package/dist/core/app/validate-headers.d.ts +6 -0
- package/dist/core/app/validate-headers.js +4 -0
- package/dist/core/base-pipeline.d.ts +5 -0
- package/dist/core/base-pipeline.js +7 -0
- package/dist/core/build/generate.d.ts +47 -0
- package/dist/core/build/generate.js +43 -25
- package/dist/core/build/plugins/plugin-css.js +8 -4
- package/dist/core/config/schemas/base.d.ts +4 -2
- package/dist/core/config/schemas/base.js +22 -1
- package/dist/core/config/schemas/relative.d.ts +3 -3
- package/dist/core/constants.js +1 -1
- package/dist/core/create-vite.js +1 -1
- package/dist/core/dev/dev.js +13 -1
- package/dist/core/head-propagation/boundary.d.ts +8 -0
- package/dist/core/head-propagation/boundary.js +11 -0
- package/dist/core/head-propagation/buffer.d.ts +21 -0
- package/dist/core/head-propagation/buffer.js +18 -0
- package/dist/core/head-propagation/comment.d.ts +7 -0
- package/dist/core/head-propagation/comment.js +7 -0
- package/dist/core/head-propagation/graph.d.ts +18 -0
- package/dist/core/head-propagation/graph.js +32 -0
- package/dist/core/head-propagation/policy.d.ts +22 -0
- package/dist/core/head-propagation/policy.js +14 -0
- package/dist/core/head-propagation/resolver.d.ts +28 -0
- package/dist/core/head-propagation/resolver.js +25 -0
- package/dist/core/messages/runtime.d.ts +3 -0
- package/dist/core/messages/runtime.js +9 -1
- package/dist/core/middleware/vite-plugin.d.ts +1 -1
- package/dist/core/middleware/vite-plugin.js +25 -0
- package/dist/core/redirects/render.d.ts +17 -0
- package/dist/core/redirects/render.js +33 -24
- package/dist/core/routing/create-manifest.d.ts +15 -0
- package/dist/core/routing/create-manifest.js +131 -130
- package/dist/core/routing/prerender.d.ts +5 -0
- package/dist/core/routing/prerender.js +7 -1
- package/dist/core/routing/rewrite.d.ts +9 -0
- package/dist/core/routing/rewrite.js +39 -26
- package/dist/core/server-islands/vite-plugin-server-islands.js +18 -6
- package/dist/integrations/hooks.js +4 -1
- package/dist/jsx/rehype.js +1 -1
- package/dist/manifest/serialized.js +5 -0
- package/dist/manifest/virtual-module.d.ts +4 -1
- package/dist/manifest/virtual-module.js +37 -35
- package/dist/runtime/client/dev-toolbar/apps/audit/rules/a11y.js +3 -3
- package/dist/runtime/server/render/astro/factory.js +6 -7
- package/dist/runtime/server/render/astro/instance.js +2 -4
- package/dist/runtime/server/render/astro/render.js +2 -11
- package/dist/runtime/server/render/common.js +3 -2
- package/dist/runtime/server/render/head-propagation/runtime.d.ts +20 -0
- package/dist/runtime/server/render/head-propagation/runtime.js +53 -0
- package/dist/runtime/server/render/page.js +5 -1
- package/dist/runtime/server/transition.d.ts +19 -1
- package/dist/runtime/server/transition.js +6 -1
- package/dist/transitions/events.d.ts +1 -1
- package/dist/transitions/events.js +5 -5
- package/dist/transitions/router.js +23 -19
- package/dist/types/public/config.d.ts +70 -11
- package/dist/types/public/integrations.d.ts +9 -2
- package/dist/vite-plugin-app/app.d.ts +5 -0
- package/dist/vite-plugin-app/app.js +17 -1
- package/dist/vite-plugin-app/createAstroServerApp.js +4 -0
- package/dist/vite-plugin-astro-server/plugin.js +2 -1
- package/dist/vite-plugin-astro-server/vite.js +2 -2
- package/dist/vite-plugin-css/index.js +2 -0
- package/dist/vite-plugin-head/index.js +63 -25
- package/dist/vite-plugin-scripts/index.js +5 -0
- package/package.json +11 -11
package/client.d.ts
CHANGED
|
@@ -30,36 +30,36 @@ interface ImportMeta {
|
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
declare module 'astro:assets' {
|
|
33
|
-
//
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
33
|
+
// getImage's type here is different from the internal function since the Vite module implicitly pass the service config
|
|
34
|
+
/**
|
|
35
|
+
* Get an optimized image and the necessary attributes to render it.
|
|
36
|
+
*
|
|
37
|
+
* **Example**
|
|
38
|
+
* ```astro
|
|
39
|
+
* ---
|
|
40
|
+
* import { getImage } from 'astro:assets';
|
|
41
|
+
* import originalImage from '../assets/image.png';
|
|
42
|
+
*
|
|
43
|
+
* const optimizedImage = await getImage({src: originalImage, width: 1280 });
|
|
44
|
+
* ---
|
|
45
|
+
* <img src={optimizedImage.src} {...optimizedImage.attributes} />
|
|
46
|
+
* ```
|
|
47
|
+
*
|
|
48
|
+
* This is functionally equivalent to using the `<Image />` component, as the component calls this function internally.
|
|
49
|
+
*/
|
|
50
|
+
export const getImage: (
|
|
51
|
+
options: import('./dist/assets/types.js').UnresolvedImageTransform,
|
|
52
|
+
) => Promise<import('./dist/assets/types.js').GetImageResult>;
|
|
53
|
+
export const imageConfig: import('./dist/types/public/config.js').AstroConfig['image'];
|
|
54
|
+
export const getConfiguredImageService: typeof import('./dist/assets/index.js').getConfiguredImageService;
|
|
55
|
+
export const inferRemoteSize: typeof import('./dist/assets/utils/index.js').inferRemoteSize;
|
|
56
|
+
export const Image: typeof import('./components/Image.astro').default;
|
|
57
|
+
export const Picture: typeof import('./components/Picture.astro').default;
|
|
58
|
+
export const Font: typeof import('./components/Font.astro').default;
|
|
59
|
+
export const fontData: Record<
|
|
60
|
+
import('astro:assets').CssVariable,
|
|
61
|
+
Array<import('astro:assets').FontData>
|
|
62
|
+
>;
|
|
63
63
|
|
|
64
64
|
type ImgAttributes = import('./dist/type-utils.js').WithRequired<
|
|
65
65
|
Omit<import('./types').HTMLAttributes<'img'>, 'src' | 'width' | 'height'>,
|
|
@@ -72,16 +72,6 @@ declare module 'astro:assets' {
|
|
|
72
72
|
export type RemoteImageProps = import('./dist/type-utils.js').Simplify<
|
|
73
73
|
import('./dist/assets/types.js').RemoteImageProps<ImgAttributes>
|
|
74
74
|
>;
|
|
75
|
-
export const {
|
|
76
|
-
getImage,
|
|
77
|
-
getConfiguredImageService,
|
|
78
|
-
imageConfig,
|
|
79
|
-
Image,
|
|
80
|
-
Picture,
|
|
81
|
-
Font,
|
|
82
|
-
inferRemoteSize,
|
|
83
|
-
fontData,
|
|
84
|
-
}: AstroAssets;
|
|
85
75
|
}
|
|
86
76
|
|
|
87
77
|
declare module 'virtual:astro:image-styles.css' {
|
|
@@ -38,6 +38,8 @@ interface AstroActionContext {
|
|
|
38
38
|
export declare function getActionContext(context: APIContext): AstroActionContext;
|
|
39
39
|
export declare const ACTION_API_CONTEXT_SYMBOL: unique symbol;
|
|
40
40
|
/** Transform form data to an object based on a Zod schema. */
|
|
41
|
-
export declare function formDataToObject<T extends z.$ZodObject>(formData: FormData, schema: T
|
|
41
|
+
export declare function formDataToObject<T extends z.$ZodObject>(formData: FormData, schema: T,
|
|
42
|
+
/** @internal */
|
|
43
|
+
prefix?: string): Record<string, unknown>;
|
|
42
44
|
export declare function serializeActionResult(res: SafeResult<any, any>): SerializedActionResult;
|
|
43
45
|
export {};
|
|
@@ -206,29 +206,60 @@ function isActionAPIContext(ctx) {
|
|
|
206
206
|
const symbol = Reflect.get(ctx, ACTION_API_CONTEXT_SYMBOL);
|
|
207
207
|
return symbol === true;
|
|
208
208
|
}
|
|
209
|
-
function formDataToObject(formData, schema) {
|
|
210
|
-
const
|
|
209
|
+
function formDataToObject(formData, schema, prefix = "") {
|
|
210
|
+
const formKeys = [...formData.keys()];
|
|
211
|
+
const obj = schema._zod.def.catchall ? Object.fromEntries(
|
|
212
|
+
[...formData.entries()].filter(([k]) => k.startsWith(prefix)).map(([k, v]) => [k.slice(prefix.length), v])
|
|
213
|
+
) : {};
|
|
211
214
|
for (const [key, baseValidator] of Object.entries(schema._zod.def.shape)) {
|
|
215
|
+
const prefixedKey = prefix + key;
|
|
212
216
|
let validator = baseValidator;
|
|
213
217
|
while (validator instanceof z.$ZodOptional || validator instanceof z.$ZodNullable || validator instanceof z.$ZodDefault) {
|
|
214
|
-
if (validator instanceof z.$ZodDefault && !
|
|
218
|
+
if (validator instanceof z.$ZodDefault && !formDataHasKeyOrPrefix(formKeys, prefixedKey)) {
|
|
215
219
|
obj[key] = validator._zod.def.defaultValue instanceof Function ? validator._zod.def.defaultValue() : validator._zod.def.defaultValue;
|
|
216
220
|
}
|
|
217
221
|
validator = validator._zod.def.innerType;
|
|
218
222
|
}
|
|
219
|
-
|
|
223
|
+
while (validator instanceof z.$ZodPipe) {
|
|
224
|
+
validator = validator._zod.def.in;
|
|
225
|
+
}
|
|
226
|
+
if (validator instanceof z.$ZodDiscriminatedUnion) {
|
|
227
|
+
const typeKey = validator._zod.def.discriminator;
|
|
228
|
+
const typeValue = formData.get(prefixedKey + "." + typeKey);
|
|
229
|
+
if (typeof typeValue === "string") {
|
|
230
|
+
const match = validator._zod.def.options.find(
|
|
231
|
+
(option) => option.def.shape[typeKey].values.has(typeValue)
|
|
232
|
+
);
|
|
233
|
+
if (match) {
|
|
234
|
+
validator = match;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
if (validator instanceof z.$ZodObject) {
|
|
239
|
+
const nestedPrefix = prefixedKey + ".";
|
|
240
|
+
const hasNestedKeys = formKeys.some((k) => k.startsWith(nestedPrefix));
|
|
241
|
+
if (hasNestedKeys) {
|
|
242
|
+
obj[key] = formDataToObject(formData, validator, nestedPrefix);
|
|
243
|
+
} else if (!(key in obj)) {
|
|
244
|
+
obj[key] = baseValidator instanceof z.$ZodNullable ? null : void 0;
|
|
245
|
+
}
|
|
246
|
+
} else if (!formData.has(prefixedKey) && key in obj) {
|
|
220
247
|
continue;
|
|
221
248
|
} else if (validator instanceof z.$ZodBoolean) {
|
|
222
|
-
const val = formData.get(
|
|
223
|
-
obj[key] = val === "true" ? true : val === "false" ? false : formData.has(
|
|
249
|
+
const val = formData.get(prefixedKey);
|
|
250
|
+
obj[key] = val === "true" ? true : val === "false" ? false : formData.has(prefixedKey);
|
|
224
251
|
} else if (validator instanceof z.$ZodArray) {
|
|
225
|
-
obj[key] = handleFormDataGetAll(
|
|
252
|
+
obj[key] = handleFormDataGetAll(prefixedKey, formData, validator);
|
|
226
253
|
} else {
|
|
227
|
-
obj[key] = handleFormDataGet(
|
|
254
|
+
obj[key] = handleFormDataGet(prefixedKey, formData, validator, baseValidator);
|
|
228
255
|
}
|
|
229
256
|
}
|
|
230
257
|
return obj;
|
|
231
258
|
}
|
|
259
|
+
function formDataHasKeyOrPrefix(formKeys, key) {
|
|
260
|
+
const prefix = key + ".";
|
|
261
|
+
return formKeys.some((k) => k === key || k.startsWith(prefix));
|
|
262
|
+
}
|
|
232
263
|
function handleFormDataGetAll(key, formData, validator) {
|
|
233
264
|
const entries = Array.from(formData.getAll(key));
|
|
234
265
|
const elementValidator = validator._zod.def.element;
|
|
@@ -95,12 +95,11 @@ async function generateImagesForPath(originalFilePath, transformsAndPath, env) {
|
|
|
95
95
|
};
|
|
96
96
|
} else {
|
|
97
97
|
const JSONData = JSON.parse(readFileSync(cachedMetaFileURL, "utf-8"));
|
|
98
|
-
if (
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
await fs.promises.unlink(cachedMetaFileURL);
|
|
98
|
+
if (typeof JSONData.expires !== "number") {
|
|
99
|
+
await Promise.allSettled([
|
|
100
|
+
fs.promises.unlink(cachedFileURL),
|
|
101
|
+
fs.promises.unlink(cachedMetaFileURL)
|
|
102
|
+
]);
|
|
104
103
|
throw new Error(
|
|
105
104
|
`Malformed cache entry for ${filepath}, cache will be regenerated for this file.`
|
|
106
105
|
);
|
|
@@ -114,9 +113,7 @@ async function generateImagesForPath(originalFilePath, transformsAndPath, env) {
|
|
|
114
113
|
}
|
|
115
114
|
if (JSONData.expires > Date.now()) {
|
|
116
115
|
await fs.promises.copyFile(cachedFileURL, finalFileURL, fs.constants.COPYFILE_FICLONE);
|
|
117
|
-
return {
|
|
118
|
-
cached: "hit"
|
|
119
|
-
};
|
|
116
|
+
return { cached: "hit" };
|
|
120
117
|
}
|
|
121
118
|
if (JSONData.etag || JSONData.lastModified) {
|
|
122
119
|
try {
|
|
@@ -124,15 +121,13 @@ async function generateImagesForPath(originalFilePath, transformsAndPath, env) {
|
|
|
124
121
|
etag: JSONData.etag,
|
|
125
122
|
lastModified: JSONData.lastModified
|
|
126
123
|
});
|
|
127
|
-
if (revalidatedData.data
|
|
124
|
+
if (revalidatedData.data !== null) {
|
|
128
125
|
originalImage = revalidatedData;
|
|
129
126
|
} else {
|
|
130
|
-
await
|
|
131
|
-
|
|
132
|
-
cachedFileURL,
|
|
133
|
-
|
|
134
|
-
fs.constants.COPYFILE_FICLONE
|
|
135
|
-
);
|
|
127
|
+
await Promise.all([
|
|
128
|
+
writeCacheMetaFile(cachedMetaFileURL, revalidatedData, env),
|
|
129
|
+
fs.promises.copyFile(cachedFileURL, finalFileURL, fs.constants.COPYFILE_FICLONE)
|
|
130
|
+
]);
|
|
136
131
|
return { cached: "revalidated" };
|
|
137
132
|
}
|
|
138
133
|
} catch (e) {
|
|
@@ -144,8 +139,10 @@ async function generateImagesForPath(originalFilePath, transformsAndPath, env) {
|
|
|
144
139
|
return { cached: "hit" };
|
|
145
140
|
}
|
|
146
141
|
}
|
|
147
|
-
await
|
|
148
|
-
|
|
142
|
+
await Promise.allSettled([
|
|
143
|
+
fs.promises.unlink(cachedFileURL),
|
|
144
|
+
fs.promises.unlink(cachedMetaFileURL)
|
|
145
|
+
]);
|
|
149
146
|
}
|
|
150
147
|
} catch (e) {
|
|
151
148
|
if (e.code !== "ENOENT") {
|
|
@@ -219,7 +216,8 @@ async function writeCacheMetaFile(cachedMetaFileURL, resultData, env) {
|
|
|
219
216
|
expires: resultData.expires,
|
|
220
217
|
etag: resultData.etag,
|
|
221
218
|
lastModified: resultData.lastModified
|
|
222
|
-
})
|
|
219
|
+
}),
|
|
220
|
+
"utf-8"
|
|
223
221
|
);
|
|
224
222
|
} catch (e) {
|
|
225
223
|
env.logger.warn(
|
|
@@ -4,7 +4,7 @@ export type RemoteCacheEntry = {
|
|
|
4
4
|
etag?: string;
|
|
5
5
|
lastModified?: string;
|
|
6
6
|
};
|
|
7
|
-
export declare function loadRemoteImage(src: string): Promise<{
|
|
7
|
+
export declare function loadRemoteImage(src: string, fetchFn?: typeof fetch): Promise<{
|
|
8
8
|
data: Buffer<ArrayBuffer>;
|
|
9
9
|
expires: number;
|
|
10
10
|
etag: string | undefined;
|
|
@@ -17,13 +17,13 @@ export declare function loadRemoteImage(src: string): Promise<{
|
|
|
17
17
|
* The remote server may respond that the cached asset is still up-to-date if the entity-tag or modification time matches (304 Not Modified), or respond with an updated asset (200 OK)
|
|
18
18
|
* @param src - url to remote asset
|
|
19
19
|
* @param revalidationData - an object containing the stored Entity-Tag of the cached asset and/or the Last Modified time
|
|
20
|
-
* @returns An
|
|
20
|
+
* @returns An object containing the refreshed expiry time and cache headers. `data` will be a `Buffer` of the new image if the asset was modified (200 OK), or `null` if the cached version is still valid (304 Not Modified).
|
|
21
21
|
*/
|
|
22
22
|
export declare function revalidateRemoteImage(src: string, revalidationData: {
|
|
23
23
|
etag?: string;
|
|
24
24
|
lastModified?: string;
|
|
25
|
-
}): Promise<{
|
|
26
|
-
data: Buffer<ArrayBuffer
|
|
25
|
+
}, fetchFn?: typeof fetch): Promise<{
|
|
26
|
+
data: Buffer<ArrayBuffer> | null;
|
|
27
27
|
expires: number;
|
|
28
28
|
etag: string | undefined;
|
|
29
29
|
lastModified: string | undefined;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import CachePolicy from "http-cache-semantics";
|
|
2
|
-
async function loadRemoteImage(src) {
|
|
2
|
+
async function loadRemoteImage(src, fetchFn = globalThis.fetch) {
|
|
3
3
|
const req = new Request(src);
|
|
4
|
-
const res = await
|
|
4
|
+
const res = await fetchFn(req, { redirect: "manual" });
|
|
5
5
|
if (res.status >= 300 && res.status < 400) {
|
|
6
6
|
throw new Error(`Failed to load remote image ${src}. The request was redirected.`);
|
|
7
7
|
}
|
|
@@ -19,35 +19,37 @@ async function loadRemoteImage(src) {
|
|
|
19
19
|
lastModified: res.headers.get("Last-Modified") ?? void 0
|
|
20
20
|
};
|
|
21
21
|
}
|
|
22
|
-
async function revalidateRemoteImage(src, revalidationData) {
|
|
22
|
+
async function revalidateRemoteImage(src, revalidationData, fetchFn = globalThis.fetch) {
|
|
23
23
|
const headers = {
|
|
24
24
|
...revalidationData.etag && { "If-None-Match": revalidationData.etag },
|
|
25
25
|
...revalidationData.lastModified && { "If-Modified-Since": revalidationData.lastModified }
|
|
26
26
|
};
|
|
27
27
|
const req = new Request(src, { headers, cache: "no-cache" });
|
|
28
|
-
const res = await
|
|
29
|
-
if (res.status >= 300 && res.status < 400) {
|
|
30
|
-
throw new Error(`Failed to revalidate cached remote image ${src}. The request was redirected.`);
|
|
31
|
-
}
|
|
28
|
+
const res = await fetchFn(req, { redirect: "manual" });
|
|
32
29
|
if (!res.ok && res.status !== 304) {
|
|
30
|
+
if (res.status >= 300 && res.status < 400) {
|
|
31
|
+
throw new Error(
|
|
32
|
+
`Failed to revalidate cached remote image ${src}. The request was redirected.`
|
|
33
|
+
);
|
|
34
|
+
}
|
|
33
35
|
throw new Error(
|
|
34
36
|
`Failed to revalidate cached remote image ${src}. The request did not return a 200 OK / 304 NOT MODIFIED response. (received ${res.status} ${res.statusText})`
|
|
35
37
|
);
|
|
36
38
|
}
|
|
37
39
|
const data = Buffer.from(await res.arrayBuffer());
|
|
38
40
|
if (res.ok && !data.length) {
|
|
39
|
-
return await loadRemoteImage(src);
|
|
41
|
+
return await loadRemoteImage(src, fetchFn);
|
|
40
42
|
}
|
|
41
43
|
const policy = new CachePolicy(
|
|
42
44
|
webToCachePolicyRequest(req),
|
|
43
45
|
webToCachePolicyResponse(
|
|
44
46
|
res.ok ? res : new Response(null, { status: 200, headers: res.headers })
|
|
45
47
|
)
|
|
46
|
-
// 304 responses
|
|
48
|
+
// 304 responses are not cacheable, so just use its headers to get the refreshed TTL
|
|
47
49
|
);
|
|
48
50
|
const expires = policy.storable() ? policy.timeToLive() : 0;
|
|
49
51
|
return {
|
|
50
|
-
data,
|
|
52
|
+
data: res.ok ? data : null,
|
|
51
53
|
expires: Date.now() + expires,
|
|
52
54
|
// While servers should respond with the same headers as a 200 response, if they don't we should reuse the stored value
|
|
53
55
|
etag: res.headers.get("Etag") ?? (res.ok ? void 0 : revalidationData.etag),
|
|
@@ -17,6 +17,9 @@ class DevFontFileIdGenerator {
|
|
|
17
17
|
}
|
|
18
18
|
return weight?.replace(/\s+/g, "-");
|
|
19
19
|
}
|
|
20
|
+
#formatStyle(style) {
|
|
21
|
+
return style?.replace(/\s+/g, "-");
|
|
22
|
+
}
|
|
20
23
|
generate({
|
|
21
24
|
cssVariable,
|
|
22
25
|
originalUrl,
|
|
@@ -26,7 +29,7 @@ class DevFontFileIdGenerator {
|
|
|
26
29
|
return [
|
|
27
30
|
cssVariable.slice(2),
|
|
28
31
|
this.#formatWeight(font.weight),
|
|
29
|
-
font.style,
|
|
32
|
+
this.#formatStyle(font.style),
|
|
30
33
|
font.meta?.subset,
|
|
31
34
|
`${this.#hasher.hashString(this.#contentResolver.resolve(originalUrl))}.${type}`
|
|
32
35
|
].filter(Boolean).join("-");
|
|
@@ -51,6 +51,7 @@ function fontsPlugin({ settings, sync, logger }) {
|
|
|
51
51
|
let isBuild;
|
|
52
52
|
let fontFetcher = null;
|
|
53
53
|
let fontTypeExtractor = null;
|
|
54
|
+
let built = false;
|
|
54
55
|
const cleanup = () => {
|
|
55
56
|
componentDataByCssVariable = null;
|
|
56
57
|
fontDataByCssVariable = null;
|
|
@@ -63,6 +64,9 @@ function fontsPlugin({ settings, sync, logger }) {
|
|
|
63
64
|
isBuild = command === "build";
|
|
64
65
|
},
|
|
65
66
|
async buildStart() {
|
|
67
|
+
if (sync) {
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
66
70
|
const { root } = settings.config;
|
|
67
71
|
const hasher = await XxhashHasher.create();
|
|
68
72
|
const storage = new UnstorageFsStorage({
|
|
@@ -252,6 +256,9 @@ function fontsPlugin({ settings, sync, logger }) {
|
|
|
252
256
|
}
|
|
253
257
|
},
|
|
254
258
|
async buildEnd() {
|
|
259
|
+
if (built) {
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
255
262
|
if (sync || !settings.config.fonts?.length || !isBuild) {
|
|
256
263
|
cleanup();
|
|
257
264
|
return;
|
|
@@ -282,6 +289,7 @@ function fontsPlugin({ settings, sync, logger }) {
|
|
|
282
289
|
}
|
|
283
290
|
} finally {
|
|
284
291
|
cleanup();
|
|
292
|
+
built = true;
|
|
285
293
|
}
|
|
286
294
|
}
|
|
287
295
|
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { ResizeOptions, SharpOptions } from 'sharp';
|
|
2
|
-
import { type LocalImageService } from './service.js';
|
|
1
|
+
import type { AvifOptions, JpegOptions, PngOptions, ResizeOptions, SharpOptions, WebpOptions } from 'sharp';
|
|
2
|
+
import { type BaseServiceTransform, type LocalImageService } from './service.js';
|
|
3
3
|
export interface SharpImageServiceConfig {
|
|
4
4
|
/**
|
|
5
5
|
* The `limitInputPixels` option passed to Sharp. See https://sharp.pixelplumbing.com/api-constructor for more information
|
|
@@ -9,6 +9,25 @@ export interface SharpImageServiceConfig {
|
|
|
9
9
|
* The `kernel` option is passed to resize calls. See https://sharp.pixelplumbing.com/api-resize/ for more information
|
|
10
10
|
*/
|
|
11
11
|
kernel?: ResizeOptions['kernel'];
|
|
12
|
+
/**
|
|
13
|
+
* The default encoder options passed to `sharp().jpeg()`.
|
|
14
|
+
*/
|
|
15
|
+
jpeg?: JpegOptions;
|
|
16
|
+
/**
|
|
17
|
+
* The default encoder options passed to `sharp().png()`.
|
|
18
|
+
*/
|
|
19
|
+
png?: PngOptions;
|
|
20
|
+
/**
|
|
21
|
+
* The default encoder options passed to `sharp().webp()`.
|
|
22
|
+
*/
|
|
23
|
+
webp?: WebpOptions;
|
|
24
|
+
/**
|
|
25
|
+
* The default encoder options passed to `sharp().avif()`.
|
|
26
|
+
*/
|
|
27
|
+
avif?: AvifOptions;
|
|
12
28
|
}
|
|
29
|
+
export declare function resolveSharpEncoderOptions(transform: Pick<BaseServiceTransform, 'format' | 'quality'>, inputFormat: string | undefined, serviceConfig?: SharpImageServiceConfig): JpegOptions | PngOptions | WebpOptions | AvifOptions | {
|
|
30
|
+
quality?: number;
|
|
31
|
+
} | undefined;
|
|
13
32
|
declare const sharpService: LocalImageService<SharpImageServiceConfig>;
|
|
14
33
|
export default sharpService;
|
|
@@ -10,6 +10,47 @@ const qualityTable = {
|
|
|
10
10
|
high: 80,
|
|
11
11
|
max: 100
|
|
12
12
|
};
|
|
13
|
+
function resolveSharpQuality(quality) {
|
|
14
|
+
if (!quality) return void 0;
|
|
15
|
+
const parsedQuality = parseQuality(quality);
|
|
16
|
+
if (typeof parsedQuality === "number") {
|
|
17
|
+
return parsedQuality;
|
|
18
|
+
}
|
|
19
|
+
return quality in qualityTable ? qualityTable[quality] : void 0;
|
|
20
|
+
}
|
|
21
|
+
function resolveSharpEncoderOptions(transform, inputFormat, serviceConfig = {}) {
|
|
22
|
+
const quality = resolveSharpQuality(transform.quality);
|
|
23
|
+
switch (transform.format) {
|
|
24
|
+
case "jpg":
|
|
25
|
+
case "jpeg":
|
|
26
|
+
return {
|
|
27
|
+
...serviceConfig.jpeg,
|
|
28
|
+
...quality === void 0 ? {} : { quality }
|
|
29
|
+
};
|
|
30
|
+
case "png":
|
|
31
|
+
return {
|
|
32
|
+
...serviceConfig.png,
|
|
33
|
+
...quality === void 0 ? {} : { quality }
|
|
34
|
+
};
|
|
35
|
+
case "webp": {
|
|
36
|
+
const webpOptions = {
|
|
37
|
+
...serviceConfig.webp,
|
|
38
|
+
...quality === void 0 ? {} : { quality }
|
|
39
|
+
};
|
|
40
|
+
if (inputFormat === "gif") {
|
|
41
|
+
webpOptions.loop ??= 0;
|
|
42
|
+
}
|
|
43
|
+
return webpOptions;
|
|
44
|
+
}
|
|
45
|
+
case "avif":
|
|
46
|
+
return {
|
|
47
|
+
...serviceConfig.avif,
|
|
48
|
+
...quality === void 0 ? {} : { quality }
|
|
49
|
+
};
|
|
50
|
+
default:
|
|
51
|
+
return quality === void 0 ? void 0 : { quality };
|
|
52
|
+
}
|
|
53
|
+
}
|
|
13
54
|
async function loadSharp() {
|
|
14
55
|
let sharpImport;
|
|
15
56
|
try {
|
|
@@ -75,19 +116,19 @@ const sharpService = {
|
|
|
75
116
|
result.flatten({ background: transform.background });
|
|
76
117
|
}
|
|
77
118
|
if (transform.format) {
|
|
78
|
-
|
|
79
|
-
if (transform.quality) {
|
|
80
|
-
const parsedQuality = parseQuality(transform.quality);
|
|
81
|
-
if (typeof parsedQuality === "number") {
|
|
82
|
-
quality = parsedQuality;
|
|
83
|
-
} else {
|
|
84
|
-
quality = transform.quality in qualityTable ? qualityTable[transform.quality] : void 0;
|
|
85
|
-
}
|
|
86
|
-
}
|
|
119
|
+
const encoderOptions = resolveSharpEncoderOptions(transform, format, config.service.config);
|
|
87
120
|
if (transform.format === "webp" && format === "gif") {
|
|
88
|
-
result.webp(
|
|
121
|
+
result.webp(encoderOptions);
|
|
122
|
+
} else if (transform.format === "webp") {
|
|
123
|
+
result.webp(encoderOptions);
|
|
124
|
+
} else if (transform.format === "png") {
|
|
125
|
+
result.png(encoderOptions);
|
|
126
|
+
} else if (transform.format === "avif") {
|
|
127
|
+
result.avif(encoderOptions);
|
|
128
|
+
} else if (transform.format === "jpeg" || transform.format === "jpg") {
|
|
129
|
+
result.jpeg(encoderOptions);
|
|
89
130
|
} else {
|
|
90
|
-
result.toFormat(transform.format,
|
|
131
|
+
result.toFormat(transform.format, encoderOptions);
|
|
91
132
|
}
|
|
92
133
|
}
|
|
93
134
|
const { data, info } = await result.toBuffer({ resolveWithObject: true });
|
|
@@ -100,5 +141,6 @@ const sharpService = {
|
|
|
100
141
|
};
|
|
101
142
|
var sharp_default = sharpService;
|
|
102
143
|
export {
|
|
103
|
-
sharp_default as default
|
|
144
|
+
sharp_default as default,
|
|
145
|
+
resolveSharpEncoderOptions
|
|
104
146
|
};
|
|
@@ -122,7 +122,10 @@ function assets({ fs, settings, sync, logger }) {
|
|
|
122
122
|
const getImageExport = isServerEnvironment ? `import { getImage as getImageInternal } from "astro/assets";
|
|
123
123
|
export const getImage = async (options) => await getImageInternal(options, imageConfig);` : `import { AstroError, AstroErrorData } from "astro/errors";
|
|
124
124
|
export const getImage = async () => {
|
|
125
|
-
throw new AstroError(
|
|
125
|
+
throw new AstroError(
|
|
126
|
+
AstroErrorData.GetImageNotUsedOnServer.message,
|
|
127
|
+
AstroErrorData.GetImageNotUsedOnServer.hint,
|
|
128
|
+
);
|
|
126
129
|
};`;
|
|
127
130
|
return {
|
|
128
131
|
code: `
|
package/dist/cli/add/index.js
CHANGED
|
@@ -207,6 +207,12 @@ async function add(names, { flags }) {
|
|
|
207
207
|
logger,
|
|
208
208
|
scripts: { "generate-types": "wrangler types" }
|
|
209
209
|
});
|
|
210
|
+
await updatePackageJsonOverrides({
|
|
211
|
+
configURL,
|
|
212
|
+
flags,
|
|
213
|
+
logger,
|
|
214
|
+
overrides: { vite: "^7" }
|
|
215
|
+
});
|
|
210
216
|
}
|
|
211
217
|
if (integrations.find((integration) => integration.id === "tailwind")) {
|
|
212
218
|
const dir = new URL("./styles/", new URL(userConfig.srcDir ?? "./src/", root));
|
|
@@ -601,6 +607,54 @@ async function updateAstroConfig({
|
|
|
601
607
|
return 2 /* cancelled */;
|
|
602
608
|
}
|
|
603
609
|
}
|
|
610
|
+
async function updatePackageJsonOverrides({
|
|
611
|
+
configURL,
|
|
612
|
+
flags,
|
|
613
|
+
logger,
|
|
614
|
+
overrides
|
|
615
|
+
}) {
|
|
616
|
+
const pkgURL = new URL("./package.json", configURL);
|
|
617
|
+
if (!existsSync(pkgURL)) {
|
|
618
|
+
logger.debug("add", "No package.json found, skipping overrides update");
|
|
619
|
+
return 0 /* none */;
|
|
620
|
+
}
|
|
621
|
+
const pkgPath = fileURLToPath(pkgURL);
|
|
622
|
+
const input = await fs.readFile(pkgPath, { encoding: "utf-8" });
|
|
623
|
+
const pkgJson = JSON.parse(input);
|
|
624
|
+
pkgJson.overrides ??= {};
|
|
625
|
+
let hasChanges = false;
|
|
626
|
+
for (const [name, range] of Object.entries(overrides)) {
|
|
627
|
+
if (!(name in pkgJson.overrides)) {
|
|
628
|
+
pkgJson.overrides[name] = range;
|
|
629
|
+
hasChanges = true;
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
if (!hasChanges) {
|
|
633
|
+
return 0 /* none */;
|
|
634
|
+
}
|
|
635
|
+
const output = JSON.stringify(pkgJson, null, 2);
|
|
636
|
+
const diff = getDiffContent(input, output);
|
|
637
|
+
if (!diff) {
|
|
638
|
+
return 0 /* none */;
|
|
639
|
+
}
|
|
640
|
+
logger.info(
|
|
641
|
+
"SKIP_FORMAT",
|
|
642
|
+
`
|
|
643
|
+
${magenta("Astro will add the following overrides to your package.json:")}`
|
|
644
|
+
);
|
|
645
|
+
clack.box(diff, "package.json", {
|
|
646
|
+
rounded: true,
|
|
647
|
+
withGuide: false,
|
|
648
|
+
width: "auto"
|
|
649
|
+
});
|
|
650
|
+
if (await askToContinue({ flags, logger })) {
|
|
651
|
+
await fs.writeFile(pkgPath, output, { encoding: "utf-8" });
|
|
652
|
+
logger.debug("add", "Updated package.json overrides");
|
|
653
|
+
return 1 /* updated */;
|
|
654
|
+
} else {
|
|
655
|
+
return 2 /* cancelled */;
|
|
656
|
+
}
|
|
657
|
+
}
|
|
604
658
|
async function updatePackageJsonScripts({
|
|
605
659
|
configURL,
|
|
606
660
|
flags,
|
|
@@ -192,7 +192,7 @@ ${contentConfig.error.message}`
|
|
|
192
192
|
logger.info("Content config changed");
|
|
193
193
|
shouldClear = true;
|
|
194
194
|
}
|
|
195
|
-
if (previousAstroVersion && previousAstroVersion !== "6.0
|
|
195
|
+
if (previousAstroVersion && previousAstroVersion !== "6.1.0") {
|
|
196
196
|
logger.info("Astro version changed");
|
|
197
197
|
shouldClear = true;
|
|
198
198
|
}
|
|
@@ -200,8 +200,8 @@ ${contentConfig.error.message}`
|
|
|
200
200
|
logger.info("Clearing content store");
|
|
201
201
|
this.#store.clearAll();
|
|
202
202
|
}
|
|
203
|
-
if ("6.0
|
|
204
|
-
this.#store.metaStore().set("astro-version", "6.0
|
|
203
|
+
if ("6.1.0") {
|
|
204
|
+
this.#store.metaStore().set("astro-version", "6.1.0");
|
|
205
205
|
}
|
|
206
206
|
if (currentConfigDigest) {
|
|
207
207
|
this.#store.metaStore().set("content-config-digest", currentConfigDigest);
|
package/dist/content/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { attachContentServerListeners } from './server-listeners.js';
|
|
2
2
|
export { createContentTypesGenerator } from './types-generator.js';
|
|
3
|
-
export { getContentPaths
|
|
3
|
+
export { getContentPaths } from './utils.js';
|
|
4
4
|
export { astroContentAssetPropagationPlugin } from './vite-plugin-content-assets.js';
|
|
5
5
|
export { astroContentImportPlugin } from './vite-plugin-content-imports.js';
|
|
6
6
|
export { astroContentVirtualModPlugin } from './vite-plugin-content-virtual-mod.js';
|
package/dist/content/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { attachContentServerListeners } from "./server-listeners.js";
|
|
2
2
|
import { createContentTypesGenerator } from "./types-generator.js";
|
|
3
|
-
import { getContentPaths
|
|
3
|
+
import { getContentPaths } from "./utils.js";
|
|
4
4
|
import { astroContentAssetPropagationPlugin } from "./vite-plugin-content-assets.js";
|
|
5
5
|
import { astroContentImportPlugin } from "./vite-plugin-content-imports.js";
|
|
6
6
|
import { astroContentVirtualModPlugin } from "./vite-plugin-content-virtual-mod.js";
|
|
@@ -10,6 +10,5 @@ export {
|
|
|
10
10
|
astroContentVirtualModPlugin,
|
|
11
11
|
attachContentServerListeners,
|
|
12
12
|
createContentTypesGenerator,
|
|
13
|
-
getContentPaths
|
|
14
|
-
hasAssetPropagationFlag
|
|
13
|
+
getContentPaths
|
|
15
14
|
};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { MarkdownHeading } from '@astrojs/markdown-remark';
|
|
2
2
|
import * as z from 'zod/v4';
|
|
3
3
|
import type * as zCore from 'zod/v4/core';
|
|
4
|
+
import type { ImageMetadata } from '../assets/types.js';
|
|
4
5
|
import { type AstroComponentFactory } from '../runtime/server/index.js';
|
|
5
6
|
import type { LiveDataCollectionResult, LiveDataEntryResult } from '../types/public/content.js';
|
|
6
7
|
import { type LIVE_CONTENT_TYPE } from './consts.js';
|
|
@@ -67,6 +68,7 @@ type RenderResult = {
|
|
|
67
68
|
headings: MarkdownHeading[];
|
|
68
69
|
remarkPluginFrontmatter: Record<string, any>;
|
|
69
70
|
};
|
|
71
|
+
export declare function updateImageReferencesInData<T extends Record<string, unknown>>(data: T, fileName?: string, imageAssetMap?: Map<string, ImageMetadata>): T;
|
|
70
72
|
export declare function renderEntry(entry: DataEntry): Promise<RenderResult>;
|
|
71
73
|
export declare function createReference(): (collection: string) => z.ZodPipe<z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
|
|
72
74
|
id: z.ZodString;
|