boltdocs 3.0.2 → 3.2.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 (123) hide show
  1. package/README.md +2 -18
  2. package/dist/{adapters-DEXNIv3x.mjs → adapters-ByYY44Zy.mjs} +1 -1
  3. package/dist/{adapters-C5AWWGfb.cjs → adapters-DvmtpdSF.cjs} +1 -1
  4. package/dist/{banner-CfdalYLL.d.ts → banner-BMop1KLF.d.ts} +2 -2
  5. package/dist/{banner-DNSkgUsO.d.cts → banner-CVD0GugR.d.cts} +2 -2
  6. package/dist/cache-CO4Dy2uQ.cjs +6 -0
  7. package/dist/cache-Dk53iOo6.mjs +6 -0
  8. package/dist/chunk-BFSpntXv.mjs +6 -0
  9. package/dist/{chunk-Ds5LZdWN.cjs → chunk-D1Md3oWO.cjs} +1 -1
  10. package/dist/client/index.cjs +433 -272
  11. package/dist/client/index.d.cts +129 -18
  12. package/dist/client/index.d.ts +129 -18
  13. package/dist/client/index.js +337 -178
  14. package/dist/client/mdx.cjs +1 -1
  15. package/dist/client/mdx.d.cts +1 -1
  16. package/dist/client/mdx.d.ts +1 -1
  17. package/dist/client/mdx.js +1 -1
  18. package/dist/client/primitives.cjs +7 -7
  19. package/dist/client/primitives.d.cts +5 -22
  20. package/dist/client/primitives.d.ts +5 -22
  21. package/dist/client/primitives.js +4 -4
  22. package/dist/client/theme/neutral.css +1 -3
  23. package/dist/client/theme/reset.css +31 -4
  24. package/dist/config-BpzaPsJj.d.cts +781 -0
  25. package/dist/config-CCXp3aXO.mjs +7 -0
  26. package/dist/{config-JGkMJoJQ.cjs → config-CMd4XoFq.cjs} +1 -1
  27. package/dist/config-DlGoEM9D.cjs +7 -0
  28. package/dist/config-xtS0ZkMm.d.mts +781 -0
  29. package/dist/{csp-CBysWlAf.cjs → csp-CRp_3U7a.cjs} +1 -1
  30. package/dist/csp-oTC2ygvF.mjs +6 -0
  31. package/dist/{docs-layout-6FQ8__ok.js → docs-layout-BdtZ9z6s.js} +9 -28
  32. package/dist/{docs-layout-3TpAt6MB.cjs → docs-layout-CFWI15Id.cjs} +69 -88
  33. package/dist/{doctor-BR1B2Mkz.cjs → doctor-BBtmNJE0.cjs} +1 -1
  34. package/dist/doctor-Bv16QSrI.cjs +7 -0
  35. package/dist/doctor-DOAbSaiL.mjs +7 -0
  36. package/dist/{generator-DtUU3Cfk.cjs → generator-COepVWGi.cjs} +1 -1
  37. package/dist/{handler-Btd4t_67.mjs → handler-DzQae4eA.mjs} +1 -1
  38. package/dist/{handler-Dzf4dSnV.cjs → handler-XX7cLTqe.cjs} +1 -1
  39. package/dist/headers-Ddwek8K7.mjs +6 -0
  40. package/dist/{headers-BXKxiPUv.cjs → headers-dg4SDrjY.cjs} +1 -1
  41. package/dist/{image-C9md50h2.js → image-Bz87fCla.js} +2 -2
  42. package/dist/{image-CR6UlaI5.cjs → image-C4TlpMHn.cjs} +18 -18
  43. package/dist/link-2PzgTnaP.js +673 -0
  44. package/dist/{icons-dev-BryEFkJu.cjs → link-D1Gjkb-2.cjs} +8 -353
  45. package/dist/{mdx-DhyMkc35.js → mdx-BuO6a1f7.js} +199 -40
  46. package/dist/{mdx-DJBg5DuL.cjs → mdx-CD-tSjRG.cjs} +237 -72
  47. package/dist/{meta-loader-C9MKjAs0.cjs → meta-loader-Dq1zcFnh.cjs} +1 -1
  48. package/dist/node/cache.cjs +6 -0
  49. package/dist/node/cache.d.cts +84 -0
  50. package/dist/node/cache.d.mts +84 -0
  51. package/dist/node/cache.mjs +6 -0
  52. package/dist/node/cli-entry.cjs +6 -6
  53. package/dist/node/cli-entry.mjs +9 -9
  54. package/dist/node/index.cjs +1 -1
  55. package/dist/node/index.d.cts +27 -638
  56. package/dist/node/index.d.mts +27 -640
  57. package/dist/node/index.mjs +1 -1
  58. package/dist/node/mdx/shiki-adapter.cjs +6 -0
  59. package/dist/node/mdx/shiki-adapter.d.cts +51 -0
  60. package/dist/node/mdx/shiki-adapter.d.mts +51 -0
  61. package/dist/node/mdx/shiki-adapter.mjs +6 -0
  62. package/dist/node-BXtqM1uH.mjs +6 -0
  63. package/dist/node-BlVk4EVg.cjs +104 -0
  64. package/dist/node-DOf4zhWc.mjs +104 -0
  65. package/dist/node-aD1eisrR.cjs +6 -0
  66. package/dist/{package-CEDhVAfO.cjs → package-BcISI5-P.cjs} +1 -1
  67. package/dist/{package-_dCCKVvG.mjs → package-CCYEAYeA.mjs} +1 -1
  68. package/dist/{pages-external-CX2uyW95.cjs → pages-external-XkYIs-d5.cjs} +1 -1
  69. package/dist/parser-DCiEWkSk.cjs +8 -0
  70. package/dist/parser-qk9FIHJ7.mjs +8 -0
  71. package/dist/plugin-C95kvu6h.mjs +73 -0
  72. package/dist/plugin-DM3u2bVj.cjs +73 -0
  73. package/dist/routes-BW6zsk7Z.mjs +6 -0
  74. package/dist/routes-BgoIB5wb.cjs +6 -0
  75. package/dist/{routes-BajCwrvX.cjs → routes-CORVxc02.cjs} +1 -1
  76. package/dist/{search-dialog-D4rplZMv.cjs → search-dialog-B1NERUNx.cjs} +101 -55
  77. package/dist/{search-dialog-Cx7aGW3U.cjs → search-dialog-BRFno7HD.cjs} +8 -8
  78. package/dist/{search-dialog-DDopgbKM.js → search-dialog-BmxHiKwt.js} +2 -2
  79. package/dist/{search-dialog-BNdRV60O.js → search-dialog-D6TvjcuV.js} +1 -1
  80. package/dist/{search-dialog-DaeSPvEo.js → search-dialog-DFnlx8LO.js} +44 -4
  81. package/dist/{search-dialog-CW1f6dn6.cjs → search-dialog-DHqwjJuG.cjs} +1 -1
  82. package/dist/server/index.cjs +1 -1
  83. package/dist/server/index.d.mts +1 -1
  84. package/dist/server/index.mjs +1 -1
  85. package/dist/shiki-adapter-CoQ6jyJ4.cjs +6 -0
  86. package/dist/shiki-adapter-D-aKw7PP.mjs +6 -0
  87. package/dist/sidebar-COTaMHR-.d.ts +1100 -0
  88. package/dist/sidebar-CrEdJuHX.d.cts +1100 -0
  89. package/dist/{types-generator-CYcHkDzZ.cjs → types-generator-BXhv7Ill.cjs} +1 -1
  90. package/dist/types-generator-bDPvUztF.mjs +26 -0
  91. package/dist/utils-Crm9oPcV.mjs +7 -0
  92. package/dist/utils-D6Xtj0FZ.cjs +7 -0
  93. package/package.json +26 -12
  94. package/src/shared/types.ts +532 -23
  95. package/dist/cache-DETwlACe.cjs +0 -6
  96. package/dist/cache-SF59enb3.mjs +0 -6
  97. package/dist/config-B5uVv5q4.cjs +0 -7
  98. package/dist/config-D3_zDkHh.mjs +0 -7
  99. package/dist/csp-gaZ51xzq.mjs +0 -6
  100. package/dist/doctor-3MheVMwd.mjs +0 -7
  101. package/dist/doctor-DQxLM202.cjs +0 -7
  102. package/dist/headers-CXyf0auY.mjs +0 -6
  103. package/dist/icons-dev-kJyGWNeg.js +0 -916
  104. package/dist/node-B9JSyEIU.mjs +0 -105
  105. package/dist/node-Cedquois.cjs +0 -105
  106. package/dist/parser-CNIPHx4s.cjs +0 -8
  107. package/dist/parser-D0QHIQsi.mjs +0 -8
  108. package/dist/plugin-WYNORxp1.cjs +0 -68
  109. package/dist/plugin-YWNVRpws.mjs +0 -68
  110. package/dist/rolldown-runtime-fkIsjY3S.mjs +0 -6
  111. package/dist/routes-CyrnmVuG.mjs +0 -6
  112. package/dist/routes-D6Tuu7Fs.cjs +0 -6
  113. package/dist/shiki-adapter-CGTmrR6S.cjs +0 -6
  114. package/dist/shiki-adapter-CXEGRnjr.mjs +0 -6
  115. package/dist/shiki-adapter-Mr8_oT_9.cjs +0 -6
  116. package/dist/sidebar-7gIifpBX.d.cts +0 -615
  117. package/dist/sidebar-BAKgJ-Er.d.ts +0 -615
  118. package/dist/types-generator-DVOnRVKU.mjs +0 -26
  119. package/dist/utils-B3xYMrpK.mjs +0 -7
  120. package/dist/utils-Bz1tG9Dg.cjs +0 -7
  121. /package/dist/{errors-C0Hx15Ag.mjs → errors-0zGHRLue.mjs} +0 -0
  122. /package/dist/{errors-Dx6JHoKE.cjs → errors-vKw8CkiX.cjs} +0 -0
  123. /package/dist/{index-CdJv4ocW.d.mts → index-1KsTDq4o.d.mts} +0 -0
@@ -4,26 +4,26 @@
4
4
  * Licensed under the MIT License.
5
5
  */
6
6
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
7
- const require_icons_dev = require('../icons-dev-BryEFkJu.cjs');
8
- const require_image = require('../image-CR6UlaI5.cjs');
9
- const require_mdx = require('../mdx-DJBg5DuL.cjs');
10
- const require_docs_layout = require('../docs-layout-3TpAt6MB.cjs');
11
- const require_search_dialog = require('../search-dialog-D4rplZMv.cjs');
12
- const require_search_dialog$1 = require('../search-dialog-Cx7aGW3U.cjs');
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');
13
13
  let react = require("react");
14
14
  let react_router_dom = require("react-router-dom");
15
15
  let react_jsx_runtime = require("react/jsx-runtime");
16
- let react_helmet_async = require("react-helmet-async");
17
- react_helmet_async = require_icons_dev.__toESM(react_helmet_async);
18
16
  let react_aria_components = require("react-aria-components");
