boltdocs 3.0.1 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (113) hide show
  1. package/README.md +2 -18
  2. package/dist/{adapters-C5AWWGfb.cjs → adapters-uGz-UKQa.cjs} +1 -1
  3. package/dist/{banner-DNSkgUsO.d.cts → banner-DdSgCs4G.d.cts} +1 -1
  4. package/dist/{banner-CfdalYLL.d.ts → banner-DjujkctF.d.ts} +1 -1
  5. package/dist/cache-B0C2i0yP.mjs +6 -0
  6. package/dist/cache-CfRTUzWC.cjs +6 -0
  7. package/dist/chunk-hT5z_Zn9-DsJawvsz.mjs +6 -0
  8. package/dist/chunk-hT5z_Zn9-SKz6VFXu.cjs +6 -0
  9. package/dist/client/index.cjs +227 -101
  10. package/dist/client/index.d.cts +57 -16
  11. package/dist/client/index.d.ts +57 -16
  12. package/dist/client/index.js +227 -102
  13. package/dist/client/mdx.cjs +1 -1
  14. package/dist/client/mdx.js +1 -1
  15. package/dist/client/primitives.cjs +4 -4
  16. package/dist/client/primitives.d.cts +1 -1
  17. package/dist/client/primitives.d.ts +1 -1
  18. package/dist/client/primitives.js +4 -4
  19. package/dist/client/theme/neutral.css +1 -3
  20. package/dist/{config-JGkMJoJQ.cjs → config-BxsogK5A.cjs} +1 -1
  21. package/dist/config-DAgpZyh6.mjs +7 -0
  22. package/dist/config-DrRQYDCI.cjs +7 -0
  23. package/dist/{docs-layout-3TpAt6MB.cjs → docs-layout-D1buSdua.cjs} +1 -1
  24. package/dist/{docs-layout-6FQ8__ok.js → docs-layout-DyLDBwS6.js} +1 -1
  25. package/dist/{doctor-DQxLM202.cjs → doctor-BadGEhXv.cjs} +1 -1
  26. package/dist/{doctor-BR1B2Mkz.cjs → doctor-DPDcRKM1.cjs} +1 -1
  27. package/dist/{doctor-3MheVMwd.mjs → doctor-vDsUDgqp.mjs} +1 -1
  28. package/dist/escape-string-regexp-AG8q1e25-9Un9V90q.mjs +6 -0
  29. package/dist/escape-string-regexp-AG8q1e25-bJ9Ixe7c.cjs +6 -0
  30. package/dist/esm-shims-DSep1HcR.mjs +6 -0
  31. package/dist/{icons-dev-kJyGWNeg.js → icons-dev-CHZOwhQA.js} +8 -3
  32. package/dist/{icons-dev-BryEFkJu.cjs → icons-dev-YtDoLUsb.cjs} +8 -3
  33. package/dist/{image-C9md50h2.js → image-5WsgWYTh.js} +2 -2
  34. package/dist/{image-CR6UlaI5.cjs → image-Hb105Gu6.cjs} +2 -2
  35. package/dist/lib-BR0SoanK-CLswltLI.cjs +6 -0
  36. package/dist/lib-BR0SoanK-DcYeDrE6.mjs +6 -0
  37. package/dist/lib-DPoCz1YB-CLYXwKST.cjs +6 -0
  38. package/dist/lib-DPoCz1YB-CyGOqgSO.mjs +6 -0
  39. package/dist/{mdx-DhyMkc35.js → mdx-Bv-pS6-O.js} +6 -2
  40. package/dist/{mdx-DJBg5DuL.cjs → mdx-CDUcJmye.cjs} +6 -2
  41. package/dist/micromark-util-character-5KqJafVT-C6gnc770.cjs +6 -0
  42. package/dist/micromark-util-character-5KqJafVT-DkPKsbgn.mjs +6 -0
  43. package/dist/node/cache.cjs +6 -0
  44. package/dist/node/cache.d.cts +83 -0
  45. package/dist/node/cache.d.mts +83 -0
  46. package/dist/node/cache.mjs +6 -0
  47. package/dist/node/cli-entry.cjs +3 -3
  48. package/dist/node/cli-entry.mjs +3 -3
  49. package/dist/node/index.cjs +1 -1
  50. package/dist/node/index.d.cts +10 -467
  51. package/dist/node/index.d.mts +12 -468
  52. package/dist/node/index.mjs +1 -1
  53. package/dist/node/mdx/shiki-adapter.cjs +6 -0
  54. package/dist/node/mdx/shiki-adapter.d.cts +3 -0
  55. package/dist/node/mdx/shiki-adapter.d.mts +3 -0
  56. package/dist/node/mdx/shiki-adapter.mjs +6 -0
  57. package/dist/node-BDBv8CT6.mjs +104 -0
  58. package/dist/node-DFV_FV0y.mjs +6 -0
  59. package/dist/node-DqsP7kXz.cjs +6 -0
  60. package/dist/node-yFmAavND.cjs +104 -0
  61. package/dist/{package-BovY3RQH.mjs → package-CoHWTf0N.mjs} +1 -1
  62. package/dist/{package-DnyxhwD-.cjs → package-_-Oa8-qN.cjs} +1 -1
  63. package/dist/{parser-D0QHIQsi.mjs → parser-BZJgAa9E.mjs} +1 -1
  64. package/dist/{parser-CNIPHx4s.cjs → parser-DlanzESE.cjs} +1 -1
  65. package/dist/plugin-BVuwx5D9.cjs +73 -0
  66. package/dist/plugin-BoxD91Yh.mjs +73 -0
  67. package/dist/rehype-slug--ZOxZ-_K-BNeYC4aT.cjs +6 -0
  68. package/dist/rehype-slug--ZOxZ-_K-CjIQEJCs.mjs +6 -0
  69. package/dist/remark-frontmatter-wFYRLcCt-CutW0gA3.mjs +8 -0
  70. package/dist/remark-frontmatter-wFYRLcCt-ENB5qG3y.cjs +8 -0
  71. package/dist/remark-gfm-B8TMkQbX-CjUJo8Rd.cjs +21 -0
  72. package/dist/remark-gfm-B8TMkQbX-Ctu0VV1_.mjs +21 -0
  73. package/dist/rollup-DMqoG11U-CKcJ37u_.mjs +59 -0
  74. package/dist/rollup-DMqoG11U-DKdxvZIj.cjs +59 -0
  75. package/dist/routes-BN2XbGcT.mjs +6 -0
  76. package/dist/routes-Cnq8xTCv.cjs +6 -0
  77. package/dist/{routes-BajCwrvX.cjs → routes-D_S9kjkS.cjs} +1 -1
  78. package/dist/{search-dialog-cHJoKjts.cjs → search-dialog-BIuxGQsg.cjs} +1 -1
  79. package/dist/{search-dialog-CwNh8lIN.cjs → search-dialog-BbtxA1uT.cjs} +12 -10
  80. package/dist/{search-dialog-D4rplZMv.cjs → search-dialog-BpNULmrl.cjs} +1 -1
  81. package/dist/{search-dialog-DoGobmuG.js → search-dialog-DC7oXU-5.js} +12 -10
  82. package/dist/{search-dialog-DaeSPvEo.js → search-dialog-PJrFRU5G.js} +1 -1
  83. package/dist/{search-dialog-CQneRo8T.js → search-dialog-gp9lrJXm.js} +1 -1
  84. package/dist/server/index.cjs +1 -1
  85. package/dist/server/index.d.mts +1 -1
  86. package/dist/shiki-adapter-CK3llqw2.mjs +6 -0
  87. package/dist/shiki-adapter-fS94vy-z.d.mts +534 -0
  88. package/dist/shiki-adapter-l2kEP5rn.d.cts +534 -0
  89. package/dist/{sidebar-BAKgJ-Er.d.ts → sidebar-DH2iPKXM.d.cts} +187 -10
  90. package/dist/{sidebar-7gIifpBX.d.cts → sidebar-DknLUI1R.d.ts} +187 -10
  91. package/package.json +15 -4
  92. package/src/shared/types.ts +177 -10
  93. package/dist/cache-DETwlACe.cjs +0 -6
  94. package/dist/cache-SF59enb3.mjs +0 -6
  95. package/dist/config-B5uVv5q4.cjs +0 -7
  96. package/dist/config-D3_zDkHh.mjs +0 -7
  97. package/dist/node-Ct4PB0S_.mjs +0 -105
  98. package/dist/node-joF9IMNr.cjs +0 -105
  99. package/dist/plugin-DeOYQvry.cjs +0 -68
  100. package/dist/plugin-IBKz7CRF.mjs +0 -68
  101. package/dist/routes-CyrnmVuG.mjs +0 -6
  102. package/dist/routes-D6Tuu7Fs.cjs +0 -6
  103. package/dist/shiki-adapter-CXEGRnjr.mjs +0 -6
  104. package/dist/shiki-adapter-Mr8_oT_9.cjs +0 -6
  105. /package/dist/{csp-CBysWlAf.cjs → csp-BX06rvdg.cjs} +0 -0
  106. /package/dist/{csp-gaZ51xzq.mjs → csp-z2D0FuRW.mjs} +0 -0
  107. /package/dist/{generator-DtUU3Cfk.cjs → generator-BN75lJOv.cjs} +0 -0
  108. /package/dist/{handler-Dzf4dSnV.cjs → handler-1LRMYeI4.cjs} +0 -0
  109. /package/dist/{headers-CXyf0auY.mjs → headers-CL0pMcwm.mjs} +0 -0
  110. /package/dist/{headers-BXKxiPUv.cjs → headers-YpD10rDb.cjs} +0 -0
  111. /package/dist/{index-CdJv4ocW.d.mts → index-DJYJzs-Z.d.mts} +0 -0
  112. /package/dist/{meta-loader-C4Hu9RN9.mjs → meta-loader-Bq-MjTXB.mjs} +0 -0
  113. /package/dist/{meta-loader-C9MKjAs0.cjs → meta-loader-CTB62-Mo.cjs} +0 -0
