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
@@ -48,6 +48,7 @@ export declare const ASTRO_CONFIG_DEFAULTS: {
48
48
  host: false;
49
49
  port: number;
50
50
  open: false;
51
+ allowedHosts: never[];
51
52
  };
52
53
  integrations: never[];
53
54
  markdown: Required<import("@astrojs/markdown-remark").AstroMarkdownOptions>;
@@ -164,19 +165,23 @@ export declare const AstroConfigSchema: z.ZodObject<{
164
165
  host: z.ZodDefault<z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodBoolean]>>>;
165
166
  port: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
166
167
  headers: z.ZodOptional<z.ZodType<OutgoingHttpHeaders, z.ZodTypeDef, OutgoingHttpHeaders>>;
168
+ allowedHosts: z.ZodDefault<z.ZodOptional<z.ZodUnion<[z.ZodArray<z.ZodString, "many">, z.ZodLiteral<true>]>>>;
167
169
  }, "strip", z.ZodTypeAny, {
168
170
  host: string | boolean;
169
171
  port: number;
172
+ allowedHosts: true | string[];
170
173
  open: string | boolean;
171
174
  headers?: OutgoingHttpHeaders | undefined;
172
175
  }, {
173
176
  headers?: OutgoingHttpHeaders | undefined;
174
177
  host?: string | boolean | undefined;
175
178
  port?: number | undefined;
179
+ allowedHosts?: true | string[] | undefined;
176
180
  open?: string | boolean | undefined;
177
181
  }>>, {
178
182
  host: string | boolean;
179
183
  port: number;
184
+ allowedHosts: true | string[];
180
185
  open: string | boolean;
181
186
  headers?: OutgoingHttpHeaders | undefined;
182
187
  }, unknown>;
@@ -783,6 +788,7 @@ export declare const AstroConfigSchema: z.ZodObject<{
783
788
  server: {
784
789
  host: string | boolean;
785
790
  port: number;
791
+ allowedHosts: true | string[];
786
792
  open: string | boolean;
787
793
  headers?: OutgoingHttpHeaders | undefined;
788
794
  };
@@ -1215,19 +1221,23 @@ export declare function createRelativeSchema(cmd: string, fileProtocolRoot: stri
1215
1221
  host: z.ZodDefault<z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodBoolean]>>>;
1216
1222
  port: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
1217
1223
  headers: z.ZodOptional<z.ZodType<OutgoingHttpHeaders, z.ZodTypeDef, OutgoingHttpHeaders>>;
1224
+ allowedHosts: z.ZodDefault<z.ZodOptional<z.ZodUnion<[z.ZodArray<z.ZodString, "many">, z.ZodLiteral<true>]>>>;
1218
1225
  }, "strip", z.ZodTypeAny, {
1219
1226
  host: string | boolean;
1220
1227
  port: number;
1228
+ allowedHosts: true | string[];
1221
1229
  open: string | boolean;
1222
1230
  headers?: OutgoingHttpHeaders | undefined;
1223
1231
  }, {
1224
1232
  headers?: OutgoingHttpHeaders | undefined;
1225
1233
  host?: string | boolean | undefined;
1226
1234
  port?: number | undefined;
1235
+ allowedHosts?: true | string[] | undefined;
1227
1236
  open?: string | boolean | undefined;
1228
1237
  }>>, {
1229
1238
  host: string | boolean;
1230
1239
  port: number;
1240
+ allowedHosts: true | string[];
1231
1241
  open: string | boolean;
1232
1242
  headers?: OutgoingHttpHeaders | undefined;
1233
1243
  }, unknown>;
