astro 5.3.0 → 5.4.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.
Files changed (59) hide show
  1. package/components/Image.astro +1 -9
  2. package/components/Picture.astro +6 -11
  3. package/dist/assets/endpoint/generic.js +1 -1
  4. package/dist/assets/endpoint/node.js +1 -1
  5. package/dist/assets/internal.js +13 -0
  6. package/dist/assets/services/service.js +1 -1
  7. package/dist/assets/utils/imageAttributes.d.ts +1 -9
  8. package/dist/assets/utils/imageAttributes.js +2 -21
  9. package/dist/assets/utils/index.d.ts +0 -1
  10. package/dist/assets/utils/index.js +0 -14
  11. package/dist/cli/dev/index.js +4 -0
  12. package/dist/cli/flags.js +2 -1
  13. package/dist/cli/preview/index.js +4 -0
  14. package/dist/config/entrypoint.d.ts +2 -0
  15. package/dist/config/entrypoint.js +5 -1
  16. package/dist/container/index.js +1 -0
  17. package/dist/content/content-layer.js +3 -3
  18. package/dist/content/loaders/glob.js +6 -5
  19. package/dist/content/runtime-assets.d.ts +1 -1
  20. package/dist/content/runtime.js +10 -5
  21. package/dist/content/types-generator.js +6 -11
  22. package/dist/content/vite-plugin-content-virtual-mod.js +2 -2
  23. package/dist/core/app/index.js +1 -1
  24. package/dist/core/app/types.d.ts +7 -0
  25. package/dist/core/build/generate.js +2 -1
  26. package/dist/core/build/index.d.ts +10 -0
  27. package/dist/core/build/plugins/plugin-manifest.js +2 -1
  28. package/dist/core/build/static-build.d.ts +0 -1
  29. package/dist/core/build/static-build.js +4 -23
  30. package/dist/core/config/merge.d.ts +3 -1
  31. package/dist/core/config/merge.js +2 -2
  32. package/dist/core/config/schema.d.ts +18 -0
  33. package/dist/core/config/schema.js +6 -3
  34. package/dist/core/constants.js +1 -1
  35. package/dist/core/create-vite.js +2 -2
  36. package/dist/core/dev/container.js +2 -2
  37. package/dist/core/dev/dev.js +1 -1
  38. package/dist/core/index.d.ts +1 -7
  39. package/dist/core/index.js +6 -7
  40. package/dist/core/messages.js +2 -2
  41. package/dist/core/preview/static-preview-server.js +2 -1
  42. package/dist/core/render-context.js +1 -0
  43. package/dist/core/routing/match.js +2 -3
  44. package/dist/core/routing/rewrite.js +15 -2
  45. package/dist/integrations/hooks.js +2 -1
  46. package/dist/runtime/server/render/head.js +3 -0
  47. package/dist/runtime/server/render/script.js +3 -1
  48. package/dist/transitions/router.js +1 -1
  49. package/dist/types/public/config.d.ts +20 -1
  50. package/dist/types/public/index.d.ts +1 -1
  51. package/dist/types/public/internal.d.ts +1 -0
  52. package/dist/vite-plugin-astro-server/plugin.js +1 -0
  53. package/dist/vite-plugin-markdown/content-entry-type.js +8 -2
  54. package/dist/vite-plugin-markdown/images.d.ts +1 -1
  55. package/dist/vite-plugin-markdown/images.js +20 -3
  56. package/dist/vite-plugin-markdown/index.js +14 -6
  57. package/package.json +9 -9
  58. package/dist/assets/utils/remotePattern.d.ts +0 -13
  59. package/dist/assets/utils/remotePattern.js +0 -56
@@ -1,7 +1,6 @@
1
1
  ---
2
2
  import { type LocalImageProps, type RemoteImageProps, getImage, imageConfig } from 'astro:assets';
3
3
  import type { UnresolvedImageTransform } from '../dist/assets/types';
4
- import { applyResponsiveAttributes } from '../dist/assets/utils/imageAttributes.js';
5
4
  import { AstroError, AstroErrorData } from '../dist/core/errors/index.js';
6
5
  import type { HTMLAttributes } from '../types';
7
6
 