17
+ let react_helmet_async = require("react-helmet-async");
18
+ react_helmet_async = require_link.__toESM(react_helmet_async);
19
19
  let virtual_boltdocs_mdx_components = require("virtual:boltdocs-mdx-components");
20
- virtual_boltdocs_mdx_components = require_icons_dev.__toESM(virtual_boltdocs_mdx_components);
20
+ virtual_boltdocs_mdx_components = require_link.__toESM(virtual_boltdocs_mdx_components);
21
21
  let virtual_boltdocs_icons = require("virtual:boltdocs-icons");
22
- virtual_boltdocs_icons = require_icons_dev.__toESM(virtual_boltdocs_icons);
22
+ virtual_boltdocs_icons = require_link.__toESM(virtual_boltdocs_icons);
23
23
  let isomorphic_dompurify = require("isomorphic-dompurify");
24
- isomorphic_dompurify = require_icons_dev.__toESM(isomorphic_dompurify);
24
+ isomorphic_dompurify = require_link.__toESM(isomorphic_dompurify);
25
25
  let virtual_boltdocs_layout = require("virtual:boltdocs-layout");
26
- virtual_boltdocs_layout = require_icons_dev.__toESM(virtual_boltdocs_layout);
26
+ virtual_boltdocs_layout = require_link.__toESM(virtual_boltdocs_layout);
27
27
  let _bdocs_ssg = require("@bdocs/ssg");
28
28
 
29
29
  //#region src/client/app/mdx-components-context.tsx
@@ -55,20 +55,6 @@ function MdxComponentsProvider({ components, children }) {
55
55
  });
56
56
  }
57
57
 
58
- //#endregion
59
- //#region src/client/app/helmet-compat.tsx
60
- const mod = react_helmet_async;
61
- /**
62
- * The `<Helmet>` component, resolved across CJS/ESM module shapes.
63
- * Falls back to a transparent fragment wrapper if the module cannot be resolved.
64
- */
65
- const Helmet = mod.Helmet || mod.default?.Helmet || (({ children }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, { children }));
66
- /**
67
- * The `<HelmetProvider>` component, resolved across CJS/ESM module shapes.
68
- * Falls back to a transparent fragment wrapper if the module cannot be resolved.
69
- */
70
- const HelmetProvider = mod.HelmetProvider || mod.default?.HelmetProvider || (({ children }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, { children }));
71
-
72
58
  //#endregion
73
59
  //#region src/client/app/scroll-handler.tsx
74
60
  /**
@@ -79,7 +65,7 @@ const HelmetProvider = mod.HelmetProvider || mod.default?.HelmetProvider || (({
79
65
  function ScrollHandler() {
80
66
  const { pathname, hash } = (0, react_router_dom.useLocation)();
81
67
  const handleScroll = (behavior = "auto") => {
82
- const container = document.querySelector(".boltdocs-content") || window;
68
+ const container = document.querySelector(".boltdocs-content") || document.querySelector(".boltdocs-external-content") || document.querySelector(".boltdocs-shell-content") || window;
83
69
  const getScrollTop = () => {
84
70
  if (container === window) return window.scrollY;
85
71
  return container.scrollTop;
@@ -112,11 +98,6 @@ function ScrollHandler() {
112
98
  }, [pathname, hash]);
113
99
  (0, react.useEffect)(() => {
114
100
  handleScroll("auto");
115
- const rafId = requestAnimationFrame(() => {
116
- handleScroll("auto");
117
- window.dispatchEvent(new Event("resize"));
118
- });
119
- return () => cancelAnimationFrame(rafId);
120
101
  }, [pathname, hash]);
121
102
  return null;
122
103
  }
@@ -143,10 +124,10 @@ function NotFound() {
143
124
  children: "The page you're looking for doesn't exist or has been moved."
144
125
  })]
145
126
  }),
146
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_icons_dev.Link, {
127
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_link.Link, {
147
128
  href: "/",
148
129
  className: "inline-flex items-center gap-2 rounded-xl border border-subtle bg-main px-6 py-2.5 text-xs font-semibold text-body hover:bg-primary-50/50 hover:border-primary-500/50 transition-all duration-300 outline-none select-none",
149
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_icons_dev.ArrowLeft, { size: 14 }), " Go to Home"]
130
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_link.ArrowLeft, { size: 14 }), " Go to Home"]
150
131
  })
151
132
  ]
152
133
  })
@@ -161,6 +142,28 @@ const mdxComponentsDefault = {
161
142
  "404": NotFound
162
143
  };
163
144
 
145
+ //#endregion
146
+ //#region src/client/app/helmet-compat.tsx
147
+ const mod = react_helmet_async;
148
+ /**
149
+ * The `<Helmet>` component, resolved across CJS/ESM module shapes.
150
+ * Falls back to a transparent fragment wrapper if the module cannot be resolved.
151
+ */
152
+ const Helmet = mod.Helmet || mod.default?.Helmet || (({ children }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, { children }));
153
+ /**
154
+ * The `<HelmetProvider>` component, resolved across CJS/ESM module shapes.
155
+ * Falls back to a transparent fragment wrapper if the module cannot be resolved.
156
+ */
157
+ const HelmetProvider = mod.HelmetProvider || mod.default?.HelmetProvider || (({ children }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, { children }));
158
+ if (typeof globalThis !== "undefined" && globalThis.__BOLTDOCS_SSG_RENDERING__) {
159
+ const hp = HelmetProvider;
160
+ if (hp && typeof hp === "function" && hp.canUseDOM) hp.canUseDOM = false;
161
+ }
162
+ if (typeof globalThis !== "undefined") {
163
+ globalThis.__BOLTDOCS_HELMET_PROVIDER__ = HelmetProvider;
164
+ globalThis.__BOLTDOCS_HELMET__ = Helmet;
165
+ }
166
+
164
167
  //#endregion
165
168
  //#region src/client/utils/i18n.ts
166
169
  /**
@@ -182,8 +185,8 @@ function getTranslated(value, locale) {
182
185
  //#region src/client/app/head.tsx
183
186
  function Head({ siteTitle, siteDescription, routes }) {
184
187
  const location = (0, react_router_dom.useLocation)();
185
- const config = require_icons_dev.useConfig();
186
- const { currentLocale, currentRoute } = require_icons_dev.useRoutes();
188
+ const config = require_link.useConfig();
189
+ const { currentLocale, currentRoute } = require_link.useRoutes();
187
190
  const route = (0, react.useMemo)(() => {
188
191
  if (currentRoute) return currentRoute;
189
192
  const normalizedPath = location.pathname.endsWith("/") && location.pathname.length > 1 ? location.pathname.slice(0, -1) : location.pathname;
@@ -278,12 +281,14 @@ function Head({ siteTitle, siteDescription, routes }) {
278
281
  content: config.seo.verification.facebook
279
282
  }),
280
283
  Object.entries(globalMetatags).map(([key, value]) => {
281
- return key.startsWith("og:") || key.startsWith("music:") || key.startsWith("video:") || key.startsWith("article:") || key.startsWith("book:") || key.startsWith("profile:") ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("meta", {
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", {
282
287
  property: key,
283
- content: value
288
+ content: strVal
284
289
  }, key) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("meta", {
285
290
  name: key,
286
- content: value
291
+ content: strVal
287
292
  }, key);
288
293
  }),
289
294
  Object.entries(seo).map(([key, value]) => {
@@ -293,15 +298,17 @@ function Head({ siteTitle, siteDescription, routes }) {
293
298
  }, "noindex");
294
299
  if (key === "robots") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("meta", {
295
300
  name: "robots",
296
- content: value
301
+ content: String(value)
297
302
  }, "robots");
298
303
  if (key === "canonical" || key === "og:url" || key === "og:image" || key === "twitter:image") return null;
299
- return key.startsWith("og:") || key.startsWith("music:") || key.startsWith("video:") || key.startsWith("article:") || key.startsWith("book:") || key.startsWith("profile:") ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("meta", {
304
+ 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 ?? "");
306
+ return isProperty ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("meta", {
300
307
  property: key,
301
- content: value
308
+ content: strVal
302
309
  }, key) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("meta", {
303
310
  name: key,
304
- content: value
311
+ content: strVal
305
312
  }, key);
306
313
  })
307
314
  ] });
@@ -313,6 +320,16 @@ const CollectionsContext = (0, react.createContext)({});
313
320
  function useCollectionsData() {
314
321
  return (0, react.use)(CollectionsContext);
315
322
  }
323
+ const CurrentPostContext = (0, react.createContext)(null);
324
+ function CurrentPostProvider({ value, children }) {
325
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CurrentPostContext.Provider, {
326
+ value,
327
+ children
328
+ });
329
+ }
330
+ function useCurrentPostData() {
331
+ return (0, react.use)(CurrentPostContext);
332
+ }
316
333
 
317
334
  //#endregion
318
335
  //#region src/client/ssg/boltdocs-shell.tsx
@@ -320,7 +337,7 @@ function useCollectionsData() {
320
337
  * Updates the HTML lang and dir attributes based on the current locale configuration.
321
338
  */
322
339
  function I18nUpdater({ config }) {
323
- const { currentLocale } = require_icons_dev.useBoltdocsContext();
340
+ const { currentLocale } = require_link.useBoltdocsContext();
324
341
  (0, react.useEffect)(() => {
325
342
  if (!config.i18n || typeof document === "undefined") return;
326
343
  const locale = currentLocale || config.i18n.defaultLocale;
@@ -332,9 +349,9 @@ function I18nUpdater({ config }) {
332
349
  }
333
350
  function StoreSync({ config, routeMap }) {
334
351
  const location = (0, react_router_dom.useLocation)();
335
- const { setLocale, setVersion } = require_icons_dev.useBoltdocsContext();
352
+ const { setLocale, setVersion } = require_link.useBoltdocsContext();
336
353
  (0, react.useEffect)(() => {
337
- const currentPath = require_icons_dev.normalizePath(location.pathname);
354
+ const currentPath = require_link.normalizePath(location.pathname);
338
355
  const matchedRoute = routeMap.get(currentPath);
339
356
  if (matchedRoute) {
340
357
  if (config.i18n) setLocale(matchedRoute.locale || config.i18n.defaultLocale);
@@ -356,11 +373,11 @@ function BoltdocsShell({ config, routes, components = {}, collectionsData }) {
356
373
  ...components
357
374
  }), [components]);
358
375
  const { pathname } = (0, react_router_dom.useLocation)();
359
- const currentPath = (0, react.useMemo)(() => require_icons_dev.normalizePath(pathname || "/"), [pathname]);
376
+ const currentPath = (0, react.useMemo)(() => require_link.normalizePath(pathname || "/"), [pathname]);
360
377
  const routeMap = (0, react.useMemo)(() => {
361
378
  const map = /* @__PURE__ */ new Map();
362
379
  for (const r of routes) {
363
- const key = require_icons_dev.normalizePath(r.path === "" ? "/" : r.path);
380
+ const key = require_link.normalizePath(r.path === "" ? "/" : r.path);
364
381
  map.set(key, r);
365
382
  }
366
383
  return map;
@@ -382,15 +399,15 @@ function BoltdocsShell({ config, routes, components = {}, collectionsData }) {
382
399
  config,
383
400
  routeMap
384
401
  ]);
385
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(HelmetProvider, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_icons_dev.RoutesProvider, {
402
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_link.RoutesProvider, {
386
403
  routes,
387
404
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_image.ThemeProvider, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_docs_layout.UIProvider, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MdxComponentsProvider, {
388
405
  components: allComponents,
389
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_icons_dev.ConfigContext.Provider, {
406
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_link.ConfigContext.Provider, {
390
407
  value: config,
391
408
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(CollectionsContext.Provider, {
392
409
  value: collectionsData || {},
393
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ScrollHandler, {}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_icons_dev.BoltdocsProvider, {
410
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ScrollHandler, {}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_link.BoltdocsProvider, {
394
411
  initialLocale: initialData.initLocale,
395
412
  initialVersion: initialData.initVersion,
396
413
  children: [
@@ -404,13 +421,16 @@ function BoltdocsShell({ config, routes, components = {}, collectionsData }) {
404
421
  siteDescription: config.theme?.description,
405
422
  routes
406
423
  }),
407
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_search_dialog$1.InternalErrorBoundary, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_router_dom.Outlet, {}) })
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, {})
427
+ }) })
408
428
  ]
409
429
  })]
410
430
  })
411
431
  })
