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
@@ -4,26 +4,22 @@
4
4
  * Licensed under the MIT License.
5
5
  */
6
6
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
7
- const require_link = require('../link-D1Gjkb-2.cjs');
8
- const require_image = require('../image-C4TlpMHn.cjs');
9
- const require_mdx = require('../mdx-CD-tSjRG.cjs');
10
- const require_docs_layout = require('../docs-layout-CFWI15Id.cjs');
11
- const require_search_dialog = require('../search-dialog-B1NERUNx.cjs');
12
- const require_search_dialog$1 = require('../search-dialog-BRFno7HD.cjs');
7
+ const require_router = require('../router-C3kygdRK.cjs');
8
+ const require_link = require('../link-vZjmD-es.cjs');
9
+ const require_image = require('../image-Hnaa2bJd.cjs');
10
+ const require_mdx = require('../mdx-D0Absdq5.cjs');
11
+ const require_docs_layout = require('../docs-layout-vzfXed1Q.cjs');
12
+ const require_search_dialog = require('../search-dialog-D3jtaw6w.cjs');
13
+ const require_search_dialog$1 = require('../search-dialog-x_qHU8ty.cjs');
13
14
  let react = require("react");
14
- let react_router_dom = require("react-router-dom");
15
15
  let react_jsx_runtime = require("react/jsx-runtime");
16
16
  let react_aria_components = require("react-aria-components");
17
17
  let react_helmet_async = require("react-helmet-async");
18
- react_helmet_async = require_link.__toESM(react_helmet_async);
18
+ react_helmet_async = require_router.__toESM(react_helmet_async);
19
19
  let virtual_boltdocs_mdx_components = require("virtual:boltdocs-mdx-components");
20
- virtual_boltdocs_mdx_components = require_link.__toESM(virtual_boltdocs_mdx_components);
21
- let virtual_boltdocs_icons = require("virtual:boltdocs-icons");
22
- virtual_boltdocs_icons = require_link.__toESM(virtual_boltdocs_icons);
23
- let isomorphic_dompurify = require("isomorphic-dompurify");
24
- isomorphic_dompurify = require_link.__toESM(isomorphic_dompurify);
20
+ virtual_boltdocs_mdx_components = require_router.__toESM(virtual_boltdocs_mdx_components);
25
21
  let virtual_boltdocs_layout = require("virtual:boltdocs-layout");
26
- virtual_boltdocs_layout = require_link.__toESM(virtual_boltdocs_layout);
22
+ virtual_boltdocs_layout = require_router.__toESM(virtual_boltdocs_layout);
27
23
  let _bdocs_ssg = require("@bdocs/ssg");
28
24
 
29
25
  //#region src/client/app/mdx-components-context.tsx