package/README.md CHANGED
@@ -1,12 +1,11 @@
1
1
  <h1 align="center">Boltdocs</h1>
2
2
 
3
3
  <p align="center">
4
- <strong>The fastest documentation framework. 2.5× faster warm builds than Docusaurus.</strong>
4
+ <strong>A modern documentation framework built with React, Vite, and MDX.</strong>
5
5
  </p>
6
6
 
7
7
  <p align="center">
8
8
  <a href="#quick-start"><img src="https://img.shields.io/badge/Quick_Start-blue?style=flat-square" alt="Quick Start" /></a>
9
- <a href="#benchmarks"><img src="https://img.shields.io/badge/Benchmarks-orange?style=flat-square" alt="Benchmarks" /></a>
10
9
  <a href="https://boltdocs.vercel.app"><img src="https://img.shields.io/badge/Live_Demo-purple?style=flat-square" alt="Live Demo" /></a>
11
10
  <br />
12
11
  <a href="https://www.npmjs.com/package/boltdocs"><img src="https://img.shields.io/npm/v/boltdocs?style=flat-square" alt="npm version" /></a>
@@ -18,21 +17,6 @@
18
17
 
19
18
  ---
20
19
 
21
- ## Benchmarks
22
-
23
- Real performance comparison with **100 pages** — Boltdocs vs Docusaurus:
24
-
25
- | Metric | Boltdocs | Docusaurus | Advantage |
26
- |--------|----------|------------|-----------|
27
- | **Cold build** (first build) | **15.66s** | 30.50s | **1.9× faster** |
28
- | **Warm rebuild** (cached) | **5.68s** | 14.24s | **2.5× faster** |
29
- | **Dev server start** | **2132ms** | 2612ms | **1.2× faster** |
30
- | **Zero-config setup** | **1 line** | 60+ lines | — |
31
-
32
- <sub>Benchmark source: `docs/src/data/benchmark-results.json`. 100-page project with identical content on both frameworks.</sub>
33
-
34
- ---
35
-
36
20
  ## Quick Start
37
21
 
