astro 3.5.6 → 3.6.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.
package/client.d.ts CHANGED
@@ -109,6 +109,7 @@ declare module 'astro:transitions' {
109
109
  type TransitionModule = typeof import('./dist/transitions/index.js');
110
110
  export const slide: TransitionModule['slide'];
111
111
  export const fade: TransitionModule['fade'];
112
+ export const createAnimationScope: TransitionModule['createAnimationScope'];
112
113
 
113
114
  type ViewTransitionsModule = typeof import('./components/ViewTransitions.astro');
114
115
  export const ViewTransitions: ViewTransitionsModule['default'];
@@ -116,10 +117,30 @@ declare module 'astro:transitions' {
116
117
 
117
118
  declare module 'astro:transitions/client' {
118
119
  type TransitionRouterModule = typeof import('./dist/transitions/router.js');
119
- export const supportsViewTransitions: TransitionRouterModule['supportsViewTransitions'];
120
- export const transitionEnabledOnThisPage: TransitionRouterModule['transitionEnabledOnThisPage'];
121
120
  export const navigate: TransitionRouterModule['navigate'];
122
- export type Options = import('./dist/transitions/router.js').Options;
121
+
122
+ type TransitionUtilModule = typeof import('./dist/transitions/util.js');
123
+ export const supportsViewTransitions: TransitionUtilModule['supportsViewTransitions'];
124
+ export const getFallback: TransitionUtilModule['getFallback'];
125
+ export const transitionEnabledOnThisPage: TransitionUtilModule['transitionEnabledOnThisPage'];
126
+
127
+ export type Fallback = import('./dist/transitions/types.ts').Fallback;
128
+ export type Direction = import('./dist/transitions/types.ts').Direction;
129
+ export type NavigationTypeString = import('./dist/transitions/types.ts').NavigationTypeString;
130
+ export type Options = import('./dist/transitions/types.ts').Options;
131
+
132
+ type EventModule = typeof import('./dist/transitions/events.js');
133
+ export const TRANSITION_BEFORE_PREPARATION: EventModule['TRANSITION_BEFORE_PREPARATION'];
134
+ export const TRANSITION_AFTER_PREPARATION: EventModule['TRANSITION_AFTER_PREPARATION'];
135
+ export const TRANSITION_BEFORE_SWAP: EventModule['TRANSITION_BEFORE_SWAP'];
136
+ export const TRANSITION_AFTER_SWAP: EventModule['TRANSITION_AFTER_SWAP'];
137
+ export const TRANSITION_PAGE_LOAD: EventModule['TRANSITION_PAGE_LOAD'];
138
+ export type TransitionBeforePreparationEvent =
139
+ import('./dist/transitions/events.ts').TransitionBeforePreparationEvent;
140
+ export type TransitionBeforeSwapEvent =
141
+ import('./dist/transitions/events.ts').TransitionBeforeSwapEvent;
142
+ export const isTransitionBeforePreparationEvent: EventModule['isTransitionBeforePreparationEvent'];
143
+ export const isTransitionBeforeSwapEvent: EventModule['isTransitionBeforeSwapEvent'];
123
144
  }
124
145
 
125
146
  declare module 'astro:prefetch' {
@@ -33,7 +33,7 @@ const { fallback = 'animate', handleForms } = Astro.props;
33
33
  // @ts-ignore
34
34
  import { init } from 'astro/prefetch';
35
35
 
36
- export type Fallback = 'none' | 'animate' | 'swap';
36
+ type Fallback = 'none' | 'animate' | 'swap';
37
37
 
38
38
  function getFallback(): Fallback {
39
39
  const el = document.querySelector('[name="astro-view-transitions-fallback"]');
@@ -85,6 +85,7 @@ const { fallback = 'animate', handleForms } = Astro.props;
85
85
  ev.preventDefault();
86
86
  navigate(href, {
87
87
  history: link.dataset.astroHistory === 'replace' ? 'replace' : 'auto',
88
+ sourceElement: link,
88
89
  });
89
90
  });
90
91
 
@@ -102,7 +103,7 @@ const { fallback = 'animate', handleForms } = Astro.props;
102
103
  let action = submitter?.getAttribute('formaction') ?? form.action ?? location.pathname;
103
104
  const method = submitter?.getAttribute('formmethod') ?? form.method;
104
105
 
105
- const options: Options = {};
106
+ const options: Options = { sourceElement: submitter ?? form };
106
107
  if (method === 'get') {
107
108
  const params = new URLSearchParams(formData as any);
108
109
  const url = new URL(action);
@@ -194,40 +194,15 @@ ${bgGreen(black(` generating optimized images `))}`);
194
194
  });
195
195
  }
196
196
  async function generatePage(pageData, ssrEntry, builtPaths, pipeline) {
197
+ let timeStart = performance.now();
197
198
  const logger = pipeline.getLogger();
198
199
  const config = pipeline.getConfig();
199
- const manifest = pipeline.getManifest();
200
+ const pageInfo = getPageDataByComponent(pipeline.getInternals(), pageData.route.component);
201
+ const linkIds = [];
202
+ const scripts = pageInfo?.hoistedScript ?? null;
203
+ const styles = pageData.styles.sort(cssOrder).map(({ sheet }) => sheet).reduce(mergeInlineCss, []);
200
204
  const pageModulePromise = ssrEntry.page;
201
205
  const onRequest = ssrEntry.onRequest;
202
- const pageInfo = getPageDataByComponent(pipeline.getInternals(), pageData.route.component);
203
- const hoistedScripts = pageInfo?.hoistedScript ?? null;
204
- const moduleStyles = pageData.styles.sort(cssOrder).map(({ sheet }) => sheet).reduce(mergeInlineCss, []);
205
- const links = /* @__PURE__ */ new Set();
206
- const styles = createStylesheetElementSet(moduleStyles, manifest.base, manifest.assetsPrefix);
207
- const scripts = createModuleScriptsSet(
208
- hoistedScripts ? [hoistedScripts] : [],
209
- manifest.base,
210
- manifest.assetsPrefix
211
- );
212
- if (pipeline.getSettings().scripts.some((script) => script.stage === "page")) {
213
- const hashedFilePath = pipeline.getInternals().entrySpecifierToBundleMap.get(PAGE_SCRIPT_ID);
214
- if (typeof hashedFilePath !== "string") {
215
- throw new Error(`Cannot find the built path for ${PAGE_SCRIPT_ID}`);
216
- }
217
- const src = createAssetLink(hashedFilePath, manifest.base, manifest.assetsPrefix);
218
- scripts.add({
219
- props: { type: "module", src },
220
- children: ""
221
- });
222
- }
223
- for (const script of pipeline.getSettings().scripts) {
224
- if (script.stage === "head-inline") {
225
- scripts.add({
226
- props: {},
227
- children: script.content
228
- });
229
- }
230
- }
231
206
  const i18nMiddleware = createI18nMiddleware(
232
207
  pipeline.getManifest().i18n,
233
208
  pipeline.getManifest().base,
@@ -259,22 +234,34 @@ async function generatePage(pageData, ssrEntry, builtPaths, pipeline) {
259
234
  );
260
235
  return;
261
236
  }
262
- for (const route of eachRouteInRouteData(pageData)) {
263
- const paths = await getPathsForRoute(route, pageModule, pipeline, builtPaths);
264
- let timeStart = performance.now();
265
- let prevTimeEnd = timeStart;
266
- for (let i = 0; i < paths.length; i++) {
267
- const path = paths[i];
268
- pipeline.getEnvironment().logger.debug("build", `Generating: ${path}`);
269
- await generatePath(path, pipeline, route, links, scripts, styles, pageModule);
270
- const timeEnd = performance.now();
271
- const timeChange = getTimeStat(prevTimeEnd, timeEnd);
272
- const timeIncrease = `(+${timeChange})`;
273
- const filePath = getOutputFilename(pipeline.getConfig(), path, pageData.route.type);
274
- const lineIcon = i === paths.length - 1 ? "\u2514\u2500" : "\u251C\u2500";
275
- logger.info(null, ` ${cyan(lineIcon)} ${dim(filePath)} ${dim(timeIncrease)}`);
276
- prevTimeEnd = timeEnd;
237
+ const generationOptions = {
238
+ pageData,
239
+ linkIds,
240
+ scripts,
241
+ styles,
242
+ mod: pageModule
243
+ };
244
+ const icon = pageData.route.type === "page" || pageData.route.type === "redirect" || pageData.route.type === "fallback" ? green("\u25B6") : magenta("\u03BB");
245
+ if (isRelativePath(pageData.route.component)) {
246
+ logger.info(null, `${icon} ${pageData.route.route}`);
247
+ for (const fallbackRoute of pageData.route.fallbackRoutes) {
248
+ logger.info(null, `${icon} ${fallbackRoute.route}`);
277
249
  }
250
+ } else {
251
+ logger.info(null, `${icon} ${pageData.route.component}`);
252
+ }
253
+ const paths = await getPathsForRoute(pageData, pageModule, pipeline, builtPaths);
254
+ let prevTimeEnd = timeStart;
255
+ for (let i = 0; i < paths.length; i++) {
256
+ const path = paths[i];
257
+ await generatePath(path, generationOptions, pipeline);
258
+ const timeEnd = performance.now();
259
+ const timeChange = getTimeStat(prevTimeEnd, timeEnd);
260
+ const timeIncrease = `(+${timeChange})`;
261
+ const filePath = getOutputFilename(pipeline.getConfig(), path, pageData.route.type);
262
+ const lineIcon = i === paths.length - 1 ? "\u2514\u2500" : "\u251C\u2500";
263
+ logger.info(null, ` ${cyan(lineIcon)} ${dim(filePath)} ${dim(timeIncrease)}`);
264
+ prevTimeEnd = timeEnd;
278
265
  }
279
266
  }
280
267
  function* eachRouteInRouteData(data) {
@@ -283,55 +270,59 @@ function* eachRouteInRouteData(data) {
283
270
  yield fallbackRoute;
284
271
  }
285
272
  }
286
- async function getPathsForRoute(route, mod, pipeline, builtPaths) {
273
+ async function getPathsForRoute(pageData, mod, pipeline, builtPaths) {
287
274
  const opts = pipeline.getStaticBuildOptions();
288
275
  const logger = pipeline.getLogger();
289
276
  let paths = [];
290
- if (route.pathname) {
291
- paths.push(route.pathname);
292
- builtPaths.add(route.pathname);
293
- for (const virtualRoute of route.fallbackRoutes) {
277
+ if (pageData.route.pathname) {
278
+ paths.push(pageData.route.pathname);
279
+ builtPaths.add(pageData.route.pathname);
280
+ for (const virtualRoute of pageData.route.fallbackRoutes) {
294
281
  if (virtualRoute.pathname) {
295
282
  paths.push(virtualRoute.pathname);
296
283
  builtPaths.add(virtualRoute.pathname);
297
284
  }
298
285
  }
299
286
  } else {
300
- const staticPaths = await callGetStaticPaths({
301
- mod,
302
- route,
303
- routeCache: opts.routeCache,
304
- logger,
305
- ssr: isServerLikeOutput(opts.settings.config)
306
- }).catch((err) => {
307
- logger.debug("build", `\u251C\u2500\u2500 ${colors.bold(colors.red("\u2717"))} ${route.component}`);
308
- throw err;
309
- });
310
- const label = staticPaths.length === 1 ? "page" : "pages";
311
- logger.debug(
312
- "build",
313
- `\u251C\u2500\u2500 ${colors.bold(colors.green("\u2714"))} ${route.component} \u2192 ${colors.magenta(
314
- `[${staticPaths.length} ${label}]`
315
- )}`
316
- );
317
- paths = staticPaths.map((staticPath) => {
318
- try {
319
- return route.generate(staticPath.params);
320
- } catch (e) {
321
- if (e instanceof TypeError) {
322
- throw getInvalidRouteSegmentError(e, route, staticPath);
323
- }
324
- throw e;
325
- }
326
- }).filter((staticPath) => {
327
- if (!builtPaths.has(removeTrailingForwardSlash(staticPath))) {
328
- return true;
287
+ for (const route of eachRouteInRouteData(pageData)) {
288
+ const staticPaths = await callGetStaticPaths({
289
+ mod,
290
+ route,
291
+ routeCache: opts.routeCache,
292
+ logger,
293
+ ssr: isServerLikeOutput(opts.settings.config)
294
+ }).catch((err) => {
295
+ logger.debug("build", `\u251C\u2500\u2500 ${colors.bold(colors.red("\u2717"))} ${route.component}`);
296
+ throw err;
297
+ });
298
+ const label = staticPaths.length === 1 ? "page" : "pages";
299
+ logger.debug(
300
+ "build",
301
+ `\u251C\u2500\u2500 ${colors.bold(colors.green("\u2714"))} ${route.component} \u2192 ${colors.magenta(
302
+ `[${staticPaths.length} ${label}]`
303
+ )}`
304
+ );
305
+ paths.push(
306
+ ...staticPaths.map((staticPath) => {
307
+ try {
308
+ return route.generate(staticPath.params);
309
+ } catch (e) {
310
+ if (e instanceof TypeError) {
311
+ throw getInvalidRouteSegmentError(e, route, staticPath);
312
+ }
313
+ throw e;
314
+ }
315
+ }).filter((staticPath) => {
316
+ if (!builtPaths.has(removeTrailingForwardSlash(staticPath))) {
317
+ return true;
318
+ }
319
+ const matchedRoute = matchRoute(staticPath, opts.manifest);
320
+ return matchedRoute === route;
321
+ })
322
+ );
323
+ for (const staticPath of paths) {
324
+ builtPaths.add(removeTrailingForwardSlash(staticPath));
329
325
  }
330
- const matchedRoute = matchRoute(staticPath, opts.manifest);
331
- return matchedRoute === route;
332
- });
333
- for (const staticPath of paths) {
334
- builtPaths.add(removeTrailingForwardSlash(staticPath));
335
326
  }
336
327
  }
337
328
  return paths;
@@ -380,69 +371,90 @@ function getUrlForPath(pathname, base, origin, format, routeType) {
380
371
  const url = new URL(buildPathname, origin);
381
372
  return url;
382
373
  }
383
- async function generatePath(pathname, pipeline, route, links, scripts, styles, mod) {
374
+ async function generatePath(pathname, gopts, pipeline) {
384
375
  const manifest = pipeline.getManifest();
385
- const logger = pipeline.getLogger();
386
- pipeline.getEnvironment().logger.debug("build", `Generating: ${pathname}`);
387
- const icon = route.type === "page" || route.type === "redirect" || route.type === "fallback" ? green("\u25B6") : magenta("\u03BB");
388
- if (isRelativePath(route.component)) {
389
- logger.info(null, `${icon} ${route.route}`);
390
- } else {
391
- logger.info(null, `${icon} ${route.component}`);
392
- }
393
- if (route.type === "page") {
394
- addPageName(pathname, pipeline.getStaticBuildOptions());
395
- }
396
- const ssr = isServerLikeOutput(pipeline.getConfig());
397
- const url = getUrlForPath(
398
- pathname,
399
- pipeline.getConfig().base,
400
- pipeline.getStaticBuildOptions().origin,
401
- pipeline.getConfig().build.format,
402
- route.type
403
- );
404
- const request = createRequest({
405
- url,
406
- headers: new Headers(),
407
- logger: pipeline.getLogger(),
408
- ssr
409
- });
410
- const i18n = pipeline.getConfig().experimental.i18n;
411
- const renderContext = await createRenderContext({
412
- pathname,
413
- request,
414
- componentMetadata: manifest.componentMetadata,
415
- scripts,
416
- styles,
417
- links,
418
- route,
419
- env: pipeline.getEnvironment(),
420
- mod,
421
- locales: i18n?.locales,
422
- routingStrategy: i18n?.routingStrategy,
423
- defaultLocale: i18n?.defaultLocale
424
- });
425
- let body;
426
- let encoding;
427
- let response;
428
- try {
429
- response = await pipeline.renderRoute(renderContext, mod);
430
- } catch (err) {
431
- if (!AstroError.is(err) && !err.id && typeof err === "object") {
432
- err.id = route.component;
376
+ const { mod, scripts: hoistedScripts, styles: _styles, pageData } = gopts;
377
+ for (const route of eachRouteInRouteData(pageData)) {
378
+ if (route.type === "page") {
379
+ addPageName(pathname, pipeline.getStaticBuildOptions());
433
380
  }
434
- throw err;
435
- }
436
- if (response.status >= 300 && response.status < 400) {
437
- if (!pipeline.getConfig().build.redirects) {
438
- return;
381
+ pipeline.getEnvironment().logger.debug("build", `Generating: ${pathname}`);
382
+ const links = /* @__PURE__ */ new Set();
383
+ const scripts = createModuleScriptsSet(
384
+ hoistedScripts ? [hoistedScripts] : [],
385
+ manifest.base,
386
+ manifest.assetsPrefix
387
+ );
388
+ const styles = createStylesheetElementSet(_styles, manifest.base, manifest.assetsPrefix);
389
+ if (pipeline.getSettings().scripts.some((script) => script.stage === "page")) {
390
+ const hashedFilePath = pipeline.getInternals().entrySpecifierToBundleMap.get(PAGE_SCRIPT_ID);
391
+ if (typeof hashedFilePath !== "string") {
392
+ throw new Error(`Cannot find the built path for ${PAGE_SCRIPT_ID}`);
393
+ }
394
+ const src = createAssetLink(hashedFilePath, manifest.base, manifest.assetsPrefix);
395
+ scripts.add({
396
+ props: { type: "module", src },
397
+ children: ""
398
+ });
399
+ }
400
+ for (const script of pipeline.getSettings().scripts) {
401
+ if (script.stage === "head-inline") {
402
+ scripts.add({
403
+ props: {},
404
+ children: script.content
405
+ });
406
+ }
439
407
  }
440
- const locationSite = getRedirectLocationOrThrow(response.headers);
441
- const siteURL = pipeline.getConfig().site;
442
- const location = siteURL ? new URL(locationSite, siteURL) : locationSite;
443
- const fromPath = new URL(renderContext.request.url).pathname;
444
- const delay = response.status === 302 ? 2 : 0;
445
- body = `<!doctype html>
408
+ const ssr = isServerLikeOutput(pipeline.getConfig());
409
+ const url = getUrlForPath(
410
+ pathname,
411
+ pipeline.getConfig().base,
412
+ pipeline.getStaticBuildOptions().origin,
413
+ pipeline.getConfig().build.format,
414
+ route.type
415
+ );
416
+ const request = createRequest({
417
+ url,
418
+ headers: new Headers(),
419
+ logger: pipeline.getLogger(),
420
+ ssr
421
+ });
422
+ const i18n = pipeline.getConfig().experimental.i18n;
423
+ const renderContext = await createRenderContext({
424
+ pathname,
425
+ request,
426
+ componentMetadata: manifest.componentMetadata,
427
+ scripts,
428
+ styles,
429
+ links,
430
+ route,
431
+ env: pipeline.getEnvironment(),
432
+ mod,
433
+ locales: i18n?.locales,
434
+ routingStrategy: i18n?.routingStrategy,
435
+ defaultLocale: i18n?.defaultLocale
436
+ });
437
+ let body;
438
+ let encoding;
439
+ let response;
440
+ try {
441
+ response = await pipeline.renderRoute(renderContext, mod);
442
+ } catch (err) {
443
+ if (!AstroError.is(err) && !err.id && typeof err === "object") {
444
+ err.id = pageData.component;
445
+ }
446
+ throw err;
447
+ }
448
+ if (response.status >= 300 && response.status < 400) {
449
+ if (!pipeline.getConfig().build.redirects) {
450
+ return;
451
+ }
452
+ const locationSite = getRedirectLocationOrThrow(response.headers);
453
+ const siteURL = pipeline.getConfig().site;
454
+ const location = siteURL ? new URL(locationSite, siteURL) : locationSite;
455
+ const fromPath = new URL(renderContext.request.url).pathname;
456
+ const delay = response.status === 302 ? 2 : 0;
457
+ body = `<!doctype html>
446
458
  <title>Redirecting to: ${location}</title>
447
459
  <meta http-equiv="refresh" content="${delay};url=${location}">
448
460
  <meta name="robots" content="noindex">
@@ -450,23 +462,24 @@ async function generatePath(pathname, pipeline, route, links, scripts, styles, m
450
462
  <body>
451
463
  <a href="${location}">Redirecting from <code>${fromPath}</code> to <code>${location}</code></a>
452
464
  </body>`;
453
- if (pipeline.getConfig().compressHTML === true) {
454
- body = body.replaceAll("\n", "");
455
- }
456
- if (route.type !== "redirect") {
457
- route.redirect = location.toString();
465
+ if (pipeline.getConfig().compressHTML === true) {
466
+ body = body.replaceAll("\n", "");
467
+ }
468
+ if (route.type !== "redirect") {
469
+ route.redirect = location.toString();
470
+ }
471
+ } else {
472
+ if (!response.body)
473
+ return;
474
+ body = Buffer.from(await response.arrayBuffer());
475
+ encoding = response.headers.get("X-Astro-Encoding") ?? "utf-8";
458
476
  }
459
- } else {
460
- if (!response.body)
461
- return;
462
- body = Buffer.from(await response.arrayBuffer());
463
- encoding = response.headers.get("X-Astro-Encoding") ?? "utf-8";
477
+ const outFolder = getOutFolder(pipeline.getConfig(), pathname, route.type);
478
+ const outFile = getOutFile(pipeline.getConfig(), outFolder, pathname, route.type);
479
+ route.distURL = outFile;
480
+ await fs.promises.mkdir(outFolder, { recursive: true });
481
+ await fs.promises.writeFile(outFile, body, encoding);
464
482
  }
465
- const outFolder = getOutFolder(pipeline.getConfig(), pathname, route.type);
466
- const outFile = getOutFile(pipeline.getConfig(), outFolder, pathname, route.type);
467
- route.distURL = outFile;
468
- await fs.promises.mkdir(outFolder, { recursive: true });
469
- await fs.promises.writeFile(outFile, body, encoding);
470
483
  }
471
484
  function createBuildManifest(settings, internals, renderers) {
472
485
  let i18nManifest = void 0;
@@ -1,4 +1,4 @@
1
- const ASTRO_VERSION = "3.5.6";
1
+ const ASTRO_VERSION = "3.6.0";
2
2
  const SUPPORTED_MARKDOWN_FILE_EXTENSIONS = [
3
3
  ".markdown",
4
4
  ".mdown",
@@ -20,7 +20,7 @@ async function dev(inlineConfig) {
20
20
  base: restart.container.settings.config.base
21
21
  })
22
22
  );
23
- const currentVersion = "3.5.6";
23
+ const currentVersion = "3.6.0";
24
24
  if (currentVersion.includes("-")) {
25
25
  logger.warn(null, msg.prerelease({ currentVersion }));
26
26
  }
@@ -50,7 +50,7 @@ function serverStart({
50
50
  base,
51
51
  isRestart = false
52
52
  }) {
53
- const version = "3.5.6";
53
+ const version = "3.6.0";
54
54
  const localPrefix = `${dim("\u2503")} Local `;
55
55
  const networkPrefix = `${dim("\u2503")} Network `;
56
56
  const emptyPrefix = " ".repeat(11);
@@ -235,7 +235,7 @@ function printHelp({
235
235
  message.push(
236
236
  linebreak(),
237
237
  ` ${bgGreen(black(` ${commandName} `))} ${green(
238
- `v${"3.5.6"}`
238
+ `v${"3.6.0"}`
239
239
  )} ${headline}`
240
240
  );
241
241
  }
@@ -417,20 +417,25 @@ This route collides with: "${collision.component}".`
417
417
  if (!hasRoute) {
418
418
  let pathname;
419
419
  let route;
420
- if (fallbackToLocale === i18n.defaultLocale && i18n.routingStrategy === "prefix-other-locales") {
420
+ if (fallbackToLocale === i18n.defaultLocale) {
421
421
  if (fallbackToRoute.pathname) {
422
422
  pathname = `/${fallbackFromLocale}${fallbackToRoute.pathname}`;
423
423
  }
424
424
  route = `/${fallbackFromLocale}${fallbackToRoute.route}`;
425
425
  } else {
426
- pathname = fallbackToRoute.pathname?.replace(`/${fallbackToLocale}/`, `/${fallbackFromLocale}/`).replace(`/${fallbackToLocale}`, `/${fallbackFromLocale}`);
427
- route = fallbackToRoute.route.replace(`/${fallbackToLocale}`, `/${fallbackFromLocale}`).replace(`/${fallbackToLocale}/`, `/${fallbackFromLocale}/`);
426
+ pathname = fallbackToRoute.pathname?.replace(
427
+ `/${fallbackToLocale}`,
428
+ `/${fallbackFromLocale}`
429
+ );
430
+ route = fallbackToRoute.route.replace(
431
+ `/${fallbackToLocale}`,
432
+ `/${fallbackFromLocale}`
433
+ );
428
434
  }
429
435
  const segments = removeLeadingForwardSlash(route).split(path.posix.sep).filter(Boolean).map((s) => {
430
436
  validateSegment(s);
431
437
  return getParts(s, route);
432
438
  });
433
- const generate = getRouteGenerator(segments, config.trailingSlash);
434
439
  const index = routes.findIndex((r) => r === fallbackToRoute);
435
440
  if (index) {
436
441
  const fallbackRoute = {
@@ -438,7 +443,6 @@ This route collides with: "${collision.component}".`
438
443
  pathname,
439
444
  route,
440
445
  segments,
441
- generate,
442
446
  pattern: getPattern(segments, config, config.trailingSlash),
443
447
  type: "fallback",
444
448
  fallbackRoutes: []
@@ -16,7 +16,7 @@ function getParams(array) {
16
16
  }
17
17
  function stringifyParams(params, route) {
18
18
  const validatedParams = Object.entries(params).reduce((acc, next) => {
19
- validateGetStaticPathsParameter(next, route.route);
19
+ validateGetStaticPathsParameter(next, route.component);
20
20
  const [key, value] = next;
21
21
  if (value !== void 0) {
22
22
  acc[key] = typeof value === "string" ? trimSlashes(value) : value.toString();
@@ -23,7 +23,7 @@ function createI18nMiddleware(i18n, base, trailingSlash) {
23
23
  }
24
24
  }
25
25
  const url = context.url;
26
- const { locales, defaultLocale, fallback, routingStrategy } = i18n;
26
+ const { locales, defaultLocale, fallback } = i18n;
27
27
  const response = await next();
28
28
  if (response instanceof Response) {
29
29
  const separators = url.pathname.split("/");
@@ -56,7 +56,7 @@ function createI18nMiddleware(i18n, base, trailingSlash) {
56
56
  if (urlLocale && fallbackKeys.includes(urlLocale)) {
57
57
  const fallbackLocale = fallback[urlLocale];
58
58
  let newPathname;
59
- if (fallbackLocale === defaultLocale && routingStrategy === "prefix-other-locales") {
59
+ if (fallbackLocale === defaultLocale) {
60
60
  newPathname = url.pathname.replace(`/${urlLocale}`, ``);
61
61
  } else {
62
62
  newPathname = url.pathname.replace(`/${urlLocale}`, `/${fallbackLocale}`);
@@ -15,6 +15,10 @@ export interface PrefetchOptions {
15
15
  * - `'fetch'`: use `fetch()`, has higher loading priority.
16
16
  */
17
17
  with?: 'link' | 'fetch';
18
+ /**
19
+ * Should prefetch even on data saver mode or slow connection. (default `false`)
20
+ */
21
+ ignoreSlowConnection?: boolean;
18
22
  }
19
23
  /**
20
24
  * Prefetch a URL so it's cached when the user navigates to it.
@@ -24,7 +24,7 @@ function initTapStrategy() {
24
24
  event,
25
25
  (e) => {
26
26
  if (elMatchesStrategy(e.target, "tap")) {
27
- prefetch(e.target.href, { with: "fetch" });
27
+ prefetch(e.target.href, { with: "fetch", ignoreSlowConnection: true });
28
28
  }
29
29
  },
30
30
  { passive: true }
@@ -112,7 +112,8 @@ function createViewportIntersectionObserver() {
112
112
  });
113
113
  }
114
114
  function prefetch(url, opts) {
115
- if (!canPrefetchUrl(url))
115
+ const ignoreSlowConnection = opts?.ignoreSlowConnection ?? false;
116
+ if (!canPrefetchUrl(url, ignoreSlowConnection))
116
117
  return;
117
118
  prefetchedUrls.add(url);
118
119
  const priority = opts?.with ?? "link";
@@ -129,14 +130,11 @@ function prefetch(url, opts) {
129
130
  });
130
131
  }
131
132
  }
132
- function canPrefetchUrl(url) {
133
+ function canPrefetchUrl(url, ignoreSlowConnection) {
133
134
  if (!navigator.onLine)
134
135
  return false;
135
- if ("connection" in navigator) {
136
- const conn = navigator.connection;
137
- if (conn.saveData || /(2|3)g/.test(conn.effectiveType))
138
- return false;
139
- }
136
+ if (!ignoreSlowConnection && isSlowConnection())
137
+ return false;
140
138
  try {
141
139
  const urlObj = new URL(url, location.href);
142
140
  return location.origin === urlObj.origin && location.pathname !== urlObj.pathname && !prefetchedUrls.has(url);
@@ -151,6 +149,9 @@ function elMatchesStrategy(el, strategy) {
151
149
  if (attrValue === "false") {
152
150
  return false;
153
151
  }
152
+ if (strategy === "tap" && (attrValue != null || prefetchAll) && isSlowConnection()) {
153
+ return true;
154
+ }
154
155
  if (attrValue == null && prefetchAll || attrValue === "") {
155
156
  return strategy === defaultStrategy;
156
157
  }
@@ -159,6 +160,13 @@ function elMatchesStrategy(el, strategy) {
159
160
  }
160
161
  return false;
161
162
  }
163
+ function isSlowConnection() {
164
+ if ("connection" in navigator) {
165
+ const conn = navigator.connection;
166
+ return conn.saveData || /(2|3)g/.test(conn.effectiveType);
167
+ }
168
+ return false;
169
+ }
162
170
  function onPageLoad(cb) {
163
171
  cb();
164
172
  let firstLoad = false;
@@ -1,3 +1,7 @@
1
- import type { SSRResult, TransitionAnimationValue } from '../../@types/astro.js';
1
+ import type { SSRResult, TransitionAnimationPair, TransitionAnimationValue } from '../../@types/astro.js';
2
2
  export declare function createTransitionScope(result: SSRResult, hash: string): string;
3
3
  export declare function renderTransition(result: SSRResult, hash: string, animationName: TransitionAnimationValue | undefined, transitionName: string): string;
4
+ export declare function createAnimationScope(transitionName: string, animations: Record<string, TransitionAnimationPair>): {
5
+ scope: string;
6
+ styles: string;
7
+ };