boltdocs 2.7.11 → 2.8.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 (84) hide show
  1. package/README.md +2 -2
  2. package/dist/banner-3N4Jd_L9.d.ts +100 -0
  3. package/dist/banner-MynZD_Ox.d.cts +100 -0
  4. package/dist/cache-BMUyNiiA.mjs +6 -0
  5. package/dist/cache-CKm45d2w.cjs +6 -0
  6. package/dist/client/index.cjs +782 -443
  7. package/dist/client/index.d.cts +86 -110
  8. package/dist/client/index.d.ts +87 -111
  9. package/dist/client/index.js +773 -439
  10. package/dist/client/mdx.cjs +8 -3
  11. package/dist/client/mdx.d.cts +39 -93
  12. package/dist/client/mdx.d.ts +38 -93
  13. package/dist/client/mdx.js +3 -3
  14. package/dist/client/primitives.cjs +7 -7
  15. package/dist/client/primitives.d.cts +411 -347
  16. package/dist/client/primitives.d.ts +411 -347
  17. package/dist/client/primitives.js +4 -4
  18. package/dist/{docs-layout-BXHV0xw_.cjs → docs-layout-CwCq42Zt.cjs} +95 -178
  19. package/dist/{docs-layout-DwFndmj5.js → docs-layout-Dn6S5g59.js} +99 -163
  20. package/dist/doctor-BArviV8X.cjs +28 -0
  21. package/dist/doctor-CgLA7_Uv.mjs +28 -0
  22. package/dist/{doctor-CrytFkqW.cjs → doctor-DyNUVe96.cjs} +1 -1
  23. package/dist/{routes-DP1vmWRj.cjs → doctor-aN_leTbh.mjs} +1 -1
  24. package/dist/{generator-ClVanhvi.mjs → generator-BHCrLU6h.mjs} +2 -2
  25. package/dist/{generator-CHqxiQhF.cjs → generator-CC2yHzhZ.cjs} +2 -2
  26. package/dist/{icons-dev-3cZMyt8r.cjs → icons-dev-DvJ-hh9x.cjs} +116 -111
  27. package/dist/{icons-dev-Df8OQ481.js → icons-dev-Oju24Wjp.js} +120 -114
  28. package/dist/{image-DtrI2cw3.cjs → image-Ch4-GxdO.cjs} +13 -13
  29. package/dist/{image-jxPb-2iV.js → image-Do8V9PCW.js} +13 -13
  30. package/dist/{mdx-UTTLFWJq.js → mdx-D3A2_l7P.js} +106 -80
  31. package/dist/{mdx-BdWkJTeB.cjs → mdx-PLhhPJRS.cjs} +104 -96
  32. package/dist/node/cli-entry.cjs +3 -1
  33. package/dist/node/cli-entry.mjs +3 -1
  34. package/dist/node/index.cjs +1 -1
  35. package/dist/node/index.d.cts +258 -152
  36. package/dist/node/index.d.mts +258 -150
  37. package/dist/node/index.mjs +1 -1
  38. package/dist/node/routes/worker.cjs +1 -1
  39. package/dist/node/routes/worker.mjs +1 -1
  40. package/dist/node-BmlP0eBP.cjs +159 -0
  41. package/dist/node-Y8_4ayje.mjs +159 -0
  42. package/dist/package-2nFy_NsW.cjs +6 -0
  43. package/dist/{package-K0zsjGIz.mjs → package-DAbtltXX.mjs} +1 -1
  44. package/dist/parser-B7-6PyQz.cjs +6 -0
  45. package/dist/{parser-Aq8LoH-0.cjs → parser-BzB-zCkF.cjs} +1 -1
  46. package/dist/parser-WGZdWs0X.mjs +6 -0
  47. package/dist/routes-BDDSxAl0.mjs +6 -0
  48. package/dist/routes-DJNJ-rTt.cjs +6 -0
  49. package/dist/routes-DiYC4nD2.cjs +6 -0
  50. package/dist/routes-_Bb2f4eI.mjs +6 -0
  51. package/dist/{search-dialog-C7xuvyNk.cjs → search-dialog-BXVoecTx.cjs} +175 -78
  52. package/dist/{search-dialog-BwkDuI9R.cjs → search-dialog-BYhOov4S.cjs} +118 -7
  53. package/dist/{search-dialog-D-DDN7zJ.js → search-dialog-C09riYmx.js} +113 -8
  54. package/dist/{search-dialog-CIQg6k8c.cjs → search-dialog-CUeAfy-8.cjs} +1 -1
  55. package/dist/{search-dialog-BNF10tDl.js → search-dialog-D8gLkhUV.js} +158 -80
  56. package/dist/{search-dialog-BHuIiUC6.js → search-dialog-DHc_8FFX.js} +1 -1
  57. package/dist/{sidebar-CyZS9YOm.d.ts → sidebar-DNq4_ZAa.d.ts} +117 -51
  58. package/dist/{sidebar-CcBkrm06.d.cts → sidebar-Dlkgbxs6.d.cts} +117 -51
  59. package/dist/utils-BYITg7T5.mjs +7 -0
  60. package/dist/utils-Cjmx1hhk.cjs +7 -0
  61. package/dist/worker-pool-CtqklOXq.cjs +6 -0
  62. package/dist/worker-pool-k0DY6k8T.mjs +6 -0
  63. package/package.json +3 -3
  64. package/src/shared/config-utils.ts +4 -0
  65. package/src/shared/types.ts +52 -6
  66. package/dist/cache-Ba-DZQNH.cjs +0 -6
  67. package/dist/cache-BuMZ58L5.mjs +0 -6
  68. package/dist/cards-BakZPTz9.d.ts +0 -30
  69. package/dist/cards-CQn9mXZS.d.cts +0 -30
  70. package/dist/doctor-Be7Ly1oM.mjs +0 -21
  71. package/dist/doctor-jMxWZyLJ.cjs +0 -21
  72. package/dist/node-BSM4qcDK.cjs +0 -111
  73. package/dist/node-BspZN3R2.mjs +0 -111
  74. package/dist/package-DIIrjuWI.cjs +0 -6
  75. package/dist/parser-CdNbqN5y.cjs +0 -6
  76. package/dist/parser-nE792MLO.mjs +0 -6
  77. package/dist/rolldown-runtime-fkIsjY3S.mjs +0 -6
  78. package/dist/routes-2k3tbUmC.cjs +0 -6
  79. package/dist/routes-CpxZIsMM.mjs +0 -6
  80. package/dist/utils-CG65J0Sc.mjs +0 -7
  81. package/dist/utils-CKunkU96.cjs +0 -7
  82. package/dist/worker-pool-CGn7DrLb.mjs +0 -6
  83. package/dist/worker-pool-Crbqgw5R.cjs +0 -6
  84. /package/dist/{meta-loader-CWg2gnbY.mjs → meta-loader-DzwDFtdT.mjs} +0 -0
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Boltdocs - https://boltdocs.vercel.app
3
+ * Copyright (c) 2026 Jesus Alcala
4
+ * Licensed under the MIT License.
5
+ */
6
+ import{a as e,d as t,u as n,v as r,y as i}from"./utils-BYITg7T5.mjs";import{createRequire as a}from"node:module";import{loadConfigFromFile as o}from"vite";import s from"node:path";import{fdir as c}from"fdir";import l from"node:fs";import{z as u}from"zod";import*as d from"@bdocs/dui";import{bullet as f,colors as p,confirm as m,dividerLog as h,double as g,error as _,info as v,round as ee,single as te,success as y,tasks as ne,warn as b}from"@bdocs/dui";import re from"picomatch";import{distance as x}from"fastest-levenshtein";const S=u.object({icon:u.string().max(50),link:u.string().url()});u.object({text:u.string().max(2e3).optional()});const C=u.object({name:u.string(),enforce:u.enum([`pre`,`post`]).optional(),version:u.string().optional(),boltdocsVersion:u.string().optional(),remarkPlugins:u.array(u.unknown()).optional(),rehypePlugins:u.array(u.unknown()).optional(),vitePlugins:u.array(u.unknown()).optional(),components:u.record(u.string(),u.string()).optional(),hooks:u.record(u.string(),u.unknown()).optional()}),w=u.object({title:u.union([u.string(),u.record(u.string(),u.string())]).optional(),description:u.union([u.string(),u.record(u.string(),u.string())]).optional(),logo:u.union([u.string(),u.object({dark:u.string(),light:u.string(),alt:u.string().optional(),width:u.number().optional(),height:u.number().optional()})]).optional(),navbar:u.array(u.object({label:u.union([u.string(),u.record(u.string(),u.string())]),href:u.string(),items:u.array(u.object({label:u.union([u.string(),u.record(u.string(),u.string())]),href:u.string()})).optional()})).optional(),sidebar:u.record(u.string(),u.array(u.object({text:u.string(),link:u.string()}))).optional(),sidebarGroups:u.record(u.string(),u.object({title:u.union([u.string(),u.record(u.string(),u.string())]).optional(),icon:u.string().optional()})).optional(),socialLinks:u.array(S).optional(),editLink:u.string().refine(e=>!e||e.includes(`:path`),{message:`editLink must contain ':path' placeholder if specified`}).optional(),communityHelp:u.string().url().optional(),version:u.string().max(50).optional(),githubRepo:u.string().max(100).optional(),favicon:u.string().optional(),tabs:u.array(u.object({id:u.string(),text:u.union([u.string(),u.record(u.string(),u.string())]),icon:u.string().optional()})).optional(),codeTheme:u.union([u.string(),u.object({light:u.string(),dark:u.string()})]).optional()}),T=u.union([u.string(),u.object({rules:u.array(u.object({userAgent:u.string(),allow:u.union([u.string(),u.array(u.string())]).optional(),disallow:u.union([u.string(),u.array(u.string())]).optional()})).optional(),sitemaps:u.array(u.string().url()).optional()})]),E=u.object({defaultLocale:u.string(),locales:u.union([u.record(u.string(),u.string()),u.array(u.string())]).transform(e=>Array.isArray(e)?Object.fromEntries(e.map(e=>[e,e])):e),localeConfigs:u.record(u.string(),u.object({label:u.string().optional(),direction:u.enum([`ltr`,`rtl`]).optional(),htmlLang:u.string().optional(),calendar:u.string().optional()})).optional()}),D=u.object({defaultVersion:u.string(),prefix:u.string().optional(),versions:u.array(u.object({label:u.string(),path:u.string()}))}),O=u.object({headers:u.record(u.string(),u.string()).optional(),enableCSP:u.boolean().optional(),customHeaders:u.record(u.string(),u.string()).optional()}),k=u.object({metatags:u.record(u.string(),u.string()).optional(),indexing:u.enum([`all`,`public`]).optional(),thumbnails:u.object({background:u.string().optional()}).optional()}),A=u.object({measurementId:u.string().min(1,`Measurement ID is required for GA4`),debug:u.boolean().optional(),anonymizeIp:u.boolean().optional(),sendPageView:u.boolean().optional(),cookieFlags:u.string().optional(),autoTrack:u.object({pageViews:u.boolean().optional(),downloads:u.boolean().optional(),externalLinks:u.boolean().optional(),search:u.boolean().optional()}).optional()}),j=u.object({tagId:u.string().min(1,`Tag ID is required for GTM`),dataLayerName:u.string().optional(),preview:u.string().optional()}),M=u.object({appId:u.string().min(1,`Algolia App ID is required`),apiKey:u.string().min(1,`Algolia API Key is required`),indexName:u.string().min(1,`Algolia Index Name is required`)}),N=u.object({ga4:A.optional(),gtm:j.optional(),algolia:M.optional()}),P=u.object({siteUrl:u.string().url().optional(),docsDir:u.string().optional(),base:u.string().optional(),theme:w.optional(),i18n:E.optional(),versions:D.optional(),plugins:u.array(C).optional(),robots:T.optional(),security:O.optional(),seo:k.optional(),integrations:N.optional(),vite:u.record(u.string(),u.unknown()).optional()});function F(e,t,n=process.cwd(),r){let i=s.resolve(n,`.boltdocs`,`generated`);l.existsSync(i)||l.mkdirSync(i,{recursive:!0});let a=e.i18n?Object.keys(e.i18n.locales):[],o=e.versions?e.versions.versions.map(e=>e.path):[],c=a.length>0?a.map(e=>`'${e}'`).join(` | `):`string`,u=o.length>0?o.map(e=>`'${e}'`).join(` | `):`string`,d=[`tsx`,`ts`,`jsx`,`js`],f=``,p=``;for(let e of d){let r=s.resolve(n,t,`mdx-components.${e}`);if(l.existsSync(r)){let e=s.join(n,t,`mdx-components`),r=s.relative(i,e).replace(/\\/g,`/`);f=`import type * as MdxComponentsModule from '${r.startsWith(`.`)?r:`./${r}`}'\n`,p=` MdxComponents: typeof MdxComponentsModule`;break}}let m=r&&r.length>0?`\ndeclare global {
7
+ namespace Boltdocs {
8
+ interface RoutePaths {
9
+ ${r.map(e=>` '${e}': void`).join(`
10
+ `)}
11
+ }
12
+ }
13
+ }`:``,h=`// This file is automatically generated by Boltdocs.
14
+ // Do not edit this file manually.
15
+
16
+ ${f}declare global {
17
+ namespace Boltdocs {
18
+ interface Types {
19
+ Locale: ${c}
20
+ Version: ${u}${p?`\n${p}`:``}
21
+ }
22
+ }
23
+ }${m}
24
+
25
+ export {}
26
+ `;l.writeFileSync(s.resolve(i,`types.d.ts`),h)}function I(e,t=process.cwd()){let n=s.resolve(t,`.boltdocs`,`generated`);l.existsSync(n)||l.mkdirSync(n,{recursive:!0});let r={routes:Array.from(new Set(e)).sort(),timestamp:Date.now()};l.writeFileSync(s.resolve(n,`link-tree.json`),JSON.stringify(r,null,2))}function L(e){return e}const R=[`boltdocs.config.js`,`boltdocs.config.mjs`,`boltdocs.config.ts`];async function z(e,t=process.cwd()){let n=t,i={docsDir:s.resolve(e),theme:{title:`Boltdocs`,description:`A Vite documentation framework`,navbar:[{label:`Home`,href:`/`},{label:`Documentation`,href:`/docs`}],codeTheme:{light:`github-light`,dark:`github-dark`}}},a={};for(let e of R){let t=s.resolve(n,e);if(l.existsSync(t))try{let e=await o({command:`serve`,mode:`development`},t,n);if(e){a=e.config;break}}catch(t){b(`Failed to load config from ${e}:`,t)}}let c={title:a.title,description:a.description,logo:a.logo,favicon:a.favicon,navbar:a.navbar,sidebar:a.sidebar,sidebarGroups:a.theme?.sidebarGroups,socialLinks:a.socialLinks,githubRepo:a.githubRepo,tabs:a.tabs,codeTheme:a.codeTheme,communityHelp:a.communityHelp,version:a.version,editLink:a.editLink,...a.theme||{}},u=Object.fromEntries(Object.entries(c).filter(([e,t])=>t!==void 0));u.navbar&&=u.navbar.map(e=>({label:e.label||e.text||``,href:e.href||e.link||e.to||``,items:e.items}));let d={docsDir:s.resolve(e),theme:{...i.theme,...u},i18n:a.i18n?{...a.i18n,locales:Array.isArray(a.i18n.locales)?Object.fromEntries(a.i18n.locales.map(e=>[e,e])):a.i18n.locales}:void 0,versions:a.versions,siteUrl:a.siteUrl,base:a.base,seo:a.seo,plugins:a.plugins||[],robots:a.robots,security:a.security,integrations:a.integrations,vite:a.vite},f=P.safeParse(d);if(!f.success)throw new r(`Invalid Boltdocs configuration:\n${f.error.issues.map(e=>` - ${e.path.join(`.`)}: ${e.message}`).join(`
27
+ `)}`);return f.data}const ie=a(import.meta.url);let B=0;function ae(e,t){let n=e.split(`-`)[0].split(`.`).map(Number),r=t.split(`-`)[0].split(`.`).map(Number);for(let e=0;e<Math.max(n.length,r.length);e++){let t=n[e]??0,i=r[e]??0;if(Number.isNaN(t)||Number.isNaN(i))return!1;if(t!==i)return t>i}return!1}async function oe(){try{let e=new AbortController,t=setTimeout(()=>e.abort(),2e3),n=await fetch(`https://registry.npmjs.org/boltdocs/latest`,{signal:e.signal,headers:{Accept:`application/vnd.npm.install-v1+json`}});return clearTimeout(t),n.ok?(await n.json()).version??null:null}catch{return null}}async function se(){try{return ie(`boltdocs/package.json`).version}catch{return`0.0.0`}}async function V(){let e=Date.now();if(e-B<864e5)return;B=e;let t=await se();if(t===`0.0.0`)return;let n=await oe();n&&ae(n,t)&&console.log(d.updateAvailable(t,n))}const H={$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 U(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 W(e,t,n){return e.doctorConfig.severity[t]||n}async function ce(e,t){l.existsSync(t)||l.mkdirSync(t,{recursive:!0});let n=s.basename(e),r=new Date().toISOString().replace(/[:.]/g,`-`),i=s.join(t,`${n}.${r}.bak`);l.copyFileSync(e,i)}const G=new Map;function K(e){let n=G.get(e);if(n)return n;let r=(async()=>{let n=await t(e,!1);return{raw:n.raw,data:n.data,content:n.content}})();return G.set(e,r),r}const q=new Map;function J(e){if(q.has(e))return q.get(e);let t=!1;try{t=l.existsSync(e)&&l.statSync(e).isFile()}catch{t=!1}return q.set(e,t),t}async function Y(e){let t=s.resolve(e,`doctor.json`);if(l.existsSync(t))try{let e=JSON.parse(l.readFileSync(t,`utf-8`));return{...H,...e,checks:{...H.checks,...e.checks,metadata:{...H.checks.metadata,...e.checks?.metadata},links:{...H.checks.links,...e.checks?.links},i18n:{...H.checks.i18n,...e.checks?.i18n},performance:{...H.checks.performance,...e.checks?.performance,budgets:{...H.checks.performance?.budgets,...e.checks?.performance?.budgets}}},fix:{...H.fix,...e.fix},reporting:{...H.reporting,...e.reporting},severity:{...H.severity,...e.severity},exclude:[...H.exclude,...e.exclude||[]]}}catch(e){b(`Failed to parse doctor.json: ${e}`)}return H}async function X(t,n=process.cwd(),r,i){let a=s.resolve(n,`.boltdocs`,`generated`);l.existsSync(a)||l.mkdirSync(a,{recursive:!0});let o=i;o||=await new c().withFullPaths().filter(e=>e.endsWith(`.md`)||e.endsWith(`.mdx`)).crawl(t).withPromise();let u=r?.base||`/docs`,d=[];for(let n=0;n<o.length;n+=100){let r=o.slice(n,n+100),i=await Promise.all(r.map(async n=>{let r=s.isAbsolute(n)?n:s.resolve(t,n),i=s.relative(t,r),{data:a}=await K(r),o;return o=a.permalink?a.permalink.startsWith(`/`)?a.permalink:`/${a.permalink}`:e(i),u===`/`?o:(u.endsWith(`/`)?u:u+`/`)+(o.startsWith(`/`)?o.substring(1):o)}));d.push(...i)}d.includes(u)||d.push(u);let f={routes:Array.from(new Set(d)).sort(),timestamp:Date.now()};return l.writeFileSync(s.resolve(a,`link-tree.json`),JSON.stringify(f,null,2)),f}function le(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-x(i,a)/Math.max(i.length,a.length);return o>.8?o*.95:1-x(e,t)/Math.max(e.length,t.length)}const Z=new Map;function Q(e,t){if(Z.has(e))return Z.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=le(e,a);c>i&&(i=c,r=a)}let a={bestMatch:r,similarity:i};return Z.set(e,a),a}async function $(e){let t=[];if(!e.doctorConfig.checks.metadata.enabled)return t;let{titleMin:r,titleMax:a,descriptionMin:o}=e.doctorConfig.checks.metadata,c=new Map;for(let l of e.files){let u=n(s.relative(e.docsDir,l));try{let{raw:n,data:s}=await K(l);if(n.trim().startsWith(`---`)&&n.split(`---`).length>=3&&Object.keys(s).length===0){let n=W(e,`malformedFrontmatter`,`high`);n!==`off`&&t.push({file:u,level:n,message:`Malformed frontmatter (YAML parsing failed).`,suggestion:`Check your YAML syntax for indentation or unquoted special characters.`})}let d=i.safeParse(s);if(!d.success){let n=W(e,`invalidFrontmatter`,`high`);if(n!==`off`)for(let e of d.error.issues)t.push({file:u,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(s[n]===void 0){let r=W(e,`missingMetadata`,`warning`);r!==`off`&&t.push({file:u,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(s[r]&&Number.isNaN(Date.parse(String(s[r])))){let n=W(e,`invalidFrontmatter`,`high`);n!==`off`&&t.push({file:u,level:n,message:`Invalid date format in field "${r}": "${s[r]}".`,suggestion:`Use a valid ISO date format (e.g., YYYY-MM-DD).`})}}if(s.title){let n=String(s.title);if(n.length<r){let i=W(e,`shortMetadata`,`low`);i!==`off`&&t.push({file:u,level:i,message:`Title is too short (${n.length} chars).`,suggestion:`Titles should be at least ${r} characters for better SEO.`})}else if(n.length>a){let r=W(e,`shortMetadata`,`low`);r!==`off`&&t.push({file:u,level:r,message:`Title is too long (${n.length} chars).`,suggestion:`Titles should be under ${a} characters.`})}let i=c.get(n)||[];i.push(u),c.set(n,i)}if(s.description&&String(s.description).length<o){let n=W(e,`shortMetadata`,`low`);n!==`off`&&t.push({file:u,level:n,message:`Description is very short.`,suggestion:`Descriptions should ideally be at least ${o} characters.`})}}catch(n){if(n instanceof Error){let r=W(e,`malformedFrontmatter`,`high`);r!==`off`&&t.push({file:u,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 c.entries())if(r.length>1){let i=W(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}async function ue(e){let t=[],{internal:r,external:i,ignore:a,timeout:o,concurrency:c}=e.doctorConfig.checks.links;if(!r&&!i&&!e.options.checkExternal)return t;let u=/(?:\[.*?\]\((.*?)\))|(?:href=["']([^"']+)["'])/g,d=new Set,f=5e5;for(let o of e.files){let c=n(s.relative(e.docsDir,o)),{content:p}=await K(o),m=[...(p.length>f?p.slice(0,f):p).replace(/```[\s\S]*?```/g,``).replace(/`[^`\n]*`/g,``).matchAll(u)];for(let n of m){let u=n[1]||n[2],f=!!n[1];if(!u||a.some(e=>u.includes(e)))continue;if(/^https?:\/\//i.test(u)){(i||e.options.checkExternal)&&d.add({url:u,file:o});continue}if(!r||/^(mailto|tel|#)/i.test(u))continue;let p;try{p=decodeURIComponent(u.split(`#`)[0].split(`?`)[0])}catch{p=u.split(`#`)[0].split(`?`)[0]}if(!p)continue;let m=!1,h=``;if(p.startsWith(`/`))if(e.routeIndex.has(p)||e.routeIndexWithSlash.has(p)||e.routeIndexWithoutSlash.has(p))m=!0;else{let t=e.basePrefix+(p.startsWith(`/`)?p:`/`+p);if(e.routeIndex.has(t)||e.routeIndexWithSlash.has(t))m=!1,h=t;else{let t=e.config.base!==`/`&&p.startsWith(e.config.base||`/`)?p.substring((e.config.base||`/`).length):p,n=t.startsWith(`/`)?t.substring(1):t;h=s.join(e.docsDir,n),m=[``,`.md`,`.mdx`,`/index.md`,`/index.mdx`].some(e=>J(h+e))}}else h=s.resolve(s.dirname(o),p),m=[``,`.md`,`.mdx`,`/index.md`,`/index.mdx`].some(e=>J(h+e));if(!m){let{bestMatch:n,similarity:r}=Q(p,e.linkTree.routes),i=!1,a=e.basePrefix+(p.startsWith(`/`)?p:`/`+p);(e.routeIndex.has(a)||e.routeIndexWithSlash.has(a))&&(n=a,r=1,i=!0);let s=r>.6||i,d=r>.75&&n!==p||i,m=W(e,`brokenLink`,`high`);m!==`off`&&t.push({file:c,level:m,message:`Broken internal link: "${u}"`,suggestion:s?`Did you mean "${n}"?`:`Ensure the target exists or check for typos.`,fix:d?async()=>{let e=u.includes(`#`)?`#`+u.split(`#`)[1]:``,t=f?`(${u})`:`href="${u}"`,r=f?`(${n}${e})`:`href="${n}${e}"`,i=l.readFileSync(o,`utf-8`).replace(t,r);l.writeFileSync(o,i),G.delete(o)}:void 0})}}}if(d.size>0){v(p.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(),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.message}}},a=Array.from(r.keys()),l=[];for(let e=0;e<a.length;e+=c){let t=a.slice(e,e+c),n=await Promise.allSettled(t.map(i));l.push(...n.map(e=>e.status===`fulfilled`?e.value:{url:`unknown`,ok:!1,error:e.reason}))}for(let i of l)if(!i.ok){let a=W(e,`brokenLink`,`warning`);if(a!==`off`){let o=r.get(i.url)||[];for(let r of o)t.push({file:n(s.relative(e.docsDir,r)),level:a,message:`Broken external link: "${i.url}"`,suggestion:`Verify the URL or update it if it's permanently down. Error: ${i.error||`Status >= 400`}`})}}}return t}async function de(e){let t=[];if(!e.doctorConfig.checks.i18n.enabled||!e.config.i18n)return t;let{defaultLocale:r,locales:i}=e.config.i18n,a=Object.keys(i),o=a.filter(e=>e!==r);for(let i of e.files){let c=n(s.relative(e.docsDir,i)),u=c.split(`/`),d=u[0];if(d===r){let n=u.slice(1).join(`/`);for(let r of o){let a=s.join(e.docsDir,r,n);if(!J(a)){let o=W(e,`missingTranslation`,`warning`);o!==`off`&&t.push({file:c,level:o,message:`Missing translation for locale "${r}"`,suggestion:`Create a version at "${r}/${n}".`,fix:async()=>{let e=s.dirname(a);l.existsSync(e)||l.mkdirSync(e,{recursive:!0}),l.copyFileSync(i,a)}})}}}else if(a.includes(d)){let n=u.slice(1).join(`/`);if(!J(s.join(e.docsDir,r,n))){let a=W(e,`missingTranslation`,`low`);a!==`off`&&t.push({file:c,level:a,message:`Orphaned translation (source missing in "${r}")`,suggestion:`Remove this file or create the source at "${r}/${n}".`,fix:async()=>{l.unlinkSync(i)}})}}}return t}async function fe(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=W(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}=Q(r.link,e.linkTree.routes),a=i>.6,o=W(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=W(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 pe(e){let t=[],n=e.doctorConfig.checks.performance;if(!n?.enabled)return t;let r=s.resolve(e.root,`.boltdocs`,`reports`,`performance.json`);if(!l.existsSync(r))return t.push({file:`(build)`,level:W(e,`budgetExceeded`,`warning`),message:"Performance metrics not found. Run `boltdocs build` first."}),t;let i;try{i=JSON.parse(l.readFileSync(r,`utf-8`))}catch{return t.push({file:`(build)`,level:W(e,`budgetExceeded`,`warning`),message:`Failed to parse performance metrics file.`}),t}let a=n.budgets,o=W(e,`budgetExceeded`,`warning`),c=U(a?.maxJSBundleSize,1/0),u=U(a?.maxCSSBundleSize,1/0),d=U(a?.maxPageHTMLSize,1/0),f=a?.maxImagesKB??1/0,p=a?.maxBuildTime??1/0,m=a?.maxFontCount??1/0;if(c!==1/0&&i.totalJSBundleSize>c){let e=(i.totalJSBundleSize/1024).toFixed(0),n=(c/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(u!==1/0&&i.totalCSSBundleSize>u){let e=(i.totalCSSBundleSize/1024).toFixed(0),n=(u/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(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: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=f*1024;if(f!==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 > ${f}kb`,suggestion:`Optimize images with lossy compression or use next-gen formats (webp/avif).`})}if(p!==1/0&&i.buildTime>p){let e=(i.buildTime/1e3).toFixed(1),n=(p/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}async function me(e){let t=s.resolve(e,`doctor.json`);if(l.existsSync(t)){b(`"doctor.json" already exists at ${e}.`);return}try{l.writeFileSync(t,JSON.stringify(H,null,2)),y(`Created "doctor.json" with default configuration.`)}catch(e){_(`Failed to create "doctor.json": ${e}`)}}async function he(e=process.cwd(),t={}){if(t.init){await me(e);return}V();try{let n=await Y(e),{format:r}=n.reporting,i=performance.now(),a=await z(`docs`,e),o=s.resolve(e,`docs`);l.existsSync(o)||(r===`pretty`&&_(`Docs dir not found at ${o}`),process.exit(1)),r===`pretty`&&console.log(g(`✦ DOCTOR — Documentation Health Check`,[` ${p.dim(`Docs dir:`)} ${o}`,` ${p.dim(`Reports:`)} ${e}/.boltdocs/reports/`])),r===`pretty`&&v(p.dim(`🔍 Discovering files and routes...`));let u=re(n.exclude||[]),d=await new c().withFullPaths().filter(e=>{if(!(e.endsWith(`.md`)||e.endsWith(`.mdx`)))return!1;let t=s.relative(o,e).replace(/\\/g,`/`),n=t.split(`/`).some(e=>e.startsWith(`_`)&&e!==`_index.md`&&e!==`_index.mdx`);return!u(t)&&!n}).crawl(o).withPromise();for(let e of d)q.set(e,!0);let b=await X(o,e,a,d),x=a.base||`/`,S=x===`/`?``:x.endsWith(`/`)?x.slice(0,-1):x,C={root:e,docsDir:o,config:a,doctorConfig:n,linkTree:b,files:d,options:t,routeIndex:new Set(b.routes),routeIndexWithSlash:new Set(b.routes.map(e=>e.endsWith(`/`)?e:e+`/`)),routeIndexWithoutSlash:new Set(b.routes.map(e=>e.endsWith(`/`)?e.slice(0,-1):e)),basePrefix:S};r===`pretty`&&v(p.dim(`🧪 Running diagnostic checks in parallel...`));let w=[$(C),ue(C),de(C),fe(C)];t.budget&&w.push(pe(C));let[T,E,D,O,...k]=await Promise.all(w),A=t.budget?k[0]:[],j=[...T,...E,...D,...O,...A];if(r===`pretty`){let e=[{label:`Metadata checks ${T.length>0?`— ${T.length} issue${T.length===1?``:`s`}`:`— OK`}`,done:T.length===0},{label:`Link checks ${E.length>0?`— ${E.length} issue${E.length===1?``:`s`}`:`— OK`}`,done:E.length===0},{label:`i18n checks ${D.length>0?`— ${D.length} issue${D.length===1?``:`s`}`:`— OK`}`,done:D.length===0},{label:`Sidebar checks ${O.length>0?`— ${O.length} issue${O.length===1?``:`s`}`:`— OK`}`,done:O.length===0}];t.budget&&e.push({label:`Performance budget ${A.length>0?`— ${A.length} issue${A.length===1?``:`s`}`:`— OK`}`,done:A.length===0}),console.log(`\n${ne(e)}`)}let M=0;if(t.fix){for(let e of j)if(e.fix){if(C.doctorConfig.fix.confirmChanges&&!await m(`Fix issue in "${e.file}": ${e.message}?`))continue;if(C.doctorConfig.fix.backupFiles){let t=s.resolve(C.docsDir,e.file);l.existsSync(t)&&await ce(t,s.resolve(C.root,C.doctorConfig.fix.backupPath))}await e.fix(),M++}}let N=((performance.now()-i)/1e3).toFixed(2),P=j.filter(e=>e.level===`high`).length,F=j.filter(e=>e.level===`warning`).length,I=j.filter(e=>e.level===`low`).length,L={summary:{total:j.length,high:P,warning:F,low:I,fixed:M,duration:N},issues:j.map(e=>({...e,fix:void 0}))};if(n.reporting.outputFile){let t=s.resolve(e,n.reporting.outputFile);l.existsSync(s.dirname(t))||l.mkdirSync(s.dirname(t),{recursive:!0}),l.writeFileSync(t,JSON.stringify(L,null,2))}if(r===`json`)console.log(JSON.stringify(L,null,2));else if(r===`pretty`){let e=j.reduce((e,t)=>(e[t.file]||(e[t.file]=[]),e[t.file].push(t),e),{});if(j.length>0){h();for(let[n,r]of Object.entries(e)){let e=[];for(let n of r){let r=n.level===`high`?`❌`:n.level===`warning`?`⚠️`:`ℹ️`,i=n.level===`high`?p.red:n.level===`warning`?p.yellow:p.blue;e.push(`${r} ${i(n.level.toUpperCase())}: ${n.message}`),n.suggestion&&e.push(` ${p.dim(`💡 ${n.suggestion}`)}`),t.fix&&n.fix&&e.push(` ${p.green(`✅ Fixed automatically`)}`)}console.log(`\n${te(`📄 ${n}`,e)}`)}h()}if(j.length===0)console.log(ee(`✨ Documentation Health Check`,[` Everything looks perfect!`,` Your documentation is in great shape.`,``,` ${p.dim(`Scanned ${d.length} file${d.length===1?``:`s`} in ${N}s`)}`]));else{let e=[];P>0&&e.push(p.red(`${P} Critical Error${P===1?``:`s`}`)),F>0&&e.push(p.yellow(`${F} Warning${F===1?``:`s`}`)),I>0&&e.push(p.blue(`${I} Improvement${I===1?``:`s`}`));let t=[...f(e).split(`
28
+ `).map(e=>e.trimStart()),``,p.dim(`Scanned ${d.length} file${d.length===1?``:`s`} in ${N}s`)];console.log(`\n${g(`Diagnosis Results`,t)}\n`),M>0&&y(`Successfully fixed ${M} issues automatically!`),P>0?_(`Please fix the critical errors before building for production.`):y(`No critical issues found. You are ready to go!`)}}n.reporting.failOnError&&P>0&&process.exit(1),n.reporting.maxWarnings!==-1&&F>n.reporting.maxWarnings&&(r===`pretty`&&_(`Failed: Too many warnings (${F} > ${n.reporting.maxWarnings})`),process.exit(1))}catch(e){_(`Doctor failed: ${e}`),process.exit(1)}}export{C as _,$ as a,X as c,V as d,R as f,I as g,F as h,ue as i,Y as l,L as m,me as n,pe as o,z as p,de as r,fe as s,he as t,H as u};
@@ -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-jMxWZyLJ.cjs`);exports.doctorAction=e.t;
6
+ const e=require(`./doctor-BArviV8X.cjs`);exports.doctorAction=e.t;
@@ -3,4 +3,4 @@
3
3
  * Copyright (c) 2026 Jesus Alcala
4
4
  * Licensed under the MIT License.
5
5
  */
6
- const e=require(`./routes-2k3tbUmC.cjs`);exports.generateRoutes=e.t;
6
+ import{t as e}from"./doctor-CgLA7_Uv.mjs";export{e as doctorAction};
@@ -3,11 +3,11 @@
3
3
  * Copyright (c) 2026 Jesus Alcala
4
4
  * Licensed under the MIT License.
5
5
  */
6
- import e from"node:path";import{double as t,info as n,success as r,warn as i}from"@bdocs/dui";import a from"node:fs";function o(e){return e.replace(/^v/,``).replace(/^\[|\]$/g,``)}function s(e){let t=e.match(/Thanks \[@(\w+)\]/);return t?t[1]:void 0}function c(e){let t=e.match(/Thanks \[@[^\]]+\]\(([^)]+)\)/);return t?t[1]:void 0}function l(e){let t=e.match(/\[`([a-f0-9]+)`\]/);return t?t[1]:void 0}function u(e){let t=e.match(/\[`[a-f0-9]+`\]\(([^)]+)\)/);return t?t[1]:void 0}function d(e,t){let n=e;return n=n.replace(/Thanks \[@[^\]]+\]\([^)]+\)/g,``),n=n.replace(/\[`[a-f0-9]+`\]\([^)]+\)/g,``),n=n.replace(/!\s*-/g,``),n=n.replace(/^-\s*/,``),n=n.replace(/^feat:\s*/i,``),n=n.replace(/^fix:\s*/i,``),n=n.replace(/^perf:\s*/i,``),n=n.replace(/^refactor:\s*/i,``),n=n.replace(/^docs:\s*/i,``),n=n.replace(/^chore:\s*/i,``),n=n.replace(/^\*\*[a-z]+(\([^)]+\))?:\*\*/gi,``),n.trim()}function f(e){let t=/^###\s+(Minor Changes|Major Changes|Patch Changes)/m.test(e),n=/^##\s+v?(\d+\.\d+\.\d+)/m.test(e);return t&&n}function p(e,t){for(let n=t+1;n<Math.min(t+10,e.length);n++){let t=e[n].trim().toLowerCase();if(t.startsWith(`### major`))return`major`;if(t.startsWith(`### minor`))return`minor`;if(t.startsWith(`### patch`))return`patch`}return null}function m(e){let t=e.split(`
6
+ import e from"node:path";import t from"node:fs";import{double as n,info as r,success as i,warn as a}from"@bdocs/dui";function o(e){return e.replace(/^v/,``).replace(/^\[|\]$/g,``)}function s(e){let t=e.match(/Thanks \[@(\w+)\]/);return t?t[1]:void 0}function c(e){let t=e.match(/Thanks \[@[^\]]+\]\(([^)]+)\)/);return t?t[1]:void 0}function l(e){let t=e.match(/\[`([a-f0-9]+)`\]/);return t?t[1]:void 0}function u(e){let t=e.match(/\[`[a-f0-9]+`\]\(([^)]+)\)/);return t?t[1]:void 0}function d(e,t){let n=e;return n=n.replace(/Thanks \[@[^\]]+\]\([^)]+\)/g,``),n=n.replace(/\[`[a-f0-9]+`\]\([^)]+\)/g,``),n=n.replace(/!\s*-/g,``),n=n.replace(/^-\s*/,``),n=n.replace(/^feat:\s*/i,``),n=n.replace(/^fix:\s*/i,``),n=n.replace(/^perf:\s*/i,``),n=n.replace(/^refactor:\s*/i,``),n=n.replace(/^docs:\s*/i,``),n=n.replace(/^chore:\s*/i,``),n=n.replace(/^\*\*[a-z]+(\([^)]+\))?:\*\*/gi,``),n.trim()}function f(e){let t=/^###\s+(Minor Changes|Major Changes|Patch Changes)/m.test(e),n=/^##\s+v?(\d+\.\d+\.\d+)/m.test(e);return t&&n}function p(e,t){for(let n=t+1;n<Math.min(t+10,e.length);n++){let t=e[n].trim().toLowerCase();if(t.startsWith(`### major`))return`major`;if(t.startsWith(`### minor`))return`minor`;if(t.startsWith(`### patch`))return`patch`}return null}function m(e){let t=e.split(`
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(t){let n=e.resolve(t);if(!a.existsSync(n))throw Error(`Changelog file not found: ${n}`);return a.readFileSync(n,`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;n(`📄 Reading changelog from: ${o}`);let f=A(j(o));if(f.length===0){i(`⚠️ No versions found in changelog`);return}let p=d?f.slice(0,d):f;a.existsSync(c)||(a.mkdirSync(c,{recursive:!0}),n(`📁 Created directory: ${c}`));for(let[t,n]of p.entries()){let i=P(n,l,u),o=`${t+1}.v${n.version}.md`,s=e.join(c,o);a.writeFileSync(s,i,`utf-8`),r(`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${t(`Changelog Generation`,m)}\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`};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(`Changelog Generation`,m)}\n`)}function P(e,t,n){let r=e.type.charAt(0).toUpperCase()+e.type.slice(1),i=F(e.changes),a=`---
11
11
  title: v${e.version}
12
12
  badge: "${r}"
13
13
  description: Changelog version ${e.version}${e.date?` (${e.date})`:``}
@@ -3,11 +3,11 @@
3
3
  * Copyright (c) 2026 Jesus Alcala
4
4
  * Licensed under the MIT License.
5
5
  */
6
- const e=require(`./chunk-CU-zTemE.cjs`);let t=require(`node:path`);t=e.t(t);let n=require(`@bdocs/dui`),r=require(`node:fs`);r=e.t(r);function i(e){return e.replace(/^v/,``).replace(/^\[|\]$/g,``)}function a(e){let t=e.match(/Thanks \[@(\w+)\]/);return t?t[1]:void 0}function o(e){let t=e.match(/Thanks \[@[^\]]+\]\(([^)]+)\)/);return t?t[1]:void 0}function s(e){let t=e.match(/\[`([a-f0-9]+)`\]/);return t?t[1]:void 0}function c(e){let t=e.match(/\[`[a-f0-9]+`\]\(([^)]+)\)/);return t?t[1]:void 0}function l(e,t){let n=e;return n=n.replace(/Thanks \[@[^\]]+\]\([^)]+\)/g,``),n=n.replace(/\[`[a-f0-9]+`\]\([^)]+\)/g,``),n=n.replace(/!\s*-/g,``),n=n.replace(/^-\s*/,``),n=n.replace(/^feat:\s*/i,``),n=n.replace(/^fix:\s*/i,``),n=n.replace(/^perf:\s*/i,``),n=n.replace(/^refactor:\s*/i,``),n=n.replace(/^docs:\s*/i,``),n=n.replace(/^chore:\s*/i,``),n=n.replace(/^\*\*[a-z]+(\([^)]+\))?:\*\*/gi,``),n.trim()}function u(e){let t=/^###\s+(Minor Changes|Major Changes|Patch Changes)/m.test(e),n=/^##\s+v?(\d+\.\d+\.\d+)/m.test(e);return t&&n}function d(e,t){for(let n=t+1;n<Math.min(t+10,e.length);n++){let t=e[n].trim().toLowerCase();if(t.startsWith(`### major`))return`major`;if(t.startsWith(`### minor`))return`minor`;if(t.startsWith(`### patch`))return`patch`}return null}function f(e){let t=e.split(`
6
+ const e=require(`./chunk-CU-zTemE.cjs`);let t=require(`node:path`);t=e.t(t);let n=require(`node:fs`);n=e.t(n);let r=require(`@bdocs/dui`);function i(e){return e.replace(/^v/,``).replace(/^\[|\]$/g,``)}function a(e){let t=e.match(/Thanks \[@(\w+)\]/);return t?t[1]:void 0}function o(e){let t=e.match(/Thanks \[@[^\]]+\]\(([^)]+)\)/);return t?t[1]:void 0}function s(e){let t=e.match(/\[`([a-f0-9]+)`\]/);return t?t[1]:void 0}function c(e){let t=e.match(/\[`[a-f0-9]+`\]\(([^)]+)\)/);return t?t[1]:void 0}function l(e,t){let n=e;return n=n.replace(/Thanks \[@[^\]]+\]\([^)]+\)/g,``),n=n.replace(/\[`[a-f0-9]+`\]\([^)]+\)/g,``),n=n.replace(/!\s*-/g,``),n=n.replace(/^-\s*/,``),n=n.replace(/^feat:\s*/i,``),n=n.replace(/^fix:\s*/i,``),n=n.replace(/^perf:\s*/i,``),n=n.replace(/^refactor:\s*/i,``),n=n.replace(/^docs:\s*/i,``),n=n.replace(/^chore:\s*/i,``),n=n.replace(/^\*\*[a-z]+(\([^)]+\))?:\*\*/gi,``),n.trim()}function u(e){let t=/^###\s+(Minor Changes|Major Changes|Patch Changes)/m.test(e),n=/^##\s+v?(\d+\.\d+\.\d+)/m.test(e);return t&&n}function d(e,t){for(let n=t+1;n<Math.min(t+10,e.length);n++){let t=e[n].trim().toLowerCase();if(t.startsWith(`### major`))return`major`;if(t.startsWith(`### minor`))return`minor`;if(t.startsWith(`### patch`))return`patch`}return null}function f(e){let t=e.split(`
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 n=t.default.resolve(e);if(!r.default.existsSync(n))throw Error(`Changelog file not found: ${n}`);return r.default.readFileSync(n,`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,n.info)(`📄 Reading changelog from: ${e}`);let l=O(k(e));if(l.length===0){(0,n.warn)(`⚠️ No versions found in changelog`);return}let u=c?l.slice(0,c):l;r.default.existsSync(a)||(r.default.mkdirSync(a,{recursive:!0}),(0,n.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);r.default.writeFileSync(u,c,`utf-8`),(0,n.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,n.double)(`Changelog Generation`,d)}\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`};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)(`Changelog Generation`,d)}\n`)}function M(e,t,n){let r=e.type.charAt(0).toUpperCase()+e.type.slice(1),i=N(e.changes),a=`---
11
11
  title: v${e.version}