38
22
  ```bash
@@ -52,7 +36,7 @@ mkdir docs && echo "# Hello World" > docs/index.md
52
36
 
53
37
  ## Why Boltdocs?
54
38
 
55
- **Zero config, instant docs.** A single command sets up a full documentation site with Tailwind CSS v4, TypeScript, MDX support, and a production-ready layout — no Docusaurus-style boilerplate.
39
+ **Zero config, instant docs.** A single command sets up a full documentation site with Tailwind CSS v4, TypeScript, MDX support, and a production-ready layout — zero boilerplate.
56
40
 
57
41
  **Built-in, not bolt-on.** i18n, versioning, full-text search, SEO, analytics (GA4/GTM), syntax highlighting (Shiki), image optimization, CSP headers, and a changelog generator — all ship as part of the framework, not as third-party plugins.
58
42
 
@@ -3,4 +3,4 @@
3
3
  * Copyright (c) 2026 Jesus Alcala
4
4
  * Licensed under the MIT License.
5
5
  */
6
- const e=require(`./handler-Dzf4dSnV.cjs`),t={"Access-Control-Allow-Origin":`*`,"Access-Control-Allow-Methods":`POST, OPTIONS`,"Access-Control-Allow-Headers":`Content-Type`,"Content-Type":`application/json`};async function n(n,r){if(Object.entries(t).forEach(([e,t])=>{r.setHeader(e,t)}),n.method===`OPTIONS`){r.status(200).end();return}if(n.method!==`POST`){r.status(405).json({error:`Method Not Allowed`});return}try{let t=await e.t(n.body,process.env);r.status(200).json(t)}catch(e){let t=e instanceof Error?e.message:`Failed to submit feedback`;return r.status(500).json({error:t})}}async function r(n,r=process.env){let i=(e,n=200)=>({statusCode:n,headers:t,body:e?JSON.stringify(e):``});if(n.httpMethod===`OPTIONS`)return i(null,200);if(n.httpMethod!==`POST`)return i({error:`Method Not Allowed`},405);try{return i(await e.t(n.body?JSON.parse(n.body):{},r))}catch(e){return i({error:e instanceof Error?e.message:`Failed to submit feedback`},500)}}async function i(n,r={}){let i=(e,n=200)=>new Response(e?JSON.stringify(e):null,{status:n,headers:t});if(n.method===`OPTIONS`)return i(null);if(n.method!==`POST`)return i({error:`Method Not Allowed`},405);try{return i(await e.t(await n.json(),{...process.env,...r}))}catch(e){return i({error:e instanceof Error?e.message:`Failed to submit feedback`},500)}}async function a(n,r=process.env){let i=(e,n=200)=>({statusCode:n,headers:t,body:e?JSON.stringify(e):``});if(n.httpMethod===`OPTIONS`)return i(null,200);if(n.httpMethod!==`POST`)return i({error:`Method Not Allowed`},405);try{return i(await e.t(n.body?JSON.parse(n.body):{},r))}catch(e){return i({error:e instanceof Error?e.message:`Failed to submit feedback`},500)}}Object.defineProperty(exports,`i`,{enumerable:!0,get:function(){return n}}),Object.defineProperty(exports,`n`,{enumerable:!0,get:function(){return i}}),Object.defineProperty(exports,`r`,{enumerable:!0,get:function(){return r}}),Object.defineProperty(exports,`t`,{enumerable:!0,get:function(){return a}});
6
+ const e=require(`./handler-1LRMYeI4.cjs`),t={"Access-Control-Allow-Origin":`*`,"Access-Control-Allow-Methods":`POST, OPTIONS`,"Access-Control-Allow-Headers":`Content-Type`,"Content-Type":`application/json`};async function n(n,r){if(Object.entries(t).forEach(([e,t])=>{r.setHeader(e,t)}),n.method===`OPTIONS`){r.status(200).end();return}if(n.method!==`POST`){r.status(405).json({error:`Method Not Allowed`});return}try{let t=await e.t(n.body,process.env);r.status(200).json(t)}catch(e){let t=e instanceof Error?e.message:`Failed to submit feedback`;return r.status(500).json({error:t})}}async function r(n,r=process.env){let i=(e,n=200)=>({statusCode:n,headers:t,body:e?JSON.stringify(e):``});if(n.httpMethod===`OPTIONS`)return i(null,200);if(n.httpMethod!==`POST`)return i({error:`Method Not Allowed`},405);try{return i(await e.t(n.body?JSON.parse(n.body):{},r))}catch(e){return i({error:e instanceof Error?e.message:`Failed to submit feedback`},500)}}async function i(n,r={}){let i=(e,n=200)=>new Response(e?JSON.stringify(e):null,{status:n,headers:t});if(n.method===`OPTIONS`)return i(null);if(n.method!==`POST`)return i({error:`Method Not Allowed`},405);try{return i(await e.t(await n.json(),{...process.env,...r}))}catch(e){return i({error:e instanceof Error?e.message:`Failed to submit feedback`},500)}}async function a(n,r=process.env){let i=(e,n=200)=>({statusCode:n,headers:t,body:e?JSON.stringify(e):``});if(n.httpMethod===`OPTIONS`)return i(null,200);if(n.httpMethod!==`POST`)return i({error:`Method Not Allowed`},405);try{return i(await e.t(n.body?JSON.parse(n.body):{},r))}catch(e){return i({error:e instanceof Error?e.message:`Failed to submit feedback`},500)}}Object.defineProperty(exports,`i`,{enumerable:!0,get:function(){return n}}),Object.defineProperty(exports,`n`,{enumerable:!0,get:function(){return i}}),Object.defineProperty(exports,`r`,{enumerable:!0,get:function(){return r}}),Object.defineProperty(exports,`t`,{enumerable:!0,get:function(){return a}});
@@ -1,5 +1,5 @@
1
1
 
2
- import { T as BoltdocsConfig, a as SidebarItem, d as SidebarMobile, f as SidebarRoot, i as SidebarHeader, l as SidebarLink, n as SidebarContent, p as SidebarSubGroup, r as SidebarGroup, s as SidebarItems, v as ComponentRoute, x as OnThisPageProps } from "./sidebar-7gIifpBX.cjs";
2
+ import { T as BoltdocsConfig, a as SidebarItem, d as SidebarMobile, f as SidebarRoot, i as SidebarHeader, l as SidebarLink, n as SidebarContent, p as SidebarSubGroup, r as SidebarGroup, s as SidebarItems, v as ComponentRoute, x as OnThisPageProps } from "./sidebar-DH2iPKXM.cjs";
3
3
  import { ReactNode } from "react";
4
4
  import * as _$react_jsx_runtime0 from "react/jsx-runtime";
5
5
 
@@ -1,5 +1,5 @@
1
1
 
2
- import { T as BoltdocsConfig, a as SidebarItem, d as SidebarMobile, f as SidebarRoot, i as SidebarHeader, l as SidebarLink, n as SidebarContent, p as SidebarSubGroup, r as SidebarGroup, s as SidebarItems, v as ComponentRoute, x as OnThisPageProps } from "./sidebar-BAKgJ-Er.js";
2
+ import { T as BoltdocsConfig, a as SidebarItem, d as SidebarMobile, f as SidebarRoot, i as SidebarHeader, l as SidebarLink, n as SidebarContent, p as SidebarSubGroup, r as SidebarGroup, s as SidebarItems, v as ComponentRoute, x as OnThisPageProps } from "./sidebar-DknLUI1R.js";
3
3
  import { ReactNode } from "react";
4
4
  import * as _$react_jsx_runtime0 from "react/jsx-runtime";
5
5
 
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Boltdocs - https://boltdocs.vercel.app
3
+ * Copyright (c) 2026 Jesus Alcala
4
+ * Licensed under the MIT License.
5
+ */
6
+ import{o as e}from"./utils-B3xYMrpK.mjs";import{globalBackgroundQueue as t}from"./node/cache.mjs";import n from"node:path";import r from"node:fs";import i from"node:crypto";const a=new Map,o=()=>{let t=e();return n.resolve(process.cwd(),t.dir,`parser`)},s=`v2.5`;var c=class{static async get(t){if(e().noCache)return null;try{let e=await r.promises.stat(t),c=a.get(t);if(c&&c.mtime===e.mtimeMs)return c.data;let l=o(),u=i.createHash(`md5`).update(t).digest(`hex`),d=n.join(l,`${u}.json`);try{let n=await r.promises.readFile(d,`utf-8`),i=JSON.parse(n);return i._mtime!==e.mtimeMs||i._v!==s?null:(a.set(t,{data:i.data,mtime:i._mtime}),i.data)}catch{return null}}catch{return null}}static async set(c,l){if(!e().noCache)try{let e=await r.promises.stat(c);a.set(c,{data:l,mtime:e.mtimeMs});let u=o(),d=i.createHash(`md5`).update(c).digest(`hex`),f=n.join(u,`${d}.json`),p={_v:s,_mtime:e.mtimeMs,data:l};t.add(async()=>{try{await r.promises.mkdir(u,{recursive:!0}),await r.promises.writeFile(f,JSON.stringify(p))}catch{}})}catch{}}static invalidate(e){a.delete(e)}static clear(){a.clear();let e=o();if(r.existsSync(e))try{r.rmSync(e,{recursive:!0,force:!0})}catch{}}};export{c as t};
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Boltdocs - https://boltdocs.vercel.app
3
+ * Copyright (c) 2026 Jesus Alcala
4
+ * Licensed under the MIT License.
5
+ */
6
+ const e=require(`./chunk-Ds5LZdWN.cjs`),t=require(`./utils-Bz1tG9Dg.cjs`),n=require(`./node/cache.cjs`);let r=require(`node:path`);r=e.n(r);let i=require(`node:fs`);i=e.n(i);let a=require(`node:crypto`);a=e.n(a);const o=new Map,s=()=>{let e=t.o();return r.default.resolve(process.cwd(),e.dir,`parser`)},c=`v2.5`;var l=class{static async get(e){if(t.o().noCache)return null;try{let t=await i.default.promises.stat(e),n=o.get(e);if(n&&n.mtime===t.mtimeMs)return n.data;let l=s(),u=a.default.createHash(`md5`).update(e).digest(`hex`),d=r.default.join(l,`${u}.json`);try{let n=await i.default.promises.readFile(d,`utf-8`),r=JSON.parse(n);return r._mtime!==t.mtimeMs||r._v!==c?null:(o.set(e,{data:r.data,mtime:r._mtime}),r.data)}catch{return null}}catch{return null}}static async set(e,l){if(!t.o().noCache)try{let t=await i.default.promises.stat(e);o.set(e,{data:l,mtime:t.mtimeMs});let u=s(),d=a.default.createHash(`md5`).update(e).digest(`hex`),f=r.default.join(u,`${d}.json`),p={_v:c,_mtime:t.mtimeMs,data:l};n.globalBackgroundQueue.add(async()=>{try{await i.default.promises.mkdir(u,{recursive:!0}),await i.default.promises.writeFile(f,JSON.stringify(p))}catch{}})}catch{}}static invalidate(e){o.delete(e)}static clear(){o.clear();let e=s();if(i.default.existsSync(e))try{i.default.rmSync(e,{recursive:!0,force:!0})}catch{}}};Object.defineProperty(exports,`t`,{enumerable:!0,get:function(){return l}});
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Boltdocs - https://boltdocs.vercel.app
3
+ * Copyright (c) 2026 Jesus Alcala
4
+ * Licensed under the MIT License.
5
+ */
6
+ import{createRequire as e}from"node:module";var t=Object.create,n=Object.defineProperty,r=Object.getOwnPropertyDescriptor,i=Object.getOwnPropertyNames,a=Object.getPrototypeOf,o=Object.prototype.hasOwnProperty,s=(e,t)=>()=>(t||(e((t={exports:{}}).exports,t),e=null),t.exports),c=(e,t)=>{let r={};for(var i in e)n(r,i,{get:e[i],enumerable:!0});return t||n(r,Symbol.toStringTag,{value:`Module`}),r},l=(e,t,a,s)=>{if(t&&typeof t==`object`||typeof t==`function`)for(var c=i(t),l=0,u=c.length,d;l<u;l++)d=c[l],!o.call(e,d)&&d!==a&&n(e,d,{get:(e=>t[e]).bind(null,d),enumerable:!(s=r(t,d))||s.enumerable});return e},u=(e,r,i)=>(i=e==null?{}:t(a(e)),l(r||!e||!e.__esModule?n(i,`default`,{value:e,enumerable:!0}):i,e)),d=e(import.meta.url);export{u as i,c as n,d as r,s as t};
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Boltdocs - https://boltdocs.vercel.app
3
+ * Copyright (c) 2026 Jesus Alcala
4
+ * Licensed under the MIT License.
5
+ */
6
+ require(`./chunk-Ds5LZdWN.cjs`);let e=require(`node:module`);var t=Object.create,n=Object.defineProperty,r=Object.getOwnPropertyDescriptor,i=Object.getOwnPropertyNames,a=Object.getPrototypeOf,o=Object.prototype.hasOwnProperty,s=(e,t)=>()=>(t||(e((t={exports:{}}).exports,t),e=null),t.exports),c=(e,t)=>{let r={};for(var i in e)n(r,i,{get:e[i],enumerable:!0});return t||n(r,Symbol.toStringTag,{value:`Module`}),r},l=(e,t,a,s)=>{if(t&&typeof t==`object`||typeof t==`function`)for(var c=i(t),l=0,u=c.length,d;l<u;l++)d=c[l],!o.call(e,d)&&d!==a&&n(e,d,{get:(e=>t[e]).bind(null,d),enumerable:!(s=r(t,d))||s.enumerable});return e},u=(e,r,i)=>(i=e==null?{}:t(a(e)),l(r||!e||!e.__esModule?n(i,`default`,{value:e,enumerable:!0}):i,e)),d=(0,e.createRequire)(require(`url`).pathToFileURL(__filename).href);Object.defineProperty(exports,`i`,{enumerable:!0,get:function(){return u}}),Object.defineProperty(exports,`n`,{enumerable:!0,get:function(){return c}}),Object.defineProperty(exports,`r`,{enumerable:!0,get:function(){return d}}),Object.defineProperty(exports,`t`,{enumerable:!0,get:function(){return s}});
@@ -4,18 +4,18 @@
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-CwNh8lIN.cjs');
7
+ const require_icons_dev = require('../icons-dev-YtDoLUsb.cjs');
8
+ const require_image = require('../image-Hb105Gu6.cjs');
9
+ const require_mdx = require('../mdx-CDUcJmye.cjs');
10
+ const require_docs_layout = require('../docs-layout-D1buSdua.cjs');
11
+ const require_search_dialog = require('../search-dialog-BpNULmrl.cjs');
12
+ const require_search_dialog$1 = require('../search-dialog-BbtxA1uT.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_aria_components = require("react-aria-components");
16
17
  let react_helmet_async = require("react-helmet-async");
17
18
  react_helmet_async = require_icons_dev.__toESM(react_helmet_async);
18
- let react_aria_components = require("react-aria-components");
19
19
  let virtual_boltdocs_mdx_components = require("virtual:boltdocs-mdx-components");
20
20
  virtual_boltdocs_mdx_components = require_icons_dev.__toESM(virtual_boltdocs_mdx_components);
21
21
  let virtual_boltdocs_icons = require("virtual:boltdocs-icons");
@@ -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
  /**
@@ -161,6 +147,28 @@ const mdxComponentsDefault = {
161
147
  "404": NotFound
162
148
  };
163
149
 
150
+ //#endregion
151
+ //#region src/client/app/helmet-compat.tsx
152
+ const mod = react_helmet_async;
153
+ /**
154
+ * The `<Helmet>` component, resolved across CJS/ESM module shapes.
155
+ * Falls back to a transparent fragment wrapper if the module cannot be resolved.
156
+ */
157
+ const Helmet = mod.Helmet || mod.default?.Helmet || (({ children }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, { children }));
158
+ /**
159
+ * The `<HelmetProvider>` component, resolved across CJS/ESM module shapes.
160
+ * Falls back to a transparent fragment wrapper if the module cannot be resolved.
161
+ */
162
+ const HelmetProvider = mod.HelmetProvider || mod.default?.HelmetProvider || (({ children }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, { children }));
163
+ if (typeof globalThis !== "undefined" && globalThis.__BOLTDOCS_SSG_RENDERING__) {
164
+ const hp = HelmetProvider;
165
+ if (hp && typeof hp === "function" && hp.canUseDOM) hp.canUseDOM = false;
166
+ }
167
+ if (typeof globalThis !== "undefined") {
168
+ globalThis.__BOLTDOCS_HELMET_PROVIDER__ = HelmetProvider;
169
+ globalThis.__BOLTDOCS_HELMET__ = Helmet;
170
+ }
171
+
164
172
  //#endregion
165
173
  //#region src/client/utils/i18n.ts
166
174
  /**
@@ -313,6 +321,16 @@ const CollectionsContext = (0, react.createContext)({});
313
321
  function useCollectionsData() {
314
322
  return (0, react.use)(CollectionsContext);
315
323
  }
324
+ const CurrentPostContext = (0, react.createContext)(null);
325
+ function CurrentPostProvider({ value, children }) {
326
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CurrentPostContext.Provider, {
327
+ value,
328
+ children
329
+ });
330
+ }
331
+ function useCurrentPostData() {
332
+ return (0, react.use)(CurrentPostContext);
333
+ }
316
334
 
317
335
  //#endregion
318
336
  //#region src/client/ssg/boltdocs-shell.tsx
@@ -382,7 +400,7 @@ function BoltdocsShell({ config, routes, components = {}, collectionsData }) {
382
400
  config,
383
401
  routeMap
384
402
  ]);
385
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(HelmetProvider, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_icons_dev.RoutesProvider, {
403
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_icons_dev.RoutesProvider, {
386
404
  routes,
387
405
  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
406
  components: allComponents,
@@ -410,7 +428,7 @@ function BoltdocsShell({ config, routes, components = {}, collectionsData }) {
410
428
  })
411
429
  })
412
430
  }) }) })
413
- }) });
431
+ });
414
432
  }
415
433
 
416
434
  //#endregion
@@ -455,17 +473,43 @@ function DocPage({ route, content: Content, mdxComponents: propComponents }) {
455
473
  /**
456
474
  * Renders an MDX page by consuming pre-loaded route data.
457
475
  *
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.
476
+ * - If the route belongs to a collection (`data.collection` is set), wraps
477
+ * the content with `CurrentPostProvider` so that `usePost()` (called without
478
+ * a slug) can read the current post's data from context.
460
479
  * - Otherwise, renders the standard `DocPage` layout.
461
480
  */
462
481
  function MdxPage({ MDXComponent, mdxComponents: propComponents, collectionPostComponent: CollectionPost }) {
463
482
  const data = (0, react_router_dom.useLoaderData)();
464
483
  if (!MDXComponent) return null;
465
- if (!!data?.collection && CollectionPost) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CollectionPost, {
466
- MDXComponent,
467
- mdxComponents: propComponents
468
- });
484
+ const collectionData = data;
485
+ if (!!collectionData?.collection) {
486
+ const postElement = CollectionPost ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CollectionPost, {
487
+ MDXComponent,
488
+ mdxComponents: propComponents
489
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DocPage, {
490
+ route: {
491
+ path: collectionData.route.path,
492
+ filePath: collectionData.route.filePath,
493
+ title: collectionData.route.title,
494
+ description: collectionData.route.description,
495
+ headings: collectionData.headings,
496
+ locale: collectionData.route.locale,
497
+ version: collectionData.route.version,
498
+ lastUpdated: collectionData.route.lastUpdated,
499
+ frontmatter: collectionData.route.frontmatter
500
+ },
501
+ content: MDXComponent,
502
+ mdxComponents: propComponents
503
+ });
504
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CurrentPostProvider, {
505
+ value: {
506
+ route: collectionData.route,
507
+ headings: collectionData.headings,
508
+ collection: collectionData.collection
509
+ },
510
+ children: postElement
511
+ });
512
+ }
469
513
  const docData = data;
470
514
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DocPage, {
471
515
  route: {
@@ -1028,7 +1072,7 @@ function VersionSelector({ className }) {
1028
1072
  function useI18n() {
1029
1073
  const navigate = (0, react_router_dom.useNavigate)();
1030
1074
  const config = require_icons_dev.useConfig();
1031
- const { allRoutes, currentRoute, currentLocale, currentVersion } = require_icons_dev.useRoutes();
1075
+ const { allRoutes, currentRoute, currentLocale, isCollectionPage } = require_icons_dev.useRoutes();
1032
1076
  const i18n = config.i18n;
1033
1077
  const { setLocale } = require_icons_dev.useBoltdocsContext();
1034
1078
  const handleLocaleChange = (locale) => {
@@ -1038,7 +1082,7 @@ function useI18n() {
1038
1082
  const safeBase = base === "/" ? "" : base.replace(/\/$/, "");
1039
1083
  const isDocRoute = !!currentRoute?.filePath;
1040
1084
  let targetPath = "";
1041
- if (currentRoute) if (isDocRoute) {
1085
+ if (currentRoute) if (isDocRoute && !currentRoute.collection && !isCollectionPage) {
1042
1086
  const baseFile = getBaseFilePath(currentRoute.filePath, currentRoute.version, currentRoute.locale);
1043
1087
  const targetRoute = allRoutes.find((r) => getBaseFilePath(r.filePath, r.version, r.locale) === baseFile && (r.locale || i18n.defaultLocale) === locale && r.version === currentRoute.version);
1044
1088
  if (targetRoute) targetPath = targetRoute.path;
@@ -1050,25 +1094,29 @@ function useI18n() {
1050
1094
  } else {
1051
1095
  let rawExternal = currentRoute.path;
1052
1096
  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();
1097
+ const localePosition = currentRoute.collection ? 1 : 0;
1098
+ if (parts.length > localePosition && (Array.isArray(i18n.locales) ? i18n.locales.includes(parts[localePosition]) : !!i18n.locales[parts[localePosition]])) {
1099
+ parts.splice(localePosition, 1);
1055
1100
  rawExternal = "/" + parts.join("/");
1056
1101
  }
1102
+ const cleanParts = rawExternal.split("/").filter(Boolean);
1057
1103
  if (locale === i18n.defaultLocale) targetPath = rawExternal === "" ? "/" : rawExternal;
1058
1104
  else {
1059
- const cleanExt = rawExternal.startsWith("/") ? rawExternal : `/${rawExternal}`;
1060
- targetPath = `/${locale}${cleanExt === "/" ? "" : cleanExt}`;
1105
+ cleanParts.splice(localePosition, 0, locale);
1106
+ targetPath = "/" + cleanParts.join("/") || "/";
1061
1107
  }
1062
1108
  }
1063
1109
  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;
1110
+ const currentPath = location.pathname;
1111
+ if (isCollectionPage) targetPath = currentPath;
1066
1112
  else {
1067
- const vPath = currentVersion && currentVersion !== config.versions?.defaultVersion ? `/${currentVersion}` : "";
1068
- targetPath = locale === i18n.defaultLocale ? `${safeBase}${vPath}` : `${safeBase}${vPath}/${locale}`;
1113
+ const parts = currentPath.split("/").filter(Boolean);
1114
+ if (parts.length > 0 && (Array.isArray(i18n.locales) ? i18n.locales.includes(parts[0]) : !!i18n.locales[parts[0]])) parts.shift();
1115
+ if (locale !== i18n.defaultLocale) parts.unshift(locale);
1116
+ targetPath = "/" + parts.join("/");
1069
1117
  }
1070
1118
  }
1071
- if (!targetPath || targetPath === "") targetPath = "/";
1119
+ if (!targetPath || targetPath === "") targetPath = "/s";
1072
1120
  targetPath = targetPath.replace(/\/+/g, "/");
1073
1121
  navigate(targetPath);
1074
1122
  };
@@ -1152,10 +1200,42 @@ function usePageNav() {
1152
1200
  //#region src/client/hooks/use-analytics.ts
1153
1201
  function createAnalyticsInstance(config) {
1154
1202
  if (typeof window === "undefined") return createDisabledAnalytics();
1203
+ if (window.posthog) return createPostHogAnalytics(config);
1155
1204
  if (typeof window.gtag === "function") return createGtagAnalytics(config);
1156
1205
  if (window.dataLayer) return createDataLayerAnalytics(config);
1157
1206
  return createDisabledAnalytics();
1158
1207
  }
1208
+ function createPostHogAnalytics(_config) {
1209
+ return {
1210
+ trackPageView: (path) => {
1211
+ window.posthog?.capture("$pageview", { $current_url: path });
1212
+ },
1213
+ trackEvent: ({ action, category, label, value, params }) => {
1214
+ window.posthog?.capture(action, {
1215
+ event_category: category,
1216
+ event_label: label,
1217
+ value,
1218
+ ...params
1219
+ });
1220
+ },
1221
+ trackSearch: (query, resultsCount) => {
1222
+ window.posthog?.capture("search", {
1223
+ query,
1224
+ results_count: resultsCount
1225
+ });
1226
+ },
1227
+ trackDownload: (file, type) => {
1228
+ window.posthog?.capture("file_download", {
1229
+ file_name: file,
1230
+ file_type: type || file.split(".").pop()
1231
+ });
1232
+ },
1233
+ trackExternalLink: (url) => {
1234
+ window.posthog?.capture("external_link", { link_url: url });
1235
+ },
1236
+ isEnabled: true
1237
+ };
1238
+ }
1159
1239
  function createGtagAnalytics(config) {
1160
1240
  return {
1161
1241
  trackPageView: (path, title) => {
@@ -1439,7 +1519,7 @@ function I18nSelector({ className }) {
1439
1519
 
1440
1520
  //#endregion
1441
1521
  //#region src/client/components/ui-base/navbar.tsx
1442
- const SearchDialog$1 = (0, react.lazy)(() => Promise.resolve().then(() => require("../search-dialog-cHJoKjts.cjs")).then((m) => ({ default: m.SearchDialog })));
1522
+ const SearchDialog$1 = (0, react.lazy)(() => Promise.resolve().then(() => require("../search-dialog-BIuxGQsg.cjs")).then((m) => ({ default: m.SearchDialog })));
1443
1523
  function Navbar() {
1444
1524
  const { links, title, logo, logoProps, github, social, config } = useNavbar();
1445
1525
  const { routes, currentRoute, isCollectionPage, currentVersion, currentLocale } = require_icons_dev.useRoutes();
@@ -1470,6 +1550,10 @@ function Navbar() {
1470
1550
  href: "site:/",
1471
1551
  children: title
1472
1552
  }),
1553
+ currentRoute?.draft && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1554
+ 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",
1555
+ children: "Draft"
1556
+ }),
1473
1557
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1474
1558
  className: "hidden sm:block",
1475
1559
  children: config.versions && currentVersion && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(VersionSelector, {})
@@ -2200,21 +2284,107 @@ function buildExternalRoutes(options) {
2200
2284
  };
2201
2285
  }
2202
2286
 
2287
+ //#endregion
2288
+ //#region src/client/collections/hooks.ts
2289
+ const DEFAULT_COLLECTION = "blog";
2290
+ /**
2291
+ * Returns the posts of a collection, filtered by the current locale and version.
2292
+ * Defaults to "blog" if no collection is specified.
2293
+ * @param collection - The name of the collection. Defaults to "blog".
2294
+ * @param options - Options to customize the query.
2295
+ * @param options.includeDrafts - If true, includes draft posts in the results.
2296
+ * @returns The filtered posts of the collection.
2297
+ */
2298
+ function usePosts(collection = DEFAULT_COLLECTION, options) {
2299
+ const data = useCollectionsData();
2300
+ const { currentLocale, currentVersion } = require_icons_dev.useRoutes();
2301
+ const config = require_icons_dev.useConfig();
2302
+ const posts = data[collection] || [];
2303
+ const defaultLocale = config.i18n?.defaultLocale;
2304
+ const defaultVersion = config.versions?.defaultVersion;
2305
+ return (0, react.useMemo)(() => {
2306
+ return posts.filter((post) => {
2307
+ const postLocale = post.locale || defaultLocale;
2308
+ const postVersion = post.version || defaultVersion;
2309
+ const localeMatch = !currentLocale || postLocale === currentLocale;
2310
+ const versionMatch = !currentVersion || postVersion === currentVersion;
2311
+ const draftMatch = options?.includeDrafts || !post.draft;
2312
+ return localeMatch && versionMatch && draftMatch;
2313
+ });
2314
+ }, [
2315
+ posts,
2316
+ currentLocale,
2317
+ currentVersion,
2318
+ defaultLocale,
2319
+ defaultVersion,
2320
+ options?.includeDrafts
2321
+ ]);
2322
+ }
2323
+ function usePost(collection, slug) {
2324
+ const ctx = useCurrentPostData();
2325
+ const posts = usePosts(collection);
2326
+ if (ctx && !slug) {
2327
+ const { route } = ctx;
2328
+ return (0, react.useMemo)(() => ({
2329
+ path: route.path,
2330
+ title: route.title,
2331
+ date: route.date,
2332
+ excerpt: route.excerpt,
2333
+ tags: route.tags,
2334
+ author: route.author,
2335
+ coverImage: route.coverImage,
2336
+ filePath: route.filePath,
2337
+ locale: route.locale,
2338
+ version: route.version,
2339
+ frontmatter: route.frontmatter,
2340
+ lastUpdated: route.lastUpdated,
2341
+ headings: route.headings
2342
+ }), [route]);
2343
+ }
2344
+ if (!collection || !slug) return void 0;
2345
+ return (0, react.useMemo)(() => posts.find((p) => p.path === `/${collection}/${slug}` || p.path.endsWith(`/${slug}`) || p.path === slug), [
2346
+ posts,
2347
+ collection,
2348
+ slug
2349
+ ]);
2350
+ }
2351
+ /**
2352
+ * Returns the recent posts of a collection. Defaults to "blog".
2353
+ * @param collection - The name of the collection. Defaults to "blog".
2354
+ * @param count - The number of recent posts to return.
2355
+ * @returns The recent posts of the collection.
2356
+ */
2357
+ function useRecentPosts(collection = DEFAULT_COLLECTION, count = 5) {
2358
+ const posts = usePosts(collection);
2359
+ return (0, react.useMemo)(() => posts.slice(0, count), [posts, count]);
2360
+ }
2361
+
2203
2362
  //#endregion
2204
2363
  //#region src/client/ssg/create-routes.collection.tsx
2205
2364
  function DefaultCollectionList() {
2206
- const data = (0, react_router_dom.useLoaderData)();
2207
- if (!data || !data.posts) return null;
2365
+ const location = (0, react_router_dom.useLocation)();
2366
+ const config = require_icons_dev.useConfig();
2367
+ const postsPerPage = config.collections?.postsPerPage ?? 10;
2368
+ const segments = location.pathname.split("/").filter(Boolean);
2369
+ const isLocalePrefixed = config.i18n && segments[0] in (config.i18n.locales || {});
2370
+ const collection = isLocalePrefixed ? segments[1] : segments[0];
2371
+ const currentPage = (isLocalePrefixed ? segments[3] : segments[2]) === "page" ? Number(isLocalePrefixed ? segments[4] : segments[3]) || 1 : 1;
2372
+ const allPosts = usePosts(collection);
2373
+ const totalPages = Math.ceil(allPosts.length / postsPerPage);
2374
+ const start = (currentPage - 1) * postsPerPage;
2375
+ const posts = allPosts.slice(start, start + postsPerPage);
2376
+ if (!posts.length) return null;
2377
+ const basePath = isLocalePrefixed ? `/${segments[0]}/${segments[1]}` : `/${segments[0]}`;
2208
2378
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2209
2379
  className: "py-8 max-w-2xl mx-auto px-4",
2210
2380
  children: [
2211
2381
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h1", {
2212
2382
  className: "text-3xl font-bold mb-6 capitalize",
2213
- children: data.collection
2383
+ children: collection
2214
2384
  }),
2215
2385
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2216
2386
  className: "space-y-6",
2217
- children: data.posts.map((post) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("article", {
2387
+ children: posts.map((post) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("article", {
2218
2388
  className: "border-b border-subtle pb-4",
2219
2389
  children: [
2220
2390
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h2", {
@@ -2236,22 +2406,22 @@ function DefaultCollectionList() {
2236
2406
  ]
2237
2407
  }, post.path))
2238
2408
  }),
2239
- data.totalPages > 1 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2409
+ totalPages > 1 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2240
2410
  className: "mt-8 flex gap-4 text-sm",
2241
2411
  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}`,
