reroute-js 1.0.0-alpha.39 → 1.0.0-alpha.40

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 (236) hide show
  1. package/README.md +34 -0
  2. package/cli/bin.d.ts +1 -1
  3. package/cli/bin.js +231 -50
  4. package/cli/bin.js.map +13 -13
  5. package/cli/index.d.ts +1 -1
  6. package/cli/index.js +8 -5
  7. package/cli/index.js.map +11 -10
  8. package/cli/src/cli.d.ts +1 -1
  9. package/cli/src/commands/analyze.d.ts +1 -1
  10. package/cli/src/commands/build.d.ts +1 -1
  11. package/cli/src/commands/dev.d.ts +1 -1
  12. package/cli/src/commands/gen.d.ts +1 -1
  13. package/cli/src/commands/gen.d.ts.map +1 -1
  14. package/cli/src/commands/index.d.ts +1 -1
  15. package/cli/src/commands/init.d.ts +1 -1
  16. package/cli/src/commands/lib/assets.d.ts +1 -1
  17. package/cli/src/commands/lib/bundler.d.ts +1 -1
  18. package/cli/src/commands/lib/command.d.ts +1 -1
  19. package/cli/src/commands/lib/env.d.ts +1 -1
  20. package/cli/src/commands/lib/images.d.ts +1 -1
  21. package/cli/src/commands/lib/index.d.ts +1 -1
  22. package/cli/src/commands/lib/log.d.ts +1 -1
  23. package/cli/src/commands/lib/markdown/availability.d.ts +1 -1
  24. package/cli/src/commands/lib/markdown/index.d.ts +1 -1
  25. package/cli/src/commands/lib/markdown/processor.d.ts +1 -1
  26. package/cli/src/commands/lib/prerender.d.ts +1 -1
  27. package/cli/src/commands/lib/production.d.ts +1 -1
  28. package/cli/src/commands/lib/routes.d.ts +1 -1
  29. package/cli/src/commands/lib/server.d.ts +1 -1
  30. package/cli/src/commands/lib/ssr-strip.d.ts +1 -1
  31. package/cli/src/commands/lib/static.d.ts +1 -1
  32. package/cli/src/commands/lib/streaming/analyzer.d.ts +1 -1
  33. package/cli/src/commands/lib/streaming/suspense.d.ts +1 -1
  34. package/cli/src/commands/lib/supervise.d.ts +1 -1
  35. package/cli/src/commands/lib/terminal-ui.d.ts +1 -1
  36. package/cli/src/commands/lib/theme.d.ts +1 -1
  37. package/cli/src/commands/lib/version.d.ts +1 -1
  38. package/cli/src/commands/lib/watch.d.ts +1 -1
  39. package/cli/src/commands/og.d.ts +1 -1
  40. package/cli/src/commands/start.d.ts +1 -1
  41. package/cli/src/commands/static-render.d.ts +1 -1
  42. package/cli/src/index.d.ts +1 -1
  43. package/core/index.d.ts +1 -1
  44. package/core/index.js +221 -46
  45. package/core/index.js.map +12 -12
  46. package/core/src/app-paths.d.ts +1 -1
  47. package/core/src/bundler/hash.d.ts +1 -1
  48. package/core/src/bundler/index.d.ts +1 -1
  49. package/core/src/config.d.ts +1 -1
  50. package/core/src/content/discovery.d.ts +1 -1
  51. package/core/src/content/index.d.ts +1 -1
  52. package/core/src/content/metadata.d.ts +1 -1
  53. package/core/src/i18n/catalog.d.ts +1 -1
  54. package/core/src/i18n/discover.d.ts +1 -1
  55. package/core/src/i18n/discover.d.ts.map +1 -1
  56. package/core/src/i18n/index.d.ts +2 -2
  57. package/core/src/i18n/index.d.ts.map +1 -1
  58. package/core/src/i18n/messages.d.ts +1 -1
  59. package/core/src/i18n/negotiate.d.ts +1 -1
  60. package/core/src/i18n/pathname.d.ts +32 -4
  61. package/core/src/i18n/pathname.d.ts.map +1 -1
  62. package/core/src/i18n/resolve.d.ts +3 -2
  63. package/core/src/i18n/resolve.d.ts.map +1 -1
  64. package/core/src/i18n/types.d.ts +44 -1
  65. package/core/src/i18n/types.d.ts.map +1 -1
  66. package/core/src/image.d.ts +1 -1
  67. package/core/src/index.d.ts +1 -1
  68. package/core/src/llms/discovery.d.ts +1 -1
  69. package/core/src/llms/extractor.d.ts +1 -1
  70. package/core/src/llms/formatter.d.ts +1 -1
  71. package/core/src/llms/full-generator.d.ts +1 -1
  72. package/core/src/llms/index-generator.d.ts +1 -1
  73. package/core/src/llms/index.d.ts +1 -1
  74. package/core/src/og/discovery.d.ts +1 -1
  75. package/core/src/og/index.d.ts +1 -1
  76. package/core/src/og/meta.d.ts +1 -1
  77. package/core/src/og/render.d.ts +1 -1
  78. package/core/src/og/types.d.ts +1 -1
  79. package/core/src/robots/discovery.d.ts +1 -1
  80. package/core/src/robots/generator.d.ts +1 -1
  81. package/core/src/robots/index.d.ts +1 -1
  82. package/core/src/robots/policies.d.ts +1 -1
  83. package/core/src/rss/discovery.d.ts +1 -1
  84. package/core/src/rss/generator.d.ts +1 -1
  85. package/core/src/rss/index.d.ts +1 -1
  86. package/core/src/sitemap/discovery.d.ts +1 -1
  87. package/core/src/sitemap/generator.d.ts +12 -2
  88. package/core/src/sitemap/generator.d.ts.map +1 -1
  89. package/core/src/sitemap/index.d.ts +1 -1
  90. package/core/src/ssr/index.d.ts +1 -1
  91. package/core/src/ssr/lib/cache.d.ts +1 -1
  92. package/core/src/ssr/lib/cleanup.d.ts +1 -1
  93. package/core/src/ssr/lib/collections.d.ts +1 -1
  94. package/core/src/ssr/lib/compression.d.ts +1 -1
  95. package/core/src/ssr/lib/compute/content.d.ts +1 -1
  96. package/core/src/ssr/lib/compute/index.d.ts +1 -1
  97. package/core/src/ssr/lib/compute/layouts.d.ts +1 -1
  98. package/core/src/ssr/lib/compute/layouts.d.ts.map +1 -1
  99. package/core/src/ssr/lib/compute/routes.d.ts +1 -1
  100. package/core/src/ssr/lib/compute/routes.d.ts.map +1 -1
  101. package/core/src/ssr/lib/content-path.d.ts +13 -2
  102. package/core/src/ssr/lib/content-path.d.ts.map +1 -1
  103. package/core/src/ssr/lib/data.d.ts +1 -1
  104. package/core/src/ssr/lib/html.d.ts +1 -1
  105. package/core/src/ssr/lib/imports.d.ts +1 -1
  106. package/core/src/ssr/lib/index.d.ts +1 -1
  107. package/core/src/ssr/lib/layouts.d.ts +1 -1
  108. package/core/src/ssr/lib/metadata.d.ts +1 -1
  109. package/core/src/ssr/lib/metadata.d.ts.map +1 -1
  110. package/core/src/ssr/lib/mime.d.ts +1 -1
  111. package/core/src/ssr/lib/modules.d.ts +1 -1
  112. package/core/src/ssr/lib/path.d.ts +1 -1
  113. package/core/src/ssr/lib/preload.d.ts +1 -1
  114. package/core/src/ssr/lib/route-match.d.ts +1 -1
  115. package/core/src/ssr/lib/scripts/collections.d.ts +1 -1
  116. package/core/src/ssr/lib/scripts/data.d.ts +1 -1
  117. package/core/src/ssr/lib/scripts/escape.d.ts +1 -1
  118. package/core/src/ssr/lib/scripts/feeds.d.ts +1 -1
  119. package/core/src/ssr/lib/scripts/index.d.ts +1 -1
  120. package/core/src/ssr/lib/seed.d.ts +1 -1
  121. package/core/src/ssr/lib/serialize.d.ts +1 -1
  122. package/core/src/ssr/lib/setup.d.ts +1 -1
  123. package/core/src/ssr/lib/styles.d.ts +1 -1
  124. package/core/src/ssr/lib/template.d.ts +1 -1
  125. package/core/src/ssr/lib/types.d.ts +7 -1
  126. package/core/src/ssr/lib/types.d.ts.map +1 -1
  127. package/core/src/ssr/render.d.ts +1 -1
  128. package/core/src/ssr/stream.d.ts +1 -1
  129. package/core/src/ssr/stream.d.ts.map +1 -1
  130. package/elysia/index.d.ts +1 -1
  131. package/elysia/index.js +370 -87
  132. package/elysia/index.js.map +18 -17
  133. package/elysia/src/index.d.ts +1 -1
  134. package/elysia/src/libs/assets.d.ts +1 -1
  135. package/elysia/src/libs/cache.d.ts +1 -1
  136. package/elysia/src/libs/caching.d.ts +1 -1
  137. package/elysia/src/libs/devReload.d.ts +1 -1
  138. package/elysia/src/libs/http.d.ts +1 -1
  139. package/elysia/src/libs/i18n.d.ts +14 -3
  140. package/elysia/src/libs/i18n.d.ts.map +1 -1
  141. package/elysia/src/libs/image.d.ts +1 -1
  142. package/elysia/src/libs/index.d.ts +1 -1
  143. package/elysia/src/libs/lazyData.d.ts +38 -0
  144. package/elysia/src/libs/lazyData.d.ts.map +1 -0
  145. package/elysia/src/libs/llms.d.ts +1 -1
  146. package/elysia/src/libs/response.d.ts +1 -1
  147. package/elysia/src/libs/serving.d.ts +1 -1
  148. package/elysia/src/plugin.d.ts +1 -1
  149. package/elysia/src/routes/artifacts.d.ts +1 -1
  150. package/elysia/src/routes/content.d.ts +1 -1
  151. package/elysia/src/routes/image.d.ts +1 -1
  152. package/elysia/src/routes/index.d.ts +1 -1
  153. package/elysia/src/routes/internal.d.ts +1 -1
  154. package/elysia/src/routes/internal.d.ts.map +1 -1
  155. package/elysia/src/routes/liveReloadClient.d.ts +1 -1
  156. package/elysia/src/routes/llms.d.ts +1 -1
  157. package/elysia/src/routes/og.d.ts +1 -1
  158. package/elysia/src/routes/redirects.d.ts +1 -1
  159. package/elysia/src/routes/robots.d.ts +1 -1
  160. package/elysia/src/routes/rss.d.ts +1 -1
  161. package/elysia/src/routes/search.d.ts +1 -1
  162. package/elysia/src/routes/sitemap.d.ts +1 -1
  163. package/elysia/src/routes/sitemap.d.ts.map +1 -1
  164. package/elysia/src/routes/ssr.d.ts +1 -1
  165. package/elysia/src/routes/ssr.d.ts.map +1 -1
  166. package/elysia/src/routes/static.d.ts +1 -1
  167. package/elysia/src/routes/themeCssRefresh.d.ts +1 -1
  168. package/elysia/src/types.d.ts +1 -1
  169. package/package.json +1 -1
  170. package/react/index.d.ts +1 -1
  171. package/react/index.js +85 -20
  172. package/react/index.js.map +6 -6
  173. package/react/src/components/ClientOnly.d.ts +1 -1
  174. package/react/src/components/ContentRoute.d.ts +1 -1
  175. package/react/src/components/Image.d.ts +1 -1
  176. package/react/src/components/LazyRoute.d.ts +1 -1
  177. package/react/src/components/Link.d.ts +1 -1
  178. package/react/src/components/Markdown.d.ts +1 -1
  179. package/react/src/components/Outlet.d.ts +1 -1
  180. package/react/src/components/index.d.ts +1 -1
  181. package/react/src/hooks/index.d.ts +1 -1
  182. package/react/src/hooks/useContent.d.ts +1 -1
  183. package/react/src/hooks/useData.d.ts +1 -1
  184. package/react/src/hooks/useFeed.d.ts +1 -1
  185. package/react/src/hooks/useLayoutData.d.ts +1 -1
  186. package/react/src/hooks/useLlms.d.ts +1 -1
  187. package/react/src/hooks/useNavigate.d.ts +1 -1
  188. package/react/src/hooks/useParams.d.ts +1 -1
  189. package/react/src/hooks/useRouter.d.ts +1 -1
  190. package/react/src/hooks/useSearch.d.ts +1 -1
  191. package/react/src/hooks/useSearchParams.d.ts +1 -1
  192. package/react/src/hooks/useToc.d.ts +1 -1
  193. package/react/src/i18n/LocaleProvider.d.ts +20 -2
  194. package/react/src/i18n/LocaleProvider.d.ts.map +1 -1
  195. package/react/src/i18n/helpers.d.ts +31 -3
  196. package/react/src/i18n/helpers.d.ts.map +1 -1
  197. package/react/src/i18n/index.d.ts +2 -2
  198. package/react/src/i18n/index.d.ts.map +1 -1
  199. package/react/src/index.d.ts +1 -1
  200. package/react/src/lib/bundle.d.ts +1 -1
  201. package/react/src/lib/collection.d.ts +1 -1
  202. package/react/src/lib/content.d.ts +1 -1
  203. package/react/src/lib/head.d.ts +1 -1
  204. package/react/src/lib/index.d.ts +1 -1
  205. package/react/src/lib/layouts.d.ts +1 -1
  206. package/react/src/lib/lazy-route.d.ts +1 -1
  207. package/react/src/lib/route-loader.d.ts +1 -1
  208. package/react/src/lib/static-data.d.ts +1 -1
  209. package/react/src/providers/ContentProvider.d.ts +1 -1
  210. package/react/src/providers/RerouteProvider.d.ts +1 -1
  211. package/react/src/providers/RerouteProvider.d.ts.map +1 -1
  212. package/react/src/providers/RouterProvider.d.ts +4 -2
  213. package/react/src/providers/RouterProvider.d.ts.map +1 -1
  214. package/react/src/providers/index.d.ts +1 -1
  215. package/react/src/types/any.d.ts +1 -1
  216. package/react/src/types/index.d.ts +1 -1
  217. package/react/src/types/router.d.ts +7 -1
  218. package/react/src/types/router.d.ts.map +1 -1
  219. package/telemetry/react.d.ts +1 -1
  220. package/telemetry/react.js +2 -2
  221. package/telemetry/react.js.map +1 -1
  222. package/telemetry/server.d.ts +1 -1
  223. package/telemetry/server.js +6 -3
  224. package/telemetry/server.js.map +11 -10
  225. package/telemetry/src/react/api.d.ts +1 -1
  226. package/telemetry/src/react/context.d.ts +1 -1
  227. package/telemetry/src/react/index.d.ts +1 -1
  228. package/telemetry/src/react/telemetry.d.ts +1 -1
  229. package/telemetry/src/server/context.d.ts +1 -1
  230. package/telemetry/src/server/headers/extractor.d.ts +1 -1
  231. package/telemetry/src/server/headers/index.d.ts +1 -1
  232. package/telemetry/src/server/headers/presets.d.ts +1 -1
  233. package/telemetry/src/server/index.d.ts +1 -1
  234. package/telemetry/src/server/instrumentation.d.ts +1 -1
  235. package/telemetry/src/server/plugin.d.ts +1 -1
  236. package/telemetry/src/server/sourcemap.d.ts +1 -1