12
12
  badge: "${r}"
13
13
  description: Changelog version ${e.version}${e.date?` (${e.date})`:``}
@@ -43,51 +43,12 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
43
43
  }) : target, mod));
44
44
 
45
45
  //#endregion
46
- let react_router_dom = require("react-router-dom");
47
46
  let react = require("react");
48
- react = __toESM(react);
47
+ let react_router_dom = require("react-router-dom");
49
48
  let react_jsx_runtime = require("react/jsx-runtime");
50
49
  let clsx = require("clsx");
51
50
  let tailwind_merge = require("tailwind-merge");
52
51
 
53
- //#region src/client/app/config-context.tsx
54
- /**
55
- * Context for the global documentation configuration.
56
- * Using a global singleton pattern to survive dual-package or duplicated-code hazards.
57
- */
58
- const CONFIG_CONTEXT_SYMBOL = Symbol.for("__BDOCS_CONFIG_CONTEXT__");
59
- const CONFIG_INSTANCE_SYMBOL = Symbol.for("__BDOCS_CONFIG_INSTANCE__");
60
- const ConfigContext = globalThis[CONFIG_CONTEXT_SYMBOL] || (globalThis[CONFIG_CONTEXT_SYMBOL] = (0, react.createContext)(null));
61
- /**
62
- * Hook to access the Boltdocs configuration.
63
- */
64
- function useConfig() {
65
- const context = (0, react.use)(ConfigContext);
66
- if (!context && typeof globalThis !== "undefined" && globalThis[CONFIG_INSTANCE_SYMBOL]) return globalThis[CONFIG_INSTANCE_SYMBOL];
67
- if (!context) throw new Error("useConfig must be used within a ConfigProvider");
68
- return context;
69
- }
70
-
71
- //#endregion
72
- //#region src/client/app/routes-context.tsx
73
- const RoutesContext = (0, react.createContext)({ routes: [] });
74
- /**
75
- * Hook to access the processed routes list from the closest provider.
76
- */
77
- function useRoutesContext() {
78
- return (0, react.use)(RoutesContext);
79
- }
80
- /**
81
- * Provider component for the documentation routes.
82
- */
83
- function RoutesProvider({ routes, children }) {
84
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RoutesContext.Provider, {
85
- value: { routes },
86
- children
87
- });
88
- }
89
-
90
- //#endregion
91
52
  //#region src/client/store/boltdocs-context.tsx