@@ -58,12 +54,13 @@ function MdxComponentsProvider({ components, children }) {
58
54
  //#endregion
59
55
  //#region src/client/app/scroll-handler.tsx
60
56
  /**
61
- * Handles scroll restoration and hash scrolling on navigation.
62
- * It ensures the page scrolls to top on pathname changes,
63
- * or specifically to an anchor element if a hash is present.
57
+ * Handles scroll restoration after navigation.
58
+ *
59
+ * Normal page navigation returns the active content container to the top
60
+ * instantly. Explicit hash navigation is positioned at its anchor instead.
64
61
  */
65
62
  function ScrollHandler() {
66
- const { pathname, hash } = (0, react_router_dom.useLocation)();
63
+ const { pathname, hash } = require_router.useLocation();
67
64
  const handleScroll = (behavior = "auto") => {
68
65
  const container = document.querySelector(".boltdocs-content") || document.querySelector(".boltdocs-external-content") || document.querySelector(".boltdocs-shell-content") || window;
69
66
  const getScrollTop = () => {
@@ -81,7 +78,10 @@ function ScrollHandler() {
81
78
  });
82
79
  };
83
80
  if (hash) {
84
- const id = hash.replace("#", "");
81
+ let id = hash.slice(1);
82
+ try {
83
+ id = decodeURIComponent(id);
84
+ } catch {}
85
85
  const element = document.getElementById(id);
86
86
  if (element) {
87
87
  const offset = 80;
@@ -90,23 +90,43 @@ function ScrollHandler() {
90
90
  return true;
91
91
  }
92
92
  }
93
- scrollTo(0, behavior);
93
+ if (container === window) {
94
+ document.documentElement.scrollTop = 0;
95
+ document.body.scrollTop = 0;
96
+ } else container.scrollTop = 0;
94
97
  return false;
95
98
  };
96
- (0, react.useLayoutEffect)(() => {
97
- handleScroll("auto");
98
- }, [pathname, hash]);
99
99
  (0, react.useEffect)(() => {
100
- handleScroll("auto");
100
+ const handleRouteCommit = (event) => {
101
+ const detail = event.detail;
102
+ if (detail?.pathname && detail.pathname !== pathname) return;
103
+ if (detail?.hash !== void 0 && detail.hash !== hash) return;
104
+ handleScroll("auto");
105
+ };
106
+ window.addEventListener("boltdocs:route-commit", handleRouteCommit);
107
+ let frame = 0;
108
+ if (hash) {
109
+ let attempts = 0;
110
+ const retry = () => {
111
+ if (handleScroll("auto") || attempts >= 8) return;
112
+ attempts++;
113
+ frame = requestAnimationFrame(retry);
114
+ };
115
+ frame = requestAnimationFrame(retry);
116
+ }
117
+ return () => {
118
+ window.removeEventListener("boltdocs:route-commit", handleRouteCommit);
119
+ if (frame) cancelAnimationFrame(frame);
120
+ };
101
121
  }, [pathname, hash]);
102
122
  return null;
103
123
  }
104
124
 
105
125
  //#endregion
106
126
  //#region src/client/components/ui-base/not-found.tsx
107
- function NotFound() {
127
+ function NotFound({ className }) {
108
128
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
109
- className: "flex items-center justify-center min-h-[65vh] text-center px-4",
129
+ className: require_link.cn("flex items-center justify-center min-h-[65vh] text-center px-4", className),
110
130
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
111
131
  className: "space-y-6 max-w-md mx-auto p-8 border border-subtle bg-surface rounded-2xl shadow-xs",
112
132
  children: [
@@ -156,8 +176,7 @@ const Helmet = mod.Helmet || mod.default?.Helmet || (({ children }) => /* @__PUR
156
176
  */
157
177
  const HelmetProvider = mod.HelmetProvider || mod.default?.HelmetProvider || (({ children }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, { children }));
158
178
  if (typeof globalThis !== "undefined" && globalThis.__BOLTDOCS_SSG_RENDERING__) {
159
- const hp = HelmetProvider;
160
- if (hp && typeof hp === "function" && hp.canUseDOM) hp.canUseDOM = false;
179
+ if (typeof HelmetProvider === "function" && HelmetProvider.canUseDOM) HelmetProvider.canUseDOM = false;
161
180
  }
162
181
  if (typeof globalThis !== "undefined") {
163
182
  globalThis.__BOLTDOCS_HELMET_PROVIDER__ = HelmetProvider;
@@ -181,16 +200,120 @@ function getTranslated(value, locale) {
181
200
  return Object.values(value)[0] || "";
182
201
  }
183
202
 
203
+ //#endregion
204
+ //#region src/shared/structured-data.ts
205
+ /** Preserve literal JSON-LD types in config files and frontmatter helpers. */
206
+ function defineStructuredData(data) {
207
+ return data;
208
+ }
209
+ /**
210
+ * Creates one JSON-LD value from the common website/article/breadcrumb presets.
211
+ * Single-node input returns an object; multiple nodes return a graph array.
212
+ */
213
+ function createStructuredData(options) {
214
+ const nodes = [];
215
+ if (options.website) nodes.push(createWebSiteStructuredData(options.website));
216
+ if (options.article) nodes.push(createArticleStructuredData(options.article));
217
+ if (options.breadcrumbs?.length) nodes.push(createBreadcrumbStructuredData(options.breadcrumbs));
218
+ if (options.additional) nodes.push(...Array.isArray(options.additional) ? options.additional : [options.additional]);
219
+ if (nodes.length === 0) throw new Error("createStructuredData() requires at least one of website, article, breadcrumbs, or additional");
220
+ return nodes.length === 1 ? nodes[0] : nodes;
221
+ }
222
+ function createWebSiteStructuredData(options) {
223
+ const data = {
224
+ "@context": "https://schema.org",
225
+ "@type": "WebSite",
226
+ name: options.name,
227
+ url: options.url
228
+ };
229
+ if (options.description) data.description = options.description;
230
+ if (options.searchUrl) data.potentialAction = {
231
+ "@type": "SearchAction",
232
+ target: `${options.searchUrl}{search_term_string}`,
233
+ "query-input": "required name=search_term_string"
234
+ };
235
+ return data;
236
+ }
237
+ function toIsoDate(value, field) {
238
+ const date = new Date(value);
239
+ if (Number.isNaN(date.getTime())) throw new TypeError(`Invalid ${field} value: ${String(value)}`);
240
+ return date.toISOString();
241
+ }
242
+ function createArticleStructuredData(options) {
243
+ const data = {
244
+ "@context": "https://schema.org",
245
+ "@type": "Article",
246
+ headline: options.headline,
247
+ url: options.url
248
+ };
249
+ if (options.description) data.description = options.description;
250
+ if (options.datePublished) data.datePublished = toIsoDate(options.datePublished, "datePublished");
251
+ if (options.dateModified) data.dateModified = toIsoDate(options.dateModified, "dateModified");
252
+ if (options.image) data.image = options.image;
253
+ if (options.author) data.author = typeof options.author === "string" ? {
254
+ "@type": "Person",
255
+ name: options.author
256
+ } : {
257
+ "@type": "Person",
258
+ ...options.author
259
+ };
260
+ return data;
261
+ }
262
+ function createBreadcrumbStructuredData(items) {
263
+ return {
264
+ "@context": "https://schema.org",
265
+ "@type": "BreadcrumbList",
266
+ itemListElement: items.map((item, index) => ({
267
+ "@type": "ListItem",
268
+ position: index + 1,
269
+ name: item.name,
270
+ item: item.url
271
+ }))
272
+ };
273
+ }
274
+
275
+ //#endregion
276
+ //#region src/client/components/structured-data.tsx
277
+ /**
278
+ * Renders safe, valid JSON-LD. Escaping `<` prevents a JSON value from closing
279
+ * the surrounding script tag when the document is rendered server-side.
280
+ */
281
+ function StructuredData({ data, id }) {
282
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("script", {
283
+ id,
284
+ type: "application/ld+json",
285
+ dangerouslySetInnerHTML: { __html: JSON.stringify(data).replace(/</g, "\\u003c") }
286
+ });
287
+ }
288
+
184
289
  //#endregion
185
290
  //#region src/client/app/head.tsx
291
+ function stringifyMetaValue(value) {
292
+ if (value == null) return "";
293
+ if (typeof value === "string") return value;
294
+ if (typeof value === "number" || typeof value === "boolean") return String(value);
295
+ if (Array.isArray(value)) return value.map(stringifyMetaValue).join(", ");
296
+ if (typeof value === "object") {
297
+ const record = value;
298
+ const namedValue = record.name ?? record.value ?? record.url;
299
+ if (namedValue !== void 0) return stringifyMetaValue(namedValue);
300
+ try {
301
+ return JSON.stringify(value);
302
+ } catch {
303
+ return "";
304
+ }
305
+ }
306
+ return String(value);
307
+ }
186
308
  function Head({ siteTitle, siteDescription, routes }) {
187
- const location = (0, react_router_dom.useLocation)();
309
+ const location = require_router.useLocation();
188
310
  const config = require_link.useConfig();
189
- const { currentLocale, currentRoute } = require_link.useRoutes();
311
+ const { currentLocale, currentRoute } = require_search_dialog.useRoutes();
190
312
  const route = (0, react.useMemo)(() => {
191
313
  if (currentRoute) return currentRoute;
192
314
  const normalizedPath = location.pathname.endsWith("/") && location.pathname.length > 1 ? location.pathname.slice(0, -1) : location.pathname;
193
315
  return routes?.find?.((r) => {
316
+ if (!r?.path) return false;
194
317
  return (r.path.endsWith("/") && r.path.length > 1 ? r.path.slice(0, -1) : r.path) === normalizedPath;
195
318
  });
196
319
  }, [
@@ -204,18 +327,23 @@ function Head({ siteTitle, siteDescription, routes }) {
204
327
  const translatedSiteTitle = getTranslated(siteTitle, currentLocale);
205
328
  const finalTitle = pageTitle ? `${pageTitle} | ${translatedSiteTitle}` : translatedSiteTitle;
206
329
  const seo = route?.seo || {};
207
- const canonicalUrl = seo.canonical || (config?.siteUrl && route?.path ? `${config.siteUrl.replace(/\/$/, "")}${route.path}` : void 0);
208
- const ogUrl = seo["og:url"] || canonicalUrl || (typeof window !== "undefined" ? window.location.href : void 0);
209
- const globalMetatags = config?.seo?.metatags || {};
330
+ const structuredData = [...Array.isArray(config?.seo?.structuredData) ? config.seo.structuredData : config?.seo?.structuredData ? [config.seo.structuredData] : [], ...Array.isArray(seo.structuredData) ? seo.structuredData : seo.structuredData ? [seo.structuredData] : []];
331
+ const canonicalUrl = stringifyMetaValue(seo.canonical) || (config?.siteUrl && route?.path ? `${config.siteUrl.replace(/\/$/, "")}${route.path}` : void 0);
332
+ const ogUrl = stringifyMetaValue(seo["og:url"]) || canonicalUrl || (typeof window !== "undefined" ? window.location.href : void 0);
210
333
  const defaultOgImage = config?.seo?.thumbnails?.background;
211
- let ogImage = seo["og:image"] || route?.coverImage || defaultOgImage;
212
- if (ogImage && config?.siteUrl && !/^https?:\/\/|^\/\//.test(ogImage)) ogImage = `${config.siteUrl.endsWith("/") ? config.siteUrl.slice(0, -1) : config.siteUrl}${ogImage.startsWith("/") ? ogImage : `/${ogImage}`}`;
334
+ let ogImage = stringifyMetaValue(seo["og:image"]) || route?.coverImage || defaultOgImage;
335
+ if (ogImage && !/^https?:\/\/|^\/\//.test(ogImage)) {
336
+ const assetPath = require_link.resolvePublicAssetUrl(ogImage.startsWith("/") ? ogImage : `/${ogImage}`, config.base);
337
+ if (config?.siteUrl) ogImage = `${config.siteUrl.replace(/\/$/, "")}${assetPath}`;
338
+ else ogImage = assetPath;
339
+ }
213
340
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(Helmet, { children: [
214
341
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("title", { children: finalTitle }),
215
342
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("meta", {
216
343
  name: "description",
217
344
  content: pageDescription
218
345
  }),
346
+ structuredData.map((data) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(StructuredData, { data }, JSON.stringify(data))),
219
347
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("meta", {
220
348
  property: "og:title",
221
349
  content: finalTitle
@@ -256,41 +384,6 @@ function Head({ siteTitle, siteDescription, routes }) {
256
384
  property: "og:image",
257
385
  content: ogImage
258
386
  }),
259
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("meta", {
260
- name: "generator",
261
- content: "Boltdocs"
262
- }),
263
- config?.seo?.verification?.google && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("meta", {
264
- name: "google-site-verification",
265
- content: config.seo.verification.google
266
- }),
267
- config?.seo?.verification?.bing && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("meta", {
268
- name: "msvalidate.01",
269
- content: config.seo.verification.bing
270
- }),
271
- config?.seo?.verification?.yandex && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("meta", {
272
- name: "yandex-verification",
273
- content: config.seo.verification.yandex
274
- }),
275
- config?.seo?.verification?.pinterest && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("meta", {
276
- name: "p:domain_verify",
277
- content: config.seo.verification.pinterest
278
- }),
279
- config?.seo?.verification?.facebook && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("meta", {
280
- name: "facebook-domain-verification",
281
- content: config.seo.verification.facebook
282
- }),
283
- Object.entries(globalMetatags).map(([key, value]) => {
284
- const isProperty = key.startsWith("og:") || key.startsWith("music:") || key.startsWith("video:") || key.startsWith("article:") || key.startsWith("book:") || key.startsWith("profile:");
285
- const strVal = String(value ?? "");
286
- return isProperty ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("meta", {
287
- property: key,
288
- content: strVal
289
- }, key) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("meta", {
290
- name: key,
291
- content: strVal
292
- }, key);
293
- }),
294
387
  Object.entries(seo).map(([key, value]) => {
295
388
  if (key === "noindex" && value === true) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("meta", {
296
389
  name: "robots",
@@ -298,11 +391,11 @@ function Head({ siteTitle, siteDescription, routes }) {
298
391
  }, "noindex");
299
392
  if (key === "robots") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("meta", {
300
393
  name: "robots",
301
- content: String(value)
394
+ content: stringifyMetaValue(value)
302
395
  }, "robots");
303
- if (key === "canonical" || key === "og:url" || key === "og:image" || key === "twitter:image") return null;
396
+ if (key === "canonical" || key === "og:url" || key === "og:image" || key === "twitter:image" || key === "structuredData") return null;
304
397
  const isProperty = key.startsWith("og:") || key.startsWith("music:") || key.startsWith("video:") || key.startsWith("article:") || key.startsWith("book:") || key.startsWith("profile:");
305
- const strVal = String(value ?? "");
398
+ const strVal = stringifyMetaValue(value);
306
399
  return isProperty ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("meta", {
307
400
  property: key,
308
401
  content: strVal
@@ -320,6 +413,35 @@ const CollectionsContext = (0, react.createContext)({});
320
413
  function useCollectionsData() {
321
414
  return (0, react.use)(CollectionsContext);
322
415
  }
416
+ function CollectionsProvider({ collectionsData, children }) {
417
+ const [data, setData] = (0, react.useState)(collectionsData);
418
+ (0, react.useEffect)(() => {
419
+ if (!{}.hot) return;
420
+ const handler = (payload) => {
421
+ setData((prev) => {
422
+ const next = { ...prev };
423
+ for (const post of payload.collections.updated) {
424
+ const collection = post.collection;
425
+ if (!collection) continue;
426
+ const arr = next[collection] ? [...next[collection]] : [];
427
+ const idx = arr.findIndex((p) => p.filePath === post.filePath);
428
+ if (idx >= 0) arr[idx] = post;
429
+ else arr.push(post);
430
+ next[collection] = arr;
431
+ }
432
+ for (const filePath of payload.collections.deleted) for (const key of Object.keys(next)) next[key] = next[key].filter((p) => p.filePath !== filePath);
433
+ return next;
434
+ });
435
+ };
436
+ const hot = {}.hot;
437
+ hot.on("boltdocs:frontmatter-update", handler);
438
+ return () => hot.off?.("boltdocs:frontmatter-update", handler);
439
+ }, []);
440
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CollectionsContext.Provider, {
441
+ value: data,
442
+ children
443
+ });
444
+ }
323
445
  const CurrentPostContext = (0, react.createContext)(null);
324
446
  function CurrentPostProvider({ value, children }) {
325
447
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CurrentPostContext.Provider, {
@@ -338,41 +460,58 @@ function useCurrentPostData() {
338
460
  */
339
461
  function I18nUpdater({ config }) {
340
462
  const { currentLocale } = require_link.useBoltdocsContext();
463
+ const locale = currentLocale || config.i18n?.defaultLocale || "en";
464
+ const localeConfig = config.i18n?.localeConfigs?.[locale];
465
+ const htmlLang = localeConfig?.htmlLang || locale;
466
+ const direction = localeConfig?.direction || "ltr";
341
467
  (0, react.useEffect)(() => {
342
468
  if (!config.i18n || typeof document === "undefined") return;
343
- const locale = currentLocale || config.i18n.defaultLocale;
344
- const localeConfig = config.i18n.localeConfigs?.[locale];
345
- document.documentElement.lang = localeConfig?.htmlLang || locale || "en";
346
- document.documentElement.dir = localeConfig?.direction || "ltr";
347
- }, [currentLocale, config.i18n]);
348
- return null;
469
+ document.documentElement.lang = htmlLang;
470
+ document.documentElement.dir = direction;
471
+ }, [
472
+ config.i18n,
473
+ direction,
474
+ htmlLang
475
+ ]);
476
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Helmet, { htmlAttributes: {
477
+ lang: htmlLang,
478
+ dir: direction
479
+ } });
349
480
  }
350
481
  function StoreSync({ config, routeMap }) {
351
- const location = (0, react_router_dom.useLocation)();
352
- const { setLocale, setVersion } = require_link.useBoltdocsContext();
482
+ const location = require_router.useLocation();
483
+ const { currentLocale, currentVersion, setLocale, setVersion } = require_link.useBoltdocsContext();
353
484
  (0, react.useEffect)(() => {
354
- const currentPath = require_link.normalizePath(location.pathname);
485
+ const currentPath = require_link.normalizePath(typeof window !== "undefined" ? window.location.pathname : location.pathname);
355
486
  const matchedRoute = routeMap.get(currentPath);
356
487
  if (matchedRoute) {
357
- if (config.i18n) setLocale(matchedRoute.locale || config.i18n.defaultLocale);
358
- if (config.versions) setVersion(matchedRoute.version || config.versions.defaultVersion);
359
- }
488
+ if (config.i18n) {
489
+ const targetLocale = matchedRoute.locale || config.i18n.defaultLocale;
490
+ if (targetLocale !== currentLocale) setLocale(targetLocale);
491
+ }
492
+ if (config.versions) {
493
+ const targetVersion = matchedRoute.version || config.versions.defaultVersion;
494
+ if (targetVersion !== currentVersion) setVersion(targetVersion);
495
+ }
496
+ } else if (config.versions && currentVersion !== config.versions.defaultVersion) setVersion(config.versions.defaultVersion);
360
497
  }, [
361
498
  location.pathname,
362
499
  config,
363
500
  routeMap,
501
+ currentLocale,
502
+ currentVersion,
364
503
  setLocale,
365
504
  setVersion
366
505
  ]);
367
506
  return null;
368
507
  }
369
- function BoltdocsShell({ config, routes, components = {}, collectionsData }) {
508
+ function BoltdocsShell({ config, routes, components = {}, collectionsData, contentClassName }) {
370
509
  const allComponents = (0, react.useMemo)(() => ({
371
510
  ...mdxComponentsDefault,
372
511
  ...virtual_boltdocs_mdx_components.default,
373
512
  ...components
374
513
  }), [components]);
375
- const { pathname } = (0, react_router_dom.useLocation)();
514
+ const { pathname } = require_router.useLocation();
376
515
  const currentPath = (0, react.useMemo)(() => require_link.normalizePath(pathname || "/"), [pathname]);
377
516
  const routeMap = (0, react.useMemo)(() => {
378
517
  const map = /* @__PURE__ */ new Map();
@@ -405,8 +544,8 @@ function BoltdocsShell({ config, routes, components = {}, collectionsData }) {
405
544
  components: allComponents,
406
545
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_link.ConfigContext.Provider, {
407
546
  value: config,
408
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(CollectionsContext.Provider, {
409
- value: collectionsData || {},
547
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(CollectionsProvider, {
548
+ collectionsData: collectionsData || {},
410
549
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ScrollHandler, {}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_link.BoltdocsProvider, {
411
550
  initialLocale: initialData.initLocale,
412
551
  initialVersion: initialData.initVersion,
@@ -421,9 +560,9 @@ function BoltdocsShell({ config, routes, components = {}, collectionsData }) {
421
560
  siteDescription: config.theme?.description,
422
561
  routes
423
562
  }),
424
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_search_dialog$1.InternalErrorBoundary, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
425
- className: "boltdocs-shell-content h-screen overflow-hidden",
426
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_router_dom.Outlet, {})
563
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_search_dialog.InternalErrorBoundary, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
564
+ className: require_link.cn("boltdocs-shell-content h-screen overflow-hidden", contentClassName),
565
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_router.Outlet, {})
427
566
  }) })
428
567
  ]
429
568
  })]
@@ -481,27 +620,31 @@ function DocPage({ route, content: Content, mdxComponents: propComponents }) {
481
620
  * - Otherwise, renders the standard `DocPage` layout.
482
621
  */
483
622
  function MdxPage({ MDXComponent, mdxComponents: propComponents, collectionPostComponent: CollectionPost }) {
484
- const data = (0, react_router_dom.useLoaderData)();
623
+ const data = require_router.useLoaderData();
624
+ const mdxComponents = {
625
+ ...useMdxComponents(),
626
+ ...propComponents
627
+ };
485
628
  if (!MDXComponent) return null;
486
- const collectionData = data;
487
- if (!!collectionData?.collection) {
629
+ const collectionData = data || {};
630
+ if (!!collectionData?.collection && !!collectionData?.route) {
488
631
  const postElement = CollectionPost ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CollectionPost, {
489
632
  MDXComponent,
490
- mdxComponents: propComponents
633
+ mdxComponents
491
634
  }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DocPage, {
492
635
  route: {
493
- path: collectionData.route.path,
494
- filePath: collectionData.route.filePath,
495
- title: collectionData.route.title,
496
- description: collectionData.route.description,
497
- headings: collectionData.headings,
498
- locale: collectionData.route.locale,
499
- version: collectionData.route.version,
500
- lastUpdated: collectionData.route.lastUpdated,
501
- frontmatter: collectionData.route.frontmatter
636
+ path: collectionData.route?.path || "",
637
+ filePath: collectionData.route?.filePath || "",
638
+ title: collectionData.route?.title,
639
+ description: collectionData.route?.description,
640
+ headings: collectionData.headings || [],
641
+ locale: collectionData.route?.locale,
642
+ version: collectionData.route?.version,
643
+ lastUpdated: collectionData.route?.lastUpdated,
644
+ frontmatter: collectionData.route?.frontmatter
502
645
  },
503
646
  content: MDXComponent,
504
- mdxComponents: propComponents
647
+ mdxComponents
505
648
  });
506
649
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CurrentPostProvider, {
507
650
  value: {
@@ -512,23 +655,23 @@ function MdxPage({ MDXComponent, mdxComponents: propComponents, collectionPostCo
512
655
  children: postElement
513
656
  });
514
657
  }
515
- const docData = data;
658
+ const docData = data || {};
516
659
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DocPage, {
517
660
  route: {
518
- path: docData.path,
519
- filePath: docData.filePath,
520
- title: docData.frontmatter?.title,
521
- description: docData.frontmatter?.description,
522
- headings: docData.headings,
523
- locale: docData.locale,
524
- version: docData.version,
525
- group: docData.group,
526
- groupTitle: docData.groupTitle,
527
- lastUpdated: docData.lastUpdated,
528
- frontmatter: docData.frontmatter
661
+ path: docData?.path || "",
662
+ filePath: docData?.filePath || "",
663
+ title: docData?.frontmatter?.title,
664
+ description: docData?.frontmatter?.description,
665
+ headings: docData?.headings || [],
666
+ locale: docData?.locale,
667
+ version: docData?.version,
668
+ group: docData?.group,
669
+ groupTitle: docData?.groupTitle,
670
+ lastUpdated: docData?.lastUpdated,
671
+ frontmatter: docData?.frontmatter
529
672
  },
530
673
  content: MDXComponent,
531
- mdxComponents: propComponents
674
+ mdxComponents
532
675
  });
533
676
  }
534
677
 
@@ -538,7 +681,7 @@ function MdxPage({ MDXComponent, mdxComponents: propComponents, collectionPostCo
538
681
  * Hook to generate breadcrumbs based on the current active route.
539
682
  */
540
683
  function useBreadcrumbs() {
541
- const { currentRoute: activeRoute } = require_link.useRoutes();
684
+ const { currentRoute: activeRoute } = require_search_dialog.useRoutes();
542
685
  const crumbs = [];
543
686
  if (activeRoute) {
544
687
  if (activeRoute.groupTitle) crumbs.push({ label: activeRoute.groupTitle });
@@ -555,11 +698,11 @@ function useBreadcrumbs() {
555
698
 
556
699
  //#endregion
557
700
  //#region src/client/components/ui-base/breadcrumbs.tsx
558
- function Breadcrumbs() {
701
+ function Breadcrumbs({ className }) {
559
702
  const { crumbs, activeRoute } = useBreadcrumbs();
560
703
  if (crumbs.length === 0) return null;
561
704
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_docs_layout.Breadcrumbs.Root, {
562
- className: "gap-2 text-xs sm:text-sm font-medium",
705
+ className: require_link.cn("gap-2 text-xs sm:text-sm font-medium", className),
563
706
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_docs_layout.Breadcrumbs.Item, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_docs_layout.Breadcrumbs.Link, {
564
707
  href: "/",
565
708
  className: "text-muted hover:text-body transition-colors flex items-center",
@@ -608,29 +751,29 @@ const useCopyMarkdown = (content) => {
608
751
  handleOpenRaw
609
752
  };
610
753
  };
611
- function CopyMarkdown({ content, mdxRaw }) {
754
+ function CopyMarkdown({ content, mdxRaw, className }) {
612
755
  const displayContent = mdxRaw || content || "";
613
756
  const { copied, handleCopy, handleOpenRaw } = useCopyMarkdown(displayContent);
614
757
  if (!displayContent) return null;
615
758
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
616
- className: "relative inline-flex z-100 shrink-0 w-max",
759
+ className: require_link.cn("relative inline-flex z-100 shrink-0 w-max", className),
617
760
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_docs_layout.ButtonGroup, {
618
761
  className: "rounded-xl border border-subtle bg-surface transition-all duration-300 hover:border-primary-500/50 group overflow-hidden",
619
762
  children: [
620
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_search_dialog.Button, {
763
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_search_dialog$1.Button, {
621
764
  onPress: handleCopy,
622
765
  className: require_link.cn("md:hidden flex items-center justify-center w-8 h-8 bg-transparent outline-none select-none cursor-pointer border-none", "text-muted transition-all duration-300 hover:bg-primary-500/5 hover:text-body", copied && "text-emerald-500 hover:bg-emerald-500/5"),
623
766
  "aria-label": copied ? "Copied!" : "Copy Markdown",
624
767
  children: copied ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_link.Check, { size: 14 }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_link.Copy, { size: 14 })
625
768
  }),
626
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_search_dialog.Button, {
769
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_search_dialog$1.Button, {
627
770
  onPress: handleCopy,
628
771
  className: require_link.cn("hidden md:flex items-center gap-2 px-5 py-2 bg-transparent text-[0.8125rem] font-semibold h-9 shrink-0 outline-none select-none cursor-pointer border-none", "text-body transition-all duration-300 hover:bg-primary-500/5", copied && "text-emerald-500 hover:bg-emerald-500/5"),
629
772
  children: [copied ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_link.Check, { size: 16 }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_link.Copy, { size: 16 }), copied ? "Copied!" : "Copy Markdown"]
630
773
  }),
631
774
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_docs_layout.Menu.Trigger, {
632
775
  placement: "bottom end",
633
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_search_dialog.Button, {
776
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_search_dialog$1.Button, {
634
777
  className: require_link.cn("flex items-center justify-center px-2.5 md:px-3.5 h-8 md:h-9 border-none border-l border-subtle/50 text-muted rounded-none bg-transparent shrink-0 outline-none select-none cursor-pointer", "transition-all duration-300 hover:bg-primary-500/5 hover:text-primary-500"),
635
778
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_link.ChevronDown, { size: 14 })
636
779
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_docs_layout.Menu.Root, {
@@ -666,7 +809,7 @@ function CopyMarkdown({ content, mdxRaw }) {
666
809
  //#endregion
667
810
  //#region src/client/components/ui-base/error-boundary.tsx
668
811
  function ErrorBoundary({ children, fallback }) {
669
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_search_dialog.ErrorBoundary, {
812
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_search_dialog$1.ErrorBoundary, {
670
813
  fallback,
671
814
  children
672
815
  });
@@ -705,7 +848,7 @@ const formatStars = (count) => {
705
848
 
706
849
  //#endregion
707
850
  //#region src/client/components/ui-base/github-stars.tsx
708
- function GithubStars({ repo }) {
851
+ function GithubStars({ repo, className }) {
709
852
  const [stars, setStars] = (0, react.useState)(null);
710
853
  (0, react.useEffect)(() => {
711
854
  if (repo) getStarsRepo(repo).then((stars) => setStars(stars)).catch(() => setStars("0"));
@@ -714,8 +857,8 @@ function GithubStars({ repo }) {
714
857
  href: `https://github.com/${repo}`,
715
858
  target: "_blank",
716
859
  rel: "noopener noreferrer",
717
- className: "inline-flex items-center gap-2 rounded-xl border border-subtle bg-surface px-3 py-1.5 text-xs font-semibold text-muted dark:hover:bg-primary-300/50 hover:bg-primary-200/50 transition-colors duration-100 hover:border-primary-500/50 hover:text-body select-none outline-none",
718
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_search_dialog.Github, { className: "h-4 w-4 text-body" }), stars !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
860
+ className: require_link.cn("inline-flex items-center gap-2 rounded-xl border border-subtle bg-surface px-3 py-1.5 text-xs font-semibold text-muted dark:hover:bg-primary-300/50 hover:bg-primary-200/50 transition-colors duration-100 hover:border-primary-500/50 hover:text-body select-none outline-none", className),
861
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_search_dialog$1.Github, { className: "h-4 w-4 text-body" }), stars !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
719
862
  className: "tabular-nums font-medium",
720
863
  children: [stars, " stars"]
721
864
  })]
@@ -727,8 +870,8 @@ function GithubStars({ repo }) {
727
870
  function useNavbar() {
728
871
  const config = require_link.useConfig();
729
872
  const { theme, resolvedTheme } = require_image.useTheme();
730
- const location = (0, react_router_dom.useLocation)();
731
- const { currentLocale } = require_link.useRoutes();
873
+ const location = require_router.useLocation();
874
+ const { currentLocale } = require_search_dialog.useRoutes();
732
875
  const themeConfig = config.theme || {};
733
876
  const title = getTranslated(themeConfig.title, currentLocale) || "Boltdocs";
734
877
  const rawLinks = themeConfig.navbar || [];
@@ -802,18 +945,18 @@ function useNavbar() {
802
945
 
803
946
  //#endregion
804
947
  //#region src/client/components/ui-base/theme-toggle.tsx
805
- function ThemeToggle() {
948
+ function ThemeToggle({ className }) {
806
949
  const { theme, setTheme } = require_image.useTheme();
807
950
  const [mounted, setMounted] = (0, react.useState)(false);
808
951
  (0, react.useEffect)(() => {
809
952
  setMounted(true);
810
953
  }, []);
811
- if (!mounted) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: "h-9 w-9" });
954
+ if (!mounted) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: require_link.cn("h-9 w-9", className) });
812
955
  const Icon = theme === "system" ? require_link.Monitor : theme === "dark" ? require_link.Moon : require_link.Sun;
813
956
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_docs_layout.Menu.Trigger, {
814
957
  placement: "bottom right",
815
958
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_aria_components.Button, {
816
- className: "flex h-9 w-9 items-center justify-center rounded-xl text-muted transition-colors hover:bg-surface hover:text-body outline-none border-none bg-transparent cursor-pointer",
959
+ className: require_link.cn("flex h-9 w-9 items-center justify-center rounded-xl text-muted transition-colors hover:bg-surface hover:text-body outline-none border-none bg-transparent cursor-pointer", className),
817
960
  "aria-label": "Selection theme",
818
961
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Icon, {
819
962
  size: 20,
@@ -896,7 +1039,7 @@ function ThemeSwitcher({ className }) {
896
1039
  //#endregion
897
1040
  //#region src/client/hooks/use-tabs.ts
898
1041
  function useTabs(tabs = [], routes = []) {
899
- const location = (0, react_router_dom.useLocation)();
1042
+ const location = require_router.useLocation();
900
1043
  const tabRefs = (0, react.useRef)([]);
901
1044
  const [indicatorStyle, setIndicatorStyle] = (0, react.useState)({
902
1045
  opacity: 0,
@@ -930,9 +1073,11 @@ function useTabs(tabs = [], routes = []) {
930
1073
 
931
1074
  //#endregion
932
1075
  //#region src/client/components/ui-base/tabs.tsx
933
- function Tabs({ tabs, routes }) {
934
- const { currentLocale } = require_link.useRoutes();
1076
+ function Tabs({ tabs, routes, allRoutes, className }) {
1077
+ const { currentLocale } = require_search_dialog.useRoutes();
935
1078
  const { indicatorStyle, tabRefs, activeIndex } = useTabs(tabs, routes);
1079
+ const routeCandidates = routes;
1080
+ const fallbackRouteCandidates = allRoutes || [];
936
1081
  (0, react.useEffect)(() => {
937
1082
  const activeTab = tabRefs.current[activeIndex];
938
1083
  if (activeTab) activeTab.scrollIntoView({
@@ -940,32 +1085,18 @@ function Tabs({ tabs, routes }) {
940
1085
  block: "nearest",
941
1086
  inline: "center"
942
1087
  });
943
- }, [activeIndex]);
944
- const renderTabIcon = (iconName) => {
945
- if (!iconName) return null;
946
- if (iconName.trim().startsWith("<svg")) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
947
- className: "h-4 w-4",
948
- dangerouslySetInnerHTML: { __html: isomorphic_dompurify.default.sanitize(iconName, { USE_PROFILES: { svg: true } }) }
949
- });
950
- const icons = {
951
- ...require_link.icons_exports,
952
- ...virtual_boltdocs_icons.default
953
- };
954
- const TabIcon = icons[iconName] || icons[iconName + "Icon"];
955
- if (TabIcon) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TabIcon, { size: 16 });
956
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("img", {
957
- src: iconName,
958
- alt: "",
959
- className: "h-4 w-4 object-contain"
960
- });
961
- };
1088
+ }, [activeIndex, tabRefs]);
1089
+ const renderTabIcon = (iconName) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_docs_layout.IconRenderer, {
1090
+ icon: require_docs_layout.resolveIcon(iconName),
1091
+ size: 16
1092
+ });
962
1093
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
963
- className: "mx-auto max-w-(--breakpoint-3xl) px-4 md:px-6 select-none",
1094
+ className: require_link.cn("mx-auto max-w-(--breakpoint-3xl) px-4 md:px-6 select-none", className),
964
1095
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_docs_layout.Tabs.List, {
965
1096
  className: "border-none py-0 scrollbar-hide relative flex flex-row items-center overflow-x-auto",
966
1097
  children: [tabs.map((tab, index) => {
967
1098
  const isActive = index === activeIndex;
968
- const firstRoute = routes.find((r) => r.tab && r.tab.toLowerCase() === tab.id.toLowerCase());
1099
+ const firstRoute = routeCandidates.find((r) => r.tab && r.tab.toLowerCase() === tab.id.toLowerCase()) || fallbackRouteCandidates.find((r) => r.tab && r.tab.toLowerCase() === tab.id.toLowerCase());
969
1100
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_link.Link, {
970
1101
  href: firstRoute ? firstRoute.path : "#",
971
1102
  ref: (el) => {
@@ -1004,9 +1135,9 @@ function getBaseFilePath(filePath, version, locale) {
1004
1135
  * Hook to manage and switch between different versions of the documentation.
1005
1136
  */
1006
1137
  function useVersion() {
1007
- const navigate = (0, react_router_dom.useNavigate)();
1138
+ const navigate = require_router.useNavigate();
1008
1139
  const config = require_link.useConfig();
1009
- const { allRoutes, currentRoute, currentVersion, currentLocale } = require_link.useRoutes();
1140
+ const { allRoutes, currentRoute, currentVersion, currentLocale } = require_search_dialog.useRoutes();
1010
1141
  const versions = config.versions;
1011
1142
  const { setVersion } = require_link.useBoltdocsContext();
1012
1143
  const handleVersionChange = (version) => {
@@ -1047,7 +1178,7 @@ function useVersion() {
1047
1178
  function VersionSelector({ className }) {
1048
1179
  const { currentVersionLabel, availableVersions, handleVersionChange } = useVersion();
1049
1180
  if (availableVersions.length === 0) return null;
1050
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_docs_layout.Menu.Trigger, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_search_dialog.Button, {
1181
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_docs_layout.Menu.Trigger, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_search_dialog$1.Button, {
1051
1182
  className: require_link.cn("flex h-9 items-center justify-between gap-2 border border-subtle bg-surface px-4 py-1.5 rounded-xl text-xs font-semibold text-body hover:bg-primary-50/20 hover:border-primary-500/50 transition-all duration-300 outline-none select-none cursor-pointer", className),
1052
1183
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1053
1184
  className: "font-semibold text-[0.8125rem]",
@@ -1072,9 +1203,10 @@ function VersionSelector({ className }) {
1072
1203
  * Hook to manage and switch between different locales (languages) of the documentation.
1073
1204
  */
1074
1205
  function useI18n() {
1075
- const navigate = (0, react_router_dom.useNavigate)();
1206
+ const navigate = require_router.useNavigate();
1207
+ const location = require_router.useLocation();
1076
1208
  const config = require_link.useConfig();
1077
- const { allRoutes, currentRoute, currentLocale, isCollectionPage } = require_link.useRoutes();
1209
+ const { allRoutes, currentRoute, currentLocale, isCollectionPage } = require_search_dialog.useRoutes();
1078
1210
  const i18n = config.i18n;
1079
1211
  const { setLocale } = require_link.useBoltdocsContext();
1080
1212
  const handleLocaleChange = (locale) => {
@@ -1085,16 +1217,16 @@ function useI18n() {
1085
1217
  const isDocRoute = !!currentRoute?.filePath;
1086
1218
  let targetPath = "";
1087
1219
  if (currentRoute) if (isDocRoute && !currentRoute.collection && !isCollectionPage) {
1088
- const baseFile = getBaseFilePath(currentRoute.filePath, currentRoute.version, currentRoute.locale);
1089
- const targetRoute = allRoutes.find((r) => getBaseFilePath(r.filePath, r.version, r.locale) === baseFile && (r.locale || i18n.defaultLocale) === locale && r.version === currentRoute.version);
1220
+ const baseFile = currentRoute.filePath ? getBaseFilePath(currentRoute.filePath, currentRoute.version, currentRoute.locale) : "";
1221
+ const targetRoute = allRoutes.find((r) => r.filePath && getBaseFilePath(r.filePath, r.version, r.locale) === baseFile && (r.locale || i18n.defaultLocale) === locale && r.version === currentRoute.version);
1090
1222
  if (targetRoute) targetPath = targetRoute.path;
1091
1223
  else {
1092
- const defaultIndexRoute = allRoutes.find((r) => getBaseFilePath(r.filePath, r.version, r.locale) === "index.md" && (r.locale || i18n.defaultLocale) === locale && r.version === currentRoute.version);
1224
+ const defaultIndexRoute = allRoutes.find((r) => r.filePath && ["index.md", "_index.md"].includes(getBaseFilePath(r.filePath, r.version, r.locale)) && (r.locale || i18n.defaultLocale) === locale && r.version === currentRoute.version);
1093
1225
  if (defaultIndexRoute) targetPath = defaultIndexRoute.path;
1094
1226
  else targetPath = `${safeBase}${currentRoute.version ? `/${currentRoute.version}` : ""}${locale === i18n.defaultLocale ? "" : `/${locale}`}` || "/";
1095
1227
  }
1096
1228
  } else {
1097
- let rawExternal = currentRoute.path;
1229
+ let rawExternal = currentRoute.path || "";
1098
1230
  const parts = rawExternal.split("/").filter(Boolean);
1099
1231
  const localePosition = currentRoute.collection ? 1 : 0;
1100
1232
  if (parts.length > localePosition && (Array.isArray(i18n.locales) ? i18n.locales.includes(parts[localePosition]) : !!i18n.locales[parts[localePosition]])) {
@@ -1118,7 +1250,7 @@ function useI18n() {
1118
1250
  targetPath = "/" + parts.join("/");
1119
1251
  }
1120
1252
  }
1121
- if (!targetPath || targetPath === "") targetPath = "/s";
1253
+ if (!targetPath || targetPath === "") targetPath = "/";
1122
1254
  targetPath = targetPath.replace(/\/+/g, "/");
1123
1255
  navigate(targetPath);
1124
1256
  };
@@ -1151,8 +1283,8 @@ function useI18n() {
1151
1283
  //#endregion
1152
1284
  //#region src/client/hooks/use-page-nav.ts
1153
1285
  function usePageNav() {
1154
- const { routes, currentRoute } = require_link.useRoutes();
1155
- const location = (0, react_router_dom.useLocation)();
1286
+ const { routes, currentRoute } = require_search_dialog.useRoutes();
1287
+ const location = require_router.useLocation();
1156
1288
  const { groups, ungrouped } = require_docs_layout.useSidebar(routes);
1157
1289
  return (0, react.useMemo)(() => {
1158
1290
  if (!currentRoute) return {
@@ -1177,14 +1309,20 @@ function usePageNav() {
1177
1309
  });
1178
1310
  const orderedRoutes = [];
1179
1311
  const flattenNode = (node) => {
1312
+ if (!node) return;
1180
1313
  if (node.path && node.path !== "#" && !node.sidebarHidden) orderedRoutes.push(node);
1181
1314
  const children = node.routes || node.subRoutes;
1182
- if (children && children.length > 0) for (const child of children) flattenNode(child);
1315
+ if (children && children.length > 0) {
1316
+ for (const child of children) if (child) flattenNode(child);
1317
+ }
1183
1318
  };
1184
- for (const item of mergedItems) if (item.type === "link") flattenNode(item.route);
1185
- else if (item.group.routes) for (const route of item.group.routes) flattenNode(route);
1319
+ for (const item of mergedItems) if (item.type === "link") {
1320
+ if (item.route) flattenNode(item.route);
1321
+ } else if (item.group.routes) {
1322
+ for (const route of item.group.routes) if (route) flattenNode(route);
1323
+ }
1186
1324
  const currentNormalizedPath = require_link.normalizePath(location.pathname);
1187
- const currentIndex = orderedRoutes.findIndex((r) => require_link.normalizePath(r.path) === currentNormalizedPath);
1325
+ const currentIndex = orderedRoutes.findIndex((r) => r && r.path && require_link.normalizePath(r.path) === currentNormalizedPath);
1188
1326
  return {
1189
1327
  prevPage: currentIndex > 0 ? orderedRoutes[currentIndex - 1] : null,
1190
1328
  nextPage: currentIndex !== -1 && currentIndex < orderedRoutes.length - 1 ? orderedRoutes[currentIndex + 1] : null,
@@ -1342,16 +1480,17 @@ function useAnalytics(options = {}) {
1342
1480
  const config = optionsConfig ?? globalConfig?.integrations;
1343
1481
  const analytics = (0, react.useMemo)(() => createAnalyticsInstance(config), [config]);
1344
1482
  const previousPath = (0, react.useRef)("");
1345
- const location = require_docs_layout.useLocation();
1483
+ const { pathname, search } = location;
1346
1484
  (0, react.useEffect)(() => {
1347
1485
  if (!autoTrackPageViews || !analytics.isEnabled) return;
1348
- const path = location.pathname + location.search;
1486
+ const path = pathname + search;
1349
1487
  if (path !== previousPath.current) {
1350
1488
  previousPath.current = path;
1351
1489
  analytics.trackPageView(path, document.title);
1352
1490
  }
1353
1491
  }, [
1354
- location.pathname,
1492
+ pathname,
1493
+ search,
1355
1494
  autoTrackPageViews,
1356
1495
  analytics
1357
1496
  ]);
@@ -1372,7 +1511,6 @@ function useAnalytics(options = {}) {
1372
1511
  return () => document.removeEventListener("click", handleClick);
1373
1512
  }, [
1374
1513
  autoTrackDownloads,
1375
- autoTrackExternalLinks,
1376
1514
  analytics,
1377
1515
  excludePatterns
1378
1516
  ]);
@@ -1417,7 +1555,7 @@ function useTrackEvent() {
1417
1555
  * @returns An array of heading objects with level, text, and id.
1418
1556
  */
1419
1557
  function useHeadings() {
1420
- const matches = (0, react_router_dom.useMatches)();
1558
+ const matches = require_router.useMatches();
1421
1559
  return (0, react.useMemo)(() => {
1422
1560
  return (matches[matches.length - 1]?.data)?.headings || [];
1423
1561
  }, [matches]);
@@ -1431,18 +1569,19 @@ function useHeadings() {
1431
1569
  */
1432
1570
  function useFeedback(options = {}) {
1433
1571
  const config = require_link.useConfig();
1434
- const { currentRoute } = require_link.useRoutes();
1572
+ const { currentRoute } = require_search_dialog.useRoutes();
1435
1573
  const [rating, setRating] = (0, react.useState)(null);
1436
1574
  const [comment, setComment] = (0, react.useState)("");
1437
1575
  const [loading, setLoading] = (0, react.useState)(false);
1438
1576
  const [submitted, setSubmitted] = (0, react.useState)(false);
1439
1577
  const [error, setError] = (0, react.useState)(null);
1578
+ const routePath = currentRoute?.path;
1440
1579
  (0, react.useEffect)(() => {
1441
1580
  setRating(null);
1442
1581
  setComment("");
1443
1582
  setSubmitted(false);
1444
1583
  setError(null);
1445
- }, [currentRoute?.path]);
1584
+ }, [routePath]);
1446
1585
  const submit = async (commentOverride, blockId) => {
1447
1586
  if (!rating) return;
1448
1587
  setLoading(true);
@@ -1497,7 +1636,7 @@ function useFeedback(options = {}) {
1497
1636
  function I18nSelector({ className }) {
1498
1637
  const { currentLocale, availableLocales, handleLocaleChange } = useI18n();
1499
1638
  if (availableLocales.length === 0) return null;
1500
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_docs_layout.Menu.Trigger, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_search_dialog.Button, {
1639
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_docs_layout.Menu.Trigger, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_search_dialog$1.Button, {
1501
1640
  className: require_link.cn("flex h-9 items-center justify-between gap-2 border border-subtle bg-surface px-4 py-1.5 rounded-xl text-xs font-semibold text-body hover:bg-primary-50/20 hover:border-primary-500/50 transition-all duration-300 outline-none select-none cursor-pointer", className),
1502
1641
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1503
1642
  className: "flex items-center gap-1.5",
@@ -1521,34 +1660,34 @@ function I18nSelector({ className }) {
1521
1660
 
1522
1661
  //#endregion
1523
1662
  //#region src/client/components/ui-base/navbar.tsx
1524
- const SearchDialog$1 = (0, react.lazy)(() => Promise.resolve().then(() => require("../search-dialog-DHqwjJuG.cjs")).then((m) => ({ default: m.SearchDialog })));
1525
- function Navbar() {
1663
+ const SearchDialog$1 = (0, react.lazy)(() => Promise.resolve().then(() => require("../search-dialog-DmirOMPg.cjs")).then((m) => ({ default: m.SearchDialog })));
1664
+ function Navbar({ className }) {
1526
1665
  const { links, title, logo, logoProps, github, social, config } = useNavbar();
1527
- const { routes, currentRoute, isCollectionPage, currentVersion, currentLocale } = require_link.useRoutes();
1666
+ const { routes, allRoutes, currentRoute, isCollectionPage, currentVersion, currentLocale } = require_search_dialog.useRoutes();
1528
1667
  const { isSidebarOpen, toggleSidebar } = require_docs_layout.useUI();
1529
1668
  const [isMobileMenuOpen, setIsMobileMenuOpen] = (0, react.useState)(false);
1530
1669
  const themeConfig = config.theme;
1531
1670
  const isDocs = !!currentRoute?.filePath && !isCollectionPage;
1532
1671
  const hasTabs = themeConfig?.tabs && themeConfig.tabs.length > 0;
1533
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_search_dialog.Navbar.Root, {
1534
- className: require_link.cn("border-b border-subtle bg-main/80 backdrop-blur-md", hasTabs && "border-b-0"),
1672
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_search_dialog$1.Navbar.Root, {
1673
+ className: require_link.cn("border-b border-subtle bg-main/80 backdrop-blur-md", hasTabs && "border-b-0", className),
1535
1674
  children: [
1536
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_search_dialog.Navbar.Content, { children: [
1537
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_search_dialog.Navbar.Left, { children: [
1538
- isDocs && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_search_dialog.Button, {
1675
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_search_dialog$1.Navbar.Content, { children: [
1676
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_search_dialog$1.Navbar.Left, { children: [
1677
+ isDocs && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_search_dialog$1.Button, {
1539
1678
  onPress: toggleSidebar,
1540
1679
  className: "mr-2 lg:hidden p-1.5 h-8 w-8 flex items-center justify-center bg-transparent border-none outline-none select-none cursor-pointer rounded-xl hover:bg-primary-50/50 transition-colors",
1541
1680
  "aria-label": isSidebarOpen ? "Close sidebar" : "Open sidebar",
1542
1681
  children: isSidebarOpen ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_link.X, { className: "w-5 h-5 text-body" }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_link.Menu, { className: "w-5 h-5 text-body" })
1543
1682
  }),
1544
- logo && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_search_dialog.Navbar.Logo, {
1683
+ logo && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_search_dialog$1.Navbar.Logo, {
1545
1684
  src: logo,
1546
1685
  alt: logoProps?.alt || title,
1547
1686
  width: logoProps?.width ?? 24,
1548
1687
  height: logoProps?.height ?? 24,
1549
1688
  href: "site:/"
1550
1689
  }),
1551
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_search_dialog.Navbar.Title, {
1690
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_search_dialog$1.Navbar.Title, {
1552
1691
  href: "site:/",
1553
1692
  children: title
1554
1693
  }),
@@ -1561,14 +1700,14 @@ function Navbar() {
1561
1700
  children: config.versions && currentVersion && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(VersionSelector, {})
1562
1701
  })
1563
1702
  ] }),
1564
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_search_dialog.Navbar.Center, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1703
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_search_dialog$1.Navbar.Center, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1565
1704
  className: "flex items-center gap-2",
1566
1705
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react.Suspense, {
1567
1706
  fallback: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: "h-9 w-32 animate-pulse rounded-md bg-surface" }),
1568
1707
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SearchDialog$1, { routes: routes || [] })
1569
1708
  })
1570
1709
  }) }),
1571
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_search_dialog.Navbar.Right, { children: [
1710
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_search_dialog$1.Navbar.Right, { children: [
1572
1711
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react.Suspense, {
1573
1712
  fallback: null,
1574
1713
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
@@ -1576,10 +1715,10 @@ function Navbar() {
1576
1715
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SearchDialog$1, { routes: routes || [] })
1577
1716
  })
1578
1717
  }),
1579
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_search_dialog.Navbar.Links, { children: links.map((link) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(NavbarLinkItem, { link }, link.href)) }),
1718
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_search_dialog$1.Navbar.Links, { children: links.map((link) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(NavbarLinkItem, { link }, link.href)) }),
1580
1719
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1581
1720
  className: "hidden sm:flex items-center gap-2",
1582
- children: [config.i18n && currentLocale && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(I18nSelector, {}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_search_dialog.Navbar.Split, { className: "bg-subtle" })]
1721
+ children: [config.i18n && currentLocale && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(I18nSelector, {}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_search_dialog$1.Navbar.Split, { className: "bg-subtle" })]
1583
1722
  }),
1584
1723
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1585
1724
  className: "hidden md:block",
@@ -1591,23 +1730,23 @@ function Navbar() {
1591
1730
  }),
1592
1731
  social.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1593
1732
  className: "hidden md:block",
1594
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_search_dialog.Navbar.Split, { className: "bg-subtle" })
1733
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_search_dialog$1.Navbar.Split, { className: "bg-subtle" })
1595
1734
  }),
1596
1735
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1597
1736
  className: "hidden md:flex items-center gap-1",
1598
- children: social.map(({ icon, link }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_search_dialog.Navbar.Socials, {
1737
+ children: social.map(({ icon, link }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_search_dialog$1.Navbar.Socials, {
1599
1738
  icon,
1600
1739
  link,
1601
1740
  className: "p-1.5 text-muted hover:text-body hover:bg-surface rounded-md transition-all focus-visible:ring-2 focus-visible:ring-primary-500/30"
1602
1741
  }, link))
1603
1742
  }),
1604
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_search_dialog.Navbar.More, {
1743
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_search_dialog$1.Navbar.More, {
1605
1744
  onPress: () => setIsMobileMenuOpen(true),
1606
1745
  className: "text-muted hover:text-body active:scale-90 transition-all focus-visible:ring-2 focus-visible:ring-primary-500/30"
1607
1746
  })
1608
1747
  ] })
1609
1748
  ] }),
1610
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_search_dialog.Navbar.MobileMenu, {
1749
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_search_dialog$1.Navbar.MobileMenu, {
1611
1750
  isOpen: isMobileMenuOpen,
1612
1751
  onClose: () => setIsMobileMenuOpen(false),
1613
1752
  className: "bg-main/98 backdrop-blur-2xl",
@@ -1624,7 +1763,7 @@ function Navbar() {
1624
1763
  children: "Connect"
1625
1764
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1626
1765
  className: "flex flex-wrap gap-2 px-2",
1627
- children: social.map(({ icon, link }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_search_dialog.Navbar.Socials, {
1766
+ children: social.map(({ icon, link }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_search_dialog$1.Navbar.Socials, {
1628
1767
  icon,
1629
1768
  link,
1630
1769
  className: "p-3 bg-surface border border-subtle rounded-xl flex-1 justify-center"
@@ -1636,7 +1775,8 @@ function Navbar() {
1636
1775
  className: "w-full border-b border-subtle bg-main",
1637
1776
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Tabs, {
1638
1777
  tabs: themeConfig.tabs,
1639
- routes: routes || []
1778
+ routes: routes || [],
1779
+ allRoutes: allRoutes || []
1640
1780
  })
1641
1781
  })
1642
1782
  ]
@@ -1644,19 +1784,19 @@ function Navbar() {
1644
1784
  }
1645
1785
  function NavbarLinkItem({ link }) {
1646
1786
  const localizedHref = require_link.useLocalizedTo(link.href || "");
1647
- const { pathname } = (0, react_router_dom.useLocation)();
1787
+ const { pathname } = require_router.useLocation();
1648
1788
  const active = pathname === localizedHref || pathname.startsWith(`${localizedHref}/`);
1649
- if (link.items && link.items.length > 0) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_search_dialog.Navbar.Dropdown, {
1789
+ if (link.items && link.items.length > 0) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_search_dialog$1.Navbar.Dropdown, {
1650
1790
  label: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1651
1791
  className: require_link.cn("transition-colors outline-none font-medium focus-visible:ring-2 focus-visible:ring-primary-500/30 rounded-sm px-2 py-1", active ? "text-primary-500" : "text-muted hover:text-body"),
1652
1792
  children: link.label
1653
1793
  }),
1654
- children: link.items?.map((item) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_search_dialog.Navbar.DropdownItem, {
1794
+ children: link.items?.map((item) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_search_dialog$1.Navbar.DropdownItem, {
1655
1795
  href: require_link.useLocalizedTo(item.href || ""),
1656
1796
  label: item.label
1657
1797
  }, item.href))
1658
1798
  });
1659
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_search_dialog.Navbar.Link, {
1799
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_search_dialog$1.Navbar.Link, {
1660
1800
  ...link,
1661
1801
  href: localizedHref,
1662
1802
  active,
@@ -1664,70 +1804,58 @@ function NavbarLinkItem({ link }) {
1664
1804
  });
1665
1805
  }
1666
1806
  function NavbarMobileLinkItem({ link, onClose }) {
1667
- const localizedHref = require_link.useLocalizedTo(link.href || "");
1668
- const { pathname } = (0, react_router_dom.useLocation)();
1669
- const active = pathname === localizedHref;
1670
- if (link.items && link.items.length > 0) return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1671
- className: "flex flex-col gap-1",
1672
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1673
- className: require_link.cn("px-3 py-2 text-sm transition-all", active ? "text-body" : "text-muted/80 hover:text-body"),
1674
- children: link.label
1675
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1676
- className: "flex flex-col gap-1 pl-4",
1677
- children: link.items?.map((item) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(NavbarMobileLinkItem, {
1678
- link: item,
1679
- onClose
1680
- }, item.href))
1681
- })]
1682
- });
1683
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_search_dialog.Navbar.MobileLink, {
1684
- ...link,
1685
- href: localizedHref,
1686
- active,
1687
- onPress: onClose,
1688
- className: require_link.cn("transition-all", active ? "text-body" : "text-muted/80 hover:text-body")
1807
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_search_dialog$1.Navbar.MobileLinkItem, {
1808
+ link,
1809
+ onClose
1689
1810
  });
1690
1811
  }
1691
1812
 
1692
1813
  //#endregion
1693
1814
  //#region src/client/components/ui-base/on-this-page.tsx
1694
- function OnThisPage({ headings = [], editLink, communityHelp, filePath }) {
1815
+ function OnThisPage({ headings = [], editLink, communityHelp, filePath, className }) {
1695
1816
  if (headings.length === 0) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("nav", {
1696
- className: "w-toc shrink-0 hidden xl:block",
1817
+ className: require_link.cn("w-toc shrink-0 hidden xl:block", className),
1697
1818
  "aria-hidden": "true"
1698
1819
  });
1699
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_docs_layout.OnThisPage.Root, { children: [
1700
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_docs_layout.OnThisPage.Header, {
1701
- className: "flex flex-row gap-x-2",
1702
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_link.TextAlignStart, { size: 16 }), "On this page"]
1703
- }),
1704
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_docs_layout.OnThisPage.Tree, {
1705
- className: "max-h-[300px]",
1706
- headings
1707
- }),
1708
- (editLink || communityHelp) && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1709
- className: "mt-8 pt-8 border-t border-subtle space-y-4",
1710
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
1711
- className: "text-xs font-bold text-body",
1712
- children: "Need help?"
1713
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("ul", {
1714
- className: "space-y-3",
1715
- children: [editLink && filePath && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("a", {
1716
- href: editLink.replace(":path", filePath),
1717
- target: "_blank",
1718
- rel: "noopener noreferrer",
1719
- className: "flex items-center gap-2 text-sm text-muted hover:text-body transition-colors",
1720
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_link.Pencil, { size: 16 }), "Edit this page"]
1721
- }) }), communityHelp && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("a", {
1722
- href: communityHelp,
1723
- target: "_blank",
1724
- rel: "noopener noreferrer",
1725
- className: "flex items-center gap-2 text-sm text-muted hover:text-body transition-colors",
1726
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_link.CircleHelp, { size: 16 }), "Community help"]
1727
- }) })]
1728
- })]
1729
- })
1730
- ] });
1820
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_docs_layout.OnThisPage.Root, {
1821
+ className: require_link.cn("sticky top-navbar hidden xl:flex flex-col shrink-0 w-toc py-4 pl-6 pr-4", className),
1822
+ children: [
1823
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_docs_layout.OnThisPage.Header, {
1824
+ className: "mb-4 text-xs font-bold text-body flex flex-row gap-x-2",
1825
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_link.TextAlignStart, { size: 16 }), "On this page"]
1826
+ }),
1827
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_docs_layout.OnThisPage.Tree, {
1828
+ className: "space-y-0.5 text-sm border-l border-subtle",
1829
+ itemClassName: "data-[level=3]:pl-3",
1830
+ linkClassName: "block py-0.5 pl-4 text-[13px] outline-none transition-colors text-muted hover:text-body data-active:text-primary-500",
1831
+ indicatorClassName: "-left-px w-0.5 rounded-full bg-primary-500",
1832
+ fadeClassName: "bg-linear-to-b from-transparent to-main",
1833
+ headings
1834
+ }),
1835
+ (editLink || communityHelp) && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1836
+ className: "mt-8 pt-8 border-t border-subtle space-y-4",
1837
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
1838
+ className: "text-xs font-bold text-body",
1839
+ children: "Need help?"
1840
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("ul", {
1841
+ className: "space-y-3",
1842
+ children: [editLink && filePath && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("a", {
1843
+ href: editLink.replace(":path", filePath),
1844
+ target: "_blank",
1845
+ rel: "noopener noreferrer",
1846
+ className: "flex items-center gap-2 text-sm text-muted hover:text-body transition-colors",
1847
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_link.Pencil, { size: 16 }), "Edit this page"]
1848
+ }) }), communityHelp && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("a", {
1849
+ href: communityHelp,
1850
+ target: "_blank",
1851
+ rel: "noopener noreferrer",
1852
+ className: "flex items-center gap-2 text-sm text-muted hover:text-body transition-colors",
1853
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_link.CircleHelp, { size: 16 }), "Community help"]
1854
+ }) })]
1855
+ })]
1856
+ })
1857
+ ]
1858
+ });
1731
1859
  }
1732
1860
 
1733
1861
  //#endregion
@@ -1736,32 +1864,44 @@ function OnThisPage({ headings = [], editLink, communityHelp, filePath }) {
1736
1864
  * Component to display the previous and next page navigation buttons.
1737
1865
  * Enhanced with subtle entrance animations, modern card layout, and hover highlights.
1738
1866
  */
1739
- function PageNav() {
1867
+ function PageNav({ className }) {
1740
1868
  const { prevPage, nextPage } = usePageNav();
1741
1869
  if (!prevPage && !nextPage) return null;
1742
1870
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_docs_layout.PageNav.Root, {
1743
- className: "pt-8 border-t border-subtle grid sm:grid-cols-2 gap-4 animate-in fade-in slide-in-from-bottom-4 duration-700 select-none",
1871
+ className: require_link.cn("pt-8 border-t border-subtle grid sm:grid-cols-2 gap-4 animate-in fade-in slide-in-from-bottom-4 duration-700 select-none", className),
1744
1872
  children: [prevPage ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_docs_layout.PageNav.Link, {
1745
1873
  to: prevPage.path,
1746
1874
  direction: "prev",
1747
1875
  className: "group border border-subtle bg-surface p-5 rounded-2xl transition-all duration-300 hover:border-primary-500/50 hover:bg-primary-50/20",
1748
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_docs_layout.PageNav.Title, {
1749
- className: "text-xs font-bold uppercase tracking-wider text-muted/60 mb-1",
1750
- children: "Previous"
1751
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_docs_layout.PageNav.Description, {
1752
- className: "text-sm sm:text-base font-bold text-body group-hover:text-primary-500 transition-colors",
1753
- children: prevPage.title
1876
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_docs_layout.PageNav.Icon, {
1877
+ className: "text-muted/60 shrink-0",
1878
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_link.ChevronLeft, {})
1879
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1880
+ className: "flex flex-col",
1881
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_docs_layout.PageNav.Title, {
1882
+ className: "text-xs font-bold uppercase tracking-wider text-muted/60 mb-1",
1883
+ children: "Previous"
1884
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_docs_layout.PageNav.Description, {
1885
+ className: "text-sm sm:text-base font-bold text-body group-hover:text-primary-500 transition-colors",
1886
+ children: prevPage.title
1887
+ })]
1754
1888
  })]
1755
1889
  }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {}), nextPage ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_docs_layout.PageNav.Link, {
1756
1890
  to: nextPage.path,
1757
1891
  direction: "next",
1758
1892
  className: "group border border-subtle bg-surface p-5 rounded-2xl transition-all duration-300 hover:border-primary-500/50 hover:bg-primary-50/20",
1759
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_docs_layout.PageNav.Title, {
1760
- className: "text-xs font-bold uppercase tracking-wider text-muted/60 mb-1",
1761
- children: "Next"
1762
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_docs_layout.PageNav.Description, {
1763
- className: "text-sm sm:text-base font-bold text-body group-hover:text-primary-500 transition-colors",
1764
- children: nextPage.title
1893
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1894
+ className: "flex flex-col",
1895
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_docs_layout.PageNav.Title, {
1896
+ className: "text-xs font-bold uppercase tracking-wider text-muted/60 mb-1",
1897
+ children: "Next"
1898
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_docs_layout.PageNav.Description, {
1899
+ className: "text-sm sm:text-base font-bold text-body group-hover:text-primary-500 transition-colors",
1900
+ children: nextPage.title
1901
+ })]
1902
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_docs_layout.PageNav.Icon, {
1903
+ className: "text-muted/60 shrink-0",
1904
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_link.ChevronRight, {})
1765
1905
  })]
1766
1906
  }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {})]
1767
1907
  });
@@ -1769,38 +1909,90 @@ function PageNav() {
1769
1909
 
1770
1910
  //#endregion
1771
1911
  //#region src/client/components/ui-base/sidebar.tsx
1772
- function SidebarMain({ routes, config }) {
1912
+ /**
1913
+ * Default look for the sidebar tree. States are driven by the primitive's
1914
+ * `data-*` attributes (`data-active`, `data-open`, `data-badge`).
1915
+ */
1916
+ const defaultItemsClassNames = {
1917
+ item: "rounded-lg px-2.5 py-1.5 text-sm transition-all text-muted hover:bg-surface hover:text-body data-active:bg-primary-500/10 data-active:text-primary-500 data-active:font-medium data-active:shadow-sm",
1918
+ groupHeader: "px-2 mb-2 text-[11px] font-bold uppercase tracking-widest text-muted/50",
1919
+ groupContent: "gap-0.5",
1920
+ subgroup: "gap-0.5",
1921
+ subgroupLink: "rounded-lg px-2.5 py-1.5 text-sm transition-all text-muted hover:bg-surface hover:text-body data-active:bg-primary-500/10 data-active:text-primary-500 data-active:font-medium data-active:shadow-sm",
1922
+ subgroupContent: "ml-4 pl-3 border-l border-subtle/50 mt-0.5 gap-0.5",
1923
+ toggle: "p-1.5 text-muted hover:text-body transition-colors"
1924
+ };
1925
+ const defaultContentClassName = "flex-1 overflow-y-auto p-4 pb-16 custom-scrollbar flex flex-col gap-6";
1926
+ const mergeSlots = (defaults, overrides) => {
1927
+ if (!overrides) return defaults;
1928
+ const merged = { ...defaults };
1929
+ for (const key of Object.keys(defaults)) if (overrides[key]) merged[key] = require_link.cn(defaults[key], overrides[key]);
1930
+ return merged;
1931
+ };
1932
+ function SidebarMain({ routes, config, className }) {
1773
1933
  const { logo, title, logoProps } = useNavbar();
1774
1934
  const { closeSidebar } = require_docs_layout.useUI();
1775
1935
  const SidebarLogo = logo ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("img", {
1776
- src: logo,
1936
+ src: require_link.resolvePublicAssetUrl(logo, config.base),
1777
1937
  alt: logoProps?.alt || title,
1778
1938
  width: 24,
1779
1939
  height: 24,
1780
1940
  className: "rounded-xl"
1781
1941
  }) : null;
1782
1942
  const hasUtilities = config.versions || config.i18n;
1783
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_docs_layout.Sidebar.Root, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_docs_layout.Sidebar.Content, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_docs_layout.Sidebar.Items, { routes }) }) }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_docs_layout.Sidebar.Mobile, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_docs_layout.Sidebar.Header, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1784
- className: "flex items-center gap-3",
1785
- children: [SidebarLogo, /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1786
- className: "font-bold text-lg tracking-tight text-body truncate max-w-[120px]",
1787
- children: title
1788
- })]
1789
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1790
- className: "flex items-center gap-2",
1791
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ThemeSwitcher, { className: "w-24 h-9 rounded-xl" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_search_dialog.Button, {
1792
- onPress: closeSidebar,
1793
- className: "h-9 w-9 flex items-center justify-center bg-transparent border-none outline-none select-none cursor-pointer rounded-xl hover:bg-primary-50/50 text-muted hover:text-body transition-colors",
1794
- "aria-label": "Close sidebar",
1795
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_link.X, { size: 20 })
1943
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_docs_layout.Sidebar.Root, {
1944
+ className: require_link.cn("hidden lg:flex flex-col w-sidebar sticky top-navbar h-[calc(100vh-var(--spacing-navbar))] border-r border-subtle bg-main", className),
1945
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_docs_layout.Sidebar.Content, {
1946
+ className: defaultContentClassName,
1947
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_docs_layout.Sidebar.Items, {
1948
+ routes,
1949
+ className: "flex flex-col gap-6",
1950
+ classNames: defaultItemsClassNames
1951
+ })
1952
+ })
1953
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_docs_layout.Sidebar.Mobile, {
1954
+ overlayClassName: "fixed inset-0 z-50 bg-black/20 backdrop-blur-sm lg:hidden entering:animate-in entering:fade-in exiting:animate-out exiting:fade-out duration-300",
1955
+ className: require_link.cn("fixed top-0 left-0 bottom-0 w-80 bg-main border-r border-subtle shadow-2xl outline-none entering:animate-in entering:slide-in-from-left exiting:animate-out exiting:slide-out-to-left duration-300", className),
1956
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_docs_layout.Sidebar.Header, {
1957
+ className: "flex items-center justify-between p-4 border-b border-subtle",
1958
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1959
+ className: "flex items-center gap-3",
1960
+ children: [SidebarLogo, /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1961
+ className: "font-bold text-lg tracking-tight text-body truncate max-w-[120px]",
1962
+ children: title
1963
+ })]
1964
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1965
+ className: "flex items-center gap-2",
1966
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ThemeSwitcher, { className: "w-24 h-9 rounded-xl" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_search_dialog$1.Button, {
1967
+ onPress: closeSidebar,
1968
+ className: "h-9 w-9 flex items-center justify-center bg-transparent border-none outline-none select-none cursor-pointer rounded-xl hover:bg-primary-50/50 text-muted hover:text-body transition-colors",
1969
+ "aria-label": "Close sidebar",
1970
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_link.X, { size: 20 })
1971
+ })]
1972
+ })]
1973
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_docs_layout.Sidebar.Content, {
1974
+ className: defaultContentClassName,
1975
+ children: [hasUtilities && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1976
+ className: "flex flex-col gap-4 mb-10",
1977
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1978
+ className: "flex gap-3",
1979
+ children: [config.versions && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(VersionSelector, { className: "flex-1 justify-between h-10 bg-surface border-subtle rounded-xl" }), config.i18n && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(I18nSelector, { className: "flex-1 justify-between h-10 bg-surface border-subtle rounded-xl" })]
1980
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: "mt-2 border-b border-subtle" })]
1981
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_docs_layout.Sidebar.Items, {
1982
+ routes,
1983
+ className: "flex flex-col gap-6",
1984
+ classNames: defaultItemsClassNames
1985
+ })]
1796
1986
  })]
1797
- })] }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_docs_layout.Sidebar.Content, { children: [hasUtilities && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1798
- className: "flex flex-col gap-4 mb-10",
1799
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1800
- className: "flex gap-3",
1801
- children: [config.versions && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(VersionSelector, { className: "flex-1 justify-between h-10 bg-surface border-subtle rounded-xl" }), config.i18n && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(I18nSelector, { className: "flex-1 justify-between h-10 bg-surface border-subtle rounded-xl" })]
1802
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: "mt-2 border-b border-subtle" })]
1803
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_docs_layout.Sidebar.Items, { routes })] })] })] });
1987
+ })] });
1988
+ }
1989
+ function SidebarItems(props) {
1990
+ const { classNames, ...rest } = props;
1991
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_docs_layout.Sidebar.Items, {
1992
+ ...rest,
1993
+ className: require_link.cn("flex flex-col gap-6", rest.className),
1994
+ classNames: mergeSlots(defaultItemsClassNames, classNames)
1995
+ });
1804
1996
  }