412
432
  }) }) })
413
- }) });
433
+ });
414
434
  }
415
435
 
416
436
  //#endregion
@@ -455,17 +475,43 @@ function DocPage({ route, content: Content, mdxComponents: propComponents }) {
455
475
  /**
456
476
  * Renders an MDX page by consuming pre-loaded route data.
457
477
  *
458
- * - If the route belongs to a collection (`data.collection` is set), renders
459
- * the custom post component if provided, else falls back to the standard DocPage.
478
+ * - If the route belongs to a collection (`data.collection` is set), wraps
479
+ * the content with `CurrentPostProvider` so that `usePost()` (called without
480
+ * a slug) can read the current post's data from context.
460
481
  * - Otherwise, renders the standard `DocPage` layout.
461
482
  */
462
483
  function MdxPage({ MDXComponent, mdxComponents: propComponents, collectionPostComponent: CollectionPost }) {
463
484
  const data = (0, react_router_dom.useLoaderData)();
464
485
  if (!MDXComponent) return null;
465
- if (!!data?.collection && CollectionPost) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CollectionPost, {
466
- MDXComponent,
467
- mdxComponents: propComponents
468
- });
486
+ const collectionData = data;
487
+ if (!!collectionData?.collection) {
488
+ const postElement = CollectionPost ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CollectionPost, {
489
+ MDXComponent,
490
+ mdxComponents: propComponents
491
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DocPage, {
492
+ 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
502
+ },
503
+ content: MDXComponent,
504
+ mdxComponents: propComponents
505
+ });
506
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CurrentPostProvider, {
507
+ value: {
508
+ route: collectionData.route,
509
+ headings: collectionData.headings,
510
+ collection: collectionData.collection
511
+ },
512
+ children: postElement
513
+ });
514
+ }
469
515
  const docData = data;
470
516
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DocPage, {
471
517
  route: {
@@ -492,7 +538,7 @@ function MdxPage({ MDXComponent, mdxComponents: propComponents, collectionPostCo
492
538
  * Hook to generate breadcrumbs based on the current active route.
493
539
  */
494
540
  function useBreadcrumbs() {
495
- const { currentRoute: activeRoute } = require_icons_dev.useRoutes();
541
+ const { currentRoute: activeRoute } = require_link.useRoutes();
496
542
  const crumbs = [];
497
543
  if (activeRoute) {
498
544
  if (activeRoute.groupTitle) crumbs.push({ label: activeRoute.groupTitle });
@@ -517,14 +563,14 @@ function Breadcrumbs() {
517
563
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_docs_layout.Breadcrumbs.Item, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_docs_layout.Breadcrumbs.Link, {
518
564
  href: "/",
519
565
  className: "text-muted hover:text-body transition-colors flex items-center",
520
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_icons_dev.Home, { size: 14 })
566
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_link.Home, { size: 14 })
521
567
  }) }), crumbs.map((crumb, i) => {
522
568
  const isActive = crumb.href === activeRoute?.path;
523
569
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_docs_layout.Breadcrumbs.Item, {
524
570
  className: "gap-2",
525
571
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_docs_layout.Breadcrumbs.Separator, { className: "text-muted/40" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_docs_layout.Breadcrumbs.Link, {
526
- href: crumb.href,
527
- className: require_icons_dev.cn("transition-colors", isActive ? "text-body font-semibold cursor-default pointer-events-none" : "text-muted hover:text-body"),
572
+ href: crumb.href ?? "",
573
+ className: require_link.cn("transition-colors", isActive ? "text-body font-semibold cursor-default pointer-events-none" : "text-muted hover:text-body"),
528
574
  children: crumb.label
529
575
  })]
530
576
  }, `crumb-${crumb.href}-${crumb.label}-${i}`);
@@ -573,26 +619,26 @@ function CopyMarkdown({ content, mdxRaw }) {
573
619
  children: [
574
620
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_search_dialog.Button, {
575
621
  onPress: handleCopy,
576
- className: require_icons_dev.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"),
622
+ 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"),
577
623
  "aria-label": copied ? "Copied!" : "Copy Markdown",
578
- children: copied ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_icons_dev.Check, { size: 14 }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_icons_dev.Copy, { size: 14 })
624
+ children: copied ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_link.Check, { size: 14 }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_link.Copy, { size: 14 })
579
625
  }),
580
626
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_search_dialog.Button, {
581
627
  onPress: handleCopy,
582
- className: require_icons_dev.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"),
583
- children: [copied ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_icons_dev.Check, { size: 16 }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_icons_dev.Copy, { size: 16 }), copied ? "Copied!" : "Copy Markdown"]
628
+ 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
+ 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"]
584
630
  }),
