boltdocs 3.2.2 → 3.3.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 (155) hide show
  1. package/bin/boltdocs.js +20 -1
  2. package/bin/preloader.mjs +28 -0
  3. package/dist/{adapters-ByYY44Zy.mjs → adapters-BmB4TKCc.mjs} +1 -1
  4. package/dist/{adapters-DvmtpdSF.cjs → adapters-Cp1Maurn.cjs} +1 -1
  5. package/dist/audit-CLXjMzwQ.mjs +11 -0
  6. package/dist/audit-COgjnQ5n.cjs +11 -0
  7. package/dist/build-BS2hefiL.cjs +6 -0
  8. package/dist/build-C5mNh9D-.mjs +6 -0
  9. package/dist/cache-CJE9nWLE.cjs +6 -0
  10. package/dist/cache-OY4HzIXl.mjs +6 -0
  11. package/dist/callout-oI_LCbxS.d.ts +71 -0
  12. package/dist/callout-plqx9Dw-.d.cts +71 -0
  13. package/dist/client/index.cjs +1265 -569
  14. package/dist/client/index.d.cts +3 -542
  15. package/dist/client/index.d.ts +3 -542
  16. package/dist/client/index.js +1167 -521
  17. package/dist/client/mdx.cjs +1 -1
  18. package/dist/client/mdx.d.cts +24 -2
  19. package/dist/client/mdx.d.ts +24 -2
  20. package/dist/client/mdx.js +1 -1
  21. package/dist/client/primitives.cjs +14 -4
  22. package/dist/client/primitives.d.cts +281 -38
  23. package/dist/client/primitives.d.ts +281 -38
  24. package/dist/client/primitives.js +5 -5
  25. package/dist/client/router.cjs +49 -0
  26. package/dist/client/router.d.cts +3 -0
  27. package/dist/client/router.d.ts +3 -0
  28. package/dist/client/router.js +8 -0
  29. package/dist/client/theme/reset.css +40 -4
  30. package/dist/{config-BpzaPsJj.d.cts → config-BoRlz0Ca.d.mts} +157 -14
  31. package/dist/{config-xtS0ZkMm.d.mts → config-CTsX_tGM.d.cts} +157 -14
  32. package/dist/config-Ceib-AOH.cjs +7 -0
  33. package/dist/config-DGLQsy7y.mjs +7 -0
  34. package/dist/{package-CH2ChQqw.cjs → config-files-BYHDOrKn.mjs} +1 -1
  35. package/dist/config-files-D9cdBMl2.cjs +6 -0
  36. package/dist/config-jJh8WYJI.cjs +6 -0
  37. package/dist/csp-C4LmN1ko.cjs +6 -0
  38. package/dist/csp-D6JEOqKh.mjs +6 -0
  39. package/dist/dev-Ch3hEe5Y.cjs +6 -0
  40. package/dist/dev-QPNxysrd.mjs +6 -0
  41. package/dist/{docs-layout-BdtZ9z6s.js → docs-layout-CbZ7LDRe.js} +504 -249
  42. package/dist/{docs-layout-CFWI15Id.cjs → docs-layout-vzfXed1Q.cjs} +516 -254
  43. package/dist/{doctor-BBtmNJE0.cjs → doctor-B1_YL0Wt.cjs} +1 -1
  44. package/dist/doctor-C7whl4ED.cjs +6 -0
  45. package/dist/doctor-DmQnml2k.mjs +6 -0
  46. package/dist/{generator-COepVWGi.cjs → generator-BlW45ST7.cjs} +5 -3
  47. package/dist/{generator-CcOBN5vI.mjs → generator-BwknNejd.mjs} +5 -3
  48. package/dist/{handler-XX7cLTqe.cjs → handler-CDEoKARD.cjs} +2 -2
  49. package/dist/{handler-DzQae4eA.mjs → handler-D7UyZlPm.mjs} +2 -2
  50. package/dist/{image-Bz87fCla.js → image-B-NDSDuY.js} +129 -11
  51. package/dist/{image-C4TlpMHn.cjs → image-Hnaa2bJd.cjs} +175 -9
  52. package/dist/index-C56bL-A-.d.cts +1344 -0
  53. package/dist/{sidebar-COTaMHR-.d.ts → index-CPUUKzxD.d.cts} +344 -327
  54. package/dist/{sidebar-CrEdJuHX.d.cts → index-Ci4kfOHF.d.ts} +344 -327
  55. package/dist/index-Cu9H6CRa.d.ts +1344 -0
  56. package/dist/link-CgdI6O2o.js +872 -0
  57. package/dist/{link-D1Gjkb-2.cjs → link-vZjmD-es.cjs} +406 -223
  58. package/dist/{mdx-BuO6a1f7.js → mdx-BRT71V5Q.js} +211 -168
  59. package/dist/{mdx-CD-tSjRG.cjs → mdx-D0Absdq5.cjs} +225 -169
  60. package/dist/native-BNCY7PRF.cjs +6 -0
  61. package/dist/native-Di9Fnfrv.mjs +6 -0
  62. package/dist/native-Kre2T5eS.cjs +6 -0
  63. package/dist/node/cache.cjs +1 -1
  64. package/dist/node/cache.d.cts +19 -3
  65. package/dist/node/cache.d.mts +19 -3
  66. package/dist/node/cache.mjs +1 -1
  67. package/dist/node/cli-entry.cjs +1 -9
  68. package/dist/node/cli-entry.mjs +1 -9
  69. package/dist/node/index.cjs +1 -1
  70. package/dist/node/index.d.cts +245 -17
  71. package/dist/node/index.d.mts +246 -18
  72. package/dist/node/index.mjs +1 -1
  73. package/dist/node/mdx/shiki-adapter.cjs +1 -1
  74. package/dist/node/mdx/shiki-adapter.d.cts +24 -3
  75. package/dist/node/mdx/shiki-adapter.d.mts +24 -2
  76. package/dist/node/mdx/shiki-adapter.mjs +1 -1
  77. package/dist/node-Du5UL5wo.mjs +23 -0
  78. package/dist/node-DunuGqyp.cjs +23 -0
  79. package/dist/{package-DSSB8B5L.mjs → package-DA848keM.mjs} +1 -1
  80. package/dist/package-wplzySjz.cjs +6 -0
  81. package/dist/pages-external-BBw8ObVK.mjs +6 -0
  82. package/dist/pages-external-DPiPFxxP.cjs +6 -0
  83. package/dist/parser-BqTOsEUa.cjs +6 -0
  84. package/dist/parser-CGMY2lJ7.mjs +6 -0
  85. package/dist/plugin-BcTzvHAJ.mjs +69 -0
  86. package/dist/plugin-TulVMt1z.cjs +69 -0
  87. package/dist/plugin-context-C-l90hFt.cjs +15 -0
  88. package/dist/plugin-context-wqHNSZum.mjs +15 -0
  89. package/dist/plugin-lifecycle-B1BzSHdn.cjs +6 -0
  90. package/dist/resolve-B7vWOd8R.cjs +6 -0
  91. package/dist/resolve-C2kKnk_5.mjs +6 -0
  92. package/dist/resolve-It1Iug83.cjs +6 -0
  93. package/dist/resolve-YdTrt_FG.mjs +6 -0
  94. package/dist/router-C3kygdRK.cjs +1285 -0
  95. package/dist/router-CZBxMRAH.js +987 -0
  96. package/dist/routes-BL4y79tb.mjs +6 -0
  97. package/dist/routes-C2nPecwu.cjs +6 -0
  98. package/dist/routes-U9L8psZ9.cjs +6 -0
  99. package/dist/{search-dialog-DHqwjJuG.cjs → search-dialog-BCOHQGSt.cjs} +1 -1
  100. package/dist/search-dialog-Bp_P1MPP.js +481 -0
  101. package/dist/{search-dialog-DFnlx8LO.js → search-dialog-BqkzDTq2.js} +107 -57
  102. package/dist/{search-dialog-BRFno7HD.cjs → search-dialog-CIeIUhAn.cjs} +218 -43
  103. package/dist/{search-dialog-D6TvjcuV.js → search-dialog-DtmxmfEu.js} +1 -1
  104. package/dist/{search-dialog-B1NERUNx.cjs → search-dialog-x_qHU8ty.cjs} +107 -58
  105. package/dist/server/index.cjs +1 -1
  106. package/dist/server/index.d.mts +1 -1
  107. package/dist/server/index.mjs +1 -1
  108. package/dist/update-check-BKqmYfwT.cjs +11 -0
  109. package/dist/update-check-QnrVR3q1.mjs +11 -0
  110. package/dist/utils-8lzafE49.mjs +7 -0
  111. package/dist/utils-ej6_SjIZ.cjs +7 -0
  112. package/dist/virtual-modules-Ca5tHk1X.cjs +30 -0
  113. package/dist/virtual-modules-Dlgt1fP0.mjs +30 -0
  114. package/package.json +18 -16
  115. package/src/shared/mdx-path.ts +12 -0
  116. package/src/shared/structured-data.ts +145 -0
  117. package/src/shared/types.ts +220 -16
  118. package/dist/banner-BMop1KLF.d.ts +0 -100
  119. package/dist/banner-CVD0GugR.d.cts +0 -100
  120. package/dist/cache-CO4Dy2uQ.cjs +0 -6
  121. package/dist/cache-Dk53iOo6.mjs +0 -6
  122. package/dist/config-CCXp3aXO.mjs +0 -7
  123. package/dist/config-CMd4XoFq.cjs +0 -6
  124. package/dist/config-DlGoEM9D.cjs +0 -7
  125. package/dist/csp-CRp_3U7a.cjs +0 -6
  126. package/dist/csp-oTC2ygvF.mjs +0 -6
  127. package/dist/doctor-Bv16QSrI.cjs +0 -7
  128. package/dist/doctor-DOAbSaiL.mjs +0 -7
  129. package/dist/headers-Ddwek8K7.mjs +0 -6
  130. package/dist/headers-dg4SDrjY.cjs +0 -6
  131. package/dist/link-2PzgTnaP.js +0 -673
  132. package/dist/meta-loader-C4Hu9RN9.mjs +0 -6
  133. package/dist/meta-loader-Dq1zcFnh.cjs +0 -6
  134. package/dist/node-B5hu_6qj.cjs +0 -104
  135. package/dist/node-BXtqM1uH.mjs +0 -6
  136. package/dist/node-C8725aw7.mjs +0 -104
  137. package/dist/node-aD1eisrR.cjs +0 -6
  138. package/dist/pages-external-BYa4JSda.mjs +0 -6
  139. package/dist/pages-external-XkYIs-d5.cjs +0 -6
  140. package/dist/parser-DCiEWkSk.cjs +0 -8
  141. package/dist/parser-qk9FIHJ7.mjs +0 -8
  142. package/dist/plugin-CX1OZ6jB.cjs +0 -73
  143. package/dist/plugin-CgfiWaFZ.mjs +0 -73
  144. package/dist/routes-BW6zsk7Z.mjs +0 -6
  145. package/dist/routes-BgoIB5wb.cjs +0 -6
  146. package/dist/routes-CORVxc02.cjs +0 -6
  147. package/dist/search-dialog-BmxHiKwt.js +0 -312
  148. package/dist/shiki-adapter-CoQ6jyJ4.cjs +0 -6
  149. package/dist/shiki-adapter-D-aKw7PP.mjs +0 -6
  150. package/dist/utils-Crm9oPcV.mjs +0 -7
  151. package/dist/utils-D6Xtj0FZ.cjs +0 -7
  152. /package/dist/{errors-0zGHRLue.mjs → errors-N-b6Sn2G.mjs} +0 -0
  153. /package/dist/{index-1KsTDq4o.d.mts → index-lFoyzCXy.d.mts} +0 -0
  154. /package/dist/{types-generator-BXhv7Ill.cjs → types-generator-DDSA93P3.cjs} +0 -0
  155. /package/dist/{types-generator-bDPvUztF.mjs → types-generator-DG1GX1EZ.mjs} +0 -0
@@ -3,4 +3,4 @@
3
3
  * Copyright (c) 2026 Jesus Alcala
4
4
  * Licensed under the MIT License.
5
5
  */
