boltdocs 3.2.2 → 3.3.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 (156) hide show
  1. package/bin/boltdocs.js +20 -1
  2. package/bin/preloader.mjs +28 -0
  3. package/dist/{adapters-ByYY44Zy.mjs → adapters-BmB4TKCc.mjs} +1 -1
  4. package/dist/{adapters-DvmtpdSF.cjs → adapters-Cp1Maurn.cjs} +1 -1
  5. package/dist/audit-CLXjMzwQ.mjs +11 -0
  6. package/dist/audit-COgjnQ5n.cjs +11 -0
  7. package/dist/build-D6FfNA8m.cjs +6 -0
  8. package/dist/build-D_7SvwTh.mjs +6 -0
  9. package/dist/cache-CJE9nWLE.cjs +6 -0
  10. package/dist/cache-OY4HzIXl.mjs +6 -0
  11. package/dist/callout-oI_LCbxS.d.ts +71 -0
  12. package/dist/callout-plqx9Dw-.d.cts +71 -0
  13. package/dist/client/index.cjs +1265 -569
  14. package/dist/client/index.d.cts +3 -542
  15. package/dist/client/index.d.ts +3 -542
  16. package/dist/client/index.js +1167 -521
  17. package/dist/client/mdx.cjs +1 -1
  18. package/dist/client/mdx.d.cts +24 -2
  19. package/dist/client/mdx.d.ts +24 -2
  20. package/dist/client/mdx.js +1 -1
  21. package/dist/client/primitives.cjs +14 -4
  22. package/dist/client/primitives.d.cts +281 -38
  23. package/dist/client/primitives.d.ts +281 -38
  24. package/dist/client/primitives.js +5 -5
  25. package/dist/client/router.cjs +49 -0
  26. package/dist/client/router.d.cts +3 -0
  27. package/dist/client/router.d.ts +3 -0
  28. package/dist/client/router.js +8 -0
  29. package/dist/client/theme/reset.css +40 -4
  30. package/dist/{config-BpzaPsJj.d.cts → config-BoRlz0Ca.d.mts} +157 -14
  31. package/dist/{config-xtS0ZkMm.d.mts → config-CTsX_tGM.d.cts} +157 -14
  32. package/dist/config-Ceib-AOH.cjs +7 -0
  33. package/dist/config-DGLQsy7y.mjs +7 -0
  34. package/dist/{package-CH2ChQqw.cjs → config-files-BYHDOrKn.mjs} +1 -1
  35. package/dist/config-files-D9cdBMl2.cjs +6 -0
  36. package/dist/config-jJh8WYJI.cjs +6 -0
  37. package/dist/csp-C4LmN1ko.cjs +6 -0
  38. package/dist/csp-D6JEOqKh.mjs +6 -0
  39. package/dist/dev-B9l7fVoQ.cjs +6 -0
  40. package/dist/dev-CwOyh-wP.mjs +6 -0
  41. package/dist/{docs-layout-BdtZ9z6s.js → docs-layout-CbZ7LDRe.js} +504 -249
  42. package/dist/{docs-layout-CFWI15Id.cjs → docs-layout-vzfXed1Q.cjs} +516 -254
  43. package/dist/{doctor-BBtmNJE0.cjs → doctor-B1_YL0Wt.cjs} +1 -1
  44. package/dist/doctor-C7whl4ED.cjs +6 -0
  45. package/dist/doctor-DmQnml2k.mjs +6 -0
  46. package/dist/{generator-COepVWGi.cjs → generator-BlW45ST7.cjs} +5 -3
  47. package/dist/{generator-CcOBN5vI.mjs → generator-BwknNejd.mjs} +5 -3
  48. package/dist/{handler-XX7cLTqe.cjs → handler-CDEoKARD.cjs} +2 -2
  49. package/dist/{handler-DzQae4eA.mjs → handler-D7UyZlPm.mjs} +2 -2
  50. package/dist/{image-Bz87fCla.js → image-B-NDSDuY.js} +129 -11
  51. package/dist/{image-C4TlpMHn.cjs → image-Hnaa2bJd.cjs} +175 -9
  52. package/dist/index-C56bL-A-.d.cts +1344 -0
  53. package/dist/{sidebar-COTaMHR-.d.ts → index-CPUUKzxD.d.cts} +344 -327
  54. package/dist/{sidebar-CrEdJuHX.d.cts → index-Ci4kfOHF.d.ts} +344 -327
  55. package/dist/index-Cu9H6CRa.d.ts +1344 -0
  56. package/dist/link-CgdI6O2o.js +872 -0
  57. package/dist/{link-D1Gjkb-2.cjs → link-vZjmD-es.cjs} +406 -223
  58. package/dist/{mdx-BuO6a1f7.js → mdx-BRT71V5Q.js} +211 -168
  59. package/dist/{mdx-CD-tSjRG.cjs → mdx-D0Absdq5.cjs} +225 -169
  60. package/dist/native-BNCY7PRF.cjs +6 -0
  61. package/dist/native-Di9Fnfrv.mjs +6 -0
  62. package/dist/native-Kre2T5eS.cjs +6 -0
  63. package/dist/node/cache.cjs +1 -1
  64. package/dist/node/cache.d.cts +19 -3
  65. package/dist/node/cache.d.mts +19 -3
  66. package/dist/node/cache.mjs +1 -1
  67. package/dist/node/cli-entry.cjs +1 -9
  68. package/dist/node/cli-entry.mjs +1 -9
  69. package/dist/node/index.cjs +1 -1
  70. package/dist/node/index.d.cts +245 -17
  71. package/dist/node/index.d.mts +246 -18
  72. package/dist/node/index.mjs +1 -1
  73. package/dist/node/mdx/shiki-adapter.cjs +1 -1
  74. package/dist/node/mdx/shiki-adapter.d.cts +24 -3
  75. package/dist/node/mdx/shiki-adapter.d.mts +24 -2
  76. package/dist/node/mdx/shiki-adapter.mjs +1 -1
  77. package/dist/node-BFNCsPs3.mjs +23 -0
  78. package/dist/node-TpmWEqXM.cjs +23 -0
  79. package/dist/{package-DSSB8B5L.mjs → package-5EsGUTVl.mjs} +1 -1
  80. package/dist/package-Ca2WSiy2.cjs +6 -0
  81. package/dist/pages-external-BBw8ObVK.mjs +6 -0
  82. package/dist/pages-external-DPiPFxxP.cjs +6 -0
  83. package/dist/parser-BqTOsEUa.cjs +6 -0
  84. package/dist/parser-CGMY2lJ7.mjs +6 -0
  85. package/dist/plugin-CUmUZOLD.mjs +69 -0
  86. package/dist/plugin-Ds3RLYpy.cjs +69 -0
  87. package/dist/plugin-context-C-l90hFt.cjs +15 -0
  88. package/dist/plugin-context-wqHNSZum.mjs +15 -0
  89. package/dist/plugin-lifecycle-BAKNKOxd.cjs +6 -0
  90. package/dist/resolve-B7vWOd8R.cjs +6 -0
  91. package/dist/resolve-C2kKnk_5.mjs +6 -0
  92. package/dist/resolve-It1Iug83.cjs +6 -0
  93. package/dist/resolve-YdTrt_FG.mjs +6 -0
  94. package/dist/router-C3kygdRK.cjs +1285 -0
  95. package/dist/router-CZBxMRAH.js +987 -0
  96. package/dist/routes-BL4y79tb.mjs +6 -0
  97. package/dist/routes-C2nPecwu.cjs +6 -0
  98. package/dist/routes-U9L8psZ9.cjs +6 -0
  99. package/dist/{search-dialog-DFnlx8LO.js → search-dialog-BqkzDTq2.js} +107 -57
  100. package/dist/search-dialog-D3jtaw6w.cjs +525 -0
  101. package/dist/search-dialog-DRiXejws.js +501 -0
  102. package/dist/{search-dialog-DHqwjJuG.cjs → search-dialog-DmirOMPg.cjs} +1 -1
  103. package/dist/{search-dialog-D6TvjcuV.js → search-dialog-MmwxFMmE.js} +1 -1
  104. package/dist/{search-dialog-B1NERUNx.cjs → search-dialog-x_qHU8ty.cjs} +107 -58
  105. package/dist/server/index.cjs +1 -1
  106. package/dist/server/index.d.mts +1 -1
  107. package/dist/server/index.mjs +1 -1
  108. package/dist/update-check-BKqmYfwT.cjs +11 -0
  109. package/dist/update-check-QnrVR3q1.mjs +11 -0
  110. package/dist/utils-8lzafE49.mjs +7 -0
  111. package/dist/utils-ej6_SjIZ.cjs +7 -0
  112. package/dist/virtual-modules-Ca5tHk1X.cjs +30 -0
  113. package/dist/virtual-modules-Dlgt1fP0.mjs +30 -0
  114. package/package.json +18 -16
  115. package/src/shared/mdx-path.ts +12 -0
  116. package/src/shared/structured-data.ts +145 -0
  117. package/src/shared/types.ts +220 -16
  118. package/dist/banner-BMop1KLF.d.ts +0 -100
  119. package/dist/banner-CVD0GugR.d.cts +0 -100
  120. package/dist/cache-CO4Dy2uQ.cjs +0 -6
  121. package/dist/cache-Dk53iOo6.mjs +0 -6
  122. package/dist/config-CCXp3aXO.mjs +0 -7
  123. package/dist/config-CMd4XoFq.cjs +0 -6
  124. package/dist/config-DlGoEM9D.cjs +0 -7
  125. package/dist/csp-CRp_3U7a.cjs +0 -6
  126. package/dist/csp-oTC2ygvF.mjs +0 -6
  127. package/dist/doctor-Bv16QSrI.cjs +0 -7
  128. package/dist/doctor-DOAbSaiL.mjs +0 -7
  129. package/dist/headers-Ddwek8K7.mjs +0 -6
  130. package/dist/headers-dg4SDrjY.cjs +0 -6
  131. package/dist/link-2PzgTnaP.js +0 -673
  132. package/dist/meta-loader-C4Hu9RN9.mjs +0 -6
  133. package/dist/meta-loader-Dq1zcFnh.cjs +0 -6
  134. package/dist/node-B5hu_6qj.cjs +0 -104
  135. package/dist/node-BXtqM1uH.mjs +0 -6
  136. package/dist/node-C8725aw7.mjs +0 -104
  137. package/dist/node-aD1eisrR.cjs +0 -6
  138. package/dist/pages-external-BYa4JSda.mjs +0 -6
  139. package/dist/pages-external-XkYIs-d5.cjs +0 -6
  140. package/dist/parser-DCiEWkSk.cjs +0 -8
  141. package/dist/parser-qk9FIHJ7.mjs +0 -8
  142. package/dist/plugin-CX1OZ6jB.cjs +0 -73
  143. package/dist/plugin-CgfiWaFZ.mjs +0 -73
  144. package/dist/routes-BW6zsk7Z.mjs +0 -6
  145. package/dist/routes-BgoIB5wb.cjs +0 -6
  146. package/dist/routes-CORVxc02.cjs +0 -6
  147. package/dist/search-dialog-BRFno7HD.cjs +0 -330
  148. package/dist/search-dialog-BmxHiKwt.js +0 -312
  149. package/dist/shiki-adapter-CoQ6jyJ4.cjs +0 -6
  150. package/dist/shiki-adapter-D-aKw7PP.mjs +0 -6
  151. package/dist/utils-Crm9oPcV.mjs +0 -7
  152. package/dist/utils-D6Xtj0FZ.cjs +0 -7
  153. /package/dist/{errors-0zGHRLue.mjs → errors-N-b6Sn2G.mjs} +0 -0
  154. /package/dist/{index-1KsTDq4o.d.mts → index-lFoyzCXy.d.mts} +0 -0
  155. /package/dist/{types-generator-BXhv7Ill.cjs → types-generator-DDSA93P3.cjs} +0 -0
  156. /package/dist/{types-generator-bDPvUztF.mjs → types-generator-DG1GX1EZ.mjs} +0 -0
