astro 5.12.2 → 5.12.4

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.
@@ -3,9 +3,9 @@
3
3
  object-position: var(--pos);
4
4
  height: auto;
5
5
  }
6
- :where([data-astro-image='full-width']) {
6
+ :where([data-astro-image="full-width"]) {
7
7
  width: 100%;
8
8
  }
9
- :where([data-astro-image='constrained']) {
9
+ :where([data-astro-image="constrained"]) {
10
10
  max-width: 100%;
11
11
  }
@@ -5,7 +5,7 @@ export type RemoteCacheEntry = {
5
5
  lastModified?: string;
6
6
  };
7
7
  export declare function loadRemoteImage(src: string): Promise<{
8
- data: Buffer;
8
+ data: Buffer<ArrayBuffer>;
9
9
  expires: number;
10
10
  etag: string | undefined;
11
11
  lastModified: string | undefined;
@@ -23,7 +23,7 @@ export declare function revalidateRemoteImage(src: string, revalidationData: {
23
23
  etag?: string;
24
24
  lastModified?: string;
25
25
  }): Promise<{
26
- data: Buffer;
26
+ data: Buffer<ArrayBuffer>;
27
27
  expires: number;
28
28
  etag: string | undefined;
29
29
  lastModified: string | undefined;
@@ -16,7 +16,7 @@ export declare const fontProviderSchema: z.ZodObject<{
16
16
  entrypoint: string | URL;
17
17
  config?: Record<string, any> | undefined;
18
18
  }>;
19
- export declare const localFontFamilySchema: z.ZodObject<z.objectUtil.extendShape<z.objectUtil.extendShape<{
19
+ export declare const localFontFamilySchema: z.ZodObject<{
20
20
  /**
21
21
  * The font family name, as identified by your font provider.
22
22
  */
@@ -25,7 +25,7 @@ export declare const localFontFamilySchema: z.ZodObject<z.objectUtil.extendShape
25
25
  * A valid [ident](https://developer.mozilla.org/en-US/docs/Web/CSS/ident) in the form of a CSS variable (i.e. starting with `--`).
26
26
  */
27
27
  cssVariable: z.ZodString;
28
- }, {
28
+ } & {
29
29
  /**
30
30
  * @default `["sans-serif"]`
31
31
  *
@@ -51,7 +51,7 @@ export declare const localFontFamilySchema: z.ZodObject<z.objectUtil.extendShape
51
51
  * Whether or not to enable optimized fallback generation. You may disable this default optimization to have full control over `fallbacks`.
52
52
  */
53
53
  optimizedFallbacks: z.ZodOptional<z.ZodBoolean>;
54
- }>, {
54
+ } & {
55
55
  /**
56
56
  * The source of your font files. Set to `"local"` to use local font files.
57
57
  */
@@ -59,7 +59,7 @@ export declare const localFontFamilySchema: z.ZodObject<z.objectUtil.extendShape
59
59
  /**
60
60
  * Each variant represents a [`@font-face` declaration](https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/).
61
61
  */
62
- variants: z.ZodArray<z.ZodObject<z.objectUtil.extendShape<{
62
+ variants: z.ZodArray<z.ZodObject<{
63
63
  /**
64
64
  * A [font weight](https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight). If the associated font is a [variable font](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_fonts/Variable_fonts_guide), you can specify a range of weights:
65
65
  *
@@ -90,7 +90,7 @@ export declare const localFontFamilySchema: z.ZodObject<z.objectUtil.extendShape
90
90
  * Font [variation settings](https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-variation-settings).
91
91
  */
92
92
  variationSettings: z.ZodOptional<z.ZodString>;
93
- }, {
93
+ } & {
94
94
  /**
95
95
  * Font [sources](https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/src). It can be a path relative to the root, a package import or a URL. URLs are particularly useful if you inject local fonts through an integration.
96
96
  */
@@ -108,7 +108,7 @@ export declare const localFontFamilySchema: z.ZodObject<z.objectUtil.extendShape
108
108
  * A [unicode range](https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/unicode-range).
109
109
  */
110
110
  unicodeRange: z.ZodOptional<z.ZodArray<z.ZodString, "atleastone">>;
111
- }>, "strict", z.ZodTypeAny, {
111
+ }, "strict", z.ZodTypeAny, {
112
112
  src: [string | URL | {
113
113
  url: string | URL;
114
114
  tech?: string | undefined;
@@ -139,7 +139,7 @@ export declare const localFontFamilySchema: z.ZodObject<z.objectUtil.extendShape
139
139
  variationSettings?: string | undefined;
140
140
  unicodeRange?: [string, ...string[]] | undefined;
141
141
  }>, "atleastone">;
142
- }>, "strict", z.ZodTypeAny, {
142
+ }, "strict", z.ZodTypeAny, {
143
143
  name: string;
144
144
  cssVariable: string;
145
145
  provider: "local";
@@ -214,7 +214,7 @@ export declare const localFontFamilySchema: z.ZodObject<z.objectUtil.extendShape
214
214
  fallbacks?: string[] | undefined;
215
215
  optimizedFallbacks?: boolean | undefined;
216
216
  }>;
217
- export declare const remoteFontFamilySchema: z.ZodObject<z.objectUtil.extendShape<z.objectUtil.extendShape<z.objectUtil.extendShape<{
217
+ export declare const remoteFontFamilySchema: z.ZodObject<{
218
218
  /**
219
219
  * The font family name, as identified by your font provider.
220
220
  */
@@ -223,7 +223,7 @@ export declare const remoteFontFamilySchema: z.ZodObject<z.objectUtil.extendShap
223
223
  * A valid [ident](https://developer.mozilla.org/en-US/docs/Web/CSS/ident) in the form of a CSS variable (i.e. starting with `--`).
224
224
  */
225
225
  cssVariable: z.ZodString;
226
- }, Omit<{
226
+ } & Omit<{
227
227
  /**
228
228
  * A [font weight](https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight). If the associated font is a [variable font](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_fonts/Variable_fonts_guide), you can specify a range of weights:
229
229
  *
@@ -254,7 +254,7 @@ export declare const remoteFontFamilySchema: z.ZodObject<z.objectUtil.extendShap
254
254
  * Font [variation settings](https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-variation-settings).
255
255
  */
256
256
  variationSettings: z.ZodOptional<z.ZodString>;
257
- }, "weight" | "style">>, {
257
+ }, "weight" | "style"> & {
258
258
  /**
259
259
  * @default `["sans-serif"]`
260
260
  *
@@ -280,7 +280,7 @@ export declare const remoteFontFamilySchema: z.ZodObject<z.objectUtil.extendShap
280
280
  * Whether or not to enable optimized fallback generation. You may disable this default optimization to have full control over `fallbacks`.
281
281
  */
282
282
  optimizedFallbacks: z.ZodOptional<z.ZodBoolean>;
283
- }>, {
283
+ } & {
284
284
  /**
285
285
  * The source of your font files. You can use a built-in provider or write your own custom provider.
286
286
  */
@@ -326,7 +326,7 @@ export declare const remoteFontFamilySchema: z.ZodObject<z.objectUtil.extendShap
326
326
  * A [unicode range](https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/unicode-range).
327
327
  */
328
328
  unicodeRange: z.ZodOptional<z.ZodArray<z.ZodString, "atleastone">>;
329
- }>, "strict", z.ZodTypeAny, {
329
+ }, "strict", z.ZodTypeAny, {
330
330
  name: string;
331
331
  cssVariable: string;
332
332
  provider: {
@@ -57,14 +57,12 @@ async function getImage(options, imageConfig) {
57
57
  };
58
58
  let originalWidth;
59
59
  let originalHeight;
60
- let originalFormat;
61
60
  if (options.inferSize && isRemoteImage(resolvedOptions.src) && isRemotePath(resolvedOptions.src)) {
62
61
  const result = await inferRemoteSize(resolvedOptions.src);
63
62
  resolvedOptions.width ??= result.width;
64
63
  resolvedOptions.height ??= result.height;
65
64
  originalWidth = result.width;
66
65
  originalHeight = result.height;
67
- originalFormat = result.format;
68
66
  delete resolvedOptions.inferSize;
69
67
  }
70
68
  const originalFilePath = isESMImportedImage(resolvedOptions.src) ? resolvedOptions.src.fsPath : void 0;
@@ -75,7 +73,6 @@ async function getImage(options, imageConfig) {
75
73
  if (isESMImportedImage(clonedSrc)) {
76
74
  originalWidth = clonedSrc.width;
77
75
  originalHeight = clonedSrc.height;
78
- originalFormat = clonedSrc.format;
79
76
  }
80
77
  if (originalWidth && originalHeight) {
81
78
  const aspectRatio = originalWidth / originalHeight;
@@ -121,12 +118,12 @@ async function getImage(options, imageConfig) {
121
118
  const validatedOptions = service.validateOptions ? await service.validateOptions(resolvedOptions, imageConfig) : resolvedOptions;
122
119
  const srcSetTransforms = service.getSrcSet ? await service.getSrcSet(validatedOptions, imageConfig) : [];
123
120
  let imageURL = await service.getURL(validatedOptions, imageConfig);
124
- const matchesOriginal = (transform) => transform.width === originalWidth && transform.height === originalHeight && transform.format === originalFormat;
121
+ const matchesValidatedTransform = (transform) => transform.width === validatedOptions.width && transform.height === validatedOptions.height && transform.format === validatedOptions.format;
125
122
  let srcSets = await Promise.all(
126
123
  srcSetTransforms.map(async (srcSet) => {
127
124
  return {
128
125
  transform: srcSet.transform,
129
- url: matchesOriginal(srcSet.transform) ? imageURL : await service.getURL(srcSet.transform, imageConfig),
126
+ url: matchesValidatedTransform(srcSet.transform) ? imageURL : await service.getURL(srcSet.transform, imageConfig),
130
127
  descriptor: srcSet.descriptor,
131
128
  attributes: srcSet.attributes
132
129
  };
@@ -142,7 +139,7 @@ async function getImage(options, imageConfig) {
142
139
  srcSets = srcSetTransforms.map((srcSet) => {
143
140
  return {
144
141
  transform: srcSet.transform,
145
- url: matchesOriginal(srcSet.transform) ? imageURL : globalThis.astroAsset.addStaticImage(srcSet.transform, propsToHash, originalFilePath),
142
+ url: matchesValidatedTransform(srcSet.transform) ? imageURL : globalThis.astroAsset.addStaticImage(srcSet.transform, propsToHash, originalFilePath),
146
143
  descriptor: srcSet.descriptor,
147
144
  attributes: srcSet.attributes
148
145
  };
@@ -1,8 +1,35 @@
1
1
  import fs from "node:fs/promises";
2
2
  import path from "node:path";
3
3
  import { fileURLToPath, pathToFileURL } from "node:url";
4
+ import { generateContentHash } from "../../../core/encryption.js";
4
5
  import { prependForwardSlash, slash } from "../../../core/path.js";
5
6
  import { imageMetadata } from "../metadata.js";
7
+ const svgContentCache = /* @__PURE__ */ new WeakMap();
8
+ const keyRegistry = /* @__PURE__ */ new Map();
9
+ function keyFor(hash) {
10
+ let key = keyRegistry.get(hash);
11
+ if (!key) {
12
+ key = { hash };
13
+ keyRegistry.set(hash, key);
14
+ }
15
+ return key;
16
+ }
17
+ async function handleSvgDeduplication(fileData, filename, fileEmitter) {
18
+ const contentHash = await generateContentHash(fileData);
19
+ const key = keyFor(contentHash);
20
+ const existing = svgContentCache.get(key);
21
+ if (existing) {
22
+ return existing.handle;
23
+ } else {
24
+ const handle = fileEmitter({
25
+ name: filename,
26
+ source: fileData,
27
+ type: "asset"
28
+ });
29
+ svgContentCache.set(key, { handle, filename });
30
+ return handle;
31
+ }
32
+ }
6
33
  async function emitESMImage(id, _watchMode, _experimentalSvgEnabled, fileEmitter) {
7
34
  if (!id) {
8
35
  return void 0;
@@ -29,11 +56,16 @@ async function emitESMImage(id, _watchMode, _experimentalSvgEnabled, fileEmitter
29
56
  const pathname = decodeURI(url.pathname);
30
57
  const filename = path.basename(pathname, path.extname(pathname) + `.${fileMetadata.format}`);
31
58
  try {
32
- const handle = fileEmitter({
33
- name: filename,
34
- source: await fs.readFile(url),
35
- type: "asset"
36
- });
59
+ let handle;
60
+ if (fileMetadata.format === "svg") {
61
+ handle = await handleSvgDeduplication(fileData, filename, fileEmitter);
62
+ } else {
63
+ handle = fileEmitter({
64
+ name: filename,
65
+ source: fileData,
66
+ type: "asset"
67
+ });
68
+ }
37
69
  emittedImage.src = `__ASTRO_ASSET_IMAGE__${handle}__`;
38
70
  } catch {
39
71
  isBuild = false;
@@ -73,11 +105,16 @@ async function emitImageMetadata(id, fileEmitter) {
73
105
  const pathname = decodeURI(url.pathname);
74
106
  const filename = path.basename(pathname, path.extname(pathname) + `.${fileMetadata.format}`);
75
107
  try {
76
- const handle = fileEmitter({
77
- name: filename,
78
- source: await fs.readFile(url),
79
- type: "asset"
80
- });
108
+ let handle;
109
+ if (fileMetadata.format === "svg") {
110
+ handle = await handleSvgDeduplication(fileData, filename, fileEmitter);
111
+ } else {
112
+ handle = fileEmitter({
113
+ name: filename,
114
+ source: fileData,
115
+ type: "asset"
116
+ });
117
+ }
81
118
  emittedImage.src = `__ASTRO_ASSET_IMAGE__${handle}__`;
82
119
  } catch {
83
120
  isBuild = false;
@@ -164,7 +164,7 @@ ${contentConfig.error.message}`);
164
164
  logger.info("Content config changed");
165
165
  shouldClear = true;
166
166
  }
167
- if (previousAstroVersion && previousAstroVersion !== "5.12.2") {
167
+ if (previousAstroVersion && previousAstroVersion !== "5.12.4") {
168
168
  logger.info("Astro version changed");
169
169
  shouldClear = true;
170
170
  }
@@ -172,8 +172,8 @@ ${contentConfig.error.message}`);
172
172
  logger.info("Clearing content store");
173
173
  this.#store.clearAll();
174
174
  }
175
- if ("5.12.2") {
176
- await this.#store.metaStore().set("astro-version", "5.12.2");
175
+ if ("5.12.4") {
176
+ await this.#store.metaStore().set("astro-version", "5.12.4");
177
177
  }
178
178
  if (currentConfigDigest) {
179
179
  await this.#store.metaStore().set("content-config-digest", currentConfigDigest);
@@ -729,22 +729,22 @@ export declare const AstroConfigSchema: z.ZodObject<{
729
729
  contentIntellisense: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
730
730
  headingIdCompat: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
731
731
  preserveScriptOrder: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
732
- fonts: z.ZodOptional<z.ZodArray<z.ZodUnion<[z.ZodObject<z.objectUtil.extendShape<z.objectUtil.extendShape<{
732
+ fonts: z.ZodOptional<z.ZodArray<z.ZodUnion<[z.ZodObject<{
733
733
  name: z.ZodString;
734
734
  cssVariable: z.ZodString;
735
- }, {
735
+ } & {
736
736
  fallbacks: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
737
737
  optimizedFallbacks: z.ZodOptional<z.ZodBoolean>;
738
- }>, {
738
+ } & {
739
739
  provider: z.ZodLiteral<"local">;
740
- variants: z.ZodArray<z.ZodObject<z.objectUtil.extendShape<{
740
+ variants: z.ZodArray<z.ZodObject<{
741
741
  weight: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodNumber]>>;
742
742
  style: z.ZodOptional<z.ZodEnum<["normal", "italic", "oblique"]>>;
743
743
  display: z.ZodOptional<z.ZodEnum<["auto", "block", "swap", "fallback", "optional"]>>;
744
744
  stretch: z.ZodOptional<z.ZodString>;
745
745
  featureSettings: z.ZodOptional<z.ZodString>;
746
746
  variationSettings: z.ZodOptional<z.ZodString>;
747
- }, {
747
+ } & {
748
748
  src: z.ZodArray<z.ZodUnion<[z.ZodUnion<[z.ZodString, z.ZodType<URL, z.ZodTypeDef, URL>]>, z.ZodObject<{
749
749
  url: z.ZodUnion<[z.ZodString, z.ZodType<URL, z.ZodTypeDef, URL>]>;
750
750
  tech: z.ZodOptional<z.ZodString>;
@@ -756,7 +756,7 @@ export declare const AstroConfigSchema: z.ZodObject<{
756
756
  tech?: string | undefined;
757
757
  }>]>, "atleastone">;
758
758
  unicodeRange: z.ZodOptional<z.ZodArray<z.ZodString, "atleastone">>;
759
- }>, "strict", z.ZodTypeAny, {
759
+ }, "strict", z.ZodTypeAny, {
760
760
  src: [string | URL | {
761
761
  url: string | URL;
762
762
  tech?: string | undefined;
@@ -787,7 +787,7 @@ export declare const AstroConfigSchema: z.ZodObject<{
787
787
  variationSettings?: string | undefined;
788
788
  unicodeRange?: [string, ...string[]] | undefined;
789
789
  }>, "atleastone">;
790
- }>, "strict", z.ZodTypeAny, {
790
+ }, "strict", z.ZodTypeAny, {
791
791
  name: string;
792
792
  cssVariable: string;
793
793
  provider: "local";
@@ -861,20 +861,20 @@ export declare const AstroConfigSchema: z.ZodObject<{
861
861
  }[]];
862
862
  fallbacks?: string[] | undefined;
863
863
  optimizedFallbacks?: boolean | undefined;
864
- }>, z.ZodObject<z.objectUtil.extendShape<z.objectUtil.extendShape<z.objectUtil.extendShape<{
864
+ }>, z.ZodObject<{
865
865
  name: z.ZodString;
866
866
  cssVariable: z.ZodString;
867
- }, Omit<{
867
+ } & Omit<{
868
868
  weight: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodNumber]>>;
869
869
  style: z.ZodOptional<z.ZodEnum<["normal", "italic", "oblique"]>>;
870
870
  display: z.ZodOptional<z.ZodEnum<["auto", "block", "swap", "fallback", "optional"]>>;
871
871
  stretch: z.ZodOptional<z.ZodString>;
872
872
  featureSettings: z.ZodOptional<z.ZodString>;
873
873
  variationSettings: z.ZodOptional<z.ZodString>;
874
- }, "weight" | "style">>, {
874
+ }, "weight" | "style"> & {
875
875
  fallbacks: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
876
876
  optimizedFallbacks: z.ZodOptional<z.ZodBoolean>;
877
- }>, {
877
+ } & {
878
878
  provider: z.ZodObject<{
879
879
  entrypoint: z.ZodUnion<[z.ZodString, z.ZodType<URL, z.ZodTypeDef, URL>]>;
880
880
  config: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodAny>>;
@@ -889,7 +889,7 @@ export declare const AstroConfigSchema: z.ZodObject<{
889
889
  styles: z.ZodOptional<z.ZodArray<z.ZodEnum<["normal", "italic", "oblique"]>, "atleastone">>;
890
890
  subsets: z.ZodOptional<z.ZodArray<z.ZodString, "atleastone">>;
891
891
  unicodeRange: z.ZodOptional<z.ZodArray<z.ZodString, "atleastone">>;
892
- }>, "strict", z.ZodTypeAny, {
892
+ }, "strict", z.ZodTypeAny, {
893
893
  name: string;
894
894
  cssVariable: string;
895
895
  provider: {
@@ -1,13 +1,7 @@
1
1
  import type { OutgoingHttpHeaders } from 'node:http';
2
2
  import { z } from 'zod';
3
- export declare function createRelativeSchema(cmd: string, fileProtocolRoot: string): z.ZodEffects<z.ZodObject<z.objectUtil.extendShape<{
4
- root: z.ZodEffects<z.ZodDefault<z.ZodOptional<z.ZodString>>, URL, string | undefined>;
5
- srcDir: z.ZodEffects<z.ZodDefault<z.ZodOptional<z.ZodString>>, URL, string | undefined>;
6
- publicDir: z.ZodEffects<z.ZodDefault<z.ZodOptional<z.ZodString>>, URL, string | undefined>;
7
- outDir: z.ZodEffects<z.ZodDefault<z.ZodOptional<z.ZodString>>, URL, string | undefined>;
8
- cacheDir: z.ZodEffects<z.ZodDefault<z.ZodOptional<z.ZodString>>, URL, string | undefined>;
3
+ export declare function createRelativeSchema(cmd: string, fileProtocolRoot: string): z.ZodEffects<z.ZodObject<{
9
4
  site: z.ZodOptional<z.ZodString>;
10
- compressHTML: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
11
5
  base: z.ZodDefault<z.ZodOptional<z.ZodString>>;
12
6
  trailingSlash: z.ZodDefault<z.ZodOptional<z.ZodUnion<[z.ZodLiteral<"always">, z.ZodLiteral<"never">, z.ZodLiteral<"ignore">]>>>;
13
7
  output: z.ZodDefault<z.ZodOptional<z.ZodUnion<[z.ZodLiteral<"static">, z.ZodLiteral<"server">]>>>;
@@ -41,72 +35,6 @@ export declare function createRelativeSchema(cmd: string, fileProtocolRoot: stri
41
35
  [k: string]: unknown;
42
36
  };
43
37
  }[], unknown>;
44
- build: z.ZodDefault<z.ZodObject<{
45
- format: z.ZodDefault<z.ZodOptional<z.ZodUnion<[z.ZodLiteral<"file">, z.ZodLiteral<"directory">, z.ZodLiteral<"preserve">]>>>;
46
- client: z.ZodEffects<z.ZodDefault<z.ZodOptional<z.ZodString>>, URL, string | undefined>;
47
- server: z.ZodEffects<z.ZodDefault<z.ZodOptional<z.ZodString>>, URL, string | undefined>;
48
- assets: z.ZodDefault<z.ZodOptional<z.ZodString>>;
49
- assetsPrefix: z.ZodUnion<[z.ZodOptional<z.ZodString>, z.ZodOptional<z.ZodIntersection<z.ZodObject<{
50
- fallback: z.ZodString;
51
- }, "strip", z.ZodTypeAny, {
52
- fallback: string;
53
- }, {
54
- fallback: string;
55
- }>, z.ZodRecord<z.ZodString, z.ZodString>>>]>;
56
- serverEntry: z.ZodDefault<z.ZodOptional<z.ZodString>>;
57
- redirects: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
58
- inlineStylesheets: z.ZodDefault<z.ZodOptional<z.ZodEnum<["always", "auto", "never"]>>>;
59
- concurrency: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
60
- }, "strip", z.ZodTypeAny, {
61
- redirects: boolean;
62
- assets: string;
63
- format: "preserve" | "file" | "directory";
64
- client: URL;
65
- server: URL;
66
- serverEntry: string;
67
- inlineStylesheets: "auto" | "never" | "always";
68
- concurrency: number;
69
- assetsPrefix?: string | ({
70
- fallback: string;
71
- } & Record<string, string>) | undefined;
72
- }, {
73
- redirects?: boolean | undefined;
74
- assets?: string | undefined;
75
- format?: "preserve" | "file" | "directory" | undefined;
76
- client?: string | undefined;
77
- server?: string | undefined;
78
- serverEntry?: string | undefined;
79
- inlineStylesheets?: "auto" | "never" | "always" | undefined;
80
- concurrency?: number | undefined;
81
- assetsPrefix?: string | ({
82
- fallback: string;
83
- } & Record<string, string>) | undefined;
84
- }>>;
85
- server: z.ZodEffects<z.ZodDefault<z.ZodObject<{
86
- open: z.ZodDefault<z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodBoolean]>>>;
87
- host: z.ZodDefault<z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodBoolean]>>>;
88
- port: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
89
- headers: z.ZodOptional<z.ZodType<OutgoingHttpHeaders, z.ZodTypeDef, OutgoingHttpHeaders>>;
90
- allowedHosts: z.ZodDefault<z.ZodOptional<z.ZodUnion<[z.ZodArray<z.ZodString, "many">, z.ZodLiteral<true>]>>>;
91
- }, "strip", z.ZodTypeAny, {
92
- host: string | boolean;
93
- port: number;
94
- allowedHosts: true | string[];
95
- open: string | boolean;
96
- headers?: OutgoingHttpHeaders | undefined;
97
- }, {
98
- host?: string | boolean | undefined;
99
- port?: number | undefined;
100
- allowedHosts?: true | string[] | undefined;
101
- headers?: OutgoingHttpHeaders | undefined;
102
- open?: string | boolean | undefined;
103
- }>>, {
104
- host: string | boolean;
105
- port: number;
106
- allowedHosts: true | string[];
107
- open: string | boolean;
108
- headers?: OutgoingHttpHeaders | undefined;
109
- }, unknown>;
110
38
  redirects: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnion<[z.ZodString, z.ZodObject<{
111
39
  status: z.ZodUnion<[z.ZodLiteral<300>, z.ZodLiteral<301>, z.ZodLiteral<302>, z.ZodLiteral<303>, z.ZodLiteral<304>, z.ZodLiteral<307>, z.ZodLiteral<308>]>;
112
40
  destination: z.ZodString;
@@ -651,22 +579,22 @@ export declare function createRelativeSchema(cmd: string, fileProtocolRoot: stri
651
579
  contentIntellisense: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
652
580
  headingIdCompat: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
653
581
  preserveScriptOrder: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
654
- fonts: z.ZodOptional<z.ZodArray<z.ZodUnion<[z.ZodObject<z.objectUtil.extendShape<z.objectUtil.extendShape<{
582
+ fonts: z.ZodOptional<z.ZodArray<z.ZodUnion<[z.ZodObject<{
655
583
  name: z.ZodString;
656
584
  cssVariable: z.ZodString;
657
- }, {
585
+ } & {
658
586
  fallbacks: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
659
587
  optimizedFallbacks: z.ZodOptional<z.ZodBoolean>;
660
- }>, {
588
+ } & {
661
589
  provider: z.ZodLiteral<"local">;
662
- variants: z.ZodArray<z.ZodObject<z.objectUtil.extendShape<{
590
+ variants: z.ZodArray<z.ZodObject<{
663
591
  weight: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodNumber]>>;
664
592
  style: z.ZodOptional<z.ZodEnum<["normal", "italic", "oblique"]>>;
665
593
  display: z.ZodOptional<z.ZodEnum<["auto", "block", "swap", "fallback", "optional"]>>;
666
594
  stretch: z.ZodOptional<z.ZodString>;
667
595
  featureSettings: z.ZodOptional<z.ZodString>;
668
596
  variationSettings: z.ZodOptional<z.ZodString>;
669
- }, {
597
+ } & {
670
598
  src: z.ZodArray<z.ZodUnion<[z.ZodUnion<[z.ZodString, z.ZodType<URL, z.ZodTypeDef, URL>]>, z.ZodObject<{
671
599
  url: z.ZodUnion<[z.ZodString, z.ZodType<URL, z.ZodTypeDef, URL>]>;
672
600
  tech: z.ZodOptional<z.ZodString>;
@@ -678,7 +606,7 @@ export declare function createRelativeSchema(cmd: string, fileProtocolRoot: stri
678
606
  tech?: string | undefined;
679
607
  }>]>, "atleastone">;
680
608
  unicodeRange: z.ZodOptional<z.ZodArray<z.ZodString, "atleastone">>;
681
- }>, "strict", z.ZodTypeAny, {
609
+ }, "strict", z.ZodTypeAny, {
682
610
  src: [string | URL | {
683
611
  url: string | URL;
684
612
  tech?: string | undefined;
@@ -709,7 +637,7 @@ export declare function createRelativeSchema(cmd: string, fileProtocolRoot: stri
709
637
  variationSettings?: string | undefined;
710
638
  unicodeRange?: [string, ...string[]] | undefined;
711
639
  }>, "atleastone">;
712
- }>, "strict", z.ZodTypeAny, {
640
+ }, "strict", z.ZodTypeAny, {
713
641
  name: string;
714
642
  cssVariable: string;
715
643
  provider: "local";
@@ -783,20 +711,20 @@ export declare function createRelativeSchema(cmd: string, fileProtocolRoot: stri
783
711
  }[]];
784
712
  fallbacks?: string[] | undefined;
785
713
  optimizedFallbacks?: boolean | undefined;
786
- }>, z.ZodObject<z.objectUtil.extendShape<z.objectUtil.extendShape<z.objectUtil.extendShape<{
714
+ }>, z.ZodObject<{
787
715
  name: z.ZodString;
788
716
  cssVariable: z.ZodString;
789
- }, Omit<{
717
+ } & Omit<{
790
718
  weight: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodNumber]>>;
791
719
  style: z.ZodOptional<z.ZodEnum<["normal", "italic", "oblique"]>>;
792
720
  display: z.ZodOptional<z.ZodEnum<["auto", "block", "swap", "fallback", "optional"]>>;
793
721
  stretch: z.ZodOptional<z.ZodString>;
794
722
  featureSettings: z.ZodOptional<z.ZodString>;
795
723
  variationSettings: z.ZodOptional<z.ZodString>;
796
- }, "weight" | "style">>, {
724
+ }, "weight" | "style"> & {
797
725
  fallbacks: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
798
726
  optimizedFallbacks: z.ZodOptional<z.ZodBoolean>;
799
- }>, {
727
+ } & {
800
728
  provider: z.ZodObject<{
801
729
  entrypoint: z.ZodUnion<[z.ZodString, z.ZodType<URL, z.ZodTypeDef, URL>]>;
802
730
  config: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodAny>>;
@@ -811,7 +739,7 @@ export declare function createRelativeSchema(cmd: string, fileProtocolRoot: stri
811
739
  styles: z.ZodOptional<z.ZodArray<z.ZodEnum<["normal", "italic", "oblique"]>, "atleastone">>;
812
740
  subsets: z.ZodOptional<z.ZodArray<z.ZodString, "atleastone">>;
813
741
  unicodeRange: z.ZodOptional<z.ZodArray<z.ZodString, "atleastone">>;
814
- }>, "strict", z.ZodTypeAny, {
742
+ }, "strict", z.ZodTypeAny, {
815
743
  name: string;
816
744
  cssVariable: string;
817
745
  provider: {
@@ -1057,7 +985,7 @@ export declare function createRelativeSchema(cmd: string, fileProtocolRoot: stri
1057
985
  }, {
1058
986
  collections?: boolean | undefined;
1059
987
  }>>;
1060
- }, {
988
+ } & {
1061
989
  root: z.ZodEffects<z.ZodDefault<z.ZodString>, import("url").URL, string | undefined>;
1062
990
  srcDir: z.ZodEffects<z.ZodDefault<z.ZodString>, import("url").URL, string | undefined>;
1063
991
  compressHTML: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
@@ -1134,7 +1062,7 @@ export declare function createRelativeSchema(cmd: string, fileProtocolRoot: stri
1134
1062
  streaming: boolean;
1135
1063
  headers?: OutgoingHttpHeaders | undefined;
1136
1064
  }, unknown>;
1137
- }>, "strip", z.ZodTypeAny, {
1065
+ }, "strip", z.ZodTypeAny, {
1138
1066
  outDir: import("url").URL;
1139
1067
  root: import("url").URL;
1140
1068
  build: {
@@ -1,4 +1,4 @@
1
- const ASTRO_VERSION = "5.12.2";
1
+ const ASTRO_VERSION = "5.12.4";
2
2
  const REROUTE_DIRECTIVE_HEADER = "X-Astro-Reroute";
3
3
  const REWRITE_DIRECTIVE_HEADER_KEY = "X-Astro-Rewrite";
4
4
  const REWRITE_DIRECTIVE_HEADER_VALUE = "yes";
@@ -22,7 +22,7 @@ async function dev(inlineConfig) {
22
22
  await telemetry.record([]);
23
23
  const restart = await createContainerWithAutomaticRestart({ inlineConfig, fs });
24
24
  const logger = restart.container.logger;
25
- const currentVersion = "5.12.2";
25
+ const currentVersion = "5.12.4";
26
26
  const isPrerelease = currentVersion.includes("-");
27
27
  if (!isPrerelease) {
28
28
  try {
@@ -34,3 +34,9 @@ export declare function decryptString(key: CryptoKey, encoded: string): Promise<
34
34
  * @param {CspAlgorithm} algorithm The algorithm to use.
35
35
  */
36
36
  export declare function generateCspDigest(data: string, algorithm: CspAlgorithm): Promise<CspHash>;
37
+ /**
38
+ * Generate SHA-256 hash of buffer.
39
+ * @param {ArrayBuffer} data The buffer data to hash
40
+ * @returns {Promise<string>} A hex string of the first 16 characters of the SHA-256 hash
41
+ */
42
+ export declare function generateContentHash(data: ArrayBuffer): Promise<string>;
@@ -72,12 +72,18 @@ async function generateCspDigest(data, algorithm) {
72
72
  const hash = encodeBase64(new Uint8Array(hashBuffer));
73
73
  return `${ALGORITHMS[algorithm]}${hash}`;
74
74
  }
75
+ async function generateContentHash(data) {
76
+ const hashBuffer = await crypto.subtle.digest("SHA-256", data);
77
+ const hashArray = new Uint8Array(hashBuffer);
78
+ return encodeBase64(hashArray);
79
+ }
75
80
  export {
76
81
  createKey,
77
82
  decodeKey,
78
83
  decryptString,
79
84
  encodeKey,
80
85
  encryptString,
86
+ generateContentHash,
81
87
  generateCspDigest,
82
88
  getEnvironmentKey,
83
89
  hasEnvironmentKey
@@ -37,7 +37,7 @@ function serverStart({
37
37
  host,
38
38
  base
39
39
  }) {
40
- const version = "5.12.2";
40
+ const version = "5.12.4";
41
41
  const localPrefix = `${dim("\u2503")} Local `;
42
42
  const networkPrefix = `${dim("\u2503")} Network `;
43
43
  const emptyPrefix = " ".repeat(11);
@@ -274,7 +274,7 @@ function printHelp({
274
274
  message.push(
275
275
  linebreak(),
276
276
  ` ${bgGreen(black(` ${commandName} `))} ${green(
277
- `v${"5.12.2"}`
277
+ `v${"5.12.4"}`
278
278
  )} ${headline}`
279
279
  );
280
280
  }
@@ -54,6 +54,7 @@ function sequence(...handlers) {
54
54
  handleContext.url = new URL(newRequest.url);
55
55
  handleContext.cookies = new AstroCookies(newRequest);
56
56
  handleContext.params = getParams(routeData, pathname);
57
+ handleContext.routePattern = routeData.route;
57
58
  setOriginPathname(
58
59
  handleContext.request,
59
60
  oldPathname,
@@ -1,4 +1,4 @@
1
1
  import type { Plugin as VitePlugin } from 'vite';
2
2
  import type { AstroPluginOptions } from '../../types/astro.js';
3
3
  export declare const VIRTUAL_ISLAND_MAP_ID = "@astro-server-islands";
4
- export declare function vitePluginServerIslands({ settings, logger }: AstroPluginOptions): VitePlugin;
4
+ export declare function vitePluginServerIslands({ settings }: AstroPluginOptions): VitePlugin;
@@ -1,8 +1,9 @@
1
1
  import MagicString from "magic-string";
2
+ import { AstroError, AstroErrorData } from "../errors/index.js";
2
3
  const VIRTUAL_ISLAND_MAP_ID = "@astro-server-islands";
3
4
  const RESOLVED_VIRTUAL_ISLAND_MAP_ID = "\0" + VIRTUAL_ISLAND_MAP_ID;
4
5
  const serverIslandPlaceholder = "'$$server-islands$$'";
5
- function vitePluginServerIslands({ settings, logger }) {
6
+ function vitePluginServerIslands({ settings }) {
6
7
  let command = "serve";
7
8
  let viteServer = null;
8
9
  const referenceIdMap = /* @__PURE__ */ new Map();
@@ -32,10 +33,7 @@ function vitePluginServerIslands({ settings, logger }) {
32
33
  for (const comp of astro.serverComponents) {
33
34
  if (!settings.serverIslandNameMap.has(comp.resolvedPath)) {
34
35
  if (!settings.adapter) {
35
- logger.error(
36
- "islands",
37
- "You tried to render a server island without an adapter added to your project. An adapter is required to use the `server:defer` attribute on any component. Your project will fail to build unless you add an adapter or remove the attribute."
38
- );
36
+ throw new AstroError(AstroErrorData.NoAdapterInstalledServerIslands);
39
37
  }
40
38
  let name = comp.localName;
41
39
  let idx = 1;
@@ -22,7 +22,7 @@ async function renderPage(result, componentFactory, props, children, streaming,
22
22
  ["Content-Type", "text/html"],
23
23
  ["Content-Length", bytes.byteLength.toString()]
24
24
  ]);
25
- if (result.cspDestination === "header" || result.cspDestination === "adapter") {
25
+ if (result.shouldInjectCspMetaTags && (result.cspDestination === "header" || result.cspDestination === "adapter")) {
26
26
  headers2.set("content-security-policy", renderCspContent(result));
27
27
  }
28
28
  return new Response(bytes, {
@@ -13,6 +13,7 @@ function astro({ settings, logger }) {
13
13
  let astroFileToCompileMetadata = /* @__PURE__ */ new Map();
14
14
  const srcRootWeb = config.srcDir.pathname.slice(config.root.pathname.length - 1);
15
15
  const isBrowserPath = (path) => path.startsWith(srcRootWeb) && srcRootWeb !== "/";
16
+ const notAstroComponent = (component) => !component.resolvedPath.endsWith(".astro");
16
17
  const prePlugin = {
17
18
  name: "astro:build",
18
19
  enforce: "pre",
@@ -170,8 +171,10 @@ File: ${id}`
170
171
  const filename = normalizePath(parsedId.filename);
171
172
  const transformResult = await compile(source, filename);
172
173
  const astroMetadata = {
173
- clientOnlyComponents: transformResult.clientOnlyComponents,
174
- hydratedComponents: transformResult.hydratedComponents,
174
+ // Remove Astro components that have been mistakenly given client directives
175
+ // We'll warn the user about this later, but for now we'll prevent them from breaking the build
176
+ clientOnlyComponents: transformResult.clientOnlyComponents.filter(notAstroComponent),
177
+ hydratedComponents: transformResult.hydratedComponents.filter(notAstroComponent),
175
178
  serverComponents: transformResult.serverComponents,
176
179
  scripts: transformResult.scripts,
177
180
  containsHead: transformResult.containsHead,
@@ -138,6 +138,42 @@ async function handleRoute({
138
138
  let statusCode = 200;
139
139
  let isReroute = false;
140
140
  let isRewrite = false;
141
+ async function renderError(err, skipMiddleware) {
142
+ const custom500 = getCustom500Route(routesList);
143
+ if (!custom500) {
144
+ throw err;
145
+ }
146
+ try {
147
+ const filePath500 = new URL(`./${custom500.component}`, config.root);
148
+ const preloaded500Component = await pipeline.preload(custom500, filePath500);
149
+ renderContext = await RenderContext.create({
150
+ locals,
151
+ pipeline,
152
+ pathname,
153
+ middleware: skipMiddleware ? void 0 : middleware,
154
+ request,
155
+ routeData: route,
156
+ clientAddress: incomingRequest.socket.remoteAddress,
157
+ actions
158
+ });
159
+ renderContext.props.error = err;
160
+ const _response = await renderContext.render(preloaded500Component);
161
+ logger.error("router", err.stack || err.message);
162
+ statusCode = 500;
163
+ return _response;
164
+ } catch (_err) {
165
+ if (isAstroError(_err) && [
166
+ AstroErrorData.MiddlewareNoDataOrNextCalled.name,
167
+ AstroErrorData.MiddlewareNotAResponse.name
168
+ ].includes(_err.name)) {
169
+ throw _err;
170
+ }
171
+ if (skipMiddleware === false) {
172
+ return renderError(_err, true);
173
+ }
174
+ throw _err;
175
+ }
176
+ }
141
177
  try {
142
178
  response = await renderContext.render(mod);
143
179
  isReroute = response.headers.has(REROUTE_DIRECTIVE_HEADER);
@@ -152,16 +188,7 @@ async function handleRoute({
152
188
  !response.headers.has(NOOP_MIDDLEWARE_HEADER) && !isReroute ? response.status : statusCodedMatched ?? response.status
153
189
  );
154
190
  } catch (err) {
155
- const custom500 = getCustom500Route(routesList);
156
- if (!custom500) {
157
- throw err;
158
- }
159
- logger.error("router", err.stack || err.message);
160
- const filePath500 = new URL(`./${custom500.component}`, config.root);
161
- const preloaded500Component = await pipeline.preload(custom500, filePath500);
162
- renderContext.props.error = err;
163
- response = await renderContext.render(preloaded500Component);
164
- statusCode = 500;
191
+ response = await renderError(err, false);
165
192
  } finally {
166
193
  renderContext.session?.[PERSIST_SYMBOL]();
167
194
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "astro",
3
- "version": "5.12.2",
3
+ "version": "5.12.4",
4
4
  "description": "Astro is a modern site builder with web best practices, performance, and DX front-of-mind.",
5
5
  "type": "module",
6
6
  "author": "withastro",
@@ -155,12 +155,12 @@
155
155
  "xxhash-wasm": "^1.1.0",
156
156
  "yargs-parser": "^21.1.1",
157
157
  "yocto-spinner": "^0.2.1",
158
- "zod": "^3.24.2",
158
+ "zod": "^3.24.4",
159
159
  "zod-to-json-schema": "^3.24.5",
160
160
  "zod-to-ts": "^1.2.0",
161
161
  "@astrojs/internal-helpers": "0.6.1",
162
- "@astrojs/telemetry": "3.3.0",
163
- "@astrojs/markdown-remark": "6.3.3"
162
+ "@astrojs/markdown-remark": "6.3.3",
163
+ "@astrojs/telemetry": "3.3.0"
164
164
  },
165
165
  "optionalDependencies": {
166
166
  "sharp": "^0.33.3"
package/templates/env.mjs CHANGED
@@ -14,7 +14,6 @@ import {
14
14
  /** @returns {string} */
15
15
  // used while generating the virtual module
16
16
  // biome-ignore lint/correctness/noUnusedFunctionParameters: `key` is used by the generated code
17
- // biome-ignore lint/correctness/noUnusedVariables: `key` is used by the generated code
18
17
  const getEnv = (key) => {
19
18
  // @@GET_ENV@@
20
19
  };