2412
+ currentPage > 1 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_router_dom.Link, {
2413
+ to: currentPage === 2 ? basePath : `${basePath}/page/${currentPage - 1}`,
2244
2414
  className: "text-primary-600 hover:underline",
2245
2415
  children: "Previous"
2246
2416
  }),
2247
2417
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [
2248
2418
  "Page ",
2249
- data.currentPage,
2419
+ currentPage,
2250
2420
  " of ",
2251
- data.totalPages
2421
+ totalPages
2252
2422
  ] }),
2253
- data.currentPage < data.totalPages && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_router_dom.Link, {
2254
- to: `/${data.collection}/page/${data.currentPage + 1}`,
2423
+ currentPage < totalPages && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_router_dom.Link, {
2424
+ to: `${basePath}/page/${currentPage + 1}`,
2255
2425
  className: "text-primary-600 hover:underline",
2256
2426
  children: "Next"
2257
2427
  })
@@ -2342,6 +2512,9 @@ function buildCollectionRoutes(options) {
2342
2512
  author: r.author,
2343
2513
  coverImage: r.coverImage,
2344
2514
  filePath: r.filePath,
2515
+ locale: r.locale,
2516
+ version: r.version,
2517
+ lastUpdated: r.lastUpdated,
2345
2518
  frontmatter: r.frontmatter
2346
2519
  }));