92
53
  const PREFERENCES_KEY = "boltdocs-user-preferences";
93
54
  const BOLTDOCS_CONTEXT_SYMBOL = Symbol.for("__BDOCS_BOLTDOCS_CONTEXT__");
@@ -167,75 +128,22 @@ function useBoltdocsContext() {
167
128
  }
168
129
 
169
130
  //#endregion
170
- //#region src/client/utils/path.ts
131
+ //#region src/client/app/config-context.tsx
171
132
  /**
172
- * Normalizes a URL path by stripping any trailing slash unless it's the root path.
173
- *
174
- * @param p - The path to normalize.
175
- * @returns The normalized path.
133
+ * Context for the global documentation configuration.
134
+ * Using a global singleton pattern to survive dual-package or duplicated-code hazards.
176
135
  */
177
- function normalizePath(p) {
178
- return p.endsWith("/") && p.length > 1 ? p.slice(0, -1) : p;
179
- }
180
-
181
- //#endregion
182
- //#region src/client/hooks/use-routes.ts
136
+ const CONFIG_CONTEXT_SYMBOL = Symbol.for("__BDOCS_CONFIG_CONTEXT__");
137
+ const CONFIG_INSTANCE_SYMBOL = Symbol.for("__BDOCS_CONFIG_INSTANCE__");
138
+ const ConfigContext = globalThis[CONFIG_CONTEXT_SYMBOL] || (globalThis[CONFIG_CONTEXT_SYMBOL] = (0, react.createContext)(null));
183
139
  /**
184
- * Hook to access the framework's routing state.
185
- * Returns both the complete set of routes and a filtered list based on the current
186
- * version and locale.
140
+ * Hook to access the Boltdocs configuration.
187
141
  */
