astro 2.5.5 → 2.5.7

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 (63) hide show
  1. package/dist/@types/astro.d.ts +9 -2
  2. package/dist/assets/services/service.js +6 -0
  3. package/dist/assets/utils/emitAsset.d.ts +1 -3
  4. package/dist/assets/utils/emitAsset.js +4 -15
  5. package/dist/assets/vite-plugin-assets.js +5 -5
  6. package/dist/config/index.js +11 -3
  7. package/dist/config/vite-plugin-content-listen.d.ts +18 -0
  8. package/dist/config/vite-plugin-content-listen.js +26 -0
  9. package/dist/content/consts.d.ts +2 -1
  10. package/dist/content/consts.js +8 -1
  11. package/dist/content/runtime-assets.d.ts +1 -2
  12. package/dist/content/runtime-assets.js +2 -3
  13. package/dist/content/runtime.js +67 -47
  14. package/dist/content/types-generator.js +9 -5
  15. package/dist/content/utils.d.ts +2 -2
  16. package/dist/content/utils.js +4 -4
  17. package/dist/content/vite-plugin-content-assets.js +26 -10
  18. package/dist/content/vite-plugin-content-imports.js +113 -150
  19. package/dist/content/vite-plugin-content-virtual-mod.d.ts +3 -3
  20. package/dist/content/vite-plugin-content-virtual-mod.js +21 -8
  21. package/dist/core/app/index.d.ts +0 -2
  22. package/dist/core/app/index.js +5 -7
  23. package/dist/core/app/node.js +4 -3
  24. package/dist/core/app/types.d.ts +3 -2
  25. package/dist/core/build/generate.js +16 -11
  26. package/dist/core/build/graph.js +3 -2
  27. package/dist/core/build/internal.d.ts +8 -4
  28. package/dist/core/build/internal.js +19 -1
  29. package/dist/core/build/plugins/plugin-css.js +9 -14
  30. package/dist/core/build/plugins/plugin-middleware.d.ts +0 -1
  31. package/dist/core/build/plugins/plugin-middleware.js +3 -16
  32. package/dist/core/build/plugins/plugin-pages.d.ts +10 -0
  33. package/dist/core/build/plugins/plugin-pages.js +40 -24
  34. package/dist/core/build/plugins/plugin-ssr.d.ts +2 -2
  35. package/dist/core/build/plugins/plugin-ssr.js +46 -20
  36. package/dist/core/build/static-build.js +18 -5
  37. package/dist/core/build/types.d.ts +2 -2
  38. package/dist/core/config/schema.d.ts +170 -170
  39. package/dist/core/constants.js +1 -1
  40. package/dist/core/dev/dev.js +1 -1
  41. package/dist/core/errors/errors-data.d.ts +57 -8
  42. package/dist/core/errors/errors-data.js +57 -12
  43. package/dist/core/messages.js +2 -2
  44. package/dist/core/render/dev/index.js +1 -2
  45. package/dist/core/render/dev/vite.js +12 -13
  46. package/dist/prerender/routing.d.ts +13 -0
  47. package/dist/prerender/routing.js +49 -0
  48. package/dist/runtime/server/astro-global.js +11 -1
  49. package/dist/runtime/server/index.d.ts +1 -1
  50. package/dist/runtime/server/index.js +9 -1
  51. package/dist/runtime/server/render/any.js +4 -2
  52. package/dist/runtime/server/render/astro/instance.js +3 -0
  53. package/dist/runtime/server/render/astro/render-template.d.ts +1 -1
  54. package/dist/runtime/server/render/astro/render-template.js +5 -9
  55. package/dist/runtime/server/render/util.d.ts +6 -0
  56. package/dist/runtime/server/render/util.js +8 -0
  57. package/dist/runtime/server/scripts.js +1 -1
  58. package/dist/vite-plugin-astro-server/route.js +3 -11
  59. package/dist/vite-plugin-head/index.js +1 -1
  60. package/dist/vite-plugin-markdown/content-entry-type.js +6 -1
  61. package/dist/vite-plugin-utils/index.js +1 -1
  62. package/package.json +4 -4
  63. package/src/content/template/virtual-mod.mjs +1 -1