585
631
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_docs_layout.Menu.Trigger, {
586
632
  placement: "bottom end",
587
633
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_search_dialog.Button, {
588
- className: require_icons_dev.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"),
589
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_icons_dev.ChevronDown, { size: 14 })
634
+ 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
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_link.ChevronDown, { size: 14 })
590
636
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_docs_layout.Menu.Root, {
591
637
  className: "w-52 bg-main border border-subtle rounded-xl p-1.5 shadow-md outline-none flex flex-col gap-0.5 animate-fade-in z-100",
592
638
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_docs_layout.Menu.Item, {
593
639
  onAction: handleCopy,
594
640
  className: "flex items-center px-3 py-2 rounded-lg text-xs font-medium text-body dark:hover:bg-primary-300/50 hover:bg-primary-200/50 transition-colors duration-100 cursor-pointer select-none outline-none group",
595
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_icons_dev.Copy, {
641
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_link.Copy, {
596
642
  size: 16,
597
643
  className: "size-4 text-muted dark:group-hover:text-primary-500 group-hover:text-primary-400"
598
644
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
@@ -602,7 +648,7 @@ function CopyMarkdown({ content, mdxRaw }) {
602
648
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_docs_layout.Menu.Item, {
603
649
  onAction: handleOpenRaw,
604
650
  className: "flex items-center gap-2 px-3 py-2 rounded-lg text-xs font-medium text-body dark:hover:bg-primary-300/50 hover:bg-primary-200/50 transition-colors duration-100 cursor-pointer select-none outline-none group",
605
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_icons_dev.ExternalLink, {
651
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_link.ExternalLink, {
606
652
  size: 16,
607
653
  className: "size-4 text-muted dark:group-hover:text-primary-500 group-hover:text-primary-400"
608
654
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
@@ -669,7 +715,7 @@ function GithubStars({ repo }) {
669
715
  target: "_blank",
670
716
  rel: "noopener noreferrer",
671
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",
672
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_icons_dev.Github, { className: "h-4 w-4 text-body" }), stars !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
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", {
673
719
  className: "tabular-nums font-medium",
674
720
  children: [stars, " stars"]
675
721
  })]
@@ -679,10 +725,10 @@ function GithubStars({ repo }) {
679
725
  //#endregion
680
726
  //#region src/client/hooks/use-navbar.ts
681
727
  function useNavbar() {
682
- const config = require_icons_dev.useConfig();
728
+ const config = require_link.useConfig();
683
729
  const { theme, resolvedTheme } = require_image.useTheme();
684
730
  const location = (0, react_router_dom.useLocation)();
685
- const { currentLocale } = require_icons_dev.useRoutes();
731
+ const { currentLocale } = require_link.useRoutes();
686
732
  const themeConfig = config.theme || {};
687
733
  const title = getTranslated(themeConfig.title, currentLocale) || "Boltdocs";
688
734
  const rawLinks = themeConfig.navbar || [];
@@ -698,7 +744,7 @@ function useNavbar() {
698
744
  const cleanPathParts = (p) => {
699
745
  const parts = p.split("/").filter(Boolean);
700
746
  let i = 0;
701
- if (config.i18n?.locales && parts[i] && config.i18n.locales[parts[i]]) i++;
747
+ if (config.i18n?.locales && parts[i] && !Array.isArray(config.i18n.locales) && config.i18n.locales[parts[i]]) i++;
702
748
  if (config.versions?.versions && parts[i]) {
703
749
  if (config.versions.versions.some((v) => v.path === parts[i])) i++;
704
750
  }
@@ -763,7 +809,7 @@ function ThemeToggle() {
763
809
  setMounted(true);
764
810
  }, []);
765
811
  if (!mounted) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: "h-9 w-9" });
766
- const Icon = theme === "system" ? require_icons_dev.Monitor : theme === "dark" ? require_icons_dev.Moon : require_icons_dev.Sun;
812
+ const Icon = theme === "system" ? require_link.Monitor : theme === "dark" ? require_link.Moon : require_link.Sun;
767
813
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_docs_layout.Menu.Trigger, {
768
814
  placement: "bottom right",
769
815
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_aria_components.Button, {
@@ -785,7 +831,7 @@ function ThemeToggle() {
785
831
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_docs_layout.Menu.Item, {
786
832
  id: "light",
787
833
  className: "group flex items-center gap-2 px-3 py-2 rounded-lg text-xs font-medium text-body dark:hover:bg-primary-300/50 hover:bg-primary-200/50 transition-colors duration-100 cursor-pointer select-none outline-none group data-selected:text-primary-500 data-selected:bg-primary-500/5",
788
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_icons_dev.Sun, {
834
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_link.Sun, {
789
835
  className: "group-hover:text-primary-500 dark:group-hover:text-primary-200",
790
836
  size: 16
791
837
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
@@ -796,7 +842,7 @@ function ThemeToggle() {
796
842
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_docs_layout.Menu.Item, {
797
843
  id: "dark",
798
844
  className: "flex items-center gap-2 px-3 py-2 rounded-lg text-xs font-medium text-body dark:hover:bg-primary-300/50 hover:bg-primary-200/50 transition-colors duration-100 cursor-pointer select-none outline-none group data-selected:text-primary-500 data-selected:bg-primary-500/5",
799
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_icons_dev.Moon, {
845
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_link.Moon, {
800
846
  className: "group-hover:text-primary-500 dark:group-hover:text-primary-200",
801
847
  size: 16
802
848
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
@@ -807,7 +853,7 @@ function ThemeToggle() {
807
853
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_docs_layout.Menu.Item, {
808
854
  id: "system",
809
855
  className: "flex items-center gap-2 px-3 py-2 rounded-lg text-xs font-medium text-body dark:hover:bg-primary-300/50 hover:bg-primary-200/50 transition-colors duration-100 cursor-pointer select-none outline-none group data-selected:text-primary-500 data-selected:bg-primary-500/5",
810
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_icons_dev.Monitor, {
856
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_link.Monitor, {
811
857
  className: "group-hover:text-primary-500 dark:group-hover:text-primary-200",
812
858
  size: 16
813
859
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
@@ -825,23 +871,23 @@ function ThemeSwitcher({ className }) {
825
871
  (0, react.useEffect)(() => {
826
872
  setMounted(true);
827
873
  }, []);
828
- if (!mounted) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: require_icons_dev.cn("h-10 w-full bg-surface rounded-xl animate-pulse", className) });
874
+ if (!mounted) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: require_link.cn("h-10 w-full bg-surface rounded-xl animate-pulse", className) });
829
875
  const isDark = theme === "dark";
830
876
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
831
- className: require_icons_dev.cn("flex p-1 bg-surface border border-subtle rounded-xl relative w-full h-11", className),
877
+ className: require_link.cn("flex p-1 bg-surface border border-subtle rounded-xl relative w-full h-11", className),
832
878
  children: [
833
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: require_icons_dev.cn("absolute inset-y-1 w-[calc(50%-4px)] bg-main border border-subtle rounded-lg transition-all duration-300 ease-out shadow-xs", isDark ? "translate-x-full" : "translate-x-0") }),
879
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: require_link.cn("absolute inset-y-1 w-[calc(50%-4px)] bg-main border border-subtle rounded-lg transition-all duration-300 ease-out shadow-xs", isDark ? "translate-x-full" : "translate-x-0") }),
834
880
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
835
881
  onClick: () => setTheme("light"),
836
- className: require_icons_dev.cn("flex-1 flex items-center justify-center rounded-lg z-10 transition-colors outline-none cursor-pointer border-none bg-transparent", !isDark ? "text-body font-semibold" : "text-muted hover:text-body"),
882
+ className: require_link.cn("flex-1 flex items-center justify-center rounded-lg z-10 transition-colors outline-none cursor-pointer border-none bg-transparent", !isDark ? "text-body font-semibold" : "text-muted hover:text-body"),
837
883
  "aria-label": "Light mode",
838
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_icons_dev.Sun, { size: 18 })
884
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_link.Sun, { size: 18 })
839
885
  }),
840
886
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
841
887
  onClick: () => setTheme("dark"),
842
- className: require_icons_dev.cn("flex-1 flex items-center justify-center rounded-lg z-10 transition-colors outline-none cursor-pointer border-none bg-transparent", isDark ? "text-body font-semibold" : "text-muted hover:text-body"),
888
+ className: require_link.cn("flex-1 flex items-center justify-center rounded-lg z-10 transition-colors outline-none cursor-pointer border-none bg-transparent", isDark ? "text-body font-semibold" : "text-muted hover:text-body"),
843
889
  "aria-label": "Dark mode",
844
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_icons_dev.Moon, { size: 18 })
890
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_link.Moon, { size: 18 })
845
891
  })
846
892
  ]
847
893
  });
@@ -857,8 +903,8 @@ function useTabs(tabs = [], routes = []) {
857
903
  transform: "translateX(0) scaleX(0)",
858
904
  width: 0
859
905
  });
860
- const currentPath = require_icons_dev.normalizePath(location.pathname);
861
- const activeTabId = routes.find((r) => require_icons_dev.normalizePath(r.path) === currentPath)?.tab?.toLowerCase();
906
+ const currentPath = require_link.normalizePath(location.pathname);
907
+ const activeTabId = routes.find((r) => require_link.normalizePath(r.path) === currentPath)?.tab?.toLowerCase();
862
908
  const activeIndex = tabs.findIndex((tab) => tab.id.toLowerCase() === activeTabId);
863
909
  const finalActiveIndex = activeIndex === -1 ? 0 : activeIndex;
864
910
  (0, react.useEffect)(() => {
@@ -885,7 +931,7 @@ function useTabs(tabs = [], routes = []) {
885
931
  //#endregion
886
932
  //#region src/client/components/ui-base/tabs.tsx
887
933
  function Tabs({ tabs, routes }) {
888
- const { currentLocale } = require_icons_dev.useRoutes();
934
+ const { currentLocale } = require_link.useRoutes();
889
935
  const { indicatorStyle, tabRefs, activeIndex } = useTabs(tabs, routes);
890
936
  (0, react.useEffect)(() => {
891
937
  const activeTab = tabRefs.current[activeIndex];
@@ -902,7 +948,7 @@ function Tabs({ tabs, routes }) {
902
948
  dangerouslySetInnerHTML: { __html: isomorphic_dompurify.default.sanitize(iconName, { USE_PROFILES: { svg: true } }) }
903
949
  });
904
950
  const icons = {
905
- ...require_icons_dev.icons_exports,
951
+ ...require_link.icons_exports,
906
952
  ...virtual_boltdocs_icons.default
907
953
  };
908
954
  const TabIcon = icons[iconName] || icons[iconName + "Icon"];
@@ -920,7 +966,7 @@ function Tabs({ tabs, routes }) {
920
966
  children: [tabs.map((tab, index) => {
921
967
  const isActive = index === activeIndex;
922
968
  const firstRoute = routes.find((r) => r.tab && r.tab.toLowerCase() === tab.id.toLowerCase());
923
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_icons_dev.Link, {
969
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_link.Link, {
924
970
  href: firstRoute ? firstRoute.path : "#",
925
971
  ref: (el) => {
926
972
  tabRefs.current[index] = el;
@@ -959,10 +1005,10 @@ function getBaseFilePath(filePath, version, locale) {
959
1005
  */
960
1006
  function useVersion() {
961
1007
  const navigate = (0, react_router_dom.useNavigate)();
962
- const config = require_icons_dev.useConfig();
963
- const { allRoutes, currentRoute, currentVersion, currentLocale } = require_icons_dev.useRoutes();
1008
+ const config = require_link.useConfig();
1009
+ const { allRoutes, currentRoute, currentVersion, currentLocale } = require_link.useRoutes();
964
1010
  const versions = config.versions;
965
- const { setVersion } = require_icons_dev.useBoltdocsContext();
1011
+ const { setVersion } = require_link.useBoltdocsContext();
966
1012
  const handleVersionChange = (version) => {
967
1013
  if (!versions || version === currentVersion) return;
968
1014
  setVersion(version);
@@ -1002,11 +1048,11 @@ function VersionSelector({ className }) {
1002
1048
  const { currentVersionLabel, availableVersions, handleVersionChange } = useVersion();
1003
1049
  if (availableVersions.length === 0) return null;
1004
1050
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_docs_layout.Menu.Trigger, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_search_dialog.Button, {
1005
- className: require_icons_dev.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),
1051
+ 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),
1006
1052
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1007
1053
  className: "font-semibold text-[0.8125rem]",
1008
1054
  children: currentVersionLabel
1009
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_icons_dev.ChevronDown, { className: "w-3.5 h-3.5 text-muted/60" })]
1055
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_link.ChevronDown, { className: "w-3.5 h-3.5 text-muted/60" })]
1010
1056
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_docs_layout.Menu.Root, {
1011
1057
  className: "w-40 bg-main border border-subtle rounded-xl p-1.5 shadow-md outline-none flex flex-col gap-0.5 animate-fade-in z-100",
1012
1058
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_docs_layout.Menu.Section, {
@@ -1027,10 +1073,10 @@ function VersionSelector({ className }) {
1027
1073
  */
1028
1074
  function useI18n() {
1029
1075
  const navigate = (0, react_router_dom.useNavigate)();
1030
- const config = require_icons_dev.useConfig();
1031
- const { allRoutes, currentRoute, currentLocale, currentVersion } = require_icons_dev.useRoutes();
1076
+ const config = require_link.useConfig();
1077
+ const { allRoutes, currentRoute, currentLocale, isCollectionPage } = require_link.useRoutes();
1032
1078
  const i18n = config.i18n;
1033
- const { setLocale } = require_icons_dev.useBoltdocsContext();
1079
+ const { setLocale } = require_link.useBoltdocsContext();
1034
1080
  const handleLocaleChange = (locale) => {
1035
1081
  if (!i18n || locale === currentLocale) return;
1036
1082
  setLocale(locale);
@@ -1038,7 +1084,7 @@ function useI18n() {
1038
1084
  const safeBase = base === "/" ? "" : base.replace(/\/$/, "");
1039
1085
  const isDocRoute = !!currentRoute?.filePath;
1040
1086
  let targetPath = "";
1041
- if (currentRoute) if (isDocRoute) {
1087
+ if (currentRoute) if (isDocRoute && !currentRoute.collection && !isCollectionPage) {
1042
1088
  const baseFile = getBaseFilePath(currentRoute.filePath, currentRoute.version, currentRoute.locale);
1043
1089
  const targetRoute = allRoutes.find((r) => getBaseFilePath(r.filePath, r.version, r.locale) === baseFile && (r.locale || i18n.defaultLocale) === locale && r.version === currentRoute.version);
1044
1090
  if (targetRoute) targetPath = targetRoute.path;
@@ -1050,25 +1096,29 @@ function useI18n() {
1050
1096
  } else {
1051
1097
  let rawExternal = currentRoute.path;
1052
1098
  const parts = rawExternal.split("/").filter(Boolean);
1053
- if (parts.length > 0 && (Array.isArray(i18n.locales) ? i18n.locales.includes(parts[0]) : !!i18n.locales[parts[0]])) {
1054
- parts.shift();
1099
+ const localePosition = currentRoute.collection ? 1 : 0;
1100
+ if (parts.length > localePosition && (Array.isArray(i18n.locales) ? i18n.locales.includes(parts[localePosition]) : !!i18n.locales[parts[localePosition]])) {
1101
+ parts.splice(localePosition, 1);
1055
1102
  rawExternal = "/" + parts.join("/");
1056
1103
  }
1104
+ const cleanParts = rawExternal.split("/").filter(Boolean);
1057
1105
  if (locale === i18n.defaultLocale) targetPath = rawExternal === "" ? "/" : rawExternal;
1058
1106
  else {
1059
- const cleanExt = rawExternal.startsWith("/") ? rawExternal : `/${rawExternal}`;
1060
- targetPath = `/${locale}${cleanExt === "/" ? "" : cleanExt}`;
1107
+ cleanParts.splice(localePosition, 0, locale);
1108
+ targetPath = "/" + cleanParts.join("/") || "/";
1061
1109
  }
1062
1110
  }
1063
1111
  else {
1064
- const targetRoute = allRoutes.find((r) => (r.locale || i18n.defaultLocale) === locale && (r.version || config.versions?.defaultVersion) === (currentVersion || config.versions?.defaultVersion));
1065
- if (targetRoute) targetPath = targetRoute.path;
1112
+ const currentPath = location.pathname;
1113
+ if (isCollectionPage) targetPath = currentPath;
1066
1114
  else {
1067
- const vPath = currentVersion && currentVersion !== config.versions?.defaultVersion ? `/${currentVersion}` : "";
1068
- targetPath = locale === i18n.defaultLocale ? `${safeBase}${vPath}` : `${safeBase}${vPath}/${locale}`;
1115
+ const parts = currentPath.split("/").filter(Boolean);
1116
+ if (parts.length > 0 && (Array.isArray(i18n.locales) ? i18n.locales.includes(parts[0]) : !!i18n.locales[parts[0]])) parts.shift();
1117
+ if (locale !== i18n.defaultLocale) parts.unshift(locale);
1118
+ targetPath = "/" + parts.join("/");
1069
1119
  }
1070
1120
  }
1071
- if (!targetPath || targetPath === "") targetPath = "/";
1121
+ if (!targetPath || targetPath === "") targetPath = "/s";
1072
1122
  targetPath = targetPath.replace(/\/+/g, "/");
1073
1123
  navigate(targetPath);
1074
1124
  };
@@ -1101,7 +1151,7 @@ function useI18n() {
1101
1151
  //#endregion
1102
1152
  //#region src/client/hooks/use-page-nav.ts
1103
1153
  function usePageNav() {
1104
- const { routes, currentRoute } = require_icons_dev.useRoutes();
1154
+ const { routes, currentRoute } = require_link.useRoutes();
1105
1155
  const location = (0, react_router_dom.useLocation)();
1106
1156
  const { groups, ungrouped } = require_docs_layout.useSidebar(routes);
1107
1157
  return (0, react.useMemo)(() => {
@@ -1133,8 +1183,8 @@ function usePageNav() {
1133
1183
  };
1134
1184
  for (const item of mergedItems) if (item.type === "link") flattenNode(item.route);
1135
1185
  else if (item.group.routes) for (const route of item.group.routes) flattenNode(route);
1136
- const currentNormalizedPath = require_icons_dev.normalizePath(location.pathname);
1137
- const currentIndex = orderedRoutes.findIndex((r) => require_icons_dev.normalizePath(r.path) === currentNormalizedPath);
1186
+ const currentNormalizedPath = require_link.normalizePath(location.pathname);
1187
+ const currentIndex = orderedRoutes.findIndex((r) => require_link.normalizePath(r.path) === currentNormalizedPath);
1138
1188
  return {
1139
1189
  prevPage: currentIndex > 0 ? orderedRoutes[currentIndex - 1] : null,
1140
1190
  nextPage: currentIndex !== -1 && currentIndex < orderedRoutes.length - 1 ? orderedRoutes[currentIndex + 1] : null,
@@ -1152,10 +1202,42 @@ function usePageNav() {
1152
1202
  //#region src/client/hooks/use-analytics.ts
1153
1203
  function createAnalyticsInstance(config) {
1154
1204
  if (typeof window === "undefined") return createDisabledAnalytics();
1205
+ if (window.posthog) return createPostHogAnalytics(config);
1155
1206
  if (typeof window.gtag === "function") return createGtagAnalytics(config);
1156
1207
  if (window.dataLayer) return createDataLayerAnalytics(config);
1157
1208
  return createDisabledAnalytics();
1158
1209
  }
1210
+ function createPostHogAnalytics(_config) {
1211
+ return {
1212
+ trackPageView: (path) => {
1213
+ window.posthog?.capture("$pageview", { $current_url: path });
1214
+ },
1215
+ trackEvent: ({ action, category, label, value, params }) => {
1216
+ window.posthog?.capture(action, {
1217
+ event_category: category,
1218
+ event_label: label,
1219
+ value,
1220
+ ...params
1221
+ });
1222
+ },
1223
+ trackSearch: (query, resultsCount) => {
1224
+ window.posthog?.capture("search", {
1225
+ query,
1226
+ results_count: resultsCount
1227
+ });
1228
+ },
1229
+ trackDownload: (file, type) => {
1230
+ window.posthog?.capture("file_download", {
1231
+ file_name: file,
1232
+ file_type: type || file.split(".").pop()
1233
+ });
1234
+ },
1235
+ trackExternalLink: (url) => {
1236
+ window.posthog?.capture("external_link", { link_url: url });
1237
+ },
1238
+ isEnabled: true
1239
+ };
1240
+ }
1159
1241
  function createGtagAnalytics(config) {
1160
1242
  return {
1161
1243
  trackPageView: (path, title) => {
@@ -1348,8 +1430,8 @@ function useHeadings() {
1348
1430
  * Resets automatically when navigating to a new page.
1349
1431
  */
1350
1432
  function useFeedback(options = {}) {
1351
- const config = require_icons_dev.useConfig();
1352
- const { currentRoute } = require_icons_dev.useRoutes();
1433
+ const config = require_link.useConfig();
1434
+ const { currentRoute } = require_link.useRoutes();
1353
1435
  const [rating, setRating] = (0, react.useState)(null);
1354
1436
  const [comment, setComment] = (0, react.useState)("");
1355
1437
  const [loading, setLoading] = (0, react.useState)(false);
@@ -1416,14 +1498,14 @@ function I18nSelector({ className }) {
1416
1498
  const { currentLocale, availableLocales, handleLocaleChange } = useI18n();
1417
1499
  if (availableLocales.length === 0) return null;
1418
1500
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_docs_layout.Menu.Trigger, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_search_dialog.Button, {
1419
- className: require_icons_dev.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),
1501
+ 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),
1420
1502
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1421
1503
  className: "flex items-center gap-1.5",
1422
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_icons_dev.Languages, { className: "w-3.5 h-3.5 text-primary-500" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1504
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_link.Languages, { className: "w-3.5 h-3.5 text-primary-500" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1423
1505
  className: "font-bold text-[0.75rem] uppercase opacity-90",
1424
1506
  children: currentLocale || "en"
1425
1507
  })]
1426
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_icons_dev.ChevronDown, { className: "w-3.5 h-3.5 text-muted/60" })]
1508
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_link.ChevronDown, { className: "w-3.5 h-3.5 text-muted/60" })]
1427
1509
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_docs_layout.Menu.Root, {
1428
1510
  className: "w-40 bg-main border border-subtle rounded-xl p-1.5 shadow-md outline-none flex flex-col gap-0.5 animate-fade-in z-100",
1429
1511
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_docs_layout.Menu.Section, {
@@ -1439,17 +1521,17 @@ function I18nSelector({ className }) {
1439
1521
 
1440
1522
  //#endregion
1441
1523
  //#region src/client/components/ui-base/navbar.tsx
1442
- const SearchDialog$1 = (0, react.lazy)(() => Promise.resolve().then(() => require("../search-dialog-CW1f6dn6.cjs")).then((m) => ({ default: m.SearchDialog })));
1524
+ const SearchDialog$1 = (0, react.lazy)(() => Promise.resolve().then(() => require("../search-dialog-DHqwjJuG.cjs")).then((m) => ({ default: m.SearchDialog })));
1443
1525
  function Navbar() {
1444
1526
  const { links, title, logo, logoProps, github, social, config } = useNavbar();
1445
- const { routes, currentRoute, isCollectionPage, currentVersion, currentLocale } = require_icons_dev.useRoutes();
1527
+ const { routes, currentRoute, isCollectionPage, currentVersion, currentLocale } = require_link.useRoutes();
1446
1528
  const { isSidebarOpen, toggleSidebar } = require_docs_layout.useUI();
1447
1529
  const [isMobileMenuOpen, setIsMobileMenuOpen] = (0, react.useState)(false);
1448
1530
  const themeConfig = config.theme;
1449
1531
  const isDocs = !!currentRoute?.filePath && !isCollectionPage;
1450
1532
  const hasTabs = themeConfig?.tabs && themeConfig.tabs.length > 0;
1451
1533
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_search_dialog.Navbar.Root, {
1452
- className: require_icons_dev.cn("border-b border-subtle bg-main/80 backdrop-blur-md", hasTabs && "border-b-0"),
1534
+ className: require_link.cn("border-b border-subtle bg-main/80 backdrop-blur-md", hasTabs && "border-b-0"),
1453
1535
  children: [
1454
1536
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_search_dialog.Navbar.Content, { children: [
1455
1537
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_search_dialog.Navbar.Left, { children: [
@@ -1457,7 +1539,7 @@ function Navbar() {
1457
1539
  onPress: toggleSidebar,
1458
1540
  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",
1459
1541
  "aria-label": isSidebarOpen ? "Close sidebar" : "Open sidebar",
1460
- children: isSidebarOpen ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_icons_dev.X, { className: "w-5 h-5 text-body" }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_icons_dev.Menu, { className: "w-5 h-5 text-body" })
1542
+ 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" })
1461
1543
  }),
1462
1544
  logo && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_search_dialog.Navbar.Logo, {
1463
1545
  src: logo,
@@ -1470,6 +1552,10 @@ function Navbar() {
1470
1552
  href: "site:/",
1471
1553
  children: title
1472
1554
  }),
1555
+ currentRoute?.draft && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1556
+ className: "hidden sm:inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium bg-yellow-100 text-yellow-800 dark:bg-yellow-900/30 dark:text-yellow-400 border border-yellow-200 dark:border-yellow-800",
1557
+ children: "Draft"
1558
+ }),
1473
1559
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1474
1560
  className: "hidden sm:block",
1475
1561
  children: config.versions && currentVersion && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(VersionSelector, {})
@@ -1557,16 +1643,16 @@ function Navbar() {
1557
1643
  });
1558
1644
  }
1559
1645
  function NavbarLinkItem({ link }) {
1560
- const localizedHref = require_icons_dev.useLocalizedTo(link.href || "");
1646
+ const localizedHref = require_link.useLocalizedTo(link.href || "");
1561
1647
  const { pathname } = (0, react_router_dom.useLocation)();
1562
1648
  const active = pathname === localizedHref || pathname.startsWith(`${localizedHref}/`);
1563
1649
  if (link.items && link.items.length > 0) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_search_dialog.Navbar.Dropdown, {
1564
1650
  label: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1565
- className: require_icons_dev.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"),
1651
+ 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"),
1566
1652
  children: link.label
1567
1653
  }),
1568
1654
  children: link.items?.map((item) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_search_dialog.Navbar.DropdownItem, {
1569
- href: require_icons_dev.useLocalizedTo(item.href || ""),
1655
+ href: require_link.useLocalizedTo(item.href || ""),
1570
1656
  label: item.label
1571
1657
  }, item.href))
1572
1658
  });
@@ -1574,17 +1660,17 @@ function NavbarLinkItem({ link }) {
1574
1660
  ...link,
1575
1661
  href: localizedHref,
1576
1662
  active,
1577
- className: require_icons_dev.cn("transition-colors outline-none font-medium focus-visible:ring-2 focus-visible:ring-primary-500/30 rounded-sm", active ? "text-primary-500" : "text-muted hover:text-body")
1663
+ className: require_link.cn("transition-colors outline-none font-medium focus-visible:ring-2 focus-visible:ring-primary-500/30 rounded-sm", active ? "text-primary-500" : "text-muted hover:text-body")
1578
1664
  });
1579
1665
  }
1580
1666
  function NavbarMobileLinkItem({ link, onClose }) {
1581
- const localizedHref = require_icons_dev.useLocalizedTo(link.href || "");
1667
+ const localizedHref = require_link.useLocalizedTo(link.href || "");
1582
1668
  const { pathname } = (0, react_router_dom.useLocation)();
1583
1669
  const active = pathname === localizedHref;
1584
1670
  if (link.items && link.items.length > 0) return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1585
1671
  className: "flex flex-col gap-1",
1586
1672
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1587
- className: require_icons_dev.cn("px-3 py-2 text-sm transition-all", active ? "text-body" : "text-muted/80 hover:text-body"),
1673
+ className: require_link.cn("px-3 py-2 text-sm transition-all", active ? "text-body" : "text-muted/80 hover:text-body"),
1588
1674
  children: link.label
1589
1675
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1590
1676
  className: "flex flex-col gap-1 pl-4",
@@ -1599,20 +1685,26 @@ function NavbarMobileLinkItem({ link, onClose }) {
1599
1685
  href: localizedHref,
1600
1686
  active,
1601
1687
  onPress: onClose,
1602
- className: require_icons_dev.cn("transition-all", active ? "text-body" : "text-muted/80 hover:text-body")
1688
+ className: require_link.cn("transition-all", active ? "text-body" : "text-muted/80 hover:text-body")
1603
1689
  });
1604
1690
  }
1605
1691
 
1606
1692
  //#endregion
1607
1693
  //#region src/client/components/ui-base/on-this-page.tsx
1608
1694
  function OnThisPage({ headings = [], editLink, communityHelp, filePath }) {
1609
- if (headings.length === 0) return null;
1695
+ if (headings.length === 0) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("nav", {
1696
+ className: "w-toc shrink-0 hidden xl:block",
1697
+ "aria-hidden": "true"
1698
+ });
1610
1699
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_docs_layout.OnThisPage.Root, { children: [
1611
1700
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_docs_layout.OnThisPage.Header, {
1612
1701
  className: "flex flex-row gap-x-2",
1613
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_icons_dev.TextAlignStart, { size: 16 }), "On this page"]
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
1614
1707
  }),
1615
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_docs_layout.OnThisPage.Tree, { headings }),
1616
1708
  (editLink || communityHelp) && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1617
1709
  className: "mt-8 pt-8 border-t border-subtle space-y-4",
1618
1710
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
@@ -1625,13 +1717,13 @@ function OnThisPage({ headings = [], editLink, communityHelp, filePath }) {
1625
1717
  target: "_blank",
1626
1718
  rel: "noopener noreferrer",
1627
1719
  className: "flex items-center gap-2 text-sm text-muted hover:text-body transition-colors",
1628
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_icons_dev.Pencil, { size: 16 }), "Edit this page"]
1720
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_link.Pencil, { size: 16 }), "Edit this page"]
1629
1721
  }) }), communityHelp && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("a", {
1630
1722
  href: communityHelp,
1631
1723
  target: "_blank",
1632
1724
  rel: "noopener noreferrer",
1633
1725
  className: "flex items-center gap-2 text-sm text-muted hover:text-body transition-colors",
1634
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_icons_dev.CircleHelp, { size: 16 }), "Community help"]
1726
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_link.CircleHelp, { size: 16 }), "Community help"]
1635
1727
  }) })]
1636
1728
  })]
1637
1729
  })
@@ -1700,7 +1792,7 @@ function SidebarMain({ routes, config }) {
1700
1792
  onPress: closeSidebar,
1701
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",
1702
1794
  "aria-label": "Close sidebar",
1703
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_icons_dev.X, { size: 20 })
1795
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_link.X, { size: 20 })
1704
1796
  })]
1705
1797
  })] }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_docs_layout.Sidebar.Content, { children: [hasUtilities && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1706
1798
  className: "flex flex-col gap-4 mb-10",
@@ -1739,7 +1831,7 @@ function Banner({ children, className = "", dismissible = false, id = "boltdocs-
1739
1831
  };
1740
1832
  if (!isVisible) return null;
1741
1833
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1742
- className: require_icons_dev.cn("relative flex items-center justify-center px-4 py-2.5 text-xs font-semibold tracking-wide bg-primary-500/10 dark:bg-primary-500/15 text-primary-700 dark:text-primary-300 border-b border-primary-500/20 select-none animate-in fade-in duration-300", className),
1834
+ className: require_link.cn("relative flex items-center justify-center px-4 py-2.5 text-xs font-semibold tracking-wide bg-primary-500/10 dark:bg-primary-500/15 text-primary-700 dark:text-primary-300 border-b border-primary-500/20 select-none animate-in fade-in duration-300", className),
1743
1835
  ...props,
1744
1836
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1745
1837
  className: "flex-1 text-center flex items-center justify-center gap-2",
@@ -1748,7 +1840,7 @@ function Banner({ children, className = "", dismissible = false, id = "boltdocs-
1748
1840
  onClick: handleDismiss,
1749
1841
  className: "absolute right-3 top-1/2 -translate-y-1/2 p-1.5 opacity-70 hover:opacity-100 transition-all duration-300 rounded-xl hover:bg-primary-500/10 cursor-pointer border-none bg-transparent flex items-center justify-center outline-none",
1750
1842
  "aria-label": "Dismiss banner",
1751
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_icons_dev.X, { className: "w-3.5 h-3.5" })
1843
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_link.X, { className: "w-3.5 h-3.5" })
1752
1844
  })]