1805
1997
  const Sidebar = Object.assign(SidebarMain, {
1806
1998
  Root: require_docs_layout.Sidebar.Root,
@@ -1811,7 +2003,7 @@ const Sidebar = Object.assign(SidebarMain, {
1811
2003
  Link: require_docs_layout.Sidebar.Link,
1812
2004
  SubGroup: require_docs_layout.Sidebar.SubGroup,
1813
2005
  Item: require_docs_layout.Sidebar.Item,
1814
- Items: require_docs_layout.Sidebar.Items
2006
+ Items: SidebarItems
1815
2007
  });
1816
2008
 
1817
2009
  //#endregion
@@ -1975,10 +2167,12 @@ function Giscus({ className }) {
1975
2167
  return () => {
1976
2168
  initializedRef.current = false;
1977
2169
  if (script.parentNode) script.parentNode.removeChild(script);
1978
- (ref.current?.querySelectorAll("iframe"))?.forEach((iframe) => iframe.remove());
2170
+ (ref.current?.querySelectorAll("iframe"))?.forEach((iframe) => {
2171
+ iframe.remove();
2172
+ });
1979
2173
  };
1980
2174
  }
1981
- }, [giscusConfig]);
2175
+ }, [giscusConfig, resolvedTheme]);
1982
2176
  (0, react.useEffect)(() => {
1983
2177
  if (!giscusConfig || !initializedRef.current) return;
1984
2178
  const theme = giscusConfig.theme || (resolvedTheme === "dark" ? "dark" : "light");
@@ -1992,14 +2186,44 @@ function Giscus({ className }) {
1992
2186
  });
1993
2187
  }