6
- const e=require(`./doctor-Bv16QSrI.cjs`);exports.doctorAction=e.t;
6
+ const e=require(`./doctor-C7whl4ED.cjs`);exports.doctorAction=e.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-D1Md3oWO.cjs`),t=require(`./utils-ej6_SjIZ.cjs`),n=require(`./pages-external-DPiPFxxP.cjs`),r=require(`./config-Ceib-AOH.cjs`),i=require(`./update-check-BKqmYfwT.cjs`);let a=require(`node:path`);a=e.r(a);let o=require(`node:fs`);o=e.r(o);let s=require(`@bdocs/dui`),c=require(`fdir`),l=require(`picomatch`);l=e.r(l);let u=require(`fastest-levenshtein`);const d={$schema:`https://boltdocs.vercel.app/schemas/doctor-config.schema.json`,checks:{metadata:{enabled:!0,titleMin:10,titleMax:60,descriptionMin:50,required:[`title`,`description`],optional:[],validateDates:!1},links:{internal:!0,external:!1,timeout:1e4,concurrency:10,ignore:[]},i18n:{enabled:!0},performance:{enabled:!0,budgets:{maxJSBundleSize:`200kb`,maxCSSBundleSize:`30kb`,maxPageHTMLSize:`80kb`,maxImagesKB:500,maxBuildTime:3e4,maxFontCount:3}}},fix:{confirmChanges:!1,backupFiles:!1,backupPath:`.boltdocs/backups`},reporting:{format:`pretty`,outputFile:`.boltdocs/reports/doctor.json`,failOnError:!1,maxWarnings:-1},severity:{missingTranslation:`warning`,brokenLink:`high`,brokenAnchor:`warning`,largeFile:`warning`,orphanedPage:`low`,duplicateTitle:`low`,shortMetadata:`low`,missingMetadata:`warning`,malformedFrontmatter:`high`,invalidFrontmatter:`high`,budgetExceeded:`warning`},exclude:[]};function f(e,t){if(e==null)return t;if(typeof e==`number`)return e;let n=e.toLowerCase().match(/^(\d+(?:\.\d+)?)\s*(b|kb|mb|gb)?$/);if(!n)return t;let r=Number.parseFloat(n[1]),i=n[2]||`b`;return Math.round(r*({b:1,kb:1024,mb:1024*1024,gb:1024*1024*1024}[i]||1))}function p(e,t,n){return e.doctorConfig.severity[t]||n}async function m(e,t){o.default.existsSync(t)||o.default.mkdirSync(t,{recursive:!0});let n=a.default.basename(e),r=new Date().toISOString().replace(/[:.]/g,`-`),i=a.default.join(t,`${n}.${r}.bak`);o.default.copyFileSync(e,i)}const h=new Map;function g(e){let n=h.get(e);if(n)return n;let r=(async()=>{let n=await t.d(e,!1);return{raw:n.raw,data:n.data,content:n.content}})();return h.set(e,r),r}const _=new Map;function v(e){if(_.has(e))return _.get(e);let t=!1;try{t=o.default.existsSync(e)&&o.default.statSync(e).isFile()}catch{t=!1}return _.set(e,t),t}async function y(e){let t=a.default.resolve(e,`doctor.json`);if(o.default.existsSync(t))try{let e=JSON.parse(o.default.readFileSync(t,`utf-8`));return{...d,...e,checks:{...d.checks,...e.checks,metadata:{...d.checks.metadata,...e.checks?.metadata},links:{...d.checks.links,...e.checks?.links},i18n:{...d.checks.i18n,...e.checks?.i18n},performance:{...d.checks.performance,...e.checks?.performance,budgets:{...d.checks.performance?.budgets,...e.checks?.performance?.budgets}}},fix:{...d.fix,...e.fix},reporting:{...d.reporting,...e.reporting},severity:{...d.severity,...e.severity},exclude:[...d.exclude,...e.exclude||[]]}}catch(e){(0,s.warn)(`Failed to parse doctor.json: ${e}`)}return d}async function b(e,r=process.cwd(),i,s){let l=a.default.resolve(r,`.boltdocs`,`generated`);o.default.existsSync(l)||o.default.mkdirSync(l,{recursive:!0});let u=s;u||=await new c.fdir().withFullPaths().filter(e=>e.endsWith(`.md`)||e.endsWith(`.mdx`)).crawl(e).withPromise();let d=i?.base||`/`,f=[];for(let n=0;n<u.length;n+=100){let r=u.slice(n,n+100),i=await Promise.all(r.map(async n=>{let r=a.default.isAbsolute(n)?n:a.default.resolve(e,n),i=a.default.relative(e,r),{data:o}=await g(r),s;return s=o.permalink?String(o.permalink).startsWith(`/`)?String(o.permalink):`/${o.permalink}`:t.a(i),d===`/`?s:(d.endsWith(`/`)?d:d+`/`)+(s.startsWith(`/`)?s.substring(1):s)}));f.push(...i)}f.includes(d)||f.push(d);let p=n.n(e,i);for(let e of p)f.includes(e)||f.push(e);let m={routes:Array.from(new Set(f)).sort(),timestamp:Date.now()};return o.default.writeFileSync(a.default.resolve(l,`link-tree.json`),JSON.stringify(m,null,2)),m}function x(e,t){if(e===t)return 1;if(!e||!t)return 0;let n=e.split(`/`).filter(Boolean),r=t.split(`/`).filter(Boolean),i=n[n.length-1]||``,a=r[r.length-1]||``;if(i===a){let e=0;for(let t of n)r.includes(t)&&e++;return e>=2?.99:.9}if(i.length>3&&a.length>3&&(a.startsWith(i)||i.startsWith(a))&&Math.min(i.length,a.length)/Math.max(i.length,a.length)>.5)return .88;let o=1-(0,u.distance)(i,a)/Math.max(i.length,a.length);return o>.8?o*.95:1-(0,u.distance)(e,t)/Math.max(e.length,t.length)}const S=new Map;function C(e,t){if(S.has(e))return S.get(e);let n=e.length,r=``,i=0;for(let a of t){if(a===e)continue;let t=a.length,o=Math.max(n,t);if(o===0)continue;let s=1-Math.abs(n-t)/o;if(s<=.8&&s<=i)continue;let c=x(e,a);c>i&&(i=c,r=a)}let a={bestMatch:r,similarity:i};return S.set(e,a),a}function w(e,t,n){let r=/```[\s\S]*?```/g,i=/`[^`\n]*`/g,a=0,o=[],s=t=>{e=e.replace(t,e=>(o.push(e),`__BD_CODE_MASK_${a++}__`))};return s(r),s(i),e.split(t).join(n).replace(/__BD_CODE_MASK_(\d+)__/g,(e,t)=>o[Number(t)]??``)}async function T(e){let n=[];if(!e.doctorConfig.checks.metadata.enabled)return n;let{titleMin:r,titleMax:i,descriptionMin:o}=e.doctorConfig.checks.metadata,s=new Map;for(let c of e.files){let l=t.u(a.default.relative(e.docsDir,c));try{let{raw:a,data:u}=await g(c);if(a.trim().startsWith(`---`)&&a.split(`---`).length>=3&&Object.keys(u).length===0){let t=p(e,`malformedFrontmatter`,`high`);t!==`off`&&n.push({file:l,level:t,message:`Malformed frontmatter (YAML parsing failed).`,suggestion:`Check your YAML syntax for indentation or unquoted special characters.`})}let d=t.g.safeParse(u);if(!d.success){let t=p(e,`invalidFrontmatter`,`high`);if(t!==`off`)for(let e of d.error.issues)n.push({file:l,level:t,message:`Invalid frontmatter field "${e.path.join(`.`)}": ${e.message}`,suggestion:`Ensure the field follows the correct type.`})}let f=Array.from(new Set([`title`,...e.doctorConfig.checks.metadata.required]));for(let t of f)if(u[t]===void 0){let r=p(e,`missingMetadata`,`warning`);r!==`off`&&n.push({file:l,level:r,message:`Missing required frontmatter field: "${t}".`,suggestion:`Add the "${t}" field to your frontmatter.`})}if(e.doctorConfig.checks.metadata.validateDates){let t=[`date`,`lastUpdated`,...e.doctorConfig.checks.metadata.optional.filter(e=>e.toLowerCase().includes(`date`))];for(let r of t)if(u[r]&&Number.isNaN(Date.parse(String(u[r])))){let t=p(e,`invalidFrontmatter`,`high`);t!==`off`&&n.push({file:l,level:t,message:`Invalid date format in field "${r}": "${u[r]}".`,suggestion:`Use a valid ISO date format (e.g., YYYY-MM-DD).`})}}if(u.title){let t=String(u.title);if(t.length<r){let i=p(e,`shortMetadata`,`low`);i!==`off`&&n.push({file:l,level:i,message:`Title is too short (${t.length} chars).`,suggestion:`Titles should be at least ${r} characters for better SEO.`})}else if(t.length>i){let r=p(e,`shortMetadata`,`low`);r!==`off`&&n.push({file:l,level:r,message:`Title is too long (${t.length} chars).`,suggestion:`Titles should be under ${i} characters.`})}let a=s.get(t)||[];a.push(l),s.set(t,a)}if(u.description&&String(u.description).length<o){let t=p(e,`shortMetadata`,`low`);t!==`off`&&n.push({file:l,level:t,message:`Description is very short.`,suggestion:`Descriptions should ideally be at least ${o} characters.`})}}catch(t){if(t instanceof Error){let r=p(e,`malformedFrontmatter`,`high`);r!==`off`&&n.push({file:l,level:r,message:`Malformed frontmatter (YAML error): ${t.message}`,suggestion:`Check your YAML syntax for indentation or unquoted special characters.`})}}}for(let[t,r]of s.entries())if(r.length>1){let i=p(e,`duplicateTitle`,`low`);if(i!==`off`)for(let e of r)n.push({file:e,level:i,message:`Duplicate title found: "${t}"`,suggestion:`Ensure each page has a unique title. Also used in: ${r.filter(t=>t!==e).join(`, `)}`})}return n}const E=/(?:\[([^\]]*)\]\(([^)\s]+)(?:\s+["'][^"']*["'])?\))|(?:href=["']([^"']+)["'])|(?:<Link\s+[^>]*?to=["'](\/[^"']+)["'])/g,D=[``,`.md`,`.mdx`,`/index.md`,`/index.mdx`];function O(e){let t=[],n=e=>{t.includes(e)||t.push(e)};n(e),e.endsWith(`/`)?n(e.slice(0,-1)):n(e+`/`);let r=e.replace(/\.(md|mdx)$/i,``);r!==e&&(n(r),n(r+`/`));let i=e.replace(/\/index\.(md|mdx)$/i,``);return i!==e&&(n(i),n(i+`/`)),n(e.endsWith(`/`)?e+`index`:e+`/index`),e.endsWith(`/index`)&&n(e.replace(/\/index$/,``)),t}async function k(e){let n=[],{internal:r,external:i,ignore:c,timeout:l,concurrency:u}=e.doctorConfig.checks.links;if(!r&&!i&&!e.options.checkExternal)return n;let d=new Set,f=5e5;for(let s of e.files){let l=t.u(a.default.relative(e.docsDir,s)),{content:u}=await g(s),m=[...(u.length>f?u.slice(0,f):u).replace(/<!--[\s\S]*?-->/g,``).replace(/```[\s\S]*?```/g,``).replace(/`[^`\n]*`/g,``).matchAll(E)];for(let t of m){let u=t[2]||t[3]||t[4],f=!!t[2],m=!!t[4];if(!u||c.some(e=>u.includes(e)))continue;if(/^(https?:|mailto:|tel:|data:|javascript:|blob:|ftp:)/i.test(u)){(i||e.options.checkExternal)&&d.add({url:u,file:s});continue}if(u.startsWith(`//`)){(i||e.options.checkExternal)&&d.add({url:u,file:s});continue}if(!r||u.startsWith(`#`))continue;let g;try{g=decodeURIComponent(u.split(`#`)[0].split(`?`)[0])}catch{g=u.split(`#`)[0].split(`?`)[0]}if(!g)continue;let _=!1,y=!1,b=``;if(g.startsWith(`/`)){let t=O(g);for(let n of t)if(e.routeIndex.has(n)||e.routeIndexWithSlash.has(n)||e.routeIndexWithoutSlash.has(n)){_=!0;break}if(!_&&e.basePrefix)for(let n of t){let t=e.basePrefix+(n.startsWith(`/`)?n:`/`+n);if(t!==n&&(e.routeIndex.has(t)||e.routeIndexWithSlash.has(t))){y=!0,b=t;break}}if(!_&&!y){let t=g.replace(/^\/+/,``),n=a.default.join(e.docsDir,t);_=D.some(e=>v(n+e))}}else{let e=a.default.resolve(a.default.dirname(s),g);_=D.some(t=>v(e+t))}if(!_){let{bestMatch:t,similarity:r}=C(g,e.linkTree.routes);y&&(t=b,r=1);let i=r>.6||y,a=r>.75&&t!==g||y,c=p(e,`brokenLink`,`high`);c!==`off`&&n.push({file:l,level:c,message:`Broken internal link: "${u}"`,suggestion:i?`Did you mean "${t}"?`:`Ensure the target exists or check for typos.`,fix:a?async()=>{let e=u.includes(`#`)?`#`+u.split(`#`)[1]:``,n=f?`(${u})`:m?`to="${u}"`:`href="${u}"`,r=f?`(${t}${e})`:m?`to="${t}${e}"`:`href="${t}${e}"`,i=w(o.default.readFileSync(s,`utf-8`),n,r);o.default.writeFileSync(s,i),h.delete(s)}:void 0})}}}if(d.size>0){(0,s.info)(s.colors.gray(`Verifying ${d.size} external links...`));let r=new Map;for(let e of d)r.has(e.url)||r.set(e.url,[]),r.get(e.url).push(e.file);let i=async e=>{try{let t=new AbortController,n=setTimeout(()=>t.abort(),l),r=await fetch(e,{method:`HEAD`,signal:t.signal,headers:{"User-Agent":`boltdocs-doctor/1.0`}});return clearTimeout(n),!r.ok&&r.status!==404?{url:e,ok:(await fetch(e,{method:`GET`,signal:t.signal,headers:{"User-Agent":`boltdocs-doctor/1.0`}})).ok}:{url:e,ok:r.ok}}catch(t){return{url:e,ok:!1,error:t instanceof Error?t.message:String(t)}}},o=Array.from(r.keys()),c=[];for(let e=0;e<o.length;e+=u){let t=o.slice(e,e+u),n=await Promise.allSettled(t.map(i));c.push(...n.map(e=>e.status===`fulfilled`?e.value:{url:`unknown`,ok:!1,error:String(e.reason)}))}for(let i of c)if(!i.ok){let o=p(e,`brokenLink`,`warning`);if(o!==`off`){let s=r.get(i.url)||[];for(let r of s)n.push({file:t.u(a.default.relative(e.docsDir,r)),level:o,message:`Broken external link: "${i.url}"`,suggestion:`Verify the URL or update it if it's permanently down. Error: ${i.error||`Status >= 400`}`})}}}return n}async function A(e){let n=[];if(!e.doctorConfig.checks.i18n.enabled||!e.config.i18n)return n;let{defaultLocale:r,locales:i}=e.config.i18n,s=Object.keys(i),c=s.filter(e=>e!==r);if(c.length===0)return n;let l=a.default.resolve(e.docsDir),u=a.default.join(l,r),d=o.default.existsSync(u)&&o.default.statSync(u).isDirectory(),f=e=>{let t=a.default.resolve(e);if(t!==l&&!t.startsWith(l+a.default.sep))throw Error(`Refusing to write outside docs dir: ${t}`);return t};for(let i of e.files){let m=t.u(a.default.relative(e.docsDir,i)),h=m.split(`/`),g=h[0],_,y;if(s.includes(g)&&g!==r?(_=g,y=h.slice(1).join(`/`)):g===r&&d?(_=r,y=h.slice(1).join(`/`)):(_=r,y=m),y)if(_===r)for(let t of c){let r=a.default.join(l,t,y);if(!v(r)){let s=p(e,`missingTranslation`,`warning`);s!==`off`&&n.push({file:m,level:s,message:`Missing translation for locale "${t}"`,suggestion:`Create a version at "${t}/${y}".`,fix:async()=>{let e=f(r),t=a.default.dirname(e);o.default.existsSync(t)||o.default.mkdirSync(t,{recursive:!0}),o.default.copyFileSync(i,e)}})}}else{let t=a.default.join(l,y),s=d?a.default.join(u,y):``;if(!(v(t)||s!==``&&v(s))){let t=p(e,`missingTranslation`,`low`);t!==`off`&&n.push({file:m,level:t,message:`Orphaned translation (source missing in "${r}")`,suggestion:`Remove this file or create the source at "${r}/${y}".`,fix:async()=>{o.default.unlinkSync(f(i))}})}}}return n}async function j(e){let t=[];if(!e.config.theme?.sidebar)return t;let n=new Set,r=e.config.theme.sidebar;for(let[i,a]of Object.entries(r))for(let r of a){if(!r.text){let n=p(e,`invalidFrontmatter`,`warning`);n!==`off`&&t.push({file:`boltdocs.config.ts`,level:n,message:`Sidebar item in group "${i}" is missing a label.`,suggestion:`Add a "text" property to the sidebar item.`})}if(r.link&&(n.add(r.link),!e.routeIndex.has(r.link))){let{bestMatch:n,similarity:i}=C(r.link,e.linkTree.routes),a=i>.6,o=p(e,`brokenLink`,`high`);o!==`off`&&t.push({file:`boltdocs.config.ts`,level:o,message:`Broken sidebar link: "${r.link}"`,suggestion:a?`Did you mean "${n}"?`:`Ensure the route exists and is correctly formatted.`})}}for(let r of e.linkTree.routes)if(!(r===`/`||r===``)&&!n.has(r)){let n=p(e,`orphanedPage`,`low`);n!==`off`&&t.push({file:`Sidebar`,level:n,message:`Orphaned page found: "${r}" is not linked in the sidebar.`,suggestion:`Consider adding it to the sidebar for better discoverability.`})}return t}async function M(e){let t=[],n=e.doctorConfig.checks.performance;if(!n?.enabled)return t;let r=a.default.resolve(e.root,`.boltdocs`,`reports`,`performance.json`);if(!o.default.existsSync(r))return t.push({file:`(build)`,level:p(e,`budgetExceeded`,`warning`)??`warning`,message:"Performance metrics not found. Run `boltdocs build` first."}),t;let i;try{i=JSON.parse(o.default.readFileSync(r,`utf-8`))}catch{return t.push({file:`(build)`,level:p(e,`budgetExceeded`,`warning`)??`warning`,message:`Failed to parse performance metrics file.`}),t}let s=n.budgets,c=p(e,`budgetExceeded`,`warning`),l=f(s?.maxJSBundleSize,1/0),u=f(s?.maxCSSBundleSize,1/0),d=f(s?.maxPageHTMLSize,1/0),m=s?.maxImagesKB??1/0,h=s?.maxBuildTime??1/0,g=s?.maxFontCount??1/0;if(l!==1/0&&i.totalJSBundleSize>l){let e=(i.totalJSBundleSize/1024).toFixed(0),n=(l/1024).toFixed(0);t.push({file:`(build)`,level:c,message:`JS bundle size exceeds budget: ${e}kb > ${n}kb`,suggestion:`Code-split large dependencies or lazy-load route components.`})}if(u!==1/0&&i.totalCSSBundleSize>u){let e=(i.totalCSSBundleSize/1024).toFixed(0),n=(u/1024).toFixed(0);t.push({file:`(build)`,level:c,message:`CSS bundle size exceeds budget: ${e}kb > ${n}kb`,suggestion:`Remove unused styles or split CSS by route.`})}if(d!==1/0){for(let e of i.pages)if(e.htmlSize>d){let n=(e.htmlSize/1024).toFixed(0),r=(d/1024).toFixed(0);t.push({file:e.route,level:c,message:`Page HTML size exceeds budget: ${n}kb > ${r}kb`,suggestion:`Reduce the amount of inline content or split into sub-pages.`})}}let _=m*1024;if(m!==1/0&&i.totalImagesSize>_){let e=(i.totalImagesSize/1024).toFixed(0);t.push({file:`(build)`,level:c,message:`Image assets exceed budget: ${e}kb > ${m}kb`,suggestion:`Optimize images with lossy compression or use next-gen formats (webp/avif).`})}if(h!==1/0&&i.buildTime>h){let e=(i.buildTime/1e3).toFixed(1),n=(h/1e3).toFixed(1);t.push({file:`(build)`,level:c,message:`Build time exceeds budget: ${e}s > ${n}s`,suggestion:"Check for large unoptimized assets or increase `concurrency` in SSG options."})}return g!==1/0&&i.fontCount>g&&t.push({file:`(build)`,level:c,message:`Font files exceed budget: ${i.fontCount} > ${g}`,suggestion:`Reduce the number of font families or use variable fonts.`}),t}async function N(e){let t=a.default.resolve(e,`doctor.json`);if(o.default.existsSync(t)){(0,s.warn)(`"doctor.json" already exists at ${e}.`);return}try{o.default.writeFileSync(t,JSON.stringify(d,null,2)),(0,s.success)(`Created "doctor.json" with default configuration.`)}catch(e){(0,s.error)(`Failed to create "doctor.json": ${e}`)}}async function P(e=process.cwd(),t={}){if(t.init){await N(e);return}i.t();try{let n=await y(e),{format:u}=n.reporting,d=performance.now(),f=await r.t(`docs`,e),p=a.default.resolve(e,`docs`);if(o.default.existsSync(p)||(u===`pretty`&&(0,s.error)(`Docs dir not found at ${p}`),process.exit(1)),u===`pretty`){let t=i.n?` ${i.i(`v${i.n}`)}`:``;console.log(`\n ${s.colors.bold(`⚡`)} ${i.s(`boltdocs`)}${t} ${s.colors.dim(`—`)} ${s.colors.bold(`doctor`)} ${s.colors.dim(`· documentation health check`)}\n`),console.log(` ${s.colors.dim(`Docs dir ${p}`)}\n ${s.colors.dim(`Reports ${e}/.boltdocs/reports/`)}\n`)}u===`pretty`&&(0,s.info)(s.colors.dim(`🔍 Discovering files and routes...`));let h=(0,l.default)(n.exclude||[]),g=await new c.fdir().withFullPaths().filter(e=>{if(!(e.endsWith(`.md`)||e.endsWith(`.mdx`)))return!1;let t=a.default.relative(p,e).replace(/\\/g,`/`),n=t.split(`/`).some(e=>e.startsWith(`_`)&&e!==`_index.md`&&e!==`_index.mdx`);return!h(t)&&!n}).crawl(p).withPromise();for(let e of g)_.set(e,!0);let v=await b(p,e,f,g),x=f.base||`/`,S=x===`/`?``:x.endsWith(`/`)?x.slice(0,-1):x,C=new Set(v.routes),w=new Set(v.routes.map(e=>e.endsWith(`/`)?e:e+`/`)),E=new Set(v.routes.map(e=>e.endsWith(`/`)?e.slice(0,-1):e));u===`pretty`&&(0,s.info)(s.colors.dim(`🧪 Running diagnostic checks in parallel...`));let D={root:e,docsDir:p,config:f,doctorConfig:n,linkTree:v,files:g,options:t,routeIndex:C,routeIndexWithSlash:w,routeIndexWithoutSlash:E,basePrefix:S};u===`pretty`&&(0,s.info)(s.colors.dim(`🧪 Running diagnostic checks in parallel...`));let O=[T(D),k(D),A(D),j(D)];t.budget&&O.push(M(D));let[N,P,F,I,...L]=await Promise.all(O),R=t.budget?L[0]??[]:[],z=[...N,...P,...F,...I,...R];if(u===`pretty`){let e=e=>e>0?s.colors.red(`${e} issue${e===1?``:`s`}`):s.colors.green(`OK`),n=[{label:`Metadata checks ${e(N.length)}`,done:N.length===0},{label:`Link checks ${e(P.length)}`,done:P.length===0},{label:`i18n checks ${e(F.length)}`,done:F.length===0},{label:`Sidebar checks ${e(I.length)}`,done:I.length===0}];t.budget&&n.push({label:`Performance budget ${e(R.length)}`,done:R.length===0}),console.log(`\n${(0,s.tasks)(n)}\n`)}let B=0;if(t.fix){for(let e of z)if(e.fix){if(D.doctorConfig.fix.confirmChanges&&!await(0,s.confirm)(`Fix issue in "${e.file}": ${e.message}?`))continue;if(D.doctorConfig.fix.backupFiles){let t=a.default.resolve(D.docsDir,e.file);o.default.existsSync(t)&&await m(t,a.default.resolve(D.root,D.doctorConfig.fix.backupPath))}await e.fix(),B++}}let V=((performance.now()-d)/1e3).toFixed(2),H=z.filter(e=>e.level===`high`).length,U=z.filter(e=>e.level===`warning`).length,W=z.filter(e=>e.level===`low`).length,G={summary:{total:z.length,high:H,warning:U,low:W,fixed:B,duration:V},issues:z.map(e=>({...e,fix:void 0}))};if(n.reporting.outputFile){let t=a.default.resolve(e,n.reporting.outputFile);o.default.existsSync(a.default.dirname(t))||o.default.mkdirSync(a.default.dirname(t),{recursive:!0}),o.default.writeFileSync(t,JSON.stringify(G,null,2))}if(u===`json`)console.log(JSON.stringify(G,null,2));else if(u===`pretty`){let e=z.reduce((e,t)=>(e[t.file]||(e[t.file]=[]),e[t.file].push(t),e),{});if(z.length>0){console.log((0,s.section)({title:`Issues`,colors:{title:i.r}}));for(let[n,r]of Object.entries(e)){let e=r.some(e=>e.level===`high`)?`high`:r.some(e=>e.level===`warning`)?`warning`:`low`,a=e.toUpperCase(),o=e===`high`?(0,s.badge)({label:a,status:`error`}):e===`warning`?(0,s.badge)({label:a,status:`warning`}):(0,s.badge)({label:a,colors:{text:`#ffffff`,bg:i.r}});console.log(`\n ${o} ${s.colors.bold(n)}`);for(let e of r){let n=e.level===`high`?`✖`:e.level===`warning`?`⚠`:`ℹ`,r=e.level===`high`?s.colors.red:e.level===`warning`?s.colors.yellow:e=>(0,s.colorize)(e,i.r,`fg`);console.log(` ${r(n)} ${e.message}`),e.suggestion&&console.log(` ${s.colors.dim(`💡 ${e.suggestion}`)}`),t.fix&&e.fix&&console.log(` ${s.colors.green(`✅ Fixed automatically`)}`)}}console.log(``)}z.length===0?(console.log(` ${s.colors.green.bold(`✨ Everything looks perfect!`)} ${s.colors.dim(`— your documentation is in great shape.`)}`),console.log(` ${s.colors.dim(`Scanned ${g.length} file${g.length===1?``:`s`} in ${V}s`)}`)):(console.log(`\n${(0,s.section)({title:`Summary`,colors:{title:i.r}})}`),H>0&&console.log(` ${(0,s.badge)({label:String(H),status:`error`})} ${s.colors.bold(`high`)}`),U>0&&console.log(` ${(0,s.badge)({label:String(U),status:`warning`})} ${s.colors.bold(`warning`)}${U===1?``:`s`}`),W>0&&console.log(` ${(0,s.badge)({label:String(W),colors:{text:`#ffffff`,bg:i.r}})} ${s.colors.bold(`low`)}`),console.log(` ${s.colors.dim(`Scanned ${g.length} file${g.length===1?``:`s`} in ${V}s`)}`),B>0&&(0,s.success)(`Successfully fixed ${B} issues automatically!`),H>0?(0,s.error)(`Please fix the critical errors before building for production.`):(0,s.success)(`No critical issues found. You are ready to go!`))}n.reporting.failOnError&&H>0&&process.exit(1),n.reporting.maxWarnings!==-1&&U>n.reporting.maxWarnings&&(u===`pretty`&&(0,s.error)(`Failed: Too many warnings (${U} > ${n.reporting.maxWarnings})`),process.exit(1))}catch(e){(0,s.error)(`Doctor failed: ${e}`),process.exit(1)}}Object.defineProperty(exports,`a`,{enumerable:!0,get:function(){return T}}),Object.defineProperty(exports,`c`,{enumerable:!0,get:function(){return b}}),Object.defineProperty(exports,`i`,{enumerable:!0,get:function(){return k}}),Object.defineProperty(exports,`l`,{enumerable:!0,get:function(){return y}}),Object.defineProperty(exports,`n`,{enumerable:!0,get:function(){return N}}),Object.defineProperty(exports,`o`,{enumerable:!0,get:function(){return M}}),Object.defineProperty(exports,`r`,{enumerable:!0,get:function(){return A}}),Object.defineProperty(exports,`s`,{enumerable:!0,get:function(){return j}}),Object.defineProperty(exports,`t`,{enumerable:!0,get:function(){return P}}),Object.defineProperty(exports,`u`,{enumerable:!0,get:function(){return d}});
@@ -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{t as e}from"./chunk-BFSpntXv.mjs";import{a as t,d as n,g as r,u as i}from"./utils-8lzafE49.mjs";import{n as a}from"./pages-external-BBw8ObVK.mjs";import{n as o}from"./config-DGLQsy7y.mjs";import{i as s,n as c,r as l,s as u,t as d}from"./update-check-QnrVR3q1.mjs";import f from"node:path";import p from"node:fs";import{badge as m,colorize as h,colors as g,confirm as _,error as v,info as y,section as b,success as x,tasks as ee,warn as S}from"@bdocs/dui";import{fdir as C}from"fdir";import te from"picomatch";import{distance as w}from"fastest-levenshtein";const T={$schema:`https://boltdocs.vercel.app/schemas/doctor-config.schema.json`,checks:{metadata:{enabled:!0,titleMin:10,titleMax:60,descriptionMin:50,required:[`title`,`description`],optional:[],validateDates:!1},links:{internal:!0,external:!1,timeout:1e4,concurrency:10,ignore:[]},i18n:{enabled:!0},performance:{enabled:!0,budgets:{maxJSBundleSize:`200kb`,maxCSSBundleSize:`30kb`,maxPageHTMLSize:`80kb`,maxImagesKB:500,maxBuildTime:3e4,maxFontCount:3}}},fix:{confirmChanges:!1,backupFiles:!1,backupPath:`.boltdocs/backups`},reporting:{format:`pretty`,outputFile:`.boltdocs/reports/doctor.json`,failOnError:!1,maxWarnings:-1},severity:{missingTranslation:`warning`,brokenLink:`high`,brokenAnchor:`warning`,largeFile:`warning`,orphanedPage:`low`,duplicateTitle:`low`,shortMetadata:`low`,missingMetadata:`warning`,malformedFrontmatter:`high`,invalidFrontmatter:`high`,budgetExceeded:`warning`},exclude:[]};function E(e,t){if(e==null)return t;if(typeof e==`number`)return e;let n=e.toLowerCase().match(/^(\d+(?:\.\d+)?)\s*(b|kb|mb|gb)?$/);if(!n)return t;let r=Number.parseFloat(n[1]),i=n[2]||`b`;return Math.round(r*({b:1,kb:1024,mb:1024*1024,gb:1024*1024*1024}[i]||1))}function D(e,t,n){return e.doctorConfig.severity[t]||n}async function ne(e,t){p.existsSync(t)||p.mkdirSync(t,{recursive:!0});let n=f.basename(e),r=new Date().toISOString().replace(/[:.]/g,`-`),i=f.join(t,`${n}.${r}.bak`);p.copyFileSync(e,i)}const O=new Map;function k(e){let t=O.get(e);if(t)return t;let r=(async()=>{let t=await n(e,!1);return{raw:t.raw,data:t.data,content:t.content}})();return O.set(e,r),r}const A=new Map;function j(e){if(A.has(e))return A.get(e);let t=!1;try{t=p.existsSync(e)&&p.statSync(e).isFile()}catch{t=!1}return A.set(e,t),t}async function M(e){let t=f.resolve(e,`doctor.json`);if(p.existsSync(t))try{let e=JSON.parse(p.readFileSync(t,`utf-8`));return{...T,...e,checks:{...T.checks,...e.checks,metadata:{...T.checks.metadata,...e.checks?.metadata},links:{...T.checks.links,...e.checks?.links},i18n:{...T.checks.i18n,...e.checks?.i18n},performance:{...T.checks.performance,...e.checks?.performance,budgets:{...T.checks.performance?.budgets,...e.checks?.performance?.budgets}}},fix:{...T.fix,...e.fix},reporting:{...T.reporting,...e.reporting},severity:{...T.severity,...e.severity},exclude:[...T.exclude,...e.exclude||[]]}}catch(e){S(`Failed to parse doctor.json: ${e}`)}return T}async function N(e,n=process.cwd(),r,i){let o=f.resolve(n,`.boltdocs`,`generated`);p.existsSync(o)||p.mkdirSync(o,{recursive:!0});let s=i;s||=await new C().withFullPaths().filter(e=>e.endsWith(`.md`)||e.endsWith(`.mdx`)).crawl(e).withPromise();let c=r?.base||`/`,l=[];for(let n=0;n<s.length;n+=100){let r=s.slice(n,n+100),i=await Promise.all(r.map(async n=>{let r=f.isAbsolute(n)?n:f.resolve(e,n),i=f.relative(e,r),{data:a}=await k(r),o;return o=a.permalink?String(a.permalink).startsWith(`/`)?String(a.permalink):`/${a.permalink}`:t(i),c===`/`?o:(c.endsWith(`/`)?c:c+`/`)+(o.startsWith(`/`)?o.substring(1):o)}));l.push(...i)}l.includes(c)||l.push(c);let u=a(e,r);for(let e of u)l.includes(e)||l.push(e);let d={routes:Array.from(new Set(l)).sort(),timestamp:Date.now()};return p.writeFileSync(f.resolve(o,`link-tree.json`),JSON.stringify(d,null,2)),d}function P(e,t){if(e===t)return 1;if(!e||!t)return 0;let n=e.split(`/`).filter(Boolean),r=t.split(`/`).filter(Boolean),i=n[n.length-1]||``,a=r[r.length-1]||``;if(i===a){let e=0;for(let t of n)r.includes(t)&&e++;return e>=2?.99:.9}if(i.length>3&&a.length>3&&(a.startsWith(i)||i.startsWith(a))&&Math.min(i.length,a.length)/Math.max(i.length,a.length)>.5)return .88;let o=1-w(i,a)/Math.max(i.length,a.length);return o>.8?o*.95:1-w(e,t)/Math.max(e.length,t.length)}const F=new Map;function I(e,t){if(F.has(e))return F.get(e);let n=e.length,r=``,i=0;for(let a of t){if(a===e)continue;let t=a.length,o=Math.max(n,t);if(o===0)continue;let s=1-Math.abs(n-t)/o;if(s<=.8&&s<=i)continue;let c=P(e,a);c>i&&(i=c,r=a)}let a={bestMatch:r,similarity:i};return F.set(e,a),a}function L(e,t,n){let r=/```[\s\S]*?```/g,i=/`[^`\n]*`/g,a=0,o=[],s=t=>{e=e.replace(t,e=>(o.push(e),`__BD_CODE_MASK_${a++}__`))};return s(r),s(i),e.split(t).join(n).replace(/__BD_CODE_MASK_(\d+)__/g,(e,t)=>o[Number(t)]??``)}async function R(e){let t=[];if(!e.doctorConfig.checks.metadata.enabled)return t;let{titleMin:n,titleMax:a,descriptionMin:o}=e.doctorConfig.checks.metadata,s=new Map;for(let c of e.files){let l=i(f.relative(e.docsDir,c));try{let{raw:i,data:u}=await k(c);if(i.trim().startsWith(`---`)&&i.split(`---`).length>=3&&Object.keys(u).length===0){let n=D(e,`malformedFrontmatter`,`high`);n!==`off`&&t.push({file:l,level:n,message:`Malformed frontmatter (YAML parsing failed).`,suggestion:`Check your YAML syntax for indentation or unquoted special characters.`})}let d=r.safeParse(u);if(!d.success){let n=D(e,`invalidFrontmatter`,`high`);if(n!==`off`)for(let e of d.error.issues)t.push({file:l,level:n,message:`Invalid frontmatter field "${e.path.join(`.`)}": ${e.message}`,suggestion:`Ensure the field follows the correct type.`})}let f=Array.from(new Set([`title`,...e.doctorConfig.checks.metadata.required]));for(let n of f)if(u[n]===void 0){let r=D(e,`missingMetadata`,`warning`);r!==`off`&&t.push({file:l,level:r,message:`Missing required frontmatter field: "${n}".`,suggestion:`Add the "${n}" field to your frontmatter.`})}if(e.doctorConfig.checks.metadata.validateDates){let n=[`date`,`lastUpdated`,...e.doctorConfig.checks.metadata.optional.filter(e=>e.toLowerCase().includes(`date`))];for(let r of n)if(u[r]&&Number.isNaN(Date.parse(String(u[r])))){let n=D(e,`invalidFrontmatter`,`high`);n!==`off`&&t.push({file:l,level:n,message:`Invalid date format in field "${r}": "${u[r]}".`,suggestion:`Use a valid ISO date format (e.g., YYYY-MM-DD).`})}}if(u.title){let r=String(u.title);if(r.length<n){let i=D(e,`shortMetadata`,`low`);i!==`off`&&t.push({file:l,level:i,message:`Title is too short (${r.length} chars).`,suggestion:`Titles should be at least ${n} characters for better SEO.`})}else if(r.length>a){let n=D(e,`shortMetadata`,`low`);n!==`off`&&t.push({file:l,level:n,message:`Title is too long (${r.length} chars).`,suggestion:`Titles should be under ${a} characters.`})}let i=s.get(r)||[];i.push(l),s.set(r,i)}if(u.description&&String(u.description).length<o){let n=D(e,`shortMetadata`,`low`);n!==`off`&&t.push({file:l,level:n,message:`Description is very short.`,suggestion:`Descriptions should ideally be at least ${o} characters.`})}}catch(n){if(n instanceof Error){let r=D(e,`malformedFrontmatter`,`high`);r!==`off`&&t.push({file:l,level:r,message:`Malformed frontmatter (YAML error): ${n.message}`,suggestion:`Check your YAML syntax for indentation or unquoted special characters.`})}}}for(let[n,r]of s.entries())if(r.length>1){let i=D(e,`duplicateTitle`,`low`);if(i!==`off`)for(let e of r)t.push({file:e,level:i,message:`Duplicate title found: "${n}"`,suggestion:`Ensure each page has a unique title. Also used in: ${r.filter(t=>t!==e).join(`, `)}`})}return t}const z=/(?:\[([^\]]*)\]\(([^)\s]+)(?:\s+["'][^"']*["'])?\))|(?:href=["']([^"']+)["'])|(?:<Link\s+[^>]*?to=["'](\/[^"']+)["'])/g,B=[``,`.md`,`.mdx`,`/index.md`,`/index.mdx`];function V(e){let t=[],n=e=>{t.includes(e)||t.push(e)};n(e),e.endsWith(`/`)?n(e.slice(0,-1)):n(e+`/`);let r=e.replace(/\.(md|mdx)$/i,``);r!==e&&(n(r),n(r+`/`));let i=e.replace(/\/index\.(md|mdx)$/i,``);return i!==e&&(n(i),n(i+`/`)),n(e.endsWith(`/`)?e+`index`:e+`/index`),e.endsWith(`/index`)&&n(e.replace(/\/index$/,``)),t}async function H(e){let t=[],{internal:n,external:r,ignore:a,timeout:o,concurrency:s}=e.doctorConfig.checks.links;if(!n&&!r&&!e.options.checkExternal)return t;let c=new Set,l=5e5;for(let o of e.files){let s=i(f.relative(e.docsDir,o)),{content:u}=await k(o),d=[...(u.length>l?u.slice(0,l):u).replace(/<!--[\s\S]*?-->/g,``).replace(/```[\s\S]*?```/g,``).replace(/`[^`\n]*`/g,``).matchAll(z)];for(let i of d){let l=i[2]||i[3]||i[4],u=!!i[2],d=!!i[4];if(!l||a.some(e=>l.includes(e)))continue;if(/^(https?:|mailto:|tel:|data:|javascript:|blob:|ftp:)/i.test(l)){(r||e.options.checkExternal)&&c.add({url:l,file:o});continue}if(l.startsWith(`//`)){(r||e.options.checkExternal)&&c.add({url:l,file:o});continue}if(!n||l.startsWith(`#`))continue;let m;try{m=decodeURIComponent(l.split(`#`)[0].split(`?`)[0])}catch{m=l.split(`#`)[0].split(`?`)[0]}if(!m)continue;let h=!1,g=!1,_=``;if(m.startsWith(`/`)){let t=V(m);for(let n of t)if(e.routeIndex.has(n)||e.routeIndexWithSlash.has(n)||e.routeIndexWithoutSlash.has(n)){h=!0;break}if(!h&&e.basePrefix)for(let n of t){let t=e.basePrefix+(n.startsWith(`/`)?n:`/`+n);if(t!==n&&(e.routeIndex.has(t)||e.routeIndexWithSlash.has(t))){g=!0,_=t;break}}if(!h&&!g){let t=m.replace(/^\/+/,``),n=f.join(e.docsDir,t);h=B.some(e=>j(n+e))}}else{let e=f.resolve(f.dirname(o),m);h=B.some(t=>j(e+t))}if(!h){let{bestMatch:n,similarity:r}=I(m,e.linkTree.routes);g&&(n=_,r=1);let i=r>.6||g,a=r>.75&&n!==m||g,c=D(e,`brokenLink`,`high`);c!==`off`&&t.push({file:s,level:c,message:`Broken internal link: "${l}"`,suggestion:i?`Did you mean "${n}"?`:`Ensure the target exists or check for typos.`,fix:a?async()=>{let e=l.includes(`#`)?`#`+l.split(`#`)[1]:``,t=u?`(${l})`:d?`to="${l}"`:`href="${l}"`,r=u?`(${n}${e})`:d?`to="${n}${e}"`:`href="${n}${e}"`,i=L(p.readFileSync(o,`utf-8`),t,r);p.writeFileSync(o,i),O.delete(o)}:void 0})}}}if(c.size>0){y(g.gray(`Verifying ${c.size} external links...`));let n=new Map;for(let e of c)n.has(e.url)||n.set(e.url,[]),n.get(e.url).push(e.file);let r=async e=>{try{let t=new AbortController,n=setTimeout(()=>t.abort(),o),r=await fetch(e,{method:`HEAD`,signal:t.signal,headers:{"User-Agent":`boltdocs-doctor/1.0`}});return clearTimeout(n),!r.ok&&r.status!==404?{url:e,ok:(await fetch(e,{method:`GET`,signal:t.signal,headers:{"User-Agent":`boltdocs-doctor/1.0`}})).ok}:{url:e,ok:r.ok}}catch(t){return{url:e,ok:!1,error:t instanceof Error?t.message:String(t)}}},a=Array.from(n.keys()),l=[];for(let e=0;e<a.length;e+=s){let t=a.slice(e,e+s),n=await Promise.allSettled(t.map(r));l.push(...n.map(e=>e.status===`fulfilled`?e.value:{url:`unknown`,ok:!1,error:String(e.reason)}))}for(let r of l)if(!r.ok){let a=D(e,`brokenLink`,`warning`);if(a!==`off`){let o=n.get(r.url)||[];for(let n of o)t.push({file:i(f.relative(e.docsDir,n)),level:a,message:`Broken external link: "${r.url}"`,suggestion:`Verify the URL or update it if it's permanently down. Error: ${r.error||`Status >= 400`}`})}}}return t}async function U(e){let t=[];if(!e.doctorConfig.checks.i18n.enabled||!e.config.i18n)return t;let{defaultLocale:n,locales:r}=e.config.i18n,a=Object.keys(r),o=a.filter(e=>e!==n);if(o.length===0)return t;let s=f.resolve(e.docsDir),c=f.join(s,n),l=p.existsSync(c)&&p.statSync(c).isDirectory(),u=e=>{let t=f.resolve(e);if(t!==s&&!t.startsWith(s+f.sep))throw Error(`Refusing to write outside docs dir: ${t}`);return t};for(let r of e.files){let d=i(f.relative(e.docsDir,r)),m=d.split(`/`),h=m[0],g,_;if(a.includes(h)&&h!==n?(g=h,_=m.slice(1).join(`/`)):h===n&&l?(g=n,_=m.slice(1).join(`/`)):(g=n,_=d),_)if(g===n)for(let n of o){let i=f.join(s,n,_);if(!j(i)){let a=D(e,`missingTranslation`,`warning`);a!==`off`&&t.push({file:d,level:a,message:`Missing translation for locale "${n}"`,suggestion:`Create a version at "${n}/${_}".`,fix:async()=>{let e=u(i),t=f.dirname(e);p.existsSync(t)||p.mkdirSync(t,{recursive:!0}),p.copyFileSync(r,e)}})}}else{let i=f.join(s,_),a=l?f.join(c,_):``;if(!(j(i)||a!==``&&j(a))){let i=D(e,`missingTranslation`,`low`);i!==`off`&&t.push({file:d,level:i,message:`Orphaned translation (source missing in "${n}")`,suggestion:`Remove this file or create the source at "${n}/${_}".`,fix:async()=>{p.unlinkSync(u(r))}})}}}return t}async function W(e){let t=[];if(!e.config.theme?.sidebar)return t;let n=new Set,r=e.config.theme.sidebar;for(let[i,a]of Object.entries(r))for(let r of a){if(!r.text){let n=D(e,`invalidFrontmatter`,`warning`);n!==`off`&&t.push({file:`boltdocs.config.ts`,level:n,message:`Sidebar item in group "${i}" is missing a label.`,suggestion:`Add a "text" property to the sidebar item.`})}if(r.link&&(n.add(r.link),!e.routeIndex.has(r.link))){let{bestMatch:n,similarity:i}=I(r.link,e.linkTree.routes),a=i>.6,o=D(e,`brokenLink`,`high`);o!==`off`&&t.push({file:`boltdocs.config.ts`,level:o,message:`Broken sidebar link: "${r.link}"`,suggestion:a?`Did you mean "${n}"?`:`Ensure the route exists and is correctly formatted.`})}}for(let r of e.linkTree.routes)if(!(r===`/`||r===``)&&!n.has(r)){let n=D(e,`orphanedPage`,`low`);n!==`off`&&t.push({file:`Sidebar`,level:n,message:`Orphaned page found: "${r}" is not linked in the sidebar.`,suggestion:`Consider adding it to the sidebar for better discoverability.`})}return t}async function G(e){let t=[],n=e.doctorConfig.checks.performance;if(!n?.enabled)return t;let r=f.resolve(e.root,`.boltdocs`,`reports`,`performance.json`);if(!p.existsSync(r))return t.push({file:`(build)`,level:D(e,`budgetExceeded`,`warning`)??`warning`,message:"Performance metrics not found. Run `boltdocs build` first."}),t;let i;try{i=JSON.parse(p.readFileSync(r,`utf-8`))}catch{return t.push({file:`(build)`,level:D(e,`budgetExceeded`,`warning`)??`warning`,message:`Failed to parse performance metrics file.`}),t}let a=n.budgets,o=D(e,`budgetExceeded`,`warning`),s=E(a?.maxJSBundleSize,1/0),c=E(a?.maxCSSBundleSize,1/0),l=E(a?.maxPageHTMLSize,1/0),u=a?.maxImagesKB??1/0,d=a?.maxBuildTime??1/0,m=a?.maxFontCount??1/0;if(s!==1/0&&i.totalJSBundleSize>s){let e=(i.totalJSBundleSize/1024).toFixed(0),n=(s/1024).toFixed(0);t.push({file:`(build)`,level:o,message:`JS bundle size exceeds budget: ${e}kb > ${n}kb`,suggestion:`Code-split large dependencies or lazy-load route components.`})}if(c!==1/0&&i.totalCSSBundleSize>c){let e=(i.totalCSSBundleSize/1024).toFixed(0),n=(c/1024).toFixed(0);t.push({file:`(build)`,level:o,message:`CSS bundle size exceeds budget: ${e}kb > ${n}kb`,suggestion:`Remove unused styles or split CSS by route.`})}if(l!==1/0){for(let e of i.pages)if(e.htmlSize>l){let n=(e.htmlSize/1024).toFixed(0),r=(l/1024).toFixed(0);t.push({file:e.route,level:o,message:`Page HTML size exceeds budget: ${n}kb > ${r}kb`,suggestion:`Reduce the amount of inline content or split into sub-pages.`})}}let h=u*1024;if(u!==1/0&&i.totalImagesSize>h){let e=(i.totalImagesSize/1024).toFixed(0);t.push({file:`(build)`,level:o,message:`Image assets exceed budget: ${e}kb > ${u}kb`,suggestion:`Optimize images with lossy compression or use next-gen formats (webp/avif).`})}if(d!==1/0&&i.buildTime>d){let e=(i.buildTime/1e3).toFixed(1),n=(d/1e3).toFixed(1);t.push({file:`(build)`,level:o,message:`Build time exceeds budget: ${e}s > ${n}s`,suggestion:"Check for large unoptimized assets or increase `concurrency` in SSG options."})}return m!==1/0&&i.fontCount>m&&t.push({file:`(build)`,level:o,message:`Font files exceed budget: ${i.fontCount} > ${m}`,suggestion:`Reduce the number of font families or use variable fonts.`}),t}var K=e({DEFAULT_DOCTOR_CONFIG:()=>T,checkI18n:()=>U,checkLinks:()=>H,checkMetadata:()=>R,checkPerformance:()=>G,checkSidebar:()=>W,doctorAction:()=>J,doctorInit:()=>q,generateLinkTree:()=>N,loadDoctorConfig:()=>M});async function q(e){let t=f.resolve(e,`doctor.json`);if(p.existsSync(t)){S(`"doctor.json" already exists at ${e}.`);return}try{p.writeFileSync(t,JSON.stringify(T,null,2)),x(`Created "doctor.json" with default configuration.`)}catch(e){v(`Failed to create "doctor.json": ${e}`)}}async function J(e=process.cwd(),t={}){if(t.init){await q(e);return}d();try{let n=await M(e),{format:r}=n.reporting,i=performance.now(),a=await o(`docs`,e),d=f.resolve(e,`docs`);if(p.existsSync(d)||(r===`pretty`&&v(`Docs dir not found at ${d}`),process.exit(1)),r===`pretty`){let t=c?` ${s(`v${c}`)}`:``;console.log(`\n ${g.bold(`⚡`)} ${u(`boltdocs`)}${t} ${g.dim(`—`)} ${g.bold(`doctor`)} ${g.dim(`· documentation health check`)}\n`),console.log(` ${g.dim(`Docs dir ${d}`)}\n ${g.dim(`Reports ${e}/.boltdocs/reports/`)}\n`)}r===`pretty`&&y(g.dim(`🔍 Discovering files and routes...`));let S=te(n.exclude||[]),w=await new C().withFullPaths().filter(e=>{if(!(e.endsWith(`.md`)||e.endsWith(`.mdx`)))return!1;let t=f.relative(d,e).replace(/\\/g,`/`),n=t.split(`/`).some(e=>e.startsWith(`_`)&&e!==`_index.md`&&e!==`_index.mdx`);return!S(t)&&!n}).crawl(d).withPromise();for(let e of w)A.set(e,!0);let T=await N(d,e,a,w),E=a.base||`/`,D=E===`/`?``:E.endsWith(`/`)?E.slice(0,-1):E,O=new Set(T.routes),k=new Set(T.routes.map(e=>e.endsWith(`/`)?e:e+`/`)),j=new Set(T.routes.map(e=>e.endsWith(`/`)?e.slice(0,-1):e));r===`pretty`&&y(g.dim(`🧪 Running diagnostic checks in parallel...`));let P={root:e,docsDir:d,config:a,doctorConfig:n,linkTree:T,files:w,options:t,routeIndex:O,routeIndexWithSlash:k,routeIndexWithoutSlash:j,basePrefix:D};r===`pretty`&&y(g.dim(`🧪 Running diagnostic checks in parallel...`));let F=[R(P),H(P),U(P),W(P)];t.budget&&F.push(G(P));let[I,L,z,B,...V]=await Promise.all(F),K=t.budget?V[0]??[]:[],q=[...I,...L,...z,...B,...K];if(r===`pretty`){let e=e=>e>0?g.red(`${e} issue${e===1?``:`s`}`):g.green(`OK`),n=[{label:`Metadata checks ${e(I.length)}`,done:I.length===0},{label:`Link checks ${e(L.length)}`,done:L.length===0},{label:`i18n checks ${e(z.length)}`,done:z.length===0},{label:`Sidebar checks ${e(B.length)}`,done:B.length===0}];t.budget&&n.push({label:`Performance budget ${e(K.length)}`,done:K.length===0}),console.log(`\n${ee(n)}\n`)}let J=0;if(t.fix){for(let e of q)if(e.fix){if(P.doctorConfig.fix.confirmChanges&&!await _(`Fix issue in "${e.file}": ${e.message}?`))continue;if(P.doctorConfig.fix.backupFiles){let t=f.resolve(P.docsDir,e.file);p.existsSync(t)&&await ne(t,f.resolve(P.root,P.doctorConfig.fix.backupPath))}await e.fix(),J++}}let Y=((performance.now()-i)/1e3).toFixed(2),X=q.filter(e=>e.level===`high`).length,Z=q.filter(e=>e.level===`warning`).length,Q=q.filter(e=>e.level===`low`).length,$={summary:{total:q.length,high:X,warning:Z,low:Q,fixed:J,duration:Y},issues:q.map(e=>({...e,fix:void 0}))};if(n.reporting.outputFile){let t=f.resolve(e,n.reporting.outputFile);p.existsSync(f.dirname(t))||p.mkdirSync(f.dirname(t),{recursive:!0}),p.writeFileSync(t,JSON.stringify($,null,2))}if(r===`json`)console.log(JSON.stringify($,null,2));else if(r===`pretty`){let e=q.reduce((e,t)=>(e[t.file]||(e[t.file]=[]),e[t.file].push(t),e),{});if(q.length>0){console.log(b({title:`Issues`,colors:{title:l}}));for(let[n,r]of Object.entries(e)){let e=r.some(e=>e.level===`high`)?`high`:r.some(e=>e.level===`warning`)?`warning`:`low`,i=e.toUpperCase(),a=m(e===`high`?{label:i,status:`error`}:e===`warning`?{label:i,status:`warning`}:{label:i,colors:{text:`#ffffff`,bg:l}});console.log(`\n ${a} ${g.bold(n)}`);for(let e of r){let n=e.level===`high`?`✖`:e.level===`warning`?`⚠`:`ℹ`,r=e.level===`high`?g.red:e.level===`warning`?g.yellow:e=>h(e,l,`fg`);console.log(` ${r(n)} ${e.message}`),e.suggestion&&console.log(` ${g.dim(`💡 ${e.suggestion}`)}`),t.fix&&e.fix&&console.log(` ${g.green(`✅ Fixed automatically`)}`)}}console.log(``)}q.length===0?(console.log(` ${g.green.bold(`✨ Everything looks perfect!`)} ${g.dim(`— your documentation is in great shape.`)}`),console.log(` ${g.dim(`Scanned ${w.length} file${w.length===1?``:`s`} in ${Y}s`)}`)):(console.log(`\n${b({title:`Summary`,colors:{title:l}})}`),X>0&&console.log(` ${m({label:String(X),status:`error`})} ${g.bold(`high`)}`),Z>0&&console.log(` ${m({label:String(Z),status:`warning`})} ${g.bold(`warning`)}${Z===1?``:`s`}`),Q>0&&console.log(` ${m({label:String(Q),colors:{text:`#ffffff`,bg:l}})} ${g.bold(`low`)}`),console.log(` ${g.dim(`Scanned ${w.length} file${w.length===1?``:`s`} in ${Y}s`)}`),J>0&&x(`Successfully fixed ${J} issues automatically!`),X>0?v(`Please fix the critical errors before building for production.`):x(`No critical issues found. You are ready to go!`))}n.reporting.failOnError&&X>0&&process.exit(1),n.reporting.maxWarnings!==-1&&Z>n.reporting.maxWarnings&&(r===`pretty`&&v(`Failed: Too many warnings (${Z} > ${n.reporting.maxWarnings})`),process.exit(1))}catch(e){v(`Doctor failed: ${e}`),process.exit(1)}}export{N as n,K as t};
@@ -7,15 +7,17 @@ const e=require(`./chunk-D1Md3oWO.cjs`);let t=require(`node:path`);t=e.r(t);let
7
7
  `),n=[],r=null,u=``;for(let e=0;e<t.length;e++){let f=t[e].trim(),p=f.match(/^##\s+v?(\d+\.\d+\.\d+)/);if(p){r&&n.push(r);let a=i(p[1]),o=`patch`,s,c=f.match(/\((\d{4}-\d{2}-\d{2})\)/);c&&(s=c[1]);let l=d(t,e);l&&(o=l),r={version:a,type:o,date:s,changes:[]},u=``;continue}let m=f.match(/^###\s+(.+)$/i);if(m){u=m[1].toLowerCase();continue}if(f.startsWith(`- `)&&r){let e=f.slice(2).trim(),t=`other`;u.includes(`feat`)||u.includes(`minor`)?t=`feat`:u.includes(`fix`)||u.includes(`patch`)?t=`fix`:u.includes(`perf`)?t=`perf`:u.includes(`refactor`)?t=`refactor`:u.includes(`docs`)||u.includes(`documentation`)?t=`docs`:u.includes(`chore`)&&(t=`chore`);let n={type:t,message:l(e,t),author:a(e),authorUrl:o(e),commit:s(e),commitUrl:c(e)};r.changes.push(n)}}return r&&n.push(r),n}const p={name:`changesets`,detect:u,parse:f},m={added:`feat`,changed:`refactor`,deprecated:`fix`,removed:`fix`,fixed:`fix`,security:`fix`};function h(e){let t=/^#\s+Changelog/i.test(e),n=/^##\s*\[[\d.]+\]\s*-\s*\d{4}-\d{2}-\d{2}/m.test(e),r=/^###\s+(Added|Changed|Deprecated|Removed|Fixed|Security)$/m.test(e);return t&&n&&r}function g(e){let t=e.split(`
8
8
  `),n=[],r=null,u=``;for(let e=0;e<t.length;e++){let d=t[e].trim(),f=d.match(/^##\s*\[(\d+\.\d+\.\d+[^\]]*)\]\s*-\s*(\d{4}-\d{2}-\d{2})/);if(f){r&&n.push(r),r={version:i(f[1]),type:`patch`,date:f[2],changes:[]},u=``;continue}if(d.match(/^##\s*\[Unreleased\]/i)){r&&n.push(r),r={version:`unreleased`,type:`patch`,date:void 0,changes:[]},u=``;continue}let p=d.match(/^###\s+(Added|Changed|Deprecated|Removed|Fixed|Security)$/i);if(p){u=p[1].toLowerCase();continue}if((d.startsWith(`- `)||d.startsWith(`* `))&&r){let e=d.slice(2).trim(),t=m[u]||`other`,n={type:t,message:l(e,t),author:a(e),authorUrl:o(e),commit:s(e),commitUrl:c(e)};r.changes.push(n)}}return r&&n.push(r),n}const _={name:`keep-a-changelog`,detect:h,parse:g},v={features:`feat`,"breaking changes":`feat`,breaking:`feat`,"bug fixes":`fix`,bugfixes:`fix`,fixes:`fix`,performance:`perf`,"build system":`chore`,builds:`chore`,tests:`chore`,chores:`chore`,documentation:`docs`,docs:`docs`,revert:`fix`,reverts:`fix`,refactor:`refactor`,"code refactoring":`refactor`};function y(e){let t=/^###\s+(Features|Bug Fixes|BREAKING CHANGES|Build System|Tests|Chores|Documentation|Reverts)/m.test(e),n=/^\*\*[a-z]+(\([^)]+\))?:\*\*/m.test(e),r=/^##\s*\[[\d.]+\]\([^)]+\)\s*\(\d{4}-\d{2}-\d{2}\)/m.test(e);return t&&(n||r)}function b(e){let t=e.split(`
9
9
  `),n=[],r=null,u=``;for(let e=0;e<t.length;e++){let d=t[e].trim(),f=d.match(/^##\s*\[(\d+\.\d+\.\d+[^\]]*)\]\([^)]+\)\s*\((\d{4}-\d{2}-\d{2})\)/);if(f){r&&n.push(r);let a=i(f[1]),o=`patch`;for(let n=e+1;n<Math.min(e+20,t.length);n++){let e=t[n].toLowerCase();if(e.includes(`major`)||e.includes(`breaking`)){o=`major`;break}(e.includes(`minor`)||e.includes(`feat`))&&(o=`minor`)}r={version:a,type:o,date:f[2],changes:[]},u=``;continue}let p=d.match(/^###\s+(.+)$/i);if(p){u=p[1].toLowerCase();continue}if((d.startsWith(`- `)||d.startsWith(`* `))&&r){let e=d.slice(2).trim(),t=v[u]||`other`,n={type:t,message:l(e,t),author:a(e),authorUrl:o(e),commit:s(e),commitUrl:c(e)};r.changes.push(n)}}return r&&n.push(r),n}const x={name:`semantic-release`,detect:y,parse:b},S={features:`feat`,"breaking changes":`feat`,breaking:`feat`,"bug fixes":`fix`,fixes:`fix`,performance:`perf`,"build system":`chore`,builds:`chore`,tests:`chore`,chores:`chore`,documentation:`docs`,docs:`docs`,revert:`fix`,reverts:`fix`,refactor:`refactor`,"code refactoring":`refactor`};function C(e){let t=/^##\s+(\d+\.\d+\.\d+)\s*\((\d{4}-\d{2}-\d{2})\)/m.test(e),n=/^###\s+(Features|Bug Fixes|BREAKING CHANGES|Build System|Tests|Chores|Documentation)/m.test(e),r=/^[*-]\s+/m.test(e);return t&&n&&r}function w(e){let t=e.split(`
10
- `),n=[],r=null,u=``;for(let e=0;e<t.length;e++){let d=t[e].trim(),f=d.match(/^##\s+(\d+\.\d+\.\d+)\s*\((\d{4}-\d{2}-\d{2})\)/);if(f){r&&n.push(r);let a=i(f[1]),o=`patch`;for(let n=e+1;n<Math.min(e+20,t.length);n++){let e=t[n].toLowerCase();if(e.includes(`major`)||e.includes(`breaking`)){o=`major`;break}(e.includes(`minor`)||e.includes(`feat`))&&(o=`minor`)}r={version:a,type:o,date:f[2],changes:[]},u=``;continue}let p=d.match(/^###\s+(.+)$/i);if(p){u=p[1].toLowerCase();continue}if((d.startsWith(`- `)||d.startsWith(`* `))&&r){let e=d.slice(2).trim(),t=S[u]||`other`,n={type:t,message:l(e,t),author:a(e),authorUrl:o(e),commit:s(e),commitUrl:c(e)};r.changes.push(n)}}return r&&n.push(r),n}const T=[_,x,{name:`standard-version`,detect:C,parse:w},p];function E(e){for(let t of T)if(t.detect(e))return{parser:t,name:t.name};return{parser:p,name:`changesets (fallback)`}}function D(e){let{parser:t}=E(e);return t?.parse(e)||[]}function O(e){return D(e)}function k(e){let r=t.default.resolve(e);if(!n.default.existsSync(r))throw Error(`Changelog file not found: ${r}`);return n.default.readFileSync(r,`utf-8`)}const A={feat:`Feature`,fix:`Bug Fix`,perf:`Performance`,refactor:`Refactor`,docs:`Documentation`,chore:`Chore`,other:`Other`};async function j(e,i={}){let a=t.default.resolve(i.output||`docs/changelog`),o=i.title||`Changelog`,s=i.inferTab!==!1,c=i.limit?Math.max(1,i.limit):void 0;(0,r.info)(`📄 Reading changelog from: ${e}`);let l=O(k(e));if(l.length===0){(0,r.warn)(`⚠️ No versions found in changelog`);return}let u=c?l.slice(0,c):l;n.default.existsSync(a)||(n.default.mkdirSync(a,{recursive:!0}),(0,r.info)(`📁 Created directory: ${a}`));for(let[e,i]of u.entries()){let c=M(i,o,s),l=`${e+1}.v${i.version}.md`,u=t.default.join(a,l);n.default.writeFileSync(u,c,`utf-8`),(0,r.success)(`Generated: ${l}`)}let d=[` ✨ Generated ${c&&c<l.length?`${c} of ${l.length} versions`:`${l.length} versions`} changelog pages in ${a}`,``,` 📝 Add this to your navbar in boltdocs.config.ts:`,` { label: '${o}', href: '/changelog' }`];console.log(`\n${(0,r.double)(d,{title:`Changelog Generation`})}\n`)}function M(e,t,n){let r=e.type.charAt(0).toUpperCase()+e.type.slice(1),i=N(e.changes),a=`---
10
+ `),n=[],r=null,u=``;for(let e=0;e<t.length;e++){let d=t[e].trim(),f=d.match(/^##\s+(\d+\.\d+\.\d+)\s*\((\d{4}-\d{2}-\d{2})\)/);if(f){r&&n.push(r);let a=i(f[1]),o=`patch`;for(let n=e+1;n<Math.min(e+20,t.length);n++){let e=t[n].toLowerCase();if(e.includes(`major`)||e.includes(`breaking`)){o=`major`;break}(e.includes(`minor`)||e.includes(`feat`))&&(o=`minor`)}r={version:a,type:o,date:f[2],changes:[]},u=``;continue}let p=d.match(/^###\s+(.+)$/i);if(p){u=p[1].toLowerCase();continue}if((d.startsWith(`- `)||d.startsWith(`* `))&&r){let e=d.slice(2).trim(),t=S[u]||`other`,n={type:t,message:l(e,t),author:a(e),authorUrl:o(e),commit:s(e),commitUrl:c(e)};r.changes.push(n)}}return r&&n.push(r),n}const T=[_,x,{name:`standard-version`,detect:C,parse:w},p];function E(e){for(let t of T)if(t.detect(e))return{parser:t,name:t.name};return{parser:p,name:`changesets (fallback)`}}function D(e){let{parser:t}=E(e);return t?.parse(e)||[]}function O(e){return D(e)}function k(e){let r=t.default.resolve(e);if(!n.default.existsSync(r))throw Error(`Changelog file not found: ${r}`);return n.default.readFileSync(r,`utf-8`)}const A={feat:`Feature`,fix:`Bug Fix`,perf:`Performance`,refactor:`Refactor`,docs:`Documentation`,chore:`Chore`,other:`Other`};function j(e){let t=``,n=!1;for(let r of e)r==="`"?(n=!n,t+=r):!n&&(r===`{`||r===`}`)?t+=`\\${r}`:t+=r;return t}async function M(e,i={}){let a=t.default.resolve(i.output||`docs/changelog`),o=i.title||`Changelog`,s=i.inferTab!==!1,c=i.limit?Math.max(1,i.limit):void 0;(0,r.info)(`📄 Reading changelog from: ${e}`);let l=O(k(e));if(l.length===0){(0,r.warn)(`⚠️ No versions found in changelog`);return}let u=l;i.type?u=l.filter(e=>e.type===i.type):c?u=l.filter(e=>e.type!==`patch`).slice(0,c):(u=l.filter(e=>e.type!==`patch`),u.length===0&&(u=l)),n.default.existsSync(a)||(n.default.mkdirSync(a,{recursive:!0}),(0,r.info)(`📁 Created directory: ${a}`));for(let[e,i]of u.entries()){let c=P(i,o,s),l=`${e+1}.v${i.version}.md`,u=t.default.join(a,l);n.default.writeFileSync(u,c,`utf-8`),(0,r.success)(`Generated: ${l}`)}let d=i.type?l.filter(e=>e.type===i.type).length:l.filter(e=>e.type!==`patch`).length,f=c?Math.min(c,l.filter(e=>e.type!==`patch`).length):void 0,p=[` ✨ Generated ${(i.type?d:f??l.filter(e=>e.type!==`patch`).length)+` of `+l.filter(e=>e.type!==`patch`).length+` versions`}${i.type?` (${i.type})`:``} changelog pages in ${a}`,``,` 📝 Add this to your navbar in boltdocs.config.ts:`,` { label: '${o}', href: '/changelog' }`];console.log(`\n${(0,r.double)(p,{title:`Changelog Generation`})}\n`)}function N(e){let t=e.replace(/^v/,``);return{"2.8.0":`/blog-covers/Boltdocs-2.8.0.webp`,"2.9.0":`/blog-covers/Boltdocs-2.9.0.webp`,"3.0.0":`/blog-covers/Boltdocs-3.0.0.webp`,"3.1.0":`/blog-covers/Boltdocs-3.1.0.webp`,"3.2.0":`/blog-covers/Boltdocs-3.2.0.webp`,"4.0.0-Nitro":`/blog-covers/Boltdocs-4.0.0-Nitro.webp`}[t]}function P(e,t,n){let r=e.type.charAt(0).toUpperCase()+e.type.slice(1),i=F(e.changes),a=N(e.version),o=`---
11
11
  title: v${e.version}
12
12
  badge: "${r}"
13
13
  description: Changelog version ${e.version}${e.date?` (${e.date})`:``}
14
+ tab: "(releases)"
15
+ ${a?`cover: "${a}"`:``}
14
16
  ---
15
17
 
16
18
  # ${t} v${e.version}
17
19
 
18
20
  ${e.date?`**Released:** ${e.date}`:``}
19
21
 
20
- `;for(let[e,t]of Object.entries(i)){if(t.length===0)continue;let n=A[e]||e;a+=`## ${n}\n\n`;for(let e of t)a+=`- ${e.message}\n`,e.author&&(e.authorUrl?a+=` - **Author:** [@${e.author}](${e.authorUrl})\n`:a+=` - **Author:** @${e.author}\n`),e.commit&&(e.commitUrl?a+=` - **Commit:** [\`${e.commit.slice(0,7)}\`](${e.commitUrl})\n`:a+=` - **Commit:** \`${e.commit.slice(0,7)}\`\n`);a+=`
21
- `}return a}function N(e){let t={feat:[],fix:[],perf:[],refactor:[],docs:[],chore:[],other:[]};for(let n of e)t[t[n.type]?n.type:`other`].push(n);return t}exports.generateChangelog=j;
22
+ `;for(let[e,t]of Object.entries(i)){if(t.length===0)continue;let n=A[e]||e;o+=`## ${n}\n\n`;for(let e of t)o+=`- ${j(e.message)}\n`,e.author&&(e.authorUrl?o+=` - **Author:** [@${e.author}](${e.authorUrl})\n`:o+=` - **Author:** @${e.author}\n`),e.commit&&(e.commitUrl?o+=` - **Commit:** [\`${e.commit.slice(0,7)}\`](${e.commitUrl})\n`:o+=` - **Commit:** \`${e.commit.slice(0,7)}\`\n`);o+=`
23
+ `}return o}function F(e){let t={feat:[],fix:[],perf:[],refactor:[],docs:[],chore:[],other:[]};for(let n of e)t[t[n.type]?n.type:`other`].push(n);return t}exports.generateChangelog=M;
@@ -7,15 +7,17 @@ import e from"node:path";import t from"node:fs";import{double as n,info as r,suc
7
7
  `),n=[],r=null,i=``;for(let e=0;e<t.length;e++){let a=t[e].trim(),f=a.match(/^##\s+v?(\d+\.\d+\.\d+)/);if(f){r&&n.push(r);let s=o(f[1]),c=`patch`,l,u=a.match(/\((\d{4}-\d{2}-\d{2})\)/);u&&(l=u[1]);let d=p(t,e);d&&(c=d),r={version:s,type:c,date:l,changes:[]},i=``;continue}let m=a.match(/^###\s+(.+)$/i);if(m){i=m[1].toLowerCase();continue}if(a.startsWith(`- `)&&r){let e=a.slice(2).trim(),t=`other`;i.includes(`feat`)||i.includes(`minor`)?t=`feat`:i.includes(`fix`)||i.includes(`patch`)?t=`fix`:i.includes(`perf`)?t=`perf`:i.includes(`refactor`)?t=`refactor`:i.includes(`docs`)||i.includes(`documentation`)?t=`docs`:i.includes(`chore`)&&(t=`chore`);let n={type:t,message:d(e,t),author:s(e),authorUrl:c(e),commit:l(e),commitUrl:u(e)};r.changes.push(n)}}return r&&n.push(r),n}const h={name:`changesets`,detect:f,parse:m},g={added:`feat`,changed:`refactor`,deprecated:`fix`,removed:`fix`,fixed:`fix`,security:`fix`};function _(e){let t=/^#\s+Changelog/i.test(e),n=/^##\s*\[[\d.]+\]\s*-\s*\d{4}-\d{2}-\d{2}/m.test(e),r=/^###\s+(Added|Changed|Deprecated|Removed|Fixed|Security)$/m.test(e);return t&&n&&r}function v(e){let t=e.split(`
8
8
  `),n=[],r=null,i=``;for(let e=0;e<t.length;e++){let a=t[e].trim(),f=a.match(/^##\s*\[(\d+\.\d+\.\d+[^\]]*)\]\s*-\s*(\d{4}-\d{2}-\d{2})/);if(f){r&&n.push(r),r={version:o(f[1]),type:`patch`,date:f[2],changes:[]},i=``;continue}if(a.match(/^##\s*\[Unreleased\]/i)){r&&n.push(r),r={version:`unreleased`,type:`patch`,date:void 0,changes:[]},i=``;continue}let p=a.match(/^###\s+(Added|Changed|Deprecated|Removed|Fixed|Security)$/i);if(p){i=p[1].toLowerCase();continue}if((a.startsWith(`- `)||a.startsWith(`* `))&&r){let e=a.slice(2).trim(),t=g[i]||`other`,n={type:t,message:d(e,t),author:s(e),authorUrl:c(e),commit:l(e),commitUrl:u(e)};r.changes.push(n)}}return r&&n.push(r),n}const y={name:`keep-a-changelog`,detect:_,parse:v},b={features:`feat`,"breaking changes":`feat`,breaking:`feat`,"bug fixes":`fix`,bugfixes:`fix`,fixes:`fix`,performance:`perf`,"build system":`chore`,builds:`chore`,tests:`chore`,chores:`chore`,documentation:`docs`,docs:`docs`,revert:`fix`,reverts:`fix`,refactor:`refactor`,"code refactoring":`refactor`};function x(e){let t=/^###\s+(Features|Bug Fixes|BREAKING CHANGES|Build System|Tests|Chores|Documentation|Reverts)/m.test(e),n=/^\*\*[a-z]+(\([^)]+\))?:\*\*/m.test(e),r=/^##\s*\[[\d.]+\]\([^)]+\)\s*\(\d{4}-\d{2}-\d{2}\)/m.test(e);return t&&(n||r)}function S(e){let t=e.split(`
9
9
  `),n=[],r=null,i=``;for(let e=0;e<t.length;e++){let a=t[e].trim(),f=a.match(/^##\s*\[(\d+\.\d+\.\d+[^\]]*)\]\([^)]+\)\s*\((\d{4}-\d{2}-\d{2})\)/);if(f){r&&n.push(r);let a=o(f[1]),s=`patch`;for(let n=e+1;n<Math.min(e+20,t.length);n++){let e=t[n].toLowerCase();if(e.includes(`major`)||e.includes(`breaking`)){s=`major`;break}(e.includes(`minor`)||e.includes(`feat`))&&(s=`minor`)}r={version:a,type:s,date:f[2],changes:[]},i=``;continue}let p=a.match(/^###\s+(.+)$/i);if(p){i=p[1].toLowerCase();continue}if((a.startsWith(`- `)||a.startsWith(`* `))&&r){let e=a.slice(2).trim(),t=b[i]||`other`,n={type:t,message:d(e,t),author:s(e),authorUrl:c(e),commit:l(e),commitUrl:u(e)};r.changes.push(n)}}return r&&n.push(r),n}const C={name:`semantic-release`,detect:x,parse:S},w={features:`feat`,"breaking changes":`feat`,breaking:`feat`,"bug fixes":`fix`,fixes:`fix`,performance:`perf`,"build system":`chore`,builds:`chore`,tests:`chore`,chores:`chore`,documentation:`docs`,docs:`docs`,revert:`fix`,reverts:`fix`,refactor:`refactor`,"code refactoring":`refactor`};function T(e){let t=/^##\s+(\d+\.\d+\.\d+)\s*\((\d{4}-\d{2}-\d{2})\)/m.test(e),n=/^###\s+(Features|Bug Fixes|BREAKING CHANGES|Build System|Tests|Chores|Documentation)/m.test(e),r=/^[*-]\s+/m.test(e);return t&&n&&r}function E(e){let t=e.split(`
10
- `),n=[],r=null,i=``;for(let e=0;e<t.length;e++){let a=t[e].trim(),f=a.match(/^##\s+(\d+\.\d+\.\d+)\s*\((\d{4}-\d{2}-\d{2})\)/);if(f){r&&n.push(r);let a=o(f[1]),s=`patch`;for(let n=e+1;n<Math.min(e+20,t.length);n++){let e=t[n].toLowerCase();if(e.includes(`major`)||e.includes(`breaking`)){s=`major`;break}(e.includes(`minor`)||e.includes(`feat`))&&(s=`minor`)}r={version:a,type:s,date:f[2],changes:[]},i=``;continue}let p=a.match(/^###\s+(.+)$/i);if(p){i=p[1].toLowerCase();continue}if((a.startsWith(`- `)||a.startsWith(`* `))&&r){let e=a.slice(2).trim(),t=w[i]||`other`,n={type:t,message:d(e,t),author:s(e),authorUrl:c(e),commit:l(e),commitUrl:u(e)};r.changes.push(n)}}return r&&n.push(r),n}const D=[y,C,{name:`standard-version`,detect:T,parse:E},h];function O(e){for(let t of D)if(t.detect(e))return{parser:t,name:t.name};return{parser:h,name:`changesets (fallback)`}}function k(e){let{parser:t}=O(e);return t?.parse(e)||[]}function A(e){return k(e)}function j(n){let r=e.resolve(n);if(!t.existsSync(r))throw Error(`Changelog file not found: ${r}`);return t.readFileSync(r,`utf-8`)}const M={feat:`Feature`,fix:`Bug Fix`,perf:`Performance`,refactor:`Refactor`,docs:`Documentation`,chore:`Chore`,other:`Other`};async function N(o,s={}){let c=e.resolve(s.output||`docs/changelog`),l=s.title||`Changelog`,u=s.inferTab!==!1,d=s.limit?Math.max(1,s.limit):void 0;r(`📄 Reading changelog from: ${o}`);let f=A(j(o));if(f.length===0){a(`⚠️ No versions found in changelog`);return}let p=d?f.slice(0,d):f;t.existsSync(c)||(t.mkdirSync(c,{recursive:!0}),r(`📁 Created directory: ${c}`));for(let[n,r]of p.entries()){let a=P(r,l,u),o=`${n+1}.v${r.version}.md`,s=e.join(c,o);t.writeFileSync(s,a,`utf-8`),i(`Generated: ${o}`)}let m=[` ✨ Generated ${d&&d<f.length?`${d} of ${f.length} versions`:`${f.length} versions`} changelog pages in ${c}`,``,` 📝 Add this to your navbar in boltdocs.config.ts:`,` { label: '${l}', href: '/changelog' }`];console.log(`\n${n(m,{title:`Changelog Generation`})}\n`)}function P(e,t,n){let r=e.type.charAt(0).toUpperCase()+e.type.slice(1),i=F(e.changes),a=`---
10
+ `),n=[],r=null,i=``;for(let e=0;e<t.length;e++){let a=t[e].trim(),f=a.match(/^##\s+(\d+\.\d+\.\d+)\s*\((\d{4}-\d{2}-\d{2})\)/);if(f){r&&n.push(r);let a=o(f[1]),s=`patch`;for(let n=e+1;n<Math.min(e+20,t.length);n++){let e=t[n].toLowerCase();if(e.includes(`major`)||e.includes(`breaking`)){s=`major`;break}(e.includes(`minor`)||e.includes(`feat`))&&(s=`minor`)}r={version:a,type:s,date:f[2],changes:[]},i=``;continue}let p=a.match(/^###\s+(.+)$/i);if(p){i=p[1].toLowerCase();continue}if((a.startsWith(`- `)||a.startsWith(`* `))&&r){let e=a.slice(2).trim(),t=w[i]||`other`,n={type:t,message:d(e,t),author:s(e),authorUrl:c(e),commit:l(e),commitUrl:u(e)};r.changes.push(n)}}return r&&n.push(r),n}const D=[y,C,{name:`standard-version`,detect:T,parse:E},h];function O(e){for(let t of D)if(t.detect(e))return{parser:t,name:t.name};return{parser:h,name:`changesets (fallback)`}}function k(e){let{parser:t}=O(e);return t?.parse(e)||[]}function A(e){return k(e)}function j(n){let r=e.resolve(n);if(!t.existsSync(r))throw Error(`Changelog file not found: ${r}`);return t.readFileSync(r,`utf-8`)}const M={feat:`Feature`,fix:`Bug Fix`,perf:`Performance`,refactor:`Refactor`,docs:`Documentation`,chore:`Chore`,other:`Other`};function N(e){let t=``,n=!1;for(let r of e)r==="`"?(n=!n,t+=r):!n&&(r===`{`||r===`}`)?t+=`\\${r}`:t+=r;return t}async function P(o,s={}){let c=e.resolve(s.output||`docs/changelog`),l=s.title||`Changelog`,u=s.inferTab!==!1,d=s.limit?Math.max(1,s.limit):void 0;r(`📄 Reading changelog from: ${o}`);let f=A(j(o));if(f.length===0){a(`⚠️ No versions found in changelog`);return}let p=f;s.type?p=f.filter(e=>e.type===s.type):d?p=f.filter(e=>e.type!==`patch`).slice(0,d):(p=f.filter(e=>e.type!==`patch`),p.length===0&&(p=f)),t.existsSync(c)||(t.mkdirSync(c,{recursive:!0}),r(`📁 Created directory: ${c}`));for(let[n,r]of p.entries()){let a=I(r,l,u),o=`${n+1}.v${r.version}.md`,s=e.join(c,o);t.writeFileSync(s,a,`utf-8`),i(`Generated: ${o}`)}let m=s.type?f.filter(e=>e.type===s.type).length:f.filter(e=>e.type!==`patch`).length,h=d?Math.min(d,f.filter(e=>e.type!==`patch`).length):void 0,g=[` ✨ Generated ${(s.type?m:h??f.filter(e=>e.type!==`patch`).length)+` of `+f.filter(e=>e.type!==`patch`).length+` versions`}${s.type?` (${s.type})`:``} changelog pages in ${c}`,``,` 📝 Add this to your navbar in boltdocs.config.ts:`,` { label: '${l}', href: '/changelog' }`];console.log(`\n${n(g,{title:`Changelog Generation`})}\n`)}function F(e){let t=e.replace(/^v/,``);return{"2.8.0":`/blog-covers/Boltdocs-2.8.0.webp`,"2.9.0":`/blog-covers/Boltdocs-2.9.0.webp`,"3.0.0":`/blog-covers/Boltdocs-3.0.0.webp`,"3.1.0":`/blog-covers/Boltdocs-3.1.0.webp`,"3.2.0":`/blog-covers/Boltdocs-3.2.0.webp`,"4.0.0-Nitro":`/blog-covers/Boltdocs-4.0.0-Nitro.webp`}[t]}function I(e,t,n){let r=e.type.charAt(0).toUpperCase()+e.type.slice(1),i=L(e.changes),a=F(e.version),o=`---
11
11
  title: v${e.version}
12
12
  badge: "${r}"
13
13
  description: Changelog version ${e.version}${e.date?` (${e.date})`:``}
14
+ tab: "(releases)"
15
+ ${a?`cover: "${a}"`:``}
14
16
  ---
15
17
 
16
18
  # ${t} v${e.version}
17
19
 
18
20
  ${e.date?`**Released:** ${e.date}`:``}
19
21
 
20
- `;for(let[e,t]of Object.entries(i)){if(t.length===0)continue;let n=M[e]||e;a+=`## ${n}\n\n`;for(let e of t)a+=`- ${e.message}\n`,e.author&&(e.authorUrl?a+=` - **Author:** [@${e.author}](${e.authorUrl})\n`:a+=` - **Author:** @${e.author}\n`),e.commit&&(e.commitUrl?a+=` - **Commit:** [\`${e.commit.slice(0,7)}\`](${e.commitUrl})\n`:a+=` - **Commit:** \`${e.commit.slice(0,7)}\`\n`);a+=`
21
- `}return a}function F(e){let t={feat:[],fix:[],perf:[],refactor:[],docs:[],chore:[],other:[]};for(let n of e)t[t[n.type]?n.type:`other`].push(n);return t}export{N as generateChangelog};
22
+ `;for(let[e,t]of Object.entries(i)){if(t.length===0)continue;let n=M[e]||e;o+=`## ${n}\n\n`;for(let e of t)o+=`- ${N(e.message)}\n`,e.author&&(e.authorUrl?o+=` - **Author:** [@${e.author}](${e.authorUrl})\n`:o+=` - **Author:** @${e.author}\n`),e.commit&&(e.commitUrl?o+=` - **Commit:** [\`${e.commit.slice(0,7)}\`](${e.commitUrl})\n`:o+=` - **Commit:** \`${e.commit.slice(0,7)}\`\n`);o+=`
23
+ `}return o}function L(e){let t={feat:[],fix:[],perf:[],refactor:[],docs:[],chore:[],other:[]};for(let n of e)t[t[n.type]?n.type:`other`].push(n);return t}export{P as generateChangelog};
@@ -3,7 +3,7 @@
3
3
  * Copyright (c) 2026 Jesus Alcala
4
4
  * Licensed under the MIT License.
5
5
  */
6
- const e=require(`./chunk-D1Md3oWO.cjs`);let t=require(`zod`);t=e.r(t);let n=require(`node:crypto`);n=e.r(n);function r(e,t){let r={alg:`RS256`,typ:`JWT`},i=Math.floor(Date.now()/1e3),a={iat:i-60,exp:i+600,iss:e},o=e=>Buffer.from(JSON.stringify(e)).toString(`base64url`),s=o(r),c=o(a),l=n.default.createSign(`RSA-SHA256`);l.update(`${s}.${c}`);let u=t.replace(/\\n/g,`
6
+ const e=require(`./chunk-D1Md3oWO.cjs`);let t=require(`node:crypto`);t=e.r(t);let n=require(`zod`);n=e.r(n);function r(e,n){let r={alg:`RS256`,typ:`JWT`},i=Math.floor(Date.now()/1e3),a={iat:i-60,exp:i+600,iss:e},o=e=>Buffer.from(JSON.stringify(e)).toString(`base64url`),s=o(r),c=o(a),l=t.default.createSign(`RSA-SHA256`);l.update(`${s}.${c}`);let u=n.replace(/\\n/g,`
7
7
  `);return`${s}.${c}.${l.sign(u,`base64`)}`}async function i(e,t,n){let i=r(e,t),a=await fetch(`https://api.github.com/app/installations/${n}/access_tokens`,{method:`POST`,headers:{Authorization:`Bearer ${i}`,Accept:`application/vnd.github+json`,"User-Agent":`Boltdocs-Feedback`}});if(!a.ok){let e=await a.text();throw Error(`Failed to get installation access token: ${a.status} ${e}`)}return(await a.json()).token}async function a(e,t,n={}){let r=await fetch(`https://api.github.com/graphql`,{method:`POST`,headers:{Authorization:`bearer ${e}`,"Content-Type":`application/json`,"User-Agent":`Boltdocs-Feedback`},body:JSON.stringify({query:t,variables:n})});if(!r.ok){let e=await r.text();throw Error(`GitHub GraphQL API error: ${r.status} ${e}`)}let i=await r.json();if(i.errors?.length){let e=i.errors.map(e=>e.message).join(`, `);throw Error(`GitHub GraphQL Error: ${e}`)}return i.data}async function o(e,t){let n=t.token;if(!n)if(t.appId&&t.privateKey&&t.installationId)n=await i(t.appId,t.privateKey,t.installationId);else throw Error(`GitHub authentication credentials missing. Provide GITHUB_TOKEN or GITHUB_APP_* variables.`);let{owner:r,repo:o,categorySlug:s=`general`}=t,{rating:c,comment:l,path:u,title:d,blockId:f}=e,p=await a(n,`query GetRepoAndCategory($owner: String!, $name: String!, $categorySlug: String!) {
8
8
  repository(owner: $owner, name: $name) {
9
9
  id
@@ -25,4 +25,4 @@ _No comments provided._`];return await a(n,`mutation AddComment($discussionId: I
25
25
  comment { id }
26
26
  }
27
27
  }`,{discussionId:_,body:v.filter(Boolean).join(`
28
- `)}),{success:!0}}var s=e.t({handleFeedback:()=>l});const c=t.object({rating:t.enum([`good`,`neutral`,`bad`]),path:t.string(),title:t.string(),comment:t.string().optional()});async function l(e,t=process.env,n={}){let r=c.safeParse(e);if(!r.success)throw Error(`Invalid feedback payload`);let i=r.data,a=n.owner||t.GITHUB_REPO_OWNER||t.BOLTDOCS_GITHUB_REPO_OWNER,s=n.repo||t.GITHUB_REPO_NAME||t.BOLTDOCS_GITHUB_REPO_NAME,l=n.categorySlug||t.GITHUB_DISCUSSION_CATEGORY||t.BOLTDOCS_GITHUB_DISCUSSION_CATEGORY||`general`,u=n.token||t.BOLTDOCS_GITHUB_TOKEN||t.GITHUB_TOKEN,d=n.appId||t.GITHUB_APP_ID,f=n.privateKey||t.GITHUB_PRIVATE_KEY,p=n.installationId||t.GITHUB_INSTALLATION_ID;if(!a||!s)throw Error(`GitHub repository coordinates (owner and repo name) are missing. Please set GITHUB_REPO_OWNER and GITHUB_REPO_NAME.`);return await o(i,{owner:a,repo:s,categorySlug:l,token:u,appId:d,privateKey:f,installationId:p}),{success:!0}}Object.defineProperty(exports,`n`,{enumerable:!0,get:function(){return s}}),Object.defineProperty(exports,`t`,{enumerable:!0,get:function(){return l}});
28
+ `)}),{success:!0}}var s=e.t({handleFeedback:()=>l});const c=n.object({rating:n.enum([`good`,`neutral`,`bad`]),path:n.string(),title:n.string(),comment:n.string().optional()});async function l(e,t=process.env,n={}){let r=c.safeParse(e);if(!r.success)throw Error(`Invalid feedback payload`);let i=r.data,a=n.owner||t.GITHUB_REPO_OWNER||t.BOLTDOCS_GITHUB_REPO_OWNER,s=n.repo||t.GITHUB_REPO_NAME||t.BOLTDOCS_GITHUB_REPO_NAME,l=n.categorySlug||t.GITHUB_DISCUSSION_CATEGORY||t.BOLTDOCS_GITHUB_DISCUSSION_CATEGORY||`general`,u=n.token||t.BOLTDOCS_GITHUB_TOKEN||t.GITHUB_TOKEN,d=n.appId||t.GITHUB_APP_ID,f=n.privateKey||t.GITHUB_PRIVATE_KEY,p=n.installationId||t.GITHUB_INSTALLATION_ID;if(!a||!s)throw Error(`GitHub repository coordinates (owner and repo name) are missing. Please set GITHUB_REPO_OWNER and GITHUB_REPO_NAME.`);return await o(i,{owner:a,repo:s,categorySlug:l,token:u,appId:d,privateKey:f,installationId:p}),{success:!0}}Object.defineProperty(exports,`n`,{enumerable:!0,get:function(){return s}}),Object.defineProperty(exports,`t`,{enumerable:!0,get:function(){return l}});
@@ -3,7 +3,7 @@
3
3
  * Copyright (c) 2026 Jesus Alcala
4
4
  * Licensed under the MIT License.
5
5
  */
6
- import{t as e}from"./chunk-BFSpntXv.mjs";import*as t from"zod";import n from"node:crypto";function r(e,t){let r={alg:`RS256`,typ:`JWT`},i=Math.floor(Date.now()/1e3),a={iat:i-60,exp:i+600,iss:e},o=e=>Buffer.from(JSON.stringify(e)).toString(`base64url`),s=o(r),c=o(a),l=n.createSign(`RSA-SHA256`);l.update(`${s}.${c}`);let u=t.replace(/\\n/g,`
6
+ import{t as e}from"./chunk-BFSpntXv.mjs";import t from"node:crypto";import*as n from"zod";function r(e,n){let r={alg:`RS256`,typ:`JWT`},i=Math.floor(Date.now()/1e3),a={iat:i-60,exp:i+600,iss:e},o=e=>Buffer.from(JSON.stringify(e)).toString(`base64url`),s=o(r),c=o(a),l=t.createSign(`RSA-SHA256`);l.update(`${s}.${c}`);let u=n.replace(/\\n/g,`
7
7
  `);return`${s}.${c}.${l.sign(u,`base64`)}`}async function i(e,t,n){let i=r(e,t),a=await fetch(`https://api.github.com/app/installations/${n}/access_tokens`,{method:`POST`,headers:{Authorization:`Bearer ${i}`,Accept:`application/vnd.github+json`,"User-Agent":`Boltdocs-Feedback`}});if(!a.ok){let e=await a.text();throw Error(`Failed to get installation access token: ${a.status} ${e}`)}return(await a.json()).token}async function a(e,t,n={}){let r=await fetch(`https://api.github.com/graphql`,{method:`POST`,headers:{Authorization:`bearer ${e}`,"Content-Type":`application/json`,"User-Agent":`Boltdocs-Feedback`},body:JSON.stringify({query:t,variables:n})});if(!r.ok){let e=await r.text();throw Error(`GitHub GraphQL API error: ${r.status} ${e}`)}let i=await r.json();if(i.errors?.length){let e=i.errors.map(e=>e.message).join(`, `);throw Error(`GitHub GraphQL Error: ${e}`)}return i.data}async function o(e,t){let n=t.token;if(!n)if(t.appId&&t.privateKey&&t.installationId)n=await i(t.appId,t.privateKey,t.installationId);else throw Error(`GitHub authentication credentials missing. Provide GITHUB_TOKEN or GITHUB_APP_* variables.`);let{owner:r,repo:o,categorySlug:s=`general`}=t,{rating:c,comment:l,path:u,title:d,blockId:f}=e,p=await a(n,`query GetRepoAndCategory($owner: String!, $name: String!, $categorySlug: String!) {
8
8
  repository(owner: $owner, name: $name) {
9
9
  id
@@ -25,4 +25,4 @@ _No comments provided._`];return await a(n,`mutation AddComment($discussionId: I
25
25
  comment { id }
26
26
  }
27
27
  }`,{discussionId:_,body:v.filter(Boolean).join(`
28
- `)}),{success:!0}}var s=e({handleFeedback:()=>l});const c=t.object({rating:t.enum([`good`,`neutral`,`bad`]),path:t.string(),title:t.string(),comment:t.string().optional()});async function l(e,t=process.env,n={}){let r=c.safeParse(e);if(!r.success)throw Error(`Invalid feedback payload`);let i=r.data,a=n.owner||t.GITHUB_REPO_OWNER||t.BOLTDOCS_GITHUB_REPO_OWNER,s=n.repo||t.GITHUB_REPO_NAME||t.BOLTDOCS_GITHUB_REPO_NAME,l=n.categorySlug||t.GITHUB_DISCUSSION_CATEGORY||t.BOLTDOCS_GITHUB_DISCUSSION_CATEGORY||`general`,u=n.token||t.BOLTDOCS_GITHUB_TOKEN||t.GITHUB_TOKEN,d=n.appId||t.GITHUB_APP_ID,f=n.privateKey||t.GITHUB_PRIVATE_KEY,p=n.installationId||t.GITHUB_INSTALLATION_ID;if(!a||!s)throw Error(`GitHub repository coordinates (owner and repo name) are missing. Please set GITHUB_REPO_OWNER and GITHUB_REPO_NAME.`);return await o(i,{owner:a,repo:s,categorySlug:l,token:u,appId:d,privateKey:f,installationId:p}),{success:!0}}export{s as n,l as t};
28
+ `)}),{success:!0}}var s=e({handleFeedback:()=>l});const c=n.object({rating:n.enum([`good`,`neutral`,`bad`]),path:n.string(),title:n.string(),comment:n.string().optional()});async function l(e,t=process.env,n={}){let r=c.safeParse(e);if(!r.success)throw Error(`Invalid feedback payload`);let i=r.data,a=n.owner||t.GITHUB_REPO_OWNER||t.BOLTDOCS_GITHUB_REPO_OWNER,s=n.repo||t.GITHUB_REPO_NAME||t.BOLTDOCS_GITHUB_REPO_NAME,l=n.categorySlug||t.GITHUB_DISCUSSION_CATEGORY||t.BOLTDOCS_GITHUB_DISCUSSION_CATEGORY||`general`,u=n.token||t.BOLTDOCS_GITHUB_TOKEN||t.GITHUB_TOKEN,d=n.appId||t.GITHUB_APP_ID,f=n.privateKey||t.GITHUB_PRIVATE_KEY,p=n.installationId||t.GITHUB_INSTALLATION_ID;if(!a||!s)throw Error(`GitHub repository coordinates (owner and repo name) are missing. Please set GITHUB_REPO_OWNER and GITHUB_REPO_NAME.`);return await o(i,{owner:a,repo:s,categorySlug:l,token:u,appId:d,privateKey:f,installationId:p}),{success:!0}}export{s as n,l as t};
@@ -3,11 +3,12 @@
3
3
  * Copyright (c) 2026 Jesus Alcala
