boltdocs 1.11.0 → 2.0.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 (46) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/LICENSE +21 -0
  3. package/dist/cache-7G6D532T.mjs +1 -0
  4. package/dist/chunk-A4HQPEPU.mjs +1 -0
  5. package/dist/chunk-BA5NH5HU.mjs +1 -0
  6. package/dist/chunk-BQCD3DWG.mjs +1 -0
  7. package/dist/chunk-H63UMKYF.mjs +1 -0
  8. package/dist/chunk-IWHRQHS7.mjs +1 -0
  9. package/dist/chunk-JZXLCA2E.mjs +1 -0
  10. package/dist/chunk-MFU7Q6WF.mjs +1 -0
  11. package/dist/chunk-QYPNX5UN.mjs +1 -0
  12. package/dist/chunk-XEAPSFMB.mjs +1 -0
  13. package/dist/client/components/mdx/index.d.mts +209 -0
  14. package/dist/client/components/mdx/index.d.ts +209 -0
  15. package/dist/client/components/mdx/index.js +1 -0
  16. package/dist/client/components/mdx/index.mjs +1 -0
  17. package/dist/client/hooks/index.d.mts +133 -0
  18. package/dist/client/hooks/index.d.ts +133 -0
  19. package/dist/client/hooks/index.js +1 -0
  20. package/dist/client/hooks/index.mjs +1 -0
  21. package/dist/client/index.d.mts +212 -0
  22. package/dist/client/index.d.ts +212 -0
  23. package/dist/client/index.js +1 -0
  24. package/dist/client/index.mjs +1 -0
  25. package/dist/client/ssr.d.mts +31 -0
  26. package/dist/client/ssr.d.ts +31 -0
  27. package/dist/client/ssr.js +1 -0
  28. package/dist/client/ssr.mjs +1 -0
  29. package/dist/config-CX4l-ZNp.d.mts +166 -0
  30. package/dist/config-CX4l-ZNp.d.ts +166 -0
  31. package/dist/node/index.d.mts +89 -0
  32. package/dist/node/index.d.ts +89 -0
  33. package/dist/node/index.js +57 -0
  34. package/dist/node/index.mjs +57 -0
  35. package/dist/search-dialog-EB3N4TYM.mjs +1 -0
  36. package/dist/types-BuZWFT7r.d.ts +159 -0
  37. package/dist/types-CvT-SGbK.d.mts +159 -0
  38. package/dist/use-routes-5bAtAAYX.d.mts +30 -0
  39. package/dist/use-routes-BefRXY3v.d.ts +30 -0
  40. package/package.json +10 -10
  41. package/src/client/app/index.tsx +9 -6
  42. package/src/client/types.ts +1 -1
  43. package/src/node/plugin/index.ts +0 -1
  44. package/src/node/routes/parser.ts +27 -32
  45. package/src/node/ssg/index.ts +29 -3
  46. package/src/node/utils.ts +23 -0