@@ -454,7 +454,7 @@ export declare const AstroErrorData: {
454
454
  * For unsupported formats such as SVGs and GIFs, you may be able to use an `img` tag directly:
455
455
  * ```astro
456
456
  * ---
457
- * import rocket from '../assets/images/rocket.svg'
457
+ * import rocket from '../assets/images/rocket.svg';
458
458
  * ---
459
459
  *
460
460
  * <img src={rocket.src} width={rocket.width} height={rocket.height} alt="A rocketship in space." />
@@ -551,7 +551,7 @@ export declare const AstroErrorData: {
551
551
  * Making changes to the response, such as setting headers, cookies, and the status code cannot be done outside of page components.
552
552
  */
553
553
  readonly ResponseSentError: {
554
- readonly title: "Unable to set response";
554
+ readonly title: "Unable to set response.";
555
555
  readonly code: 3030;
556
556
  readonly message: "The response has already been sent to the browser and cannot be altered.";
557
557
  };
@@ -570,7 +570,7 @@ export declare const AstroErrorData: {
570
570
  * ```
571
571
  */
572
572
  readonly MiddlewareNoDataOrNextCalled: {
573
- readonly title: "The middleware didn't return a response or call `next`";
573
+ readonly title: "The middleware didn't return a response or call `next`.";
574
574
  readonly code: 3031;
575
575
  readonly message: "The middleware needs to either return a `Response` object or call the `next` function.";
576
576
  };
@@ -588,7 +588,7 @@ export declare const AstroErrorData: {
588
588
  * ```
589
589
  */
590
590
  readonly MiddlewareNotAResponse: {
591
- readonly title: "The middleware returned something that is not a `Response` object";
591
+ readonly title: "The middleware returned something that is not a `Response` object.";
592
592
  readonly code: 3032;
593
593
  readonly message: "Any data returned from middleware must be a valid `Response` object.";
594
594
  };
@@ -608,11 +608,61 @@ export declare const AstroErrorData: {
608
608
  * ```
609
609
  */
610
610
  readonly LocalsNotAnObject: {
611
- readonly title: "Value assigned to `locals` is not accepted";
611
+ readonly title: "Value assigned to `locals` is not accepted.";
612
612
  readonly code: 3033;
613
613
  readonly message: "`locals` can only be assigned to an object. Other values like numbers, strings, etc. are not accepted.";
614
614
  readonly hint: "If you tried to remove some information from the `locals` object, try to use `delete` or set the property to `undefined`.";
615
615
  };
616
+ /**
617
+ * @docs
618
+ * @see
619
+ * - [Assets (Experimental)](https://docs.astro.build/en/guides/assets/)
620
+ * @description
621
+ * When using the default image services, `Image`'s and `getImage`'s `src` parameter must be either an imported image or an URL, it cannot be a filepath.
622
+ *
623
+ * ```astro
624
+ * ---
625
+ * import { Image } from "astro:assets";
626
+ * import myImage from "../my_image.png";
627
+ * ---
628
+ *
629
+ * <!-- GOOD: `src` is the full imported image. -->
630
+ * <Image src={myImage} alt="Cool image" />
631
+ *
632
+ * <!-- BAD: `src` is an image's `src` path instead of the full image. -->
633
+ * <Image src={myImage.src} alt="Cool image" />
634
+ * ```
635
+ */
636
+ readonly LocalImageUsedWrongly: {
637
+ readonly title: "ESM imported images must be passed as-is.";
638
+ readonly code: 3034;
639
+ readonly message: (imageFilePath: string) => string;
640
+ };
641
+ /**
642
+ * @docs
643
+ * @see
644
+ * - [Astro.glob](https://docs.astro.build/en/reference/api-reference/#astroglob)
645
+ * @description
646
+ * `Astro.glob()` can only be used in `.astro` files. You can use [`import.meta.glob()`](https://vitejs.dev/guide/features.html#glob-import) instead to acheive the same result.
647
+ */
648
+ readonly AstroGlobUsedOutside: {
649
+ readonly title: "Astro.glob() used outside of an Astro file.";
650
+ readonly code: 3035;
651
+ readonly message: (globStr: string) => string;
652
+ readonly hint: "See Vite's documentation on `import.meta.glob` for more information: https://vitejs.dev/guide/features.html#glob-import";
653
+ };
654
+ /**
655
+ * @docs
656
+ * @see
657
+ * - [Astro.glob](https://docs.astro.build/en/reference/api-reference/#astroglob)
658
+ * @description
659
+ * `Astro.glob()` did not return any matching files. There might be a typo in the glob pattern.
660
+ */
661
+ readonly AstroGlobNoMatch: {
662
+ readonly title: "Astro.glob() did not match any files.";
663
+ readonly code: 3036;
664
+ readonly message: (globStr: string) => string;
665
+ };
616
666
  /**
617
667
  * @docs
618
668
  * @see
@@ -858,7 +908,6 @@ export declare const AstroErrorData: {
858
908
  };
859
909
  /**
860
910
  * @docs
861
- * @message A content collection schema should not contain `slug` since it is reserved for slug generation. Remove this from your `COLLECTION_NAME` collection schema.
862
911
  * @see
863
912
  * - [The reserved entry `slug` field](https://docs.astro.build/en/guides/content-collections/)
864
913
  * @description
@@ -867,7 +916,7 @@ export declare const AstroErrorData: {
867
916
  readonly ContentSchemaContainsSlugError: {
868
917
  readonly title: "Content Schema should not contain `slug`.";
869
918
  readonly code: 9003;
870
- readonly message: (collection: string) => string;
919
+ readonly message: (collectionName: string) => string;
871
920
  readonly hint: "See https://docs.astro.build/en/guides/content-collections/ for more on the `slug` field.";
872
921
  };
873
922
  /**
@@ -879,7 +928,7 @@ export declare const AstroErrorData: {
879
928
  readonly CollectionDoesNotExistError: {
880
929
  readonly title: "Collection does not exist";
881
930
  readonly code: 9004;
882
- readonly message: (collection: string) => string;
931
+ readonly message: (collectionName: string) => string;
883
932
  readonly hint: "See https://docs.astro.build/en/guides/content-collections/ for more on creating collections.";
884
933
  };
885
934
  /**
@@ -466,7 +466,7 @@ Expected \`${defaultExpectedValue}\` value but got \`${suffix}\`.`;
466
466
  * For unsupported formats such as SVGs and GIFs, you may be able to use an `img` tag directly:
467
467
  * ```astro
468
468
  * ---
469
- * import rocket from '../assets/images/rocket.svg'
469
+ * import rocket from '../assets/images/rocket.svg';
470
470
  * ---
471
471
  *
472
472
  * <img src={rocket.src} width={rocket.width} height={rocket.height} alt="A rocketship in space." />
@@ -565,7 +565,7 @@ Expected \`${defaultExpectedValue}\` value but got \`${suffix}\`.`;
565
565
  * Making changes to the response, such as setting headers, cookies, and the status code cannot be done outside of page components.
566
566
  */
567
567
  ResponseSentError: {
568
- title: "Unable to set response",
568
+ title: "Unable to set response.",
569
569
  code: 3030,
570
570
  message: "The response has already been sent to the browser and cannot be altered."
571
571
  },
@@ -584,7 +584,7 @@ Expected \`${defaultExpectedValue}\` value but got \`${suffix}\`.`;
584
584
  * ```
585
585
  */
586
586
  MiddlewareNoDataOrNextCalled: {
587
- title: "The middleware didn't return a response or call `next`",
587
+ title: "The middleware didn't return a response or call `next`.",
588
588
  code: 3031,
589
589
  message: "The middleware needs to either return a `Response` object or call the `next` function."
590
590
  },
@@ -602,7 +602,7 @@ Expected \`${defaultExpectedValue}\` value but got \`${suffix}\`.`;
602
602
  * ```
603
603
  */
604
604
  MiddlewareNotAResponse: {
605
- title: "The middleware returned something that is not a `Response` object",
605
+ title: "The middleware returned something that is not a `Response` object.",
606
606
  code: 3032,
607
607
  message: "Any data returned from middleware must be a valid `Response` object."
608
608
  },
@@ -622,11 +622,61 @@ Expected \`${defaultExpectedValue}\` value but got \`${suffix}\`.`;
622
622
  * ```
623
623
  */
624
624
  LocalsNotAnObject: {
625
- title: "Value assigned to `locals` is not accepted",
625
+ title: "Value assigned to `locals` is not accepted.",
626
626
  code: 3033,
627
627
  message: "`locals` can only be assigned to an object. Other values like numbers, strings, etc. are not accepted.",
628
628
  hint: "If you tried to remove some information from the `locals` object, try to use `delete` or set the property to `undefined`."
629
629
  },
630
+ /**
631
+ * @docs
632
+ * @see
633
+ * - [Assets (Experimental)](https://docs.astro.build/en/guides/assets/)
634
+ * @description
635
+ * When using the default image services, `Image`'s and `getImage`'s `src` parameter must be either an imported image or an URL, it cannot be a filepath.
636
+ *
637
+ * ```astro
638
+ * ---
639
+ * import { Image } from "astro:assets";
640
+ * import myImage from "../my_image.png";
641
+ * ---
642
+ *
643
+ * <!-- GOOD: `src` is the full imported image. -->
644
+ * <Image src={myImage} alt="Cool image" />
645
+ *
646
+ * <!-- BAD: `src` is an image's `src` path instead of the full image. -->
647
+ * <Image src={myImage.src} alt="Cool image" />
648
+ * ```
649
+ */
650
+ LocalImageUsedWrongly: {
651
+ title: "ESM imported images must be passed as-is.",
652
+ code: 3034,
653
+ message: (imageFilePath) => `\`Image\`'s and \`getImage\`'s \`src\` parameter must be an imported image or an URL, it cannot be a filepath. Received \`${imageFilePath}\`.`
654
+ },
655
+ /**
656
+ * @docs
657
+ * @see
658
+ * - [Astro.glob](https://docs.astro.build/en/reference/api-reference/#astroglob)
659
+ * @description
660
+ * `Astro.glob()` can only be used in `.astro` files. You can use [`import.meta.glob()`](https://vitejs.dev/guide/features.html#glob-import) instead to acheive the same result.
661
+ */
662
+ AstroGlobUsedOutside: {
663
+ title: "Astro.glob() used outside of an Astro file.",
664
+ code: 3035,
665
+ message: (globStr) => `\`Astro.glob(${globStr})\` can only be used in \`.astro\` files. \`import.meta.glob(${globStr})\` can be used instead to achieve a similar result.`,
666
+ hint: "See Vite's documentation on `import.meta.glob` for more information: https://vitejs.dev/guide/features.html#glob-import"
667
+ },
668
+ /**
669
+ * @docs
670
+ * @see
671
+ * - [Astro.glob](https://docs.astro.build/en/reference/api-reference/#astroglob)
672
+ * @description
673
+ * `Astro.glob()` did not return any matching files. There might be a typo in the glob pattern.
674
+ */
675
+ AstroGlobNoMatch: {
676
+ title: "Astro.glob() did not match any files.",
677
+ code: 3036,
678
+ message: (globStr) => `\`Astro.glob(${globStr})\` did not return any matching files. Check the pattern for typos.`
679
+ },
630
680
  // No headings here, that way Vite errors are merged with Astro ones in the docs, which makes more sense to users.
631
681
  // Vite Errors - 4xxx
632
682
  /**
@@ -890,7 +940,6 @@ Expected \`${defaultExpectedValue}\` value but got \`${suffix}\`.`;
890
940
  },
891
941
  /**
892
942
  * @docs
893
- * @message A content collection schema should not contain `slug` since it is reserved for slug generation. Remove this from your `COLLECTION_NAME` collection schema.
894
943
  * @see
895
944
  * - [The reserved entry `slug` field](https://docs.astro.build/en/guides/content-collections/)
896
945
  * @description
@@ -899,9 +948,7 @@ Expected \`${defaultExpectedValue}\` value but got \`${suffix}\`.`;
899
948
  ContentSchemaContainsSlugError: {
900
949
  title: "Content Schema should not contain `slug`.",
901
950
  code: 9003,
902
- message: (collection) => {
903
- return `A content collection schema should not contain \`slug\` since it is reserved for slug generation. Remove this from your ${collection} collection schema.`;
904
- },
951
+ message: (collectionName) => `A content collection schema should not contain \`slug\` since it is reserved for slug generation. Remove this from your ${collectionName} collection schema.`,
905
952
  hint: "See https://docs.astro.build/en/guides/content-collections/ for more on the `slug` field."
906
953
  },
907
954
  /**
@@ -913,9 +960,7 @@ Expected \`${defaultExpectedValue}\` value but got \`${suffix}\`.`;
913
960
  CollectionDoesNotExistError: {
914
961
  title: "Collection does not exist",
915
962
  code: 9004,
916
- message: (collection) => {
917
- return `The collection **${collection}** does not exist. Ensure a collection directory with this name exists.`;
918
- },
963
+ message: (collectionName) => `The collection **${collectionName}** does not exist. Ensure a collection directory with this name exists.`,
919
964
  hint: "See https://docs.astro.build/en/guides/content-collections/ for more on creating collections."
920
965
  },
921
966
  /**
@@ -47,7 +47,7 @@ function serverStart({
47
47
  base,
48
48
  isRestart = false
49
49
  }) {
50
- const version = "2.5.5";
50
+ const version = "2.5.7";
51
51
  const localPrefix = `${dim("\u2503")} Local `;
52
52
  const networkPrefix = `${dim("\u2503")} Network `;
53
53
  const emptyPrefix = " ".repeat(11);
@@ -233,7 +233,7 @@ function printHelp({
233
233
  message.push(
234
234
  linebreak(),
235
235
  ` ${bgGreen(black(` ${commandName} `))} ${green(
236
- `v${"2.5.5"}`
236
+ `v${"2.5.7"}`
237
237
  )} ${headline}`
238
238
  );
239
239
  }
@@ -1,4 +1,3 @@
1
- import { fileURLToPath } from "url";
2
1
  import { PAGE_SCRIPT_ID } from "../../../vite-plugin-scripts/index.js";
3
2
  import { createAPIContext } from "../../endpoint/index.js";
4
3
  import { enhanceViteSSRError } from "../../errors/dev/index.js";
@@ -22,7 +21,7 @@ async function preload({
22
21
  }) {
23
22
  const renderers = await loadRenderers(env.loader, env.settings);
24
23
  try {
25
- const mod = await env.loader.import(fileURLToPath(filePath));
24
+ const mod = await env.loader.import(viteID(filePath));
26
25
  return [renderers, mod];
27
26
  } catch (error) {
28
27
  if (MarkdownError.is(error) || CSSError.is(error) || AggregateError.is(error)) {
@@ -1,15 +1,13 @@
1
1
  import npath from "path";
2
- import { PROPAGATED_ASSET_FLAG } from "../../../content/consts.js";
3
2
  import { SUPPORTED_MARKDOWN_FILE_EXTENSIONS } from "../../constants.js";
4
3
  import { unwrapId } from "../../util.js";
5
4
  import { isCSSRequest } from "./util.js";
6
- const fileExtensionsToSSR = /* @__PURE__ */ new Set([".astro", ...SUPPORTED_MARKDOWN_FILE_EXTENSIONS]);
5
+ const fileExtensionsToSSR = /* @__PURE__ */ new Set([".astro", ".mdoc", ...SUPPORTED_MARKDOWN_FILE_EXTENSIONS]);
7
6
  const STRIP_QUERY_PARAMS_REGEX = /\?.*$/;
7
+ const ASTRO_PROPAGATED_ASSET_REGEX = /\?astroPropagatedAssets/;
8
8
  async function* crawlGraph(loader, _id, isRootFile, scanned = /* @__PURE__ */ new Set()) {
9
9
  const id = unwrapId(_id);
10
10
  const importedModules = /* @__PURE__ */ new Set();
11
- if (new URL(id, "file://").searchParams.has(PROPAGATED_ASSET_FLAG))
12
- return;
13
11
  const moduleEntriesForId = isRootFile ? (
14
12
  // "getModulesByFile" pulls from a delayed module cache (fun implementation detail),
15
13
  // So we can get up-to-date info on initial server load.
@@ -28,19 +26,18 @@ async function* crawlGraph(loader, _id, isRootFile, scanned = /* @__PURE__ */ ne
28
26
  scanned.add(id);
29
27
  const entryIsStyle = isCSSRequest(id);
30
28
  for (const importedModule of entry.importedModules) {
29
+ let isPropagationStoppingPoint = false;
31
30
  if (importedModule.id) {
32
31
  const importedModulePathname = importedModule.id.replace(STRIP_QUERY_PARAMS_REGEX, "");
33
32
  if (entryIsStyle && !isCSSRequest(importedModulePathname)) {
34
33
  continue;
35
34
  }
36
- if (fileExtensionsToSSR.has(
37
- npath.extname(
38
- // Use `id` instead of `pathname` to preserve query params.
39
- // Should not SSR a module with an unexpected query param,
40
- // like "?astroPropagatedAssets"
41
- importedModule.id
42
- )
43
- )) {
35
+ const isFileTypeNeedingSSR = fileExtensionsToSSR.has(
36
+ npath.extname(importedModulePathname)
37
+ );
38
+ isPropagationStoppingPoint = ASTRO_PROPAGATED_ASSET_REGEX.test(importedModule.id);
39
+ if (isFileTypeNeedingSSR && // Should not SSR a module with ?astroPropagatedAssets
40
+ !isPropagationStoppingPoint) {
44
41
  const mod = loader.getModuleById(importedModule.id);
45
42
  if (!(mod == null ? void 0 : mod.ssrModule)) {
46
43
  try {
@@ -50,7 +47,9 @@ async function* crawlGraph(loader, _id, isRootFile, scanned = /* @__PURE__ */ ne
50
47
  }
51
48
  }
52
49
  }
53
- importedModules.add(importedModule);
50
+ if (!isPropagationStoppingPoint) {
51
+ importedModules.add(importedModule);
52
+ }
54
53
  }
55
54
  }
56
55
  }
@@ -0,0 +1,13 @@
1
+ import type { AstroSettings, RouteData } from '../@types/astro';
2
+ import { type DevelopmentEnvironment } from '../core/render/dev/index.js';
3
+ type GetSortedPreloadedMatchesParams = {
4
+ env: DevelopmentEnvironment;
5
+ matches: RouteData[];
6
+ settings: AstroSettings;
7
+ };
8
+ export declare function getSortedPreloadedMatches({ env, matches, settings, }: GetSortedPreloadedMatchesParams): Promise<{
9
+ readonly preloadedComponent: import("../core/render/dev/index.js").ComponentPreload;
10
+ readonly route: RouteData;
11
+ readonly filePath: URL;
12
+ }[]>;
13
+ export {};
@@ -0,0 +1,49 @@
1
+ import { preload } from "../core/render/dev/index.js";
2
+ import { getPrerenderStatus } from "./metadata.js";
3
+ async function getSortedPreloadedMatches({
4
+ env,
5
+ matches,
6
+ settings
7
+ }) {
8
+ return (await preloadAndSetPrerenderStatus({
9
+ env,
10
+ matches,
11
+ settings
12
+ })).sort((a, b) => prioritizePrerenderedMatchesComparator(a.route, b.route));
13
+ }
14
+ async function preloadAndSetPrerenderStatus({
15
+ env,
16
+ matches,
17
+ settings
18
+ }) {
19
+ const preloaded = await Promise.all(
20
+ matches.map(async (route) => {
21
+ const filePath = new URL(`./${route.component}`, settings.config.root);
22
+ const preloadedComponent = await preload({ env, filePath });
23
+ const prerenderStatus = getPrerenderStatus({
24
+ filePath,
25
+ loader: env.loader
26
+ });
27
+ if (prerenderStatus !== void 0) {
28
+ route.prerender = prerenderStatus;
29
+ }
30
+ return { preloadedComponent, route, filePath };
31
+ })
32
+ );
33
+ return preloaded;
34
+ }
35
+ function prioritizePrerenderedMatchesComparator(a, b) {
36
+ if (areRegexesEqual(a.pattern, b.pattern)) {
37
+ if (a.prerender !== b.prerender) {
38
+ return a.prerender ? -1 : 1;
39
+ }
40
+ return a.component < b.component ? -1 : 1;
41
+ }
42
+ return 0;
43
+ }
44
+ function areRegexesEqual(regexp1, regexp2) {
45
+ return regexp1.source === regexp2.source && regexp1.global === regexp2.global;
46
+ }
47
+ export {
48
+ getSortedPreloadedMatches
49
+ };
@@ -1,9 +1,19 @@
1
1
  import { ASTRO_VERSION } from "../../core/constants.js";
2
+ import { AstroError, AstroErrorData } from "../../core/errors/index.js";
2
3
  function createAstroGlobFn() {
3
4
  const globHandler = (importMetaGlobResult, globValue) => {
5
+ if (typeof importMetaGlobResult === "string") {
6
+ throw new AstroError({
7
+ ...AstroErrorData.AstroGlobUsedOutside,
8
+ message: AstroErrorData.AstroGlobUsedOutside.message(JSON.stringify(importMetaGlobResult))
9
+ });
10
+ }
4
11
  let allEntries = [...Object.values(importMetaGlobResult)];
5
12
  if (allEntries.length === 0) {
6
- throw new Error(`Astro.glob(${JSON.stringify(globValue())}) - no matches found.`);
13
+ throw new AstroError({
14
+ ...AstroErrorData.AstroGlobNoMatch,
15
+ message: AstroErrorData.AstroGlobNoMatch.message(JSON.stringify(importMetaGlobResult))
16
+ });
7
17
  }
8
18
  return Promise.all(allEntries.map((fn) => fn()));
9
19
  };
@@ -1,7 +1,7 @@
1
1
  export { createComponent } from './astro-component.js';
2
2
  export { createAstro } from './astro-global.js';
3
3
  export { renderEndpoint } from './endpoint.js';
4
- export { escapeHTML, HTMLBytes, HTMLString, markHTMLString, unescapeHTML } from './escape.js';
4
+ export { escapeHTML, HTMLBytes, HTMLString, isHTMLString, markHTMLString, unescapeHTML, } from './escape.js';
5
5
  export { renderJSX } from './jsx.js';
6
6
  export { addAttribute, createHeadAndContent, defineScriptVars, Fragment, maybeRenderHead, renderAstroTemplateResult as renderAstroComponent, renderComponent, renderComponentToIterable, Renderer as Renderer, renderHead, renderHTMLElement, renderPage, renderScriptElement, renderSlot, renderSlotToString, renderTemplate as render, renderTemplate, renderToString, renderUniqueStylesheet, stringifyChunk, voidElementNames, } from './render/index.js';
7
7
  export type { AstroComponentFactory, AstroComponentInstance, ComponentSlots, RenderInstruction, } from './render/index.js';
@@ -1,7 +1,14 @@
1
1
  import { createComponent } from "./astro-component.js";
2
2
  import { createAstro } from "./astro-global.js";
3
3
  import { renderEndpoint } from "./endpoint.js";
4
- import { escapeHTML, HTMLBytes, HTMLString, markHTMLString, unescapeHTML } from "./escape.js";
4
+ import {
5
+ escapeHTML,
6
+ HTMLBytes,
7
+ HTMLString,
8
+ isHTMLString,
9
+ markHTMLString,
10
+ unescapeHTML
11
+ } from "./escape.js";
5
12
  import { renderJSX } from "./jsx.js";
6
13
  import {
7
14
  addAttribute,
@@ -93,6 +100,7 @@ export {
93
100
  defineScriptVars,
94
101
  defineStyleVars,
95
102
  escapeHTML,
103
+ isHTMLString,
96
104
  markHTMLString,
97
105
  maybeRenderHead,
98
106
  mergeSlots,
@@ -5,6 +5,7 @@ import {
5
5
  renderAstroTemplateResult
6
6
  } from "./astro/index.js";
7
7
  import { SlotString } from "./slot.js";
8
+ import { bufferIterators } from "./util.js";
8
9
  async function* renderChild(child) {
9
10
  child = await child;
10
11
  if (child instanceof SlotString) {
@@ -15,8 +16,9 @@ async function* renderChild(child) {
15
16
  } else if (isHTMLString(child)) {
16
17
  yield child;
17
18
  } else if (Array.isArray(child)) {
18
- for (const value of child) {
19
- yield markHTMLString(await renderChild(value));
19
+ const bufferedIterators = bufferIterators(child.map((c) => renderChild(c)));
20
+ for (const value of bufferedIterators) {
21
+ yield markHTMLString(await value);
20
22
  }
21
23
  } else if (typeof child === "function") {
22
24
  yield* renderChild(child());
@@ -29,6 +29,9 @@ class AstroComponentInstance {
29
29
  value = await value;
30
30
  }
31
31
  if (isHeadAndContent(value)) {
32
+ if (this.result.extraHead.length === 0 && value.head) {
33
+ yield renderChild(value.head);
34
+ }
32
35
  yield* value.content;
33
36
  } else {
34
37
  yield* renderChild(value);
@@ -7,7 +7,7 @@ export declare class RenderTemplateResult {
7
7
  private expressions;
8
8
  private error;
9
9
  constructor(htmlParts: TemplateStringsArray, expressions: unknown[]);
10
- [Symbol.asyncIterator](): AsyncGenerator<any, void, unknown>;
10
+ [Symbol.asyncIterator](): AsyncGenerator<any, void, undefined>;
11
11
  }
12
12
  export declare function isRenderTemplateResult(obj: unknown): obj is RenderTemplateResult;
13
13
  export declare function renderAstroTemplateResult(component: RenderTemplateResult): AsyncIterable<string | HTMLBytes | RenderInstruction>;
@@ -2,7 +2,7 @@ var _a;
2
2
  import { markHTMLString } from "../../escape.js";
3
3
  import { isPromise } from "../../util.js";
4
4
  import { renderChild } from "../any.js";
5
- import { EagerAsyncIterableIterator } from "../util.js";
5
+ import { bufferIterators } from "../util.js";
6
6
  const renderTemplateResultSym = Symbol.for("astro.renderTemplateResult");
7
7
  class RenderTemplateResult {
8
8
  constructor(htmlParts, expressions) {
@@ -23,18 +23,14 @@ class RenderTemplateResult {
23
23
  }
24
24
  async *[(_a = renderTemplateResultSym, Symbol.asyncIterator)]() {
25
25
  const { htmlParts, expressions } = this;
26
- let iterables = [];
27
- for (let i = 0; i < htmlParts.length; i++) {
28
- iterables.push(new EagerAsyncIterableIterator(renderChild(expressions[i])));
29
- }
30
- setTimeout(() => {
31
- iterables.forEach((it) => !it.isStarted() && it.buffer());
32
- }, 0);
26
+ let iterables = bufferIterators(expressions.map((e) => renderChild(e)));
33
27
  for (let i = 0; i < htmlParts.length; i++) {
34
28
  const html = htmlParts[i];
35
29
  const iterable = iterables[i];
36
30
  yield markHTMLString(html);
37
- yield* iterable;
31
+ if (iterable) {
32
+ yield* iterable;
33
+ }
38
34
  }
39
35
  }
40
36
  }
@@ -6,6 +6,12 @@ export declare function formatList(values: string[]): string;
6
6
  export declare function addAttribute(value: any, key: string, shouldEscape?: boolean): any;
7
7
  export declare function internalSpreadAttributes(values: Record<any, any>, shouldEscape?: boolean): any;
8
8
  export declare function renderElement(name: string, { props: _props, children }: SSRElement, shouldEscape?: boolean): string;
9
+ /**
10
+ * This will take an array of async iterables and start buffering them eagerly.
11
+ * To avoid useless buffering, it will only start buffering the next tick, so the
12
+ * first sync iterables won't be buffered.
13
+ */
14
+ export declare function bufferIterators<T>(iterators: AsyncIterable<T>[]): AsyncIterable<T>[];
9
15
  export declare class EagerAsyncIterableIterator {
10
16
  #private;
11
17
  constructor(iterable: AsyncIterable<any>);
@@ -96,6 +96,13 @@ function renderElement(name, { props: _props, children = "" }, shouldEscape = tr
96
96
  }
97
97
  return `<${name}${internalSpreadAttributes(props, shouldEscape)}>${children}</${name}>`;
98
98
  }
99
+ function bufferIterators(iterators) {
100
+ const eagerIterators = iterators.map((it) => new EagerAsyncIterableIterator(it));
101
+ setTimeout(() => {
102
+ eagerIterators.forEach((it) => !it.isStarted() && it.buffer());
103
+ }, 0);
104
+ return eagerIterators;
105
+ }
99
106
  class EagerAsyncIterableIterator {
100
107
  #iterable;
101
108
  #queue = new Queue();
@@ -183,6 +190,7 @@ class Queue {
183
190
  export {
184
191
  EagerAsyncIterableIterator,
185
192
  addAttribute,
193
+ bufferIterators,
186
194
  defineScriptVars,
187
195
  formatList,
188
196
  internalSpreadAttributes,
@@ -1,5 +1,5 @@
1
1
  import islandScript from "./astro-island.prebuilt.js";
2
- const ISLAND_STYLES = `<style>astro-island,astro-slot{display:contents}</style>`;
2
+ const ISLAND_STYLES = `<style>astro-island,astro-slot,astro-static-slot{display:contents}</style>`;
3
3
  function determineIfNeedsHydrationScript(result) {
4
4
  if (result._metadata.hasHydrationScript) {
5
5
  return false;
@@ -9,7 +9,7 @@ import { preload, renderPage } from "../core/render/dev/index.js";
9
9
  import { getParamsAndProps, GetParamsAndPropsError } from "../core/render/index.js";
10
10
  import { createRequest } from "../core/request.js";
11
11
  import { matchAllRoutes } from "../core/routing/index.js";
12
- import { getPrerenderStatus } from "../prerender/metadata.js";
12
+ import { getSortedPreloadedMatches } from "../prerender/routing.js";
13
13
  import { isHybridOutput } from "../prerender/utils.js";
14
14
  import { log404 } from "./common.js";
15
15
  import { handle404Response, writeSSRResult, writeWebResponse } from "./response.js";
@@ -20,16 +20,8 @@ function getCustom404Route(manifest) {
20
20
  async function matchRoute(pathname, env, manifest) {
21
21
  const { logging, settings, routeCache } = env;
22
22
  const matches = matchAllRoutes(pathname, manifest);
23
- for await (const maybeRoute of matches) {
24
- const filePath = new URL(`./${maybeRoute.component}`, settings.config.root);
25
- const preloadedComponent = await preload({ env, filePath });
26
- const prerenderStatus = getPrerenderStatus({
27
- filePath,
28
- loader: env.loader
29
- });
30
- if (prerenderStatus !== void 0) {
31
- maybeRoute.prerender = prerenderStatus;
32
- }
23
+ const preloadedMatches = await getSortedPreloadedMatches({ env, matches, settings });
24
+ for await (const { preloadedComponent, route: maybeRoute, filePath } of preloadedMatches) {
33
25
  const [, mod] = preloadedComponent;
34
26
  const paramsAndPropsRes = await getParamsAndProps({
35
27
  mod,
@@ -1,6 +1,6 @@
1
1
  import { getTopLevelPages, walkParentInfos } from "../core/build/graph.js";
2
2
  import { getAstroMetadata } from "../vite-plugin-astro/index.js";
3
- const injectExp = /^\/\/\s*astro-head-inject/;
3
+ const injectExp = /(^\/\/|\/\/!)\s*astro-head-inject/;
4
4
  function configHeadVitePlugin({
5
5
  settings
6
6
  }) {
@@ -10,7 +10,9 @@ const markdownContentEntryType = {
10
10
  slug: parsed.data.slug,
11
11
  rawData: parsed.matter
12
12
  };
13
- }
13
+ },
14
+ // We need to handle propagation for Markdown because they support layouts which will bring in styles.
15
+ handlePropagation: true
14
16
  };
15
17
  const mdxContentEntryType = {
16
18
  extensions: [".mdx"],
@@ -23,6 +25,9 @@ const mdxContentEntryType = {
23
25
  rawData: parsed.matter
24
26
  };
25
27
  },
28
+ // MDX can import scripts and styles,
29
+ // so wrap all MDX files with script / style propagation checks
30
+ handlePropagation: true,
26
31
  contentModuleTypes: `declare module 'astro:content' {
27
32
  interface Render {
28
33
  '.mdx': Promise<{
@@ -7,7 +7,7 @@ import {
7
7
  } from "../core/path.js";
8
8
  import { viteID } from "../core/util.js";
9
9
  function escapeViteEnvReferences(code) {
10
- return code.replace(/import\.meta\.env/g, "import\\u002Emeta.env");
10
+ return code.replace(/import\.meta\.env/g, "import\\u002Emeta.env").replace(/process\.env/g, "process\\u002Eenv");
11
11
  }
12
12
  function getFileInfo(id, config) {
13
13
  const sitePathname = appendForwardSlash(