@@ -0,0 +1,1285 @@
1
+ /**
2
+ * Boltdocs - https://boltdocs.vercel.app
3
+ * Copyright (c) 2026 Jesus Alcala
4
+ * Licensed under the MIT License.
5
+ */
6
+ //#region \0rolldown/runtime.js
7
+ var __create = Object.create;
8
+ var __defProp = Object.defineProperty;
9
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
10
+ var __getOwnPropNames = Object.getOwnPropertyNames;
11
+ var __getProtoOf = Object.getPrototypeOf;
12
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
13
+ var __exportAll = (all, no_symbols) => {
14
+ let target = {};
15
+ for (var name in all) {
16
+ __defProp(target, name, {
17
+ get: all[name],
18
+ enumerable: true
19
+ });
20
+ }
21
+ if (!no_symbols) {
22
+ __defProp(target, Symbol.toStringTag, { value: "Module" });
23
+ }
24
+ return target;
25
+ };
26
+ var __copyProps = (to, from, except, desc) => {
27
+ if (from && typeof from === "object" || typeof from === "function") {
28
+ for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
29
+ key = keys[i];
30
+ if (!__hasOwnProp.call(to, key) && key !== except) {
31
+ __defProp(to, key, {
32
+ get: ((k) => from[k]).bind(null, key),
33
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
34
+ });
35
+ }
36
+ }
37
+ }
38
+ return to;
39
+ };
40
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
41
+ value: mod,
42
+ enumerable: true
43
+ }) : target, mod));
44
+
45
+ //#endregion
46
+ let react = require("react");
47
+ react = __toESM(react);
48
+ let react_jsx_runtime = require("react/jsx-runtime");
49
+
50
+ //#region src/client/router/utils.ts
51
+ function normalizeBasename(basename) {
52
+ if (!basename || basename === "/") return "/";
53
+ return basename.replace(/\/$/, "") || "/";
54
+ }
55
+ function hasBasename(path, basename) {
56
+ const normalized = normalizeBasename(basename);
57
+ if (normalized === "/") return true;
58
+ if (path === normalized) return true;
59
+ return path.startsWith(`${normalized}/`);
60
+ }
61
+ function stripBasename(path, basename) {
62
+ const normalized = normalizeBasename(basename);
63
+ if (normalized === "/") return path;
64
+ if (!hasBasename(path, normalized)) return path;
65
+ const stripped = path.slice(normalized.length);
66
+ return stripped.startsWith("/") ? stripped : `/${stripped}`;
67
+ }
68
+ function addBasename(path, basename) {
69
+ const normalized = normalizeBasename(basename);
70
+ if (normalized === "/") return path;
71
+ if (hasBasename(path, normalized)) return path;
72
+ if (path.startsWith("/")) return `${normalized}${path}`;
73
+ return `${normalized}/${path}`;
74
+ }
75
+
76
+ //#endregion
77
+ //#region src/client/router/context.tsx
78
+ function getActiveLocale() {
79
+ if (typeof globalThis === "undefined") return void 0;
80
+ const instance = globalThis[Symbol.for("__BDOCS_BOLTDOCS_INSTANCE__")];
81
+ if (instance && typeof instance === "object" && "currentLocale" in instance && typeof instance.currentLocale === "string") return instance.currentLocale;
82
+ if (typeof window === "undefined") return void 0;
83
+ try {
84
+ const raw = window.localStorage.getItem("boltdocs-user-preferences");
85
+ if (!raw) return void 0;
86
+ const preferences = JSON.parse(raw);
87
+ return typeof preferences.locale === "string" ? preferences.locale : void 0;
88
+ } catch {
89
+ return;
90
+ }
91
+ }
92
+ const defaultNavigate = () => {};
93
+ const defaultLocation = {
94
+ pathname: "/",
95
+ search: "",
96
+ hash: ""
97
+ };
98
+ const g$1 = typeof globalThis !== "undefined" ? globalThis : {};
99
+ function getGlobalContext(key, create) {
100
+ const existing = g$1[key];
101
+ if (existing) return existing;
102
+ const context = create();
103
+ g$1[key] = context;
104
+ return context;
105
+ }
106
+ const LocationContext = getGlobalContext("__BOLTDOCS_LOCATION_CONTEXT__", () => (0, react.createContext)(defaultLocation));
107
+ const NavigateContext = getGlobalContext("__BOLTDOCS_NAVIGATE_CONTEXT__", () => (0, react.createContext)(defaultNavigate));
108
+ const PrefetchContext = getGlobalContext("__BOLTDOCS_PREFETCH_CONTEXT__", () => (0, react.createContext)(async () => {}));
109
+ const RouteDataContext = getGlobalContext("__BOLTDOCS_ROUTE_DATA_CONTEXT__", () => (0, react.createContext)(null));
110
+ const MatchesContext = getGlobalContext("__BOLTDOCS_MATCHES_CONTEXT__", () => (0, react.createContext)([]));
111
+ function normalizeComparablePath(pathname) {
112
+ if (pathname.length <= 1) return pathname || "/";
113
+ return pathname.replace(/\/$/, "") || "/";
114
+ }
115
+ function dispatchNavigationStart(location) {
116
+ if (typeof window === "undefined") return;
117
+ window.dispatchEvent(new CustomEvent("boltdocs:navigation-start", { detail: location }));
118
+ }
119
+ function scheduleLocationUpdate(setLocation, nextLocation, viewTransitions) {
120
+ setTimeout(() => {
121
+ const enabled = typeof viewTransitions === "boolean" ? viewTransitions : viewTransitions?.enabled === true;
122
+ const startViewTransition = document.startViewTransition;
123
+ if (enabled && startViewTransition) {
124
+ const types = typeof viewTransitions === "object" ? viewTransitions.types : void 0;
125
+ startViewTransition.call(document, {
126
+ update: () => setLocation(nextLocation),
127
+ ...types?.length ? { types } : {}
128
+ });
129
+ return;
130
+ }
131
+ setLocation(nextLocation);
132
+ }, 0);
133
+ }
134
+ function getLocationFromWindow() {
135
+ if (typeof window === "undefined") return defaultLocation;
136
+ return {
137
+ pathname: window.location.pathname || "/",
138
+ search: window.location.search || "",
139
+ hash: window.location.hash || ""
140
+ };
141
+ }
142
+ const LocationProvider = ({ pathname: propPathname, children, loaderData = null, matches = [], basename, defaultLocale, prefetch: prefetchProp, viewTransitions }) => {
143
+ const [location, setLocation] = (0, react.useState)(() => {
144
+ if (typeof window !== "undefined") return getLocationFromWindow();
145
+ return propPathname ? {
146
+ pathname: propPathname,
147
+ search: "",
148
+ hash: ""
149
+ } : defaultLocation;
150
+ });
151
+ (0, react.useEffect)(() => {
152
+ if (typeof window === "undefined") return;
153
+ const handlePopState = () => {
154
+ const nextLocation = getLocationFromWindow();
155
+ scheduleLocationUpdate(setLocation, nextLocation, viewTransitions);
156
+ dispatchNavigationStart(nextLocation);
157
+ };
158
+ window.addEventListener("popstate", handlePopState);
159
+ return () => window.removeEventListener("popstate", handlePopState);
160
+ }, [viewTransitions]);
161
+ const prefetched = (0, react.useRef)(/* @__PURE__ */ new Set());
162
+ const fallbackPrefetch = (0, react.useCallback)(async (to) => {
163
+ if (typeof window === "undefined" || !to || prefetched.current.has(to)) return;
164
+ prefetched.current.add(to);
165
+ }, []);
166
+ const prefetch = prefetchProp ?? fallbackPrefetch;
167
+ const navigate = (0, react.useCallback)((to, options) => {
168
+ if (typeof window === "undefined") return;
169
+ if (!to) return;
170
+ const normalizedBasename = normalizeBasename(basename);
171
+ if (/^https?:\/\//i.test(to) || to.startsWith("//")) {
172
+ window.location.href = to;
173
+ return;
174
+ }
175
+ if (to.startsWith("#")) {
176
+ const newUrl = new URL(to, window.location.href);
177
+ const nextLocation = {
178
+ pathname: window.location.pathname,
179
+ search: window.location.search,
180
+ hash: newUrl.hash
181
+ };
182
+ if (nextLocation.pathname === window.location.pathname && nextLocation.search === window.location.search && nextLocation.hash === window.location.hash) {
183
+ if (options?.state !== void 0) if (options.replace) window.history.replaceState(options.state, "", newUrl.href);
184
+ else window.history.pushState(options.state, "", newUrl.href);
185
+ return;
186
+ }
187
+ if (options?.replace) window.history.replaceState(options.state ?? null, "", newUrl.href);
188
+ else window.history.pushState(options?.state ?? null, "", newUrl.href);
189
+ scheduleLocationUpdate(setLocation, nextLocation, options?.viewTransition === false ? false : viewTransitions);
190
+ dispatchNavigationStart(nextLocation);
191
+ return;
192
+ }
193
+ const resolvedUrl = new URL(to, window.location.href);
194
+ if (resolvedUrl.origin !== window.location.origin) {
195
+ window.location.href = to;
196
+ return;
197
+ }
198
+ let finalPath = resolvedUrl.pathname + resolvedUrl.search + resolvedUrl.hash;
199
+ if (normalizedBasename !== "/" && !hasBasename(resolvedUrl.pathname, normalizedBasename)) {
200
+ const activeLocale = getActiveLocale();
201
+ if (activeLocale && defaultLocale && activeLocale !== defaultLocale && !finalPath.startsWith(`/${activeLocale}/`) && finalPath !== `/${activeLocale}`) finalPath = `/${activeLocale}${finalPath === "/" ? "" : finalPath}`;
202
+ } else if (normalizedBasename !== "/") finalPath = addBasename(finalPath, normalizedBasename);
203
+ const finalUrl = new URL(finalPath, window.location.href);
204
+ if (normalizeComparablePath(finalUrl.pathname) === normalizeComparablePath(window.location.pathname) && finalUrl.search === window.location.search && finalUrl.hash === window.location.hash) {
205
+ if (options?.state !== void 0) if (options.replace) window.history.replaceState(options.state, "", finalPath);
206
+ else window.history.pushState(options.state, "", finalPath);
207
+ return;
208
+ }
209
+ if (options?.replace) window.history.replaceState(options?.state ?? null, "", finalPath);
210
+ else window.history.pushState(options?.state ?? null, "", finalPath);
211
+ const nextLocation = {
212
+ pathname: finalUrl.pathname,
213
+ search: finalUrl.search,
214
+ hash: finalUrl.hash
215
+ };
216
+ scheduleLocationUpdate(setLocation, nextLocation, options?.viewTransition === false ? false : viewTransitions);
217
+ dispatchNavigationStart(nextLocation);
218
+ }, [
219
+ basename,
220
+ defaultLocale,
221
+ viewTransitions
222
+ ]);
223
+ (0, react.useEffect)(() => {
224
+ if (typeof window === "undefined") return;
225
+ const normalizedBasename = normalizeBasename(basename);
226
+ const handleClick = (e) => {
227
+ if (e.defaultPrevented || e.button !== 0 || e.metaKey || e.altKey || e.ctrlKey || e.shiftKey) return;
228
+ let target = e.target;
229
+ while (target && target.nodeName !== "A") target = target.parentElement;
230
+ if (!target || target.nodeName !== "A") return;
231
+ const anchor = target;
232
+ const href = anchor.getAttribute("href");
233
+ if (!href || anchor.target === "_blank" || anchor.hasAttribute("download") || href.startsWith("#")) return;
234
+ if (/^https?:\/\//i.test(href) || href.startsWith("//")) return;
235
+ let resolvedPathname;
236
+ try {
237
+ const resolved = new URL(href, document.baseURI || window.location.href);
238
+ if (resolved.origin !== window.location.origin) return;
239
+ resolvedPathname = resolved.pathname;
240
+ } catch {
241
+ return;
242
+ }
243
+ const isUnderBasename = normalizedBasename === "/" || hasBasename(resolvedPathname, normalizedBasename);
244
+ const currentIsUnderBasename = normalizedBasename === "/" || hasBasename(window.location.pathname, normalizedBasename);
245
+ if (!isUnderBasename && currentIsUnderBasename) return;
246
+ e.preventDefault();
247
+ navigate(href);
248
+ };
249
+ document.addEventListener("click", handleClick);
250
+ return () => document.removeEventListener("click", handleClick);
251
+ }, [navigate, basename]);
252
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(LocationContext.Provider, {
253
+ value: location,
254
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(NavigateContext.Provider, {
255
+ value: navigate,
256
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PrefetchContext.Provider, {
257
+ value: prefetch,
258
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RouteDataContext.Provider, {
259
+ value: loaderData,
260
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MatchesContext.Provider, {
261
+ value: matches,
262
+ children
263
+ })
264
+ })
265
+ })
266
+ })
267
+ });
268
+ };
269
+
270
+ //#endregion
271
+ //#region src/client/router/hooks.ts
272
+ function useLocation() {
273
+ return (0, react.use)(LocationContext);
274
+ }
275
+ function useNavigate() {
276
+ return (0, react.use)(NavigateContext);
277
+ }
278
+ function usePrefetch() {
279
+ return (0, react.use)(PrefetchContext);
280
+ }
281
+ function useRouteData() {
282
+ return (0, react.use)(RouteDataContext);
283
+ }
284
+ /** Alias for useRouteData — parity with react-router-dom's useLoaderData */
285
+ function useLoaderData() {
286
+ return (0, react.use)(RouteDataContext);
287
+ }
288
+ function useMatches() {
289
+ return (0, react.use)(MatchesContext);
290
+ }
291
+
292
+ //#endregion
293
+ //#region src/client/router/outlet.tsx
294
+ const g = typeof globalThis !== "undefined" ? globalThis : {};
295
+ const existingOutletContext = g.__BOLTDOCS_OUTLET_CONTEXT__;
296
+ const OutletContext = existingOutletContext ?? (0, react.createContext)(null);
297
+ if (!existingOutletContext) g.__BOLTDOCS_OUTLET_CONTEXT__ = OutletContext;
298
+ const Outlet = () => {
299
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, { children: (0, react.use)(OutletContext) });
300
+ };
301
+
302
+ //#endregion
303
+ //#region src/client/router/renderer.tsx
304
+ function normalizePath(path) {
305
+ if (!path) return "/";
306
+ const normalized = path.replace(/\\/g, "/").replace(/\/+/g, "/");
307
+ if (normalized.length > 1 && normalized.endsWith("/")) return normalized.slice(0, -1);
308
+ return normalized;
309
+ }
310
+ function splitRoutePath(path) {
311
+ return normalizePath(path).replace(/^\//, "").split("/").filter((segment) => segment && segment !== ".");
312
+ }
313
+ const preparedRouteCache = /* @__PURE__ */ new WeakMap();
314
+ const routeMatchCache = /* @__PURE__ */ new WeakMap();
315
+ const routeSegmentsCache = /* @__PURE__ */ new WeakMap();
316
+ function getRouteSegments(route) {
317
+ let segments = routeSegmentsCache.get(route);
318
+ if (!segments) {
319
+ segments = route.path ? splitRoutePath(route.path) : [];
320
+ routeSegmentsCache.set(route, segments);
321
+ }
322
+ return segments;
323
+ }
324
+ function getPreparedRoutes(routes) {
325
+ const cached = preparedRouteCache.get(routes);
326
+ if (cached) return cached;
327
+ const prepared = routes.map((route, index) => ({
328
+ route,
329
+ index,
330
+ segments: getRouteSegments(route),
331
+ score: routeScore(route),
332
+ children: route.children ? getPreparedRoutes(route.children) : void 0
333
+ })).sort((a, b) => b.score - a.score || a.index - b.index).map(({ route, segments, score, children }) => ({
334
+ route,
335
+ segments,
336
+ score,
337
+ children
338
+ }));
339
+ preparedRouteCache.set(routes, prepared);
340
+ return prepared;
341
+ }
342
+ function matchRoutePath(preparedRoute, target) {
343
+ const route = preparedRoute.route;
344
+ if (route.index || route.path === "" || route.path === ".") return target.length === 0 ? {
345
+ consumed: 0,
346
+ exact: true,
347
+ wildcard: false,
348
+ params: {}
349
+ } : null;
350
+ if (!route.path) return {
351
+ consumed: 0,
352
+ exact: !route.children?.length && target.length === 0,
353
+ wildcard: false,
354
+ params: {}
355
+ };
356
+ const routeSegments = preparedRoute.segments;
357
+ if (routeSegments.length === 0) return target.length === 0 ? {
358
+ consumed: 0,
359
+ exact: true,
360
+ wildcard: false,
361
+ params: {}
362
+ } : null;
363
+ let consumed = 0;
364
+ const params = {};
365
+ for (const segment of routeSegments) {
366
+ if (segment === "*") {
367
+ params["*"] = target.slice(consumed).join("/");
368
+ return {
369
+ consumed: target.length,
370
+ exact: true,
371
+ wildcard: true,
372
+ params
373
+ };
374
+ }
375
+ const targetSegment = target[consumed];
376
+ if (targetSegment === void 0) return null;
377
+ if (segment.startsWith(":")) params[segment.slice(1)] = targetSegment;
378
+ else if (segment !== targetSegment) return null;
379
+ consumed++;
380
+ }
381
+ return {
382
+ consumed,
383
+ exact: consumed === target.length,
384
+ wildcard: false,
385
+ params
386
+ };
387
+ }
388
+ function routeScore(route) {
389
+ if (route.index || route.path === "" || route.path === ".") return 1e3;
390
+ if (route.path === "*") return -1e3;
391
+ if (!route.path) return 0;
392
+ return splitRoutePath(route.path).reduce((score, segment) => {
393
+ if (segment === "*") return score - 100;
394
+ if (segment.startsWith(":")) return score + 10;
395
+ return score + 100;
396
+ }, 0);
397
+ }
398
+ function matchRouteBranchInternal(routes, target) {
399
+ for (const preparedRoute of routes) {
400
+ const route = preparedRoute.route;
401
+ const match = matchRoutePath(preparedRoute, target);
402
+ if (!match) continue;
403
+ const remaining = target.slice(match.consumed);
404
+ if (preparedRoute.children?.length) {
405
+ const childBranch = matchRouteBranchInternal(preparedRoute.children, remaining);
406
+ if (childBranch.length > 0) return [{
407
+ route,
408
+ params: match.params
409
+ }, ...childBranch.map((child) => ({
410
+ route: child.route,
411
+ params: {
412
+ ...match.params,
413
+ ...child.params
414
+ }
415
+ }))];
416
+ if (!match.exact) continue;
417
+ }
418
+ if (match.exact || match.wildcard) return [{
419
+ route,
420
+ params: match.params
421
+ }];
422
+ }
423
+ return [];
424
+ }
425
+ function getTargetSegments(pathname, basename) {
426
+ const normalizedPathname = normalizePath(pathname);
427
+ const targets = [splitRoutePath(normalizedPathname)];
428
+ const normalizedBasename = normalizeBasename(basename);
429
+ if (normalizedBasename !== "/" && hasBasename(normalizedPathname, normalizedBasename)) targets.push(splitRoutePath(stripBasename(normalizedPathname, normalizedBasename)));
430
+ return targets;
431
+ }
432
+ function matchRouteBranchWithParams(routes, pathname, basename) {
433
+ const cacheKey = `${normalizePath(pathname)}\u0000${normalizeBasename(basename)}`;
434
+ let matches = routeMatchCache.get(routes);
435
+ if (!matches) {
436
+ matches = /* @__PURE__ */ new Map();
437
+ routeMatchCache.set(routes, matches);
438
+ }
439
+ const cached = matches.get(cacheKey);
440
+ if (cached) return cached;
441
+ const preparedRoutes = getPreparedRoutes(routes);
442
+ for (const target of getTargetSegments(pathname, basename)) {
443
+ const branch = matchRouteBranchInternal(preparedRoutes, target);
444
+ if (branch.length > 0) {
445
+ cacheRouteEntry(matches, cacheKey, branch);
446
+ return branch;
447
+ }
448
+ }
449
+ cacheRouteEntry(matches, cacheKey, []);
450
+ return [];
451
+ }
452
+ function matchRouteBranch(routes, pathname, basename) {
453
+ return matchRouteBranchWithParams(routes, pathname, basename).map((match) => match.route);
454
+ }
455
+ const resolvedLazyCache = /* @__PURE__ */ new WeakMap();
456
+ const pendingLazyCache = /* @__PURE__ */ new WeakMap();
457
+ const routeCacheScopes = /* @__PURE__ */ new WeakMap();
458
+ let nextRouteCacheScope = 0;
459
+ const prefetchCache = /* @__PURE__ */ new Map();
460
+ const loaderDataCache = /* @__PURE__ */ new Map();
461
+ const MAX_ROUTE_CACHE_ENTRIES = 128;
462
+ const MAX_ACTIVE_PREFETCHES = 2;
463
+ const MAX_PENDING_PREFETCHES = 16;
464
+ const ROUTE_RESOLUTION_TIMEOUT_MS = 4500;
465
+ const ROUTE_LOADER_TIMEOUT_MS = 4500;
466
+ const PREFETCH_SKIPPED = Symbol("prefetch-skipped");
467
+ function withTimeout(promise, timeoutMs, message) {
468
+ return new Promise((resolve, reject) => {
469
+ const timer = setTimeout(() => reject(new Error(message)), timeoutMs);
470
+ promise.then((value) => {
471
+ clearTimeout(timer);
472
+ resolve(value);
473
+ }, (error) => {
474
+ clearTimeout(timer);
475
+ reject(error);
476
+ });
477
+ });
478
+ }
479
+ function createPrefetchQueue() {
480
+ let activePrefetches = 0;
481
+ const pendingPrefetches = [];
482
+ const drain = () => {
483
+ while (activePrefetches < MAX_ACTIVE_PREFETCHES && pendingPrefetches.length > 0) {
484
+ const task = pendingPrefetches.shift();
485
+ if (!task) break;
486
+ activePrefetches++;
487
+ task.run().then(task.resolve, task.reject).finally(() => {
488
+ activePrefetches--;
489
+ drain();
490
+ });
491
+ }
492
+ };
493
+ return {
494
+ enqueue(run) {
495
+ if (pendingPrefetches.length >= MAX_PENDING_PREFETCHES) return PREFETCH_SKIPPED;
496
+ return new Promise((resolve, reject) => {
497
+ pendingPrefetches.push({
498
+ run,
499
+ resolve,
500
+ reject
501
+ });
502
+ drain();
503
+ });
504
+ },
505
+ clear() {
506
+ for (const task of pendingPrefetches.splice(0)) task.resolve();
507
+ }
508
+ };
509
+ }
510
+ function getRouteCacheScope(routes) {
511
+ let scope = routeCacheScopes.get(routes);
512
+ if (scope === void 0) {
513
+ scope = ++nextRouteCacheScope;
514
+ routeCacheScopes.set(routes, scope);
515
+ }
516
+ return scope;
517
+ }
518
+ function cacheRouteEntry(cache, key, value) {
519
+ if (cache.size >= MAX_ROUTE_CACHE_ENTRIES) {
520
+ const oldest = cache.keys().next().value;
521
+ if (oldest !== void 0) cache.delete(oldest);
522
+ }
523
+ cache.set(key, value);
524
+ }
525
+ async function resolveRouteBranch(branch) {
526
+ const resolved = [];
527
+ for (const route of branch) {
528
+ if (!route.element && !route.Component && route.lazy) try {
529
+ let result = resolvedLazyCache.get(route);
530
+ if (!result) {
531
+ let pending = pendingLazyCache.get(route);
532
+ if (!pending) {
533
+ pending = route.lazy();
534
+ pendingLazyCache.set(route, pending);
535
+ }
536
+ try {
537
+ result = await withTimeout(pending, ROUTE_RESOLUTION_TIMEOUT_MS, "Timed out while loading a documentation route");
538
+ } finally {
539
+ pendingLazyCache.delete(route);
540
+ }
541
+ resolvedLazyCache.set(route, result);
542
+ }
543
+ resolved.push({
544
+ ...route,
545
+ ...result
546
+ });
547
+ continue;
548
+ } catch (err) {
549
+ console.error("[RouteRenderer] Error resolving lazy route:", err);
550
+ }
551
+ resolved.push(route);
552
+ }
553
+ return resolved;
554
+ }
555
+ function asLoaderData(value) {
556
+ return value !== null && typeof value === "object" ? value : null;
557
+ }
558
+ function getLoaderDataKey(routeScope, pathname, search = "") {
559
+ return `${routeScope}:${pathname}${search}`;
560
+ }
561
+ function loadRouteData(key, matches, resolvedBranch, request) {
562
+ const cached = loaderDataCache.get(key);
563
+ if (cached) return cached;
564
+ const pending = withTimeout(Promise.all(resolvedBranch.map(async (route, index) => {
565
+ if (!route?.loader) return null;
566
+ try {
567
+ return asLoaderData(await route.loader({
568
+ request,
569
+ params: matches[index].params
570
+ }));
571
+ } catch (err) {
572
+ console.error("[RouteRenderer] loader error:", err);
573
+ throw err;
574
+ }
575
+ })).then((values) => {
576
+ const merged = {};
577
+ for (const value of values) if (value) Object.assign(merged, value);
578
+ return merged;
579
+ }), ROUTE_LOADER_TIMEOUT_MS, "Timed out while loading documentation data");
580
+ cacheRouteEntry(loaderDataCache, key, pending);
581
+ pending.catch(() => loaderDataCache.delete(key));
582
+ return pending;
583
+ }
584
+ function RouteContent({ routes, initialPathname, resolvedBranch: initialResolvedBranch, basename, hasLoaderData }) {
585
+ const location = useLocation();
586
+ const currentPathname = location.pathname || initialPathname || "/";
587
+ const currentSearch = location.search || "";
588
+ const currentHash = location.hash || "";
589
+ const routeMatches = (0, react.useMemo)(() => matchRouteBranchWithParams(routes, currentPathname, basename), [
590
+ routes,
591
+ currentPathname,
592
+ basename
593
+ ]);
594
+ const matchedBranch = (0, react.useMemo)(() => routeMatches.map((match) => match.route), [routeMatches]);
595
+ const isFirstRenderRef = (0, react.useRef)(true);
596
+ const isInitialNavigation = currentPathname === initialPathname && isFirstRenderRef.current;
597
+ const usesInitialResolvedBranch = !!initialResolvedBranch && isInitialNavigation;
598
+ const initialBranch = (0, react.useMemo)(() => usesInitialResolvedBranch ? initialResolvedBranch : matchedBranch, [
599
+ matchedBranch,
600
+ usesInitialResolvedBranch,
601
+ initialResolvedBranch
602
+ ]);
603
+ const initialLoaderData = asLoaderData((0, react.use)(RouteDataContext));
604
+ const initialDataAvailable = isInitialNavigation && hasLoaderData === true;
605
+ const needsAsyncWork = initialBranch.some((route) => !usesInitialResolvedBranch && !route.element && !route.Component && !!route.lazy || !!route.loader && !initialDataAvailable);
606
+ const routeScope = getRouteCacheScope(routes);
607
+ const navigationKey = `${routeScope}\u0000${currentPathname}\u0000${currentSearch}`;
608
+ const outerData = initialDataAvailable ? initialLoaderData : null;
609
+ const outerDataRef = (0, react.useRef)(outerData);
610
+ outerDataRef.current = outerData;
611
+ const navigationIdRef = (0, react.useRef)(0);
612
+ const committedNavigationRef = (0, react.useRef)("");
613
+ const [resolved, setResolved] = (0, react.useState)(!needsAsyncWork ? {
614
+ branch: initialBranch,
615
+ key: navigationKey,
616
+ pathname: currentPathname,
617
+ search: currentSearch,
618
+ loaderData: outerData
619
+ } : null);
620
+ const routeNeedsAsyncWork = needsAsyncWork && resolved?.key !== navigationKey;
621
+ (0, react.useEffect)(() => {
622
+ isFirstRenderRef.current = false;
623
+ }, []);
624
+ (0, react.useEffect)(() => {
625
+ if (!routeNeedsAsyncWork) return;
626
+ const navigationId = ++navigationIdRef.current;
627
+ let cancelled = false;
628
+ const matches = routeMatches;
629
+ const branch = matchedBranch;
630
+ const requestUrl = typeof window !== "undefined" ? new URL(`${currentPathname}${currentSearch}`, window.location.origin).href : `http://localhost${currentPathname}${currentSearch}`;
631
+ resolveRouteBranch(branch).then(async (resolvedBranch) => {
632
+ if (cancelled || navigationId !== navigationIdRef.current) return;
633
+ let loaderData;
634
+ try {
635
+ loaderData = await loadRouteData(getLoaderDataKey(routeScope, currentPathname, currentSearch), matches, resolvedBranch, new Request(requestUrl));
636
+ } catch {
637
+ loaderData = {
638
+ ...outerDataRef.current || {},
639
+ __loaderError: true
640
+ };
641
+ }
642
+ if (cancelled || navigationId !== navigationIdRef.current) return;
643
+ (0, react.startTransition)(() => {
644
+ setResolved({
645
+ branch: resolvedBranch,
646
+ key: navigationKey,
647
+ pathname: currentPathname,
648
+ search: currentSearch,
649
+ loaderData
650
+ });
651
+ });
652
+ }).catch((error) => {
653
+ if (cancelled || navigationId !== navigationIdRef.current) return;
654
+ console.warn("[RouteRenderer] navigation error:", error);
655
+ (0, react.startTransition)(() => {
656
+ setResolved({
657
+ branch,
658
+ key: navigationKey,
659
+ pathname: currentPathname,
660
+ search: currentSearch,
661
+ loaderData: {
662
+ ...outerDataRef.current || {},
663
+ __routeError: true
664
+ }
665
+ });
666
+ });
667
+ });
668
+ return () => {
669
+ cancelled = true;
670
+ };
671
+ }, [
672
+ currentPathname,
673
+ currentSearch,
674
+ routeMatches,
675
+ matchedBranch,
676
+ routeNeedsAsyncWork,
677
+ navigationKey,
678
+ routeScope
679
+ ]);
680
+ const hasResolvedCurrentRoute = resolved?.key === navigationKey;
681
+ const hasRenderableBranch = (0, react.useCallback)((candidate) => candidate.some((route) => route.element || route.Component), []);
682
+ const previousBranch = resolved?.branch;
683
+ const lastRenderableBranchRef = (0, react.useRef)([]);
684
+ const branch = usesInitialResolvedBranch ? hasResolvedCurrentRoute ? resolved.branch : initialBranch : !routeNeedsAsyncWork || hasResolvedCurrentRoute ? hasResolvedCurrentRoute ? resolved.branch : initialBranch : hasRenderableBranch(previousBranch || []) ? previousBranch || [] : hasRenderableBranch(lastRenderableBranchRef.current) ? lastRenderableBranchRef.current : matchedBranch;
685
+ if (hasResolvedCurrentRoute && hasRenderableBranch(branch)) lastRenderableBranchRef.current = branch;
686
+ (0, react.useEffect)(() => {
687
+ if (typeof window === "undefined") return;
688
+ const commitKey = `${currentPathname}${currentSearch}${currentHash}`;
689
+ if (committedNavigationRef.current === commitKey) return;
690
+ if (routeNeedsAsyncWork && !hasResolvedCurrentRoute) return;
691
+ if (!hasRenderableBranch(branch)) return;
692
+ committedNavigationRef.current = commitKey;
693
+ window.dispatchEvent(new CustomEvent("boltdocs:route-commit", { detail: {
694
+ pathname: currentPathname,
695
+ search: currentSearch,
696
+ hash: currentHash
697
+ } }));
698
+ }, [
699
+ branch,
700
+ currentHash,
701
+ currentPathname,
702
+ currentSearch,
703
+ hasRenderableBranch,
704
+ hasResolvedCurrentRoute,
705
+ routeNeedsAsyncWork
706
+ ]);
707
+ if (branch.length === 0) return null;
708
+ let currentElement = null;
709
+ for (let i = branch.length - 1; i >= 0; i--) {
710
+ const route = branch[i];
711
+ let element = route.element;
712
+ if (!element && route.Component) {
713
+ const Comp = route.Component;
714
+ element = /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Comp, {}, route.path ?? `${route.index ? "index" : "route"}-${route.locale ?? "none"}`);
715
+ }
716
+ if (!element) continue;
717
+ if (currentElement === null) currentElement = element;
718
+ else {
719
+ let wrappedElement = element;
720
+ if (react.default.isValidElement(element)) {
721
+ const el = element;
722
+ const existingChildren = el.props.children;
723
+ wrappedElement = react.default.cloneElement(el, { children: existingChildren ?? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Outlet, {}) });
724
+ }
725
+ currentElement = /* @__PURE__ */ (0, react_jsx_runtime.jsx)(OutletContext.Provider, {
726
+ value: currentElement,
727
+ children: wrappedElement
728
+ });
729
+ }
730
+ }
731
+ const finalData = hasResolvedCurrentRoute && resolved.loaderData ? resolved.loaderData : outerData;
732
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RouteDataContext.Provider, {
733
+ value: finalData,
734
+ children: currentElement
735
+ });
736
+ }
737
+ const RouteRenderer = ({ routes, pathname, loaderData, resolvedBranch, basename, defaultLocale, hasLoaderData = false, prefetch: prefetchProp, viewTransitions }) => {
738
+ const prefetchQueueRef = (0, react.useRef)(null);
739
+ if (!prefetchQueueRef.current) prefetchQueueRef.current = createPrefetchQueue();
740
+ const prefetchQueue = prefetchQueueRef.current;
741
+ (0, react.useEffect)(() => {
742
+ return () => prefetchQueue.clear();
743
+ }, [prefetchQueue]);
744
+ const prefetch = (0, react.useCallback)(async (to) => {
745
+ if (typeof window === "undefined" || !to) return;
746
+ const target = new URL(to, window.location.href);
747
+ if (target.origin !== window.location.origin || target.hash) return;
748
+ const key = `${getRouteCacheScope(routes)}:${target.pathname}${target.search}`;
749
+ const cached = prefetchCache.get(key);
750
+ if (cached) return cached;
751
+ const pending = prefetchQueue.enqueue(async () => {
752
+ const matches = matchRouteBranchWithParams(routes, target.pathname, basename);
753
+ if (matches.length === 0) return;
754
+ const branch = await resolveRouteBranch(matches.map((match) => match.route));
755
+ await loadRouteData(getLoaderDataKey(getRouteCacheScope(routes), target.pathname, target.search), matches, branch, new Request(target.href));
756
+ });
757
+ if (pending === PREFETCH_SKIPPED) return;
758
+ cacheRouteEntry(prefetchCache, key, pending);
759
+ try {
760
+ await pending;
761
+ } catch (error) {
762
+ prefetchCache.delete(key);
763
+ throw error;
764
+ }
765
+ }, [
766
+ routes,
767
+ basename,
768
+ prefetchQueue
769
+ ]);
770
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(LocationProvider, {
771
+ pathname,
772
+ loaderData,
773
+ basename,
774
+ defaultLocale,
775
+ prefetch: prefetchProp || prefetch,
776
+ viewTransitions,
777
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RouteContent, {
778
+ routes,
779
+ initialPathname: pathname,
780
+ resolvedBranch,
781
+ basename,
782
+ hasLoaderData
783
+ })
784
+ });
785
+ };
786
+
787
+ //#endregion
788
+ //#region src/client/router/url-contract.ts
789
+ function normalizeUrlBase(base) {
790
+ if (!base || base === "/") return "/";
791
+ return (base.startsWith("/") ? base : `/${base}`).replace(/\/+/g, "/").replace(/\/$/, "") || "/";
792
+ }
793
+ function normalizeUrlPath(path) {
794
+ if (!path) return "/";
795
+ const normalized = `/${path}`.replace(/\/+/g, "/");
796
+ if (normalized.length > 1 && normalized.endsWith("/")) return normalized.slice(0, -1);
797
+ return normalized;
798
+ }
799
+ function hasUrlBase(pathname, base) {
800
+ const normalizedPath = normalizeUrlPath(pathname);
801
+ const normalizedBase = normalizeUrlBase(base);
802
+ if (normalizedBase === "/") return true;
803
+ return normalizedPath === normalizedBase || normalizedPath.startsWith(`${normalizedBase}/`);
804
+ }
805
+ function stripUrlBase(pathname, base) {
806
+ const normalizedPath = normalizeUrlPath(pathname);
807
+ const normalizedBase = normalizeUrlBase(base);
808
+ if (normalizedBase === "/") return normalizedPath;
809
+ if (!hasUrlBase(normalizedPath, normalizedBase)) return normalizedPath;
810
+ return normalizeUrlPath(normalizedPath.slice(normalizedBase.length) || "/");
811
+ }
812
+ function addUrlBase(pathname, base) {
813
+ const normalizedPath = normalizeUrlPath(pathname);
814
+ const normalizedBase = normalizeUrlBase(base);
815
+ if (normalizedBase === "/" || hasUrlBase(normalizedPath, normalizedBase)) return normalizedPath;
816
+ return normalizeUrlPath(`${normalizedBase}/${normalizedPath}`);
817
+ }
818
+ function getConfiguredLocales(config) {
819
+ if (!config.i18n) return [];
820
+ return Array.isArray(config.i18n.locales) ? [...config.i18n.locales] : Object.keys(config.i18n.locales);
821
+ }
822
+ function getConfiguredVersions(config) {
823
+ return config.versions?.versions.map((version) => version.path) || [];
824
+ }
825
+ function getVersionPrefixSegments(config) {
826
+ const prefix = config.versions?.prefix;
827
+ if (!prefix) return [];
828
+ return normalizeUrlPath(prefix).split("/").filter(Boolean);
829
+ }
830
+ function getVersionSegments(version, config) {
831
+ if (!version || !config.versions || !isConfiguredVersion(version, config)) return [];
832
+ return [...getVersionPrefixSegments(config), version];
833
+ }
834
+ function isConfiguredLocale(value, config) {
835
+ return !!value && getConfiguredLocales(config).includes(value);
836
+ }
837
+ function isConfiguredVersion(value, config) {
838
+ return !!value && getConfiguredVersions(config).includes(value);
839
+ }
840
+ function matchConfiguredVersion(parts, start, config) {
841
+ const prefix = getVersionPrefixSegments(config);
842
+ const versionIndex = start + prefix.length;
843
+ if (!prefix.every((segment, index) => parts[start + index] === segment) || !isConfiguredVersion(parts[versionIndex], config)) return { nextIndex: start };
844
+ return {
845
+ version: parts[versionIndex],
846
+ nextIndex: versionIndex + 1
847
+ };
848
+ }
849
+ function splitUrlReference(to) {
850
+ const firstDelimiter = to.search(/[?#]/);
851
+ if (firstDelimiter < 0) return {
852
+ pathname: to,
853
+ search: "",
854
+ hash: ""
855
+ };
856
+ const pathname = to.slice(0, firstDelimiter);
857
+ const suffix = to.slice(firstDelimiter);
858
+ const hashIndex = suffix.indexOf("#");
859
+ if (hashIndex < 0) return {
860
+ pathname,
861
+ search: suffix,
862
+ hash: ""
863
+ };
864
+ return {
865
+ pathname,
866
+ search: suffix.slice(0, hashIndex),
867
+ hash: suffix.slice(hashIndex)
868
+ };
869
+ }
870
+ function stripSiteProtocol(to) {
871
+ if (!to.startsWith("site:")) return {
872
+ value: to,
873
+ siteProtocol: false
874
+ };
875
+ return {
876
+ value: to.slice(5) || "/",
877
+ siteProtocol: true
878
+ };
879
+ }
880
+ /** Returns true for URI schemes such as `mailto:`, `tel:`, or `data:`. */
881
+ function hasUriScheme(value) {
882
+ return /^[a-z][a-z\d+.-]*:/i.test(value);
883
+ }
884
+ function normalizeSuffix(value, prefix) {
885
+ if (!value) return "";
886
+ return value.startsWith(prefix) ? value : `${prefix}${value}`;
887
+ }
888
+ function getRouteHint(pathname, routes) {
889
+ if (!routes) return void 0;
890
+ const normalized = normalizeUrlPath(pathname);
891
+ return routes.find((route) => normalizeUrlPath(route.path) === normalized);
892
+ }
893
+ function getCollectionFromPath(pathname, config) {
894
+ const parts = normalizeUrlPath(pathname).split("/").filter(Boolean);
895
+ const locales = getConfiguredLocales(config);
896
+ const collectionNames = Array.isArray(config.collections) ? config.collections : Object.keys(config.collections?.labels || {});
897
+ const collections = new Set(collectionNames);
898
+ let index = 0;
899
+ const versionMatch = matchConfiguredVersion(parts, index, config);
900
+ const version = versionMatch.version;
901
+ index = versionMatch.nextIndex;
902
+ let locale;
903
+ if (locales.includes(parts[index] || "")) {
904
+ locale = parts[index];
905
+ index++;
906
+ }
907
+ const collection = parts[index];
908
+ if (!collection || !collections.has(collection)) return { remainder: parts };
909
+ return {
910
+ collection,
911
+ locale,
912
+ version,
913
+ remainder: parts.slice(index + 1)
914
+ };
915
+ }
916
+ function classifyUrlPath(pathname, config, options = {}) {
917
+ if (options.kind) return options.kind;
918
+ const normalizedPath = normalizeUrlPath(pathname);
919
+ const hint = getRouteHint(normalizedPath, options.routes);
920
+ if (hint?.kind) return hint.kind;
921
+ if (hint?.collection) return "collection";
922
+ if (getCollectionFromPath(normalizedPath, config).collection) return "collection";
923
+ if (hasUrlBase(normalizedPath, config.base)) return "doc";
924
+ return "external";
925
+ }
926
+ function parseUrlReference(to, config, options = {}) {
927
+ const { value, siteProtocol } = stripSiteProtocol(to);
928
+ const split = splitUrlReference(value);
929
+ const pathname = normalizeUrlPath(split.pathname || "/");
930
+ const hadBase = hasUrlBase(pathname, config.base);
931
+ const kind = classifyUrlPath(pathname, config, options);
932
+ if (kind === "doc") {
933
+ const parts = stripUrlBase(pathname, config.base).split("/").filter(Boolean);
934
+ let index = 0;
935
+ const versionMatch = matchConfiguredVersion(parts, index, config);
936
+ const version = versionMatch.version;
937
+ index = versionMatch.nextIndex;
938
+ const locale = isConfiguredLocale(parts[index], config) ? parts[index] : void 0;
939
+ if (locale) index++;
940
+ return {
941
+ pathname,
942
+ routePath: normalizeUrlPath(parts.slice(index).join("/")),
943
+ search: split.search,
944
+ hash: split.hash,
945
+ kind,
946
+ locale,
947
+ version,
948
+ siteProtocol,
949
+ hadBase
950
+ };
951
+ }
952
+ if (kind === "collection") {
953
+ const collection = getCollectionFromPath(pathname, config);
954
+ return {
955
+ pathname,
956
+ routePath: normalizeUrlPath(collection.remainder.join("/")),
957
+ search: split.search,
958
+ hash: split.hash,
959
+ kind,
960
+ locale: collection.locale,
961
+ version: collection.version,
962
+ collection: collection.collection,
963
+ siteProtocol,
964
+ hadBase
965
+ };
966
+ }
967
+ const parts = pathname.split("/").filter(Boolean);
968
+ const locale = isConfiguredLocale(parts[0], config) ? parts[0] : void 0;
969
+ return {
970
+ pathname,
971
+ routePath: normalizeUrlPath((locale ? parts.slice(1) : parts).join("/")),
972
+ search: split.search,
973
+ hash: split.hash,
974
+ kind,
975
+ locale,
976
+ siteProtocol,
977
+ hadBase
978
+ };
979
+ }
980
+ function buildUrl(options, config) {
981
+ const routePath = normalizeUrlPath(options.path || "/");
982
+ const locale = options.locale && options.locale !== config.i18n?.defaultLocale ? options.locale : void 0;
983
+ const search = normalizeSuffix(options.search, "?");
984
+ const hash = normalizeSuffix(options.hash, "#");
985
+ let pathname;
986
+ if (options.kind === "doc") pathname = normalizeUrlPath([
987
+ normalizeUrlBase(config.base) === "/" ? void 0 : normalizeUrlBase(config.base).slice(1),
988
+ ...getVersionSegments(options.version, config),
989
+ locale,
990
+ routePath === "/" ? void 0 : routePath.slice(1)
991
+ ].filter(Boolean).join("/"));
992
+ else if (options.kind === "collection") {
993
+ if (!options.collection) throw new Error("A collection route requires a collection name");
994
+ pathname = normalizeUrlPath([
995
+ normalizeUrlBase(config.base) === "/" ? void 0 : normalizeUrlBase(config.base).slice(1),
996
+ ...getVersionSegments(options.version, config),
997
+ locale,
998
+ options.collection,
999
+ routePath === "/" ? void 0 : routePath.slice(1)
1000
+ ].filter(Boolean).join("/"));
1001
+ } else pathname = normalizeUrlPath([locale, routePath === "/" ? void 0 : routePath.slice(1)].filter(Boolean).join("/"));
1002
+ return `${pathname}${search}${hash}`;
1003
+ }
1004
+ function resolveUrlReference(to, config, options = {}) {
1005
+ const { value, siteProtocol } = stripSiteProtocol(to);
1006
+ if (hasUriScheme(value) || /^(?:https?:)?\/\//i.test(value)) return to;
1007
+ if (value.startsWith("#") || value.startsWith("?")) return siteProtocol ? value : to;
1008
+ const parsed = parseUrlReference(value, config, options);
1009
+ const kind = options.kind || parsed.kind;
1010
+ const locale = options.locale ?? parsed.locale;
1011
+ const version = options.version ?? parsed.version;
1012
+ const derived = getCollectionFromPath(stripUrlBase(parsed.pathname, config.base), config);
1013
+ const collection = parsed.collection ?? derived.collection;
1014
+ const routePath = derived.collection && !parsed.collection ? normalizeUrlPath(derived.remainder.join("/")) : parsed.routePath;
1015
+ return buildUrl({
1016
+ kind: collection || parsed.kind === "collection" ? "collection" : kind,
1017
+ path: routePath,
1018
+ locale,
1019
+ version,
1020
+ collection,
1021
+ search: parsed.search,
1022
+ hash: parsed.hash,
1023
+ hadBase: parsed.hadBase
1024
+ }, config);
1025
+ }
1026
+
1027
+ //#endregion
1028
+ Object.defineProperty(exports, 'LocationContext', {
1029
+ enumerable: true,
1030
+ get: function () {
1031
+ return LocationContext;
1032
+ }
1033
+ });
1034
+ Object.defineProperty(exports, 'LocationProvider', {
1035
+ enumerable: true,
1036
+ get: function () {
1037
+ return LocationProvider;
1038
+ }
1039
+ });
1040
+ Object.defineProperty(exports, 'MatchesContext', {
1041
+ enumerable: true,
1042
+ get: function () {
1043
+ return MatchesContext;
1044
+ }
1045
+ });
1046
+ Object.defineProperty(exports, 'NavigateContext', {
1047
+ enumerable: true,
1048
+ get: function () {
1049
+ return NavigateContext;
1050
+ }
1051
+ });
1052
+ Object.defineProperty(exports, 'Outlet', {
1053
+ enumerable: true,
1054
+ get: function () {
1055
+ return Outlet;
1056
+ }
1057
+ });
1058
+ Object.defineProperty(exports, 'OutletContext', {
1059
+ enumerable: true,
1060
+ get: function () {
1061
+ return OutletContext;
1062
+ }
1063
+ });
1064
+ Object.defineProperty(exports, 'PrefetchContext', {
1065
+ enumerable: true,
1066
+ get: function () {
1067
+ return PrefetchContext;
1068
+ }
1069
+ });
1070
+ Object.defineProperty(exports, 'RouteDataContext', {
1071
+ enumerable: true,
1072
+ get: function () {
1073
+ return RouteDataContext;
1074
+ }
1075
+ });
1076
+ Object.defineProperty(exports, 'RouteRenderer', {
1077
+ enumerable: true,
1078
+ get: function () {
1079
+ return RouteRenderer;
1080
+ }
1081
+ });
1082
+ Object.defineProperty(exports, '__exportAll', {
1083
+ enumerable: true,
1084
+ get: function () {
1085
+ return __exportAll;
1086
+ }
1087
+ });
1088
+ Object.defineProperty(exports, '__toESM', {
1089
+ enumerable: true,
1090
+ get: function () {
1091
+ return __toESM;
1092
+ }
1093
+ });
1094
+ Object.defineProperty(exports, 'addBasename', {
1095
+ enumerable: true,
1096
+ get: function () {
1097
+ return addBasename;
1098
+ }
1099
+ });
1100
+ Object.defineProperty(exports, 'addUrlBase', {
1101
+ enumerable: true,
1102
+ get: function () {
1103
+ return addUrlBase;
1104
+ }
1105
+ });
1106
+ Object.defineProperty(exports, 'buildUrl', {
1107
+ enumerable: true,
1108
+ get: function () {
1109
+ return buildUrl;
1110
+ }
1111
+ });
1112
+ Object.defineProperty(exports, 'classifyUrlPath', {
1113
+ enumerable: true,
1114
+ get: function () {
1115
+ return classifyUrlPath;
1116
+ }
1117
+ });
1118
+ Object.defineProperty(exports, 'defaultNavigate', {
1119
+ enumerable: true,
1120
+ get: function () {
1121
+ return defaultNavigate;
1122
+ }
1123
+ });
1124
+ Object.defineProperty(exports, 'getConfiguredLocales', {
1125
+ enumerable: true,
1126
+ get: function () {
1127
+ return getConfiguredLocales;
1128
+ }
1129
+ });
1130
+ Object.defineProperty(exports, 'getConfiguredVersions', {
1131
+ enumerable: true,
1132
+ get: function () {
1133
+ return getConfiguredVersions;
1134
+ }
1135
+ });
1136
+ Object.defineProperty(exports, 'getVersionPrefixSegments', {
1137
+ enumerable: true,
1138
+ get: function () {
1139
+ return getVersionPrefixSegments;
1140
+ }
1141
+ });
1142
+ Object.defineProperty(exports, 'getVersionSegments', {
1143
+ enumerable: true,
1144
+ get: function () {
1145
+ return getVersionSegments;
1146
+ }
1147
+ });
1148
+ Object.defineProperty(exports, 'hasBasename', {
1149
+ enumerable: true,
1150
+ get: function () {
1151
+ return hasBasename;
1152
+ }
1153
+ });
1154
+ Object.defineProperty(exports, 'hasUriScheme', {
1155
+ enumerable: true,
1156
+ get: function () {
1157
+ return hasUriScheme;
1158
+ }
1159
+ });
1160
+ Object.defineProperty(exports, 'hasUrlBase', {
1161
+ enumerable: true,
1162
+ get: function () {
1163
+ return hasUrlBase;
1164
+ }
1165
+ });
1166
+ Object.defineProperty(exports, 'isConfiguredLocale', {
1167
+ enumerable: true,
1168
+ get: function () {
1169
+ return isConfiguredLocale;
1170
+ }
1171
+ });
1172
+ Object.defineProperty(exports, 'isConfiguredVersion', {
1173
+ enumerable: true,
1174
+ get: function () {
1175
+ return isConfiguredVersion;
1176
+ }
1177
+ });
1178
+ Object.defineProperty(exports, 'matchRouteBranch', {
1179
+ enumerable: true,
1180
+ get: function () {
1181
+ return matchRouteBranch;
1182
+ }
1183
+ });
1184
+ Object.defineProperty(exports, 'matchRouteBranchWithParams', {
1185
+ enumerable: true,
1186
+ get: function () {
1187
+ return matchRouteBranchWithParams;
1188
+ }
1189
+ });
1190
+ Object.defineProperty(exports, 'normalizeBasename', {
1191
+ enumerable: true,
1192
+ get: function () {
1193
+ return normalizeBasename;
1194
+ }
1195
+ });
1196
+ Object.defineProperty(exports, 'normalizeUrlBase', {
1197
+ enumerable: true,
1198
+ get: function () {
1199
+ return normalizeUrlBase;
1200
+ }
1201
+ });
1202
+ Object.defineProperty(exports, 'normalizeUrlPath', {
1203
+ enumerable: true,
1204
+ get: function () {
1205
+ return normalizeUrlPath;
1206
+ }
1207
+ });
1208
+ Object.defineProperty(exports, 'parseUrlReference', {
1209
+ enumerable: true,
1210
+ get: function () {
1211
+ return parseUrlReference;
1212
+ }
1213
+ });
1214
+ Object.defineProperty(exports, 'resolveRouteBranch', {
1215
+ enumerable: true,
1216
+ get: function () {
1217
+ return resolveRouteBranch;
1218
+ }
1219
+ });
1220
+ Object.defineProperty(exports, 'resolveUrlReference', {
1221
+ enumerable: true,
1222
+ get: function () {
1223
+ return resolveUrlReference;
1224
+ }
1225
+ });
1226
+ Object.defineProperty(exports, 'splitUrlReference', {
1227
+ enumerable: true,
1228
+ get: function () {
1229
+ return splitUrlReference;
1230
+ }
1231
+ });
1232
+ Object.defineProperty(exports, 'stripBasename', {
1233
+ enumerable: true,
1234
+ get: function () {
1235
+ return stripBasename;
1236
+ }
1237
+ });
1238
+ Object.defineProperty(exports, 'stripSiteProtocol', {
1239
+ enumerable: true,
1240
+ get: function () {
1241
+ return stripSiteProtocol;
1242
+ }
1243
+ });
1244
+ Object.defineProperty(exports, 'stripUrlBase', {
1245
+ enumerable: true,
1246
+ get: function () {
1247
+ return stripUrlBase;
1248
+ }
1249
+ });
1250
+ Object.defineProperty(exports, 'useLoaderData', {
1251
+ enumerable: true,
1252
+ get: function () {
1253
+ return useLoaderData;
1254
+ }
1255
+ });
1256
+ Object.defineProperty(exports, 'useLocation', {
1257
+ enumerable: true,
1258
+ get: function () {
1259
+ return useLocation;
1260
+ }
1261
+ });
1262
+ Object.defineProperty(exports, 'useMatches', {
1263
+ enumerable: true,
1264
+ get: function () {
1265
+ return useMatches;
1266
+ }
1267
+ });
1268
+ Object.defineProperty(exports, 'useNavigate', {
1269
+ enumerable: true,
1270
+ get: function () {
1271
+ return useNavigate;
1272
+ }
1273
+ });
1274
+ Object.defineProperty(exports, 'usePrefetch', {
1275
+ enumerable: true,
1276
+ get: function () {
1277
+ return usePrefetch;
1278
+ }
1279
+ });
1280
+ Object.defineProperty(exports, 'useRouteData', {
1281
+ enumerable: true,
1282
+ get: function () {
1283
+ return useRouteData;
1284
+ }
1285
+ });