1994
2188
 
2189
+ //#endregion
2190
+ //#region src/shared/mdx-path.ts
2191
+ function normalizeMdxPath(value) {
2192
+ return value.replace(/\\/g, "/").replace(/^\/+/, "");
2193
+ }
2194
+ function matchesMdxUpdatePath(routeFilePath, updateRelativePath) {
2195
+ return normalizeMdxPath(routeFilePath) === normalizeMdxPath(updateRelativePath);
2196
+ }
2197
+
1995
2198
  //#endregion
1996
2199
  //#region src/client/ssg/mdx-elements.tsx
1997
- const Loading = () => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1998
- className: "text-muted text-sm py-4",
1999
- children: "Loading..."
2000
- });
2001
- function resolveModuleLoader(loader) {
2002
- return typeof loader === "function" ? loader() : Promise.resolve(loader);
2200
+ async function resolveModuleLoader(loader) {
2201
+ if (typeof loader !== "function") return Promise.resolve(loader);
2202
+ try {
2203
+ const res = loader();
2204
+ if (res && typeof res.then === "function") return await res;
2205
+ return { default: loader };
2206
+ } catch {
2207
+ return { default: loader };
2208
+ }
2209
+ }
2210
+ function extractMdxComponent(mod, moduleKey, pathKey) {
2211
+ if (!mod) return null;
2212
+ let target = mod;
2213
+ if (mod.default !== void 0) target = mod.default;
2214
+ if (typeof target === "function" || typeof target === "string") return target;
2215
+ if (target && typeof target === "object") {
2216
+ const possibleKeys = [moduleKey, pathKey].filter(Boolean);
2217
+ for (const key of possibleKeys) {
2218
+ const value = target[key];
2219
+ if (value) {
2220
+ if (typeof value === "function" || typeof value === "string") return value;
2221
+ if (typeof value === "object" && value.default) return value.default;
2222
+ }
2223
+ }
2224
+ if (target.default !== void 0) return extractMdxComponent({ default: target.default }, moduleKey, pathKey);
2225
+ }
2226
+ return null;
2003
2227
  }
2004
2228
  const EagerMdxElement = ({ moduleLoader, moduleKey, route, components, collectionPostComponent }) => {
2005
2229
  const [mod, setMod] = (0, react.useState)(moduleLoader);
@@ -2009,16 +2233,20 @@ const EagerMdxElement = ({ moduleLoader, moduleKey, route, components, collectio
2009
2233
  (0, react.useEffect)(() => {
2010
2234
  if (!{}.hot || !moduleKey) return;
2011
2235
  const handler = (data) => {
2012
- if (data.relPath.replace(/\\/g, "/").replace(/^\//, "") !== route.filePath.replace(/\\/g, "/").replace(/^\//, "")) return;
2013
- import(moduleKey + "?t=" + Date.now()).then((m) => {
2236
+ if (!matchesMdxUpdatePath(route.filePath, data.relPath)) return;
2237
+ import(`${{}.env.BASE_URL.replace(/\/$/, "")}${moduleKey}?t=${Date.now()}`).then((m) => {
2014
2238
  setMod(m);
2015
2239
  });
2016
2240
  };
2017
- ({}).hot.on("boltdocs:mdx-update", handler);
2018
- return () => ({}).hot?.off("boltdocs:mdx-update", handler);
2241
+ const hot = {}.hot;
2242
+ hot.on("boltdocs:mdx-update", handler);
2243
+ return () => hot.off?.("boltdocs:mdx-update", handler);
2019
2244
  }, [moduleKey, route.filePath]);
2020
- const MDXComponent = mod?.default ?? mod ?? null;
2021
- if (!MDXComponent) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Loading, {});
2245
+ const MDXComponent = extractMdxComponent(mod, moduleKey, route.path || "/");
2246
+ if (!MDXComponent) return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2247
+ className: "prose dark:prose-invert py-8",
2248
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h1", { children: route.title }), route.description && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: route.description })]
2249
+ });
2022
2250
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MdxPage, {
2023
2251
  MDXComponent,
2024
2252
  mdxComponents: components ?? {},
@@ -2052,12 +2280,12 @@ function DocRouteProvider({ value, children }) {
2052
2280
  //#endregion
2053
2281
  //#region src/client/app/docs-layout.tsx
2054
2282
  function DocsLayout({ collectionsData }) {
2055
- const { currentRoute } = require_link.useRoutes();
2283
+ const { currentRoute } = require_search_dialog.useRoutes();
2056
2284
  const content = /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DocRouteProvider, {
2057
2285
  value: currentRoute,
2058
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_search_dialog$1.InternalErrorBoundary, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(virtual_boltdocs_layout.default, {
2286
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_search_dialog.InternalErrorBoundary, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(virtual_boltdocs_layout.default, {
2059
2287
  route: currentRoute,
2060
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_router_dom.Outlet, {})
2288
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_router.Outlet, {})
2061
2289
  }) })
2062
2290
  });
2063
2291
  if (collectionsData) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CollectionsContext.Provider, {
@@ -2092,21 +2320,59 @@ function buildModuleMap(mdxModules) {
2092
2320
  }
2093
2321
  return moduleMap;
2094
2322
  }
2323
+ function cleanModulePath(value) {
2324
+ return value.replace(/\\/g, "/").replace(/^\/+/, "").replace(/\/\([^)]+\)/g, "").replace(/^\([^)]+\)\//, "");
2325
+ }
2326
+ /**
2327
+ * Resolves a route source path against both Vite glob keys and relative keys.
2328
+ * Exact cleaned matches are preferred so `es/guide.md` cannot select the
2329
+ * default-locale `guide.md` when both modules are present.
2330
+ */
2331
+ function resolveModuleKey(filePath, moduleMap) {
2332
+ const normalized = filePath.replace(/\\/g, "/");
2333
+ const cleanPath = cleanModulePath(normalized);
2334
+ for (const candidate of [
2335
+ normalized,
2336
+ normalized.replace(/^\//, ""),
2337
+ cleanPath
2338
+ ]) {
2339
+ const direct = moduleMap.get(candidate);
2340
+ if (direct) return direct;
2341
+ }
2342
+ for (const [relativePath, moduleKey] of moduleMap.entries()) {
2343
+ const cleanRelative = cleanModulePath(relativePath);
2344
+ if (normalized.endsWith(relativePath) || relativePath.endsWith(normalized) || cleanPath.endsWith(cleanRelative) || cleanRelative.endsWith(cleanPath)) return moduleKey;
2345
+ }
2346
+ }
2095
2347
 
2096
2348
  //#endregion
2097
2349
  //#region src/client/ssg/create-routes.doc.tsx
2350
+ function FallbackWrapper({ children }) {
2351
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, { children });
2352
+ }
2098
2353
  function buildDocRoutes(options) {
2099
2354
  const { routesData, config, mdxModules, components, externalPages } = options;
2100
2355
  const baseDocsPath = (config.base || "/docs").replace(/\/$/, "") || "/";
2101
2356
  const defaultVersionMetadata = [];
2102
2357
  const defaultVersion = config.versions?.defaultVersion;
2103
2358
  const docsBase = (config.base || "/docs").replace(/\/$/, "");
2359
+ const urlConfig = {
2360
+ base: config.base,
2361
+ i18n: config.i18n,
2362
+ versions: config.versions,
2363
+ collections: []
2364
+ };
2104
2365
  if (defaultVersion) routesData.filter((r) => !r.collection).forEach((route) => {
2105
2366
  if (route.version) return;
2106
2367
  const p = route.path || "";
2107
2368
  const subPath = p.startsWith(docsBase) ? p.substring(docsBase.length).replace(/^\//, "") : p.replace(/^\//, "");
2108
- if (!(subPath === defaultVersion || subPath.startsWith(`${defaultVersion}/`))) {
2109
- const explicitPath = `${docsBase}/${defaultVersion}/${subPath}`.replace(/\/+/g, "/").replace(/\/$/, "") || "/";
2369
+ if (!(route.version === defaultVersion)) {
2370
+ const explicitPath = require_router.buildUrl({
2371
+ kind: "doc",
2372
+ path: `/${subPath}`,
2373
+ locale: route.locale,
2374
+ version: defaultVersion
2375
+ }, urlConfig);
2110
2376
  defaultVersionMetadata.push({
2111
2377
  ...route,
2112
2378
  path: explicitPath,
@@ -2116,16 +2382,22 @@ function buildDocRoutes(options) {
2116
2382
  });
2117
2383
  const docMetadata = [...routesData.filter((r) => !r.collection), ...defaultVersionMetadata];
2118
2384
  const moduleMap = buildModuleMap(mdxModules);
2119
- const mdxModuleKeys = Object.keys(mdxModules);
2120
- const isLazy = mdxModuleKeys.length > 0 && typeof mdxModules[mdxModuleKeys[0]] === "function";
2385
+ const routeMetadata = /* @__PURE__ */ new Map();
2386
+ const getDocumentIdentity = (route) => {
2387
+ const parsed = require_router.parseUrlReference(route.path, urlConfig, { kind: "doc" });
2388
+ return {
2389
+ path: parsed.routePath,
2390
+ version: route.version || parsed.version || config.versions?.defaultVersion
2391
+ };
2392
+ };
2121
2393
  const docRoutes = docMetadata.map((route) => {
2122
- const normalizedFilePath = route.filePath.replace(/\\/g, "/");
2123
- const moduleKey = moduleMap.get(normalizedFilePath);
2394
+ const moduleKey = resolveModuleKey(route.filePath, moduleMap);
2124
2395
  const moduleLoader = moduleKey ? mdxModules[moduleKey] : null;
2125
2396
  const fullPath = withBase(route.path === "" ? "/" : route.path, config);
2126
2397
  const path = fullPath === baseDocsPath ? "." : fullPath.startsWith(baseDocsPath + "/") ? fullPath.slice(baseDocsPath.length + 1) : fullPath;
2127
2398
  const routeRecord = {
2128
2399
  path,
2400
+ locale: route.locale,
2129
2401
  loader: async () => ({
2130
2402
  path,
2131
2403
  frontmatter: {
@@ -2145,7 +2417,8 @@ function buildDocRoutes(options) {
2145
2417
  }),
2146
2418
  getStaticPaths: () => [path]
2147
2419
  };
2148
- if (isLazy && moduleLoader) routeRecord.lazy = async () => {
2420
+ routeMetadata.set(routeRecord, route);
2421
+ if (moduleLoader) routeRecord.lazy = async () => {
2149
2422
  const mod = await resolveModuleLoader(moduleLoader);
2150
2423
  return { Component: function LoadedMdxRoute() {
2151
2424
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(EagerMdxElement, {
@@ -2153,7 +2426,7 @@ function buildDocRoutes(options) {
2153
2426
  moduleLoader: mod,
2154
2427
  route,
2155
2428
  components: components ?? {}
2156
- }, moduleKey || path);
2429
+ }, `${moduleKey || path}-${route.locale || config.i18n?.defaultLocale || "en"}`);
2157
2430
  } };
2158
2431
  };
2159
2432
  else routeRecord.element = /* @__PURE__ */ (0, react_jsx_runtime.jsx)(EagerMdxElement, {
@@ -2161,95 +2434,147 @@ function buildDocRoutes(options) {
2161
2434
  moduleLoader: moduleLoader ?? {},
2162
2435
  route,
2163
2436
  components: components ?? {}
2164
- }, moduleKey || path);
2437
+ }, `${moduleKey || path}-${route.locale || config.i18n?.defaultLocale || "en"}`);
2165
2438
  return routeRecord;
2166
2439
  });
2167
2440
  const locales = config.i18n?.locales ? Array.isArray(config.i18n.locales) ? config.i18n.locales : Object.keys(config.i18n.locales) : [];
2168
2441
  const allVersions = config.versions?.versions?.map((v) => v.path) || [];
2169
2442
  const targetBasePaths = [];
2170
- targetBasePaths.push({
2171
- path: baseDocsPath,
2172
- filter: () => true,
2173
- locale: config.i18n?.defaultLocale,
2174
- version: config.versions?.defaultVersion
2175
- });
2176
- if (allVersions.length > 0) allVersions.forEach((v) => {
2177
- const fullP = baseDocsPath === "/" ? `/${v}` : `${baseDocsPath}/${v}`;
2443
+ const addTargetBase = (locale, version) => {
2444
+ const fullPath = require_router.buildUrl({
2445
+ kind: "doc",
2446
+ path: "/",
2447
+ locale,
2448
+ version
2449
+ }, urlConfig);
2178
2450
  targetBasePaths.push({
2179
- path: fullP,
2180
- filter: (rp) => !!rp && rp.startsWith(fullP.replace(/\/$/, "") + "/"),
2181
- locale: config.i18n?.defaultLocale,
2182
- version: v
2183
- });
2184
- });
2185
- if (locales.length > 0) locales.forEach((l) => {
2186
- const fullP = baseDocsPath === "/" ? `/${l}` : `${baseDocsPath}/${l}`;
2187
- targetBasePaths.push({
2188
- path: fullP,
2189
- filter: (rp) => !!rp && rp.startsWith(fullP.replace(/\/$/, "") + "/"),
2190
- locale: l,
2191
- version: config.versions?.defaultVersion
2192
- });
2193
- });
2194
- if (allVersions.length > 0 && locales.length > 0) allVersions.forEach((v) => {
2195
- locales.forEach((l) => {
2196
- const fullP = baseDocsPath === "/" ? `/${v}/${l}` : `${baseDocsPath}/${v}/${l}`;
2197
- targetBasePaths.push({
2198
- path: fullP,
2199
- filter: (rp) => !!rp && rp.startsWith(fullP.replace(/\/$/, "") + "/"),
2200
- locale: l,
2201
- version: v
2202
- });
2451
+ path: fullPath,
2452
+ locale,
2453
+ version
2203
2454
  });
2204
- });
2455
+ };
2456
+ addTargetBase(config.i18n?.defaultLocale);
2457
+ for (const version of allVersions) addTargetBase(config.i18n?.defaultLocale, version);
2458
+ for (const locale of locales) addTargetBase(locale);
2459
+ for (const version of allVersions) for (const locale of locales) addTargetBase(locale, version);
2205
2460
  const docPathRegistry = new Set(docRoutes.map((r) => (r.path || "").replace(/\/$/, "")));
2206
2461
  const externalPaths = /* @__PURE__ */ new Set();
2207
2462
  if (externalPages) Object.keys(externalPages).forEach((rawPath) => {
2208
2463
  const p = rawPath.startsWith("/") ? rawPath : `/${rawPath}`;
2209
2464
  externalPaths.add(p.replace(/\/$/, ""));
2210
- if (config.i18n) Object.keys(config.i18n.locales).forEach((locale) => {
2465
+ if (config.i18n) (Array.isArray(config.i18n.locales) ? config.i18n.locales : Object.keys(config.i18n.locales)).forEach((locale) => {
2211
2466
  externalPaths.add(`/${locale}${p === "/" ? "" : p}`.replace(/\/$/, ""));
2212
2467
  });
2213
2468
  });
2214
- targetBasePaths.forEach(({ path: bPath, filter, locale: bLocale, version: bVersion }) => {
2469
+ targetBasePaths.forEach(({ path: bPath, locale: bLocale, version: bVersion }) => {
2215
2470
  if (bPath === "/") return;
2216
2471
  const normalizedPath = bPath.replace(/\/$/, "");
2217
2472
  if (!(docPathRegistry.has(normalizedPath) || externalPaths.has(normalizedPath))) {
2218
2473
  const defaultTab = config.theme?.tabs?.[0]?.id;
2219
2474
  const defaultTabPath = defaultTab ? `${normalizedPath}/${defaultTab}`.replace(/\/+/g, "/") : null;
2220
- let matchedRouteObj = defaultTabPath && docPathRegistry.has(defaultTabPath.replace(/\/$/, "")) ? docRoutes.find((r) => r.path && r.path.replace(/\/$/, "") === defaultTabPath.replace(/\/$/, "")) : docRoutes.find((r) => r.path && filter(r.path) && r.path !== normalizedPath);
2475
+ let matchedRouteObj = defaultTabPath ? docRoutes.find((r) => {
2476
+ return routeMetadata.get(r)?.path?.replace(/\/$/, "") === defaultTabPath.replace(/\/$/, "");
2477
+ }) : void 0;
2478
+ if (!matchedRouteObj) matchedRouteObj = docRoutes.find((r) => {
2479
+ const routePath = routeMetadata.get(r)?.path?.replace(/\/$/, "");
2480
+ return !!routePath && (routePath === normalizedPath || routePath.startsWith(`${normalizedPath}/`));
2481
+ });
2221
2482
  if (!matchedRouteObj && docRoutes.length > 0) matchedRouteObj = docRoutes[0];
2483
+ if (matchedRouteObj && bLocale) {
2484
+ const localeBaseRoute = matchedRouteObj;
2485
+ const defaultLocale = config.i18n?.defaultLocale;
2486
+ const matchedMeta = routeMetadata.get(localeBaseRoute);
2487
+ const matchedIdentity = matchedMeta ? getDocumentIdentity(matchedMeta) : void 0;
2488
+ const localeMatch = docRoutes.find((r) => {
2489
+ const meta = routeMetadata.get(r);
2490
+ if (!meta || !matchedIdentity) return false;
2491
+ if (!(meta.locale === bLocale || bLocale === defaultLocale && !meta.locale)) return false;
2492
+ const identity = getDocumentIdentity(meta);
2493
+ return identity.path === matchedIdentity.path && identity.version === (bVersion || config.versions?.defaultVersion);
2494
+ });
2495
+ if (localeMatch) matchedRouteObj = localeMatch;
2496
+ }
2222
2497
  if (matchedRouteObj) {
2498
+ const matchedRoute = matchedRouteObj;
2223
2499
  const redirectPath = bPath === baseDocsPath ? "." : bPath.startsWith(baseDocsPath + "/") ? bPath.slice(baseDocsPath.length + 1) : bPath;
2224
2500
  const isBasePathFallback = redirectPath === ".";
2225
- docRoutes.push({
2501
+ const matchedMetaObj = (() => {
2502
+ const matchedMeta = routeMetadata.get(matchedRoute);
2503
+ if (!matchedMeta) return void 0;
2504
+ const matchedIdentity = getDocumentIdentity(matchedMeta);
2505
+ const targetVersion = bVersion || config.versions?.defaultVersion;
2506
+ const targetLocale = bLocale || config.i18n?.defaultLocale;
2507
+ return docMetadata.find((m) => {
2508
+ const identity = getDocumentIdentity(m);
2509
+ const locale = m.locale || config.i18n?.defaultLocale;
2510
+ return identity.path === matchedIdentity.path && locale === targetLocale && identity.version === targetVersion;
2511
+ }) || matchedMeta;
2512
+ })();
2513
+ const fallbackMetaObj = matchedMetaObj ? {
2514
+ ...matchedMetaObj,
2515
+ path: bPath,
2516
+ filePath: matchedMetaObj.filePath,
2517
+ locale: bLocale,
2518
+ version: bVersion,
2519
+ slugParts: [],
2520
+ fallback: true,
2521
+ seo: {
2522
+ ...matchedMetaObj.seo,
2523
+ canonical: config.siteUrl ? `${config.siteUrl.replace(/\/$/, "")}${withBase(bPath, config)}` : withBase(bPath, config)
2524
+ }
2525
+ } : {
2526
+ path: bPath,
2527
+ filePath: "",
2528
+ title: redirectPath,
2529
+ componentPath: "",
2530
+ headings: [],
2531
+ locale: bLocale,
2532
+ version: bVersion,
2533
+ fallback: true
2534
+ };
2535
+ const fallbackRoute = {
2226
2536
  ...isBasePathFallback ? { index: true } : { path: redirectPath },
2227
- element: matchedRouteObj.element,
2228
- lazy: matchedRouteObj.lazy,
2229
- loader: matchedRouteObj.loader,
2537
+ locale: bLocale,
2538
+ loader: matchedRoute.loader,
2230
2539
  getStaticPaths: () => []
2540
+ };
2541
+ const resolveFallbackComponent = async () => {
2542
+ const moduleKey = resolveModuleKey(fallbackMetaObj.filePath, moduleMap);
2543
+ const moduleLoader = moduleKey ? mdxModules[moduleKey] : null;
2544
+ const localeKey = bLocale || config.i18n?.defaultLocale || "en";
2545
+ const key = `${moduleKey || bPath}-${localeKey}`;
2546
+ if (!moduleLoader) return null;
2547
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(EagerMdxElement, {
2548
+ moduleKey,
2549
+ moduleLoader: await resolveModuleLoader(moduleLoader),
2550
+ route: fallbackMetaObj,
2551
+ components: components ?? {}
2552
+ }, key);
2553
+ };
2554
+ if (matchedRoute.lazy) fallbackRoute.lazy = async () => {
2555
+ const fallbackComponent = await resolveFallbackComponent();
2556
+ return { Component: () => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FallbackWrapper, { children: fallbackComponent }) };
2557
+ };
2558
+ else if (matchedRoute.element) fallbackRoute.element = matchedRoute.element;
2559
+ fallbackRoute.loader = async () => ({
2560
+ path: redirectPath,
2561
+ frontmatter: {
2562
+ title: fallbackMetaObj.title,
2563
+ description: fallbackMetaObj.description || "",
2564
+ ...fallbackMetaObj.frontmatter || {}
2565
+ },
2566
+ seo: fallbackMetaObj.seo,
2567
+ headings: fallbackMetaObj.headings || [],
2568
+ filePath: fallbackMetaObj.filePath,
2569
+ locale: fallbackMetaObj.locale,
2570
+ version: fallbackMetaObj.version,
2571
+ group: fallbackMetaObj.group,
2572
+ groupTitle: fallbackMetaObj.groupTitle,
2573
+ date: fallbackMetaObj.date,
2574
+ lastUpdated: fallbackMetaObj.lastUpdated
2231
2575
  });
2232
- const matchedMetaObj = docMetadata.find((m) => {
2233
- const fullPath = withBase(m.path === "" ? "/" : m.path, config);
2234
- return (fullPath === baseDocsPath ? "." : fullPath.startsWith(baseDocsPath + "/") ? fullPath.slice(baseDocsPath.length + 1) : fullPath) === matchedRouteObj.path;
2235
- });
2236
- if (matchedMetaObj) {
2237
- const canonicalPath = withBase(matchedMetaObj.path, config);
2238
- const canonicalUrl = config.siteUrl ? `${config.siteUrl.replace(/\/$/, "")}${canonicalPath}` : canonicalPath;
2239
- docMetadata.push({
2240
- ...matchedMetaObj,
2241
- path: bPath,
2242
- filePath: matchedMetaObj.filePath,
2243
- locale: bLocale,
2244
- version: bVersion,
2245
- slugParts: [],
2246
- fallback: true,
2247
- seo: {
2248
- ...matchedMetaObj.seo,
2249
- canonical: canonicalUrl
2250
- }
2251
- });
2252
- }
2576
+ docRoutes.push(fallbackRoute);
2577
+ docMetadata.push(fallbackMetaObj);
2253
2578
  }
2254
2579
  }
2255
2580
  });
@@ -2270,6 +2595,97 @@ function ExternalPageWrapper({ children }) {
2270
2595
 
2271
2596
  //#endregion
2272
2597
  //#region src/client/ssg/create-routes.external.tsx
2598
+ function getLocales(config) {
2599
+ if (!config.i18n) return [];
2600
+ return Array.isArray(config.i18n.locales) ? config.i18n.locales : Object.keys(config.i18n.locales);
2601
+ }
2602
+ function getLocalizedPaths(pathname, config) {
2603
+ const paths = [{
2604
+ path: pathname,
2605
+ locale: config.i18n?.defaultLocale
2606
+ }];
2607
+ for (const locale of getLocales(config)) {
2608
+ const localizedPath = pathname === "/" ? `/${locale}` : `/${locale}${pathname}`;
2609
+ if (!paths.some((entry) => entry.path === localizedPath)) paths.push({
2610
+ path: localizedPath,
2611
+ locale
2612
+ });
2613
+ }
2614
+ return paths;
2615
+ }
2616
+ /**
2617
+ * Content wrapper for file-routed MDX pages. The external layout renders the
2618
+ * site chrome (navbar/footer), but unlike docs pages these routes are not
2619
+ * nested inside DocsLayout, so the MDX content needs its own page container
2620
+ * with the page title and prose typography — otherwise it renders raw and
2621
+ * edge-to-edge directly below the navbar.
2622
+ */
2623
+ function ExternalMdxContent({ title, children, className, contentClassName }) {
2624
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2625
+ className: require_link.cn("boltdocs-page w-full pt-4 pb-20 px-4 sm:px-8", className),
2626
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2627
+ className: require_link.cn("mx-auto w-full max-w-3xl sm:max-w-4xl lg:max-w-5xl", contentClassName),
2628
+ children: [title && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h1", {
2629
+ className: "text-4xl font-bold tracking-tight text-body mb-3",
2630
+ children: title
2631
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2632
+ className: "prose prose-neutral dark:prose-invert max-w-none",
2633
+ children
2634
+ })]
2635
+ })
2636
+ });
2637
+ }
2638
+ function routeTitle(pathname) {
2639
+ const segment = pathname === "/" ? "Home" : pathname.split("/").filter(Boolean).at(-1);
2640
+ return segment ? segment.replace(/[-_]/g, " ").replace(/\b\w/g, (letter) => letter.toUpperCase()) : "Page";
2641
+ }
2642
+ function buildExternalRouteRecord(options) {
2643
+ const { path, locale, component, mdxLoader, externalLayout, components, title } = options;
2644
+ const record = {
2645
+ path,
2646
+ locale,
2647
+ loader: async () => ({
2648
+ path,
2649
+ locale
2650
+ }),
2651
+ getStaticPaths: () => [path]
2652
+ };
2653
+ const ExternalLayout = externalLayout;
2654
+ const ExternalComponent = component;
2655
+ if (ExternalComponent) record.element = /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ExternalPageWrapper, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ExternalLayout, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ExternalComponent, {}) }) });
2656
+ else if (mdxLoader) record.lazy = async () => {
2657
+ const module = await resolveModuleLoader(mdxLoader);
2658
+ return { Component: function ExternalMdxRoute() {
2659
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ExternalPageWrapper, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ExternalLayout, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ExternalMdxContent, {
2660
+ title,
2661
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(EagerMdxElement, {
2662
+ moduleLoader: module,
2663
+ moduleKey: path,
2664
+ route: {
2665
+ path,
2666
+ title,
2667
+ filePath: path,
2668
+ componentPath: "",
2669
+ headings: [],
2670
+ locale
2671
+ },
2672
+ components: components || {}
2673
+ })
2674
+ }) }) });
2675
+ } };
2676
+ };
2677
+ return record;
2678
+ }
2679
+ function buildExternalRouteMetadata(path, locale, title) {
2680
+ return {
2681
+ path,
2682
+ locale,
2683
+ title,
2684
+ filePath: "",
2685
+ componentPath: "",
2686
+ headings: []
2687
+ };
2688
+ }
2273
2689
  function buildExternalRoutes(options) {
2274
2690
  const { externalPages, externalLayout, config } = options;
2275
2691
  const children = [];
@@ -2280,54 +2696,76 @@ function buildExternalRoutes(options) {
2280
2696
  };
2281
2697
  const EffectiveExternalLayout = externalLayout || (({ children }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, { children }));
2282
2698
  Object.entries(externalPages).forEach(([rawPath, ExtComponent]) => {
2283
- const path = rawPath.startsWith("/") ? rawPath : `/${rawPath}`;
2284
- metadata.push({
2285
- path,
2286
- locale: config.i18n?.defaultLocale,
2287
- title: rawPath === "/" ? "Home" : rawPath.replace(/^\//, "").split("/").pop() || "Page",
2288
- filePath: "",
2289
- componentPath: "",
2290
- headings: []
2291
- });
2292
- children.push({
2293
- path,
2294
- element: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ExternalPageWrapper, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(EffectiveExternalLayout, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ExtComponent, {}) }) }),
2295
- loader: async () => ({
2296
- path,
2297
- locale: config.i18n?.defaultLocale
2298
- }),
2299
- getStaticPaths: () => [path]
2300
- });
2301
- if (config.i18n) Object.keys(config.i18n.locales).forEach((locale) => {
2302
- const localePath = `/${locale}${rawPath === "/" ? "" : rawPath}`;
2303
- metadata.push({
2304
- path: localePath,
2305
- locale,
2306
- title: rawPath,
2307
- filePath: "",
2308
- componentPath: "",
2309
- headings: []
2310
- });
2311
- children.push({
2312
- path: localePath,
2313
- element: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ExternalPageWrapper, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(EffectiveExternalLayout, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ExtComponent, {}) }) }),
2314
- loader: async () => ({
2315
- path: localePath,
2316
- locale
2317
- }),
2318
- getStaticPaths: () => [localePath]
2319
- });
2320
- });
2699
+ const pathname = rawPath.startsWith("/") ? rawPath : `/${rawPath}`;
2700
+ for (const localized of getLocalizedPaths(pathname, config)) {
2701
+ metadata.push(buildExternalRouteMetadata(localized.path, localized.locale, routeTitle(pathname)));
2702
+ children.push({ ...buildExternalRouteRecord({
2703
+ path: localized.path,
2704
+ locale: localized.locale,
2705
+ component: ExtComponent,
2706
+ externalLayout: EffectiveExternalLayout,
2707
+ title: routeTitle(pathname)
2708
+ }) });
2709
+ }
2321
2710
  });