4
4
  * Licensed under the MIT License.
5
5
  */
6
- import { O as Link, r as cn, t as Link$1 } from "./link-2PzgTnaP.js";
6
+ import { M as Link, W as useConfig, d as resolvePublicAssetUrl, o as cn, t as Link$1 } from "./link-CgdI6O2o.js";
7
7
  import * as React$1 from "react";
8
8
  import { createContext, use, useEffect, useState } from "react";
9
- import { Fragment, jsx, jsxs } from "react/jsx-runtime";
9
+ import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
10
10
  import * as RAC from "react-aria-components";
11
+ import { Button } from "react-aria-components";
11
12
 
12
13
  //#region src/client/app/theme-context.tsx
13
14
  const THEME_CONTEXT_SYMBOL = Symbol.for("__BDOCS_THEME_CONTEXT__");
@@ -90,11 +91,11 @@ function useTheme() {
90
91
 
91
92
  //#endregion
92
93
  //#region src/client/components/primitives/heading.tsx
93
- const Heading = React$1.forwardRef(({ level, id, children, className, showAnchor = true, anchorPosition = "wrap", anchorIcon, anchorClassName, ...props }, ref) => {
94
+ const Heading = React$1.forwardRef(({ level, id, children, className, showAnchor = true, anchorPosition = "wrap", anchorIcon, anchorClassName, anchorIconClassName, ...props }, ref) => {
94
95
  const Tag = `h${Math.min(Math.max(Math.floor(level), 1), 6)}`;
95
96
  const hasAnchor = !!(id && showAnchor);
96
97
  const defaultIcon = /* @__PURE__ */ jsx(Link, {
97
- className: cn("transition-all duration-200", anchorPosition === "wrap" ? "opacity-0 ml-2 text-muted/50 group-hover:text-primary-500 group-hover:opacity-100" : "text-muted/50 hover:text-primary-500"),
98
+ className: cn("transition-all duration-200", anchorPosition === "wrap" ? "opacity-0 ml-2 text-muted/50 group-hover:text-primary-500 group-hover:opacity-100" : "text-muted/50 hover:text-primary-500", anchorIconClassName),
98
99
  size: 16
99
100
  });
100
101
  const icon = anchorIcon ?? defaultIcon;
@@ -106,7 +107,7 @@ const Heading = React$1.forwardRef(({ level, id, children, className, showAnchor
106
107
  "aria-label": "Anchor",
107
108
  children: [children, icon]
108
109
  });
109
- return /* @__PURE__ */ jsxs(Fragment, { children: [
110
+ return /* @__PURE__ */ jsxs(Fragment$1, { children: [
110
111
  anchorPosition === "before" && /* @__PURE__ */ jsx(Link$1, {
111
112
  href: `#${id}`,
112
113
  className: cn("header-anchor mr-2 opacity-0 group-hover:opacity-100 transition-opacity duration-200", anchorClassName),
@@ -132,6 +133,66 @@ const Heading = React$1.forwardRef(({ level, id, children, className, showAnchor
132
133
  });
133
134
  Heading.displayName = "Heading";
134
135
 
136
+ //#endregion
137
+ //#region src/client/components/primitives/callout.tsx
138
+ /**
139
+ * Style-neutral callout primitives.
140
+ *
141
+ * Own structure and expose state via `data-callout-root` / `data-variant`.
142
+ * No colors, borders, or sizes are baked in — the theme owns all visuals.
143
+ */
144
+ function Callout({ children, variant = "note", title, icon, className, iconClassName, titleClassName, bodyClassName, ...props }) {
145
+ return /* @__PURE__ */ jsxs(CalloutRoot, {
146
+ variant,
147
+ className,
148
+ ...props,
149
+ children: [icon != null && /* @__PURE__ */ jsx(CalloutIcon, {
150
+ className: iconClassName,
151
+ children: icon
152
+ }), /* @__PURE__ */ jsxs("div", {
153
+ className: cn("flex-1", bodyClassName),
154
+ children: [title != null && /* @__PURE__ */ jsx(CalloutTitle, {
155
+ className: titleClassName,
156
+ children: title
157
+ }), children]
158
+ })]
159
+ });
160
+ }
161
+ function CalloutRoot({ variant, children, className, ...props }) {
162
+ return /* @__PURE__ */ jsx("div", {
163
+ "data-callout-root": true,
164
+ "data-variant": variant,
165
+ className: cn("flex gap-4", className),
166
+ ...props,
167
+ children
168
+ });
169
+ }
170
+ function CalloutIcon({ children, className, ...props }) {
171
+ return /* @__PURE__ */ jsx("div", {
172
+ className: cn("shrink-0", className),
173
+ ...props,
174
+ children
175
+ });
176
+ }
177
+ function CalloutTitle({ children, className, as: Tag = "div", ...props }) {
178
+ return /* @__PURE__ */ jsx(Tag, {
179
+ className,
180
+ ...props,
181
+ children
182
+ });
183
+ }
184
+ function CalloutBody({ children, className, ...props }) {
185
+ return /* @__PURE__ */ jsx("div", {
186
+ className,
187
+ ...props,
188
+ children
189
+ });
190
+ }
191
+ Callout.Root = CalloutRoot;
192
+ Callout.Icon = CalloutIcon;
193
+ Callout.Title = CalloutTitle;
194
+ Callout.Body = CalloutBody;
195
+
135
196
  //#endregion
136
197
  //#region src/client/components/primitives/code-block.tsx
137
198
  /**
@@ -167,6 +228,16 @@ function CodeBlockGroup({ children, className, ...props }) {
167
228
  });
168
229
  }
169
230
  /**
231
+ * Trailing action area in the header (copy, feedback, custom actions).
232
+ */
233
+ function CodeBlockActions({ children, className, ...props }) {
234
+ return /* @__PURE__ */ jsx("div", {
235
+ className: cn("flex items-center gap-1 bg-(--color-code-bg) pl-2 z-10", className),
236
+ ...props,
237
+ children
238
+ });
239
+ }
240
+ /**
170
241
  * Content area of the code block.
171
242
  * Wraps the `<pre>` or `<div>` containing the code.
172
243
  */
@@ -177,9 +248,53 @@ function CodeBlockContent({ className, children, shouldTruncate = false, ...prop
177
248
  children
178
249
  });
179
250
  }
251
+ /**
252
+ * The code area itself. Renders pre-rendered Shiki HTML when `highlightedHtml`
253
+ * is provided, otherwise a plain `<pre>` with the default code styling.
254
+ */
255
+ function CodeBlockPre({ className, highlightedHtml, isHighlighted = false, ref, children, ...props }) {
256
+ if (highlightedHtml) return /* @__PURE__ */ jsx("div", {
257
+ ref,
258
+ className: cn("shiki-wrapper overflow-x-auto", className),
259
+ dangerouslySetInnerHTML: { __html: highlightedHtml },
260
+ ...props
261
+ });
262
+ return /* @__PURE__ */ jsx("pre", {
263
+ ref,
264
+ className: cn("m-0 rounded-none border-none bg-transparent", "text-[0.875rem] leading-[1.6] overflow-x-auto", {
265
+ "p-0 [&>code]:grid [&>code]:p-5 [&>code]:bg-transparent [&>code]:whitespace-pre": isHighlighted,
266
+ "p-5": !isHighlighted
267
+ }, className),
268
+ ...props,
269
+ children
270
+ });
271
+ }
272
+ /**
273
+ * Expand / collapse region for long code blocks. Renders nothing when the
274
+ * block is not expandable.
275
+ */
276
+ function CodeBlockExpand({ className, buttonClassName, isExpandable, shouldTruncate, isExpanded, onToggle, expandLabel = "Expand code", collapseLabel = "Show less", expandIcon, ...props }) {
277
+ if (!isExpandable) return null;
278
+ return /* @__PURE__ */ jsx("div", {
279
+ className: cn({
280
+ "absolute bottom-0 inset-x-0 h-32 flex items-end justify-center pb-4 z-10": shouldTruncate,
281
+ "relative flex justify-center pb-4 pt-1 -mt-4": !shouldTruncate
282
+ }, className),
283
+ style: shouldTruncate ? { backgroundImage: "linear-gradient(to top, var(--color-code-bg) 10%, transparent)" } : void 0,
284
+ ...props,
285
+ children: /* @__PURE__ */ jsxs(Button, {
286
+ onPress: onToggle,
287
+ className: cn("inline-flex items-center gap-2 rounded-full bg-surface border border-subtle px-5 py-2 text-[0.8125rem] font-medium text-body outline-none cursor-pointer transition-all hover:bg-soft hover:-translate-y-px backdrop-blur-md", buttonClassName),
288
+ children: [expandIcon, isExpanded ? collapseLabel : expandLabel]
289
+ })
290
+ });
291
+ }
180
292
  CodeBlock.Header = CodeBlockHeader;
181
293
  CodeBlock.Group = CodeBlockGroup;
294
+ CodeBlock.Actions = CodeBlockActions;
182
295
  CodeBlock.Content = CodeBlockContent;
296
+ CodeBlock.Pre = CodeBlockPre;
297
+ CodeBlock.Expand = CodeBlockExpand;
183
298
 
184
299
  //#endregion
185
300
  //#region src/client/components/primitives/tooltip.tsx
@@ -187,16 +302,16 @@ CodeBlock.Content = CodeBlockContent;
187
302
  * Modern, accessible Tooltip component built with React Aria Components.
188
303
  * Featuring glassmorphism, animations, and smart positioning.
189
304
  */
190
- function TooltipContent({ className, children, ...props }) {
305
+ function TooltipContent({ className, arrowClassName, children, ...props }) {
191
306
  return /* @__PURE__ */ jsx(RAC.Tooltip, {
192
307
  ...props,
193
308
  offset: 8,
194
309
  className: (values) => cn("group z-50 overflow-visible rounded-md bg-surface px-2.5 py-1.5 text-xs font-medium text-body ring-1 ring-subtle outline-hidden select-none", "data-entering:animate-in data-entering:fade-in data-entering:zoom-in-95 data-entering:duration-100", "data-exiting:animate-out data-exiting:fade-out data-exiting:zoom-out-95 data-exiting:duration-75", "data-[placement=top]:slide-in-from-bottom-1", "data-[placement=bottom]:slide-in-from-top-1", "data-[placement=left]:slide-in-from-right-1", "data-[placement=right]:slide-in-from-left-1", typeof className === "function" ? className(values) : className),
195
- children: (values) => /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(RAC.OverlayArrow, { children: /* @__PURE__ */ jsxs("svg", {
310
+ children: (values) => /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(RAC.OverlayArrow, { children: /* @__PURE__ */ jsxs("svg", {
196
311
  width: 8,
197
312
  height: 8,
198
313
  viewBox: "0 0 8 8",
199
- className: "fill-bg-surface/90 stroke-border-subtle group-data-[placement=bottom]:rotate-180 group-data-[placement=left]:-rotate-90 group-data-[placement=right]:rotate-90",
314
+ className: cn("fill-bg-surface/90 stroke-border-subtle group-data-[placement=bottom]:rotate-180 group-data-[placement=left]:-rotate-90 group-data-[placement=right]:rotate-90", arrowClassName),
200
315
  children: [/* @__PURE__ */ jsx("title", { children: "Arrow" }), /* @__PURE__ */ jsx("path", { d: "M0 0 L4 4 L8 0" })]
201
316
  }) }), typeof children === "function" ? children(values) : children] })
202
317
  });
@@ -220,14 +335,17 @@ Tooltip.Content = TooltipContent;
220
335
  * A responsive image component that automatically supports dark and light theme variations
221
336
  * via the `theme` prop.
222
337
  */
223
- function Image({ theme, className, ...props }) {
338
+ function Image({ theme, className, src, alt, ...props }) {
224
339
  const { resolvedTheme } = useTheme();
340
+ const config = useConfig();
225
341
  if (theme && theme !== resolvedTheme) return null;
226
342
  return /* @__PURE__ */ jsx("img", {
227
343
  className: cn("max-w-full h-auto rounded-lg my-8", className),
228
- ...props
344
+ alt: alt ?? "",
345
+ ...props,
346
+ src: typeof src === "string" ? resolvePublicAssetUrl(src, config.base) : src
229
347
  });
230
348
  }
231
349
 
232
350
  //#endregion
233
- export { CodeBlockGroup as a, ThemeProvider as c, CodeBlockContent as i, useTheme as l, Tooltip as n, CodeBlockHeader as o, CodeBlock as r, Heading as s, Image as t };
351
+ export { useTheme as _, CodeBlockContent as a, CodeBlockHeader as c, CalloutBody as d, CalloutIcon as f, ThemeProvider as g, Heading as h, CodeBlockActions as i, CodeBlockPre as l, CalloutTitle as m, Tooltip as n, CodeBlockExpand as o, CalloutRoot as p, CodeBlock as r, CodeBlockGroup as s, Image as t, Callout as u };