@@ -46,14 +45,7 @@ if (import.meta.env.DEV) {
46
45
  additionalAttributes['data-image-component'] = 'true';
47
46
  }
48
47
 
49
- const { class: className, ...attributes } = useResponsive
50
- ? applyResponsiveAttributes({
51
- layout,
52
- image,
53
- props,
54
- additionalAttributes,
55
- })
56
- : { ...additionalAttributes, ...image.attributes };
48
+ const { class: className, ...attributes } = { ...additionalAttributes, ...image.attributes };
57
49
  ---
58
50
 
59
51
  {/* Applying class outside of the spread prevents it from applying unnecessary astro-* classes */}
@@ -1,8 +1,7 @@
1
1
  ---
2
2
  import { type LocalImageProps, type RemoteImageProps, getImage, imageConfig } from 'astro:assets';
3
3
  import * as mime from 'mrmime';
4
- import { applyResponsiveAttributes } from '../dist/assets/utils/imageAttributes';
5
- import { isESMImportedImage, resolveSrc } from '../dist/assets/utils/imageKind';
4
+ import { isESMImportedImage, resolveSrc } from '../dist/assets/utils/imageKind.js';
6
5
  import { AstroError, AstroErrorData } from '../dist/core/errors/index.js';
7
6
  import type {
8
7
  GetImageResult,
@@ -101,18 +100,14 @@ if (fallbackImage.srcSet.values.length > 0) {
101
100
  imgAdditionalAttributes.srcset = fallbackImage.srcSet.attribute;
102
101
  }
103
102
 
104
- const { class: className, ...attributes } = useResponsive
105
- ? applyResponsiveAttributes({
106
- layout,
107
- image: fallbackImage,
108
- props,
109
- additionalAttributes: imgAdditionalAttributes,
110
- })
111
- : { ...imgAdditionalAttributes, ...fallbackImage.attributes };
112
-
113
103
  if (import.meta.env.DEV) {
114
104
  imgAdditionalAttributes['data-image-component'] = 'true';
115
105
  }
106
+
107
+ const { class: className, ...attributes } = {
108
+ ...imgAdditionalAttributes,
109
+ ...fallbackImage.attributes,
110
+ };
116
111
  ---
117
112
 
118
113
  <picture {...pictureAttributes}>
@@ -1,9 +1,9 @@
1
1
  import { imageConfig } from "astro:assets";
2
2
  import { isRemotePath } from "@astrojs/internal-helpers/path";
3
+ import { isRemoteAllowed } from "@astrojs/internal-helpers/remote";
3
4
  import * as mime from "mrmime";
4
5
  import { getConfiguredImageService } from "../internal.js";
5
6
  import { etag } from "../utils/etag.js";
6
- import { isRemoteAllowed } from "../utils/remotePattern.js";
7
7
  async function loadRemoteImage(src, headers) {
8
8
  try {
9
9
  const res = await fetch(src, {
@@ -4,10 +4,10 @@ import { isAbsolute } from "node:path";
4
4
  import { fileURLToPath, pathToFileURL } from "node:url";
5
5
  import { assetsDir, imageConfig, outDir } from "astro:assets";
6
6
  import { isRemotePath, removeQueryString } from "@astrojs/internal-helpers/path";
7
+ import { isRemoteAllowed } from "@astrojs/internal-helpers/remote";
7
8
  import * as mime from "mrmime";
8
9
  import { getConfiguredImageService } from "../internal.js";
9
10
  import { etag } from "../utils/etag.js";
10
- import { isRemoteAllowed } from "../utils/remotePattern.js";
11
11
  function replaceFileSystemReferences(src) {
12
12
  return os.platform().includes("win32") ? src.replace(/^\/@fs\//, "") : src.replace(/^\/@fs/, "");
13
13
  }
@@ -11,6 +11,7 @@ import { isLocalService } from "./services/service.js";
11
11
  import {
12
12
  isImageMetadata
13
13
  } from "./types.js";
14
+ import { addCSSVarsToStyle, cssFitValues } from "./utils/imageAttributes.js";
14
15
  import { isESMImportedImage, isRemoteImage, resolveSrc } from "./utils/imageKind.js";
15
16
  import { inferRemoteSize } from "./utils/remoteProbe.js";
16
17
  async function getConfiguredImageService() {
@@ -108,6 +109,18 @@ async function getImage(options, imageConfig) {
108
109
  }
109
110
  delete resolvedOptions.priority;
110
111
  delete resolvedOptions.densities;
112
+ if (layout !== "none") {
113
+ resolvedOptions.style = addCSSVarsToStyle(
114
+ {
115
+ w: String(resolvedOptions.width),
116
+ h: String(resolvedOptions.height),
117
+ fit: cssFitValues.includes(resolvedOptions.fit ?? "") && resolvedOptions.fit,
118
+ pos: resolvedOptions.position
119
+ },
120
+ resolvedOptions.style
121
+ );
122
+ resolvedOptions["data-astro-image"] = layout;
123
+ }
111
124
  }
112
125
  const validatedOptions = service.validateOptions ? await service.validateOptions(resolvedOptions, imageConfig) : resolvedOptions;
113
126
  const srcSetTransforms = service.getSrcSet ? await service.getSrcSet(validatedOptions, imageConfig) : [];
@@ -1,8 +1,8 @@
1
+ import { isRemoteAllowed } from "@astrojs/internal-helpers/remote";
1
2
  import { AstroError, AstroErrorData } from "../../core/errors/index.js";
2
3
  import { isRemotePath, joinPaths } from "../../core/path.js";
3
4
  import { DEFAULT_HASH_PROPS, DEFAULT_OUTPUT_FORMAT, VALID_SUPPORTED_FORMATS } from "../consts.js";
4
5
  import { isESMImportedImage, isRemoteImage } from "../utils/imageKind.js";
5
- import { isRemoteAllowed } from "../utils/remotePattern.js";
6
6
  function isLocalService(service) {
7
7
  if (!service) {
8
8
  return false;
@@ -1,10 +1,2 @@
1
- import type { GetImageResult, ImageLayout, LocalImageProps, RemoteImageProps } from '../types.js';
1
+ export declare const cssFitValues: string[];
2
2
  export declare function addCSSVarsToStyle(vars: Record<string, string | false | undefined>, styles?: string | Record<string, any>): string;
3
- export declare function applyResponsiveAttributes<T extends LocalImageProps<unknown> | RemoteImageProps<unknown>>({ layout, image, props, additionalAttributes, }: {
4
- layout: Exclude<ImageLayout, 'none'>;
5
- image: GetImageResult;
6
- additionalAttributes: Record<string, any>;
7
- props: T;
8
- }): {
9
- [x: string]: any;
10
- };
@@ -1,4 +1,5 @@
1
1
  import { toStyleString } from "../../runtime/server/render/util.js";
2
+ const cssFitValues = ["fill", "contain", "cover", "scale-down"];
2
3
  function addCSSVarsToStyle(vars, styles) {
3
4
  const cssVars = Object.entries(vars).filter(([_, value]) => value !== void 0 && value !== false).map(([key, value]) => `--${key}: ${value};`).join(" ");
4
5
  if (!styles) {
@@ -7,27 +8,7 @@ function addCSSVarsToStyle(vars, styles) {
7
8
  const style = typeof styles === "string" ? styles : toStyleString(styles);
8
9
  return `${cssVars} ${style}`;
9
10
  }
10
- const cssFitValues = ["fill", "contain", "cover", "scale-down"];
11
- function applyResponsiveAttributes({
12
- layout,
13
- image,
14
- props,
15
- additionalAttributes
16
- }) {
17
- const attributes = { ...additionalAttributes, ...image.attributes };
18
- attributes.style = addCSSVarsToStyle(
19
- {
20
- w: image.attributes.width ?? props.width ?? image.options.width,
21
- h: image.attributes.height ?? props.height ?? image.options.height,
22
- fit: cssFitValues.includes(props.fit ?? "") && props.fit,
23
- pos: props.position
24
- },
25
- attributes.style
26
- );
27
- attributes["data-astro-image"] = layout;
28
- return attributes;
29
- }
30
11
  export {
31
12
  addCSSVarsToStyle,
32
- applyResponsiveAttributes
13
+ cssFitValues
33
14
  };
@@ -2,7 +2,6 @@ export { emitESMImage } from './node/emitAsset.js';
2
2
  export { isESMImportedImage, isRemoteImage } from './imageKind.js';
3
3
  export { imageMetadata } from './metadata.js';
4
4
  export { getOrigQueryParams } from './queryParams.js';
5
- export { isRemoteAllowed, matchHostname, matchPathname, matchPattern, matchPort, matchProtocol, type RemotePattern, } from './remotePattern.js';
6
5
  export { hashTransform, propsToFilename } from './transformToPath.js';
7
6
  export { inferRemoteSize } from './remoteProbe.js';
8
7
  export { makeSvgComponent } from './svg.js';
@@ -2,14 +2,6 @@ import { emitESMImage } from "./node/emitAsset.js";
2
2
  import { isESMImportedImage, isRemoteImage } from "./imageKind.js";
3
3
  import { imageMetadata } from "./metadata.js";
4
4
  import { getOrigQueryParams } from "./queryParams.js";
5
- import {
6
- isRemoteAllowed,
7
- matchHostname,
8
- matchPathname,
9
- matchPattern,
10
- matchPort,
11
- matchProtocol
12
- } from "./remotePattern.js";
13
5
  import { hashTransform, propsToFilename } from "./transformToPath.js";
14
6
  import { inferRemoteSize } from "./remoteProbe.js";
15
7
  import { makeSvgComponent } from "./svg.js";
@@ -20,13 +12,7 @@ export {
20
12
  imageMetadata,
21
13
  inferRemoteSize,
22
14
  isESMImportedImage,
23
- isRemoteAllowed,
24
15
  isRemoteImage,
25
16
  makeSvgComponent,
26
- matchHostname,
27
- matchPathname,
28
- matchPattern,
29
- matchPort,
30
- matchProtocol,
31
17
  propsToFilename
32
18
  };
@@ -15,6 +15,10 @@ async function dev({ flags }) {
15
15
  ["--host <custom-address>", `Expose on a network IP address at <custom-address>`],
16
16
  ["--open", "Automatically open the app in the browser on server start"],
17
17
  ["--force", "Clear the content layer cache, forcing a full rebuild."],
18
+ [
19
+ "--allowed-hosts",
20
+ "Specify a comma-separated list of allowed hosts or allow any hostname."
21
+ ],
18
22
  ["--help (-h)", "See all available flags."]
19
23
  ]
20
24
  },
package/dist/cli/flags.js CHANGED
@@ -15,7 +15,8 @@ function flagsToAstroInlineConfig(flags) {
15
15
  server: {
16
16
  port: typeof flags.port === "number" ? flags.port : void 0,
17
17
  host: typeof flags.host === "string" || typeof flags.host === "boolean" ? flags.host : void 0,
18
- open: typeof flags.open === "string" || typeof flags.open === "boolean" ? flags.open : void 0
18
+ open: typeof flags.open === "string" || typeof flags.open === "boolean" ? flags.open : void 0,
19
+ allowedHosts: typeof flags.allowedHosts === "string" ? flags.allowedHosts.split(",") : typeof flags.allowedHosts === "boolean" && flags.allowedHosts === true ? flags.allowedHosts : []
19
20
  }
20
21
  };
21
22
  }
@@ -13,6 +13,10 @@ async function preview({ flags }) {
13
13
  ["--host", `Listen on all addresses, including LAN and public addresses.`],
14
14
  ["--host <custom-address>", `Expose on a network IP address at <custom-address>`],
15
15
  ["--open", "Automatically open the app in the browser on server start"],
16
+ [
17
+ "--allowed-hosts",
18
+ "Specify a comma-separated list of allowed hosts or allow any hostname."
19
+ ],
16
20
  ["--help (-h)", "See all available flags."]
17
21
  ]
18
22
  },
@@ -2,6 +2,8 @@ import type { SharpImageServiceConfig } from '../assets/services/sharp.js';
2
2
  import type { ImageServiceConfig } from '../types/public/index.js';
3
3
  export { defineConfig, getViteConfig } from './index.js';
4
4
  export { envField } from '../env/config.js';
5
+ export { mergeConfig } from '../core/config/merge.js';
6
+ export { validateConfig } from '../core/config/validate.js';
5
7
  /**
6
8
  * Return the configuration needed to use the Sharp-based image service
7
9
  */
@@ -1,5 +1,7 @@
1
1
  import { defineConfig, getViteConfig } from "./index.js";
2
2
  import { envField } from "../env/config.js";
3
+ import { mergeConfig } from "../core/config/merge.js";
4
+ import { validateConfig } from "../core/config/validate.js";
3
5
  function sharpImageService(config = {}) {
4
6
  return {
5
7
  entrypoint: "astro/assets/services/sharp",
@@ -16,6 +18,8 @@ export {
16
18
  defineConfig,
17
19
  envField,
18
20
  getViteConfig,
21
+ mergeConfig,
19
22
  passthroughImageService,
20
- sharpImageService
23
+ sharpImageService,
24
+ validateConfig
21
25
  };
@@ -38,6 +38,7 @@ function createManifest(manifest, renderers, middleware) {
38
38
  clientDirectives: manifest?.clientDirectives ?? getDefaultClientDirectives(),
39
39
  renderers: renderers ?? manifest?.renderers ?? [],
40
40
  base: manifest?.base ?? ASTRO_CONFIG_DEFAULTS.base,
41
+ userAssetsBase: manifest?.userAssetsBase ?? "",
41
42
  componentMetadata: manifest?.componentMetadata ?? /* @__PURE__ */ new Map(),
42
43
  inlinedScripts: manifest?.inlinedScripts ?? /* @__PURE__ */ new Map(),
43
44
  i18n: manifest?.i18n,
@@ -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.3.0") {
156
+ if (previousAstroVersion && previousAstroVersion !== "5.4.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.3.0") {
165
- await this.#store.metaStore().set("astro-version", "5.3.0");
164
+ if ("5.4.0") {
165
+ await this.#store.metaStore().set("astro-version", "5.4.0");
166
166
  }
167
167
  if (currentConfigDigest) {
168
168
  await this.#store.metaStore().set("content-config-digest", currentConfigDigest);
@@ -1,10 +1,10 @@
1
1
  import { promises as fs, existsSync } from "node:fs";
2
2
  import { relative } from "node:path";
3
3
  import { fileURLToPath, pathToFileURL } from "node:url";
4
- import fastGlob from "fast-glob";
5
4
  import { bold, green } from "kleur/colors";
6
- import micromatch from "micromatch";
7
5
  import pLimit from "p-limit";
6
+ import picomatch from "picomatch";
7
+ import { glob as tinyglobby } from "tinyglobby";
8
8
  import { getContentEntryIdAndSlug, posixRelative } from "../utils.js";
9
9
  function generateIdDefault({ entry, base, data }) {
10
10
  if (data.slug) {
@@ -154,8 +154,9 @@ function glob(globOptions) {
154
154
  if (!exists) {
155
155
  logger.warn(`The base directory "${fileURLToPath(baseDir)}" does not exist.`);
156
156
  }
157
- const files = await fastGlob(globOptions.pattern, {
158
- cwd: fileURLToPath(baseDir)
157
+ const files = await tinyglobby(globOptions.pattern, {
158
+ cwd: fileURLToPath(baseDir),
159
+ expandDirectories: false
159
160
  });
160
161
  if (exists && files.length === 0) {
161
162
  logger.warn(
@@ -220,7 +221,7 @@ function glob(globOptions) {
220
221
  return;
221
222
  }
222
223
  watcher.add(filePath);
223
- const matchesGlob = (entry) => !entry.startsWith("../") && micromatch.isMatch(entry, globOptions.pattern);
224
+ const matchesGlob = (entry) => !entry.startsWith("../") && picomatch.isMatch(entry, globOptions.pattern);
224
225
  const basePath = fileURLToPath(baseDir);
225
226
  async function onChange(changedPath) {
226
227
  const entry = posixRelative(basePath, changedPath);
@@ -4,8 +4,8 @@ export declare function createImage(pluginContext: PluginContext, shouldEmitFile
4
4
  ASTRO_ASSET: string;
5
5
  width: number;
6
6
  height: number;
7
- format: import("../assets/types.js").ImageInputFormat;
8
7
  src: string;
8
+ format: import("../assets/types.js").ImageInputFormat;
9
9
  fsPath: string;
10
10
  orientation?: number | undefined;
11
11
  }, string>;
@@ -298,12 +298,17 @@ async function updateImageReferencesInBody(html, fileName) {
298
298
  for (const [_full, imagePath] of html.matchAll(CONTENT_LAYER_IMAGE_REGEX)) {
299
299
  try {
300
300
  const decodedImagePath = JSON.parse(imagePath.replaceAll("&#x22;", '"'));
301
- const id = imageSrcToImportId(decodedImagePath.src, fileName);
302
- const imported = imageAssetMap.get(id);
303
- if (!id || imageObjects.has(id) || !imported) {
304
- continue;
301
+ let image;
302
+ if (URL.canParse(decodedImagePath.src)) {
303
+ image = await getImage(decodedImagePath);
304
+ } else {
305
+ const id = imageSrcToImportId(decodedImagePath.src, fileName);
306
+ const imported = imageAssetMap.get(id);
307
+ if (!id || imageObjects.has(id) || !imported) {
308
+ continue;
309
+ }
310
+ image = await getImage({ ...decodedImagePath, src: imported });
305
311
  }
306
- const image = await getImage({ ...decodedImagePath, src: imported });
307
312
  imageObjects.set(imagePath, image);
308
313
  } catch {
309
314
  throw new Error(`Failed to parse image reference: ${imagePath}`);
@@ -1,7 +1,7 @@
1
1
  import * as path from "node:path";
2
2
  import { fileURLToPath, pathToFileURL } from "node:url";
3
- import glob from "fast-glob";
4
3
  import { bold, cyan } from "kleur/colors";
4
+ import { glob } from "tinyglobby";
5
5
  import { normalizePath } from "vite";
6
6
  import { z } from "zod";
7
7
  import { zodToJsonSchema } from "zod-to-json-schema";
@@ -48,20 +48,15 @@ async function createContentTypesGenerator({
48
48
  }
49
49
  const globResult = await glob("**", {
50
50
  cwd: fileURLToPath(contentPaths.contentDir),
51
- fs: {
52
- readdir: fs.readdir.bind(fs),
53
- readdirSync: fs.readdirSync.bind(fs)
54
- },
55
- onlyFiles: false,
56
- objectMode: true
51
+ absolute: true
57
52
  });
58
- for (const entry of globResult) {
59
- const fullPath = path.join(fileURLToPath(contentPaths.contentDir), entry.path);
53
+ for (const fullPath of globResult) {
60
54
  const entryURL = pathToFileURL(fullPath);
61
55
  if (entryURL.href.startsWith(contentPaths.config.url.href)) continue;
62
- if (entry.dirent.isFile()) {
56
+ const stat = fs.statSync(fullPath);
57
+ if (stat.isFile()) {
63
58
  events.push({ name: "add", entry: entryURL });
64
- } else if (entry.dirent.isDirectory()) {
59
+ } else if (stat.isDirectory()) {
65
60
  events.push({ name: "addDir", entry: entryURL });
66
61
  }
67
62
  }
@@ -2,8 +2,8 @@ import nodeFs from "node:fs";
2
2
  import { extname } from "node:path";
3
3
  import { fileURLToPath, pathToFileURL } from "node:url";
4
4
  import { dataToEsm } from "@rollup/pluginutils";
5
- import glob from "fast-glob";
6
5
  import pLimit from "p-limit";
6
+ import { glob } from "tinyglobby";
7
7
  import { AstroError, AstroErrorData } from "../core/errors/index.js";
8
8
  import { rootRelativePath } from "../core/viteUtils.js";
9
9
  import { createDefaultAstroMetadata } from "../vite-plugin-astro/metadata.js";
@@ -225,7 +225,7 @@ async function generateLookupMap({
225
225
  {
226
226
  absolute: true,
227
227
  cwd: fileURLToPath(root),
228
- fs
228
+ expandDirectories: false
229
229
  }
230
230
  );
231
231
  const limit = pLimit(10);
@@ -115,7 +115,7 @@ class App {
115
115
  if (!pathname) {
116
116
  pathname = prependForwardSlash(this.removeBase(url.pathname));
117
117
  }
118
- let routeData = matchRoute(pathname, this.#manifestData);
118
+ let routeData = matchRoute(decodeURI(pathname), this.#manifestData);
119
119
  if (!routeData || routeData.prerender) return void 0;
120
120
  return routeData;
121
121
  }
@@ -38,6 +38,13 @@ export type SSRManifest = {
38
38
  routes: RouteInfo[];
39
39
  site?: string;
40
40
  base: string;
41
+ /**
42
+ * The base of the assets generated **by the user**. For example, scripts created by the user falls under this category.
43
+ *
44
+ * The value of this field comes from `vite.base`. We aren't usually this tight to vite in our code base, so probably
45
+ * this should be refactored somehow.
46
+ */
47
+ userAssetsBase: string | undefined;
41
48
  trailingSlash: AstroConfig['trailingSlash'];
42
49
  buildFormat: NonNullable<AstroConfig['build']>['format'];
43
50
  compressHTML: boolean;
@@ -208,7 +208,7 @@ async function getPathsForRoute(route, mod, pipeline, builtPaths) {
208
208
  if (!builtPaths.has(removeTrailingForwardSlash(staticPath))) {
209
209
  return true;
210
210
  }
211
- const matchedRoute = matchRoute(staticPath, options.routesList);
211
+ const matchedRoute = matchRoute(decodeURI(staticPath), options.routesList);
212
212
  return matchedRoute === route;
213
213
  });
214
214
  for (const staticPath of paths) {
@@ -388,6 +388,7 @@ function createBuildManifest(settings, internals, renderers, middleware, key) {
388
388
  compressHTML: settings.config.compressHTML,
389
389
  renderers,
390
390
  base: settings.config.base,
391
+ userAssetsBase: settings.config?.vite?.base,
391
392
  assetsPrefix: settings.config.build.assetsPrefix,
392
393
  site: settings.config.site,
393
394
  componentMetadata: internals.componentMetadata,
@@ -7,6 +7,16 @@ export interface BuildOptions {
7
7
  * @default false
8
8
  */
9
9
  devOutput?: boolean;
10
+ /**
11
+ * Teardown the compiler WASM instance after build. This can improve performance when
12
+ * building once, but may cause a performance hit if building multiple times in a row.
13
+ *
14
+ * When building multiple projects in the same execution (e.g. during tests), disabling
15
+ * this option can greatly improve performance at the cost of some extra memory usage.
16
+ *
17
+ * @default true
18
+ */
19
+ teardownCompiler?: boolean;
10
20
  }
11
21
  /**
12
22
  * Builds your site for deployment. By default, this will generate static files and place them in a dist/ directory.
@@ -1,5 +1,5 @@
1
1
  import { fileURLToPath } from "node:url";
2
- import glob from "fast-glob";
2
+ import { glob } from "tinyglobby";
3
3
  import { getAssetsPrefix } from "../../../assets/utils/getAssetsPrefix.js";
4
4
  import { normalizeTheLocale } from "../../../i18n/index.js";
5
5
  import { toFallbackType, toRoutingStrategy } from "../../../i18n/utils.js";
@@ -216,6 +216,7 @@ function buildManifest(opts, internals, staticFiles, encodedKey) {
216
216
  routes,
217
217
  site: settings.config.site,
218
218
  base: settings.config.base,
219
+ userAssetsBase: settings.config?.vite?.base,
219
220
  trailingSlash: settings.config.trailingSlash,
220
221
  compressHTML: settings.config.compressHTML,
221
222
  assetsPrefix: settings.config.build.assetsPrefix,
@@ -6,7 +6,6 @@ export declare function viteBuild(opts: StaticBuildOptions): Promise<{
6
6
  ssrOutputChunkNames: string[];
7
7
  }>;
8
8
  export declare function staticBuild(opts: StaticBuildOptions, internals: BuildInternals, ssrOutputChunkNames: string[]): Promise<void>;
9
- export declare function copyFiles(fromFolder: URL, toFolder: URL, includeDotfiles?: boolean): Promise<void[] | undefined>;
10
9
  /**
11
10
  * This function takes the virtual module name of any page entrypoint and
12
11
  * transforms it to generate a final `.mjs` output file.
@@ -2,8 +2,8 @@ import fs from "node:fs";
2
2
  import path from "node:path";
3
3
  import { fileURLToPath, pathToFileURL } from "node:url";
4
4
  import { teardown } from "@astrojs/compiler";
5
- import glob from "fast-glob";
6
5
  import { bgGreen, black, green } from "kleur/colors";
6
+ import { glob } from "tinyglobby";
7
7
  import * as vite from "vite";
8
8
  import { createBuildInternals } from "../../core/build/internal.js";
9
9
  import { emptyDir, removeEmptyDirs } from "../../core/fs/index.js";
@@ -185,8 +185,8 @@ async function clientBuild(opts, internals, input, container) {
185
185
  const ssr = settings.buildOutput === "server";
186
186
  const out = ssr ? settings.config.build.client : getOutDirWithinCwd(settings.config.outDir);
187
187
  if (!input.size) {
188
- if (ssr) {
189
- await copyFiles(settings.config.publicDir, out, true);
188
+ if (ssr && fs.existsSync(settings.config.publicDir)) {
189
+ await fs.promises.cp(settings.config.publicDir, out, { recursive: true, force: true });
190
190
  }
191
191
  return null;
192
192
  }
@@ -283,29 +283,11 @@ async function cleanServerOutput(opts, ssrOutputChunkNames, internals) {
283
283
  await Promise.all(
284
284
  fileNames.filter((fileName) => fileName.endsWith(".d.ts")).map((fileName) => fs.promises.rm(new URL(fileName, out)))
285
285
  );
286
- await copyFiles(out, opts.settings.config.outDir, true);
286
+ await fs.promises.cp(out, opts.settings.config.outDir, { recursive: true, force: true });
287
287
  await fs.promises.rm(out, { recursive: true });
288
288
  return;
289
289
  }
290
290
  }
291
- async function copyFiles(fromFolder, toFolder, includeDotfiles = false) {
292
- const files = await glob("**/*", {
293
- cwd: fileURLToPath(fromFolder),
294
- dot: includeDotfiles
295
- });
296
- if (files.length === 0) return;
297
- return await Promise.all(
298
- files.map(async function copyFile(filename) {
299
- const from = new URL(filename, fromFolder);
300
- const to = new URL(filename, toFolder);
301
- const lastFolder = new URL("./", to);
302
- return fs.promises.mkdir(lastFolder, { recursive: true }).then(async function fsCopyFile() {
303
- const p = await fs.promises.copyFile(from, to, fs.constants.COPYFILE_FICLONE);
304
- return p;
305
- });
306
- })
307
- );
308
- }
309
291
  async function ssrMoveAssets(opts) {
310
292
  opts.logger.info("build", "Rearranging server assets...");
311
293
  const serverRoot = opts.settings.buildOutput === "static" ? opts.settings.config.build.client : opts.settings.config.build.server;
@@ -336,7 +318,6 @@ function makeAstroPageEntryPointFileName(prefix, facadeModuleId, routes) {
336
318
  return `pages${name.replace(/\/$/, "/index").replaceAll(/[[\]]/g, "_").replaceAll("...", "---")}.astro.mjs`;
337
319
  }
338
320
  export {
339
- copyFiles,
340
321
  makeAstroPageEntryPointFileName,
341
322
  staticBuild,
342
323
  viteBuild
@@ -1 +1,3 @@
1
- export declare function mergeConfig(defaults: Record<string, any>, overrides: Record<string, any>, isRoot?: boolean): Record<string, any>;
1
+ import type { DeepPartial } from '../../type-utils.js';
2
+ import type { AstroConfig, AstroInlineConfig } from '../../types/public/index.js';
3
+ export declare function mergeConfig<C extends AstroConfig | AstroInlineConfig>(defaults: C, overrides: DeepPartial<C>): C;
@@ -47,8 +47,8 @@ function mergeConfigRecursively(defaults, overrides, rootPath) {
47
47
  }
48
48
  return merged;
49
49
  }
50
- function mergeConfig(defaults, overrides, isRoot = true) {
51
- return mergeConfigRecursively(defaults, overrides, isRoot ? "" : ".");
50
+ function mergeConfig(defaults, overrides) {
51
+ return mergeConfigRecursively(defaults, overrides, "");
52
52
  }
53
53
  export {
54
54
  mergeConfig