188
- function useRoutes() {
189
- const { routes: allRoutes } = useRoutesContext();
190
- const config = useConfig();
191
- const location = (0, react_router_dom.useLocation)();
192
- const { hasHydrated, currentLocale: currentLocaleStore, currentVersion: currentVersionStore } = useBoltdocsContext();
193
- const currentPath = normalizePath(location.pathname);
194
- const currentRoute = allRoutes?.find?.((r) => normalizePath(r.path) === currentPath);
195
- const currentLocale = config.i18n ? currentLocaleStore || config.i18n.defaultLocale : void 0;
196
- const currentVersion = config.versions ? currentVersionStore || config.versions.defaultVersion : void 0;
197
- return {
198
- routes: (0, react.useMemo)(() => {
199
- if (!allRoutes) return [];
200
- const alternateCounts = /* @__PURE__ */ new Map();
201
- const defaultLocale = config.i18n?.defaultLocale || "";
202
- const defaultVersion = config.versions?.defaultVersion || "";
203
- for (const r of allRoutes) {
204
- const locale = r.locale || defaultLocale;
205
- const version = r.version || defaultVersion;
206
- const key = `${r.filePath}::${locale}::${version}`;
207
- alternateCounts.set(key, (alternateCounts.get(key) || 0) + 1);
208
- }
209
- return allRoutes.filter((r) => {
210
- const localeMatch = config.i18n ? (r.locale || config.i18n.defaultLocale) === currentLocale : true;
211
- const versionMatch = config.versions ? (r.version || config.versions.defaultVersion) === currentVersion : true;
212
- if (!(localeMatch && versionMatch)) return false;
213
- const isCurrentLocalePrefixed = !!currentRoute?.locale;
214
- const isCurrentVersionPrefixed = !!currentRoute?.version;
215
- const isRouteLocalePrefixed = !!r.locale;
216
- const isRouteVersionPrefixed = !!r.version;
217
- const locale = r.locale || defaultLocale;
218
- const version = r.version || defaultVersion;
219
- const key = `${r.filePath}::${locale}::${version}`;
220
- if ((alternateCounts.get(key) || 0) > 1) {
221
- const localeMismatch = config.i18n && isCurrentLocalePrefixed !== isRouteLocalePrefixed;
222
- const versionMismatch = config.versions && isCurrentVersionPrefixed !== isRouteVersionPrefixed;
223
- if (localeMismatch || versionMismatch) return false;
224
- }
225
- return true;
226
- });
227
- }, [
228
- allRoutes,
229
- config,
230
- currentLocale,
231
- currentVersion,
232
- currentRoute
233
- ]),
234
- allRoutes,
235
- currentRoute,
236
- currentLocale,
237
- currentVersion
238
- };
142
+ function useConfig() {
143
+ const context = (0, react.use)(ConfigContext);
144
+ if (!context && typeof globalThis !== "undefined" && globalThis[CONFIG_INSTANCE_SYMBOL]) return globalThis[CONFIG_INSTANCE_SYMBOL];
145
+ if (!context) throw new Error("useConfig must be used within a ConfigProvider");
146
+ return context;
239
147
  }
240
148
 
241
149
  //#endregion
@@ -272,7 +180,7 @@ var icons_exports = /* @__PURE__ */ __exportAll({
272
180
  });
273
181
  function createIcon(displayName, paths, viewBox = "0 0 24 24") {
274
182
  const Component = ({ size = 24, className, ...props }) => {
275
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
183
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("svg", {
276
184
  xmlns: "http://www.w3.org/2000/svg",
277
185
  width: size,
278
186
  height: size,
@@ -284,7 +192,7 @@ function createIcon(displayName, paths, viewBox = "0 0 24 24") {
284
192
  strokeLinejoin: "round",
285
193
  className,
286
194
  ...props,
287
- children: paths
195
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("title", { children: displayName }), paths]
288
196
  });
289
197
  };
290
198
  Component.displayName = displayName;
@@ -517,6 +425,103 @@ const FileText = createIcon("FileText", /* @__PURE__ */ (0, react_jsx_runtime.js
517
425
  ] }));