2322
2711
  return {
2323
2712
  children,
2324
2713
  metadata
2325
2714
  };
2326
2715
  }
2716
+ function buildExternalFileRoutes(options) {
2717
+ const { externalFilePages, externalFileMdx, externalLayout, components, config } = options;
2718
+ const children = [];
2719
+ const metadata = [];
2720
+ if (!externalFilePages && !externalFileMdx) return {
2721
+ children,
2722
+ metadata
2723
+ };
2724
+ const EffectiveExternalLayout = externalLayout || (({ children }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, { children }));
2725
+ const locales = getLocales(config);
2726
+ const isLocalizedPath = (pathname) => locales.some((locale) => pathname === `/${locale}` || pathname.startsWith(`/${locale}/`));
2727
+ const localeOfPath = (pathname) => {
2728
+ const first = pathname.split("/").filter(Boolean)[0];
2729
+ return first && locales.includes(first) ? first : void 0;
2730
+ };
2731
+ const fileRoutes = new Set([...Object.keys(externalFilePages || {}), ...Object.keys(externalFileMdx || {})]);
2732
+ const registeredPaths = /* @__PURE__ */ new Set();
2733
+ const pushRoute = (pathname, locale, mdxLoader, component) => {
2734
+ if (registeredPaths.has(pathname)) return;
2735
+ registeredPaths.add(pathname);
2736
+ metadata.push(buildExternalRouteMetadata(pathname, locale, routeTitle(pathname)));
2737
+ children.push(buildExternalRouteRecord({
2738
+ path: pathname,
2739
+ locale,
2740
+ component,
2741
+ mdxLoader,
2742
+ externalLayout: EffectiveExternalLayout,
2743
+ components,
2744
+ title: routeTitle(pathname)
2745
+ }));
2746
+ };
2747
+ for (const pathname of fileRoutes) pushRoute(pathname, localeOfPath(pathname) || config.i18n?.defaultLocale, externalFileMdx?.[pathname], externalFilePages?.[pathname]);
2748
+ for (const pathname of fileRoutes) {
2749
+ if (isLocalizedPath(pathname)) continue;
2750
+ const mdxLoader = externalFileMdx?.[pathname];
2751
+ const component = externalFilePages?.[pathname];
2752
+ for (const localized of getLocalizedPaths(pathname, config)) pushRoute(localized.path, localized.locale, mdxLoader, component);
2753
+ }
2754
+ return {
2755
+ children,
2756
+ metadata
2757
+ };
2758
+ }
2327
2759
 
