boltdocs 3.0.2 → 3.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (123) hide show
  1. package/README.md +2 -18
  2. package/dist/{adapters-DEXNIv3x.mjs → adapters-ByYY44Zy.mjs} +1 -1
  3. package/dist/{adapters-C5AWWGfb.cjs → adapters-DvmtpdSF.cjs} +1 -1
  4. package/dist/{banner-CfdalYLL.d.ts → banner-BMop1KLF.d.ts} +2 -2
  5. package/dist/{banner-DNSkgUsO.d.cts → banner-CVD0GugR.d.cts} +2 -2
  6. package/dist/cache-CO4Dy2uQ.cjs +6 -0
  7. package/dist/cache-Dk53iOo6.mjs +6 -0
  8. package/dist/chunk-BFSpntXv.mjs +6 -0
  9. package/dist/{chunk-Ds5LZdWN.cjs → chunk-D1Md3oWO.cjs} +1 -1
  10. package/dist/client/index.cjs +433 -272
  11. package/dist/client/index.d.cts +129 -18
  12. package/dist/client/index.d.ts +129 -18
  13. package/dist/client/index.js +337 -178
  14. package/dist/client/mdx.cjs +1 -1
  15. package/dist/client/mdx.d.cts +1 -1
  16. package/dist/client/mdx.d.ts +1 -1
  17. package/dist/client/mdx.js +1 -1
  18. package/dist/client/primitives.cjs +7 -7
  19. package/dist/client/primitives.d.cts +5 -22
  20. package/dist/client/primitives.d.ts +5 -22
  21. package/dist/client/primitives.js +4 -4
  22. package/dist/client/theme/neutral.css +1 -3
  23. package/dist/client/theme/reset.css +31 -4
  24. package/dist/config-BpzaPsJj.d.cts +781 -0
  25. package/dist/config-CCXp3aXO.mjs +7 -0
  26. package/dist/{config-JGkMJoJQ.cjs → config-CMd4XoFq.cjs} +1 -1
  27. package/dist/config-DlGoEM9D.cjs +7 -0
  28. package/dist/config-xtS0ZkMm.d.mts +781 -0
  29. package/dist/{csp-CBysWlAf.cjs → csp-CRp_3U7a.cjs} +1 -1
  30. package/dist/csp-oTC2ygvF.mjs +6 -0
  31. package/dist/{docs-layout-6FQ8__ok.js → docs-layout-BdtZ9z6s.js} +9 -28
  32. package/dist/{docs-layout-3TpAt6MB.cjs → docs-layout-CFWI15Id.cjs} +69 -88
  33. package/dist/{doctor-BR1B2Mkz.cjs → doctor-BBtmNJE0.cjs} +1 -1
  34. package/dist/doctor-Bv16QSrI.cjs +7 -0
  35. package/dist/doctor-DOAbSaiL.mjs +7 -0
  36. package/dist/{generator-DtUU3Cfk.cjs → generator-COepVWGi.cjs} +1 -1
  37. package/dist/{handler-Btd4t_67.mjs → handler-DzQae4eA.mjs} +1 -1
  38. package/dist/{handler-Dzf4dSnV.cjs → handler-XX7cLTqe.cjs} +1 -1
  39. package/dist/headers-Ddwek8K7.mjs +6 -0
  40. package/dist/{headers-BXKxiPUv.cjs → headers-dg4SDrjY.cjs} +1 -1
  41. package/dist/{image-C9md50h2.js → image-Bz87fCla.js} +2 -2
  42. package/dist/{image-CR6UlaI5.cjs → image-C4TlpMHn.cjs} +18 -18
  43. package/dist/link-2PzgTnaP.js +673 -0
  44. package/dist/{icons-dev-BryEFkJu.cjs → link-D1Gjkb-2.cjs} +8 -353
  45. package/dist/{mdx-DhyMkc35.js → mdx-BuO6a1f7.js} +199 -40
  46. package/dist/{mdx-DJBg5DuL.cjs → mdx-CD-tSjRG.cjs} +237 -72
  47. package/dist/{meta-loader-C9MKjAs0.cjs → meta-loader-Dq1zcFnh.cjs} +1 -1
  48. package/dist/node/cache.cjs +6 -0
  49. package/dist/node/cache.d.cts +84 -0
  50. package/dist/node/cache.d.mts +84 -0
  51. package/dist/node/cache.mjs +6 -0
  52. package/dist/node/cli-entry.cjs +6 -6
  53. package/dist/node/cli-entry.mjs +9 -9
  54. package/dist/node/index.cjs +1 -1
  55. package/dist/node/index.d.cts +27 -638
  56. package/dist/node/index.d.mts +27 -640
  57. package/dist/node/index.mjs +1 -1
  58. package/dist/node/mdx/shiki-adapter.cjs +6 -0
  59. package/dist/node/mdx/shiki-adapter.d.cts +51 -0
  60. package/dist/node/mdx/shiki-adapter.d.mts +51 -0
  61. package/dist/node/mdx/shiki-adapter.mjs +6 -0
  62. package/dist/node-BXtqM1uH.mjs +6 -0
  63. package/dist/node-BlVk4EVg.cjs +104 -0
  64. package/dist/node-DOf4zhWc.mjs +104 -0
  65. package/dist/node-aD1eisrR.cjs +6 -0
  66. package/dist/{package-CEDhVAfO.cjs → package-BcISI5-P.cjs} +1 -1
  67. package/dist/{package-_dCCKVvG.mjs → package-CCYEAYeA.mjs} +1 -1
  68. package/dist/{pages-external-CX2uyW95.cjs → pages-external-XkYIs-d5.cjs} +1 -1
  69. package/dist/parser-DCiEWkSk.cjs +8 -0
  70. package/dist/parser-qk9FIHJ7.mjs +8 -0
  71. package/dist/plugin-C95kvu6h.mjs +73 -0
  72. package/dist/plugin-DM3u2bVj.cjs +73 -0
  73. package/dist/routes-BW6zsk7Z.mjs +6 -0
  74. package/dist/routes-BgoIB5wb.cjs +6 -0
  75. package/dist/{routes-BajCwrvX.cjs → routes-CORVxc02.cjs} +1 -1
  76. package/dist/{search-dialog-D4rplZMv.cjs → search-dialog-B1NERUNx.cjs} +101 -55
  77. package/dist/{search-dialog-Cx7aGW3U.cjs → search-dialog-BRFno7HD.cjs} +8 -8
  78. package/dist/{search-dialog-DDopgbKM.js → search-dialog-BmxHiKwt.js} +2 -2
  79. package/dist/{search-dialog-BNdRV60O.js → search-dialog-D6TvjcuV.js} +1 -1
  80. package/dist/{search-dialog-DaeSPvEo.js → search-dialog-DFnlx8LO.js} +44 -4
  81. package/dist/{search-dialog-CW1f6dn6.cjs → search-dialog-DHqwjJuG.cjs} +1 -1
  82. package/dist/server/index.cjs +1 -1
  83. package/dist/server/index.d.mts +1 -1
  84. package/dist/server/index.mjs +1 -1
  85. package/dist/shiki-adapter-CoQ6jyJ4.cjs +6 -0
  86. package/dist/shiki-adapter-D-aKw7PP.mjs +6 -0
  87. package/dist/sidebar-COTaMHR-.d.ts +1100 -0
  88. package/dist/sidebar-CrEdJuHX.d.cts +1100 -0
  89. package/dist/{types-generator-CYcHkDzZ.cjs → types-generator-BXhv7Ill.cjs} +1 -1
  90. package/dist/types-generator-bDPvUztF.mjs +26 -0
  91. package/dist/utils-Crm9oPcV.mjs +7 -0
  92. package/dist/utils-D6Xtj0FZ.cjs +7 -0
  93. package/package.json +26 -12
  94. package/src/shared/types.ts +532 -23
  95. package/dist/cache-DETwlACe.cjs +0 -6
  96. package/dist/cache-SF59enb3.mjs +0 -6
  97. package/dist/config-B5uVv5q4.cjs +0 -7
  98. package/dist/config-D3_zDkHh.mjs +0 -7
  99. package/dist/csp-gaZ51xzq.mjs +0 -6
  100. package/dist/doctor-3MheVMwd.mjs +0 -7
  101. package/dist/doctor-DQxLM202.cjs +0 -7
  102. package/dist/headers-CXyf0auY.mjs +0 -6
  103. package/dist/icons-dev-kJyGWNeg.js +0 -916
  104. package/dist/node-B9JSyEIU.mjs +0 -105
  105. package/dist/node-Cedquois.cjs +0 -105
  106. package/dist/parser-CNIPHx4s.cjs +0 -8
  107. package/dist/parser-D0QHIQsi.mjs +0 -8
  108. package/dist/plugin-WYNORxp1.cjs +0 -68
  109. package/dist/plugin-YWNVRpws.mjs +0 -68
  110. package/dist/rolldown-runtime-fkIsjY3S.mjs +0 -6
  111. package/dist/routes-CyrnmVuG.mjs +0 -6
  112. package/dist/routes-D6Tuu7Fs.cjs +0 -6
  113. package/dist/shiki-adapter-CGTmrR6S.cjs +0 -6
  114. package/dist/shiki-adapter-CXEGRnjr.mjs +0 -6
  115. package/dist/shiki-adapter-Mr8_oT_9.cjs +0 -6
  116. package/dist/sidebar-7gIifpBX.d.cts +0 -615
  117. package/dist/sidebar-BAKgJ-Er.d.ts +0 -615
  118. package/dist/types-generator-DVOnRVKU.mjs +0 -26
  119. package/dist/utils-B3xYMrpK.mjs +0 -7
  120. package/dist/utils-Bz1tG9Dg.cjs +0 -7
  121. /package/dist/{errors-C0Hx15Ag.mjs → errors-0zGHRLue.mjs} +0 -0
  122. /package/dist/{errors-Dx6JHoKE.cjs → errors-vKw8CkiX.cjs} +0 -0
  123. /package/dist/{index-CdJv4ocW.d.mts → index-1KsTDq4o.d.mts} +0 -0