518
426
  const CornerDownLeft = createIcon("CornerDownLeft", /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("polyline", { points: "9 10 4 15 9 20" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d: "M20 4v7a4 4 0 0 1-4 4H4" })] }));
519
427
 
428
+ //#endregion
429
+ //#region src/client/app/routes-context.tsx
430
+ const RoutesContext = (0, react.createContext)({ routes: [] });
431
+ /**
432
+ * Hook to access the processed routes list from the closest provider.
433
+ */
434
+ function useRoutesContext() {
435
+ return (0, react.use)(RoutesContext);
436
+ }
437
+ /**
438
+ * Provider component for the documentation routes.
439
+ */
440
+ function RoutesProvider({ routes, children }) {
441
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RoutesContext.Provider, {
442
+ value: { routes },
443
+ children
444
+ });
445
+ }
446
+
447
+ //#endregion
448
+ //#region src/client/utils/path.ts
449
+ /**
450
+ * Normalizes a URL path by stripping any trailing slash unless it's the root path.
451
+ *
452
+ * @param p - The path to normalize.
453
+ * @returns The normalized path.
454
+ */
455
+ function normalizePath(p) {
456
+ return p.endsWith("/") && p.length > 1 ? p.slice(0, -1) : p;
457
+ }
458
+
459
+ //#endregion
460
+ //#region src/client/hooks/use-routes.ts
461
+ /**
462
+ * Hook to access the framework's routing state.
463
+ * Returns both the complete set of routes and a filtered list based on the current
464
+ * version and locale.
465
+ */
466
+ function useRoutes() {
467
+ const { routes: allRoutes } = useRoutesContext();
468
+ const config = useConfig();
469
+ const location = (0, react_router_dom.useLocation)();
470
+ const { hasHydrated, currentLocale: currentLocaleStore, currentVersion: currentVersionStore } = useBoltdocsContext();
471
+ const currentPath = normalizePath(location.pathname);
472
+ const currentRoute = allRoutes?.find?.((r) => normalizePath(r.path) === currentPath);
473
+ const currentLocale = config.i18n ? currentLocaleStore || config.i18n.defaultLocale : void 0;
474
+ const currentVersion = config.versions ? currentVersionStore || config.versions.defaultVersion : void 0;
475
+ const routes = (0, react.useMemo)(() => {
476
+ if (!allRoutes) return [];
477
+ const alternateCounts = /* @__PURE__ */ new Map();
478
+ const defaultLocale = config.i18n?.defaultLocale || "";
479
+ const defaultVersion = config.versions?.defaultVersion || "";
480
+ for (const r of allRoutes) {
481
+ const locale = r.locale || defaultLocale;
482
+ const version = r.version || defaultVersion;
483
+ const key = `${r.filePath}::${locale}::${version}`;
484
+ alternateCounts.set(key, (alternateCounts.get(key) || 0) + 1);
485
+ }
486
+ return allRoutes.filter((r) => {
487
+ const localeMatch = config.i18n ? (r.locale || config.i18n.defaultLocale) === currentLocale : true;
488
+ const versionMatch = config.versions ? (r.version || config.versions.defaultVersion) === currentVersion : true;
489
+ if (!(localeMatch && versionMatch)) return false;
490
+ const isCurrentLocalePrefixed = !!currentRoute?.locale;
491
+ const isCurrentVersionPrefixed = !!currentRoute?.version;
492
+ const isRouteLocalePrefixed = !!r.locale;
493
+ const isRouteVersionPrefixed = !!r.version;
494
+ const locale = r.locale || defaultLocale;
495
+ const version = r.version || defaultVersion;
496
+ const key = `${r.filePath}::${locale}::${version}`;
497
+ if ((alternateCounts.get(key) || 0) > 1) {
498
+ const localeMismatch = config.i18n && isCurrentLocalePrefixed !== isRouteLocalePrefixed;
499
+ const versionMismatch = config.versions && isCurrentVersionPrefixed !== isRouteVersionPrefixed;
500
+ if (localeMismatch || versionMismatch) return false;
501
+ }
502
+ return true;
503
+ });
504
+ }, [
505
+ allRoutes,
506
+ config,
507
+ currentLocale,
508
+ currentVersion,
509
+ currentRoute
510
+ ]);
511
+ const collections = (0, react.useMemo)(() => {
512
+ return new Set((allRoutes || []).map((r) => r.collection).filter(Boolean));
513
+ }, [allRoutes]);
514
+ const currentSegment = location.pathname.split("/").filter(Boolean)[0]?.toLowerCase();
515
+ return {
516
+ routes,
517
+ allRoutes,
518
+ currentRoute,
519
+ isCollectionPage: !!currentRoute?.collection || (currentSegment ? collections.has(currentSegment) : false),
520
+ currentLocale,
521
+ currentVersion
522
+ };
523
+ }
524
+
520
525
  //#endregion
