astro 4.0.4 → 4.0.6

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.
Files changed (40) hide show
  1. package/astro-jsx.d.ts +8 -2
  2. package/astro.js +1 -1
  3. package/components/Picture.astro +1 -1
  4. package/dist/assets/build/generate.js +2 -1
  5. package/dist/assets/endpoint/config.d.ts +2 -0
  6. package/dist/assets/endpoint/config.js +12 -0
  7. package/dist/assets/endpoint/generic.js +2 -1
  8. package/dist/assets/endpoint/node.js +2 -1
  9. package/dist/assets/internal.d.ts +2 -6
  10. package/dist/assets/internal.js +12 -31
  11. package/dist/assets/services/service.js +2 -1
  12. package/dist/assets/utils/imageKind.d.ts +3 -0
  13. package/dist/assets/utils/imageKind.js +10 -0
  14. package/dist/assets/utils/index.d.ts +2 -0
  15. package/dist/assets/utils/index.js +17 -0
  16. package/dist/assets/utils/remotePattern.d.ts +2 -0
  17. package/dist/assets/utils/remotePattern.js +11 -0
  18. package/dist/assets/utils/transformToPath.js +1 -1
  19. package/dist/assets/vite-plugin-assets.js +1 -1
  20. package/dist/core/app/index.js +19 -7
  21. package/dist/core/build/index.js +1 -1
  22. package/dist/core/build/static-build.js +1 -1
  23. package/dist/core/config/schema.d.ts +360 -360
  24. package/dist/core/constants.js +1 -1
  25. package/dist/core/create-vite.js +2 -0
  26. package/dist/core/dev/container.js +1 -1
  27. package/dist/core/dev/dev.js +1 -1
  28. package/dist/core/errors/errors-data.d.ts +6 -0
  29. package/dist/core/errors/errors-data.js +12 -2
  30. package/dist/core/messages.js +2 -2
  31. package/dist/core/routing/manifest/create.js +1 -1
  32. package/dist/integrations/astroFeaturesValidation.js +7 -7
  33. package/dist/transitions/router.js +7 -5
  34. package/dist/vite-plugin-astro-server/error.d.ts +7 -0
  35. package/dist/vite-plugin-astro-server/error.js +24 -0
  36. package/dist/vite-plugin-astro-server/plugin.js +33 -7
  37. package/dist/vite-plugin-astro-server/request.js +3 -16
  38. package/dist/vite-plugin-fileurl/index.d.ts +2 -0
  39. package/dist/vite-plugin-fileurl/index.js +14 -0
  40. package/package.json +2 -2
