boltdocs 2.1.1 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (133) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/bin/boltdocs.js +2 -2
  3. package/dist/base-ui/index.d.mts +25 -0
  4. package/dist/base-ui/index.d.ts +25 -0
  5. package/dist/base-ui/index.js +1 -0
  6. package/dist/base-ui/index.mjs +1 -0
  7. package/dist/{cache-Q4T6VAUL.mjs → cache-P6WK424C.mjs} +1 -1
  8. package/dist/chunk-22NXDNP4.mjs +74 -0
  9. package/dist/chunk-2HUVMMJU.mjs +1 -0
  10. package/dist/chunk-2Z5T6EAU.mjs +1 -0
  11. package/dist/chunk-CRZGOE32.mjs +1 -0
  12. package/dist/chunk-HA6543SL.mjs +1 -0
  13. package/dist/chunk-JD3RSDE4.mjs +1 -0
  14. package/dist/chunk-JZXLCA2E.mjs +1 -0
  15. package/dist/chunk-NBCYHLAA.mjs +1 -0
  16. package/dist/chunk-RPUERTVC.mjs +1 -0
  17. package/dist/chunk-T3W44KWY.mjs +1 -0
  18. package/dist/chunk-URTD6E6S.mjs +1 -0
  19. package/dist/chunk-W2NB4T6V.mjs +1 -0
  20. package/dist/chunk-Y4RRHPXC.mjs +1 -0
  21. package/dist/client/index.d.mts +13 -115
  22. package/dist/client/index.d.ts +13 -115
  23. package/dist/client/index.js +1 -1
  24. package/dist/client/index.mjs +1 -1
  25. package/dist/client/ssr.js +1 -1
  26. package/dist/client/ssr.mjs +1 -1
  27. package/dist/client/types.d.mts +3 -0
  28. package/dist/client/types.d.ts +3 -0
  29. package/dist/client/types.js +1 -0
  30. package/dist/client/types.mjs +0 -0
  31. package/dist/copy-markdown-C-90ixSe.d.ts +15 -0
  32. package/dist/copy-markdown-CbS8X-qe.d.mts +15 -0
  33. package/dist/{client/hooks → hooks}/index.d.mts +16 -11
  34. package/dist/{client/hooks → hooks}/index.d.ts +16 -11
  35. package/dist/hooks/index.js +1 -0
  36. package/dist/hooks/index.mjs +1 -0
  37. package/dist/integrations/index.d.mts +48 -0
  38. package/dist/integrations/index.d.ts +48 -0
  39. package/dist/integrations/index.js +1 -0
  40. package/dist/integrations/index.mjs +1 -0
  41. package/dist/link-DfBwCeZc.d.mts +68 -0
  42. package/dist/link-DfBwCeZc.d.ts +68 -0
  43. package/dist/loading-B7X5Wchs.d.ts +66 -0
  44. package/dist/loading-WuaQbsKb.d.mts +66 -0
  45. package/dist/{client/components/mdx → mdx}/index.d.mts +6 -38
  46. package/dist/{client/components/mdx → mdx}/index.d.ts +6 -38
  47. package/dist/mdx/index.js +1 -0
  48. package/dist/mdx/index.mjs +1 -0
  49. package/dist/node/cli-entry.js +31 -27
  50. package/dist/node/cli-entry.mjs +5 -1
  51. package/dist/node/index.d.mts +44 -14
  52. package/dist/node/index.d.ts +44 -14
  53. package/dist/node/index.js +24 -24
  54. package/dist/node/index.mjs +1 -1
  55. package/dist/primitives/index.d.mts +301 -0
  56. package/dist/primitives/index.d.ts +301 -0
  57. package/dist/primitives/index.js +1 -0
  58. package/dist/primitives/index.mjs +1 -0
  59. package/dist/search-dialog-ZRXBAQJ5.mjs +1 -0
  60. package/dist/{types-Cp21DHI6.d.mts → types-j7jvWsJj.d.mts} +63 -17
  61. package/dist/{types-Cp21DHI6.d.ts → types-j7jvWsJj.d.ts} +63 -17
  62. package/dist/{use-routes-xLhumjbV.d.ts → use-routes-Cd806kGw.d.ts} +1 -1
  63. package/dist/{use-routes-8Iei6jTp.d.mts → use-routes-DDL0_jkQ.d.mts} +1 -1
  64. package/package.json +35 -8
  65. package/src/client/app/index.tsx +155 -35
  66. package/src/client/app/mdx-component.tsx +7 -3
  67. package/src/client/app/theme-context.tsx +47 -23
  68. package/src/client/components/default-layout.tsx +16 -6
  69. package/src/client/components/primitives/breadcrumbs.tsx +1 -1
  70. package/src/client/components/primitives/navbar.tsx +8 -5
  71. package/src/client/components/primitives/search-dialog.tsx +15 -6
  72. package/src/client/components/primitives/sidebar.tsx +3 -2
  73. package/src/client/components/primitives/skeleton.tsx +26 -0
  74. package/src/client/components/ui-base/breadcrumbs.tsx +1 -1
  75. package/src/client/components/ui-base/index.ts +17 -0
  76. package/src/client/components/ui-base/loading.tsx +43 -73
  77. package/src/client/components/ui-base/navbar.tsx +74 -39
  78. package/src/client/components/ui-base/page-nav.tsx +2 -1
  79. package/src/client/components/ui-base/powered-by.tsx +11 -5
  80. package/src/client/components/ui-base/search-dialog.tsx +16 -5
  81. package/src/client/components/ui-base/sidebar.tsx +33 -22
  82. package/src/client/components/ui-base/tabs.tsx +4 -1
  83. package/src/client/components/ui-base/theme-toggle.tsx +35 -15
  84. package/src/client/hooks/use-i18n.ts +38 -7
  85. package/src/client/hooks/use-localized-to.ts +51 -73
  86. package/src/client/hooks/use-navbar.ts +10 -3
  87. package/src/client/hooks/use-page-nav.ts +27 -6
  88. package/src/client/hooks/use-routes.ts +62 -17
  89. package/src/client/hooks/use-search.ts +84 -46
  90. package/src/client/hooks/use-sidebar.ts +6 -2
  91. package/src/client/hooks/use-version.ts +5 -0
  92. package/src/client/integrations/index.ts +1 -0
  93. package/src/client/store/use-boltdocs-store.ts +44 -0
  94. package/src/client/theme/neutral.css +29 -0
  95. package/src/client/types.ts +4 -2
  96. package/src/client/utils/i18n.ts +23 -0
  97. package/src/node/{cli.ts → cli/build.ts} +17 -23
  98. package/src/node/cli/dev.ts +22 -0
  99. package/src/node/cli/doctor.ts +243 -0
  100. package/src/node/cli/index.ts +9 -0
  101. package/src/node/cli/ui.ts +54 -0
  102. package/src/node/cli-entry.ts +16 -16
  103. package/src/node/config.ts +54 -17
  104. package/src/node/index.ts +1 -1
  105. package/src/node/mdx/cache.ts +12 -0
  106. package/src/node/mdx/highlighter.ts +47 -0
  107. package/src/node/mdx/index.ts +114 -0
  108. package/src/node/mdx/rehype-shiki.ts +53 -0
  109. package/src/node/mdx/remark-shiki.ts +61 -0
  110. package/src/node/plugin/entry.ts +1 -1
  111. package/src/node/plugin/html.ts +8 -4
  112. package/src/node/plugin/index.ts +135 -72
  113. package/src/node/routes/index.ts +34 -13
  114. package/src/node/routes/parser.ts +13 -5
  115. package/src/node/search/index.ts +55 -0
  116. package/src/node/ssg/index.ts +15 -7
  117. package/src/node/ssg/robots.ts +7 -4
  118. package/src/node/utils.ts +32 -2
  119. package/tsup.config.ts +7 -2
  120. package/dist/chunk-52MVMZWS.mjs +0 -1
  121. package/dist/chunk-BVWWKXJH.mjs +0 -1
  122. package/dist/chunk-DVY3RDXD.mjs +0 -1
  123. package/dist/chunk-FUVYCYWC.mjs +0 -1
  124. package/dist/chunk-GBLMDJ2B.mjs +0 -1
  125. package/dist/chunk-ISPX45DF.mjs +0 -1
  126. package/dist/chunk-PNXZMUCO.mjs +0 -1
  127. package/dist/chunk-V2ZHKQSP.mjs +0 -74
  128. package/dist/client/components/mdx/index.js +0 -1
  129. package/dist/client/components/mdx/index.mjs +0 -1
  130. package/dist/client/hooks/index.js +0 -1
  131. package/dist/client/hooks/index.mjs +0 -1
  132. package/dist/search-dialog-TWGYKF2D.mjs +0 -1
  133. package/src/node/mdx.ts +0 -279