2347
2520
  const ListElement = collectionLists?.[colName] || DefaultCollectionList;
@@ -2422,18 +2595,6 @@ function createRoutes(options) {
2422
2595
  function DocsLayoutComponent({ children }) {
2423
2596
  const { routes: filteredRoutes, currentRoute, isCollectionPage } = require_icons_dev.useRoutes();
2424
2597
  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
- }, []);
2437
2598
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_docs_layout.DocsLayout, {
2438
2599
  className: "selection:bg-primary-500/10 selection:text-primary-500",
2439
2600
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Navbar, {}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_docs_layout.DocsLayout.Body, {
@@ -2475,8 +2636,7 @@ function DocsLayoutComponent({ children }) {
2475
2636
  ]
2476
2637
  })
2477
2638
  }),
2478
- AskAiDialog && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AskAiDialog, {}),
2479
- !isCollectionPage && !isAskAiOpen && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(OnThisPage, {
2639
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(OnThisPage, {
2480
2640
  headings: currentRoute?.headings,
2481
2641
  filePath: currentRoute?.filePath,
2482
2642
  communityHelp: config.theme?.communityHelp,
@@ -2487,41 +2647,6 @@ function DocsLayoutComponent({ children }) {
2487
2647
  });
2488
2648
  }
2489
2649
 
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
- return useCollectionsData()[collection] || [];
2499
- }
2500
- /**
2501
- * Returns a post by its slug.
2502
- * @param collection - The name of the collection.
2503
- * @param slug - The slug of the post.
2504
- * @returns The post with the given slug.
2505
- */
2506
- function usePost(collection, slug) {
2507
- const posts = usePosts(collection);
2508
- return (0, react.useMemo)(() => posts.find((p) => p.path === `/${collection}/${slug}` || p.path.endsWith(`/${slug}`) || p.path === slug), [
2509
- posts,
2510
- collection,
2511
- slug
2512
- ]);
2513
- }
2514
- /**
2515
- * Returns the recent posts of a collection.
2516
- * @param collection - The name of the collection.
2517
- * @param count - The number of recent posts to return.
2518
- * @returns The recent posts of the collection.
2519
- */
2520
- function useRecentPosts(collection, count = 5) {
2521
- const posts = usePosts(collection);
2522
- return (0, react.useMemo)(() => posts.slice(0, count), [posts, count]);
2523
- }
2524
-
2525
2650
  //#endregion
2526
2651
  //#region src/client/utils/react-to-text.ts
2527
2652
  const reactToText = (node, resolvers) => {
@@ -2542,6 +2667,7 @@ exports.BoltdocsShell = BoltdocsShell;
2542
2667
  exports.Breadcrumbs = Breadcrumbs;
2543
2668
  exports.CollectionsContext = CollectionsContext;
2544
2669
  exports.CopyMarkdown = CopyMarkdown;
2670
+ exports.CurrentPostProvider = CurrentPostProvider;
2545
2671
  exports.DocsLayout = DocsLayoutComponent;
2546
2672
  exports.ErrorBoundary = ErrorBoundary;
2547
2673
  exports.MdxPage = MdxPage;