1753
1845
  });
1754
1846
  }
@@ -1756,16 +1848,16 @@ function Banner({ children, className = "", dismissible = false, id = "boltdocs-
1756
1848
  //#endregion
1757
1849
  //#region src/client/components/ui-base/feedback.tsx
1758
1850
  function Feedback({ className }) {
1759
- if (!(require_icons_dev.useConfig().integrations?.feedback?.custom)?.enabled) return null;
1851
+ if (!(require_link.useConfig().integrations?.feedback?.custom)?.enabled) return null;
1760
1852
  const { rating, setRating, comment, setComment, loading, submitted, error, submit } = useFeedback();
1761
1853
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1762
- className: require_icons_dev.cn("w-full max-w-2xl mt-12 mb-6 p-6 rounded-2xl border border-subtle bg-surface/50 backdrop-blur-xs select-none", className),
1854
+ className: require_link.cn("w-full max-w-2xl mt-12 mb-6 p-6 rounded-2xl border border-subtle bg-surface/50 backdrop-blur-xs select-none", className),
1763
1855
  children: submitted ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1764
1856
  className: "flex flex-col items-center justify-center py-4 text-center animate-in fade-in zoom-in duration-300",
1765
1857
  children: [
1766
1858
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1767
1859
  className: "flex h-12 w-12 items-center justify-center rounded-full bg-emerald-500/10 text-emerald-500 mb-3 border border-emerald-500/20",
1768
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_icons_dev.Check, { size: 24 })
1860
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_link.Check, { size: 24 })
1769
1861
  }),
