astro 4.7.0 → 4.7.1

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 (42) hide show
  1. package/dist/@types/astro.d.ts +1 -1
  2. package/dist/config/index.js +1 -1
  3. package/dist/content/index.d.ts +0 -1
  4. package/dist/content/index.js +0 -2
  5. package/dist/content/utils.js +1 -3
  6. package/dist/core/build/generate.js +1 -1
  7. package/dist/core/build/index.js +1 -1
  8. package/dist/core/build/plugins/plugin-manifest.js +1 -1
  9. package/dist/core/build/plugins/plugin-ssr.js +1 -1
  10. package/dist/core/build/static-build.js +1 -1
  11. package/dist/core/compile/compile.js +1 -1
  12. package/dist/core/constants.d.ts +1 -1
  13. package/dist/core/constants.js +1 -1
  14. package/dist/core/dev/container.js +1 -1
  15. package/dist/core/dev/dev.js +1 -1
  16. package/dist/core/errors/errors-data.d.ts +1 -1
  17. package/dist/core/errors/errors-data.js +2 -2
  18. package/dist/core/errors/index.d.ts +1 -0
  19. package/dist/core/errors/index.js +2 -0
  20. package/dist/core/errors/overlay.js +2 -2
  21. package/dist/core/messages.js +2 -2
  22. package/dist/core/preview/index.js +1 -1
  23. package/dist/core/routing/priority.d.ts +1 -1
  24. package/dist/core/sync/index.js +1 -1
  25. package/dist/integrations/{index.js → hooks.js} +1 -1
  26. package/dist/prerender/utils.d.ts +1 -1
  27. package/dist/runtime/client/dev-toolbar/helpers.d.ts +1 -1
  28. package/dist/runtime/client/dev-toolbar/helpers.js +1 -1
  29. package/dist/runtime/server/astro-global.js +1 -1
  30. package/dist/runtime/server/render/astro/instance.js +10 -10
  31. package/dist/runtime/server/render/util.js +3 -1
  32. package/dist/transitions/events.d.ts +5 -4
  33. package/dist/transitions/events.js +13 -7
  34. package/dist/transitions/router.js +93 -34
  35. package/dist/vite-plugin-astro-server/vite.js +4 -5
  36. package/dist/vite-plugin-integrations-container/index.js +1 -1
  37. package/package.json +12 -12
  38. /package/dist/{content/error-map.d.ts → core/errors/zod-error-map.d.ts} +0 -0
  39. /package/dist/{content/error-map.js → core/errors/zod-error-map.js} +0 -0
  40. /package/dist/integrations/{astroFeaturesValidation.d.ts → features-validation.d.ts} +0 -0
  41. /package/dist/integrations/{astroFeaturesValidation.js → features-validation.js} +0 -0
  42. /package/dist/integrations/{index.d.ts → hooks.d.ts} +0 -0
@@ -14,7 +14,7 @@ import type { AstroTimer } from '../core/config/timer.js';
14
14
  import type { TSConfig } from '../core/config/tsconfig.js';
15
15
  import type { AstroCookies } from '../core/cookies/index.js';
16
16
  import type { AstroIntegrationLogger, Logger, LoggerLevel } from '../core/logger/core.js';
17
- import type { getToolbarServerCommunicationHelpers } from '../integrations/index.js';
17
+ import type { getToolbarServerCommunicationHelpers } from '../integrations/hooks.js';
18
18
  import type { AstroPreferences } from '../preferences/index.js';
19
19
  import type { ToolbarAppEventTarget, ToolbarServerHelpers } from '../runtime/client/dev-toolbar/helpers.js';
20
20
  import type { AstroDevToolbar, DevToolbarCanvas } from '../runtime/client/dev-toolbar/toolbar.js';
@@ -19,7 +19,7 @@ function getViteConfig(inlineConfig) {
19
19
  import("../core/logger/node.js"),
20
20
  import("../core/config/index.js"),
21
21
  import("../core/create-vite.js"),
22
- import("../integrations/index.js"),
22
+ import("../integrations/hooks.js"),
23
23
  import("./vite-plugin-content-listen.js")
24
24
  ]);