package/src/node/mdx.ts DELETED
@@ -1,279 +0,0 @@
1
- import mdxPlugin from '@mdx-js/rollup'
2
- import remarkGfm from 'remark-gfm'
3
- import remarkFrontmatter from 'remark-frontmatter'
4
- import rehypeSlug from 'rehype-slug'
5
- import type { Plugin } from 'vite'
6
- import crypto from 'crypto'
7
- import { visit } from 'unist-util-visit'
8
- import { createHighlighter } from 'shiki'
9
-
10
- import type { Highlighter } from 'shiki'
11
-
12
- import type { BoltdocsConfig } from './config'
13
- import { TransformCache } from './cache'
14
-
15
- let shikiHighlighter: Highlighter | null = null
16
-
17
- /**
18
- * Retrieves or initializes the Shiki highlighter instance.
19
- * Supports dual-theme configurations (light/dark).
20
- *
21
- * @param codeTheme - Theme configuration (string for single, object for dual).
22
- * @returns A promise resolving to the highlighter instance.
23
- */
24
- async function getShikiHighlighter(codeTheme: any) {
25
- if (shikiHighlighter) return shikiHighlighter
26
-
27
- const themes =
28
- typeof codeTheme === 'object'
29
- ? [codeTheme.light, codeTheme.dark]
30
- : [codeTheme ?? 'github-dark']
31
-
32
- // Fallbacks for standard themes
33
- ;['github-light', 'github-dark'].forEach((t) => {
34
- if (!themes.includes(t)) themes.push(t)
35
- })
36
-
37
- // Initialize with a core set of languages first to speed up boot
38
- shikiHighlighter = await createHighlighter({
39
- themes,
40
- langs: [
41
- 'tsx',
42
- 'jsx',
43
- 'ts',
44
- 'js',
45
- 'json',
46
- 'md',
47
- 'mdx',
48
- 'css',
49
- 'html',
50
- 'bash',
51
- 'sh',
52
- 'yaml',
53
- 'yml',
54
- ],
55
- })
56
-
57
- return shikiHighlighter
58
- }
59
-
60
- /**
61
- * Custom remark plugin to highlight code in ComponentPreview components.
62
- * This runs before rehype, ensuring that the 'highlightedHtml' prop is correctly
63
- * attached to the MDX component as a JSX attribute.
64
- *
65
- * Supports both string literals and MDX expression values (template literals)
66
- * for the 'code' attribute.
67
- *
68
- * @param config - The Boltdocs configuration
69
- * @returns A remark plugin function
70
- */
71
- export function remarkShiki(config?: BoltdocsConfig) {
72
- return async (tree: any) => {
73
- const codeTheme = config?.themeConfig?.codeTheme ?? {
74
- light: 'github-light',
75
- dark: 'github-dark',
76
- }
77
- const highlighter = await getShikiHighlighter(codeTheme)
78
-
79
- visit(tree, ['mdxJsxFlowElement', 'mdxJsxTextElement'], (node: any) => {
80
- if (node.name !== 'ComponentPreview') return
81
-
82
- const codeAttr = node.attributes?.find((a: any) => a.name === 'code')
83
- let code = ''
84
-
85
- if (codeAttr) {
86
- if (typeof codeAttr.value === 'string') {
87
- code = codeAttr.value
88
- } else if (codeAttr.value?.type === 'mdxJsxAttributeValueExpression') {
89
- const expr = codeAttr.value.value ?? ''
90
- code = expr.match(/^[`'"](.+)[`'"]$/)?.[1] ?? expr
91
- }
92
- }
93
-
94
- if (!code) return
95
-
96
- const options: any =
97
- typeof codeTheme === 'object'
98
- ? {
99
- themes: { light: codeTheme.light, dark: codeTheme.dark },
100
- lang: 'tsx',
101
- }
102
- : { theme: codeTheme, lang: 'tsx' }
103
-
104
- const html = highlighter.codeToHtml(code, options)
105
-
106
- node.attributes = (node.attributes ?? []).filter(
107
- (a: any) => a.name !== 'highlightedHtml',
108
- )
109
- node.attributes.push({
110
- type: 'mdxJsxAttribute',
111
- name: 'highlightedHtml',
112
- value: html,
113
- })
114
- })
115
- }
116
- }
117
-
118
- /**
119
- * Custom rehype plugin to perform syntax highlighting at build time for
120
- * standard Markdown code blocks.
121
- *
122
- * Injects 'data-highlighted="true"' and 'highlightedHtml' into the 'pre' tag properties,
123
- * which are then consumed by the client-side CodeBlock component.
124
- *
125
- * @param config - The Boltdocs configuration
126
- * @returns A rehype plugin function
127
- */
128
- export function rehypeShiki(config?: BoltdocsConfig) {
129
- return async (tree: any) => {
130
- const codeTheme = config?.themeConfig?.codeTheme || {
131
- light: 'github-light',
132
- dark: 'github-dark',
133
- }
134
- const highlighter = await getShikiHighlighter(codeTheme)
135
-
136
- visit(tree, 'element', (node: any) => {
137
- // Handle standard Markdown code blocks
138
- if (node.tagName === 'pre' && node.children?.[0]?.tagName === 'code') {
139
- const codeNode = node.children[0]
140
- const className = codeNode.properties?.className || []
141
- const langMatch = className.find((c: string) =>
142
- c.startsWith('language-'),
143
- )
144
- const lang = langMatch ? langMatch.slice(9) : 'text'
145
- const code = codeNode.children[0]?.value || ''
146
-
147
- const options: any = { lang }
148
- if (typeof codeTheme === 'object') {
149
- options.themes = {
150
- light: codeTheme.light,
151
- dark: codeTheme.dark,
152
- }
153
- } else {
154
- options.theme = codeTheme
155
- }
156
-
157
- const html = highlighter.codeToHtml(code, options)
158
-
159
- // Inject highlighted HTML and mark as highlighted for CodeBlock component
160
- node.properties.dataHighlighted = 'true'
161
- node.properties.highlightedHtml = html
162
- node.children = []
163
- }
164
- })
165
- }
166
- }
167
-
168
- const MDX_PLUGIN_VERSION = 'v3'
169
-
170
- /**
171
- * Persistent cache for MDX transformations.
172
- * Saves results to `.boltdocs/transform-mdx.json.gz`.
173
- */
174
- const mdxCache = new TransformCache('mdx')
175
- let mdxCacheLoaded = false
176
-
177
- /**
178
- * Configures the MDX compiler for Vite using `@mdx-js/rollup`.
179
- * Includes standard remark and rehype plugins for GitHub Flavored Markdown (GFM),
180
- * frontmatter extraction, and auto-linking headers.
181
- *
182
- * Also wraps the plugin with a persistent cache to avoid re-compiling unchanged MDX files.
183
- *
184
- * @param config - The Boltdocs configuration containing custom plugins
185
- * @param compiler - The MDX compiler plugin (for testing)
186
- * @returns A Vite plugin configured for MDX parsing with caching
187
- */
188
- export function boltdocsMdxPlugin(
189
- config?: BoltdocsConfig,
190
- compiler = mdxPlugin,
191
- ): Plugin {
192
- const extraRemarkPlugins =
193
- config?.plugins?.flatMap((p) => p.remarkPlugins || []) || []
194
- const extraRehypePlugins =
195
- config?.plugins?.flatMap((p) => p.rehypePlugins || []) || []
196
-
197
- const baseMdxPlugin = compiler({
198
- remarkPlugins: [
199
- remarkGfm,
200
- remarkFrontmatter,
201
- [remarkShiki, config],
202
- ...(extraRemarkPlugins as any[]),
203
- ],
204
- rehypePlugins: [
205
- rehypeSlug,
206
- [rehypeShiki, config],
207
- ...(extraRehypePlugins as any[]),
208
- ],
209
- jsxRuntime: 'automatic',
210
- providerImportSource: '@mdx-js/react',
211
- }) as Plugin
212
-
213
- // @ts-ignore
214
- if (baseMdxPlugin.isMock) {
215
- console.log('MDX PLUGIN IS MOCKED')
216
- }
217
-
218
- return {
219
- ...baseMdxPlugin,
220
- name: 'vite-plugin-boltdocs-mdx',
221
-
222
- async buildStart() {
223
- hits = 0
224
- total = 0
225
- if (!mdxCacheLoaded) {
226
- mdxCache.load()
227
- mdxCacheLoaded = true
228
- }
229
- if (baseMdxPlugin.buildStart) {
230
- await (baseMdxPlugin.buildStart as any).call(this)
231
- }
232
- },
233
-
234
- async transform(code, id, options) {
235
- if (!id.endsWith('.md') && !id.endsWith('.mdx')) {
236
- return (baseMdxPlugin.transform as any)?.call(this, code, id, options)
237
- }
238
-
239
- console.log(`[boltdocs] Transforming MDX: ${id}`)
240
- total++
241
- // Create a cache key based on path, content, and plugin version
242
- const contentHash = crypto.createHash('md5').update(code).digest('hex')
243
- const cacheKey = `${id}:${contentHash}:${MDX_PLUGIN_VERSION}`
244
-
245
- const cached = mdxCache.get(cacheKey)
246
- if (cached) {
247
- hits++
248
- return { code: cached, map: null }
249
- }
250
-
251
- const result = await (baseMdxPlugin.transform as any).call(
252
- this,
253
- code,
254
- id,
255
- options,
256
- )
257
-
258
- if (result && typeof result === 'object' && result.code) {
259
- mdxCache.set(cacheKey, result.code)
260
- }
261
-
262
- return result
263
- },
264
-
265
- async buildEnd() {
266
- console.log(
267
- `[boltdocs] MDX Cache Performance: ${hits}/${total} hits (${Math.round((hits / total) * 100) || 0}%)`,
268
- )
269
- mdxCache.save()
270
- await mdxCache.flush() // Use instance flush or global flushCache
271
- if (baseMdxPlugin.buildEnd) {
272
- await (baseMdxPlugin.buildEnd as any).call(this)
273
- }
274
- },
275
- }
276
- }
277
-
278
- let hits = 0
279
- let total = 0