package/core/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * reroute-js v1.0.0-alpha.39
2
+ * reroute-js v1.0.0-alpha.40
3
3
  *
4
4
  * @license MIT
5
5
  * @copyright 2026 stewones <hi@stewan.io>
@@ -286,6 +286,9 @@ async function discoverI18n(cwd, options = {}) {
286
286
  const defaultLocale = options.defaultLocale ?? DEFAULT_LOCALE;
287
287
  const cookie = options.cookie ?? DEFAULT_COOKIE;
288
288
  const redirectContentOnNegotiate = options.redirectContentOnNegotiate ?? true;
289
+ const prefixPages = options.prefixPages ?? false;
290
+ const unprefixedPaths = options.unprefixedPaths ?? [];
291
+ const localeParam = options.localeParam ?? "";
289
292
  const absDir = join2(cwd, localesDir);
290
293
  const disabled = {
291
294
  enabled: false,
@@ -294,6 +297,9 @@ async function discoverI18n(cwd, options = {}) {
294
297
  localesDir,
295
298
  cookie,
296
299
  redirectContentOnNegotiate,
300
+ prefixPages,
301
+ unprefixedPaths,
302
+ localeParam,
297
303
  catalogs: {}
298
304
  };
299
305
  let catalogs;
@@ -317,6 +323,9 @@ async function discoverI18n(cwd, options = {}) {
317
323
  localesDir,
318
324
  cookie,
319
325
  redirectContentOnNegotiate,
326
+ prefixPages,
327
+ unprefixedPaths,
328
+ localeParam,
320
329
  catalogs
321
330
  };
322
331
  }
@@ -417,11 +426,15 @@ var exports_pathname = {};
417
426
  __export(exports_pathname, {
418
427
  contentKey: () => contentKey,
419
428
  hreflangTags: () => hreflangTags,
429
+ isUnprefixedPath: () => isUnprefixedPath,
420
430
  localizeContentHref: () => localizeContentHref,
421
431
  localizeHref: () => localizeHref,
432
+ localizePagePath: () => localizePagePath,
422
433
  looksLikeLocale: () => looksLikeLocale,
423
434
  normalizePathname: () => normalizePathname,
435
+ pageHreflangTags: () => pageHreflangTags,
424
436
  parseContentPath: () => parseContentPath,
437
+ parseLocalePrefix: () => parseLocalePrefix,
425
438
  toOgLocale: () => toOgLocale
426
439
  });
427
440
  function looksLikeLocale(segment) {
@@ -469,13 +482,36 @@ function localizeContentHref(collection, name, locale, defaultLocale) {
469
482
  }
470
483
  return `/${collection}/${locale}/${name}`;
471
484
  }
472
- function localizeHref(to, locale, defaultLocale, availableLocales = [], collections) {
485
+ function parseLocalePrefix(pathname, availableLocales) {
486
+ const [, segment = "", ...rest] = normalizePathname(pathname).split("/");
487
+ const locale = availableLocales.find((l) => l.toLowerCase() === segment.toLowerCase());
488
+ if (!locale)
489
+ return;
490
+ return { locale, segment, routingPathname: `/${rest.join("/")}` };
491
+ }
492
+ function localizePagePath(pathname, locale, defaultLocale) {
493
+ if (locale === defaultLocale)
494
+ return pathname;
495
+ return pathname === "/" ? `/${locale}` : `/${locale}${pathname}`;
496
+ }
497
+ function isUnprefixedPath(pathname, unprefixedPaths = []) {
498
+ const path = normalizePathname(pathname);
499
+ return unprefixedPaths.some((prefix) => {
500
+ const base = prefix.replace(/\/+$/, "");
501
+ return base === "" || path === base || path.startsWith(`${base}/`);
502
+ });
503
+ }
504
+ function localizeHref(to, locale, defaultLocale, availableLocales = [], collections, prefixPages) {
473
505
  try {
474
506
  const url = new URL(to, "http://local");
475
- const parsed = parseContentPath(url.pathname, availableLocales, collections);
476
- if (!parsed)
507
+ const parsed = parseContentPath(url.pathname, availableLocales, prefixPages ? collections ?? [] : collections);
508
+ if (parsed) {
509
+ url.pathname = localizeContentHref(parsed.collection, parsed.name, locale, defaultLocale);
510
+ } else if (prefixPages && to.startsWith("/") && url.origin === "http://local" && !/\.[^/]+$/.test(url.pathname) && !parseLocalePrefix(url.pathname, availableLocales) && !isUnprefixedPath(url.pathname, prefixPages.unprefixedPaths)) {
511
+ url.pathname = localizePagePath(url.pathname, locale, defaultLocale);
512
+ } else {
477
513
  return to;
478
- url.pathname = localizeContentHref(parsed.collection, parsed.name, locale, defaultLocale);
514
+ }
479
515
  return `${url.pathname}${url.search}${url.hash}`;
480
516
  } catch {
481
517
  return to;
@@ -490,18 +526,20 @@ function contentKey(collection, name, locale, defaultLocale = "en-US") {
490
526
  function toOgLocale(locale) {
491
527
  return locale.replace(/-/g, "_");
492
528
  }
493
- function hreflangTags(baseUrl, collection, name, locales, defaultLocale) {
529
+ function alternateLinks(baseUrl, locales, defaultLocale, pathFor) {
494
530
  const base = baseUrl.replace(/\/$/, "");
495
- const tags = [];
496
- for (const locale of locales) {
497
- const path = localizeContentHref(collection, name, locale, defaultLocale);
498
- tags.push(`<link rel="alternate" hreflang="${locale}" href="${base}${path}" />`);
499
- }
500
- const defaultPath = localizeContentHref(collection, name, defaultLocale, defaultLocale);
501
- tags.push(`<link rel="alternate" hreflang="x-default" href="${base}${defaultPath}" />`);
502
- return tags.join(`
531
+ return [...locales, "x-default"].map((hreflang) => {
532
+ const path = pathFor(hreflang === "x-default" ? defaultLocale : hreflang);
533
+ return `<link rel="alternate" hreflang="${hreflang}" href="${base}${path}" />`;
534
+ }).join(`
503
535
  `);
504
536
  }
537
+ function hreflangTags(baseUrl, collection, name, locales, defaultLocale) {
538
+ return alternateLinks(baseUrl, locales, defaultLocale, (locale) => localizeContentHref(collection, name, locale, defaultLocale));
539
+ }
540
+ function pageHreflangTags(baseUrl, routingPathname, locales, defaultLocale) {
541
+ return alternateLinks(baseUrl, locales, defaultLocale, (locale) => localizePagePath(routingPathname, locale, defaultLocale));
542
+ }
505
543
  var init_pathname = () => {};
506
544
 
507
545
  // packages/core/src/i18n/resolve.ts
@@ -525,7 +563,71 @@ function stripLangParam(search) {
525
563
  const rest = params.toString();
526
564
  return rest ? `?${rest}` : "";
527
565
  }
566
+ function unprefix(pagePathname, search, defaultLocale) {
567
+ const query = search ? `?${search.replace(/^\?/, "")}` : "";
568
+ return {
569
+ locale: defaultLocale,
570
+ routingPathname: pagePathname,
571
+ fromPath: true,
572
+ fromQuery: false,
573
+ redirectTo: `${pagePathname}${query}`,
574
+ permanent: true,
575
+ urlOnly: true
576
+ };
577
+ }
578
+ function resolvePrefixedLocale(input) {
579
+ const prefix = parseLocalePrefix(input.pathname, input.availableLocales);
580
+ const pagePathname = prefix?.routingPathname ?? normalizePathname(input.pathname);
581
+ if (!isUnprefixedPath(pagePathname, input.unprefixedPaths)) {
582
+ return resolvePrefixedPage(input, prefix, pagePathname);
583
+ }
584
+ return prefix ? unprefix(pagePathname, input.search, input.defaultLocale) : resolveNegotiatedLocale(input);
585
+ }
586
+ function resolvePrefixedPage(input, prefix, pagePathname) {
587
+ const { search, availableLocales, defaultLocale } = input;
588
+ const isAvailable = (locale2) => !!locale2 && availableLocales.some((l) => l.toLowerCase() === locale2.toLowerCase());
589
+ const parsed = parseContentPath(pagePathname, availableLocales, input.collections ?? []);
590
+ const urlLocale = parsed?.locale ?? prefix?.locale ?? defaultLocale;
591
+ const queryLocale = parseLangParam(search, isAvailable, availableLocales);
592
+ const locale = queryLocale ?? urlLocale;
593
+ const misplaced = !!prefix && (!!parsed || prefix.locale === defaultLocale || prefix.segment !== prefix.locale);
594
+ const defaultSegment = !prefix && parsed?.locale === defaultLocale;
595
+ const canonical = parsed ? localizeContentHref(parsed.collection, parsed.name, locale, defaultLocale) : localizePagePath(pagePathname, locale, defaultLocale);
596
+ return {
597
+ locale,
598
+ routingPathname: parsed?.routingPathname ?? pagePathname,
599
+ fromPath: !!(parsed?.locale || prefix),
600
+ fromQuery: !!queryLocale,
601
+ redirectTo: queryLocale || misplaced || defaultSegment ? `${canonical}${stripLangParam(search)}` : undefined,
602
+ permanent: !queryLocale && (misplaced || defaultSegment),
603
+ urlOnly: true,
604
+ parsed: parsed ? { ...parsed, locale } : undefined
605
+ };
606
+ }
607
+ function resolveParamLocale(input, localeParam) {
608
+ const { pathname, search, availableLocales, defaultLocale } = input;
609
+ const parsed = parseContentPath(pathname, availableLocales, input.collections);
610
+ const named = new URLSearchParams(search ?? "").get(localeParam);
611
+ const param = named ? availableLocales.find((l) => l.toLowerCase() === named.toLowerCase()) : undefined;
612
+ const pathLocale = parsed?.locale && canonicalLocale(parsed.locale, availableLocales);
613
+ const locale = pathLocale || param || defaultLocale;
614
+ return {
615
+ locale,
616
+ routingPathname: parsed?.routingPathname ?? normalizePathname(pathname),
617
+ fromPath: !!pathLocale,
618
+ fromQuery: false,
619
+ urlOnly: true,
620
+ parsed: parsed ? { ...parsed, locale: pathLocale || undefined } : undefined
621
+ };
622
+ }
528
623
  function resolveLocale(input) {
624
+ if (input.prefixPages)
625
+ return resolvePrefixedLocale(input);
626
+ if (input.localeParam)
627
+ return resolveParamLocale(input, input.localeParam);
628
+ return resolveNegotiatedLocale(input);
629
+ }
630
+ function resolveNegotiatedLocale(input) {
529
631
  const {
530
632
  pathname,
531
633
  search,
@@ -1416,7 +1518,9 @@ function matchRoutes(routes, pathname) {
1416
1518
  // packages/core/src/ssr/lib/content-path.ts
1417
1519
  var exports_content_path = {};
1418
1520
  __export(exports_content_path, {
1419
- resolveContentPathParts: () => resolveContentPathParts
1521
+ pagePathname: () => pagePathname,
1522
+ resolveContentPathParts: () => resolveContentPathParts,
1523
+ routingPathname: () => routingPathname
1420
1524
  });
1421
1525
  function resolveContentPathParts(pathname) {
1422
1526
  const pathOnly = pathname.split("?")[0].split("#")[0];
@@ -1454,6 +1558,17 @@ function resolveContentPathParts(pathname) {
1454
1558
  routingPathname: `/${parts.join("/")}`
1455
1559
  };
1456
1560
  }
1561
+ function pagePathname(pathname) {
1562
+ const pathOnly = pathname.split("?")[0].split("#")[0];
1563
+ const i18n = globalThis.__REROUTE_I18N__;
1564
+ if (!i18n?.prefixPages)
1565
+ return pathOnly;
1566
+ return parseLocalePrefix(pathOnly, i18n.locales || [])?.routingPathname ?? pathOnly;
1567
+ }
1568
+ function routingPathname(pathname) {
1569
+ const page = pagePathname(pathname);
1570
+ return resolveContentPathParts(page)?.routingPathname ?? page;
1571
+ }
1457
1572
  var init_content_path = __esm(() => {
1458
1573
  init_pathname();
1459
1574
  });
@@ -1696,7 +1811,7 @@ async function computeLayoutData(pathname, clientDir, _cwd, isWatchMode, options
1696
1811
  try {
1697
1812
  const layouts = routesModule?.layouts;
1698
1813
  const routes = routesModule?.routes;
1699
- const matchingLayouts = getMatchingLayouts(pathname, layouts, routes);
1814
+ const matchingLayouts = getMatchingLayouts(routingPathname(pathname), layouts, routes);
1700
1815
  for (const layout of matchingLayouts) {
1701
1816
  try {
1702
1817
  const layoutStatus = await processLayout(layout, pathname, clientDir, isWatchMode, streaming, maxAgeMs, searchParams, ssrData, pendingTasks, options.headers);
@@ -1725,6 +1840,7 @@ function mergeLayoutData(ssrData, pathname) {
1725
1840
  }
1726
1841
  var init_layouts2 = __esm(() => {
1727
1842
  init_cache();
1843
+ init_content_path();
1728
1844
  init_imports();
1729
1845
  init_layouts();
1730
1846
  });
@@ -1769,9 +1885,7 @@ async function computeRouteData(pathname, clientDir, _cwd, isWatchMode, options,
1769
1885
  }).catch(() => {}));
1770
1886
  };
1771
1887
  try {
1772
- const resolved = resolveContentPathParts(pathname);
1773
- const pathnameOnly = (resolved?.routingPathname || pathname).split("?")[0];
1774
- const match = typeof routesModule?.matchRoute === "function" ? routesModule.matchRoute(pathnameOnly) : null;
1888
+ const match = typeof routesModule?.matchRoute === "function" ? routesModule.matchRoute(routingPathname(pathname)) : null;
1775
1889
  const route = match?.route;
1776
1890
  const params = match?.params || {};
1777
1891
  if (!route || typeof route.path !== "string") {
@@ -2767,9 +2881,8 @@ async function extractPageMetadata(pathname, clientDir, cwd, isWatchMode, curren
2767
2881
  let perPageHead = "";
2768
2882
  let pageLang;
2769
2883
  let statusOverride = currentStatusOverride;
2770
- const resolved = resolveContentPathParts(pathname);
2771
- const routingPathname = resolved?.routingPathname || pathname;
2772
- await extractLayoutMetadata(routingPathname, clientDir, cwd, isWatchMode, (head) => {
2884
+ const routingPathname2 = routingPathname(pathname);
2885
+ await extractLayoutMetadata(routingPathname2, pathname, clientDir, cwd, isWatchMode, (head) => {
2773
2886
  perPageHead += head;
2774
2887
  }, (lang) => {
2775
2888
  if (!pageLang)
@@ -2805,11 +2918,14 @@ ${ogMetaTags}`;
2805
2918
  }, (lang) => {
2806
2919
  pageLang = lang;
2807
2920
  }, ogConfig, titleSuffix, baseUrl);
2808
- const routeResult = await extractRouteMetadata(pathname, clientDir, cwd, isWatchMode, statusOverride, ssrData, ogConfig, titleSuffix, routingPathname);
2921
+ const routeResult = await extractRouteMetadata(pathname, clientDir, cwd, isWatchMode, statusOverride, ssrData, ogConfig, titleSuffix, routingPathname2);
2809
2922
  perPageHead += routeResult.head;
2810
2923
  if (routeResult.lang)
2811
2924
  pageLang = routeResult.lang;
2812
2925
  statusOverride = routeResult.statusOverride;
2926
+ if (baseUrl && !(statusOverride && statusOverride >= 400)) {
2927
+ perPageHead += pageI18nHead(baseUrl, pathname);
2928
+ }
2813
2929
  return {
2814
2930
  perPageHead,
2815
2931
  pageLang,
@@ -2817,7 +2933,7 @@ ${ogMetaTags}`;
2817
2933
  ssrExport: routeResult.ssrExport
2818
2934
  };
2819
2935
  }
2820
- async function processLayoutForMetadata(layout, clientDir, isWatchMode, addHead, setLang, ogConfig, titleSuffix) {
2936
+ async function processLayoutForMetadata(layout, requestPathname, clientDir, isWatchMode, addHead, setLang, ogConfig, titleSuffix) {
2821
2937
  if (typeof layout?.path !== "string")
2822
2938
  return;
2823
2939
  try {
@@ -2826,7 +2942,7 @@ async function processLayoutForMetadata(layout, clientDir, isWatchMode, addHead,
2826
2942
  if (meta)
2827
2943
  addHead(buildHeadFromMeta(meta, ogConfig, titleSuffix));
2828
2944
  if (ssr) {
2829
- const ssrHead = extractSSRHead(ssr, undefined, ogConfig, undefined, meta, titleSuffix);
2945
+ const ssrHead = extractSSRHead(ssr, requestPathname, undefined, ogConfig, undefined, meta, titleSuffix);
2830
2946
  if (ssrHead)
2831
2947
  addHead(`
2832
2948
  ${ssrHead}`);
@@ -2836,15 +2952,36 @@ ${ssrHead}`);
2836
2952
  }
2837
2953
  } catch {}
2838
2954
  }
2839
- async function extractLayoutMetadata(pathname, clientDir, cwd, isWatchMode, addHead, setLang, ogConfig, titleSuffix) {
2955
+ async function extractLayoutMetadata(pathname, requestPathname, clientDir, cwd, isWatchMode, addHead, setLang, ogConfig, titleSuffix) {
2840
2956
  try {
2841
2957
  const m = await loadRoutesModule(cwd, isWatchMode);
2842
2958
  const matchingLayouts = getMatchingLayouts(pathname, m?.layouts, m?.routes);
2843
2959
  for (const layout of matchingLayouts) {
2844
- await processLayoutForMetadata(layout, clientDir, isWatchMode, addHead, setLang, ogConfig, titleSuffix);
2960
+ await processLayoutForMetadata(layout, requestPathname, clientDir, isWatchMode, addHead, setLang, ogConfig, titleSuffix);
2845
2961
  }
2846
2962
  } catch {}
2847
2963
  }
2964
+ function readI18n() {
2965
+ return globalThis.__REROUTE_I18N__;
2966
+ }
2967
+ function isContentUrl(i18n, collection) {
2968
+ return !i18n.prefixPages || !!i18n.collections?.includes(collection);
2969
+ }
2970
+ function pageI18nHead(baseUrl, pathname) {
2971
+ const i18n = readI18n();
2972
+ if (!(i18n?.enabled && i18n.prefixPages && i18n.locales))
2973
+ return "";
2974
+ if (i18n.locales.length < 2)
2975
+ return "";
2976
+ const resolved = resolveContentPathParts(pathname);
2977
+ if (resolved && isContentUrl(i18n, resolved.collection))
2978
+ return "";
2979
+ const page = pagePathname(pathname);
2980
+ if (isUnprefixedPath(page, i18n.unprefixedPaths))
2981
+ return "";
2982
+ return `
2983
+ ${pageHreflangTags(baseUrl, page, i18n.locales, i18n.defaultLocale || "en-US")}`;
2984
+ }
2848
2985
  function resolveContentLocales(collection, name, fallbackLocales) {
2849
2986
  const g = globalThis;
2850
2987
  const byCollection = g.__REROUTE_COLLECTIONS__;
@@ -2884,15 +3021,15 @@ function extractContentMetadata(pathname, addHead, setLang, ogConfig, titleSuffi
2884
3021
  const meta = exp?.meta;
2885
3022
  const ssr = exp?.ssr;
2886
3023
  addHead(buildHeadFromMeta(meta, ogConfig, titleSuffix));
2887
- const ssrHead = extractSSRHead(ssr, undefined, ogConfig, undefined, meta, titleSuffix);
3024
+ const ssrHead = extractSSRHead(ssr, pathname, undefined, ogConfig, undefined, meta, titleSuffix);
2888
3025
  if (ssrHead)
2889
3026
  addHead(`
2890
3027
  ${ssrHead}`);
2891
3028
  const lang = extractSSRLang(ssr);
2892
3029
  if (lang)
2893
3030
  setLang(lang);
2894
- const i18n = g.__REROUTE_I18N__;
2895
- if (i18n?.enabled && baseUrl && i18n.locales && i18n.locales.length > 1) {
3031
+ const i18n = readI18n();
3032
+ if (i18n?.enabled && baseUrl && i18n.locales && i18n.locales.length > 1 && isContentUrl(i18n, resolved.collection)) {
2896
3033
  const locales = resolveContentLocales(resolved.collection, resolved.name, i18n.locales);
2897
3034
  addContentI18nHead(addHead, baseUrl, resolved.collection, resolved.name, locales, i18n.defaultLocale || "en-US", i18n.locale || i18n.defaultLocale || "en-US");
2898
3035
  }
@@ -2918,9 +3055,9 @@ function getContentMetaFromExports(pathname) {
2918
3055
  return;
2919
3056
  }
2920
3057
  }
2921
- async function extractMatchedRouteMetadata(pathname, clientDir, m, isWatchMode, statusOverride, ssrData, ogConfig, titleSuffix, routingPathname) {
3058
+ async function extractMatchedRouteMetadata(pathname, clientDir, m, isWatchMode, statusOverride, ssrData, ogConfig, titleSuffix, routingPathname2) {
2922
3059
  const pathnameOnly = pathname.split("?")[0];
2923
- const matchPath = (routingPathname || pathname).split("?")[0];
3060
+ const matchPath = (routingPathname2 || pathname).split("?")[0];
2924
3061
  const match = typeof m.matchRoute === "function" ? m.matchRoute(matchPath) : null;
2925
3062
  const r = match?.route;
2926
3063
  if (!r) {
@@ -2945,7 +3082,7 @@ async function extractMatchedRouteMetadata(pathname, clientDir, m, isWatchMode,
2945
3082
  }
2946
3083
  const contentMeta = getContentMetaFromExports(pathnameOnly);
2947
3084
  const headMeta = contentMeta || meta;
2948
- const ssrHead = extractSSRHead(ssr, routeData, ogConfig, head, headMeta, titleSuffix);
3085
+ const ssrHead = extractSSRHead(ssr, pathname, routeData, ogConfig, head, headMeta, titleSuffix);
2949
3086
  if (ssrHead)
2950
3087
  head += `
2951
3088
  ${ssrHead}`;
@@ -2961,7 +3098,7 @@ ${ssrHead}`;
2961
3098
  }
2962
3099
  return { head: "", statusOverride };
2963
3100
  }
2964
- async function extractRouteMetadata(pathname, clientDir, cwd, isWatchMode, currentStatusOverride, ssrData, ogConfig, titleSuffix, routingPathname) {
3101
+ async function extractRouteMetadata(pathname, clientDir, cwd, isWatchMode, currentStatusOverride, ssrData, ogConfig, titleSuffix, routingPathname2) {
2965
3102
  let head = "";
2966
3103
  let lang;
2967
3104
  let statusOverride = currentStatusOverride;
@@ -2971,14 +3108,14 @@ async function extractRouteMetadata(pathname, clientDir, cwd, isWatchMode, curre
2971
3108
  if (!m) {
2972
3109
  return { head, lang, statusOverride: statusOverride || 404 };
2973
3110
  }
2974
- const matchPath = (routingPathname || pathname).split("?")[0];
3111
+ const matchPath = (routingPathname2 || pathname).split("?")[0];
2975
3112
  const match = typeof m.matchRoute === "function" ? m.matchRoute(matchPath) : null;
2976
3113
  const r = match?.route;
2977
3114
  if (!r) {
2978
3115
  statusOverride = statusOverride || 404;
2979
3116
  }
2980
3117
  if (r && typeof r.path === "string") {
2981
- const result = await extractMatchedRouteMetadata(pathname, clientDir, m, isWatchMode, statusOverride, ssrData, ogConfig, titleSuffix, routingPathname);
3118
+ const result = await extractMatchedRouteMetadata(pathname, clientDir, m, isWatchMode, statusOverride, ssrData, ogConfig, titleSuffix, routingPathname2);
2982
3119
  head = result.head;
2983
3120
  lang = result.lang;
2984
3121
  statusOverride = result.statusOverride;
@@ -3018,7 +3155,7 @@ async function extractNotFoundMetadata(pathname, clientDir, routesModule, isWatc
3018
3155
  const { meta, ssr } = await loadModuleMetaAndSSR(chosen, abs, isWatchMode);
3019
3156
  if (meta)
3020
3157
  head += buildHeadFromMeta(meta, ogConfig, titleSuffix);
3021
- const ssrHead = extractSSRHead(ssr, undefined, ogConfig, undefined, meta, titleSuffix);
3158
+ const ssrHead = extractSSRHead(ssr, pathname, undefined, ogConfig, undefined, meta, titleSuffix);
3022
3159
  if (ssrHead)
3023
3160
  head += `
3024
3161
  ${ssrHead}`;
@@ -3081,13 +3218,17 @@ function generateMissingOGTags(head, ogConfig) {
3081
3218
  ${additionalTags.join(`
3082
3219
  `)}` : "";
3083
3220
  }
3084
- function extractSSRHead(ssr, data, ogConfig, existingHead, meta, titleSuffix) {
3221
+ function extractSSRHead(ssr, pathname, data, ogConfig, existingHead, meta, titleSuffix) {
3085
3222
  if (!ssr)
3086
3223
  return "";
3087
3224
  let headContent = "";
3088
3225
  if (typeof ssr.head === "function") {
3089
3226
  try {
3090
- const result = ssr.head({ data, meta });
3227
+ const result = ssr.head({
3228
+ pathname,
3229
+ data,
3230
+ meta
3231
+ });
3091
3232
  if (typeof result === "string")
3092
3233
  headContent = result;
3093
3234
  else if (Array.isArray(result))
@@ -6219,18 +6360,43 @@ function createStaticEntry(route, baseUrl, defaultChangefreq, defaultPriority) {
6219
6360
  priority: route.priority !== undefined ? route.priority : loc === "/" ? 1 : defaultPriority
6220
6361
  };
6221
6362
  }
6222
- function collectAllEntries(discovery4, baseUrl, changefreq, priority, excludeRoutes) {
6363
+ function localizePageEntry(entry, baseUrl, i18n) {
6364
+ const base = baseUrl.replace(/\/$/, "");
6365
+ if (!(i18n && entry.loc.startsWith(base)))
6366
+ return [entry];
6367
+ const path2 = entry.loc.slice(base.length) || "/";
6368
+ if (parseContentPath(path2, i18n.locales, i18n.collections))
6369
+ return [entry];
6370
+ if (isUnprefixedPath(path2, i18n.unprefixedPaths))
6371
+ return [entry];
6372
+ const { locales, defaultLocale } = i18n;
6373
+ const urlFor = (locale) => `${base}${localizePagePath(path2, locale, defaultLocale)}`;
6374
+ const alternates = [
6375
+ ...locales.map((locale) => ({ hreflang: locale, href: urlFor(locale) })),
6376
+ { hreflang: "x-default", href: urlFor(defaultLocale) }
6377
+ ];
6378
+ return locales.map((locale) => ({
6379
+ ...entry,
6380
+ loc: urlFor(locale),
6381
+ alternates
6382
+ }));
6383
+ }
6384
+ function collectAllEntries(discovery4, baseUrl, changefreq, priority, excludeRoutes, i18n) {
6223
6385
  const allEntries = [];
6386
+ const addPage = (entry) => {
6387
+ allEntries.push(...localizePageEntry(entry, baseUrl, i18n));
6388
+ };
6224
6389
  for (const route of discovery4.staticRoutes) {
6225
6390
  if (shouldIncludeRoute(route.pattern, excludeRoutes)) {
6226
- allEntries.push(createStaticEntry(route, baseUrl, changefreq, priority));
6391
+ addPage(createStaticEntry(route, baseUrl, changefreq, priority));
6227
6392
  }
6228
6393
  }
6229
6394
  for (const [_collection, entries] of discovery4.collections.entries()) {
6230
6395
  allEntries.push(...entries);
6231
6396
  }
6232
6397
  for (const [_pattern, entries] of discovery4.ssrDataRoutes.entries()) {
6233
- allEntries.push(...entries);
6398
+ for (const entry of entries)
6399
+ addPage(entry);
6234
6400
  }
6235
6401
  return allEntries;
6236
6402
  }
@@ -6276,7 +6442,7 @@ async function generateSitemap(discovery4, baseUrl, options = {}) {
6276
6442
  priority = 0.5,
6277
6443
  maxUrlsPerPage = DEFAULT_MAX_URLS
6278
6444
  } = options;
6279
- const allEntries = collectAllEntries(discovery4, baseUrl, changefreq, priority, options.excludeRoutes);
6445
+ const allEntries = collectAllEntries(discovery4, baseUrl, changefreq, priority, options.excludeRoutes, options.i18n);
6280
6446
  sortEntries(allEntries);
6281
6447
  const needsIndex = allEntries.length > maxUrlsPerPage;
6282
6448
  if (needsIndex) {
@@ -6336,7 +6502,9 @@ function escapeXml2(unsafe) {
6336
6502
  return unsafe.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&apos;");
6337
6503
  }
6338
6504
  var DEFAULT_MAX_URLS = 50000;
6339
- var init_generator2 = () => {};
6505
+ var init_generator2 = __esm(() => {
6506
+ init_pathname();
6507
+ });
6340
6508
 
6341
6509
  // packages/core/src/sitemap/index.ts
6342
6510
  var init_sitemap = __esm(() => {
@@ -6606,7 +6774,10 @@ function generateMetaUpdateScript(ctx, ssrDataSnapshot) {
6606
6774
  }
6607
6775
  let headResult;
6608
6776
  try {
6609
- headResult = ctx.ssrExport.head({ data: routeData });
6777
+ headResult = ctx.ssrExport.head({
6778
+ pathname: ctx.pathname,
6779
+ data: routeData
6780
+ });
6610
6781
  } catch (err) {
6611
6782
  console.error("[reroute] Error calling ssr.head() at stream end:", err);
6612
6783
  return "";
@@ -6830,6 +7001,7 @@ export {
6830
7001
  inlineThemeCSS,
6831
7002
  isCompressible,
6832
7003
  isThenable,
7004
+ isUnprefixedPath,
6833
7005
  join,
6834
7006
  layoutCovers,
6835
7007
  layoutWraps,
@@ -6842,6 +7014,7 @@ export {
6842
7014
  loadRoutesModule,
6843
7015
  localizeContentHref,
6844
7016
  localizeHref,
7017
+ localizePagePath,
6845
7018
  looksLikeLocale,
6846
7019
  lookupMessage,
6847
7020
  markPageHead,
@@ -6852,8 +7025,10 @@ export {
6852
7025
  mergeVary,
6853
7026
  negotiateLocale,
6854
7027
  normalizePathname,
7028
+ pageHreflangTags,
6855
7029
  parseContentPath,
6856
7030
  parseCookieValue,
7031
+ parseLocalePrefix,
6857
7032
  performSSRSetup,
6858
7033
  preloadContentModule,
6859
7034
  processCollections,
@@ -6885,4 +7060,4 @@ export {
6885
7060
  toPromise
6886
7061
  };
6887
7062
 
6888
- //# debugId=D26568AD3E41E3C164756E2164756E21
7063
+ //# debugId=A17B01FC76A0FE5664756E2164756E21