25
25
  const logger = new Logger({
@@ -1,5 +1,4 @@
1
1
  export { CONTENT_FLAG, PROPAGATED_ASSET_FLAG } from './consts.js';
2
- export { errorMap } from './error-map.js';
3
2
  export { attachContentServerListeners } from './server-listeners.js';
4
3
  export { createContentTypesGenerator } from './types-generator.js';
5
4
  export { contentObservable, getContentPaths, getDotAstroTypeReference, hasAssetPropagationFlag, } from './utils.js';
@@ -1,5 +1,4 @@
1
1
  import { CONTENT_FLAG, PROPAGATED_ASSET_FLAG } from "./consts.js";
2
- import { errorMap } from "./error-map.js";
3
2
  import { attachContentServerListeners } from "./server-listeners.js";
4
3
  import { createContentTypesGenerator } from "./types-generator.js";
5
4
  import {
@@ -20,7 +19,6 @@ export {
20
19
  attachContentServerListeners,
21
20
  contentObservable,
22
21
  createContentTypesGenerator,
23
- errorMap,
24
22
  getContentPaths,
25
23
  getDotAstroTypeReference,
26
24
  hasAssetPropagationFlag
@@ -5,11 +5,9 @@ import { slug as githubSlug } from "github-slugger";
5
5
  import matter from "gray-matter";
6
6
  import { normalizePath } from "vite";
7
7
  import { z } from "zod";
8
- import { AstroError, AstroErrorData } from "../core/errors/index.js";
9
- import { MarkdownError } from "../core/errors/index.js";
8
+ import { AstroError, AstroErrorData, MarkdownError, errorMap } from "../core/errors/index.js";
10
9
  import { isYAMLException } from "../core/errors/utils.js";
11
10
  import { CONTENT_FLAGS, CONTENT_TYPES_FILE, PROPAGATED_ASSET_FLAG } from "./consts.js";
12
- import { errorMap } from "./error-map.js";
13
11
  import { createImage } from "./runtime-assets.js";
14
12
  const collectionConfigParser = z.union([
15
13
  z.object({
@@ -17,7 +17,7 @@ import {
17
17
  removeTrailingForwardSlash
18
18
  } from "../../core/path.js";
19
19
  import { toRoutingStrategy } from "../../i18n/utils.js";
20
- import { runHookBuildGenerated } from "../../integrations/index.js";
20
+ import { runHookBuildGenerated } from "../../integrations/hooks.js";
21
21
  import { getOutputDirectory, isServerLikeOutput } from "../../prerender/utils.js";
22
22
  import { NoPrerenderedRoutesWithDomains } from "../errors/errors-data.js";
23
23
  import { AstroError, AstroErrorData } from "../errors/index.js";
@@ -10,7 +10,7 @@ import {
10
10
  runHookBuildStart,
11
11
  runHookConfigDone,
12
12
  runHookConfigSetup
13
- } from "../../integrations/index.js";
13
+ } from "../../integrations/hooks.js";
14
14
  import { isServerLikeOutput } from "../../prerender/utils.js";
15
15
  import { resolveConfig } from "../config/config.js";
16
16
  import { createNodeLogger } from "../config/logging.js";
@@ -4,7 +4,7 @@ import {} from "vite";
4
4
  import { getAssetsPrefix } from "../../../assets/utils/getAssetsPrefix.js";
5
5
  import { normalizeTheLocale } from "../../../i18n/index.js";
6
6
  import { toRoutingStrategy } from "../../../i18n/utils.js";
7
- import { runHookBuildSsr } from "../../../integrations/index.js";
7
+ import { runHookBuildSsr } from "../../../integrations/hooks.js";
8
8
  import { BEFORE_HYDRATION_SCRIPT_ID, PAGE_SCRIPT_ID } from "../../../vite-plugin-scripts/index.js";
9
9
  import { fileExtension, joinPaths, prependForwardSlash } from "../../path.js";
10
10
  import { serializeRouteData } from "../../routing/index.js";
@@ -1,6 +1,6 @@
1
1
  import { join } from "node:path";
2
2
  import { fileURLToPath, pathToFileURL } from "node:url";
3
- import { isFunctionPerRouteEnabled } from "../../../integrations/index.js";
3
+ import { isFunctionPerRouteEnabled } from "../../../integrations/hooks.js";
4
4
  import { isServerLikeOutput } from "../../../prerender/utils.js";
5
5
  import { routeIsRedirect } from "../../redirects/index.js";
6
6
  import { addRollupInput } from "../add-rollup-input.js";
@@ -15,7 +15,7 @@ import {
15
15
  import { emptyDir, removeEmptyDirs } from "../../core/fs/index.js";
16
16
  import { appendForwardSlash, prependForwardSlash, removeFileExtension } from "../../core/path.js";
17
17
  import { isModeServerWithNoAdapter } from "../../core/util.js";
18
- import { runHookBuildSetup } from "../../integrations/index.js";
18
+ import { runHookBuildSetup } from "../../integrations/hooks.js";
19
19
  import { getOutputDirectory, isServerLikeOutput } from "../../prerender/utils.js";
20
20
  import { PAGE_SCRIPT_ID } from "../../vite-plugin-scripts/index.js";
21
21
  import { AstroError, AstroErrorData } from "../errors/index.js";
@@ -22,7 +22,7 @@ async function compile({
22
22
  normalizedFilename: normalizeFilename(filename, astroConfig.root),
23
23
  sourcemap: "both",
24
24
  internalURL: "astro/compiler-runtime",
25
- // TODO: this is no longer neccessary for `Astro.site`
25
+ // TODO: this is no longer necessary for `Astro.site`
26
26
  // but it somehow allows working around caching issues in content collections for some tests
27
27
  astroGlobalArgs: JSON.stringify(astroConfig.site),
28
28
  scopedStyleStrategy: astroConfig.scopedStyleStrategy,
@@ -34,7 +34,7 @@ export declare const DEFAULT_404_COMPONENT = "astro-default-404";
34
34
  export declare const REROUTABLE_STATUS_CODES: number[];
35
35
  /**
36
36
  * The symbol which is used as a field on the request object to store the client address.
37
- * The clientAddresss provided by the adapter (or the dev server) is stored on this field.
37
+ * The clientAddress provided by the adapter (or the dev server) is stored on this field.
38
38
  */
39
39
  export declare const clientAddressSymbol: unique symbol;
40
40
  /**
@@ -1,4 +1,4 @@
1
- const ASTRO_VERSION = "4.7.0";
1
+ const ASTRO_VERSION = "4.7.1";
2
2
  const REROUTE_DIRECTIVE_HEADER = "X-Astro-Reroute";
3
3
  const ROUTE_TYPE_HEADER = "X-Astro-Route-Type";
4
4
  const DEFAULT_404_COMPONENT = "astro-default-404";
@@ -6,7 +6,7 @@ import {
6
6
  runHookConfigSetup,
7
7
  runHookServerDone,
8
8
  runHookServerStart
9
- } from "../../integrations/index.js";
9
+ } from "../../integrations/hooks.js";
10
10
  import { createVite } from "../create-vite.js";
11
11
  import { apply as applyPolyfill } from "../polyfill.js";
12
12
  async function createContainer({
@@ -19,7 +19,7 @@ async function dev(inlineConfig) {
19
19
  await telemetry.record([]);
20
20
  const restart = await createContainerWithAutomaticRestart({ inlineConfig, fs });
21
21
  const logger = restart.container.logger;
22
- const currentVersion = "4.7.0";
22
+ const currentVersion = "4.7.1";
23
23
  const isPrerelease = currentVersion.includes("-");
24
24
  if (!isPrerelease) {
25
25
  try {
@@ -389,7 +389,7 @@ export declare const NoMatchingImport: {
389
389
  export declare const InvalidPrerenderExport: {
390
390
  name: string;
391
391
  title: string;
392
- message(prefix: string, suffix: string, isHydridOuput: boolean): string;
392
+ message(prefix: string, suffix: string, isHydridOutput: boolean): string;
393
393
  hint: string;
394
394
  };
395
395
  /**
@@ -125,8 +125,8 @@ const NoMatchingImport = {
125
125
  const InvalidPrerenderExport = {
126
126
  name: "InvalidPrerenderExport",
127
127
  title: "Invalid prerender export.",
128
- message(prefix, suffix, isHydridOuput) {
129
- const defaultExpectedValue = isHydridOuput ? "false" : "true";
128
+ message(prefix, suffix, isHydridOutput) {
129
+ const defaultExpectedValue = isHydridOutput ? "false" : "true";
130
130
  let msg = `A \`prerender\` export has been detected, but its value cannot be statically analyzed.`;
131
131
  if (prefix !== "const")
132
132
  msg += `
@@ -3,3 +3,4 @@ export { AggregateError, AstroError, AstroUserError, CSSError, CompilerError, Ma
3
3
  export type { ErrorLocation, ErrorWithMetadata } from './errors.js';
4
4
  export { codeFrame } from './printer.js';
5
5
  export { createSafeError, positionAt } from './utils.js';
6
+ export { errorMap } from './zod-error-map.js';
@@ -10,6 +10,7 @@ import {
10
10
  } from "./errors.js";
11
11
  import { codeFrame } from "./printer.js";
12
12
  import { createSafeError, positionAt } from "./utils.js";
13
+ import { errorMap } from "./zod-error-map.js";
13
14
  export {
14
15
  AggregateError,
15
16
  AstroError,
@@ -20,6 +21,7 @@ export {
20
21
  MarkdownError,
21
22
  codeFrame,
22
23
  createSafeError,
24
+ errorMap,
23
25
  isAstroError,
24
26
  positionAt
25
27
  };
@@ -62,7 +62,7 @@ const style = (
62
62
 
63
63
  /* Theme toggle */
64
64
  --toggle-ball-color: var(--accent);
65
- --toggle-tabel-background: var(--background);
65
+ --toggle-table-background: var(--background);
66
66
  --sun-icon-color: #ffffff;
67
67
  --moon-icon-color: #a3acc8;
68
68
  --toggle-border-color: #C3CADB;
@@ -150,7 +150,7 @@ const style = (
150
150
  }
151
151
 
152
152
  #theme-toggle-label {
153
- background-color: var(--toggle-tabel-background);
153
+ background-color: var(--toggle-table-background);
154
154
  border-radius: 50px;
155
155
  cursor: pointer;
156
156
  display: flex;
@@ -37,7 +37,7 @@ function serverStart({
37
37
  host,
38
38
  base
39
39
  }) {
40
- const version = "4.7.0";
40
+ const version = "4.7.1";
41
41
  const localPrefix = `${dim("\u2503")} Local `;
42
42
  const networkPrefix = `${dim("\u2503")} Network `;
43
43
  const emptyPrefix = " ".repeat(11);
@@ -269,7 +269,7 @@ function printHelp({
269
269
  message.push(
270
270
  linebreak(),
271
271
  ` ${bgGreen(black(` ${commandName} `))} ${green(
272
- `v${"4.7.0"}`
272
+ `v${"4.7.1"}`
273
273
  )} ${headline}`
274
274
  );
275
275
  }
@@ -4,7 +4,7 @@ import { fileURLToPath, pathToFileURL } from "node:url";
4
4
  import { AstroIntegrationLogger } from "../../core/logger/core.js";
5
5
  import { telemetry } from "../../events/index.js";
6
6
  import { eventCliSession } from "../../events/session.js";
7
- import { runHookConfigDone, runHookConfigSetup } from "../../integrations/index.js";
7
+ import { runHookConfigDone, runHookConfigSetup } from "../../integrations/hooks.js";
8
8
  import { resolveConfig } from "../config/config.js";
9
9
  import { createNodeLogger } from "../config/logging.js";
10
10
  import { createSettings } from "../config/settings.js";
@@ -16,7 +16,7 @@ import type { RouteData } from '../../@types/astro.js';
16
16
  * - Prerendered routes are sorted before non-prerendered routes.
17
17
  * - Endpoints are sorted before pages.
18
18
  * For example, a file `/foo.ts` is sorted before `/bar.astro`.
19
- * - If both routes are equal regarding all previosu conditions, they are sorted alphabetically.
19
+ * - If both routes are equal regarding all previous conditions, they are sorted alphabetically.
20
20
  * For example, `/bar` is sorted before `/foo`.
21
21
  * The definition of "alphabetically" is dependent on the default locale of the running system.
22
22
  */
@@ -8,7 +8,7 @@ import { createContentTypesGenerator } from "../../content/index.js";
8
8
  import { globalContentConfigObserver } from "../../content/utils.js";
9
9
  import { telemetry } from "../../events/index.js";
10
10
  import { eventCliSession } from "../../events/session.js";
11
- import { runHookConfigSetup } from "../../integrations/index.js";
11
+ import { runHookConfigSetup } from "../../integrations/hooks.js";
12
12
  import { setUpEnvTs } from "../../vite-plugin-inject-env-ts/index.js";
13
13
  import { getTimeStat } from "../build/util.js";
14
14
  import { resolveConfig } from "../config/config.js";
@@ -4,7 +4,7 @@ import { bold } from "kleur/colors";
4
4
  import { buildClientDirectiveEntrypoint } from "../core/client-directive/index.js";
5
5
  import { mergeConfig } from "../core/config/index.js";
6
6
  import { isServerLikeOutput } from "../prerender/utils.js";
7
- import { validateSupportedFeatures } from "./astroFeaturesValidation.js";
7
+ import { validateSupportedFeatures } from "./features-validation.js";
8
8
  async function withTakingALongTimeMsg({
9
9
  name,
10
10
  hookName,
@@ -2,6 +2,6 @@ import type { AstroConfig } from '../@types/astro.js';
2
2
  export declare function isServerLikeOutput(config: AstroConfig): boolean;
3
3
  export declare function getPrerenderDefault(config: AstroConfig): boolean;
4
4
  /**
5
- * Returns the correct output directory of hte SSR build based on the configuration
5
+ * Returns the correct output directory of the SSR build based on the configuration
6
6
  */
7
7
  export declare function getOutputDirectory(config: AstroConfig): URL;
@@ -1,6 +1,6 @@
1
1
  type NotificationPayload = {
2
2
  state: true;
3
- level?: 'error' | 'warn' | 'info';
3
+ level?: 'error' | 'warning' | 'info';
4
4
  } | {
5
5
  state: false;
6
6
  };
@@ -25,7 +25,7 @@ class ToolbarAppEventTarget extends EventTarget {
25
25
  */
26
26
  toggleState(options) {
27
27
  this.dispatchEvent(
28
- new CustomEvent("app-toggled", {
28
+ new CustomEvent("toggle-app", {
29
29
  detail: {
30
30
  state: options.state
31
31
  }
@@ -21,7 +21,7 @@ function createAstroGlobFn() {
21
21
  }
22
22
  function createAstro(site) {
23
23
  return {
24
- // TODO: this is no longer neccessary for `Astro.site`
24
+ // TODO: this is no longer necessary for `Astro.site`
25
25
  // but it somehow allows working around caching issues in content collections for some tests
26
26
  site: site ? new URL(site) : void 0,
27
27
  generator: `Astro v${ASTRO_VERSION}`,
@@ -31,20 +31,20 @@ class AstroComponentInstance {
31
31
  if (this.returnValue !== void 0)
32
32
  return this.returnValue;
33
33
  this.returnValue = this.factory(result, this.props, this.slotValues);
34
+ if (isPromise(this.returnValue)) {
35
+ this.returnValue.then((resolved) => {
36
+ this.returnValue = resolved;
37
+ }).catch(() => {
38
+ });
39
+ }
34
40
  return this.returnValue;
35
41
  }
36
42
  async render(destination) {
37
- if (this.returnValue === void 0) {
38
- await this.init(this.result);
39
- }
40
- let value = this.returnValue;
41
- if (isPromise(value)) {
42
- value = await value;
43
- }
44
- if (isHeadAndContent(value)) {
45
- await value.content.render(destination);
43
+ const returnValue = await this.init(this.result);
44
+ if (isHeadAndContent(returnValue)) {
45
+ await returnValue.content.render(destination);
46
46
  } else {
47
- await renderChild(destination, value);
47
+ await renderChild(destination, returnValue);
48
48
  }
49
49
  }
50
50
  }
@@ -4,13 +4,15 @@ const voidElementNames = /^(area|base|br|col|command|embed|hr|img|input|keygen|l
4
4
  const htmlBooleanAttributes = /^(?:allowfullscreen|async|autofocus|autoplay|controls|default|defer|disabled|disablepictureinpicture|disableremoteplayback|formnovalidate|hidden|loop|nomodule|novalidate|open|playsinline|readonly|required|reversed|scoped|seamless|itemscope)$/i;
5
5
  const htmlEnumAttributes = /^(?:contenteditable|draggable|spellcheck|value)$/i;
6
6
  const svgEnumAttributes = /^(?:autoReverse|externalResourcesRequired|focusable|preserveAlpha)$/i;
7
+ const AMPERSAND_REGEX = /&/g;
8
+ const DOUBLE_QUOTE_REGEX = /"/g;
7
9
  const STATIC_DIRECTIVES = /* @__PURE__ */ new Set(["set:html", "set:text"]);
8
10
  const toIdent = (k) => k.trim().replace(/(?!^)\b\w|\s+|\W+/g, (match, index) => {
9
11
  if (/\W/.test(match))
10
12
  return "";
11
13
  return index === 0 ? match : match.toUpperCase();
12
14
  });
13
- const toAttributeString = (value, shouldEscape = true) => shouldEscape ? String(value).replace(/&/g, "&").replace(/"/g, """) : value;
15
+ const toAttributeString = (value, shouldEscape = true) => shouldEscape ? String(value).replace(AMPERSAND_REGEX, "&").replace(DOUBLE_QUOTE_REGEX, """) : value;
14
16
  const kebab = (k) => k.toLowerCase() === k ? k : k.replace(/[A-Z]/g, (match) => `-${match.toLowerCase()}`);
15
17
  const toStyleString = (obj) => Object.entries(obj).filter(([_, v]) => typeof v === "string" && v.trim() || typeof v === "number").map(([k, v]) => {
16
18
  if (k[0] !== "-" && k[1] !== "-")
@@ -16,13 +16,14 @@ declare class BeforeEvent extends Event {
16
16
  readonly sourceElement: Element | undefined;
17
17
  readonly info: any;
18
18
  newDocument: Document;
19
- constructor(type: string, eventInitDict: EventInit | undefined, from: URL, to: URL, direction: Direction | string, navigationType: NavigationTypeString, sourceElement: Element | undefined, info: any, newDocument: Document);
19
+ signal: AbortSignal;
20
+ constructor(type: string, eventInitDict: EventInit | undefined, from: URL, to: URL, direction: Direction | string, navigationType: NavigationTypeString, sourceElement: Element | undefined, info: any, newDocument: Document, signal: AbortSignal);
20
21
  }
21
22
  export declare const isTransitionBeforePreparationEvent: (value: any) => value is TransitionBeforePreparationEvent;
22
23
  export declare class TransitionBeforePreparationEvent extends BeforeEvent {
23
24
  formData: FormData | undefined;
24
25
  loader: () => Promise<void>;
25
- constructor(from: URL, to: URL, direction: Direction | string, navigationType: NavigationTypeString, sourceElement: Element | undefined, info: any, newDocument: Document, formData: FormData | undefined, loader: (event: TransitionBeforePreparationEvent) => Promise<void>);
26
+ constructor(from: URL, to: URL, direction: Direction | string, navigationType: NavigationTypeString, sourceElement: Element | undefined, info: any, newDocument: Document, signal: AbortSignal, formData: FormData | undefined, loader: (event: TransitionBeforePreparationEvent) => Promise<void>);
26
27
  }
27
28
  export declare const isTransitionBeforeSwapEvent: (value: any) => value is TransitionBeforeSwapEvent;
28
29
  export declare class TransitionBeforeSwapEvent extends BeforeEvent {
@@ -31,6 +32,6 @@ export declare class TransitionBeforeSwapEvent extends BeforeEvent {
31
32
  swap: () => void;
32
33
  constructor(afterPreparation: BeforeEvent, viewTransition: ViewTransition, swap: (event: TransitionBeforeSwapEvent) => void);
33
34
  }
34
- export declare function doPreparation(from: URL, to: URL, direction: Direction | string, navigationType: NavigationTypeString, sourceElement: Element | undefined, info: any, formData: FormData | undefined, defaultLoader: (event: TransitionBeforePreparationEvent) => Promise<void>): Promise<TransitionBeforePreparationEvent>;
35
- export declare function doSwap(afterPreparation: BeforeEvent, viewTransition: ViewTransition, defaultSwap: (event: TransitionBeforeSwapEvent) => void): Promise<TransitionBeforeSwapEvent>;
35
+ export declare function doPreparation(from: URL, to: URL, direction: Direction | string, navigationType: NavigationTypeString, sourceElement: Element | undefined, info: any, signal: AbortSignal, formData: FormData | undefined, defaultLoader: (event: TransitionBeforePreparationEvent) => Promise<void>): Promise<TransitionBeforePreparationEvent>;
36
+ export declare function doSwap(afterPreparation: BeforeEvent, viewTransition: ViewTransition, defaultSwap: (event: TransitionBeforeSwapEvent) => void): TransitionBeforeSwapEvent;
36
37
  export {};
@@ -14,7 +14,8 @@ class BeforeEvent extends Event {
14
14
  sourceElement;
15
15
  info;
16
16
  newDocument;
17
- constructor(type, eventInitDict, from, to, direction, navigationType, sourceElement, info, newDocument) {
17
+ signal;
18
+ constructor(type, eventInitDict, from, to, direction, navigationType, sourceElement, info, newDocument, signal) {
18
19
  super(type, eventInitDict);
19
20
  this.from = from;
20
21
  this.to = to;
@@ -23,6 +24,7 @@ class BeforeEvent extends Event {
23
24
  this.sourceElement = sourceElement;
24
25
  this.info = info;
25
26
  this.newDocument = newDocument;
27
+ this.signal = signal;
26
28
  Object.defineProperties(this, {
27
29
  from: { enumerable: true },
28
30
  to: { enumerable: true, writable: true },
@@ -30,7 +32,8 @@ class BeforeEvent extends Event {
30
32
  navigationType: { enumerable: true },
31
33
  sourceElement: { enumerable: true },
32
34
  info: { enumerable: true },
33
- newDocument: { enumerable: true, writable: true }
35
+ newDocument: { enumerable: true, writable: true },
36
+ signal: { enumerable: true }
34
37
  });
35
38
  }
36
39
  }
@@ -38,7 +41,7 @@ const isTransitionBeforePreparationEvent = (value) => value.type === TRANSITION_
38
41
  class TransitionBeforePreparationEvent extends BeforeEvent {
39
42
  formData;
40
43
  loader;
41
- constructor(from, to, direction, navigationType, sourceElement, info, newDocument, formData, loader) {
44
+ constructor(from, to, direction, navigationType, sourceElement, info, newDocument, signal, formData, loader) {
42
45
  super(
43
46
  TRANSITION_BEFORE_PREPARATION,
44
47
  { cancelable: true },
@@ -48,7 +51,8 @@ class TransitionBeforePreparationEvent extends BeforeEvent {
48
51
  navigationType,
49
52
  sourceElement,
50
53
  info,
51
- newDocument
54
+ newDocument,
55
+ signal
52
56
  );
53
57
  this.formData = formData;
54
58
  this.loader = loader.bind(this, this);
@@ -73,7 +77,8 @@ class TransitionBeforeSwapEvent extends BeforeEvent {
73
77
  afterPreparation.navigationType,
74
78
  afterPreparation.sourceElement,
75
79
  afterPreparation.info,
76
- afterPreparation.newDocument
80
+ afterPreparation.newDocument,
81
+ afterPreparation.signal
77
82
  );
78
83
  this.direction = afterPreparation.direction;
79
84
  this.viewTransition = viewTransition;
@@ -85,7 +90,7 @@ class TransitionBeforeSwapEvent extends BeforeEvent {
85
90
  });
86
91
  }
87
92
  }
88
- async function doPreparation(from, to, direction, navigationType, sourceElement, info, formData, defaultLoader) {
93
+ async function doPreparation(from, to, direction, navigationType, sourceElement, info, signal, formData, defaultLoader) {
89
94
  const event = new TransitionBeforePreparationEvent(
90
95
  from,
91
96
  to,
@@ -94,6 +99,7 @@ async function doPreparation(from, to, direction, navigationType, sourceElement,
94
99
  sourceElement,
95
100
  info,
96
101
  window.document,
102
+ signal,
97
103
  formData,
98
104
  defaultLoader
99
105
  );
@@ -108,7 +114,7 @@ async function doPreparation(from, to, direction, navigationType, sourceElement,
108
114
  }
109
115
  return event;
110
116
  }
111
- async function doSwap(afterPreparation, viewTransition, defaultSwap) {
117
+ function doSwap(afterPreparation, viewTransition, defaultSwap) {
112
118
  const event = new TransitionBeforeSwapEvent(afterPreparation, viewTransition, defaultSwap);
113
119
  document.dispatchEvent(event);
114
120
  event.swap();
@@ -11,10 +11,9 @@ const updateScrollPosition = (positions) => {
11
11
  const supportsViewTransitions = inBrowser && !!document.startViewTransition;
12
12
  const transitionEnabledOnThisPage = () => inBrowser && !!document.querySelector('[name="astro-view-transitions-enabled"]');
13
13
  const samePage = (thisLocation, otherLocation) => thisLocation.pathname === otherLocation.pathname && thisLocation.search === otherLocation.search;
14
+ let mostRecentNavigation;
15
+ let mostRecentTransition;
14
16
  let originalLocation;
15
- let viewTransition;
16
- let skipTransition = false;
17
- let viewTransitionFinished;
18
17
  const triggerEvent = (name) => document.dispatchEvent(new Event(name));
19
18
  const onPageLoad = () => triggerEvent("astro:page-load");
20
19
  const announce = () => {
@@ -173,7 +172,7 @@ function preloadStyleLinks(newDocument) {
173
172
  }
174
173
  return links;
175
174
  }
176
- async function updateDOM(preparationEvent, options, historyState, fallback) {
175
+ async function updateDOM(preparationEvent, options, currentTransition, historyState, fallback) {
177
176
  const persistedHeadElement = (el, newDoc) => {
178
177
  const id = el.getAttribute(PERSIST_ATTR);
179
178
  const newEl = id && newDoc.head.querySelector(`[${PERSIST_ATTR}="${id}"]`);
@@ -274,26 +273,37 @@ async function updateDOM(preparationEvent, options, historyState, fallback) {
274
273
  const newAnimations = nextAnimations.filter(
275
274
  (a) => !currentAnimations.includes(a) && !isInfinite(a)
276
275
  );
277
- return Promise.all(newAnimations.map((a) => a.finished));
276
+ return Promise.allSettled(newAnimations.map((a) => a.finished));
278
277
  }
279
- if (!skipTransition) {
280
- document.documentElement.setAttribute(DIRECTION_ATTR, preparationEvent.direction);
281
- if (fallback === "animate") {
278
+ if (fallback === "animate" && !currentTransition.transitionSkipped && !preparationEvent.signal.aborted) {
279
+ try {
282
280
  await animate("old");
281
+ } catch (err) {
283
282
  }
284
- } else {
285
- throw new DOMException("Transition was skipped");
286
283
  }
287
284
  const pageTitleForBrowserHistory = document.title;
288
- const swapEvent = await doSwap(preparationEvent, viewTransition, defaultSwap);
285
+ const swapEvent = doSwap(preparationEvent, currentTransition.viewTransition, defaultSwap);
289
286
  moveToLocation(swapEvent.to, swapEvent.from, options, pageTitleForBrowserHistory, historyState);
290
287
  triggerEvent(TRANSITION_AFTER_SWAP);
291
- if (fallback === "animate" && !skipTransition) {
292
- animate("new").then(() => viewTransitionFinished());
288
+ if (fallback === "animate") {
289
+ if (!currentTransition.transitionSkipped && !swapEvent.signal.aborted) {
290
+ animate("new").finally(() => currentTransition.viewTransitionFinished());
291
+ } else {
292
+ currentTransition.viewTransitionFinished();
293
+ }
293
294
  }
294
295
  }
296
+ function abortAndRecreateMostRecentNavigation() {
297
+ mostRecentNavigation?.controller.abort();
298
+ return mostRecentNavigation = {
299
+ controller: new AbortController()
300
+ };
301
+ }
295
302
  async function transition(direction, from, to, options, historyState) {
303
+ const currentNavigation = abortAndRecreateMostRecentNavigation();
296
304
  if (!transitionEnabledOnThisPage() || location.origin !== to.origin) {
305
+ if (currentNavigation === mostRecentNavigation)
306
+ mostRecentNavigation = void 0;
297
307
  location.href = to.href;
298
308
  return;
299
309
  }
@@ -304,6 +314,8 @@ async function transition(direction, from, to, options, historyState) {
304
314
  if (samePage(from, to)) {
305
315
  if (direction !== "back" && to.hash || direction === "back" && from.hash) {
306
316
  moveToLocation(to, from, options, document.title, historyState);
317
+ if (currentNavigation === mostRecentNavigation)
318
+ mostRecentNavigation = void 0;
307
319
  return;
308
320
  }
309
321
  }
@@ -314,16 +326,21 @@ async function transition(direction, from, to, options, historyState) {
314
326
  navigationType,
315
327
  options.sourceElement,
316
328
  options.info,
329
+ currentNavigation.controller.signal,
317
330
  options.formData,
318
331
  defaultLoader
319
332
  );
320
- if (prepEvent.defaultPrevented) {
321
- location.href = to.href;
333
+ if (prepEvent.defaultPrevented || prepEvent.signal.aborted) {
334
+ if (currentNavigation === mostRecentNavigation)
335
+ mostRecentNavigation = void 0;
336
+ if (!prepEvent.signal.aborted) {
337
+ location.href = to.href;
338
+ }
322
339
  return;
323
340
  }
324
341
  async function defaultLoader(preparationEvent) {
325
342
  const href = preparationEvent.to.href;
326
- const init = {};
343
+ const init = { signal: preparationEvent.signal };
327
344
  if (preparationEvent.formData) {
328
345
  init.method = "POST";
329
346
  const form = preparationEvent.sourceElement instanceof HTMLFormElement ? preparationEvent.sourceElement : preparationEvent.sourceElement instanceof HTMLElement && "form" in preparationEvent.sourceElement ? preparationEvent.sourceElement.form : preparationEvent.sourceElement?.closest("form");
@@ -345,42 +362,80 @@ async function transition(direction, from, to, options, historyState) {
345
362
  return;
346
363
  }
347
364
  const links = preloadStyleLinks(preparationEvent.newDocument);
348
- links.length && await Promise.all(links);
349
- if (import.meta.env.DEV)
350
- await prepareForClientOnlyComponents(preparationEvent.newDocument, preparationEvent.to);
365
+ links.length && !preparationEvent.signal.aborted && await Promise.all(links);
366
+ if (import.meta.env.DEV && !preparationEvent.signal.aborted)
367
+ await prepareForClientOnlyComponents(
368
+ preparationEvent.newDocument,
369
+ preparationEvent.to,
370
+ preparationEvent.signal
371
+ );
351
372
  }
352
- skipTransition = false;
373
+ async function abortAndRecreateMostRecentTransition() {
374
+ if (mostRecentTransition) {
375
+ if (mostRecentTransition.viewTransition) {
376
+ try {
377
+ mostRecentTransition.viewTransition.skipTransition();
378
+ } catch {
379
+ }
380
+ try {
381
+ await mostRecentTransition.viewTransition.updateCallbackDone;
382
+ } catch {
383
+ }
384
+ }
385
+ }
386
+ return mostRecentTransition = { transitionSkipped: false };
387
+ }
388
+ const currentTransition = await abortAndRecreateMostRecentTransition();
389
+ if (prepEvent.signal.aborted) {
390
+ if (currentNavigation === mostRecentNavigation)
391
+ mostRecentNavigation = void 0;
392
+ return;
393
+ }
394
+ document.documentElement.setAttribute(DIRECTION_ATTR, prepEvent.direction);
353
395
  if (supportsViewTransitions) {
354
- viewTransition = document.startViewTransition(
355
- async () => await updateDOM(prepEvent, options, historyState)
396
+ currentTransition.viewTransition = document.startViewTransition(
397
+ async () => await updateDOM(prepEvent, options, currentTransition, historyState)
356
398
  );
357
399
  } else {
358
400
  const updateDone = (async () => {
359
- await new Promise((r) => setTimeout(r));
360
- await updateDOM(prepEvent, options, historyState, getFallback());
401
+ await Promise.resolve();
402
+ await updateDOM(prepEvent, options, currentTransition, historyState, getFallback());
361
403
  })();
362
- viewTransition = {
404
+ currentTransition.viewTransition = {
363
405
  updateCallbackDone: updateDone,
364
406
  // this is about correct
365
407
  ready: updateDone,
366
408
  // good enough
367
- finished: new Promise((r) => viewTransitionFinished = r),
409
+ // Finished promise could have been done better: finished rejects iff updateDone does.
410
+ // Our simulation always resolves, never rejects.
411
+ finished: new Promise((r) => currentTransition.viewTransitionFinished = r),
368
412
  // see end of updateDOM
369
413
  skipTransition: () => {
370
- skipTransition = true;
414
+ currentTransition.transitionSkipped = true;
415
+ document.documentElement.removeAttribute(OLD_NEW_ATTR);
371
416
  }
372
417
  };
373
418
  }
374
- viewTransition.ready.then(async () => {
419
+ currentTransition.viewTransition.updateCallbackDone.finally(async () => {
375
420
  await runScripts();
376
421
  onPageLoad();
377
422
  announce();
378
423
  });
379
- viewTransition.finished.then(() => {
424
+ currentTransition.viewTransition.finished.finally(() => {
425
+ currentTransition.viewTransition = void 0;
426
+ if (currentTransition === mostRecentTransition)
427
+ mostRecentTransition = void 0;
428
+ if (currentNavigation === mostRecentNavigation)
429
+ mostRecentNavigation = void 0;
380
430
  document.documentElement.removeAttribute(DIRECTION_ATTR);
381
431
  document.documentElement.removeAttribute(OLD_NEW_ATTR);
382
432
  });
383
- await viewTransition.ready;
433
+ try {
434
+ await currentTransition.viewTransition.updateCallbackDone;
435
+ } catch (e) {
436
+ const err = e;
437
+ console.log("[astro]", err.name, err.message, err.stack);
438
+ }
384
439
  }
385
440
  let navigateOnServerWarned = false;
386
441
  async function navigate(href, options) {
@@ -456,7 +511,7 @@ if (inBrowser) {
456
511
  script.dataset.astroExec = "";
457
512
  }
458
513
  }
459
- async function prepareForClientOnlyComponents(newDocument, toLocation) {
514
+ async function prepareForClientOnlyComponents(newDocument, toLocation, signal) {
460
515
  if (newDocument.body.querySelector(`astro-island[client='only']`)) {
461
516
  const nextPage = document.createElement("iframe");
462
517
  nextPage.src = toLocation.href;
@@ -481,11 +536,15 @@ async function prepareForClientOnlyComponents(newDocument, toLocation) {
481
536
  });
482
537
  }
483
538
  async function hydrationDone(loadingPage) {
484
- await new Promise(
485
- (r) => loadingPage.contentWindow?.addEventListener("load", r, { once: true })
486
- );
539
+ if (!signal.aborted) {
540
+ await new Promise(
541
+ (r) => loadingPage.contentWindow?.addEventListener("load", r, { once: true })
542
+ );
543
+ }
487
544
  return new Promise(async (r) => {
488
545
  for (let count = 0; count <= 20; ++count) {
546
+ if (signal.aborted)
547
+ break;
489
548
  if (!loadingPage.contentDocument.body.querySelector("astro-island[ssr]"))
490
549
  break;
491
550
  await new Promise((r2) => setTimeout(r2, 50));
@@ -15,7 +15,7 @@ async function* crawlGraph(loader, _id, isRootFile, scanned = /* @__PURE__ */ ne
15
15
  loader.getModulesByFile(id) ?? /* @__PURE__ */ new Set()
16
16
  ) : (
17
17
  // For non-root files, we're safe to pull from "getModuleById" based on testing.
18
- // TODO: Find better invalidation strat to use "getModuleById" in all cases!
18
+ // TODO: Find better invalidation strategy to use "getModuleById" in all cases!
19
19
  /* @__PURE__ */ new Set([loader.getModuleById(id)])
20
20
  );
21
21
  for (const entry of moduleEntriesForId) {
@@ -24,14 +24,13 @@ async function* crawlGraph(loader, _id, isRootFile, scanned = /* @__PURE__ */ ne
24
24
  }
25
25
  if (id === entry.id) {
26
26
  scanned.add(id);
27
- const entryIsStyle = isCSSRequest(id);
27
+ if (isCSSRequest(id)) {
28
+ continue;
29
+ }
28
30
  for (const importedModule of entry.importedModules) {
29
31
  if (!importedModule.id)
30
32
  continue;
31
33
  const importedModulePathname = importedModule.id.replace(STRIP_QUERY_PARAMS_REGEX, "");
32
- if (entryIsStyle && !isCSSRequest(importedModulePathname)) {
33
- continue;
34
- }
35
34
  const isFileTypeNeedingSSR = fileExtensionsToSSR.has(npath.extname(importedModulePathname));
36
35
  const isPropagationStoppingPoint = ASTRO_PROPAGATED_ASSET_REGEX.test(importedModule.id);
37
36
  if (isFileTypeNeedingSSR && // Should not SSR a module with ?astroPropagatedAssets
@@ -1,5 +1,5 @@
1
1
  import { normalizePath } from "vite";
2
- import { runHookServerSetup } from "../integrations/index.js";
2
+ import { runHookServerSetup } from "../integrations/hooks.js";
3
3
  function astroIntegrationsContainerPlugin({
4
4
  settings,
5
5
  logger
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "astro",
3
- "version": "4.7.0",
3
+ "version": "4.7.1",
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",
@@ -104,12 +104,12 @@
104
104
  ],
105
105
  "dependencies": {
106
106
  "@astrojs/compiler": "^2.7.1",
107
- "@babel/core": "^7.24.4",
108
- "@babel/generator": "^7.24.4",
109
- "@babel/parser": "^7.24.4",
107
+ "@babel/core": "^7.24.5",
108
+ "@babel/generator": "^7.24.5",
109
+ "@babel/parser": "^7.24.5",
110
110
  "@babel/plugin-transform-react-jsx": "^7.23.4",
111
- "@babel/traverse": "^7.24.1",
112
- "@babel/types": "^7.24.0",
111
+ "@babel/traverse": "^7.24.5",
112
+ "@babel/types": "^7.24.5",
113
113
  "@types/babel__core": "^7.20.5",
114
114
  "@types/cookie": "^0.6.0",
115
115
  "acorn": "^8.11.3",
@@ -118,7 +118,7 @@
118
118
  "boxen": "^7.1.1",
119
119
  "chokidar": "^3.6.0",
120
120
  "ci-info": "^4.0.0",
121
- "clsx": "^2.1.0",
121
+ "clsx": "^2.1.1",
122
122
  "common-ancestor-path": "^1.0.1",
123
123
  "cookie": "^0.6.0",
124
124
  "cssesc": "^3.0.0",
@@ -128,7 +128,7 @@
128
128
  "diff": "^5.2.0",
129
129
  "dlv": "^1.1.3",
130
130
  "dset": "^3.1.3",
131
- "es-module-lexer": "^1.5.0",
131
+ "es-module-lexer": "^1.5.2",
132
132
  "esbuild": "^0.20.2",
133
133
  "estree-walker": "^3.0.3",
134
134
  "execa": "^8.0.1",
@@ -161,8 +161,8 @@
161
161
  "vitefu": "^0.2.5",
162
162
  "which-pm": "^2.1.1",
163
163
  "yargs-parser": "^21.1.1",
164
- "zod": "^3.23.0",
165
- "zod-to-json-schema": "^3.22.5",
164
+ "zod": "^3.23.5",
165
+ "zod-to-json-schema": "^3.23.0",
166
166
  "@astrojs/internal-helpers": "0.4.0",
167
167
  "@astrojs/markdown-remark": "5.1.0",
168
168
  "@astrojs/telemetry": "3.1.0"
@@ -196,14 +196,14 @@
196
196
  "@types/yargs-parser": "^21.0.3",
197
197
  "cheerio": "1.0.0-rc.12",
198
198
  "eol": "^0.9.1",
199
- "memfs": "^4.8.2",
199
+ "memfs": "^4.9.1",
200
200
  "node-mocks-http": "^1.14.1",
201
201
  "parse-srcset": "^1.0.2",
202
202
  "rehype-autolink-headings": "^7.1.0",
203
203
  "rehype-slug": "^6.0.0",
204
204
  "rehype-toc": "^3.0.2",
205
205
  "remark-code-titles": "^0.1.2",
206
- "rollup": "^4.16.1",
206
+ "rollup": "^4.17.1",
207
207
  "sass": "^1.75.0",
208
208
  "srcset-parse": "^1.1.0",
209
209
  "unified": "^11.0.4",
File without changes