@@ -1887,9 +1897,11 @@ export declare function createRelativeSchema(cmd: string, fileProtocolRoot: stri
1887
1897
  port: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
1888
1898
  headers: z.ZodOptional<z.ZodType<OutgoingHttpHeaders, z.ZodTypeDef, OutgoingHttpHeaders>>;
1889
1899
  streaming: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
1900
+ allowedHosts: z.ZodDefault<z.ZodOptional<z.ZodUnion<[z.ZodArray<z.ZodString, "many">, z.ZodLiteral<true>]>>>;
1890
1901
  }, "strip", z.ZodTypeAny, {
1891
1902
  host: string | boolean;
1892
1903
  port: number;
1904
+ allowedHosts: true | string[];
1893
1905
  open: string | boolean;
1894
1906
  streaming: boolean;
1895
1907
  headers?: OutgoingHttpHeaders | undefined;
@@ -1897,11 +1909,13 @@ export declare function createRelativeSchema(cmd: string, fileProtocolRoot: stri
1897
1909
  headers?: OutgoingHttpHeaders | undefined;
1898
1910
  host?: string | boolean | undefined;
1899
1911
  port?: number | undefined;
1912
+ allowedHosts?: true | string[] | undefined;
1900
1913
  open?: string | boolean | undefined;
1901
1914
  streaming?: boolean | undefined;
1902
1915
  }>>>, {
1903
1916
  host: string | boolean;
1904
1917
  port: number;
1918
+ allowedHosts: true | string[];
1905
1919
  open: string | boolean;
1906
1920
  streaming: boolean;
1907
1921
  headers?: OutgoingHttpHeaders | undefined;
@@ -1911,6 +1925,7 @@ export declare function createRelativeSchema(cmd: string, fileProtocolRoot: stri
1911
1925
  server: {
1912
1926
  host: string | boolean;
1913
1927
  port: number;
1928
+ allowedHosts: true | string[];
1914
1929
  open: string | boolean;
1915
1930
  streaming: boolean;
1916
1931
  headers?: OutgoingHttpHeaders | undefined;
@@ -2256,6 +2271,7 @@ export declare function createRelativeSchema(cmd: string, fileProtocolRoot: stri
2256
2271
  server: {
2257
2272
  host: string | boolean;
2258
2273
  port: number;
2274
+ allowedHosts: true | string[];
2259
2275
  open: string | boolean;
2260
2276
  streaming: boolean;
2261
2277
  headers?: OutgoingHttpHeaders | undefined;
@@ -2601,6 +2617,7 @@ export declare function createRelativeSchema(cmd: string, fileProtocolRoot: stri
2601
2617
  server: {
2602
2618
  host: string | boolean;
2603
2619
  port: number;
2620
+ allowedHosts: true | string[];
2604
2621
  open: string | boolean;
2605
2622
  streaming: boolean;
2606
2623
  headers?: OutgoingHttpHeaders | undefined;
@@ -2946,6 +2963,7 @@ export declare function createRelativeSchema(cmd: string, fileProtocolRoot: stri
2946
2963
  server: {
2947
2964
  host: string | boolean;
2948
2965
  port: number;
2966
+ allowedHosts: true | string[];
2949
2967
  open: string | boolean;
2950
2968
  streaming: boolean;
2951
2969
  headers?: OutgoingHttpHeaders | undefined;
@@ -34,7 +34,8 @@ const ASTRO_CONFIG_DEFAULTS = {
34
34
  server: {
35
35
  host: false,
36
36
  port: 4321,
37
- open: false
37
+ open: false,
38
+ allowedHosts: []
38
39
  },
39
40
  integrations: [],
40
41
  markdown: markdownConfigDefaults,
@@ -112,7 +113,8 @@ const AstroConfigSchema = z.object({
112
113
  open: z.union([z.string(), z.boolean()]).optional().default(ASTRO_CONFIG_DEFAULTS.server.open),
113
114
  host: z.union([z.string(), z.boolean()]).optional().default(ASTRO_CONFIG_DEFAULTS.server.host),
114
115
  port: z.number().optional().default(ASTRO_CONFIG_DEFAULTS.server.port),
115
- headers: z.custom().optional()
116
+ headers: z.custom().optional(),
117
+ allowedHosts: z.union([z.array(z.string()), z.literal(true)]).optional().default(ASTRO_CONFIG_DEFAULTS.server.allowedHosts)
116
118
  }).default({})
117
119
  ),
118
120
  redirects: z.record(
@@ -447,7 +449,8 @@ function createRelativeSchema(cmd, fileProtocolRoot) {
447
449
  host: z.union([z.string(), z.boolean()]).optional().default(ASTRO_CONFIG_DEFAULTS.server.host),
448
450
  port: z.number().optional().default(ASTRO_CONFIG_DEFAULTS.server.port),
449
451
  headers: z.custom().optional(),
450
- streaming: z.boolean().optional().default(true)
452
+ streaming: z.boolean().optional().default(true),
453
+ allowedHosts: z.union([z.array(z.string()), z.literal(true)]).optional().default(ASTRO_CONFIG_DEFAULTS.server.allowedHosts)
451
454
  }).optional().default({})
452
455
  )
453
456
  }).transform((config) => {
@@ -1,4 +1,4 @@
1
- const ASTRO_VERSION = "5.3.0";
1
+ const ASTRO_VERSION = "5.4.0";
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";
@@ -1,6 +1,6 @@
1
1
  import nodeFs from "node:fs";
2
2
  import { fileURLToPath } from "node:url";
3
- import glob from "fast-glob";
3
+ import { convertPathToPattern } from "tinyglobby";
4
4
  import * as vite from "vite";
5
5
  import { crawlFrameworkPkgs } from "vitefu";
6
6
  import { vitePluginActions, vitePluginUserActions } from "../actions/plugins.js";
@@ -84,7 +84,7 @@ async function createVite(commandConfig, { settings, logger, mode, command, fs =
84
84
  }
85
85
  }
86
86
  });
87
- const srcDirPattern = glob.convertPathToPattern(fileURLToPath(settings.config.srcDir));
87
+ const srcDirPattern = convertPathToPattern(fileURLToPath(settings.config.srcDir));
88
88
  const envLoader = createEnvLoader(mode, settings.config);
89
89
  const commonConfig = {
90
90
  // Tell Vite not to combine config from vite.config.js with our provided inline config
@@ -28,7 +28,7 @@ async function createContainer({
28
28
  });
29
29
  const {
30
30
  base,
31
- server: { host, headers, open: serverOpen }
31
+ server: { host, headers, open: serverOpen, allowedHosts }
32
32
  } = settings.config;
33
33
  const isServerOpenURL = typeof serverOpen == "string" && !isRestart;
34
34
  const isServerOpenBoolean = serverOpen && !isRestart;
@@ -41,7 +41,7 @@ async function createContainer({
41
41
  const mode = inlineConfig?.mode ?? "development";
42
42
  const viteConfig = await createVite(
43
43
  {
44
- server: { host, headers, open },
44
+ server: { host, headers, open, allowedHosts },
45
45
  optimizeDeps: {
46
46
  include: rendererClientEntries
47
47
  }
@@ -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.3.0";
25
+ const currentVersion = "5.4.0";
26
26
  const isPrerelease = currentVersion.includes("-");
27
27
  if (!isPrerelease) {
28
28
  try {
@@ -1,13 +1,7 @@
1
1
  import type { AstroInlineConfig } from '../types/public/config.js';
2
+ export { default as build } from './build/index.js';
2
3
  export { default as dev } from './dev/index.js';
3
4
  export { default as preview } from './preview/index.js';
4
- /**
5
- * Builds your site for deployment. By default, this will generate static files and place them in a dist/ directory.
6
- * If SSR is enabled, this will generate the necessary server files to serve your site.
7
- *
8
- * @experimental The JavaScript API is experimental
9
- */
10
- export declare const build: (inlineConfig: AstroInlineConfig) => Promise<void>;
11
5
  /**
12
6
  * Generates TypeScript types for all Astro modules. This sets up a `src/env.d.ts` file for type inferencing,
13
7
  * and defines the `astro:content` module for the Content Collections API.
@@ -1,12 +1,11 @@
1
- import { default as _build } from "./build/index.js";
2
1
  import { default as _sync } from "./sync/index.js";
3
- import { default as default2 } from "./dev/index.js";
4
- import { default as default3 } from "./preview/index.js";
5
- const build = (inlineConfig) => _build(inlineConfig);
2
+ import { default as default2 } from "./build/index.js";
3
+ import { default as default3 } from "./dev/index.js";
4
+ import { default as default4 } from "./preview/index.js";
6
5
  const sync = (inlineConfig) => _sync(inlineConfig);
7
6
  export {
8
- build,
9
- default2 as dev,
10
- default3 as preview,
7
+ default2 as build,
8
+ default3 as dev,
9
+ default4 as preview,
11
10
  sync
12
11
  };
@@ -38,7 +38,7 @@ function serverStart({
38
38
  host,
39
39
  base
40
40
  }) {
41
- const version = "5.3.0";
41
+ const version = "5.4.0";
42
42
  const localPrefix = `${dim("\u2503")} Local `;
43
43
  const networkPrefix = `${dim("\u2503")} Network `;
44
44
  const emptyPrefix = " ".repeat(11);
@@ -281,7 +281,7 @@ function printHelp({
281
281
  message.push(
282
282
  linebreak(),
283
283
  ` ${bgGreen(black(` ${commandName} `))} ${green(
284
- `v${"5.3.0"}`
284
+ `v${"5.4.0"}`
285
285
  )} ${headline}`
286
286
  );
287
287
  }
@@ -19,7 +19,8 @@ async function createStaticPreviewServer(settings, logger) {
19
19
  host: settings.config.server.host,
20
20
  port: settings.config.server.port,
21
21
  headers: settings.config.server.headers,
22
- open: settings.config.server.open
22
+ open: settings.config.server.open,
23
+ allowedHosts: settings.config.server.allowedHosts
23
24
  },
24
25
  plugins: [vitePluginAstroPreview(settings)]
25
26
  });
@@ -316,6 +316,7 @@ class RenderContext {
316
316
  };
317
317
  const result = {
318
318
  base: manifest.base,
319
+ userAssetsBase: manifest.userAssetsBase,
319
320
  cancelled: false,
320
321
  clientDirectives,
321
322
  inlinedScripts,
@@ -1,13 +1,12 @@
1
1
  import { redirectIsExternal } from "../redirects/render.js";
2
2
  import { SERVER_ISLAND_BASE_PREFIX, SERVER_ISLAND_COMPONENT } from "../server-islands/endpoint.js";
3
3
  function matchRoute(pathname, manifest) {
4
- const decodedPathname = decodeURI(pathname);
5
4
  return manifest.routes.find((route) => {
6
- return route.pattern.test(decodedPathname) || route.fallbackRoutes.some((fallbackRoute) => fallbackRoute.pattern.test(decodedPathname));
5
+ return route.pattern.test(pathname) || route.fallbackRoutes.some((fallbackRoute) => fallbackRoute.pattern.test(pathname));
7
6
  });
8
7
  }
9
8
  function matchAllRoutes(pathname, manifest) {
10
- return manifest.routes.filter((route) => route.pattern.test(decodeURI(pathname)));
9
+ return manifest.routes.filter((route) => route.pattern.test(pathname));
11
10
  }
12
11
  const ROUTE404_RE = /^\/404\/?$/;
13
12
  const ROUTE500_RE = /^\/500\/?$/;
@@ -1,7 +1,12 @@
1
1
  import { shouldAppendForwardSlash } from "../build/util.js";
2
2
  import { originPathnameSymbol } from "../constants.js";
3
3
  import { AstroError, AstroErrorData } from "../errors/index.js";
4
- import { appendForwardSlash, removeTrailingForwardSlash } from "../path.js";
4
+ import {
5
+ appendForwardSlash,
6
+ joinPaths,
7
+ prependForwardSlash,
8
+ removeTrailingForwardSlash
9
+ } from "../path.js";
5
10
  import { createRequest } from "../request.js";
6
11
  import { DEFAULT_404_ROUTE } from "./astro-designed-error-pages.js";
7
12
  function findRouteToRewrite({
@@ -21,10 +26,18 @@ function findRouteToRewrite({
21
26
  newUrl = new URL(payload, new URL(request.url).origin);
22
27
  }
23
28
  let pathname = newUrl.pathname;
29
+ const shouldAppendSlash = shouldAppendForwardSlash(trailingSlash, buildFormat);
24
30
  if (base !== "/" && newUrl.pathname.startsWith(base)) {
25
- pathname = shouldAppendForwardSlash(trailingSlash, buildFormat) ? appendForwardSlash(newUrl.pathname) : removeTrailingForwardSlash(newUrl.pathname);
31
+ pathname = shouldAppendSlash ? appendForwardSlash(newUrl.pathname) : removeTrailingForwardSlash(newUrl.pathname);
26
32
  pathname = pathname.slice(base.length);
27
33
  }
34
+ if (!pathname.startsWith("/") && shouldAppendSlash && newUrl.pathname.endsWith("/")) {
35
+ pathname = prependForwardSlash(pathname);
36
+ }
37
+ if (pathname === "/" && base !== "/" && !shouldAppendSlash) {
38
+ pathname = "";
39
+ }
40
+ newUrl.pathname = joinPaths(...[base, pathname].filter(Boolean));
28
41
  const decodedPathname = decodeURI(pathname);
29
42
  let foundRoute;
30
43
  for (const route of routes) {
@@ -1,6 +1,7 @@
1
1
  import fsMod from "node:fs";
2
2
  import { fileURLToPath } from "node:url";
3
3
  import { bold } from "kleur/colors";
4
+ import { mergeConfig as mergeViteConfig } from "vite";
4
5
  import astroIntegrationActionsRouteHandler from "../actions/integration.js";
5
6
  import { isActionsFilePresent } from "../actions/utils.js";
6
7
  import { CONTENT_LAYER_TYPE } from "../content/consts.js";
@@ -377,7 +378,7 @@ async function runHookBuildSetup({
377
378
  pages,
378
379
  target,
379
380
  updateConfig: (newConfig) => {
380
- updatedConfig = mergeConfig(updatedConfig, newConfig);
381
+ updatedConfig = mergeViteConfig(updatedConfig, newConfig);
381
382
  return { ...updatedConfig };
382
383
  },
383
384
  logger: getLogger(integration, logger)
@@ -13,6 +13,9 @@ function renderAllHeadContent(result) {
13
13
  );
14
14
  result.styles.clear();
15
15
  const scripts = Array.from(result.scripts).filter(uniqueElements).map((script) => {
16
+ if (result.userAssetsBase) {
17
+ script.props.src = (result.base === "/" ? "" : result.base) + result.userAssetsBase + script.props.src;
18
+ }
16
19
  return renderElement("script", script, false);
17
20
  });
18
21
  const links = Array.from(result.links).filter(uniqueElements).map((link) => renderElement("link", link, false));
@@ -11,7 +11,9 @@ async function renderScript(result, id) {
11
11
  }
12
12
  }
13
13
  const resolved = await result.resolve(id);
14
- return markHTMLString(`<script type="module" src="${resolved}"></script>`);
14
+ return markHTMLString(
15
+ `<script type="module" src="${result.userAssetsBase ? (result.base === "/" ? "" : result.base) + result.userAssetsBase : ""}${resolved}"></script>`
16
+ );
15
17
  }
16
18
  export {
17
19
  renderScript
@@ -252,7 +252,7 @@ async function transition(direction, from, to, options, historyState) {
252
252
  if (preparationEvent.formData) {
253
253
  init.method = "POST";
254
254
  const form = preparationEvent.sourceElement instanceof HTMLFormElement ? preparationEvent.sourceElement : preparationEvent.sourceElement instanceof HTMLElement && "form" in preparationEvent.sourceElement ? preparationEvent.sourceElement.form : preparationEvent.sourceElement?.closest("form");
255
- init.body = form?.attributes.getNamedItem("enctype")?.value === "application/x-www-form-urlencoded" ? new URLSearchParams(preparationEvent.formData) : preparationEvent.formData;
255
+ init.body = from !== void 0 && Reflect.get(HTMLFormElement.prototype, "attributes", form).getNamedItem("enctype")?.value === "application/x-www-form-urlencoded" ? new URLSearchParams(preparationEvent.formData) : preparationEvent.formData;
256
256
  }
257
257
  const response = await fetchHTML(href, init);
258
258
  if (response === null) {
@@ -1,9 +1,9 @@
1
1
  import type { OutgoingHttpHeaders } from 'node:http';
2
+ import type { RemotePattern } from '@astrojs/internal-helpers/remote';
2
3
  import type { RehypePlugins, RemarkPlugins, RemarkRehype, ShikiConfig } from '@astrojs/markdown-remark';
3
4
  import type { BuiltinDriverName, BuiltinDriverOptions, Driver, Storage } from 'unstorage';
4
5
  import type { UserConfig as OriginalViteUserConfig, SSROptions as ViteSSROptions } from 'vite';
5
6
  import type { ImageFit, ImageLayout } from '../../assets/types.js';
6
- import type { RemotePattern } from '../../assets/utils/remotePattern.js';
7
7
  import type { SvgRenderMode } from '../../assets/utils/svg.js';
8
8
  import type { AssetsPrefix } from '../../core/app/types.js';
9
9
  import type { AstroConfigType } from '../../core/config/schema.js';
@@ -54,6 +54,25 @@ export type ServerConfig = {
54
54
  * If the given port is already in use, Astro will automatically try the next available port.
55
55
  */
56
56
  port?: number;
57
+ /**
58
+ * @name server.allowedHosts
59
+ * @type {string[] | true}
60
+ * @default `[]`
61
+ * @version 5.4.0
62
+ * @description
63
+ *
64
+ * A list of hostnames that Astro is allowed to respond to. When the value is set to `true`, any
65
+ * hostname is allowed.
66
+ *
67
+ * ```js
68
+ * {
69
+ * server: {
70
+ * allowedHosts: ['staging.example.com', 'qa.example.com']
71
+ * }
72
+ * }
73
+ * ```
74
+ */
75
+ allowedHosts?: string[] | true;
57
76
  /**
58
77
  * @name server.headers
59
78
  * @typeraw {OutgoingHttpHeaders}
@@ -12,10 +12,10 @@ export type * from './common.js';
12
12
  export type * from './manifest.js';
13
13
  export type { AstroIntegrationLogger } from '../../core/logger/core.js';
14
14
  export type { ToolbarServerHelpers } from '../../runtime/client/dev-toolbar/helpers.js';
15
+ export type { RemotePattern } from '@astrojs/internal-helpers/remote';
15
16
  export type { MarkdownHeading, RehypePlugins, RemarkPlugins, ShikiConfig, } from '@astrojs/markdown-remark';
16
17
  export type { ExternalImageService, ImageService, LocalImageService, } from '../../assets/services/service.js';
17
18
  export type { GetImageResult, ImageInputFormat, ImageMetadata, ImageOutputFormat, ImageQuality, ImageQualityPreset, ImageTransform, UnresolvedImageTransform, } from '../../assets/types.js';
18
- export type { RemotePattern } from '../../assets/utils/remotePattern.js';
19
19
  export type { AssetsPrefix, SSRManifest } from '../../core/app/types.js';
20
20
  export type { AstroCookieGetOptions, AstroCookieSetOptions, AstroCookies, } from '../../core/cookies/index.js';
21
21
  export type { ContainerRenderer } from '../../container/index.js';
@@ -195,6 +195,7 @@ export interface SSRResult {
195
195
  */
196
196
  cancelled: boolean;
197
197
  base: string;
198
+ userAssetsBase: string | undefined;
198
199
  styles: Set<SSRElement>;
199
200
  scripts: Set<SSRElement>;
200
201
  links: Set<SSRElement>;
@@ -150,6 +150,7 @@ function createDevelopmentManifest(settings) {
150
150
  clientDirectives: settings.clientDirectives,
151
151
  renderers: [],
152
152
  base: settings.config.base,
153
+ userAssetsBase: settings.config?.vite?.base,
153
154
  assetsPrefix: settings.config.build.assetsPrefix,
154
155
  site: settings.config.site,
155
156
  componentMetadata: /* @__PURE__ */ new Map(),
@@ -15,7 +15,10 @@ const markdownContentEntryType = {
15
15
  // We need to handle propagation for Markdown because they support layouts which will bring in styles.
16
16
  handlePropagation: true,
17
17
  async getRenderFunction(config) {
18
- const processor = await createMarkdownProcessor(config.markdown);
18
+ const processor = await createMarkdownProcessor({
19
+ image: config.image,
20
+ ...config.markdown
21
+ });
19
22
  return async function renderToString(entry) {
20
23
  const result = await processor.render(entry.body ?? "", {
21
24
  frontmatter: entry.data,
@@ -24,7 +27,10 @@ const markdownContentEntryType = {
24
27
  });
25
28
  return {
26
29
  html: result.code,
27
- metadata: result.metadata
30
+ metadata: {
31
+ ...result.metadata,
32
+ imagePaths: result.metadata.localImagePaths.concat(result.metadata.remoteImagePaths)
33
+ }
28
34
  };
29
35
  };
30
36
  }
@@ -2,4 +2,4 @@ export type MarkdownImagePath = {
2
2
  raw: string;
3
3
  safeName: string;
4
4
  };
5
- export declare function getMarkdownCodeForImages(imagePaths: MarkdownImagePath[], html: string): string;
5
+ export declare function getMarkdownCodeForImages(localImagePaths: MarkdownImagePath[], remoteImagePaths: string[], html: string): string;
@@ -1,11 +1,11 @@
1
- function getMarkdownCodeForImages(imagePaths, html) {
1
+ function getMarkdownCodeForImages(localImagePaths, remoteImagePaths, html) {
2
2
  return `
3
3
  import { getImage } from "astro:assets";
4
- ${imagePaths.map((entry) => `import Astro__${entry.safeName} from ${JSON.stringify(entry.raw)};`).join("\n")}
4
+ ${localImagePaths.map((entry) => `import Astro__${entry.safeName} from ${JSON.stringify(entry.raw)};`).join("\n")}
5
5
 
6
6
  const images = async function(html) {
7
7
  const imageSources = {};
8
- ${imagePaths.map((entry) => {
8
+ ${localImagePaths.map((entry) => {
9
9
  const rawUrl = JSON.stringify(entry.raw);
10
10
  return `{
11
11
  const regex = new RegExp('__ASTRO_IMAGE_="([^"]*' + ${rawUrl.replace(
@@ -22,6 +22,23 @@ function getMarkdownCodeForImages(imagePaths, html) {
22
22
  occurrenceCounter++;
23
23
  }
24
24
  }`;
25
+ }).join("\n")}
26
+ ${remoteImagePaths.map((raw) => {
27
+ const rawUrl = JSON.stringify(raw);
28
+ return `{
29
+ const regex = new RegExp('__ASTRO_IMAGE_="([^"]*' + ${rawUrl.replace(
30
+ /[.*+?^${}()|[\]\\]/g,
31
+ "\\\\$&"
32
+ )} + '[^"]*)"', 'g');
33
+ let match;
34
+ let occurrenceCounter = 0;
35
+ while ((match = regex.exec(html)) !== null) {
36
+ const matchKey = ${rawUrl} + '_' + occurrenceCounter;
37
+ const props = JSON.parse(match[1].replace(/&#x22;/g, '"'));
38
+ imageSources[matchKey] = await getImage(props);
39
+ occurrenceCounter++;
40
+ }
41
+ }`;
25
42
  }).join("\n")}
26
43
  return imageSources;
27
44
  };
@@ -44,7 +44,10 @@ function markdown({ settings, logger }) {
44
44
  const raw = safeParseFrontmatter(rawFile, id);
45
45
  const fileURL = pathToFileURL(fileId);
46
46
  if (!processor) {
47
- processor = createMarkdownProcessor(settings.config.markdown);
47
+ processor = createMarkdownProcessor({
48
+ image: settings.config.image,
49
+ ...settings.config.markdown
50
+ });
48
51
  }
49
52
  const renderResult = await (await processor).render(raw.content, {
50
53
  // @ts-expect-error passing internal prop
@@ -55,12 +58,17 @@ function markdown({ settings, logger }) {
55
58
  throw new AstroError(AstroErrorData.InvalidFrontmatterInjectionError);
56
59
  }
57
60
  let html = renderResult.code;
58
- const { headings, imagePaths: rawImagePaths, frontmatter } = renderResult.metadata;
61
+ const {
62
+ headings,
63
+ localImagePaths: rawLocalImagePaths,
64
+ remoteImagePaths,
65
+ frontmatter
66
+ } = renderResult.metadata;
59
67
  const isMarkdownPage = isPage(fileURL, settings);
60
68
  const charset = isMarkdownPage ? '<meta charset="utf-8">' : "";
61
- const imagePaths = [];
62
- for (const imagePath of rawImagePaths) {
63
- imagePaths.push({
69
+ const localImagePaths = [];
70
+ for (const imagePath of rawLocalImagePaths) {
71
+ localImagePaths.push({
64
72
  raw: imagePath,
65
73
  safeName: shorthash(imagePath)
66
74
  });
@@ -80,7 +88,7 @@ function markdown({ settings, logger }) {
80
88
  ${layout ? `import Layout from ${JSON.stringify(layout)};` : ""}
81
89
 
82
90
  ${// Only include the code relevant to `astro:assets` if there's images in the file
83
- imagePaths.length > 0 ? getMarkdownCodeForImages(imagePaths, html) : `const html = () => ${JSON.stringify(html)};`}
91
+ localImagePaths.length > 0 || remoteImagePaths.length > 0 ? getMarkdownCodeForImages(localImagePaths, remoteImagePaths, html) : `const html = () => ${JSON.stringify(html)};`}
84
92
 
85
93
  export const frontmatter = ${JSON.stringify(frontmatter)};
86
94
  export const file = ${JSON.stringify(fileId)};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "astro",
3
- "version": "5.3.0",
3
+ "version": "5.4.0",
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",
@@ -123,9 +123,8 @@
123
123
  "dlv": "^1.1.3",
124
124
  "dset": "^3.1.4",
125
125
  "es-module-lexer": "^1.6.0",
126
- "esbuild": "^0.24.2",
126
+ "esbuild": "^0.25.0",
127
127
  "estree-walker": "^3.0.3",
128
- "fast-glob": "^3.3.3",
129
128
  "flattie": "^1.1.1",
130
129
  "github-slugger": "^2.0.0",
131
130
  "html-escaper": "3.0.3",
@@ -134,23 +133,24 @@
134
133
  "kleur": "^4.1.5",
135
134
  "magic-string": "^0.30.17",
136
135
  "magicast": "^0.3.5",
137
- "micromatch": "^4.0.8",
138
136
  "mrmime": "^2.0.0",
139
137
  "neotraverse": "^0.6.18",
140
138
  "p-limit": "^6.2.0",
141
139
  "p-queue": "^8.1.0",
140
+ "picomatch": "^4.0.2",
142
141
  "preferred-pm": "^4.1.1",
143
142
  "prompts": "^2.4.2",
144
143
  "rehype": "^13.0.2",
145
144
  "semver": "^7.7.1",
146
145
  "shiki": "^1.29.2",
147
146
  "tinyexec": "^0.3.2",
147
+ "tinyglobby": "^0.2.12",
148
148
  "tsconfck": "^3.1.4",
149
149
  "ultrahtml": "^1.5.3",
150
150
  "unist-util-visit": "^5.0.0",
151
151
  "unstorage": "^1.14.4",
152
152
  "vfile": "^6.0.3",
153
- "vite": "^6.0.11",
153
+ "vite": "^6.2.0",
154
154
  "vitefu": "^1.0.5",
155
155
  "which-pm": "^3.0.1",
156
156
  "xxhash-wasm": "^1.1.0",
@@ -159,9 +159,9 @@
159
159
  "zod": "^3.24.1",
160
160
  "zod-to-json-schema": "^3.24.1",
161
161
  "zod-to-ts": "^1.2.0",
162
- "@astrojs/markdown-remark": "6.1.0",
163
- "@astrojs/telemetry": "3.2.0",
164
- "@astrojs/internal-helpers": "0.5.1"
162
+ "@astrojs/internal-helpers": "0.6.0",
163
+ "@astrojs/markdown-remark": "6.2.0",
164
+ "@astrojs/telemetry": "3.2.0"
165
165
  },
166
166
  "optionalDependencies": {
167
167
  "sharp": "^0.33.3"
@@ -179,7 +179,7 @@
179
179
  "@types/html-escaper": "3.0.4",
180
180
  "@types/http-cache-semantics": "^4.0.4",
181
181
  "@types/js-yaml": "^4.0.9",
182
- "@types/micromatch": "^4.0.9",
182
+ "@types/picomatch": "^3.0.2",
183
183
  "@types/prompts": "^2.4.9",
184
184
  "@types/semver": "^7.5.8",
185
185
  "@types/yargs-parser": "^21.0.3",
@@ -1,13 +0,0 @@
1
- import type { AstroConfig } from '../../types/public/config.js';
2
- export type RemotePattern = {
3
- hostname?: string;
4
- pathname?: string;
5
- protocol?: string;
6
- port?: string;
7
- };
8
- export declare function matchPattern(url: URL, remotePattern: RemotePattern): boolean;
9
- export declare function matchPort(url: URL, port?: string): boolean;
10
- export declare function matchProtocol(url: URL, protocol?: string): boolean;
11
- export declare function matchHostname(url: URL, hostname?: string, allowWildcard?: boolean): boolean;
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;