2328
2760
  //#endregion
2329
2761
  //#region src/client/collections/hooks.ts
2330
2762
  const DEFAULT_COLLECTION = "blog";
2763
+ const NO_DATE = Number.NEGATIVE_INFINITY;
2764
+ function getPostTimestamp(date) {
2765
+ if (!date) return NO_DATE;
2766
+ const timestamp = new Date(date).getTime();
2767
+ return Number.isFinite(timestamp) ? timestamp : NO_DATE;
2768
+ }
2331
2769
  /**
2332
2770
  * Returns the posts of a collection, filtered by the current locale and version.
2333
2771
  * Defaults to "blog" if no collection is specified.
@@ -2338,7 +2776,7 @@ const DEFAULT_COLLECTION = "blog";
2338
2776
  */
2339
2777
  function usePosts(collection = DEFAULT_COLLECTION, options) {
2340
2778
  const data = useCollectionsData();
2341
- const { currentLocale, currentVersion } = require_link.useRoutes();
2779
+ const { currentLocale, currentVersion } = require_search_dialog.useRoutes();
2342
2780
  const config = require_link.useConfig();
2343
2781
  const posts = data[collection] || [];
2344
2782
  const defaultLocale = config.i18n?.defaultLocale;
@@ -2351,6 +2789,10 @@ function usePosts(collection = DEFAULT_COLLECTION, options) {
2351
2789
  const versionMatch = !currentVersion || postVersion === currentVersion;
2352
2790
  const draftMatch = options?.includeDrafts || !post.draft;
2353
2791
  return localeMatch && versionMatch && draftMatch;
2792
+ }).sort((a, b) => {
2793
+ const dateA = getPostTimestamp(a.date);
2794
+ const dateOrder = getPostTimestamp(b.date) - dateA;
2795
+ return dateOrder !== 0 ? dateOrder : a.path.localeCompare(b.path);
2354
2796
  });