1770
1862
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", {
1771
1863
  className: "text-lg font-semibold text-default",
@@ -1789,23 +1881,23 @@ function Feedback({ className }) {
1789
1881
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
1790
1882
  type: "button",
1791
1883
  onClick: () => setRating("good"),
1792
- className: require_icons_dev.cn("flex items-center gap-1.5 px-3 py-1.5 rounded-lg border text-sm font-medium transition-all duration-200 outline-none cursor-pointer", rating === "good" ? "border-primary-500 bg-primary-500/10 text-primary-500 dark:text-primary-400" : "border-subtle hover:border-body hover:bg-surface text-muted hover:text-body"),
1884
+ className: require_link.cn("flex items-center gap-1.5 px-3 py-1.5 rounded-lg border text-sm font-medium transition-all duration-200 outline-none cursor-pointer", rating === "good" ? "border-primary-500 bg-primary-500/10 text-primary-500 dark:text-primary-400" : "border-subtle hover:border-body hover:bg-surface text-muted hover:text-body"),
1793
1885
  "aria-label": "Helpful",
1794
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_icons_dev.FaceGood, {}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "Yes" })]
1886
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_link.FaceGood, {}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "Yes" })]
1795
1887
  }),
1796
1888
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
1797
1889
  type: "button",
1798
1890
  onClick: () => setRating("neutral"),
1799
- className: require_icons_dev.cn("flex items-center gap-1.5 px-3 py-1.5 rounded-lg border text-sm font-medium transition-all duration-200 outline-none cursor-pointer", rating === "neutral" ? "border-primary-500 bg-primary-500/10 text-primary-500 dark:text-primary-400" : "border-subtle hover:border-body hover:bg-surface text-muted hover:text-body"),
1891
+ className: require_link.cn("flex items-center gap-1.5 px-3 py-1.5 rounded-lg border text-sm font-medium transition-all duration-200 outline-none cursor-pointer", rating === "neutral" ? "border-primary-500 bg-primary-500/10 text-primary-500 dark:text-primary-400" : "border-subtle hover:border-body hover:bg-surface text-muted hover:text-body"),
1800
1892
  "aria-label": "Neutral",
1801
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_icons_dev.FaceRegular, {}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "Regular" })]
1893
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_link.FaceRegular, {}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "Regular" })]
1802
1894
  }),
1803
1895
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
1804
1896
  type: "button",
1805
1897
  onClick: () => setRating("bad"),
1806
- className: require_icons_dev.cn("flex items-center gap-1.5 px-3 py-1.5 rounded-lg border text-sm font-medium transition-all duration-200 outline-none cursor-pointer", rating === "bad" ? "border-primary-500 bg-primary-500/10 text-primary-500 dark:text-primary-400" : "border-subtle hover:border-body hover:bg-surface text-muted hover:text-body"),
1898
+ className: require_link.cn("flex items-center gap-1.5 px-3 py-1.5 rounded-lg border text-sm font-medium transition-all duration-200 outline-none cursor-pointer", rating === "bad" ? "border-primary-500 bg-primary-500/10 text-primary-500 dark:text-primary-400" : "border-subtle hover:border-body hover:bg-surface text-muted hover:text-body"),
1807
1899
  "aria-label": "Not helpful",
1808
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_icons_dev.FaceBad, {}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "No" })]
1900
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_link.FaceBad, {}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "No" })]
1809
1901
  })
1810
1902
  ]
1811
1903
  })]
@@ -1840,7 +1932,7 @@ function Feedback({ className }) {
1840
1932
  //#endregion
1841
1933
  //#region src/client/components/ui-base/giscus.tsx
1842
1934
  function Giscus({ className }) {
1843
- const config = require_icons_dev.useConfig();
1935
+ const config = require_link.useConfig();
1844
1936
  const { resolvedTheme } = require_image.useTheme();
1845
1937
  const ref = (0, react.useRef)(null);
1846
1938
  const initializedRef = (0, react.useRef)(false);
@@ -1896,7 +1988,7 @@ function Giscus({ className }) {
1896
1988
  if (!giscusConfig) return null;
1897
1989
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1898
1990
  ref,
1899
- className: require_icons_dev.cn("w-full max-w-2xl mt-12 mb-6", className)
1991
+ className: require_link.cn("w-full max-w-2xl mt-12 mb-6", className)
1900
1992
  });
1901
1993
  }