521
526
  //#region src/client/hooks/use-localized-to.ts
522
527
  function useLocalizedTo(to) {
@@ -567,7 +572,7 @@ function cn(...inputs) {
567
572
  * A primitive Link component that wraps a standard anchor tag
568
573
  * and adds framework-specific logic for path localization and preloading.
569
574
  */
570
- const Link = (props) => {
575
+ function Link(props) {
571
576
  const { href, onMouseEnter, onFocus, onClick, ...rest } = props;
572
577
  const navigate = (0, react_router_dom.useNavigate)();
573
578
  const localizedHref = useLocalizedTo(href ?? "");
@@ -592,11 +597,11 @@ const Link = (props) => {
592
597
  onMouseEnter: handleMouseEnter,
593
598
  onFocus: handleFocus
594
599
  });
595
- };
600
+ }
596
601
  /**
597
602
  * A primitive NavLink component that provides active state detection.
598
603
  */
599
- const NavLink = (props) => {
604
+ function NavLink(props) {
600
605
  const { href, end = false, className, children, ...rest } = props;
601
606
  const location = (0, react_router_dom.useLocation)();
602
607
  const localizedHref = useLocalizedTo(href ?? "");
@@ -609,7 +614,7 @@ const NavLink = (props) => {
609
614
  className: resolvedClassName,
610
615
  children: resolvedChildren
611
616
  });
612
- };
617
+ }
613
618
 
614
619
  //#endregion
615
620
  //#region src/client/components/icons-dev.tsx