2355
2797
  }, [
2356
2798
  posts,
@@ -2402,20 +2844,57 @@ function useRecentPosts(collection = DEFAULT_COLLECTION, count = 5) {
2402
2844
 
2403
2845
  //#endregion
2404
2846
  //#region src/client/ssg/create-routes.collection.tsx
2847
+ function CollectionIndex({ indexContent, ListElement }) {
2848
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [indexContent, /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ListElement, {})] });
2849
+ }
2850
+ function splitCollectionPath(routePath) {
2851
+ return routePath.split("/").filter(Boolean);
2852
+ }
2853
+ /**
2854
+ * Resolve the child path of a collection post relative to its layout route.
2855
+ *
2856
+ * Route generation emits collection paths without the configured docs base
2857
+ * (e.g. `/blog/post` or `/es/blog/post`), while the collection layout lives
2858
+ * under the base (`/docs/blog`). Keeping everything after the collection
2859
+ * segment as a *relative* child path is what makes the router match
2860
+ * `/docs/blog/post` and the SSG emit `dist/docs/blog/post.html` — never a
2861
+ * root-level `/blog/post` that neither the matcher nor the cache can reach.
2862
+ */
2863
+ function getCollectionSubPath(routePath, colBase, collection) {
2864
+ if (routePath.startsWith(`${colBase}/`)) return routePath.slice(colBase.length + 1);
2865
+ const parts = splitCollectionPath(routePath);
2866
+ const collectionIndex = parts.indexOf(collection);
2867
+ if (collectionIndex >= 0) return parts.slice(collectionIndex + 1).join("/");
2868
+ return parts.join("/");
2869
+ }
2870
+ function isCollectionIndexRoute(route, collection) {
2871
+ const normalizedPath = route.path.replace(/\/$/, "");
2872
+ return normalizedPath === `/${collection}` || normalizedPath.endsWith(`/${collection}`);
2873
+ }
2874
+ function getCollectionModule(route, moduleMap, mdxModules) {
2875
+ const moduleKey = resolveModuleKey(route.filePath, moduleMap);
2876
+ return {
2877
+ moduleKey,
2878
+ moduleLoader: moduleKey ? mdxModules[moduleKey] : null
2879
+ };
2880
+ }
2405
2881
  function DefaultCollectionList() {
2406
- const location = (0, react_router_dom.useLocation)();
2882
+ const location = require_router.useLocation();
2407
2883
  const config = require_link.useConfig();
2884
+ const loaderData = require_router.useLoaderData();
2408
2885
  const postsPerPage = config.collections?.postsPerPage ?? 10;
2409
- const segments = location.pathname.split("/").filter(Boolean);
2410
- const isLocalePrefixed = config.i18n && segments[0] in (config.i18n.locales || {});
2411
- const collection = isLocalePrefixed ? segments[1] : segments[0];
2412
- const currentPage = (isLocalePrefixed ? segments[3] : segments[2]) === "page" ? Number(isLocalePrefixed ? segments[4] : segments[3]) || 1 : 1;
2886
+ const basePath = location.pathname.replace(/\/page\/\d+\/?$/, "").replace(/\/$/, "");
2887
+ const segments = basePath.split("/").filter(Boolean);
2888
+ const collection = loaderData && loaderData.collection || segments[segments.length - 1];
2413
2889
  const allPosts = usePosts(collection);
2414
- const totalPages = Math.ceil(allPosts.length / postsPerPage);
2890
+ const totalPages = loaderData && loaderData.totalPages || Math.ceil(allPosts.length / postsPerPage);
2891
+ const currentPage = loaderData && loaderData.currentPage || (() => {
2892
+ const match = location.pathname.match(/\/page\/(\d+)\/?$/);
2893
+ return match ? Number(match[1]) : 1;
2894
+ })();
2415
2895
  const start = (currentPage - 1) * postsPerPage;
2416
- const posts = allPosts.slice(start, start + postsPerPage);
2896
+ const posts = loaderData && loaderData.posts || allPosts.slice(start, start + postsPerPage);
2417
2897
  if (!posts.length) return null;
2418
- const basePath = isLocalePrefixed ? `/${segments[0]}/${segments[1]}` : `/${segments[0]}`;
2419
2898
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2420
2899
  className: "py-8 max-w-2xl mx-auto px-4",
2421
2900
  children: [
@@ -2430,7 +2909,7 @@ function DefaultCollectionList() {
2430
2909
  children: [
2431
2910
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h2", {
2432
2911
  className: "text-xl font-semibold mb-2",
2433
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_router_dom.Link, {
2912
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_link.Link, {
2434
2913
  to: post.path,
2435
2914
  className: "text-primary-600 hover:underline",
2436
2915
  children: post.title
@@ -2450,7 +2929,7 @@ function DefaultCollectionList() {
2450
2929
  totalPages > 1 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2451
2930
  className: "mt-8 flex gap-4 text-sm",
2452
2931
  children: [
2453
- currentPage > 1 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_router_dom.Link, {
2932
+ currentPage > 1 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_link.Link, {
2454
2933
  to: currentPage === 2 ? basePath : `${basePath}/page/${currentPage - 1}`,
2455
2934
  className: "text-primary-600 hover:underline",
2456
2935
  children: "Previous"
@@ -2461,7 +2940,7 @@ function DefaultCollectionList() {
2461
2940
  " of ",
2462
2941
  totalPages
2463
2942
  ] }),
2464
- currentPage < totalPages && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_router_dom.Link, {
2943
+ currentPage < totalPages && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_link.Link, {
2465
2944
  to: `${basePath}/page/${currentPage + 1}`,
2466
2945
  className: "text-primary-600 hover:underline",
2467
2946
  children: "Next"
@@ -2482,111 +2961,197 @@ function buildCollectionRoutes(options) {
2482
2961
  collectionsMap.get(r.collection).push(r);
2483
2962
  }
2484
2963
  const moduleMap = buildModuleMap(mdxModules);
2485
- const mdxModuleKeys = Object.keys(mdxModules);
2486
- const isLazy = mdxModuleKeys.length > 0 && typeof mdxModules[mdxModuleKeys[0]] === "function";
2964
+ const defaultLocale = config.i18n?.defaultLocale || "en";
2487
2965
  for (const [colName, colRoutes] of collectionsMap) {
2488
- const colBase = `/${colName}`;
2489
- colRoutes.sort((a, b) => {
2490
- const da = a.date ? new Date(a.date).getTime() : 0;
2491
- return (b.date ? new Date(b.date).getTime() : 0) - da;
2492
- });
2493
- const colChildren = [];
2494
- for (const route of colRoutes) {
2495
- const normalizedFilePath = route.filePath.replace(/\\/g, "/");
2496
- const moduleKey = moduleMap.get(normalizedFilePath);
2497
- const moduleLoader = moduleKey ? mdxModules[moduleKey] : null;
2498
- const subPath = route.path.startsWith(colBase + "/") ? route.path.slice(colBase.length + 1) : route.path.replace(colBase, "") || "";
2499
- const routeWithCollection = {
2500
- ...route,
2501
- collection: colName
2502
- };
2503
- const postComponent = collectionPosts?.[colName];
2504
- const routeRecord = {
2505
- path: subPath,
2966
+ const postsByVariant = /* @__PURE__ */ new Map();
2967
+ const indexByVariant = /* @__PURE__ */ new Map();
2968
+ for (const r of colRoutes) {
2969
+ const effectiveLocale = r.locale || defaultLocale;
2970
+ const key = `${r.version || ""}::${effectiveLocale}`;
2971
+ if (!postsByVariant.has(key)) postsByVariant.set(key, []);
2972
+ if (isCollectionIndexRoute(r, colName)) indexByVariant.set(key, r);
2973
+ else postsByVariant.get(key).push(r);
2974
+ }
2975
+ for (const [variant, variantRoutes] of postsByVariant) {
2976
+ const [version, locale] = variant.split("::");
2977
+ const localeRoutes = variantRoutes;
2978
+ const colBase = require_router.buildUrl({
2979
+ kind: "collection",
2980
+ collection: colName,
2981
+ path: "/",
2982
+ locale: locale === defaultLocale ? void 0 : locale,
2983
+ version: version || void 0
2984
+ }, {
2985
+ base: config.base,
2986
+ i18n: config.i18n,
2987
+ versions: config.versions,
2988
+ collections: [colName]
2989
+ });
2990
+ localeRoutes.sort((a, b) => {
2991
+ const getTimestamp = (date) => {
2992
+ if (!date) return Number.NEGATIVE_INFINITY;
2993
+ const value = new Date(date).getTime();
2994
+ return Number.isFinite(value) ? value : Number.NEGATIVE_INFINITY;
2995
+ };
2996
+ const da = getTimestamp(a.date);
2997
+ const dateOrder = getTimestamp(b.date) - da;
2998
+ return dateOrder !== 0 ? dateOrder : a.path.localeCompare(b.path);
2999
+ });
3000
+ const colChildren = [];
3001
+ for (const route of localeRoutes) {
3002
+ const { moduleKey, moduleLoader } = getCollectionModule(route, moduleMap, mdxModules);
3003
+ const subPath = getCollectionSubPath(route.path, colBase, colName);
3004
+ const routeWithCollection = {
3005
+ ...route,
3006
+ collection: colName
3007
+ };
3008
+ const postComponent = collectionPosts?.[colName];
3009
+ const routeRecord = {
3010
+ path: subPath,
3011
+ loader: async () => ({
3012
+ route: routeWithCollection,
3013
+ headings: route.headings || [],
3014
+ collection: colName,
3015
+ path: subPath,
3016
+ frontmatter: {
3017
+ title: route.title,
3018
+ description: route.description || "",
3019
+ ...route.frontmatter || {}
3020
+ },
3021
+ filePath: route.filePath,
3022
+ locale: route.locale,
3023
+ version: route.version,
3024
+ date: route.date,
3025
+ lastUpdated: route.lastUpdated
3026
+ }),
3027
+ getStaticPaths: () => [subPath || "."]
3028
+ };
3029
+ if (moduleLoader) routeRecord.lazy = async () => {
3030
+ const mod = await resolveModuleLoader(moduleLoader);
3031
+ return { Component: function LoadedCollectionMdxRoute() {
3032
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(EagerMdxElement, {
3033
+ moduleKey,
3034
+ moduleLoader: mod,
3035
+ route,
3036
+ components,
3037
+ collectionPostComponent: postComponent
3038
+ }, `${moduleKey || subPath}-${locale}`);
3039
+ } };
3040
+ };
3041
+ else routeRecord.element = /* @__PURE__ */ (0, react_jsx_runtime.jsx)(EagerMdxElement, {
3042
+ moduleKey,
3043
+ moduleLoader: {},
3044
+ route,
3045
+ components,
3046
+ collectionPostComponent: postComponent
3047
+ }, `${moduleKey || subPath}-${locale}`);
3048
+ colChildren.push(routeRecord);
3049
+ metadata.push(route);
3050
+ }
3051
+ const totalPages = Math.ceil(localeRoutes.length / postsPerPage);
3052
+ const paginatedPosts = localeRoutes.map((r) => ({
3053
+ path: r.path,
3054
+ title: r.title,
3055
+ date: r.date,
3056
+ excerpt: r.excerpt,
3057
+ tags: r.tags,
3058
+ author: r.author,
3059
+ coverImage: r.coverImage,
3060
+ filePath: r.filePath,
3061
+ locale: r.locale,
3062
+ version: r.version,
3063
+ lastUpdated: r.lastUpdated,
3064
+ frontmatter: r.frontmatter
3065
+ }));
3066
+ const ListElement = collectionLists?.[colName] || DefaultCollectionList;
3067
+ const indexRoute = indexByVariant.get(variant);
3068
+ const indexRecord = {
3069
+ index: true,
3070
+ path: "",
2506
3071
  loader: async () => ({
2507
- route: routeWithCollection,
2508
- headings: route.headings || [],
3072
+ posts: paginatedPosts.slice(0, postsPerPage),
3073
+ totalPages,
3074
+ currentPage: 1,
2509
3075
  collection: colName,
2510
- path: subPath,
2511
- frontmatter: {
2512
- title: route.title,
2513
- description: route.description || "",
2514
- ...route.frontmatter || {}
2515
- },
2516
- filePath: route.filePath,
2517
- locale: route.locale,
2518
- version: route.version,
2519
- date: route.date,
2520
- lastUpdated: route.lastUpdated
3076
+ ...indexRoute ? {
3077
+ route: indexRoute,
3078
+ headings: indexRoute.headings || [],
3079
+ frontmatter: {
3080
+ title: indexRoute.title,
3081
+ description: indexRoute.description || "",
3082
+ ...indexRoute.frontmatter || {}
3083
+ },
3084
+ filePath: indexRoute.filePath,
3085
+ locale: indexRoute.locale,
3086
+ version: indexRoute.version
3087
+ } : {}
2521
3088
  }),
2522
- getStaticPaths: () => [subPath || "."]
3089
+ getStaticPaths: () => [""]
2523
3090
  };
2524
- if (isLazy && moduleLoader) routeRecord.lazy = async () => {
2525
- const mod = await resolveModuleLoader(moduleLoader);
2526
- return { Component: function LoadedCollectionMdxRoute() {
2527
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(EagerMdxElement, {
2528
- moduleKey,
2529
- moduleLoader: mod,
2530
- route,
2531
- components,
2532
- collectionPostComponent: postComponent
2533
- }, moduleKey || subPath);
2534
- } };
3091
+ if (indexRoute) {
3092
+ const { moduleKey, moduleLoader } = getCollectionModule(indexRoute, moduleMap, mdxModules);
3093
+ const postComponent = collectionPosts?.[colName];
3094
+ const createIndexContent = (resolvedModule) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(EagerMdxElement, {
3095
+ moduleKey,
3096
+ moduleLoader: resolvedModule,
3097
+ route: indexRoute,
3098
+ components,
3099
+ collectionPostComponent: postComponent
3100
+ }, `${moduleKey || colBase}-${locale}`);
3101
+ if (moduleLoader) indexRecord.lazy = async () => {
3102
+ const mod = await resolveModuleLoader(moduleLoader);
3103
+ return { Component: function LoadedCollectionIndex() {
3104
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CollectionIndex, {
3105
+ indexContent: createIndexContent(mod),
3106
+ ListElement
3107
+ });
3108
+ } };
3109
+ };
3110
+ else indexRecord.element = /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CollectionIndex, {
3111
+ indexContent: createIndexContent({}),
3112
+ ListElement
3113
+ });
3114
+ } else indexRecord.element = /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ListElement, {});
3115
+ colChildren.unshift(indexRecord);
3116
+ metadata.push({
3117
+ path: colBase,
3118
+ locale,
3119
+ collection: colName,
3120
+ title: indexRoute?.title || colName,
3121
+ filePath: indexRoute?.filePath || "",
3122
+ componentPath: indexRoute?.componentPath || "",
3123
+ headings: indexRoute?.headings || []
3124
+ });
3125
+ for (let p = 2; p <= totalPages; p++) {
3126
+ const pagePath = `page/${p}`;
3127
+ colChildren.push({
3128
+ path: pagePath,
3129
+ element: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ListElement, {}),
3130
+ loader: async () => ({
3131
+ posts: paginatedPosts.slice((p - 1) * postsPerPage, p * postsPerPage),
3132
+ totalPages,
3133
+ currentPage: p,
3134
+ collection: colName
3135
+ }),
3136
+ getStaticPaths: () => [pagePath]
3137
+ });
3138
+ metadata.push({
3139
+ path: `${colBase}/${pagePath}`.replace(/\/+/g, "/"),
3140
+ locale,
3141
+ collection: colName,
3142
+ title: colName,
3143
+ filePath: "",
3144
+ componentPath: "",
3145
+ headings: []
3146
+ });
3147
+ }
3148
+ const blogLayoutRoute = {
3149
+ path: colBase,
3150
+ element: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(collectionLayouts?.[colName] || DocsLayout, { collectionsData: collectionsData || {} }),
3151
+ children: colChildren
2535
3152
  };
2536
- else routeRecord.element = /* @__PURE__ */ (0, react_jsx_runtime.jsx)(EagerMdxElement, {
2537
- moduleKey,
2538
- moduleLoader,
2539
- route,
2540
- components,
2541
- collectionPostComponent: postComponent
2542
- }, moduleKey || subPath);
2543
- colChildren.push(routeRecord);
2544
- metadata.push(route);
3153
+ children.push(blogLayoutRoute);
2545
3154
  }
2546
- const totalPages = Math.ceil(colRoutes.length / postsPerPage);
2547
- const paginatedPosts = colRoutes.map((r) => ({
2548
- path: r.path,
2549
- title: r.title,
2550
- date: r.date,
2551
- excerpt: r.excerpt,
2552
- tags: r.tags,
2553
- author: r.author,
2554
- coverImage: r.coverImage,
2555
- filePath: r.filePath,
2556
- locale: r.locale,
2557
- version: r.version,
2558
- lastUpdated: r.lastUpdated,
2559
- frontmatter: r.frontmatter
2560
- }));
2561
- const ListElement = collectionLists?.[colName] || DefaultCollectionList;
2562
- colChildren.unshift({
2563
- index: true,
2564
- element: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ListElement, {}),
2565
- loader: async () => ({
2566
- posts: paginatedPosts.slice(0, postsPerPage),
2567
- totalPages,
2568
- currentPage: 1,
2569
- collection: colName
2570
- }),
2571
- getStaticPaths: () => []
2572
- });
2573
- for (let p = 2; p <= totalPages; p++) colChildren.push({
2574
- path: `page/${p}`,
2575
- element: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ListElement, {}),
2576
- loader: async () => ({
2577
- posts: paginatedPosts.slice((p - 1) * postsPerPage, p * postsPerPage),
2578
- totalPages,
2579
- currentPage: p,
2580
- collection: colName
2581
- }),
2582
- getStaticPaths: () => [`page/${p}`]
2583
- });
2584
- const blogLayoutRoute = {
2585
- path: colBase,
2586
- element: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(collectionLayouts?.[colName] || DocsLayout, { collectionsData: collectionsData || {} }),
2587
- children: colChildren
2588
- };
2589
- children.push(blogLayoutRoute);
2590
3155
  }
2591
3156
  return {
2592
3157
  children,
@@ -2602,6 +3167,22 @@ function createRoutes(options) {
2602
3167
  const baseDocsPath = (config.base || "/docs").replace(/\/$/, "") || "/";
2603
3168
  const { routes: docRoutes, metadata: docMetadata } = buildDocRoutes(options);
2604
3169
  const externalRoutes = buildExternalRoutes(options);
3170
+ const externalFileRoutes = config.experimental?.fileRouting ? buildExternalFileRoutes(options) : {
3171
+ children: [],
3172
+ metadata: []
3173
+ };
3174
+ const occupiedPaths = new Set([...docMetadata.map((route) => route.path), ...externalRoutes.metadata.map((route) => route.path)]);
3175
+ const acceptedExternalFilePaths = /* @__PURE__ */ new Set();
3176
+ const filteredExternalFileRoutes = {
3177
+ children: externalFileRoutes.children,
3178
+ metadata: externalFileRoutes.metadata.filter((route) => {
3179
+ if (occupiedPaths.has(route.path)) return false;
3180
+ occupiedPaths.add(route.path);
3181
+ acceptedExternalFilePaths.add(route.path);
3182
+ return true;
3183
+ })
3184
+ };
3185
+ filteredExternalFileRoutes.children = externalFileRoutes.children.filter((route) => !route.path || acceptedExternalFilePaths.has(route.path));
2605
3186
  const collectionRoutes = buildCollectionRoutes(options);
2606
3187
  const children = [
2607
3188
  {
@@ -2610,18 +3191,20 @@ function createRoutes(options) {
2610
3191
  children: docRoutes
2611
3192
  },
2612
3193
  ...externalRoutes.children,
3194
+ ...filteredExternalFileRoutes.children,
2613
3195
  ...collectionRoutes.children,
2614
3196
  {
2615
3197
  path: "*",
2616
3198
  element: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ExternalPageWrapper, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(EffectiveExternalLayout, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(NotFoundWrapper, {}) }) })
2617
3199
  }
2618
3200
  ];
2619
- return [{
3201
+ const routes = [{
2620
3202
  element: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(BoltdocsShell, {
2621
3203
  config,
2622
3204
  routes: [
2623
3205
  ...docMetadata,
2624
3206
  ...externalRoutes.metadata,
3207
+ ...filteredExternalFileRoutes.metadata,
2625
3208
  ...collectionRoutes.metadata
2626
3209
  ],
2627
3210
  components,
@@ -2629,6 +3212,19 @@ function createRoutes(options) {
2629
3212
  }),
2630
3213
  children
2631
3214
  }];
3215
+ const BaseAwareRouteRenderer = (props) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_router.RouteRenderer, {
3216
+ ...props,
3217
+ basename: config.base,
3218
+ defaultLocale: config.i18n?.defaultLocale,
3219
+ viewTransitions: config.experimental?.viewTransitions === true ? true : typeof config.experimental?.viewTransitions === "object" ? config.experimental.viewTransitions : void 0
3220
+ });
3221
+ return {
3222
+ routes,
3223
+ RouteRenderer: BaseAwareRouteRenderer,
3224
+ matchRouteBranch: require_router.matchRouteBranch,
3225
+ matchRouteBranchWithParams: require_router.matchRouteBranchWithParams,
3226
+ resolveRouteBranch: require_router.resolveRouteBranch
3227
+ };
2632
3228
  }
2633
3229
 
2634
3230
  //#endregion
@@ -2642,7 +3238,7 @@ function createRoutes(options) {
2642
3238
  * A custom layout can reuse any primitive and the slot wiring just works.
2643
3239
  */
2644
3240
  function DocsLayoutComponent({ children }) {
2645
- const { routes: filteredRoutes, currentRoute, isCollectionPage } = require_link.useRoutes();
3241
+ const { routes: filteredRoutes, currentRoute, isCollectionPage } = require_search_dialog.useRoutes();
2646
3242
  const config = require_link.useConfig();
2647
3243
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_docs_layout.DocsLayout, {
2648
3244
  className: "selection:bg-primary-500/10 selection:text-primary-500",
@@ -2653,32 +3249,38 @@ function DocsLayoutComponent({ children }) {
2653
3249
  routes: filteredRoutes || [],
2654
3250
  config
2655
3251
  }),
2656
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_docs_layout.DocsLayout.Content, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_docs_layout.DocsLayout.ContentMdx, { children: [
2657
- !isCollectionPage && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_docs_layout.DocsLayout.Header, { children: [
2658
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2659
- className: "mb-4 border-b border-subtle pb-4 flex flex-wrap items-center justify-between gap-3",
2660
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Breadcrumbs, {}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CopyMarkdown, {
2661
- mdxRaw: currentRoute?._rawContent,
2662
- route: currentRoute
2663
- })]
2664
- }),
2665
- currentRoute?.title && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h1", {
2666
- className: "text-4xl font-bold tracking-tight text-default mb-3",
2667
- children: currentRoute.title
2668
- }),
2669
- currentRoute?.description && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
2670
- className: "text-lg text-muted-foreground mb-6 leading-relaxed",
2671
- children: currentRoute.description
3252
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_docs_layout.DocsLayout.Content, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_docs_layout.DocsLayout.ContentMdx, {
3253
+ className: "pt-4 pb-20 px-4 sm:px-8",
3254
+ children: [
3255
+ !isCollectionPage && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_docs_layout.DocsLayout.Header, { children: [
3256
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3257
+ className: "mb-4 border-b border-subtle pb-4 flex flex-wrap items-center justify-between gap-3",
3258
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Breadcrumbs, {}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CopyMarkdown, {
3259
+ mdxRaw: currentRoute?._rawContent,
3260
+ route: currentRoute
3261
+ })]
3262
+ }),
3263
+ currentRoute?.title && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h1", {
3264
+ className: "text-4xl font-bold tracking-tight text-body mb-3",
3265
+ children: currentRoute.title
3266
+ }),
3267
+ currentRoute?.description && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
3268
+ className: "text-lg text-muted mb-6 leading-relaxed",
3269
+ children: currentRoute.description
3270
+ })
3271
+ ] }),
3272
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ErrorBoundary, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
3273
+ className: "prose prose-neutral dark:prose-invert max-w-none",
3274
+ children: children ?? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_router.Outlet, {})
3275
+ }) }),
3276
+ !isCollectionPage && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Feedback, {}),
3277
+ !isCollectionPage && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Giscus, {}),
3278
+ !isCollectionPage && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
3279
+ className: "mt-20",
3280
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PageNav, {})
2672
3281
  })
