astro 5.5.6 → 5.6.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 CHANGED
@@ -108,22 +108,7 @@ declare module '*.avif' {
108
108
  export default metadata;
109
109
  }
110
110
  declare module '*.svg' {
111
- type Props = {
112
- /**
113
- * Accessible, short-text description
114
- *
115
- * {@link https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title|MDN Reference}
116
- */
117
- title?: string;
118
- /**
119
- * Shorthand for setting the `height` and `width` properties
120
- */
121
- size?: number | string;
122
- /**
123
- * Override the default rendering mode for SVGs
124
- */
125
- mode?: import('./dist/assets/utils/svg.js').SvgRenderMode;
126
- } & astroHTML.JSX.SVGAttributes;
111
+ type Props = astroHTML.JSX.SVGAttributes;
127
112
 
128
113
  const Component: ((_props: Props) => any) & ImageMetadata;
129
114
  export default Component;
@@ -4,30 +4,10 @@ import {
4
4
  spreadAttributes,
5
5
  unescapeHTML
6
6
  } from "../runtime/server/index.js";
7
- const countersByPage = /* @__PURE__ */ new WeakMap();
8
7
  function createSvgComponent({ meta, attributes, children }) {
9
- const renderedIds = /* @__PURE__ */ new WeakMap();
10
- const Component = createComponent((result, props) => {
11
- let counter = countersByPage.get(result) ?? 0;
12
- const {
13
- title: titleProp,
14
- viewBox,
15
- mode,
16
- ...normalizedProps
17
- } = normalizeProps(attributes, props);
18
- const title = titleProp ? unescapeHTML(`<title>${titleProp}</title>`) : "";
19
- if (mode === "sprite") {
20
- let symbol = "";
21
- let id = renderedIds.get(result);
22
- if (!id) {
23
- countersByPage.set(result, ++counter);
24
- id = `a:${counter}`;
25
- symbol = unescapeHTML(`<symbol${spreadAttributes({ viewBox, id })}>${children}</symbol>`);
26
- renderedIds.set(result, id);
27
- }
28
- return render`<svg${spreadAttributes(normalizedProps)}>${title}${symbol}<use href="#${id}" /></svg>`;
29
- }
30
- return render`<svg${spreadAttributes({ viewBox, ...normalizedProps })}>${title}${unescapeHTML(children)}</svg>`;
8
+ const Component = createComponent((_, props) => {
9
+ const normalizedProps = normalizeProps(attributes, props);
10
+ return render`<svg${spreadAttributes(normalizedProps)}>${unescapeHTML(children)}</svg>`;
31
11
  });
32
12
  if (import.meta.env.DEV) {
33
13
  makeNonEnumerable(Component);
@@ -38,18 +18,14 @@ function createSvgComponent({ meta, attributes, children }) {
38
18
  return Object.assign(Component, meta);
39
19
  }
40
20
  const ATTRS_TO_DROP = ["xmlns", "xmlns:xlink", "version"];
41
- const DEFAULT_ATTRS = { role: "img" };
21
+ const DEFAULT_ATTRS = {};
42
22
  function dropAttributes(attributes) {
43
23
  for (const attr of ATTRS_TO_DROP) {
44
24
  delete attributes[attr];
45
25
  }
46
26
  return attributes;
47
27
  }
48
- function normalizeProps(attributes, { size, ...props }) {
49
- if (size !== void 0 && props.width === void 0 && props.height === void 0) {
50
- props.height = size;
51
- props.width = size;
52
- }
28
+ function normalizeProps(attributes, props) {
53
29
  return dropAttributes({ ...DEFAULT_ATTRS, ...attributes, ...props });
54
30
  }
55
31
  function makeNonEnumerable(object) {
@@ -1,5 +1,2 @@
1
1
  import type { ImageMetadata } from '../types.js';
2
- export type SvgRenderMode = 'inline' | 'sprite';
3
- export declare function makeSvgComponent(meta: ImageMetadata, contents: Buffer | string, options?: {
4
- mode?: SvgRenderMode;
5
- }): string;
2
+ export declare function makeSvgComponent(meta: ImageMetadata, contents: Buffer | string): string;
@@ -12,12 +12,12 @@ function parseSvg(contents) {
12
12
  const body = renderSync({ ...root, children });
13
13
  return { attributes, body };
14
14
  }
15
- function makeSvgComponent(meta, contents, options) {
15
+ function makeSvgComponent(meta, contents) {
16
16
  const file = typeof contents === "string" ? contents : contents.toString("utf-8");
17
17
  const { attributes, body: children } = parseSvg(file);
18
18
  const props = {
19
19
  meta,
20
- attributes: dropAttributes({ mode: options?.mode, ...attributes }),
20
+ attributes: dropAttributes(attributes),
21
21
  children
22
22
  };
23
23
  return `import { createSvgComponent } from 'astro/assets/runtime';
@@ -182,9 +182,7 @@ function assets({ settings }) {
182
182
  }
183
183
  if (settings.config.experimental.svg && /\.svg$/.test(id)) {
184
184
  const { contents, ...metadata } = imageMetadata;
185
- return makeSvgComponent(metadata, contents, {
186
- mode: settings.config.experimental.svg.mode
187
- });
185
+ return makeSvgComponent(metadata, contents);
188
186
  }
189
187
  if (options?.ssr) {
190
188
  return `export default ${getProxyCode(
@@ -1,7 +1,7 @@
1
1
  import "./polyfill.js";
2
2
  import { posix } from "node:path";
3
3
  import { getDefaultClientDirectives } from "../core/client-directive/index.js";
4
- import { ASTRO_CONFIG_DEFAULTS } from "../core/config/schema.js";
4
+ import { ASTRO_CONFIG_DEFAULTS } from "../core/config/schemas/index.js";
5
5
  import { validateConfig } from "../core/config/validate.js";
6
6
  import { createKey } from "../core/encryption.js";
7
7
  import { Logger } from "../core/logger/core.js";
@@ -153,7 +153,7 @@ ${contentConfig.error.message}`);
153
153
  logger.info("Content config changed");
154
154
  shouldClear = true;
155
155
  }
156
- if (previousAstroVersion && previousAstroVersion !== "5.5.6") {
156
+ if (previousAstroVersion && previousAstroVersion !== "5.6.0") {
157
157
  logger.info("Astro version changed");
158
158
  shouldClear = true;
159
159
  }
@@ -161,8 +161,8 @@ ${contentConfig.error.message}`);
161
161
  logger.info("Clearing content store");
162
162
  this.#store.clearAll();
163
163
  }
164
- if ("5.5.6") {
165
- await this.#store.metaStore().set("astro-version", "5.5.6");
164
+ if ("5.6.0") {
165
+ await this.#store.metaStore().set("astro-version", "5.6.0");
166
166
  }
167
167
  if (currentConfigDigest) {
168
168
  await this.#store.metaStore().set("content-config-digest", currentConfigDigest);
@@ -3,6 +3,7 @@ import type { RouteData, SSRManifest } from '../../types/public/internal.js';
3
3
  import { getSetCookiesFromResponse } from '../cookies/index.js';
4
4
  import { AstroIntegrationLogger } from '../logger/core.js';
5
5
  export { deserializeManifest } from './common.js';
6
+ type ErrorPagePath = `${string}/404` | `${string}/500` | `${string}/404/` | `${string}/500/` | `${string}404.html` | `${string}500.html`;
6
7
  export interface RenderOptions {
7
8
  /**
8
9
  * Whether to automatically add all cookies written by `Astro.cookie.set()` to the response headers.
@@ -24,6 +25,19 @@ export interface RenderOptions {
24
25
  * The mutable object that will be made available as `Astro.locals` in pages, and as `ctx.locals` in API routes and middleware.
25
26
  */
26
27
  locals?: object;
28
+ /**
29
+ * A custom fetch function for retrieving prerendered pages - 404 or 500.
30
+ *
31
+ * If not provided, Astro will fallback to its default behavior for fetching error pages.
32
+ *
33
+ * When a dynamic route is matched but ultimately results in a 404, this function will be used
34
+ * to fetch the prerendered 404 page if available. Similarly, it may be used to fetch a
35
+ * prerendered 500 error page when necessary.
36
+ *
37
+ * @param {ErrorPagePath} url - The URL of the prerendered 404 or 500 error page to fetch.
38
+ * @returns {Promise<Response>} A promise resolving to the prerendered response.
39
+ */
40
+ prerenderedErrorPageFetch?: (url: ErrorPagePath) => Promise<Response>;
27
41
  /**
28
42
  * **Advanced API**: you probably do not need to use this.
29
43
  *
@@ -45,6 +59,7 @@ export interface RenderErrorOptions {
45
59
  */
46
60
  error?: unknown;
47
61
  clientAddress: string | undefined;
62
+ prerenderedErrorPageFetch: (url: ErrorPagePath) => Promise<Response>;
48
63
  }
49
64
  export declare class App {
50
65
  #private;
@@ -193,6 +193,7 @@ class App {
193
193
  let addCookieHeader;
194
194
  const url = new URL(request.url);
195
195
  const redirect = this.#redirectTrailingSlash(url.pathname);
196
+ const prerenderedErrorPageFetch = renderOptions?.prerenderedErrorPageFetch ?? fetch;
196
197
  if (redirect !== url.pathname) {
197
198
  const status = request.method === "GET" ? 301 : 308;
198
199
  return new Response(
@@ -226,7 +227,12 @@ class App {
226
227
  if (typeof locals !== "object") {
227
228
  const error = new AstroError(AstroErrorData.LocalsNotAnObject);
228
229
  this.#logger.error(null, error.stack);
229
- return this.#renderError(request, { status: 500, error, clientAddress });
230
+ return this.#renderError(request, {
231
+ status: 500,
232
+ error,
233
+ clientAddress,
234
+ prerenderedErrorPageFetch
235
+ });
230
236
  }
231
237
  }
232
238
  if (!routeData) {
@@ -242,7 +248,12 @@ class App {
242
248
  if (!routeData) {
243
249
  this.#logger.debug("router", "Astro hasn't found routes that match " + request.url);
244
250
  this.#logger.debug("router", "Here's the available routes:\n", this.#manifestData);
245
- return this.#renderError(request, { locals, status: 404, clientAddress });
251
+ return this.#renderError(request, {
252
+ locals,
253
+ status: 404,
254
+ clientAddress,
255
+ prerenderedErrorPageFetch
256
+ });
246
257
  }
247
258
  const pathname = this.#getPathnameFromRequest(request);
248
259
  const defaultStatus = this.#getDefaultStatusCode(routeData, pathname);
@@ -263,7 +274,13 @@ class App {
263
274
  response = await renderContext.render(await mod.page());
264
275
  } catch (err) {
265
276
  this.#logger.error(null, err.stack || err.message || String(err));
266
- return this.#renderError(request, { locals, status: 500, error: err, clientAddress });
277
+ return this.#renderError(request, {
278
+ locals,
279
+ status: 500,
280
+ error: err,
281
+ clientAddress,
282
+ prerenderedErrorPageFetch
283
+ });
267
284
  } finally {
268
285
  await session?.[PERSIST_SYMBOL]();
269
286
  }
@@ -275,7 +292,8 @@ class App {
275
292
  // We don't have an error to report here. Passing null means we pass nothing intentionally
276
293
  // while undefined means there's no error
277
294
  error: response.status === 500 ? null : void 0,
278
- clientAddress
295
+ clientAddress,
296
+ prerenderedErrorPageFetch
279
297
  });
280
298
  }
281
299
  if (response.headers.has(REROUTE_DIRECTIVE_HEADER)) {
@@ -314,7 +332,8 @@ class App {
314
332
  response: originalResponse,
315
333
  skipMiddleware = false,
316
334
  error,
317
- clientAddress
335
+ clientAddress,
336
+ prerenderedErrorPageFetch
318
337
  }) {
319
338
  const errorRoutePath = `/${status}${this.#manifest.trailingSlash === "always" ? "/" : ""}`;
320
339
  const errorRouteData = matchRoute(errorRoutePath, this.#manifestData);
@@ -327,7 +346,7 @@ class App {
327
346
  url
328
347
  );
329
348
  if (statusURL.toString() !== request.url) {
330
- const response2 = await fetch(statusURL.toString());
349
+ const response2 = await prerenderedErrorPageFetch(statusURL.toString());
331
350
  const override = { status };
332
351
  return this.#mergeResponses(response2, originalResponse, override);
333
352
  }
@@ -356,7 +375,8 @@ class App {
356
375
  status,
357
376
  response: originalResponse,
358
377
  skipMiddleware: true,
359
- clientAddress
378
+ clientAddress,
379
+ prerenderedErrorPageFetch
360
380
  });
361
381
  }
362
382
  } finally {
@@ -111,7 +111,7 @@ class AstroBuilder {
111
111
  }
112
112
  /** Run the build logic. build() is marked private because usage should go through ".run()" */
113
113
  async build({ viteConfig }) {
114
- await runHookBuildStart({ config: this.settings.config, logging: this.logger });
114
+ await runHookBuildStart({ config: this.settings.config, logger: this.logger });
115
115
  this.validateConfig();
116
116
  this.logger.info("build", `output: ${blue('"' + this.settings.config.output + '"')}`);
117
117
  this.logger.info("build", `mode: ${blue('"' + this.settings.buildOutput + '"')}`);
@@ -166,7 +166,7 @@ class AstroBuilder {
166
166
  settings: this.settings,
167
167
  pages: pageNames,
168
168
  routes: Object.values(allPages).flat().map((pageData) => pageData.route).concat(hasServerIslands ? getServerIslandRouteData(this.settings.config) : []),
169
- logging: this.logger
169
+ logger: this.logger
170
170
  });
171
171
  if (this.logger.level && levels[this.logger.level()] <= levels["info"]) {
172
172
  await this.printStats({
@@ -1,6 +1,6 @@
1
1
  export { configPaths, resolveConfig, resolveConfigPath, resolveRoot, } from './config.js';
2
2
  export { createNodeLogger } from './logging.js';
3
3
  export { mergeConfig } from './merge.js';
4
- export type { AstroConfigType } from './schema.js';
4
+ export type { AstroConfigType } from './schemas/index.js';
5
5
  export { createSettings } from './settings.js';
6
6
  export { loadTSConfig, updateTSConfigForFramework } from './tsconfig.js';