@@ -0,0 +1,57 @@
1
+ import{a as $,b as G,c as H,d as it,e as nt,f as D,g as J,h as rt,i as _,j as X,k as j,l as st,m as at}from"../chunk-MFU7Q6WF.mjs";import"../chunk-JZXLCA2E.mjs";import{loadEnv as zt}from"vite";import jt from"fast-glob";var R=new st({name:"routes"});function K(){R.invalidateAll()}function Z(o){R.invalidate(o)}import F from"path";import Dt from"github-slugger";function lt(o,r,i,p){let e=decodeURIComponent(o),c=F.resolve(e),l=F.resolve(r),u=$(F.relative(l,c));if(u.startsWith("../")||u===".."||c.includes("\0"))throw new Error(`Security breach: File is outside of docs directory or contains null bytes: ${o}`);let{data:t,content:n}=nt(o),s=u.split("/"),a,f;if(p?.versions&&s.length>0){let C=s[0];p.versions.versions[C]&&(f=C,s=s.slice(1))}if(p?.i18n&&s.length>0){let C=s[0];p.i18n.locales[C]&&(a=C,s=s.slice(1))}let v;if(s.length>0){let C=s[0].match(/^\((.+)\)$/);C&&(v=C[1].toLowerCase(),s=s.slice(1))}let d=s.join("/"),m;t.permalink?m=t.permalink.startsWith("/")?t.permalink:`/${t.permalink}`:m=rt(d||"index.md");let g=i;f&&(g+="/"+f),a&&(g+="/"+a),g+=m==="/"?"":m,(!g||g==="")&&(g="/");let y=s[s.length-1],k=G(y),x=G(F.basename(o,F.extname(o))),h=t.sidebarPosition??H(y),w=s.length>=2?s[0]:void 0,S=w?G(w):void 0,L=s.length>=2&&/^index\.mdx?$/.test(k),$t=new Dt,tt=[],wt=/^(#{2,4})\s+(.+)$/gm,V;for(;(V=wt.exec(n))!==null;){let C=V[1].length,St=V[2].replace(/\[([^\]]+)\]\([^\)]+\)/g,"$1").replace(/[_*`]/g,"").trim(),ot=_(St).trim(),Mt=$t.slug(ot);tt.push({level:C,text:ot,id:Mt})}let kt=t.title?_(String(t.title)):x,W=t.description?_(String(t.description)):"";!W&&n&&(W=X(n.replace(/^#+.*$/gm,"").replace(/\[([^\]]+)\]\([^\)]+\)/g,"$1").replace(/[_*`]/g,"").replace(/\s+/g," ")).trim().slice(0,160));let Rt=t.badge?_(String(t.badge)):void 0,et=t.icon?String(t.icon):void 0,Bt=Tt(n);return{route:{path:g,componentPath:o,filePath:u,title:kt,description:W,sidebarPosition:h,headings:tt,locale:a,version:f,badge:Rt,icon:et,tab:v,_content:Bt,_rawContent:n},relativeDir:S,isGroupIndex:L,inferredTab:v,groupMeta:L?{title:t.groupTitle||t.title||(S?j(S):""),position:t.groupPosition??t.sidebarPosition??(w?H(w):void 0),icon:et}:void 0,inferredGroupPosition:w?H(w):void 0}}function Tt(o){let r=o.replace(/^#+.*$/gm,"").replace(/\[([^\]]+)\]\([^\)]+\)/g,"$1").replace(/\{[^\}]+\}/g,"").replace(/[_*`]/g,"").replace(/\s+/g," ");return X(r).trim()}function dt(o){return o.sort((r,i)=>!r.group&&!i.group?ct(r,i):r.group?i.group?r.group!==i.group?_t(r,i):ct(r,i):1:-1)}function ct(o,r){return o.sidebarPosition!==void 0&&r.sidebarPosition!==void 0?o.sidebarPosition-r.sidebarPosition:o.sidebarPosition!==void 0?-1:r.sidebarPosition!==void 0?1:o.title.localeCompare(r.title)}function _t(o,r){return o.groupPosition!==void 0&&r.groupPosition!==void 0?o.groupPosition-r.groupPosition:o.groupPosition!==void 0?-1:r.groupPosition!==void 0?1:(o.groupTitle||o.group).localeCompare(r.groupTitle||r.group)}var E=new Map;async function I(o,r,i="/docs"){let p=performance.now();R.load(),E.clear(),(process.env.BOLTDOCS_FORCE_REPARSE==="true"||r?.i18n)&&R.invalidateAll();let e=await jt(["**/*.md","**/*.mdx"],{cwd:o,absolute:!0,suppressErrors:!0,followSymbolicLinks:!1});R.pruneStale(new Set(e));let c=50,l=[],u=0;for(let d=0;d<e.length;d+=c){let m=e.slice(d,d+c),g=await Promise.all(m.map(async y=>{let k=R.get(y);if(k)return u++,k;let x=lt(y,o,i,r);return R.set(y,x),x}));l.push(...g),d+c<e.length&&await new Promise(y=>setImmediate(y))}R.save();let t=new Map,n=[];for(let d of l)if(d.isGroupIndex&&d.relativeDir&&n.push(d),d.relativeDir){let m=t.get(d.relativeDir);m?(m.position===void 0&&d.inferredGroupPosition!==void 0&&(m.position=d.inferredGroupPosition),!m.icon&&d.route.icon&&(m.icon=d.route.icon)):(m={title:j(d.relativeDir),position:d.inferredGroupPosition,icon:d.route.icon},t.set(d.relativeDir,m))}for(let d of n){let m=t.get(d.relativeDir);d.groupMeta&&(m.title=d.groupMeta.title,d.groupMeta.position!==void 0&&(m.position=d.groupMeta.position),d.groupMeta.icon&&(m.icon=d.groupMeta.icon))}let s=new Array(l.length);for(let d=0;d<l.length;d++){let m=l[d],g=m.relativeDir,y=g?t.get(g):void 0;s[d]={...m.route,group:g,groupTitle:y?.title||(g?j(g):void 0),groupPosition:y?.position,groupIcon:y?.icon}}let a=s;if(r?.i18n){let d=Ft(s,r,i);a=[...s,...d]}let f=dt(a),v=performance.now()-p;return console.log(`[boltdocs] Route generation: ${v.toFixed(2)}ms (${e.length} files, ${u} cache hits)`),f}function Ft(o,r,i){let p=r.i18n.defaultLocale,e=Object.keys(r.i18n.locales),c=[],l=new Map,u=[];for(let t of o){let n=t.locale||p;l.has(n)||l.set(n,new Set),l.get(n).add(t.path),n===p&&u.push(t)}for(let t of e){if(t===p)continue;let n=l.get(t)||new Set;for(let s of u){let a=Et(s.path,p,t,i);n.has(a)||c.push({...s,path:a,locale:t})}}return c}function Et(o,r,i,p){let e=`${o}:${i}`,c=E.get(e);if(c)return c;let l=p,u=o.match(new RegExp(`^${p}/(v[0-9]+)`));u&&(l+="/"+u[1]);let t=o.substring(l.length),n=`/${r}`;if(t.startsWith(n+"/"))t="/"+i+"/"+t.substring(n.length+1);else if(t===n)t="/"+i;else if(t==="/"||t==="")t="/"+i;else{let a=t.startsWith("/")?"":"/";t="/"+i+a+t}let s=l+t;return E.size>2e3&&E.clear(),E.set(e,s),s}import{ViteImageOptimizer as Ut}from"vite-plugin-image-optimizer";import Q from"path";import It from"fs";import{loadConfigFromFile as Ot}from"vite";var N=["boltdocs.config.js","boltdocs.config.mjs","boltdocs.config.ts"];async function z(o,r=process.cwd()){let i=r,p={docsDir:Q.resolve(o),themeConfig:{title:"Boltdocs",description:"A Vite documentation framework",navbar:[{label:"Home",href:"/"},{label:"Documentation",href:"/docs"}],codeTheme:{light:"github-light",dark:"github-dark"},poweredBy:!0,breadcrumbs:!0}},e={};for(let t of N){let n=Q.resolve(i,t);if(It.existsSync(n))try{let s=await Ot({command:"serve",mode:"development"},n,i);if(s){e=s.config;break}}catch(s){console.warn(`[boltdocs] Failed to load config from ${t}:`,s)}}let l={...{title:e.title,description:e.description,logo:e.logo,navbar:e.navbar,sidebar:e.sidebar,socialLinks:e.socialLinks,footer:e.footer,githubRepo:e.githubRepo,tabs:e.tabs},...e.themeConfig||{}},u=Object.fromEntries(Object.entries(l).filter(([t,n])=>n!==void 0));return u.navbar&&(u.navbar=u.navbar.map(t=>({label:t.label||t.text||"",href:t.href||t.link||t.to||"",items:t.items?.map(n=>({label:n.label||n.text||"",href:n.href||n.link||n.to||""}))}))),{docsDir:Q.resolve(o),themeConfig:{...p.themeConfig,...u,codeTheme:u.codeTheme||(e.themeConfig||e).codeTheme||p.themeConfig?.codeTheme},i18n:e.i18n,versions:e.versions,siteUrl:e.siteUrl,plugins:e.plugins||[],external:e.external,integrations:e.integrations}}import T from"fs";import M from"path";import{fileURLToPath as Lt}from"url";import{createRequire as Gt}from"module";function pt(o,r){let i=D(r.title),p=D(r.description);return o.replace(/<title>.*?<\/title>/,`<title>${i}</title>`).replace(/(<meta name="description" content=")[^"]*(")/,`$1${p}$2`).replace(/(<meta property="og:title" content=")[^"]*(")/,`$1${i}$2`).replace(/(<meta property="og:description" content=")[^"]*(")/,`$1${p}$2`).replace(/(<meta name="twitter:title" content=")[^"]*(")/,`$1${i}$2`).replace(/(<meta name="twitter:description" content=")[^"]*(")/,`$1${p}$2`)}function mt(o,r){let i=r?.siteUrl?.replace(/\/$/,"")||"https://example.com",p=new Date().toISOString().split("T")[0],e=[{url:"/",priority:"1.0",changefreq:"daily"}];if(r?.i18n){let l=r.i18n.defaultLocale;for(let u of Object.keys(r.i18n.locales))u!==l&&e.push({url:`/${u}/`,priority:"1.0",changefreq:"daily"})}return`<?xml version="1.0" encoding="UTF-8"?>
2
+ <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
3
+ ${[...e,...o.map(l=>({url:l,priority:"0.8",changefreq:"weekly"}))].map(l=>` <url>
4
+ <loc>${J(i)}${J(l.url)}</loc>
5
+ <lastmod>${p}</lastmod>
6
+ <changefreq>${l.changefreq}</changefreq>
7
+ <priority>${l.priority}</priority>
8
+ </url>`).join(`
9
+ `)}
10
+ </urlset>`}var Ht=Lt(import.meta.url),ut=M.dirname(Ht),gt=Gt(import.meta.url);async function Y(o){let{docsDir:r,docsDirName:i,outDir:p,config:e}=o,c=await I(r,e),l=e?.themeConfig?.title||"Boltdocs",u=e?.themeConfig?.description||"",t=M.resolve(ut,"../client/ssr.js");if(!T.existsSync(t)){console.error("[boltdocs] SSR module not found at",t,"- Did you build the core package?");return}let n=gt("module"),s=n.prototype.require;n.prototype.require=function(g,...y){return g==="virtual:boltdocs-layout"?{__esModule:!0,default:function(x){try{let w=s.apply(this,[M.resolve(ut,"../client/index.js")]).DefaultLayout||(({children:L})=>L);return s.apply(this,["react"]).createElement(w,x)}catch{return x.children}}}:s.apply(this,[g,...y])};let{render:a}=gt(t);n.prototype.require=s;let f=M.join(p,"index.html");if(!T.existsSync(f)){console.warn("[boltdocs] No index.html found in outDir, skipping SSG.");return}let v=T.readFileSync(f,"utf-8");await Promise.all(c.map(async g=>{let y=`${g.title} | ${l}`,k=g.description||u,x={};x[`/${i}/${g.filePath}`]={default:()=>null};try{let h=await a({path:g.path,routes:c,config:e||{},docsDirName:i,modules:x,homePage:void 0}),w=pt(v,{title:D(y),description:D(k)}).replace("<!--app-html-->",h).replace('<div id="root"></div>',`<div id="root">${h}</div>`),S=M.join(p,g.path);await T.promises.mkdir(S,{recursive:!0}),await T.promises.writeFile(M.join(S,"index.html"),w,"utf-8")}catch(h){console.error(`[boltdocs] Error SSR rendering route ${g.path}:`,h&&(h.stack||h))}}));let d=mt(c.map(g=>g.path),e);T.writeFileSync(M.join(p,"sitemap.xml"),d,"utf-8"),console.log(`[boltdocs] Generated ${c.length} static pages + sitemap.xml`);let{flushCache:m}=await import("../cache-7G6D532T.mjs");await m()}import B from"path";import Nt from"path";function ft(o,r){let i=o.homePage?`import HomePage from '${$(o.homePage)}';`:"",p=o.homePage?"homePage: HomePage,":"",e=r?.plugins?.flatMap(a=>Object.entries(a.components||{}))||[],c=e.map(([a,f])=>`import * as _comp_${a} from '${$(f)}';
11
+ const ${a} = _comp_${a}.default || _comp_${a}['${a}'] || _comp_${a};`).join(`
12
+ `),l=e.map(([a])=>a).join(", "),u=Nt.basename(o.docsDir||"docs"),t=Object.entries(r?.external||{}),n=t.map(([a,f],v)=>`import _ext_${v} from '${$(f)}';`).join(`
13
+ `),s=t.length>0?`externalPages: { ${t.map(([a],f)=>`"${a}": _ext_${f}`).join(", ")} },`:"";return`
14
+ import { createBoltdocsApp as _createApp } from 'boltdocs/client';
15
+ import _routes from 'virtual:boltdocs-routes';
16
+ import _config from 'virtual:boltdocs-config';
17
+ import _user_mdx_components from 'virtual:boltdocs-mdx-components';
18
+ ${i}
19
+ ${c}
20
+ ${n}
21
+
22
+ _createApp({
23
+ target: '#root',
24
+ routes: _routes,
25
+ docsDirName: '${u}',
26
+ config: _config,
27
+ modules: import.meta.glob('/${u}/**/*.{md,mdx}'),
28
+ hot: import.meta.hot,
29
+ ${p}
30
+ ${s}
31
+ components: { ${l}${l?", ":""} ...(_user_mdx_components || {}) },
32
+ });
33
+ `}function ht(o,r){let i=r.themeConfig?.title||"Boltdocs",p=r.themeConfig?.description||"",e=[`<meta name="description" content="${p}">`,`<meta property="og:title" content="${i}">`,`<meta property="og:description" content="${p}">`,'<meta property="og:type" content="website">','<meta name="twitter:card" content="summary">',`<meta name="twitter:title" content="${i}">`,`<meta name="twitter:description" content="${p}">`,'<meta name="generator" content="Boltdocs">'].join(`
34
+ `),c=`
35
+ <script>
36
+ (function() {
37
+ try {
38
+ var stored = localStorage.getItem("boltdocs-theme");
39
+ var theme = stored || (window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light");
40
+ if (theme === "light") {
41
+ document.documentElement.classList.add("theme-light");
42
+ document.documentElement.dataset.theme = "light";
43
+ } else {
44
+ document.documentElement.classList.remove("theme-light");
45
+ document.documentElement.dataset.theme = "dark";
46
+ }
47
+ } catch (e) {}
48
+ })();
49
+ </script>
50
+ `;return o=o.replace(/<title>.*?<\/title>/,`<title>${i}</title>`),o=o.replace("</head>",` ${e}
51
+ ${c} </head>`),o.includes("src/main")||(o=o.replace("</body>",` <script type="module">import "virtual:boltdocs-entry";</script>
52
+ </body>`)),o}import yt from"fs";function xt(o={},r){let i=B.resolve(process.cwd(),o.docsDir||"docs"),p=$(i),e=r,c,l=!1,u=e?.plugins?.flatMap(t=>t.vitePlugins||[])||[];return[{name:"vite-plugin-boltdocs",enforce:"pre",async config(t,n){l=n.command==="build";let s=t.envDir||process.cwd(),a=zt(n.mode,s,"");return Object.assign(process.env,a),e||(e=await z(i)),{optimizeDeps:{include:["react","react-dom"]}}},configResolved(t){c=t},configureServer(t){let n=N.map(m=>B.resolve(process.cwd(),m)),s=["tsx","jsx"],a=s.map(m=>B.resolve(i,`layout.${m}`)),f=["tsx","ts","jsx","js"],v=f.map(m=>B.resolve(i,`mdx-components.${m}`));t.watcher.add([...n,...v,...a]);let d=async(m,g)=>{let y=$(m);if(N.some(h=>y.endsWith(h))){t.restart();return}if(f.some(h=>y.endsWith(`mdx-components.${h}`))){let h=t.moduleGraph.getModuleById("\0virtual:boltdocs-mdx-components");h&&t.moduleGraph.invalidateModule(h),t.ws.send({type:"full-reload"});return}if(s.some(h=>y.endsWith(`layout.${h}`))){let h=t.moduleGraph.getModuleById("\0virtual:boltdocs-layout");h&&t.moduleGraph.invalidateModule(h),t.ws.send({type:"full-reload"});return}if(!y.startsWith(p)||!it(y))return;g==="add"||g==="unlink"?K():Z(m);let k=await I(i,e),x=t.moduleGraph.getModuleById("\0virtual:boltdocs-routes");x&&t.moduleGraph.invalidateModule(x),t.ws.send({type:"custom",event:"boltdocs:routes-update",data:k})};t.watcher.on("add",m=>d(m,"add")),t.watcher.on("unlink",m=>d(m,"unlink")),t.watcher.on("change",m=>d(m,"change"))},resolveId(t){if(t==="virtual:boltdocs-routes"||t==="virtual:boltdocs-config"||t==="virtual:boltdocs-entry"||t==="virtual:boltdocs-mdx-components"||t==="virtual:boltdocs-layout")return"\0"+t},async load(t){if(t==="\0virtual:boltdocs-routes"){let n=await I(i,e);return`export default ${JSON.stringify(n,null,2)};`}if(t==="\0virtual:boltdocs-config"){let n={themeConfig:e?.themeConfig,integrations:e?.integrations,i18n:e?.i18n,versions:e?.versions,siteUrl:e?.siteUrl};return`export default ${JSON.stringify(n,null,2)};`}if(t==="\0virtual:boltdocs-entry")return ft(o,e);if(t==="\0virtual:boltdocs-mdx-components"){let n=["tsx","ts","jsx","js"],s=null;for(let a of n){let f=B.resolve(i,`mdx-components.${a}`);if(yt.existsSync(f)){s=f;break}}if(s){let a=$(s);return`import * as components from '${a}';
53
+ const mdxComponents = components.default || components;
54
+ export default mdxComponents;
55
+ export * from '${a}';`}return"export default {};"}if(t==="\0virtual:boltdocs-layout"){let n=["tsx","jsx"],s=null;for(let a of n){let f=B.resolve(i,`layout.${a}`);if(yt.existsSync(f)){s=f;break}}return s?`import UserLayout from '${$(s)}';
56
+ export default UserLayout;`:`import { DefaultLayout } from 'boltdocs/client';
57
+ export default DefaultLayout;`}},transformIndexHtml:{order:"pre",handler(t){return ht(t,e)}},async closeBundle(){if(!l)return;let t=c?.build?.outDir?B.resolve(c.root,c.build.outDir):B.resolve(process.cwd(),"dist"),n=B.basename(i||"docs");await Y({docsDir:i,docsDirName:n,outDir:t,config:e});let{flushCache:s}=await import("../cache-7G6D532T.mjs");await s()}},Ut({includePublic:!0,png:{quality:80},jpeg:{quality:80},jpg:{quality:80},webp:{quality:80},avif:{quality:80},svg:{multipass:!0,plugins:[{name:"preset-default"}]}}),...u.filter(t=>!!t)]}import qt from"@mdx-js/rollup";import At from"remark-gfm";import Vt from"remark-frontmatter";import Wt from"rehype-slug";import Jt from"crypto";import{visit as Pt}from"unist-util-visit";import{createHighlighter as Xt}from"shiki";var U=null;async function vt(o){if(U)return U;let r=typeof o=="object"?[o.light,o.dark]:[o??"github-dark"];return["github-light","github-dark"].forEach(i=>{r.includes(i)||r.push(i)}),U=await Xt({themes:r,langs:["tsx","jsx","ts","js","json","md","mdx","css","html","bash","sh","yaml","yml"]}),U}function Kt(o){return async r=>{let i=o?.themeConfig?.codeTheme??{light:"github-light",dark:"github-dark"},p=await vt(i);Pt(r,["mdxJsxFlowElement","mdxJsxTextElement"],e=>{if(e.name!=="ComponentPreview")return;let c=e.attributes?.find(n=>n.name==="code"),l="";if(c){if(typeof c.value=="string")l=c.value;else if(c.value?.type==="mdxJsxAttributeValueExpression"){let n=c.value.value??"";l=n.match(/^[`'"](.+)[`'"]$/)?.[1]??n}}if(!l)return;let u=typeof i=="object"?{themes:{light:i.light,dark:i.dark},lang:"tsx"}:{theme:i,lang:"tsx"},t=p.codeToHtml(l,u);e.attributes=(e.attributes??[]).filter(n=>n.name!=="highlightedHtml"),e.attributes.push({type:"mdxJsxAttribute",name:"highlightedHtml",value:t})})}}function Zt(o){return async r=>{let i=o?.themeConfig?.codeTheme||{light:"github-light",dark:"github-dark"},p=await vt(i);Pt(r,"element",e=>{if(e.tagName==="pre"&&e.children?.[0]?.tagName==="code"){let c=e.children[0],u=(c.properties?.className||[]).find(f=>f.startsWith("language-")),t=u?u.slice(9):"text",n=c.children[0]?.value||"",s={lang:t};typeof i=="object"?s.themes={light:i.light,dark:i.dark}:s.theme=i;let a=p.codeToHtml(n,s);e.properties.dataHighlighted="true",e.properties.highlightedHtml=a,e.children=[]}})}}var Qt="v3",O=new at("mdx"),bt=!1;function Ct(o,r=qt){let i=o?.plugins?.flatMap(c=>c.remarkPlugins||[])||[],p=o?.plugins?.flatMap(c=>c.rehypePlugins||[])||[],e=r({remarkPlugins:[At,Vt,[Kt,o],...i],rehypePlugins:[Wt,[Zt,o],...p],jsxRuntime:"automatic",providerImportSource:"@mdx-js/react"});return e.isMock&&console.log("MDX PLUGIN IS MOCKED"),{...e,name:"vite-plugin-boltdocs-mdx",async buildStart(){q=0,A=0,bt||(O.load(),bt=!0),e.buildStart&&await e.buildStart.call(this)},async transform(c,l,u){if(!l.endsWith(".md")&&!l.endsWith(".mdx"))return e.transform?.call(this,c,l,u);console.log(`[boltdocs] Transforming MDX: ${l}`),A++;let t=Jt.createHash("md5").update(c).digest("hex"),n=`${l}:${t}:${Qt}`,s=O.get(n);if(s)return q++,{code:s,map:null};let a=await e.transform.call(this,c,l,u);return a&&typeof a=="object"&&a.code&&O.set(n,a.code),a},async buildEnd(){console.log(`[boltdocs] MDX Cache Performance: ${q}/${A} hits (${Math.round(q/A*100)||0}%)`),O.save(),await O.flush(),e.buildEnd&&await e.buildEnd.call(this)}}}var q=0,A=0;async function Yt(o){let r=o?.docsDir||"docs",i=await z(r);return[...xt(o,i),Ct(i)]}export{Yt as default,Y as generateStaticPages};
@@ -0,0 +1 @@
1
+ import{a as f}from"./chunk-H63UMKYF.mjs";import{h as g,i as h,j as u,k as m,l as S,m as d,n as p,o as y,p as D}from"./chunk-BQCD3DWG.mjs";import"./chunk-XEAPSFMB.mjs";import"./chunk-JZXLCA2E.mjs";import{useEffect as K,useCallback as M}from"react";import{useNavigate as R}from"react-router-dom";import{Fragment as T,jsx as o,jsxs as n}from"react/jsx-runtime";function N({routes:v}){let{isOpen:I,setIsOpen:a,query:w,setQuery:k,list:E}=f(v),r=R();K(()=>{let e=t=>{(/Mac/.test(navigator.userAgent)?t.metaKey:t.ctrlKey)&&(t.key==="k"||t.key==="j")&&(t.preventDefault(),a(i=>!i))};return window.addEventListener("keydown",e),()=>window.removeEventListener("keydown",e)},[a]);let l=M(e=>{let t=String(e);if(a(!1),t.includes("#")){let[s,c]=t.split("#");r(s),setTimeout(()=>{let i=document.getElementById(c);i&&i.scrollIntoView({behavior:"smooth"})},100)}else r(t)},[r,a]);return n(T,{children:[o(g.SearchTrigger,{onPress:()=>a(!0)}),o(h,{isOpen:I,onOpenChange:a,children:n(u,{onSelectionChange:l,children:[o(m,{value:w,onChange:e=>k(e.target.value)}),o(S,{items:E,children:e=>n(d,{onPress:()=>l(e.id),textValue:e.title,children:[o(p,{isHeading:e.isHeading}),n("div",{className:"flex flex-col justify-center gap-0.5",children:[o(y,{children:e.title}),o(D,{children:e.groupTitle})]})]},e.id)})]})})]})}export{N as SearchDialog};
@@ -0,0 +1,159 @@
1
+ import React__default from 'react';
2
+ import { B as BoltdocsConfig } from './config-CX4l-ZNp.js';
3
+
4
+ /**
5
+ * Metadata provided by the server for a specific route.
6
+ * Maps closely to the `RouteMeta` type in the Node environment.
7
+ */
8
+ interface ComponentRoute {
9
+ /** The final URL path */
10
+ path: string;
11
+ /** The absolute filesystem path of the source file */
12
+ componentPath: string;
13
+ /** The page title */
14
+ title: string;
15
+ /** Explicit order in the sidebar */
16
+ sidebarPosition?: number;
17
+ /** The relative path from the docs directory */
18
+ filePath: string;
19
+ /** The group directory name */
20
+ group?: string;
21
+ /** The display title of the group */
22
+ groupTitle?: string;
23
+ /** Explicit order of the group in the sidebar */
24
+ groupPosition?: number;
25
+ /** Extracted markdown headings for search indexing */
26
+ headings?: {
27
+ level: number;
28
+ text: string;
29
+ id: string;
30
+ }[];
31
+ /** The page summary or description */
32
+ description?: string;
33
+ /** The locale this route belongs to, if i18n is configured */
34
+ locale?: string;
35
+ /** The version this route belongs to, if versioning is configured */
36
+ version?: string;
37
+ /** Optional icon to display (Lucide icon name or raw SVG) */
38
+ icon?: string;
39
+ /** The tab this route belongs to, if tabs are configured */
40
+ tab?: string;
41
+ /** Optional badge to display next to the sidebar item */
42
+ badge?: string | {
43
+ text: 'updated' | 'new' | 'deprecated';
44
+ expires?: string;
45
+ };
46
+ /** Optional icon for the route's group */
47
+ groupIcon?: string;
48
+ /** The extracted plain-text content of the page for search indexing */
49
+ _content?: string;
50
+ /** The raw markdown content of the page */
51
+ _rawContent?: string;
52
+ }
53
+ /**
54
+ * Site configuration provided by the server.
55
+ */
56
+ type SiteConfig = BoltdocsConfig;
57
+ /**
58
+ * Configuration options for initializing the Boltdocs client app.
59
+ */
60
+ interface CreateBoltdocsAppOptions {
61
+ /** CSS selector for the DOM element where the app should mount (e.g. '#root') */
62
+ target: string;
63
+ /** Initial routes generated by the Vite plugin (`virtual:boltdocs-routes`) */
64
+ routes: ComponentRoute[];
65
+ /** The name of the documentation directory (e.g. 'docs') */
66
+ docsDirName: string;
67
+ /** Site configuration (`virtual:boltdocs-config`) */
68
+ config: SiteConfig;
69
+ /** Dynamic import mapping from `import.meta.glob` for the documentation pages */
70
+ modules: Record<string, () => Promise<{
71
+ default: React__default.ComponentType<any>;
72
+ }>>;
73
+ /** The `import.meta.hot` instance necessary for fast refresh/HMR updates */
74
+ hot?: {
75
+ accept: (cb?: (mod: any) => void) => void;
76
+ dispose: (cb: (data: any) => void) => void;
77
+ on: (event: string, cb: (data: any) => void) => void;
78
+ data: any;
79
+ };
80
+ /** Optional custom React component to render when visiting the root path ('/') */
81
+ homePage?: React__default.ComponentType;
82
+ /** Custom external pages mapped by their route path */
83
+ externalPages?: Record<string, React__default.ComponentType>;
84
+ /** Optional custom MDX components provided by plugins */
85
+ components?: Record<string, React__default.ComponentType>;
86
+ }
87
+ /**
88
+ * Types for CodeSandbox integration.
89
+ */
90
+ interface SandboxFile {
91
+ content: string | object;
92
+ isBinary?: boolean;
93
+ }
94
+ type SandboxFiles = Record<string, SandboxFile>;
95
+ interface SandboxOptions {
96
+ files?: SandboxFiles;
97
+ dependencies?: Record<string, string>;
98
+ devDependencies?: Record<string, string>;
99
+ title?: string;
100
+ description?: string;
101
+ template?: string;
102
+ /** The file path to open by default in the editor (e.g. `"src/App.tsx"`). */
103
+ entry?: string;
104
+ /** Options for the embedded iframe view, used by `embedSandbox()`. */
105
+ embed?: SandboxEmbedOptions;
106
+ /** Custom scripts for the package.json (e.g. `{ "start": "vite" }`). */
107
+ scripts?: Record<string, string>;
108
+ /** Optional default theme configuration for the sandbox project. */
109
+ themeConfig?: Record<string, unknown>;
110
+ }
111
+ interface SandboxEmbedOptions {
112
+ /** Which panel to display: `"editor"`, `"preview"`, or `"split"`. */
113
+ view?: 'editor' | 'preview' | 'split';
114
+ /** Color theme: `"dark"` or `"light"`. */
115
+ theme?: 'dark' | 'light';
116
+ /** Whether to hide the navigation bar in the embed. */
117
+ hideNavigation?: boolean;
118
+ }
119
+ /**
120
+ * Tab configuration for the documentation site.
121
+ */
122
+ interface BoltdocsTab {
123
+ id: string;
124
+ text: string;
125
+ icon?: string;
126
+ }
127
+ /**
128
+ * Props for the OnThisPage (TOC) component.
129
+ */
130
+ interface OnThisPageProps {
131
+ headings?: {
132
+ level: number;
133
+ text: string;
134
+ id: string;
135
+ }[];
136
+ editLink?: string;
137
+ communityHelp?: string;
138
+ filePath?: string;
139
+ }
140
+ /**
141
+ * Props for user-defined layout components (layout.tsx).
142
+ */
143
+ interface LayoutProps {
144
+ children: React__default.ReactNode;
145
+ }
146
+ /**
147
+ * Unified type for navbar links.
148
+ */
149
+ interface NavbarLink {
150
+ label: string;
151
+ href: string;
152
+ active: boolean;
153
+ /** Optional icon or string for external link indication */
154
+ to?: string;
155
+ /** Nested items for NavigationMenu */
156
+ items?: NavbarLink[];
157
+ }
158
+
159
+ export type { BoltdocsTab as B, ComponentRoute as C, LayoutProps as L, NavbarLink as N, OnThisPageProps as O, SandboxOptions as S, CreateBoltdocsAppOptions as a, SandboxEmbedOptions as b, SandboxFile as c, SandboxFiles as d };
@@ -0,0 +1,159 @@
1
+ import React__default from 'react';
2
+ import { B as BoltdocsConfig } from './config-CX4l-ZNp.mjs';
3
+
4
+ /**
5
+ * Metadata provided by the server for a specific route.
6
+ * Maps closely to the `RouteMeta` type in the Node environment.
7
+ */
8
+ interface ComponentRoute {
9
+ /** The final URL path */
10
+ path: string;
11
+ /** The absolute filesystem path of the source file */
12
+ componentPath: string;
13
+ /** The page title */
14
+ title: string;
15
+ /** Explicit order in the sidebar */
16
+ sidebarPosition?: number;
17
+ /** The relative path from the docs directory */
18
+ filePath: string;
19
+ /** The group directory name */
20
+ group?: string;
21
+ /** The display title of the group */
22
+ groupTitle?: string;
23
+ /** Explicit order of the group in the sidebar */
24
+ groupPosition?: number;
25
+ /** Extracted markdown headings for search indexing */
26
+ headings?: {
27
+ level: number;
28
+ text: string;
29
+ id: string;
30
+ }[];
31
+ /** The page summary or description */
32
+ description?: string;
33
+ /** The locale this route belongs to, if i18n is configured */
34
+ locale?: string;
35
+ /** The version this route belongs to, if versioning is configured */
36
+ version?: string;
37
+ /** Optional icon to display (Lucide icon name or raw SVG) */
38
+ icon?: string;
39
+ /** The tab this route belongs to, if tabs are configured */
40
+ tab?: string;
41
+ /** Optional badge to display next to the sidebar item */
42
+ badge?: string | {
43
+ text: 'updated' | 'new' | 'deprecated';
44
+ expires?: string;
45
+ };
46
+ /** Optional icon for the route's group */
47
+ groupIcon?: string;
48
+ /** The extracted plain-text content of the page for search indexing */
49
+ _content?: string;
50
+ /** The raw markdown content of the page */
51
+ _rawContent?: string;
52
+ }
53
+ /**
54
+ * Site configuration provided by the server.
55
+ */
56
+ type SiteConfig = BoltdocsConfig;
57
+ /**
58
+ * Configuration options for initializing the Boltdocs client app.
59
+ */
60
+ interface CreateBoltdocsAppOptions {
61
+ /** CSS selector for the DOM element where the app should mount (e.g. '#root') */
62
+ target: string;
63
+ /** Initial routes generated by the Vite plugin (`virtual:boltdocs-routes`) */
64
+ routes: ComponentRoute[];
65
+ /** The name of the documentation directory (e.g. 'docs') */
66
+ docsDirName: string;
67
+ /** Site configuration (`virtual:boltdocs-config`) */
68
+ config: SiteConfig;
69
+ /** Dynamic import mapping from `import.meta.glob` for the documentation pages */
70
+ modules: Record<string, () => Promise<{
71
+ default: React__default.ComponentType<any>;
72
+ }>>;
73
+ /** The `import.meta.hot` instance necessary for fast refresh/HMR updates */
74
+ hot?: {
75
+ accept: (cb?: (mod: any) => void) => void;
76
+ dispose: (cb: (data: any) => void) => void;
77
+ on: (event: string, cb: (data: any) => void) => void;
78
+ data: any;
79
+ };
80
+ /** Optional custom React component to render when visiting the root path ('/') */
81
+ homePage?: React__default.ComponentType;
82
+ /** Custom external pages mapped by their route path */
83
+ externalPages?: Record<string, React__default.ComponentType>;
84
+ /** Optional custom MDX components provided by plugins */
85
+ components?: Record<string, React__default.ComponentType>;
86
+ }
87
+ /**
88
+ * Types for CodeSandbox integration.
89
+ */
90
+ interface SandboxFile {
91
+ content: string | object;
92
+ isBinary?: boolean;
93
+ }
94
+ type SandboxFiles = Record<string, SandboxFile>;
95
+ interface SandboxOptions {
96
+ files?: SandboxFiles;
97
+ dependencies?: Record<string, string>;
98
+ devDependencies?: Record<string, string>;
99
+ title?: string;
100
+ description?: string;
101
+ template?: string;
102
+ /** The file path to open by default in the editor (e.g. `"src/App.tsx"`). */
103
+ entry?: string;
104
+ /** Options for the embedded iframe view, used by `embedSandbox()`. */
105
+ embed?: SandboxEmbedOptions;
106
+ /** Custom scripts for the package.json (e.g. `{ "start": "vite" }`). */
107
+ scripts?: Record<string, string>;
108
+ /** Optional default theme configuration for the sandbox project. */
109
+ themeConfig?: Record<string, unknown>;
110
+ }
111
+ interface SandboxEmbedOptions {
112
+ /** Which panel to display: `"editor"`, `"preview"`, or `"split"`. */
113
+ view?: 'editor' | 'preview' | 'split';
114
+ /** Color theme: `"dark"` or `"light"`. */
115
+ theme?: 'dark' | 'light';
116
+ /** Whether to hide the navigation bar in the embed. */
117
+ hideNavigation?: boolean;
118
+ }
119
+ /**
120
+ * Tab configuration for the documentation site.
121
+ */
122
+ interface BoltdocsTab {
123
+ id: string;
124
+ text: string;
125
+ icon?: string;
126
+ }
127
+ /**
128
+ * Props for the OnThisPage (TOC) component.
129
+ */
130
+ interface OnThisPageProps {
131
+ headings?: {
132
+ level: number;
133
+ text: string;
134
+ id: string;
135
+ }[];
136
+ editLink?: string;
137
+ communityHelp?: string;
138
+ filePath?: string;
139
+ }
140
+ /**
141
+ * Props for user-defined layout components (layout.tsx).
142
+ */
143
+ interface LayoutProps {
144
+ children: React__default.ReactNode;
145
+ }
146
+ /**
147
+ * Unified type for navbar links.
148
+ */
149
+ interface NavbarLink {
150
+ label: string;
151
+ href: string;
152
+ active: boolean;
153
+ /** Optional icon or string for external link indication */
154
+ to?: string;
155
+ /** Nested items for NavigationMenu */
156
+ items?: NavbarLink[];
157
+ }
158
+
159
+ export type { BoltdocsTab as B, ComponentRoute as C, LayoutProps as L, NavbarLink as N, OnThisPageProps as O, SandboxOptions as S, CreateBoltdocsAppOptions as a, SandboxEmbedOptions as b, SandboxFile as c, SandboxFiles as d };
@@ -0,0 +1,30 @@
1
+ import { B as BoltdocsConfig } from './config-CX4l-ZNp.mjs';
2
+ import { C as ComponentRoute } from './types-CvT-SGbK.mjs';
3
+
4
+ /**
5
+ * Hook to access the framework's routing state.
6
+ * Returns both the complete set of routes and a filtered list based on the current
7
+ * version and locale.
8
+ */
9
+ declare function useRoutes(): {
10
+ routes: ComponentRoute[];
11
+ allRoutes: ComponentRoute[];
12
+ currentRoute: ComponentRoute | undefined;
13
+ currentLocale: string | undefined;
14
+ currentLocaleLabel: string | undefined;
15
+ availableLocales: {
16
+ key: string;
17
+ label: string;
18
+ isCurrent: boolean;
19
+ }[];
20
+ currentVersion: string | undefined;
21
+ currentVersionLabel: string | undefined;
22
+ availableVersions: {
23
+ key: string;
24
+ label: string;
25
+ isCurrent: boolean;
26
+ }[];
27
+ config: BoltdocsConfig;
28
+ };
29
+
30
+ export { useRoutes as u };
@@ -0,0 +1,30 @@
1
+ import { B as BoltdocsConfig } from './config-CX4l-ZNp.js';
2
+ import { C as ComponentRoute } from './types-BuZWFT7r.js';
3
+
4
+ /**
5
+ * Hook to access the framework's routing state.
6
+ * Returns both the complete set of routes and a filtered list based on the current
7
+ * version and locale.
8
+ */
9
+ declare function useRoutes(): {
10
+ routes: ComponentRoute[];
11
+ allRoutes: ComponentRoute[];
12
+ currentRoute: ComponentRoute | undefined;
13
+ currentLocale: string | undefined;
14
+ currentLocaleLabel: string | undefined;
15
+ availableLocales: {
16
+ key: string;
17
+ label: string;
18
+ isCurrent: boolean;
19
+ }[];
20
+ currentVersion: string | undefined;
21
+ currentVersionLabel: string | undefined;
22
+ availableVersions: {
23
+ key: string;
24
+ label: string;
25
+ isCurrent: boolean;
26
+ }[];
27
+ config: BoltdocsConfig;
28
+ };
29
+
30
+ export { useRoutes as u };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "boltdocs",
3
- "version": "1.11.0",
3
+ "version": "2.0.0",
4
4
  "description": "A lightweight documentation generator for React projects.",
5
5
  "main": "dist/node/index.js",
6
6
  "module": "dist/node/index.mjs",
@@ -36,13 +36,6 @@
36
36
  },
37
37
  "./theme/neutral.css": "./src/client/theme/neutral.css"
38
38
  },
39
- "scripts": {
40
- "build": "tsup",
41
- "dev": "tsup --watch",
42
- "format": "pnpm exec biome format --write",
43
- "lint": "pnpm exec biome lint --write",
44
- "check": "pnpm exec biome check --write"
45
- },
46
39
  "keywords": [
47
40
  "docs",
48
41
  "documentation",
@@ -66,6 +59,7 @@
66
59
  "fast-glob": "^3.3.3",
67
60
  "github-slugger": "^2.0.0",
68
61
  "gray-matter": "^4.0.3",
62
+ "isomorphic-dompurify": "^3.7.1",
69
63
  "lucide-react": "^0.575.0",
70
64
  "react-aria-components": "^1.16.0",
71
65
  "react-router-dom": "^6.30.3",
@@ -85,7 +79,6 @@
85
79
  "react": "^19.1.0",
86
80
  "react-dom": "^19.1.0"
87
81
  },
88
- "packageManager": "pnpm@10.30.2",
89
82
  "devDependencies": {
90
83
  "@types/node": "^25.3.2",
91
84
  "@types/react": "^19.2.14",
@@ -93,5 +86,12 @@
93
86
  "@types/react-router-dom": "^5.3.3",
94
87
  "tsup": "^8.5.1",
95
88
  "typescript": "^5.9.3"
89
+ },
90
+ "scripts": {
91
+ "build": "tsup",
92
+ "dev": "tsup --watch",
93
+ "format": "pnpm exec biome format --write",
94
+ "lint": "pnpm exec biome lint --write",
95
+ "check": "pnpm exec biome check --write"
96
96
  }
97
- }
97
+ }
@@ -31,7 +31,7 @@ export function AppShell({
31
31
  initialRoutes: ComponentRoute[]
32
32
  initialConfig: BoltdocsConfig
33
33
  docsDirName: string
34
- modules: Record<string, () => Promise<{ default: React.ComponentType }>>
34
+ modules: Record<string, () => Promise<{ default: React.ComponentType<any> }>>
35
35
  hot?: CreateBoltdocsAppOptions['hot']
36
36
  homePage?: React.ComponentType
37
37
  externalPages?: Record<string, React.ComponentType>
@@ -50,15 +50,19 @@ export function AppShell({
50
50
  )
51
51
  .map((route) => {
52
52
  const loaderKey = Object.keys(modules).find(
53
- (k) => k === `/${docsDirName}/${route.filePath}`,
53
+ (k) =>
54
+ k === `/${docsDirName}/${route.filePath}` || // Vite dev/build relative path
55
+ k.endsWith(`/${docsDirName}/${route.filePath}`) || // SSG absolute path fallback
56
+ k.endsWith(`/${docsDirName}\\${route.filePath.replace(/\\/g, '/')}`), // Windows fallback
54
57
  )
55
58
  const loader = loaderKey ? modules[loaderKey] : null
56
59
 
57
60
  return {
58
61
  ...route,
59
- Component: React.lazy(() => {
60
- if (!loader) return Promise.resolve({ default: NotFound })
61
- return loader() as any
62
+ Component: React.lazy<React.ComponentType<any>>(async () => {
63
+ if (!loader) return { default: NotFound as React.ComponentType<any> }
64
+ const mod = await loader()
65
+ return mod
62
66
  }),
63
67
  }
64
68
  })
@@ -113,7 +117,6 @@ export function AppShell({
113
117
  ),
114
118
  )}
115
119
 
116
- {/* Documentation pages WITH sidebar + TOC layout */}
117
120
  <Route key="docs-layout" element={<DocsLayout />}>
118
121
  {resolvedRoutes.map((route) => (
119
122
  <Route
@@ -62,7 +62,7 @@ export interface CreateBoltdocsAppOptions {
62
62
  /** Site configuration (`virtual:boltdocs-config`) */
63
63
  config: SiteConfig
64
64
  /** Dynamic import mapping from `import.meta.glob` for the documentation pages */
65
- modules: Record<string, () => Promise<{ default: React.ComponentType }>>
65
+ modules: Record<string, () => Promise<{ default: React.ComponentType<any> }>>
66
66
  /** The `import.meta.hot` instance necessary for fast refresh/HMR updates */
67
67
  hot?: {
68
68
  accept: (cb?: (mod: any) => void) => void
@@ -262,7 +262,6 @@ export default DefaultLayout;`
262
262
  plugins: [
263
263
  {
264
264
  name: 'preset-default',
265
- params: { overrides: { removeViewBox: false } },
266
265
  },
267
266
  ] as any,
268
267
  },