package/astro-jsx.d.ts CHANGED
@@ -517,7 +517,8 @@ declare namespace astroHTML.JSX {
517
517
  | 'search'
518
518
  | 'send'
519
519
  | undefined
520
- | null;
520
+ | null;
521
+ exportparts?: string | undefined | null;
521
522
  hidden?: boolean | string | undefined | null;
522
523
  id?: string | undefined | null;
523
524
  inert?: boolean | string | undefined | null;
@@ -533,18 +534,23 @@ declare namespace astroHTML.JSX {
533
534
  | undefined
534
535
  | null;
535
536
  is?: string | undefined | null;
537
+
538
+ // Microdata API
536
539
  itemid?: string | undefined | null;
537
540
  itemprop?: string | undefined | null;
538
541
  itemref?: string | undefined | null;
539
542
  itemscope?: boolean | string | undefined | null;
540
543
  itemtype?: string | undefined | null;
544
+
541
545
  lang?: string | undefined | null;
546
+ part?: string | undefined | null;
547
+ popover?: boolean | string | undefined | null;
542
548
  slot?: string | undefined | null;
543
549
  spellcheck?: 'true' | 'false' | boolean | undefined | null;
544
550
  style?: string | StyleObject | undefined | null;
545
551
  tabindex?: number | string | undefined | null;
546
552
  title?: string | undefined | null;
547
- translate?: 'yes' | 'no' | undefined | null;
553
+ translate?: 'yes' | 'no' | '' | undefined | null;
548
554
 
549
555
  // <command>, <menuitem>
550
556
  radiogroup?: string | undefined | null;
package/astro.js CHANGED
@@ -67,7 +67,7 @@ Please upgrade Node.js to a supported version: "${engines}"\n`);
67
67
  console.log(
68
68
  `${ci.name} CI Environment Detected!\nAdditional steps may be needed to set your Node.js version:`
69
69
  );
70
- console.log(`Documentation: https://docs.astro.build/guides/deploy`);
70
+ console.log(`Documentation: https://docs.astro.build/en/guides/deploy/`);
71
71
  if (CI_INSTRUCTIONS[platform]) {
72
72
  console.log(`${ci.name} Documentation: ${CI_INSTRUCTIONS[platform]}`);
73
73
  }
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  import { getImage, type LocalImageProps, type RemoteImageProps } from 'astro:assets';
3
3
  import type { GetImageResult, ImageOutputFormat } from '../dist/@types/astro';
4
- import { isESMImportedImage } from '../dist/assets/internal';
4
+ import { isESMImportedImage } from '../dist/assets/utils/imageKind';
5
5
  import { AstroError, AstroErrorData } from '../dist/core/errors/index.js';
6
6
  import type { HTMLAttributes } from '../types';
7
7
 
@@ -5,7 +5,8 @@ import { getOutDirWithinCwd } from "../../core/build/common.js";
5
5
  import { getTimeStat } from "../../core/build/util.js";
6
6
  import { isRemotePath, prependForwardSlash } from "../../core/path.js";
7
7
  import { isServerLikeOutput } from "../../prerender/utils.js";
8
- import { getConfiguredImageService, isESMImportedImage } from "../internal.js";
8
+ import { getConfiguredImageService } from "../internal.js";
9
+ import { isESMImportedImage } from "../utils/imageKind.js";
9
10
  import { loadRemoteImage } from "./remote.js";
10
11
  async function prepareAssetsGenerationEnv(pipeline, totalCount) {
11
12
  const config = pipeline.getConfig();
@@ -0,0 +1,2 @@
1
+ import type { AstroSettings } from '../../@types/astro.js';
2
+ export declare function injectImageEndpoint(settings: AstroSettings, mode: 'dev' | 'build'): AstroSettings;
@@ -0,0 +1,12 @@
1
+ function injectImageEndpoint(settings, mode) {
2
+ const endpointEntrypoint = settings.config.image.endpoint ?? (mode === "dev" ? "astro/assets/endpoint/node" : "astro/assets/endpoint/generic");
3
+ settings.injectedRoutes.push({
4
+ pattern: "/_image",
5
+ entrypoint: endpointEntrypoint,
6
+ prerender: false
7
+ });
8
+ return settings;
9
+ }
10
+ export {
11
+ injectImageEndpoint
12
+ };
@@ -1,8 +1,9 @@
1
1
  import { isRemotePath } from "@astrojs/internal-helpers/path";
2
2
  import mime from "mime/lite.js";
3
- import { getConfiguredImageService, isRemoteAllowed } from "../internal.js";
3
+ import { getConfiguredImageService } from "../internal.js";
4
4
  import { etag } from "../utils/etag.js";
5
5
  import { imageConfig } from "astro:assets";
6
+ import { isRemoteAllowed } from "../utils/remotePattern.js";
6
7
  async function loadRemoteImage(src) {
7
8
  try {
8
9
  const res = await fetch(src);
@@ -2,9 +2,10 @@ import { isRemotePath, removeQueryString } from "@astrojs/internal-helpers/path"
2
2
  import { readFile } from "fs/promises";
3
3
  import mime from "mime/lite.js";
4
4
  import os from "os";
5
- import { getConfiguredImageService, isRemoteAllowed } from "../internal.js";
5
+ import { getConfiguredImageService } from "../internal.js";
6
6
  import { etag } from "../utils/etag.js";
7
7
  import { assetsDir, imageConfig } from "astro:assets";
8
+ import { isRemoteAllowed } from "../utils/remotePattern.js";
8
9
  function replaceFileSystemReferences(src) {
9
10
  return os.platform().includes("win32") ? src.replace(/^\/@fs\//, "") : src.replace(/^\/@fs/, "");
10
11
  }
@@ -1,9 +1,5 @@
1
- import type { AstroConfig, AstroSettings } from '../@types/astro.js';
1
+ import type { AstroConfig } from '../@types/astro.js';
2
2
  import { type ImageService } from './services/service.js';
3
- import type { GetImageResult, ImageMetadata, UnresolvedImageTransform } from './types.js';
4
- export declare function injectImageEndpoint(settings: AstroSettings, mode: 'dev' | 'build'): AstroSettings;
5
- export declare function isESMImportedImage(src: ImageMetadata | string): src is ImageMetadata;
6
- export declare function isRemoteImage(src: ImageMetadata | string): src is string;
7
- export declare function isRemoteAllowed(src: string, { domains, remotePatterns, }: Partial<Pick<AstroConfig['image'], 'domains' | 'remotePatterns'>>): boolean;
3
+ import type { GetImageResult, UnresolvedImageTransform } from './types.js';
8
4
  export declare function getConfiguredImageService(): Promise<ImageService>;
9
5
  export declare function getImage(options: UnresolvedImageTransform, imageConfig: AstroConfig['image']): Promise<GetImageResult>;
@@ -1,32 +1,7 @@
1
- import { isRemotePath } from "@astrojs/internal-helpers/path";
2
1
  import { AstroError, AstroErrorData } from "../core/errors/index.js";
3
2
  import { DEFAULT_HASH_PROPS } from "./consts.js";
4
3
  import { isLocalService } from "./services/service.js";
5
- import { matchHostname, matchPattern } from "./utils/remotePattern.js";
6
- function injectImageEndpoint(settings, mode) {
7
- const endpointEntrypoint = settings.config.image.endpoint ?? (mode === "dev" ? "astro/assets/endpoint/node" : "astro/assets/endpoint/generic");
8
- settings.injectedRoutes.push({
9
- pattern: "/_image",
10
- entrypoint: endpointEntrypoint,
11
- prerender: false
12
- });
13
- return settings;
14
- }
15
- function isESMImportedImage(src) {
16
- return typeof src === "object";
17
- }
18
- function isRemoteImage(src) {
19
- return typeof src === "string";
20
- }
21
- function isRemoteAllowed(src, {
22
- domains = [],
23
- remotePatterns = []
24
- }) {
25
- if (!isRemotePath(src))
26
- return false;
27
- const url = new URL(src);
28
- return domains.some((domain) => matchHostname(url, domain)) || remotePatterns.some((remotePattern) => matchPattern(url, remotePattern));
29
- }
4
+ import { isESMImportedImage, isRemoteImage } from "./utils/imageKind.js";
30
5
  async function getConfiguredImageService() {
31
6
  if (!globalThis?.astroAsset?.imageService) {
32
7
  const { default: service } = await import(
@@ -51,6 +26,16 @@ async function getImage(options, imageConfig) {
51
26
  message: AstroErrorData.ExpectedImageOptions.message(JSON.stringify(options))
52
27
  });
53
28
  }
29
+ if (typeof options.src === "undefined") {
30
+ throw new AstroError({
31
+ ...AstroErrorData.ExpectedImage,
32
+ message: AstroErrorData.ExpectedImage.message(
33
+ options.src,
34
+ "undefined",
35
+ JSON.stringify(options)
36
+ )
37
+ });
38
+ }
54
39
  const service = await getConfiguredImageService();
55
40
  const resolvedOptions = {
56
41
  ...options,
@@ -95,9 +80,5 @@ async function getImage(options, imageConfig) {
95
80
  }
96
81
  export {
97
82
  getConfiguredImageService,
98
- getImage,
99
- injectImageEndpoint,
100
- isESMImportedImage,
101
- isRemoteAllowed,
102
- isRemoteImage
83
+ getImage
103
84
  };
@@ -1,7 +1,8 @@
1
1
  import { AstroError, AstroErrorData } from "../../core/errors/index.js";
2
2
  import { isRemotePath, joinPaths } from "../../core/path.js";
3
3
  import { DEFAULT_HASH_PROPS, DEFAULT_OUTPUT_FORMAT, VALID_SUPPORTED_FORMATS } from "../consts.js";
4
- import { isESMImportedImage, isRemoteAllowed } from "../internal.js";
4
+ import { isESMImportedImage } from "../utils/imageKind.js";
5
+ import { isRemoteAllowed } from "../utils/remotePattern.js";
5
6
  function isLocalService(service) {
6
7
  if (!service) {
7
8
  return false;
@@ -0,0 +1,3 @@
1
+ import type { ImageMetadata } from '../types.js';
2
+ export declare function isESMImportedImage(src: ImageMetadata | string): src is ImageMetadata;
3
+ export declare function isRemoteImage(src: ImageMetadata | string): src is string;
@@ -0,0 +1,10 @@
1
+ function isESMImportedImage(src) {
2
+ return typeof src === "object";
3
+ }
4
+ function isRemoteImage(src) {
5
+ return typeof src === "string";
6
+ }
7
+ export {
8
+ isESMImportedImage,
9
+ isRemoteImage
10
+ };
@@ -1,4 +1,6 @@
1
1
  export { emitESMImage } from './emitAsset.js';
2
+ export { isESMImportedImage, isRemoteImage } from './imageKind.js';
2
3
  export { imageMetadata } from './metadata.js';
3
4
  export { getOrigQueryParams } from './queryParams.js';
5
+ export { isRemoteAllowed, matchHostname, matchPathname, matchPattern, matchPort, matchProtocol, type RemotePattern, } from './remotePattern.js';
4
6
  export { hashTransform, propsToFilename } from './transformToPath.js';
@@ -1,11 +1,28 @@
1
1
  import { emitESMImage } from "./emitAsset.js";
2
+ import { isESMImportedImage, isRemoteImage } from "./imageKind.js";
2
3
  import { imageMetadata } from "./metadata.js";
3
4
  import { getOrigQueryParams } from "./queryParams.js";
5
+ import {
6
+ isRemoteAllowed,
7
+ matchHostname,
8
+ matchPathname,
9
+ matchPattern,
10
+ matchPort,
11
+ matchProtocol
12
+ } from "./remotePattern.js";
4
13
  import { hashTransform, propsToFilename } from "./transformToPath.js";
5
14
  export {
6
15
  emitESMImage,
7
16
  getOrigQueryParams,
8
17
  hashTransform,
9
18
  imageMetadata,
19
+ isESMImportedImage,
20
+ isRemoteAllowed,
21
+ isRemoteImage,
22
+ matchHostname,
23
+ matchPathname,
24
+ matchPattern,
25
+ matchPort,
26
+ matchProtocol,
10
27
  propsToFilename
11
28
  };
@@ -1,3 +1,4 @@
1
+ import type { AstroConfig } from '../../@types/astro.js';
1
2
  export type RemotePattern = {
2
3
  hostname?: string;
3
4
  pathname?: string;
@@ -9,3 +10,4 @@ export declare function matchPort(url: URL, port?: string): boolean;
9
10
  export declare function matchProtocol(url: URL, protocol?: string): boolean;
10
11
  export declare function matchHostname(url: URL, hostname?: string, allowWildcard?: boolean): boolean;
11
12
  export declare function matchPathname(url: URL, pathname?: string, allowWildcard?: boolean): boolean;
13
+ export declare function isRemoteAllowed(src: string, { domains, remotePatterns, }: Partial<Pick<AstroConfig['image'], 'domains' | 'remotePatterns'>>): boolean;
@@ -1,3 +1,4 @@
1
+ import { isRemotePath } from "@astrojs/internal-helpers/path";
1
2
  function matchPattern(url, remotePattern) {
2
3
  return matchProtocol(url, remotePattern.protocol) && matchHostname(url, remotePattern.hostname, true) && matchPort(url, remotePattern.port) && matchPathname(url, remotePattern.pathname, true);
3
4
  }
@@ -37,7 +38,17 @@ function matchPathname(url, pathname, allowWildcard) {
37
38
  }
38
39
  return false;
39
40
  }
41
+ function isRemoteAllowed(src, {
42
+ domains = [],
43
+ remotePatterns = []
44
+ }) {
45
+ if (!isRemotePath(src))
46
+ return false;
47
+ const url = new URL(src);
48
+ return domains.some((domain) => matchHostname(url, domain)) || remotePatterns.some((remotePattern) => matchPattern(url, remotePattern));
49
+ }
40
50
  export {
51
+ isRemoteAllowed,
41
52
  matchHostname,
42
53
  matchPathname,
43
54
  matchPattern,
@@ -2,7 +2,7 @@ import { deterministicString } from "deterministic-object-hash";
2
2
  import { basename, extname } from "node:path";
3
3
  import { removeQueryString } from "../../core/path.js";
4
4
  import { shorthash } from "../../runtime/server/shorthash.js";
5
- import { isESMImportedImage } from "../internal.js";
5
+ import { isESMImportedImage } from "./imageKind.js";
6
6
  function propsToFilename(transform, hash) {
7
7
  let filename = removeQueryString(
8
8
  isESMImportedImage(transform.src) ? transform.src.src : transform.src
@@ -10,8 +10,8 @@ import {
10
10
  } from "../core/path.js";
11
11
  import { isServerLikeOutput } from "../prerender/utils.js";
12
12
  import { VALID_INPUT_FORMATS, VIRTUAL_MODULE_ID, VIRTUAL_SERVICE_ID } from "./consts.js";
13
- import { isESMImportedImage } from "./internal.js";
14
13
  import { emitESMImage } from "./utils/emitAsset.js";
14
+ import { isESMImportedImage } from "./utils/imageKind.js";
15
15
  import { getProxyCode } from "./utils/proxy.js";
16
16
  import { hashTransform, propsToFilename } from "./utils/transformToPath.js";
17
17
  const resolvedVirtualModuleId = "\0" + VIRTUAL_MODULE_ID;
@@ -263,7 +263,8 @@ class App {
263
263
  * This also handles pre-rendered /404 or /500 routes
264
264
  */
265
265
  async #renderError(request, { status, response: originalResponse, skipMiddleware = false }) {
266
- const errorRouteData = matchRoute("/" + status, this.#manifestData);
266
+ const errorRoutePath = `/${status}${this.#manifest.trailingSlash === "always" ? "/" : ""}`;
267
+ const errorRouteData = matchRoute(errorRoutePath, this.#manifestData);
267
268
  const url = new URL(request.url);
268
269
  if (errorRouteData) {
269
270
  if (errorRouteData.prerender) {
@@ -308,8 +309,8 @@ class App {
308
309
  Reflect.set(response, responseSentSymbol, true);
309
310
  return response;
310
311
  }
311
- #mergeResponses(newResponse, oldResponse, override) {
312
- if (!oldResponse) {
312
+ #mergeResponses(newResponse, originalResponse, override) {
313
+ if (!originalResponse) {
313
314
  if (override !== void 0) {
314
315
  return new Response(newResponse.body, {
315
316
  status: override.status,
@@ -319,12 +320,23 @@ class App {
319
320
  }
320
321
  return newResponse;
321
322
  }
322
- const { statusText, headers } = oldResponse;
323
- const status = override?.status ? override.status : oldResponse.status === 200 ? newResponse.status : oldResponse.status;
323
+ const status = override?.status ? override.status : originalResponse.status === 200 ? newResponse.status : originalResponse.status;
324
+ try {
325
+ originalResponse.headers.delete("Content-type");
326
+ } catch {
327
+ }
324
328
  return new Response(newResponse.body, {
325
329
  status,
326
- statusText: status === 200 ? newResponse.statusText : statusText,
327
- headers: new Headers(Array.from(headers))
330
+ statusText: status === 200 ? newResponse.statusText : originalResponse.statusText,
331
+ // If you're looking at here for possible bugs, it means that it's not a bug.
332
+ // With the middleware, users can meddle with headers, and we should pass to the 404/500.
333
+ // If users see something weird, it's because they are setting some headers they should not.
334
+ //
335
+ // Although, we don't want it to replace the content-type, because the error page must return `text/html`
336
+ headers: new Headers([
337
+ ...Array.from(newResponse.headers),
338
+ ...Array.from(originalResponse.headers)
339
+ ])
328
340
  });
329
341
  }
330
342
  #getDefaultStatusCode(routeData, pathname) {
@@ -2,7 +2,7 @@ import { blue, bold, green } from "kleur/colors";
2
2
  import fs from "node:fs";
3
3
  import { performance } from "node:perf_hooks";
4
4
  import { fileURLToPath } from "node:url";
5
- import { injectImageEndpoint } from "../../assets/internal.js";
5
+ import { injectImageEndpoint } from "../../assets/endpoint/config.js";
6
6
  import { telemetry } from "../../events/index.js";
7
7
  import { eventCliSession } from "../../events/session.js";
8
8
  import {
@@ -269,7 +269,7 @@ async function runPostBuildHooks(container, ssrOutputs, clientOutputs) {
269
269
  const config = container.options.settings.config;
270
270
  const build = container.options.settings.config.build;
271
271
  for (const [fileName, mutation] of mutations) {
272
- const root = isServerLikeOutput(config) ? mutation.targets.includes("server") ? build.server : build.client : config.outDir;
272
+ const root = isServerLikeOutput(config) ? mutation.targets.includes("server") ? build.server : build.client : getOutDirWithinCwd(config.outDir);
273
273
  const fullPath = path.join(fileURLToPath(root), fileName);
274
274
  const fileURL = pathToFileURL(fullPath);
275
275
  await fs.promises.mkdir(new URL("./", fileURL), { recursive: true });