@@ -2,18 +2,90 @@ import type { Plugin as VitePlugin } from 'vite'
2
2
  import type { ComponentType } from 'react'
3
3
 
4
4
  /**
5
- * Represents a single social link in the configuration.
5
+ * Metadata representing a single documentation route.
6
+ * This information is used to build the client-side router and the sidebar navigation.
6
7
  */
7
- export interface BoltdocsSocialLink {
8
- icon: 'discord' | 'x' | 'github' | 'bluesky' | string
9
- link: string
8
+ export interface RouteMeta {
9
+ /** The final URL path for the route (e.g., '/docs/guide/start') */
10
+ path: string
11
+ /** The absolute filesystem path to the source markdown/mdx file */
12
+ componentPath: string
13
+ /** The title of the page, usually extracted from frontmatter or the filename */
14
+ title: string
15
+ /** The relative path from the docs directory, used for edit links */
16
+ filePath: string
17
+ /** Optional description of the page (for SEO/meta tags) */
18
+ description?: string
19
+ /** Optional explicit position for ordering in the sidebar */
20
+ sidebarPosition?: number
21
+ /** The group (directory) this route belongs to */
22
+ group?: string
23
+ /** The display title for the route's group */
24
+ groupTitle?: string
25
+ /** Optional explicit position for ordering the group itself */
26
+ groupPosition?: number
27
+ /** Optional icon for the route's group */
28
+ groupIcon?: string
29
+ /** The sub-route group this route belongs to (from folders starting with _) */
30
+ subRouteGroup?: string
31
+ /** Extracted markdown headings for search indexing */
32
+ headings?: { level: number; text: string; id: 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 badge to display next to the sidebar item (e.g., 'New', 'Experimental') */
38
+ badge?: BadgeValue
39
+ /** Optional icon to display (Lucide icon name or raw SVG) */
40
+ icon?: string
41
+ /** The tab this route belongs to, if tabs are configured */
42
+ tab?: string
43
+ /** The collection this route belongs to (from [name] directories like [blog]) */
44
+ collection?: string
45
+ /** Tags for blog posts or other taxonomy */
46
+ tags?: string[]
47
+ /** Author identifier for blog posts */
48
+ author?: string
49
+ /** Draft flag — excluded from production builds */
50
+ draft?: boolean
51
+ /** Feature flags required for this page to be visible */
52
+ featureFlags?: string[]
53
+ /** Short excerpt/summary for list displays */
54
+ excerpt?: string
55
+ /** Cover image for blog posts */
56
+ coverImage?: string
57
+ /** The extracted plain-text content of the page for search indexing */
58
+ _content?: string
59
+ /** The raw markdown content of the page */
60
+ _rawContent?: string
61
+ /** Extracted SEO and Open Graph metadata from frontmatter */
62
+ seo?: Record<string, any>
63
+ /** The publication date */
64
+ date?: string | Date
65
+ /** The last updated timestamp or date */
66
+ lastUpdated?: string | number | Date
67
+ /** Optional category for the page */
68
+ category?: string
69
+ /** Optional explicit order (alternative to sidebarPosition) */
70
+ order?: number
71
+ /** Optional explicit label for the sidebar */
72
+ sidebarLabel?: string
73
+ /** Whether the page is hidden from the sidebar */
74
+ sidebarHidden?: boolean
75
+ /** Raw extensible frontmatter data for custom components and formatters */
76
+ frontmatter?: Record<string, any>
77
+ /** Optional recursive child routes for deep sidebar hierarchies */
78
+ subRoutes?: RouteMeta[]
79
+ /** Clean URL segments stripped of locale/version prefixes */
80
+ slugParts?: string[]
10
81
  }
11
82
 
12
83
  /**
13
- * Configuration for the site footer.
84
+ * Represents a single social link in the configuration.
14
85
  */
15
- export interface BoltdocsFooterConfig {
16
- text?: string
86
+ export interface BoltdocsSocialLink {
87
+ icon: 'discord' | 'x' | 'github' | 'bluesky' | string
88
+ link: string
17
89
  }
18
90
 
19
91
  /**
@@ -48,7 +120,6 @@ export interface BoltdocsThemeConfig {
48
120
  { title?: string | Record<string, string>; icon?: string }
49
121
  >
50
122
  socialLinks?: BoltdocsSocialLink[]
51
- footer?: BoltdocsFooterConfig
52
123
  editLink?: string
53
124
  communityHelp?: string
54
125
  version?: string
@@ -115,6 +186,44 @@ export interface BoltdocsVersionConfig {
115
186
  path: string
116
187
  }
117
188
 
189
+ /**
190
+ * Configuration for content collections (e.g. blog posts, changelog)
191
+ * declared in `boltdocs.config.ts`. Each entry maps a directory name
192
+ * (e.g. `[blog]`) to its display + ordering settings.
193
+ */
194
+ export interface BoltdocsCollectionsConfig {
195
+ /**
196
+ * Map of collection id (matches the bracketed directory name) to
197
+ * its display label. Falls back to the id when a label is missing.
198
+ */
199
+ labels?: Record<string, string | Record<string, string>>
200
+ /**
201
+ * Map of collection id to a numeric position used for sidebar ordering.
202
+ * Collections with no explicit position are sorted last.
203
+ */
204
+ positions?: Record<string, number>
205
+ /**
206
+ * Items-per-page for paginated collection routes (e.g. blog indexes).
207
+ * Falls back to the framework default (10) when omitted.
208
+ */
209
+ postsPerPage?: number
210
+ /**
211
+ * Default collection ID used by collection routing when no collection
212
+ * is explicitly referenced. Defaults to `'blog'`.
213
+ */
214
+ defaultCollection?: string
215
+ /**
216
+ * Date format string for rendering post dates in listing pages.
217
+ * Defaults to `'MMMM dd, yyyy'`.
218
+ */
219
+ dateFormat?: string
220
+ /**
221
+ * Field used to sort posts within a collection.
222
+ * Defaults to `'date'`.
223
+ */
224
+ sortBy?: 'date' | 'title' | 'sidebarPosition'
225
+ }
226
+
118
227
  /**
119
228
  * Configuration for documentation versioning.
120
229
  */
@@ -129,6 +238,385 @@ export interface BoltdocsVersionsConfig {
129
238
  */
130
239
  export type BadgeValue = string | { text: string; expires?: string }
131
240
 
241
+ /**
242
+ * Context provided to plugin lifecycle hooks.
243
+ */
244
+ export interface PluginContext {
245
+ readonly config: BoltdocsConfig
246
+ readonly logger: PluginLogger
247
+ readonly store: PluginStore
248
+ readonly meta: PluginMeta
249
+ readonly docsDir: string
250
+ readonly rootDir: string
251
+ readonly outDir: string
252
+ readonly routes: RouteMeta[]
253
+ /** Namespaced cache helpers bound to the core's cache machinery. */
254
+ readonly caches: PluginCachesAPI
255
+ /** Structured diagnostics channel; reports can be drained via `list()`. */
256
+ readonly diagnostics: PluginDiagnosticsAPI
257
+ /** Helpers for resolving paths inside the workspace safely. */
258
+ readonly paths: PluginPathsAPI
259
+ /** Declare virtual modules the core should expose to Vite. */
260
+ readonly virtualModules: PluginVirtualModulesAPI
261
+ /** Register and query transform middleware at runtime. */
262
+ readonly middleware: PluginMiddlewareAPI
263
+ /**
264
+ * Hook into dev-server file watching and send custom HMR events
265
+ * to connected clients.
266
+ */
267
+ readonly hmr: PluginHmrAPI
268
+ /**
269
+ * Register HTTP middleware and server lifecycle hooks without
270
+ * writing a Vite plugin.
271
+ */
272
+ readonly server: PluginServerAPI
273
+ }
274
+
275
+ /**
276
+ * Functional cache helpers exposed through `PluginContext.caches`.
277
+ *
278
+ * Plugin authors do not get a reference to the raw `TransformCache` /
279
+ * `FileCache` instances — those stay encapsulated in core. The methods
280
+ * returned here are bound to namespaced keys so two plugins cannot
281
+ * collide.
282
+ */
283
+ export interface PluginCachesAPI {
284
+ /** Sharded, hash-keyed cache. One namespace per plugin recommended. */
285
+ transform(namespace: string): PluginTransformCacheAPI
286
+ /** Routes cache wrapper around the parsed-doc cache. */
287
+ routes: PluginRoutesCacheAPI
288
+ /** In-memory LRU cache keyed by namespace + plugin-supplied key. */
289
+ memory<V = unknown>(
290
+ namespace: string,
291
+ opts?: { max?: number; ttl?: number },
292
+ ): PluginMemoryCacheAPI<V>
293
+ }
294
+
295
+ export interface PluginTransformCacheAPI {
296
+ /** Async read — first call may warm from disk if the entry was evicted. */
297
+ get(key: string): Promise<string | null>
298
+ /** Synchronous write that batches a background disk flush. */
299
+ set(key: string, value: string): void
300
+ /** Force-flush background writes. Call before measuring disk state. */
301
+ flush(): Promise<void>
302
+ }
303
+
304
+ export interface PluginRoutesCacheAPI {
305
+ /** Read a parsed `RouteMeta` (and its private `_content` blob) by abs file path. */
306
+ get(filePath: string): RouteMeta | null
307
+ /** Write a parsed route entry. Caller assumptions match `docCache.set`. */
308
+ set(filePath: string, route: RouteMeta): void
309
+ /** Invalidate one route. Use when content changes. */
310
+ invalidate(filePath: string): void
311
+ /** Clear every cached route. Use when the directory layout changes. */
312
+ invalidateAll(): void
313
+ }
314
+
315
+ export interface PluginMemoryCacheAPI<V> {
316
+ get(key: string): V | undefined
317
+ set(key: string, value: V): void
318
+ has(key: string): boolean
319
+ }
320
+
321
+ /**
322
+ * Plugin diagnostics API.
323
+ *
324
+ * Plugins push structured records instead of spamming the logger; downstream
325
+ * tools (dev-server overlay, CI reporters, IDE plugins) drain the queue via
326
+ * `list()`.
327
+ */
328
+ export interface DiagnosticRecord {
329
+ readonly id: number
330
+ readonly severity: 'info' | 'warn' | 'error'
331
+ readonly code: string
332
+ readonly message: string
333
+ readonly pluginName: string
334
+ readonly filePath?: string
335
+ readonly routePath?: string
336
+ readonly time: Date
337
+ }
338
+
339
+ export interface PluginDiagnosticsAPI {
340
+ report(
341
+ severity: DiagnosticRecord['severity'],
342
+ code: string,
343
+ message: string,
344
+ where?: { filePath?: string; routePath?: string },
345
+ ): void
346
+ list(): readonly DiagnosticRecord[]
347
+ clear(): void
348
+ }
349
+
350
+ /**
351
+ * Path-resolution helpers exposed through `PluginContext.paths`.
352
+ *
353
+ * Both `resolveDocs` and `resolveAsset` validate the resulting path against
354
+ * the workspace boundary and reject any segment that resolves outside the
355
+ * docs / project root directories.
356
+ */
357
+ export interface PluginPathsAPI {
358
+ resolveDocs(...parts: string[]): string
359
+ resolveAsset(...parts: string[]): string
360
+ /**
361
+ * Build a `file://` URL for an absolute path inside the workspace.
362
+ * Useful for `new URL(import.meta.url)` replacements and image srcsets.
363
+ */
364
+ safeFileURL(absFilePath: string): string
365
+ }
366
+
367
+ /**
368
+ * Plugin virtual-modules registration.
369
+ *
370
+ * Plugins call `add(id, loader)` to expose a `virtual:<plugin>/<id>` module
371
+ * to Vite without having to author a full Vite plugin. The loader returns
372
+ * the module source code as a string; the core wraps it in the right
373
+ * `resolveId`/`load` plumbing at Vite build time.
374
+ */
375
+ export interface RegisteredVirtualModule {
376
+ readonly id: string
377
+ readonly eager: boolean
378
+ readonly loader: () => string | Promise<string>
379
+ }
380
+
381
+ export interface PluginVirtualModulesAPI {
382
+ add(
383
+ id: string,
384
+ loader: () => string | Promise<string>,
385
+ opts?: { eager?: boolean },
386
+ ): void
387
+ has(id: string): boolean
388
+ list(): readonly RegisteredVirtualModule[]
389
+ }
390
+
391
+ /**
392
+ * Logger interface for plugin logging.
393
+ */
394
+ export interface PluginLogger {
395
+ info(message: string): void
396
+ warn(message: string): void
397
+ error(message: string | Error): void
398
+ debug(message: string): void
399
+ }
400
+
401
+ /**
402
+ * Key-value store interface for plugins.
403
+ */
404
+ export interface PluginStore {
405
+ get<T = unknown>(pluginName: string, key: string): T | undefined
406
+ set(pluginName: string, key: string, value: unknown): void
407
+ has(pluginName: string, key: string): boolean
408
+ }
409
+
410
+ /**
411
+ * Plugin metadata provided in the context.
412
+ */
413
+ export interface PluginMeta {
414
+ name: string
415
+ version?: string
416
+ boltdocsVersion?: string
417
+ }
418
+
419
+ /**
420
+ * Chain control signal returned by transform hooks. Use with `__signal` in
421
+ * the return value to influence the middleware chain:
422
+ *
423
+ * - `'skip'`: stop processing this hook for the current file (remaining
424
+ * plugins in the chain still run).
425
+ * - `'break'`: stop the entire chain immediately — no further plugin's
426
+ * transform hooks run for this file.
427
+ *
428
+ * @example
429
+ * ```ts
430
+ * transformMdx: async (_ctx, { code }) => ({
431
+ * code: code.replace(/foo/g, 'bar'),
432
+ * __signal: 'skip', // skip remaining plugins
433
+ * })
434
+ * ```
435
+ */
436
+ export type ChainSignal = 'skip' | 'break'
437
+
438
+ /**
439
+ * Returned by a transform hook that wants to signal the chain. The `__signal`
440
+ * field is optional — most hooks will just return `{ code: string }` and the
441
+ * chain continues normally. When `__signal` is present, `runChain` reacts:
442
+ *
443
+ * - `'skip'` continues with the next plugin, but passes the **original params**
444
+ * (the output of this hook is discarded).
445
+ * - `'break'` stops the chain immediately.
446
+ *
447
+ * @template T The params shape (e.g. `{ code: string; filePath: string }`).
448
+ */
449
+ export type TransformResult<T> = T & { __signal?: ChainSignal }
450
+
451
+ /**
452
+ * Enriched params passed to `transformSource` and `transformMdx`. The `code`
453
+ * and `filePath` fields are always present. The optional `frontmatter` and
454
+ * `route` fields are populated when available (they are `undefined` in the
455
+ * early pipeline where frontmatter hasn't been parsed yet).
456
+ */
457
+ export interface TransformSourceParams {
458
+ /** The raw or compiled code (source before MDX / JS after MDX). */
459
+ code: string
460
+ /** Absolute file path of the source document. */
461
+ filePath: string
462
+ /** Parsed frontmatter, if available. `undefined` in very early pipeline. */
463
+ frontmatter?: Record<string, unknown>
464
+ }
465
+
466
+ /**
467
+ * Enriched params passed to `transformHtml`. The `html` and `path` fields
468
+ * are always present. The optional `route` carries the generated `RouteMeta`
469
+ * for richer context (locale, version, collection, etc.).
470
+ */
471
+ export interface TransformHtmlParams {
472
+ /** The rendered HTML string for this page. */
473
+ html: string
474
+ /** The route path (e.g. `/docs/guides/start`). */
475
+ path: string
476
+ /** The route metadata for the page, if available. */
477
+ route?: RouteMeta
478
+ }
479
+
480
+ /**
481
+ * Plugin transform middleware. Each middleware runs in the transform
482
+ * pipeline alongside lifecycle hooks. The `name` field is optional —
483
+ * when omitted, the owning plugin's name is used as context.
484
+ * Middleware runs in `enforce` order (pre → normal → post) and supports
485
+ * `__signal: 'skip'` / `__signal: 'break'` for chain control.
486
+ */
487
+ export interface PluginTransformMiddleware {
488
+ /** Optional name. Defaults to the owning plugin's name for diagnostics. */
489
+ name?: string
490
+ enforce?: 'pre' | 'post'
491
+ transformSource?: (
492
+ ctx: PluginContext,
493
+ params: TransformSourceParams,
494
+ ) =>
495
+ | TransformResult<{ code: string }>
496
+ | Promise<TransformResult<{ code: string }>>
497
+ transformMdx?: (
498
+ ctx: PluginContext,
499
+ params: TransformSourceParams,
500
+ ) =>
501
+ | TransformResult<{ code: string }>
502
+ | Promise<TransformResult<{ code: string }>>
503
+ transformHtml?: (
504
+ ctx: PluginContext,
505
+ params: TransformHtmlParams,
506
+ ) =>
507
+ | TransformResult<{ html: string }>
508
+ | Promise<TransformResult<{ html: string }>>
509
+ }
510
+
511
+ /**
512
+ * Plugin middleware registry API exposed through `PluginContext.middleware`.
513
+ * Plugins can register named middleware entries from lifecycle hooks.
514
+ */
515
+ export interface PluginMiddlewareAPI {
516
+ add(middleware: PluginTransformMiddleware): void
517
+ remove(name: string): void
518
+ has(name: string): boolean
519
+ list(): readonly PluginTransformMiddleware[]
520
+ }
521
+
522
+ /**
523
+ * HMR event types plugins can listen to.
524
+ */
525
+ export type PluginHmrEvent = 'add' | 'change' | 'unlink'
526
+
527
+ /**
528
+ * Plugin HMR API — hook into file-watching events and send custom
529
+ * HMR messages to connected clients.
530
+ */
531
+ export interface PluginHmrAPI {
532
+ /**
533
+ * Register a callback for file events scoped to the docs directory.
534
+ * The callback receives the normalized file path and event type.
535
+ */
536
+ onFileEvent(
537
+ eventType: PluginHmrEvent,
538
+ handler: (filePath: string) => void | Promise<void>,
539
+ ): void
540
+ /** Shorthand for `onFileEvent('add', handler)`. */
541
+ onFileAdd(handler: (filePath: string) => void | Promise<void>): void
542
+ /** Shorthand for `onFileEvent('change', handler)`. */
543
+ onFileChange(handler: (filePath: string) => void | Promise<void>): void
544
+ /** Shorthand for `onFileEvent('unlink', handler)`. */
545
+ onFileUnlink(handler: (filePath: string) => void | Promise<void>): void
546
+ /**
547
+ * Send a custom HMR event to all connected clients.
548
+ * The client can listen with `import.meta.hot.on('boltdocs:plugin:<name>', ...)`.
549
+ */
550
+ send(event: string, data?: unknown): void
551
+ }
552
+
553
+ /**
554
+ * Plugin Server API — register HTTP middleware and lifecycle hooks
555
+ * for the dev server and preview server, without writing a Vite plugin.
556
+ */
557
+ export interface PluginServerAPI {
558
+ /**
559
+ * Register a Connect-style middleware function.
560
+ * Runs on both dev and preview servers.
561
+ */
562
+ use(middleware: PluginServerMiddleware): void
563
+ /**
564
+ * Register a middleware scoped to a specific path prefix.
565
+ * Only requests starting with `path` trigger the handler.
566
+ */
567
+ useAt(path: string, handler: PluginServerMiddleware): void
568
+ /** Called when the dev/preview server starts (once per process). */
569
+ onStart(callback: () => void | Promise<void>): void
570
+ /** Called when the server shuts down (cleanup). */
571
+ onEnd(callback: () => void | Promise<void>): void
572
+ }
573
+
574
+ /**
575
+ * Connect-style middleware signature.
576
+ */
577
+ export type PluginServerMiddleware = (
578
+ req: import('http').IncomingMessage,
579
+ res: import('http').ServerResponse,
580
+ next: (err?: unknown) => void,
581
+ ) => void | Promise<void>
582
+
583
+ /**
584
+ * Plugin lifecycle hooks with full type safety.
585
+ */
586
+ export interface PluginLifecycleHooks {
587
+ beforeBuild?: (ctx: PluginContext) => Promise<void> | void
588
+ afterBuild?: (ctx: PluginContext) => Promise<void> | void
589
+ beforeDev?: (ctx: PluginContext) => Promise<void> | void
590
+ afterDev?: (ctx: PluginContext) => Promise<void> | void
591
+ buildEnd?: (ctx: PluginContext) => Promise<void> | void
592
+ transformSource?: (
593
+ ctx: PluginContext,
594
+ params: TransformSourceParams,
595
+ ) =>
596
+ | TransformResult<{ code: string }>
597
+ | Promise<TransformResult<{ code: string }>>
598
+ transformMdx?: (
599
+ ctx: PluginContext,
600
+ params: TransformSourceParams,
601
+ ) =>
602
+ | TransformResult<{ code: string }>
603
+ | Promise<TransformResult<{ code: string }>>
604
+ transformHtml?: (
605
+ ctx: PluginContext,
606
+ params: TransformHtmlParams,
607
+ ) =>
608
+ | TransformResult<{ html: string }>
609
+ | Promise<TransformResult<{ html: string }>>
610
+ }
611
+
612
+ /**
613
+ * MDX processor configuration.
614
+ * When `processor` is set to 'satteri', the Sätteri Rust-based compiler is used.
615
+ */
616
+ export interface BoltdocsMdxConfig {
617
+ processor?: 'unified' | 'satteri'
618
+ }
619
+
132
620
  /**
133
621
  * Defines a Boltdocs plugin.
134
622
  *
@@ -144,23 +632,22 @@ export interface BoltdocsPlugin {
144
632
  rehypePlugins?: unknown[]
145
633
  vitePlugins?: VitePlugin[]
146
634
  components?: Record<string, string>
147
- /** Lifecycle hooks — use the `PluginLifecycleHooks` type from the node API. */
148
- hooks?: Record<string, (ctx: unknown) => Promise<void> | void>
635
+ /** Optional runtime metadata exposed to client via useConfig().plugins[].metadata */
636
+ metadata?: Record<string, unknown>
637
+ /** Declarative transform middleware entries. */
638
+ middleware?: PluginTransformMiddleware[]
639
+ /** Lifecycle hooks with full type safety */
640
+ hooks?: PluginLifecycleHooks
149
641
  }
150
642
 
151
643
  /**
152
- * Configuration for the collections (blog) feature.
153
644
  */
154
- export interface BoltdocsCollectionsConfig {
155
- /** Number of posts per page in collection listing pages. Defaults to 10. */
156
- postsPerPage?: number
157
- /** The name of the default collection used by BlogList when none is specified. */
158
- defaultCollection?: string
159
- /** Date format string for rendering post dates (e.g., 'MMMM dd, yyyy'). */
160
- dateFormat?: string
161
- /** Field to sort posts by. Defaults to 'date'. */
162
- sortBy?: 'date' | 'title' | 'sidebarPosition'
163
- }
645
+
646
+ /**
647
+ */
648
+
649
+ /**
650
+ */
164
651
 
165
652
  export interface BoltdocsSecurityConfig {
166
653
  headers?: Record<string, string>
@@ -258,11 +745,21 @@ export interface BoltdocsVercelConfig {
258
745
  speedInsights?: boolean
259
746
  }
260
747
 
748
+ export interface BoltdocsPostHogConfig {
749
+ apiKey: string
750
+ host?: string
751
+ capturePageview?: boolean
752
+ capturePageleave?: boolean
753
+ sessionRecording?: boolean
754
+ autocapture?: boolean
755
+ }
756
+
261
757
  export interface BoltdocsIntegrationsConfig {
262
758
  analytics?: {
263
759
  ga4?: BoltdocsGA4Config
264
760
  vercel?: BoltdocsVercelConfig
265
761
  gtm?: BoltdocsGTMConfig
762
+ posthog?: BoltdocsPostHogConfig
266
763
  }
267
764
  search?: {
268
765
  algolia?: BoltdocsAlgoliaConfig
@@ -273,6 +770,16 @@ export interface BoltdocsIntegrationsConfig {
273
770
  }
274
771
  }
275
772
 
773
+ /**
774
+ * Configuration for drafts visibility control.
775
+ */
776
+ export interface BoltdocsDraftsConfig {
777
+ /** If true, drafts are visible in all environments. Default: false */
778
+ visible?: boolean
779
+ /** Environments where drafts are visible (e.g. ['development', 'staging']). Default: [] */
780
+ environments?: string[]
781
+ }
782
+
276
783
  /**
277
784
  * The root configuration object for Boltdocs.
278
785
  */
@@ -283,12 +790,15 @@ export interface BoltdocsConfig {
283
790
  theme?: BoltdocsThemeConfig
284
791
  i18n?: BoltdocsI18nConfig
285
792
  versions?: BoltdocsVersionsConfig
793
+ mdx?: BoltdocsMdxConfig
286
794
  plugins?: BoltdocsPlugin[]
287
795
  collections?: BoltdocsCollectionsConfig
288
796
  robots?: BoltdocsRobotsConfig
289
797
  security?: BoltdocsSecurityConfig
290
798
  seo?: BoltdocsSeoConfig
291
799
  integrations?: BoltdocsIntegrationsConfig
800
+ drafts?: BoltdocsDraftsConfig
801
+ featureFlags?: Record<string, boolean | string>
292
802
  directoryMeta?: Record<string, unknown>
293
803
  vite?: unknown
294
804
  }
@@ -339,7 +849,6 @@ export type BoltdocsMdxComponents = Boltdocs.Types extends {
339
849
  MdxComponents: infer M
340
850
  }
341
851
  ? TransformMdxComponents<UnpackMdxComponents<M>>
342
- : {
343
- [key: string]: ComponentType<any>
852
+ : Omit<Record<string, ComponentType<any>>, 'Frontmatter'> & {
344
853
  Frontmatter: Record<string, ComponentType<any>>
345
854
  }
@@ -1,6 +0,0 @@
1
- /**
2
- * Boltdocs - https://boltdocs.vercel.app
3
- * Copyright (c) 2026 Jesus Alcala
4
- * Licensed under the MIT License.
5
- */
6
- const e=require(`./chunk-Ds5LZdWN.cjs`),t=require(`./utils-Bz1tG9Dg.cjs`);let n=require(`node:path`);n=e.n(n);let r=require(`node:fs`);r=e.n(r);let i=require(`node:fs/promises`);i=e.n(i);let a=require(`node:crypto`);a=e.n(a);let o=require(`node:zlib`);o=e.n(o);let s=require(`node:util`),c=require(`lru-cache`);const l=i.default.writeFile,u=i.default.readFile,d=i.default.mkdir,f=i.default.rename,p=(0,s.promisify)(o.default.gzip),m=(0,s.promisify)(o.default.gunzip),h=new class{activeTasks=new Set;add(e){let t=Promise.resolve().then(e).catch(()=>{}).finally(()=>{this.activeTasks.delete(t)});this.activeTasks.add(t)}async flush(){await Promise.all(Array.from(this.activeTasks))}get pending(){return this.activeTasks.size}};var g=class{entries=new Map;cachePath=null;compress;constructor(e={}){let r=t.o();if(this.compress=e.compress===void 0?r.compress:e.compress,e.name){let t=e.root||process.cwd(),i=this.compress?`json.gz`:`json`;this.cachePath=n.default.resolve(t,r.dir,`${e.name}.${i}`)}}async load(){if(!t.o().noCache&&this.cachePath)try{let e=await u(this.cachePath);this.cachePath.endsWith(`.gz`)&&(e=await m(e));let t=JSON.parse(e.toString(`utf-8`));this.entries=new Map(Object.entries(t))}catch(e){if(e.code===`ENOENT`)return}}save(){if(t.o().noCache||!this.cachePath)return;let e=Object.fromEntries(this.entries),r=JSON.stringify(e),i=this.cachePath,o=this.compress;h.add(async()=>{try{await d(n.default.dirname(i),{recursive:!0});let e=Buffer.from(r);o&&(e=await p(e));let t=`${i}.${a.default.randomBytes(4).toString(`hex`)}.tmp`;await l(t,e),await f(t,i)}catch{}})}get(e){let n=this.entries.get(e);return!n||t.s(e)!==n.mtime?null:n.data}getStale(e){let t=this.entries.get(e);return t?t.data:null}set(e,n){this.entries.set(e,{data:n,mtime:t.s(e)})}isValid(e){let n=this.entries.get(e);return n?t.s(e)===n.mtime:!1}invalidate(e){this.entries.delete(e)}invalidateAll(){this.entries.clear()}pruneStale(e){for(let t of this.entries.keys())e.has(t)||this.entries.delete(t)}get size(){return this.entries.size}async flush(){await h.flush()}},_=class{index=new Map;memoryCache;baseDir;shardsDir;indexPath;saveTimeout=null;constructor(e,r=process.cwd()){let i=t.o();this.baseDir=n.default.resolve(r,i.dir,`transform-${e}`),this.shardsDir=n.default.resolve(this.baseDir,`shards`),this.indexPath=n.default.resolve(this.baseDir,`index.json`),this.memoryCache=new c.LRUCache({max:i.lruLimit,ttl:i.lruTTL,updateAgeOnGet:!0})}async load(){if(!t.o().noCache)try{let e=await u(this.indexPath,`utf-8`);this.index=new Map(Object.entries(JSON.parse(e)))}catch(e){if(e.code===`ENOENT`)return}}save(){if(t.o().noCache)return;let e=JSON.stringify(Object.fromEntries(this.index)),r=this.indexPath;h.add(async()=>{try{await d(n.default.dirname(r),{recursive:!0}),await l(r,e)}catch{}})}async getMany(e){let t=new Map,r=[];for(let n of e){let e=this.memoryCache.get(n);e?t.set(n,e):this.index.has(n)&&r.push(n)}if(r.length>0){let e=await Promise.all(r.map(async e=>{let t=this.index.get(e),r=n.default.resolve(this.shardsDir,`${t}.gz`);try{let t=(await m(await u(r))).toString(`utf-8`);return this.memoryCache.set(e,t),{key:e,val:t}}catch{return null}}));for(let n of e)n&&t.set(n.key,n.val)}return t}async getAsync(e){let t=this.memoryCache.get(e);if(t)return t;let r=this.index.get(e);if(!r)return null;let i=n.default.resolve(this.shardsDir,`${r}.gz`);try{let t=(await m(await u(i))).toString(`utf-8`);return this.memoryCache.set(e,t),t}catch(e){return e.code,null}}set(e,t){let r=a.default.createHash(`md5`).update(t).digest(`hex`);this.index.set(e,r),this.memoryCache.set(e,t);let o=n.default.resolve(this.shardsDir,`${r}.gz`);h.add(async()=>{try{try{await i.default.access(o);return}catch{}await d(this.shardsDir,{recursive:!0});let e=await p(Buffer.from(t)),n=`${o}.${a.default.randomBytes(4).toString(`hex`)}.tmp`;await l(n,e),await f(n,o)}catch{}}),this.saveTimeout&&clearTimeout(this.saveTimeout),this.saveTimeout=setTimeout(()=>{this.save()},500),typeof this.saveTimeout.unref==`function`&&this.saveTimeout.unref()}get size(){return this.index.size}async flush(){await h.flush()}};async function v(){await h.flush()}const y=new Map,b=()=>{let e=t.o();return n.default.resolve(process.cwd(),e.dir,`parser`)},x=`v2.5`;var S=class{static async get(e){if(t.o().noCache)return null;try{let t=await r.default.promises.stat(e),i=y.get(e);if(i&&i.mtime===t.mtimeMs)return i.data;let o=b(),s=a.default.createHash(`md5`).update(e).digest(`hex`),c=n.default.join(o,`${s}.json`);try{let n=await r.default.promises.readFile(c,`utf-8`),i=JSON.parse(n);return i._mtime!==t.mtimeMs||i._v!==x?null:(y.set(e,{data:i.data,mtime:i._mtime}),i.data)}catch{return null}}catch{return null}}static async set(e,i){if(!t.o().noCache)try{let t=await r.default.promises.stat(e);y.set(e,{data:i,mtime:t.mtimeMs});let o=b(),s=a.default.createHash(`md5`).update(e).digest(`hex`),c=n.default.join(o,`${s}.json`),l={_v:x,_mtime:t.mtimeMs,data:i};h.add(async()=>{try{await r.default.promises.mkdir(o,{recursive:!0}),await r.default.promises.writeFile(c,JSON.stringify(l))}catch{}})}catch{}}static invalidate(e){y.delete(e)}static clear(){y.clear();let e=b();if(r.default.existsSync(e))try{r.default.rmSync(e,{recursive:!0,force:!0})}catch{}}};Object.defineProperty(exports,`i`,{enumerable:!0,get:function(){return v}}),Object.defineProperty(exports,`n`,{enumerable:!0,get:function(){return g}}),Object.defineProperty(exports,`r`,{enumerable:!0,get:function(){return _}}),Object.defineProperty(exports,`t`,{enumerable:!0,get:function(){return S}});
@@ -1,6 +0,0 @@
1
- /**
2
- * Boltdocs - https://boltdocs.vercel.app
3
- * Copyright (c) 2026 Jesus Alcala
4
- * Licensed under the MIT License.
5
- */
6
- import{o as e,s as t}from"./utils-B3xYMrpK.mjs";import n from"node:path";import r from"node:fs";import i from"node:fs/promises";import a from"node:crypto";import o from"node:zlib";import{promisify as s}from"node:util";import{LRUCache as c}from"lru-cache";const l=i.writeFile,u=i.readFile,d=i.mkdir,f=i.rename,p=s(o.gzip),m=s(o.gunzip),h=new class{activeTasks=new Set;add(e){let t=Promise.resolve().then(e).catch(()=>{}).finally(()=>{this.activeTasks.delete(t)});this.activeTasks.add(t)}async flush(){await Promise.all(Array.from(this.activeTasks))}get pending(){return this.activeTasks.size}};var g=class{entries=new Map;cachePath=null;compress;constructor(t={}){let r=e();if(this.compress=t.compress===void 0?r.compress:t.compress,t.name){let e=t.root||process.cwd(),i=this.compress?`json.gz`:`json`;this.cachePath=n.resolve(e,r.dir,`${t.name}.${i}`)}}async load(){if(!e().noCache&&this.cachePath)try{let e=await u(this.cachePath);this.cachePath.endsWith(`.gz`)&&(e=await m(e));let t=JSON.parse(e.toString(`utf-8`));this.entries=new Map(Object.entries(t))}catch(e){if(e.code===`ENOENT`)return}}save(){if(e().noCache||!this.cachePath)return;let t=Object.fromEntries(this.entries),r=JSON.stringify(t),i=this.cachePath,o=this.compress;h.add(async()=>{try{await d(n.dirname(i),{recursive:!0});let e=Buffer.from(r);o&&(e=await p(e));let t=`${i}.${a.randomBytes(4).toString(`hex`)}.tmp`;await l(t,e),await f(t,i)}catch{}})}get(e){let n=this.entries.get(e);return!n||t(e)!==n.mtime?null:n.data}getStale(e){let t=this.entries.get(e);return t?t.data:null}set(e,n){this.entries.set(e,{data:n,mtime:t(e)})}isValid(e){let n=this.entries.get(e);return n?t(e)===n.mtime:!1}invalidate(e){this.entries.delete(e)}invalidateAll(){this.entries.clear()}pruneStale(e){for(let t of this.entries.keys())e.has(t)||this.entries.delete(t)}get size(){return this.entries.size}async flush(){await h.flush()}},_=class{index=new Map;memoryCache;baseDir;shardsDir;indexPath;saveTimeout=null;constructor(t,r=process.cwd()){let i=e();this.baseDir=n.resolve(r,i.dir,`transform-${t}`),this.shardsDir=n.resolve(this.baseDir,`shards`),this.indexPath=n.resolve(this.baseDir,`index.json`),this.memoryCache=new c({max:i.lruLimit,ttl:i.lruTTL,updateAgeOnGet:!0})}async load(){if(!e().noCache)try{let e=await u(this.indexPath,`utf-8`);this.index=new Map(Object.entries(JSON.parse(e)))}catch(e){if(e.code===`ENOENT`)return}}save(){if(e().noCache)return;let t=JSON.stringify(Object.fromEntries(this.index)),r=this.indexPath;h.add(async()=>{try{await d(n.dirname(r),{recursive:!0}),await l(r,t)}catch{}})}async getMany(e){let t=new Map,r=[];for(let n of e){let e=this.memoryCache.get(n);e?t.set(n,e):this.index.has(n)&&r.push(n)}if(r.length>0){let e=await Promise.all(r.map(async e=>{let t=this.index.get(e),r=n.resolve(this.shardsDir,`${t}.gz`);try{let t=(await m(await u(r))).toString(`utf-8`);return this.memoryCache.set(e,t),{key:e,val:t}}catch{return null}}));for(let n of e)n&&t.set(n.key,n.val)}return t}async getAsync(e){let t=this.memoryCache.get(e);if(t)return t;let r=this.index.get(e);if(!r)return null;let i=n.resolve(this.shardsDir,`${r}.gz`);try{let t=(await m(await u(i))).toString(`utf-8`);return this.memoryCache.set(e,t),t}catch(e){return e.code,null}}set(e,t){let r=a.createHash(`md5`).update(t).digest(`hex`);this.index.set(e,r),this.memoryCache.set(e,t);let o=n.resolve(this.shardsDir,`${r}.gz`);h.add(async()=>{try{try{await i.access(o);return}catch{}await d(this.shardsDir,{recursive:!0});let e=await p(Buffer.from(t)),n=`${o}.${a.randomBytes(4).toString(`hex`)}.tmp`;await l(n,e),await f(n,o)}catch{}}),this.saveTimeout&&clearTimeout(this.saveTimeout),this.saveTimeout=setTimeout(()=>{this.save()},500),typeof this.saveTimeout.unref==`function`&&this.saveTimeout.unref()}get size(){return this.index.size}async flush(){await h.flush()}};async function v(){await h.flush()}const y=new Map,b=()=>{let t=e();return n.resolve(process.cwd(),t.dir,`parser`)},x=`v2.5`;var S=class{static async get(t){if(e().noCache)return null;try{let e=await r.promises.stat(t),i=y.get(t);if(i&&i.mtime===e.mtimeMs)return i.data;let o=b(),s=a.createHash(`md5`).update(t).digest(`hex`),c=n.join(o,`${s}.json`);try{let n=await r.promises.readFile(c,`utf-8`),i=JSON.parse(n);return i._mtime!==e.mtimeMs||i._v!==x?null:(y.set(t,{data:i.data,mtime:i._mtime}),i.data)}catch{return null}}catch{return null}}static async set(t,i){if(!e().noCache)try{let e=await r.promises.stat(t);y.set(t,{data:i,mtime:e.mtimeMs});let o=b(),s=a.createHash(`md5`).update(t).digest(`hex`),c=n.join(o,`${s}.json`),l={_v:x,_mtime:e.mtimeMs,data:i};h.add(async()=>{try{await r.promises.mkdir(o,{recursive:!0}),await r.promises.writeFile(c,JSON.stringify(l))}catch{}})}catch{}}static invalidate(e){y.delete(e)}static clear(){y.clear();let e=b();if(r.existsSync(e))try{r.rmSync(e,{recursive:!0,force:!0})}catch{}}};export{v as i,g as n,_ as r,S as t};
@@ -1,7 +0,0 @@
1
- /**
2
- * Boltdocs - https://boltdocs.vercel.app
3
- * Copyright (c) 2026 Jesus Alcala
4
- * Licensed under the MIT License.
5
- */
6
- const e=require(`./chunk-Ds5LZdWN.cjs`),t=require(`./errors-Dx6JHoKE.cjs`),n=require(`./types-generator-CYcHkDzZ.cjs`);let r=require(`node:path`);r=e.n(r);let i=require(`node:fs`);i=e.n(i);let a=require(`zod`),o=require(`@bdocs/dui`);function s(e){return e}const c=a.z.object({icon:a.z.string().max(50),link:a.z.string().url()});a.z.object({text:a.z.string().max(2e3).optional()});const l=a.z.object({name:a.z.string(),enforce:a.z.enum([`pre`,`post`]).optional(),version:a.z.string().optional(),boltdocsVersion:a.z.string().optional(),remarkPlugins:a.z.array(a.z.unknown()).optional(),rehypePlugins:a.z.array(a.z.unknown()).optional(),vitePlugins:a.z.array(a.z.unknown()).optional(),components:a.z.record(a.z.string(),a.z.string()).optional(),hooks:a.z.record(a.z.string(),a.z.unknown()).optional()}),u=a.z.object({title:a.z.union([a.z.string(),a.z.record(a.z.string(),a.z.string())]).optional(),description:a.z.union([a.z.string(),a.z.record(a.z.string(),a.z.string())]).optional(),logo:a.z.union([a.z.string(),a.z.object({dark:a.z.string(),light:a.z.string(),alt:a.z.string().optional(),width:a.z.number().optional(),height:a.z.number().optional()})]).optional(),navbar:a.z.array(a.z.object({label:a.z.union([a.z.string(),a.z.record(a.z.string(),a.z.string())]),href:a.z.string(),items:a.z.array(a.z.object({label:a.z.union([a.z.string(),a.z.record(a.z.string(),a.z.string())]),href:a.z.string()})).optional()})).optional(),sidebar:a.z.record(a.z.string(),a.z.array(a.z.object({text:a.z.string(),link:a.z.string()}))).optional(),sidebarGroups:a.z.record(a.z.string(),a.z.object({title:a.z.union([a.z.string(),a.z.record(a.z.string(),a.z.string())]).optional(),icon:a.z.string().optional()})).optional(),socialLinks:a.z.array(c).optional(),editLink:a.z.string().refine(e=>!e||e.includes(`:path`),{message:`editLink must contain ':path' placeholder if specified`}).optional(),communityHelp:a.z.string().url().optional(),version:a.z.string().max(50).optional(),githubRepo:a.z.string().max(100).optional(),favicon:a.z.string().optional(),tabs:a.z.array(a.z.object({id:a.z.string(),text:a.z.union([a.z.string(),a.z.record(a.z.string(),a.z.string())]),icon:a.z.string().optional()})).optional(),codeTheme:a.z.union([a.z.string(),a.z.object({light:a.z.string(),dark:a.z.string()})]).optional()}),d=a.z.union([a.z.string(),a.z.object({rules:a.z.array(a.z.object({userAgent:a.z.string(),allow:a.z.union([a.z.string(),a.z.array(a.z.string())]).optional(),disallow:a.z.union([a.z.string(),a.z.array(a.z.string())]).optional()})).optional(),sitemaps:a.z.array(a.z.string().url()).optional()})]),f=a.z.object({defaultLocale:a.z.string(),locales:a.z.union([a.z.record(a.z.string(),a.z.string()),a.z.array(a.z.string())]).transform(e=>Array.isArray(e)?Object.fromEntries(e.map(e=>[e,e])):e),localeConfigs:a.z.record(a.z.string(),a.z.object({label:a.z.string().optional(),direction:a.z.enum([`ltr`,`rtl`]).optional(),htmlLang:a.z.string().optional(),calendar:a.z.string().optional()})).optional()}),p=a.z.object({defaultVersion:a.z.string(),prefix:a.z.string().optional(),versions:a.z.array(a.z.object({label:a.z.string(),path:a.z.string()}))}),m=a.z.object({headers:a.z.record(a.z.string(),a.z.string()).optional(),enableCSP:a.z.boolean().optional(),customHeaders:a.z.record(a.z.string(),a.z.string()).optional()}),h=a.z.object({google:a.z.string().optional(),bing:a.z.string().optional(),yandex:a.z.string().optional(),pinterest:a.z.string().optional(),facebook:a.z.string().optional()}),g=a.z.object({metatags:a.z.record(a.z.string(),a.z.string()).optional(),indexing:a.z.enum([`all`,`public`]).optional(),thumbnails:a.z.object({background:a.z.string().optional()}).optional(),verification:h.optional()}),_=a.z.object({measurementId:a.z.string().min(1,`Measurement ID is required for GA4`),debug:a.z.boolean().optional(),anonymizeIp:a.z.boolean().optional(),sendPageView:a.z.boolean().optional(),cookieFlags:a.z.string().optional(),autoTrack:a.z.object({pageViews:a.z.boolean().optional(),downloads:a.z.boolean().optional(),externalLinks:a.z.boolean().optional(),search:a.z.boolean().optional()}).optional()}),v=a.z.object({tagId:a.z.string().min(1,`Tag ID is required for GTM`),dataLayerName:a.z.string().optional(),preview:a.z.string().optional()}),y=a.z.object({appId:a.z.string().min(1,`Algolia App ID is required`),apiKey:a.z.string().min(1,`Algolia API Key is required`),indexName:a.z.string().min(1,`Algolia Index Name is required`)}),b=a.z.object({repo:a.z.string().min(1,`Giscus repository is required`),repoId:a.z.string().min(1,`Giscus repository ID is required`),category:a.z.string().optional(),categoryId:a.z.string().optional(),mapping:a.z.enum([`pathname`,`url`,`title`,`og:title`,`specific`,`number`]).optional(),strict:a.z.union([a.z.enum([`0`,`1`]),a.z.boolean()]).optional(),reactionsEnabled:a.z.union([a.z.enum([`0`,`1`]),a.z.boolean()]).optional(),emitMetadata:a.z.union([a.z.enum([`0`,`1`]),a.z.boolean()]).optional(),inputPosition:a.z.enum([`top`,`bottom`]).optional(),theme:a.z.string().optional(),darkTheme:a.z.string().optional(),lang:a.z.string().optional(),loading:a.z.enum([`lazy`,`eager`]).optional()}),x=a.z.object({enabled:a.z.boolean(),owner:a.z.string().min(1,`GitHub owner is required`),repo:a.z.string().min(1,`GitHub repository name is required`),categorySlug:a.z.string().optional(),endpoint:a.z.string().optional()}),S=a.z.object({analytics:a.z.boolean().optional(),speedInsights:a.z.boolean().optional()}),C=a.z.object({ga4:_.optional(),gtm:v.optional(),vercel:S.optional()}),w=a.z.object({algolia:y.optional()}),T=a.z.object({giscus:b.optional(),custom:x.optional()}),E=a.z.object({analytics:C.optional(),search:w.optional(),feedback:T.optional()}),D=a.z.object({siteUrl:a.z.string().url().optional(),docsDir:a.z.string().optional(),base:a.z.string().optional(),theme:u.optional(),i18n:f.optional(),versions:p.optional(),plugins:a.z.array(l).optional(),robots:d.optional(),security:m.optional(),seo:g.optional(),integrations:E.optional(),vite:a.z.record(a.z.string(),a.z.unknown()).optional()}),O=[`boltdocs.config.js`,`boltdocs.config.mjs`,`boltdocs.config.ts`];async function k(e,n=process.cwd()){let a=n,s={docsDir:r.default.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`}}},c={};for(let e of O){let t=r.default.resolve(a,e);if(i.default.existsSync(t))try{let{loadConfigFromFile:e}=await import(`vite`),n=await e({command:`serve`,mode:`development`},t,a);if(n){c=n.config;break}}catch(t){(0,o.warn)(`Failed to load config from ${e}:`,t)}}let l={title:c.title,description:c.description,logo:c.logo,favicon:c.favicon,navbar:c.navbar,sidebar:c.sidebar,sidebarGroups:c.theme?.sidebarGroups,socialLinks:c.socialLinks,githubRepo:c.githubRepo,tabs:c.tabs,codeTheme:c.codeTheme,communityHelp:c.communityHelp,version:c.version,editLink:c.editLink,...c.theme||{}},u=Object.fromEntries(Object.entries(l).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:r.default.resolve(e),theme:{...s.theme,...u},i18n:c.i18n?{...c.i18n,locales:Array.isArray(c.i18n.locales)?Object.fromEntries(c.i18n.locales.map(e=>[e,e])):c.i18n.locales}:void 0,versions:c.versions,siteUrl:c.siteUrl,base:c.base,seo:c.seo,plugins:c.plugins||[],robots:c.robots,security:c.security,integrations:c.integrations,vite:c.vite},f=D.safeParse(d);if(!f.success)throw new t.r(`Invalid Boltdocs configuration:\n${f.error.issues.map(e=>` - ${e.path.join(`.`)}: ${e.message}`).join(`
7
- `)}`);return f.data}async function A(e,t=process.cwd()){let r=await k(e,t);return n.t(r,e,t),r}Object.defineProperty(exports,`a`,{enumerable:!0,get:function(){return s}}),Object.defineProperty(exports,`i`,{enumerable:!0,get:function(){return l}}),Object.defineProperty(exports,`n`,{enumerable:!0,get:function(){return k}}),Object.defineProperty(exports,`r`,{enumerable:!0,get:function(){return A}}),Object.defineProperty(exports,`t`,{enumerable:!0,get:function(){return O}});