1902
1994
 
@@ -1929,7 +2021,7 @@ const EagerMdxElement = ({ moduleLoader, moduleKey, route, components, collectio
1929
2021
  if (!MDXComponent) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Loading, {});
1930
2022
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MdxPage, {
1931
2023
  MDXComponent,
1932
- mdxComponents: components,
2024
+ mdxComponents: components ?? {},
1933
2025
  collectionPostComponent
1934
2026
  });
1935
2027
  };
@@ -1938,14 +2030,36 @@ const NotFoundWrapper = () => {
1938
2030
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(components.NotFound || components["404"] || NotFound, {});
1939
2031
  };
1940
2032
 
2033
+ //#endregion
2034
+ //#region src/client/app/doc-route-context.tsx
2035
+ /**
2036
+ * Context that exposes the currently active route to every primitive in the
2037
+ * tree. Slot renderers and other primitives consume it via `useDocRoute()`
2038
+ * instead of calling `useRoutes()` directly so a single computation is shared
2039
+ * across the whole layout.
2040
+ *
2041
+ * `undefined` means "no active route" (e.g. on a not-found page or before the
2042
+ * routes context has hydrated).
2043
+ */
2044
+ const DocRouteContext = (0, react.createContext)(void 0);
2045
+ function DocRouteProvider({ value, children }) {
2046
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DocRouteContext.Provider, {
2047
+ value,
2048
+ children
2049
+ });
2050
+ }
2051
+
1941
2052
  //#endregion
1942
2053
  //#region src/client/app/docs-layout.tsx
1943
2054
  function DocsLayout({ collectionsData }) {
1944
- const { currentRoute } = require_icons_dev.useRoutes();
1945
- const content = /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_search_dialog$1.InternalErrorBoundary, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(virtual_boltdocs_layout.default, {
1946
- route: currentRoute,
1947
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_router_dom.Outlet, {})
1948
- }) });
2055
+ const { currentRoute } = require_link.useRoutes();
2056
+ const content = /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DocRouteProvider, {
2057
+ 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, {
2059
+ route: currentRoute,
2060
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_router_dom.Outlet, {})
2061
+ }) })
2062
+ });
1949
2063
  if (collectionsData) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CollectionsContext.Provider, {
1950
2064
  value: collectionsData,
1951
2065
  children: content
@@ -2038,15 +2152,15 @@ function buildDocRoutes(options) {
2038
2152
  moduleKey,
2039
2153
  moduleLoader: mod,
2040
2154
  route,
2041
- components
2155
+ components: components ?? {}
2042
2156
  }, moduleKey || path);
2043
2157
  } };
2044
2158
  };
2045
2159
  else routeRecord.element = /* @__PURE__ */ (0, react_jsx_runtime.jsx)(EagerMdxElement, {
2046
2160
  moduleKey,
2047
- moduleLoader,
2161
+ moduleLoader: moduleLoader ?? {},
2048
2162
  route,
2049
- components
2163
+ components: components ?? {}
2050
2164
  }, moduleKey || path);
2051
2165
  return routeRecord;
2052
2166
  });
@@ -2145,6 +2259,15 @@ function buildDocRoutes(options) {
2145
2259
  };
2146
2260
  }
2147
2261
 
2262
+ //#endregion
2263
+ //#region src/client/ssg/external-page-wrapper.tsx
2264
+ function ExternalPageWrapper({ children }) {
2265
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2266
+ className: "boltdocs-external-content h-screen overflow-y-auto",
2267
+ children
2268
+ });
2269
+ }
2270
+
2148
2271
  //#endregion
2149
2272
  //#region src/client/ssg/create-routes.external.tsx
2150
2273
  function buildExternalRoutes(options) {
@@ -2163,11 +2286,12 @@ function buildExternalRoutes(options) {
2163
2286
  locale: config.i18n?.defaultLocale,
2164
2287
  title: rawPath === "/" ? "Home" : rawPath.replace(/^\//, "").split("/").pop() || "Page",
2165
2288
  filePath: "",
2289
+ componentPath: "",
2166
2290
  headings: []
2167
2291
  });
2168
2292
  children.push({
2169
2293
  path,
2170
- element: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(EffectiveExternalLayout, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ExtComponent, {}) }),
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, {}) }) }),
2171
2295
  loader: async () => ({
2172
2296
  path,
2173
2297
  locale: config.i18n?.defaultLocale
@@ -2181,11 +2305,12 @@ function buildExternalRoutes(options) {
2181
2305
  locale,
2182
2306
  title: rawPath,
2183
2307
  filePath: "",
2308
+ componentPath: "",
2184
2309
  headings: []
2185
2310
  });
2186
2311
  children.push({
2187
2312
  path: localePath,
2188
- element: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(EffectiveExternalLayout, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ExtComponent, {}) }),
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, {}) }) }),
2189
2314
  loader: async () => ({
2190
2315
  path: localePath,
2191
2316
  locale
@@ -2200,21 +2325,107 @@ function buildExternalRoutes(options) {
2200
2325
  };
2201
2326
  }
2202
2327
 
2328
+ //#endregion
2329
+ //#region src/client/collections/hooks.ts
2330
+ const DEFAULT_COLLECTION = "blog";
2331
+ /**
2332
+ * Returns the posts of a collection, filtered by the current locale and version.
2333
+ * Defaults to "blog" if no collection is specified.
2334
+ * @param collection - The name of the collection. Defaults to "blog".
2335
+ * @param options - Options to customize the query.
2336
+ * @param options.includeDrafts - If true, includes draft posts in the results.
2337
+ * @returns The filtered posts of the collection.
2338
+ */
2339
+ function usePosts(collection = DEFAULT_COLLECTION, options) {
2340
+ const data = useCollectionsData();
2341
+ const { currentLocale, currentVersion } = require_link.useRoutes();
2342
+ const config = require_link.useConfig();
2343
+ const posts = data[collection] || [];
2344
+ const defaultLocale = config.i18n?.defaultLocale;
2345
+ const defaultVersion = config.versions?.defaultVersion;
2346
+ return (0, react.useMemo)(() => {
2347
+ return posts.filter((post) => {
2348
+ const postLocale = post.locale || defaultLocale;
2349
+ const postVersion = post.version || defaultVersion;
2350
+ const localeMatch = !currentLocale || postLocale === currentLocale;
2351
+ const versionMatch = !currentVersion || postVersion === currentVersion;
2352
+ const draftMatch = options?.includeDrafts || !post.draft;
2353
+ return localeMatch && versionMatch && draftMatch;
2354
+ });
2355
+ }, [
2356
+ posts,
2357
+ currentLocale,
2358
+ currentVersion,
2359
+ defaultLocale,
2360
+ defaultVersion,
2361
+ options?.includeDrafts
2362
+ ]);
2363
+ }
2364
+ function usePost(collection, slug) {
2365
+ const ctx = useCurrentPostData();
2366
+ const posts = usePosts(collection);
2367
+ if (ctx && !slug) {
2368
+ const { route } = ctx;
2369
+ return (0, react.useMemo)(() => ({
2370
+ path: route.path,
2371
+ title: route.title,
2372
+ date: route.date,
2373
+ excerpt: route.excerpt,
2374
+ tags: route.tags,
2375
+ author: route.author,
2376
+ coverImage: route.coverImage,
2377
+ filePath: route.filePath,
2378
+ locale: route.locale,
2379
+ version: route.version,
2380
+ frontmatter: route.frontmatter,
2381
+ lastUpdated: route.lastUpdated,
2382
+ headings: route.headings
2383
+ }), [route]);
2384
+ }
2385
+ if (!collection || !slug) return void 0;
2386
+ return (0, react.useMemo)(() => posts.find((p) => p.path === `/${collection}/${slug}` || p.path.endsWith(`/${slug}`) || p.path === slug), [
2387
+ posts,
2388
+ collection,
2389
+ slug
2390
+ ]);
2391
+ }
2392
+ /**
2393
+ * Returns the recent posts of a collection. Defaults to "blog".
2394
+ * @param collection - The name of the collection. Defaults to "blog".
2395
+ * @param count - The number of recent posts to return.
2396
+ * @returns The recent posts of the collection.
2397
+ */
2398
+ function useRecentPosts(collection = DEFAULT_COLLECTION, count = 5) {
2399
+ const posts = usePosts(collection);
2400
+ return (0, react.useMemo)(() => posts.slice(0, count), [posts, count]);
2401
+ }
2402
+
2203
2403
  //#endregion
2204
2404
  //#region src/client/ssg/create-routes.collection.tsx
2205
2405
  function DefaultCollectionList() {
2206
- const data = (0, react_router_dom.useLoaderData)();
2207
- if (!data || !data.posts) return null;
2406
+ const location = (0, react_router_dom.useLocation)();
2407
+ const config = require_link.useConfig();
2408
+ 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;
2413
+ const allPosts = usePosts(collection);
2414
+ const totalPages = Math.ceil(allPosts.length / postsPerPage);
2415
+ const start = (currentPage - 1) * postsPerPage;
2416
+ const posts = allPosts.slice(start, start + postsPerPage);
2417
+ if (!posts.length) return null;
2418
+ const basePath = isLocalePrefixed ? `/${segments[0]}/${segments[1]}` : `/${segments[0]}`;
2208
2419
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2209
2420
  className: "py-8 max-w-2xl mx-auto px-4",
2210
2421
  children: [
2211
2422
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h1", {
2212
2423
  className: "text-3xl font-bold mb-6 capitalize",
2213
- children: data.collection
2424
+ children: collection
2214
2425
  }),
2215
2426
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2216
2427
  className: "space-y-6",
2217
- children: data.posts.map((post) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("article", {
2428
+ children: posts.map((post) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("article", {
2218
2429
  className: "border-b border-subtle pb-4",
2219
2430
  children: [
2220
2431
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h2", {
@@ -2236,22 +2447,22 @@ function DefaultCollectionList() {
2236
2447
  ]
2237
2448
  }, post.path))
2238
2449
  }),
2239
- data.totalPages > 1 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2450
+ totalPages > 1 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2240
2451
  className: "mt-8 flex gap-4 text-sm",
2241
2452
  children: [
2242
- data.currentPage > 1 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_router_dom.Link, {
2243
- to: data.currentPage === 2 ? `/${data.collection}` : `/${data.collection}/page/${data.currentPage - 1}`,
2453
+ currentPage > 1 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_router_dom.Link, {
2454
+ to: currentPage === 2 ? basePath : `${basePath}/page/${currentPage - 1}`,
2244
2455
  className: "text-primary-600 hover:underline",
2245
2456
  children: "Previous"
2246
2457
  }),
2247
2458
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [
2248
2459
  "Page ",
2249
- data.currentPage,
2460
+ currentPage,
2250
2461
  " of ",
2251
- data.totalPages
2462
+ totalPages
2252
2463
  ] }),
2253
- data.currentPage < data.totalPages && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_router_dom.Link, {
2254
- to: `/${data.collection}/page/${data.currentPage + 1}`,
2464
+ currentPage < totalPages && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_router_dom.Link, {
2465
+ to: `${basePath}/page/${currentPage + 1}`,
2255
2466
  className: "text-primary-600 hover:underline",
2256
2467
  children: "Next"
2257
2468
  })
@@ -2342,6 +2553,9 @@ function buildCollectionRoutes(options) {
2342
2553
  author: r.author,
2343
2554
  coverImage: r.coverImage,
2344
2555
  filePath: r.filePath,
2556
+ locale: r.locale,
2557
+ version: r.version,
2558
+ lastUpdated: r.lastUpdated,
2345
2559
  frontmatter: r.frontmatter
2346
2560
  }));