2673
- ] }),
2674
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ErrorBoundary, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2675
- className: "prose prose-neutral dark:prose-invert max-w-none",
2676
- children
2677
- }) }),
2678
- !isCollectionPage && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Feedback, {}),
2679
- !isCollectionPage && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Giscus, {}),
2680
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_docs_layout.DocsLayout.Footer, { children: !isCollectionPage && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PageNav, {}) })
2681
- ] }) }),
3282
+ ]
3283
+ }) }),
2682
3284
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2683
3285
  className: "overflow-y-auto sticky",
2684
3286
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(OnThisPage, {
@@ -2707,6 +3309,48 @@ const reactToText = (node, resolvers) => {
2707
3309
  return "";
2708
3310
  };
2709
3311
 
3312
+ //#endregion
3313
+ //#region src/client/components/mdx/use-code-block.ts
3314
+ /**
3315
+ * @deprecated Use the feature-scoped hooks instead: `useCopyButton`,
3316
+ * `useExpandable` and `useCodeBlockFeedback`. This composition keeps the
3317
+ * historical single-hook API and will be removed in a future major version.
3318
+ */
3319
+ function useCodeBlock(props) {
3320
+ const lang = props.lang || props["data-lang"] || "";
3321
+ const isHighlighted = props["data-highlighted"] === "true" || typeof props.className === "string" && props.className.includes("shiki");
3322
+ const rawHighlightedHtml = props.highlightedHtml || props["data-highlighted-html"];
3323
+ const effectiveHighlightedHtml = typeof rawHighlightedHtml === "string" ? rawHighlightedHtml.replace(/<span class="line">\s*(?:<span[^>]*>\s*<\/span>)?\s*<\/span>\s*(<\/code>\s*<\/pre>)/g, "$1") : rawHighlightedHtml;
3324
+ const effectiveTitle = props.title || props["data-title"];
3325
+ const { copied, handleCopy } = require_mdx.useCopyButton();
3326
+ const { isExpanded, setIsExpanded, isExpandable, shouldTruncate, preRef } = require_mdx.useExpandable({
3327
+ children: props.children,
3328
+ highlightedHtml: effectiveHighlightedHtml
3329
+ });
3330
+ const { rated, handleRate, enabled: showCodeBlockFeedback } = require_mdx.useCodeBlockFeedback({
3331
+ plain: props.plain,
3332
+ lang
3333
+ });
3334
+ const copyFromRef = () => handleCopy(preRef.current?.textContent ?? "");
3335
+ const rateFromRef = (type) => handleRate(type, preRef.current?.textContent ?? "");
3336
+ return {
3337
+ copied,
3338
+ isExpanded,
3339
+ setIsExpanded,
3340
+ isExpandable,
3341
+ preRef,
3342
+ handleCopy: copyFromRef,
3343
+ shouldTruncate,
3344
+ isHighlighted,
3345
+ effectiveHighlightedHtml,
3346
+ effectiveTitle,
3347
+ lang,
3348
+ showCodeBlockFeedback,
3349
+ rated,
3350
+ handleRate: rateFromRef
3351
+ };
3352
+ }
3353
+
2710
3354
  //#endregion
2711
3355
  exports.Banner = Banner;
2712
3356
  exports.BoltdocsShell = BoltdocsShell;
@@ -2716,13 +3360,23 @@ exports.CopyMarkdown = CopyMarkdown;
2716
3360
  exports.CurrentPostProvider = CurrentPostProvider;
2717
3361
  exports.DocsLayout = DocsLayoutComponent;
2718
3362
  exports.ErrorBoundary = ErrorBoundary;
3363
+ exports.LocationContext = require_router.LocationContext;
3364
+ exports.LocationProvider = require_router.LocationProvider;
3365
+ exports.MatchesContext = require_router.MatchesContext;
2719
3366
  exports.MdxPage = MdxPage;
2720
3367
  exports.Navbar = Navbar;
3368
+ exports.NavigateContext = require_router.NavigateContext;
2721
3369
  exports.NotFound = NotFound;
2722
3370
  exports.OnThisPage = OnThisPage;
3371
+ exports.Outlet = require_router.Outlet;
3372
+ exports.OutletContext = require_router.OutletContext;
2723
3373
  exports.PageNav = PageNav;
2724
- exports.SearchDialog = require_search_dialog$1.SearchDialog;
3374
+ exports.PrefetchContext = require_router.PrefetchContext;
3375
+ exports.RouteDataContext = require_router.RouteDataContext;
3376
+ exports.RouteRenderer = require_router.RouteRenderer;
3377
+ exports.SearchDialog = require_search_dialog.SearchDialog;
2725
3378
  exports.Sidebar = Sidebar;
3379
+ exports.StructuredData = StructuredData;
2726
3380
  exports.Timeline = require_mdx.Timeline;
2727
3381
  Object.defineProperty(exports, 'ViteReactSSG', {
2728
3382
  enumerable: true,
@@ -2730,30 +3384,71 @@ Object.defineProperty(exports, 'ViteReactSSG', {
2730
3384
  return _bdocs_ssg.ViteReactSSG;
2731
3385
  }
2732
3386
  });
3387
+ exports.addBasename = require_router.addBasename;
3388
+ exports.addUrlBase = require_router.addUrlBase;
3389
+ exports.buildUrl = require_router.buildUrl;
3390
+ exports.classifyUrlPath = require_router.classifyUrlPath;
2733
3391
  exports.cn = require_link.cn;
2734
3392
  exports.copyToClipboard = require_mdx.copyToClipboard;
3393
+ exports.createArticleStructuredData = createArticleStructuredData;
3394
+ exports.createBreadcrumbStructuredData = createBreadcrumbStructuredData;
2735
3395
  exports.createRoutes = createRoutes;
3396
+ exports.createStructuredData = createStructuredData;
3397
+ exports.createWebSiteStructuredData = createWebSiteStructuredData;
3398
+ exports.defaultNavigate = require_router.defaultNavigate;
3399
+ exports.defineStructuredData = defineStructuredData;
3400
+ exports.getConfiguredLocales = require_router.getConfiguredLocales;
3401
+ exports.getConfiguredVersions = require_router.getConfiguredVersions;
2736
3402
  exports.getStarsRepo = getStarsRepo;
2737
3403
  exports.getTranslated = getTranslated;
3404
+ exports.getVersionPrefixSegments = require_router.getVersionPrefixSegments;
3405
+ exports.getVersionSegments = require_router.getVersionSegments;
3406
+ exports.hasBasename = require_router.hasBasename;
3407
+ exports.hasUriScheme = require_router.hasUriScheme;
3408
+ exports.hasUrlBase = require_router.hasUrlBase;
3409
+ exports.isConfiguredLocale = require_router.isConfiguredLocale;
3410
+ exports.isConfiguredVersion = require_router.isConfiguredVersion;
3411
+ exports.matchRouteBranch = require_router.matchRouteBranch;
3412
+ exports.matchRouteBranchWithParams = require_router.matchRouteBranchWithParams;
3413
+ exports.normalizeBasename = require_router.normalizeBasename;
3414
+ exports.normalizeUrlBase = require_router.normalizeUrlBase;
3415
+ exports.normalizeUrlPath = require_router.normalizeUrlPath;
3416
+ exports.parseUrlReference = require_router.parseUrlReference;
2738
3417
  exports.reactToText = reactToText;
3418
+ exports.resolvePublicAssetUrl = require_link.resolvePublicAssetUrl;
3419
+ exports.resolveRouteBranch = require_router.resolveRouteBranch;
3420
+ exports.resolveUrlReference = require_router.resolveUrlReference;
3421
+ exports.splitUrlReference = require_router.splitUrlReference;
3422
+ exports.startViewTransition = require_link.startViewTransition;
3423
+ exports.stripBasename = require_router.stripBasename;
3424
+ exports.stripSiteProtocol = require_router.stripSiteProtocol;
3425
+ exports.stripUrlBase = require_router.stripUrlBase;
2739
3426
  exports.useAnalytics = useAnalytics;
2740
3427
  exports.useBreadcrumbs = useBreadcrumbs;
2741
- exports.useCodeBlock = require_mdx.useCodeBlock;
3428
+ exports.useCodeBlock = useCodeBlock;
3429
+ exports.useCodeBlockFeedback = require_mdx.useCodeBlockFeedback;
2742
3430
  exports.useConfig = require_link.useConfig;
3431
+ exports.useCopyButton = require_mdx.useCopyButton;
3432
+ exports.useExpandable = require_mdx.useExpandable;
2743
3433
  exports.useFeedback = useFeedback;
2744
3434
  exports.useHeadings = useHeadings;
2745
3435
  exports.useI18n = useI18n;
3436
+ exports.useLoaderData = require_router.useLoaderData;
2746
3437
  exports.useLocalizedTo = require_link.useLocalizedTo;
2747
- exports.useLocation = require_docs_layout.useLocation;
3438
+ exports.useLocation = require_router.useLocation;
3439
+ exports.useMatches = require_router.useMatches;
2748
3440
  exports.useMdxComponents = useMdxComponents;
2749
3441
  exports.useMergedComponents = useMergedComponents;
2750
3442
  exports.useNavbar = useNavbar;
3443
+ exports.useNavigate = require_router.useNavigate;
2751
3444
  exports.usePageNav = usePageNav;
2752
3445
  exports.usePost = usePost;
2753
3446
  exports.usePosts = usePosts;
3447
+ exports.usePrefetch = require_router.usePrefetch;
2754
3448
  exports.useRecentPosts = useRecentPosts;
2755
- exports.useRoutes = require_link.useRoutes;
2756
- exports.useSearch = require_search_dialog$1.useSearch;
3449
+ exports.useRouteData = require_router.useRouteData;
3450
+ exports.useRoutes = require_search_dialog.useRoutes;
3451
+ exports.useSearch = require_search_dialog.useSearch;
2757
3452
  exports.useSearchHighlight = require_docs_layout.useSearchHighlight;
2758
3453
  exports.useSidebar = require_docs_layout.useSidebar;
2759
3454
  exports.useTabs = useTabs;
@@ -2761,4 +3456,5 @@ exports.useTheme = require_image.useTheme;
2761
3456
  exports.useTrackEvent = useTrackEvent;
2762
3457
  exports.useTrackPageView = useTrackPageView;
2763
3458
  exports.useUI = require_docs_layout.useUI;
2764
- exports.useVersion = useVersion;
3459
+ exports.useVersion = useVersion;
3460
+ exports.useViewTransition = require_link.useViewTransition;