2347
2561
  const ListElement = collectionLists?.[colName] || DefaultCollectionList;
@@ -2399,7 +2613,7 @@ function createRoutes(options) {
2399
2613
  ...collectionRoutes.children,
2400
2614
  {
2401
2615
  path: "*",
2402
- element: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(EffectiveExternalLayout, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(NotFoundWrapper, {}) })
2616
+ element: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ExternalPageWrapper, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(EffectiveExternalLayout, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(NotFoundWrapper, {}) }) })
2403
2617
  }
2404
2618
  ];
2405
2619
  return [{
@@ -2419,21 +2633,17 @@ function createRoutes(options) {
2419
2633
 
2420
2634
  //#endregion
2421
2635
  //#region src/client/components/docs-layout-default.tsx
2636
+ /**
2637
+ * Default docs layout — composes the visual primitives and delegates
2638
+ * sub-area routing to them. Slot rendering (plugin injections at
2639
+ * `navbar:end`, `sidebar:bottom`, `docs-content:top`, etc.) is handled
2640
+ * internally by each primitive so the layout itself does no slot "magic".
2641
+ *
2642
+ * A custom layout can reuse any primitive and the slot wiring just works.
2643
+ */
2422
2644
  function DocsLayoutComponent({ children }) {
2423
- const { routes: filteredRoutes, currentRoute, isCollectionPage } = require_icons_dev.useRoutes();
2424
- const config = require_icons_dev.useConfig();
2425
- const AskAiDialog = useMergedComponents().AskAiDialog;
2426
- const [isAskAiOpen, setIsAskAiOpen] = (0, react.useState)(false);
2427
- (0, react.useEffect)(() => {
2428
- const handleOpen = () => setIsAskAiOpen(true);
2429
- const handleClose = () => setIsAskAiOpen(false);
2430
- window.addEventListener("boltdocs:ask-ai:open", handleOpen);
2431
- window.addEventListener("boltdocs:ask-ai:close", handleClose);
2432
- return () => {
2433
- window.removeEventListener("boltdocs:ask-ai:open", handleOpen);
2434
- window.removeEventListener("boltdocs:ask-ai:close", handleClose);
2435
- };
2436
- }, []);
2645
+ const { routes: filteredRoutes, currentRoute, isCollectionPage } = require_link.useRoutes();
2646
+ const config = require_link.useConfig();
2437
2647
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_docs_layout.DocsLayout, {
2438
2648
  className: "selection:bg-primary-500/10 selection:text-primary-500",
2439
2649
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Navbar, {}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_docs_layout.DocsLayout.Body, {
@@ -2443,97 +2653,46 @@ function DocsLayoutComponent({ children }) {
2443
2653
  routes: filteredRoutes || [],
2444
2654
  config
2445
2655
  }),
2446
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_docs_layout.DocsLayout.Content, {
2447
- className: "animate-in fade-in duration-500 scroll-smooth",
2448
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_docs_layout.DocsLayout.ContentMdx, {
2449
- className: "max-w-3xl sm:max-w-4xl lg:max-w-5xl px-4 sm:px-6 pt-8 pb-24",
2450
- children: [
2451
- !isCollectionPage && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_docs_layout.DocsLayout.Header, { children: [
2452
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2453
- className: "mb-4 border-b border-subtle pb-4 flex flex-wrap items-center justify-between gap-3",
2454
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Breadcrumbs, {}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CopyMarkdown, {
2455
- mdxRaw: currentRoute?._rawContent,
2456
- route: currentRoute
2457
- })]
2458
- }),
2459
- currentRoute?.title && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h1", {
2460
- className: "text-4xl font-bold tracking-tight text-default mb-3",
2461
- children: currentRoute.title
2462
- }),
2463
- currentRoute?.description && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
2464
- className: "text-lg text-muted-foreground mb-6 leading-relaxed",
2465
- children: currentRoute.description
2466
- })
2467
- ] }),
2468
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ErrorBoundary, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2469
- className: "prose prose-neutral dark:prose-invert max-w-none",
2470
- children
2471
- }) }),
2472
- !isCollectionPage && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Feedback, {}),
2473
- !isCollectionPage && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Giscus, {}),
2474
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_docs_layout.DocsLayout.Footer, { children: !isCollectionPage && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PageNav, {}) })
2475
- ]
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
2672
+ })
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
+ ] }) }),
2682
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2683
+ className: "overflow-y-auto sticky",
2684
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(OnThisPage, {
2685
+ headings: currentRoute?.headings,
2686
+ filePath: currentRoute?.filePath,
2687
+ communityHelp: config.theme?.communityHelp,
2688
+ editLink: config.theme?.editLink
2476
2689
  })
2477
- }),
2478
- AskAiDialog && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AskAiDialog, {}),
2479
- !isCollectionPage && !isAskAiOpen && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(OnThisPage, {
2480
- headings: currentRoute?.headings,
2481
- filePath: currentRoute?.filePath,
2482
- communityHelp: config.theme?.communityHelp,
2483
- editLink: config.theme?.editLink
2484
2690
  })
2485
2691
  ]
2486
2692
  })]
2487
2693
  });
2488
2694
  }
2489
2695
 
2490
- //#endregion
2491
- //#region src/client/collections/hooks.ts
2492
- /**
2493
- * Returns the posts of a collection.
2494
- * @param collection - The name of the collection.
2495
- * @returns The posts of the collection.
2496
- */
2497
- function usePosts(collection) {
2498
- const data = useCollectionsData();
2499
- const { currentLocale, currentVersion } = require_icons_dev.useRoutes();
2500
- const config = require_icons_dev.useConfig();
2501
- const posts = data[collection] || [];
2502
- const defaultLocale = config.i18n?.defaultLocale;
2503
- const defaultVersion = config.versions?.defaultVersion;
2504
- return (0, react.useMemo)(() => {
2505
- return posts.filter((post) => {
2506
- const postLocale = post.locale || defaultLocale;
2507
- const postVersion = post.version || defaultVersion;
2508
- return (!currentLocale || postLocale === currentLocale) && (!currentVersion || postVersion === currentVersion);
2509
- });
2510
- }, [
2511
- posts,
2512
- currentLocale,
2513
- currentVersion,
2514
- defaultLocale,
2515
- defaultVersion
2516
- ]);
2517
- }
2518
- function usePost(collection, slug) {
2519
- const posts = usePosts(collection);
2520
- return (0, react.useMemo)(() => posts.find((p) => p.path === `/${collection}/${slug}` || p.path.endsWith(`/${slug}`) || p.path === slug), [
2521
- posts,
2522
- collection,
2523
- slug
2524
- ]);
2525
- }
2526
- /**
2527
- * Returns the recent posts of a collection.
2528
- * @param collection - The name of the collection.
2529
- * @param count - The number of recent posts to return.
2530
- * @returns The recent posts of the collection.
2531
- */
2532
- function useRecentPosts(collection, count = 5) {
2533
- const posts = usePosts(collection);
2534
- return (0, react.useMemo)(() => posts.slice(0, count), [posts, count]);
2535
- }
2536
-
2537
2696
  //#endregion
2538
2697
  //#region src/client/utils/react-to-text.ts
2539
2698
  const reactToText = (node, resolvers) => {
@@ -2554,6 +2713,7 @@ exports.BoltdocsShell = BoltdocsShell;
2554
2713
  exports.Breadcrumbs = Breadcrumbs;
2555
2714
  exports.CollectionsContext = CollectionsContext;
2556
2715
  exports.CopyMarkdown = CopyMarkdown;
2716
+ exports.CurrentPostProvider = CurrentPostProvider;
2557
2717
  exports.DocsLayout = DocsLayoutComponent;
2558
2718
  exports.ErrorBoundary = ErrorBoundary;
2559
2719
  exports.MdxPage = MdxPage;
@@ -2563,13 +2723,14 @@ exports.OnThisPage = OnThisPage;
2563
2723
  exports.PageNav = PageNav;
2564
2724
  exports.SearchDialog = require_search_dialog$1.SearchDialog;
2565
2725
  exports.Sidebar = Sidebar;
2726
+ exports.Timeline = require_mdx.Timeline;
2566
2727
  Object.defineProperty(exports, 'ViteReactSSG', {
2567
2728
  enumerable: true,
2568
2729
  get: function () {
2569
2730
  return _bdocs_ssg.ViteReactSSG;
2570
2731
  }
2571
2732
  });
2572
- exports.cn = require_icons_dev.cn;
2733
+ exports.cn = require_link.cn;
2573
2734
  exports.copyToClipboard = require_mdx.copyToClipboard;
2574
2735
  exports.createRoutes = createRoutes;
2575
2736
  exports.getStarsRepo = getStarsRepo;
@@ -2578,11 +2739,11 @@ exports.reactToText = reactToText;
2578
2739
  exports.useAnalytics = useAnalytics;
2579
2740
  exports.useBreadcrumbs = useBreadcrumbs;
2580
2741
  exports.useCodeBlock = require_mdx.useCodeBlock;
2581
- exports.useConfig = require_icons_dev.useConfig;
2742
+ exports.useConfig = require_link.useConfig;
2582
2743
  exports.useFeedback = useFeedback;
2583
2744
  exports.useHeadings = useHeadings;
2584
2745
  exports.useI18n = useI18n;
2585
- exports.useLocalizedTo = require_icons_dev.useLocalizedTo;
2746
+ exports.useLocalizedTo = require_link.useLocalizedTo;
2586
2747
  exports.useLocation = require_docs_layout.useLocation;
2587
2748
  exports.useMdxComponents = useMdxComponents;
2588
2749
  exports.useMergedComponents = useMergedComponents;
@@ -2591,7 +2752,7 @@ exports.usePageNav = usePageNav;
2591
2752
  exports.usePost = usePost;
2592
2753
  exports.usePosts = usePosts;
2593
2754
  exports.useRecentPosts = useRecentPosts;
2594
- exports.useRoutes = require_icons_dev.useRoutes;
2755
+ exports.useRoutes = require_link.useRoutes;
2595
2756
  exports.useSearch = require_search_dialog$1.useSearch;
2596
2757
  exports.useSearchHighlight = require_docs_layout.useSearchHighlight;
2597
2758
  exports.useSidebar = require_docs_layout.useSidebar;