boltdocs 1.10.2 → 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 (250) 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 +138 -298
  22. package/dist/client/index.d.ts +138 -298
  23. package/dist/client/index.js +1 -3630
  24. package/dist/client/index.mjs +1 -697
  25. package/dist/client/ssr.d.mts +7 -3
  26. package/dist/client/ssr.d.ts +7 -3
  27. package/dist/client/ssr.js +1 -2928
  28. package/dist/client/ssr.mjs +1 -33
  29. package/dist/{config-BsFQ-ErD.d.ts → config-CX4l-ZNp.d.mts} +42 -35
  30. package/dist/{config-BsFQ-ErD.d.mts → config-CX4l-ZNp.d.ts} +42 -35
  31. package/dist/node/index.d.mts +2 -4
  32. package/dist/node/index.d.ts +2 -4
  33. package/dist/node/index.js +31 -1161
  34. package/dist/node/index.mjs +31 -736
  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 +34 -12
  41. package/src/client/app/config-context.tsx +18 -0
  42. package/src/client/app/docs-layout.tsx +14 -0
  43. package/src/client/app/index.tsx +137 -262
  44. package/src/client/app/mdx-component.tsx +52 -0
  45. package/src/client/app/mdx-components-context.tsx +23 -0
  46. package/src/client/app/mdx-page.tsx +20 -0
  47. package/src/client/app/preload.tsx +38 -30
  48. package/src/client/app/router.tsx +30 -0
  49. package/src/client/app/scroll-handler.tsx +40 -0
  50. package/src/client/app/theme-context.tsx +75 -0
  51. package/src/client/components/default-layout.tsx +80 -0
  52. package/src/client/components/docs-layout.tsx +105 -0
  53. package/src/client/components/icons-dev.tsx +74 -0
  54. package/src/client/components/mdx/admonition.tsx +107 -0
  55. package/src/client/components/mdx/badge.tsx +41 -0
  56. package/src/client/components/mdx/button.tsx +35 -0
  57. package/src/client/components/mdx/card.tsx +124 -0
  58. package/src/client/components/mdx/code-block.tsx +119 -0
  59. package/src/client/components/mdx/component-preview.tsx +47 -0
  60. package/src/client/components/mdx/component-props.tsx +83 -0
  61. package/src/client/components/mdx/field.tsx +66 -0
  62. package/src/client/components/mdx/file-tree.tsx +287 -0
  63. package/src/client/components/mdx/hooks/use-code-block.ts +56 -0
  64. package/src/client/components/mdx/hooks/use-component-preview.ts +16 -0
  65. package/src/client/components/mdx/hooks/useTable.ts +74 -0
  66. package/src/client/components/mdx/hooks/useTabs.ts +68 -0
  67. package/src/client/components/mdx/image.tsx +23 -0
  68. package/src/client/components/mdx/index.ts +53 -0
  69. package/src/client/components/mdx/link.tsx +38 -0
  70. package/src/client/components/mdx/list.tsx +192 -0
  71. package/src/client/components/mdx/table.tsx +156 -0
  72. package/src/client/components/mdx/tabs.tsx +135 -0
  73. package/src/client/components/mdx/video.tsx +68 -0
  74. package/src/client/components/primitives/breadcrumbs.tsx +79 -0
  75. package/src/client/components/primitives/button-group.tsx +54 -0
  76. package/src/client/components/primitives/button.tsx +145 -0
  77. package/src/client/components/primitives/helpers/observer.ts +120 -0
  78. package/src/client/components/primitives/index.ts +17 -0
  79. package/src/client/components/primitives/link.tsx +122 -0
  80. package/src/client/components/primitives/menu.tsx +159 -0
  81. package/src/client/components/primitives/navbar.tsx +359 -0
  82. package/src/client/components/primitives/navigation-menu.tsx +116 -0
  83. package/src/client/components/primitives/on-this-page.tsx +461 -0
  84. package/src/client/components/primitives/page-nav.tsx +87 -0
  85. package/src/client/components/primitives/popover.tsx +47 -0
  86. package/src/client/components/primitives/search-dialog.tsx +183 -0
  87. package/src/client/components/primitives/sidebar.tsx +154 -0
  88. package/src/client/components/primitives/tabs.tsx +90 -0
  89. package/src/client/components/primitives/tooltip.tsx +83 -0
  90. package/src/client/components/primitives/types.ts +11 -0
  91. package/src/client/components/ui-base/breadcrumbs.tsx +42 -0
  92. package/src/client/components/ui-base/copy-markdown.tsx +112 -0
  93. package/src/client/components/ui-base/error-boundary.tsx +52 -0
  94. package/src/client/components/ui-base/github-stars.tsx +27 -0
  95. package/src/client/components/ui-base/head.tsx +69 -0
  96. package/src/client/components/ui-base/loading.tsx +87 -0
  97. package/src/client/components/ui-base/navbar.tsx +138 -0
  98. package/src/client/components/ui-base/not-found.tsx +24 -0
  99. package/src/client/components/ui-base/on-this-page.tsx +152 -0
  100. package/src/client/components/ui-base/page-nav.tsx +39 -0
  101. package/src/client/components/ui-base/powered-by.tsx +19 -0
  102. package/src/client/components/ui-base/progress-bar.tsx +67 -0
  103. package/src/client/components/ui-base/search-dialog.tsx +82 -0
  104. package/src/client/components/ui-base/sidebar.tsx +104 -0
  105. package/src/client/components/ui-base/tabs.tsx +65 -0
  106. package/src/client/components/ui-base/theme-toggle.tsx +32 -0
  107. package/src/client/hooks/index.ts +12 -0
  108. package/src/client/hooks/use-breadcrumbs.ts +22 -0
  109. package/src/client/hooks/use-i18n.ts +84 -0
  110. package/src/client/hooks/use-localized-to.ts +95 -0
  111. package/src/client/hooks/use-location.ts +5 -0
  112. package/src/client/hooks/use-navbar.ts +60 -0
  113. package/src/client/hooks/use-onthispage.ts +23 -0
  114. package/src/client/hooks/use-page-nav.ts +22 -0
  115. package/src/client/hooks/use-routes.ts +72 -0
  116. package/src/client/hooks/use-search.ts +71 -0
  117. package/src/client/hooks/use-sidebar.ts +49 -0
  118. package/src/client/hooks/use-tabs.ts +43 -0
  119. package/src/client/hooks/use-version.ts +78 -0
  120. package/src/client/index.ts +55 -17
  121. package/src/client/integrations/codesandbox.ts +179 -0
  122. package/src/client/ssr.tsx +27 -16
  123. package/src/client/theme/neutral.css +360 -0
  124. package/src/client/types.ts +131 -27
  125. package/src/client/utils/cn.ts +6 -0
  126. package/src/client/utils/copy-clipboard.ts +22 -0
  127. package/src/client/utils/get-base-file-path.ts +21 -0
  128. package/src/client/utils/github.ts +121 -0
  129. package/src/client/utils/use-on-change.ts +15 -0
  130. package/src/client/virtual.d.ts +24 -0
  131. package/src/node/cache.ts +156 -156
  132. package/src/node/config.ts +159 -103
  133. package/src/node/index.ts +13 -13
  134. package/src/node/mdx.ts +213 -61
  135. package/src/node/plugin/entry.ts +29 -18
  136. package/src/node/plugin/html.ts +11 -11
  137. package/src/node/plugin/index.ts +161 -84
  138. package/src/node/plugin/types.ts +2 -4
  139. package/src/node/routes/cache.ts +6 -6
  140. package/src/node/routes/index.ts +206 -113
  141. package/src/node/routes/parser.ts +102 -82
  142. package/src/node/routes/sorter.ts +15 -15
  143. package/src/node/routes/types.ts +24 -24
  144. package/src/node/ssg/index.ts +73 -47
  145. package/src/node/ssg/meta.ts +4 -4
  146. package/src/node/ssg/options.ts +5 -5
  147. package/src/node/ssg/sitemap.ts +14 -14
  148. package/src/node/utils.ts +54 -31
  149. package/tsconfig.json +25 -20
  150. package/tsup.config.ts +23 -14
  151. package/dist/PackageManagerTabs-NVT7G625.mjs +0 -99
  152. package/dist/SearchDialog-AGVF6JBO.mjs +0 -194
  153. package/dist/SearchDialog-YPDOM7Q6.css +0 -2847
  154. package/dist/Video-KNTY5BNO.mjs +0 -6
  155. package/dist/cache-KNL5B4EE.mjs +0 -12
  156. package/dist/chunk-7SFUJWTB.mjs +0 -211
  157. package/dist/chunk-FFBNU6IJ.mjs +0 -386
  158. package/dist/chunk-FMTOYQLO.mjs +0 -37
  159. package/dist/chunk-TKLQWU7H.mjs +0 -1920
  160. package/dist/chunk-Z7JHYNAS.mjs +0 -57
  161. package/dist/client/index.css +0 -2847
  162. package/dist/client/ssr.css +0 -2847
  163. package/dist/types-Dj-bfnC3.d.mts +0 -74
  164. package/dist/types-Dj-bfnC3.d.ts +0 -74
  165. package/src/client/theme/components/CodeBlock/CodeBlock.tsx +0 -61
  166. package/src/client/theme/components/CodeBlock/index.ts +0 -1
  167. package/src/client/theme/components/PackageManagerTabs/PackageManagerTabs.tsx +0 -131
  168. package/src/client/theme/components/PackageManagerTabs/index.ts +0 -1
  169. package/src/client/theme/components/PackageManagerTabs/pkg-tabs.css +0 -64
  170. package/src/client/theme/components/Playground/Playground.tsx +0 -180
  171. package/src/client/theme/components/Playground/index.ts +0 -1
  172. package/src/client/theme/components/Playground/playground.css +0 -238
  173. package/src/client/theme/components/Video/Video.tsx +0 -84
  174. package/src/client/theme/components/Video/index.ts +0 -1
  175. package/src/client/theme/components/Video/video.css +0 -41
  176. package/src/client/theme/components/mdx/Admonition.tsx +0 -80
  177. package/src/client/theme/components/mdx/Badge.tsx +0 -31
  178. package/src/client/theme/components/mdx/Button.tsx +0 -50
  179. package/src/client/theme/components/mdx/Card.tsx +0 -80
  180. package/src/client/theme/components/mdx/Field.tsx +0 -60
  181. package/src/client/theme/components/mdx/FileTree.tsx +0 -229
  182. package/src/client/theme/components/mdx/List.tsx +0 -57
  183. package/src/client/theme/components/mdx/Table.tsx +0 -151
  184. package/src/client/theme/components/mdx/Tabs.tsx +0 -123
  185. package/src/client/theme/components/mdx/index.ts +0 -27
  186. package/src/client/theme/components/mdx/mdx-components.css +0 -764
  187. package/src/client/theme/icons/bun.tsx +0 -62
  188. package/src/client/theme/icons/deno.tsx +0 -20
  189. package/src/client/theme/icons/discord.tsx +0 -12
  190. package/src/client/theme/icons/github.tsx +0 -15
  191. package/src/client/theme/icons/npm.tsx +0 -13
  192. package/src/client/theme/icons/pnpm.tsx +0 -72
  193. package/src/client/theme/icons/twitter.tsx +0 -12
  194. package/src/client/theme/styles/markdown.css +0 -394
  195. package/src/client/theme/styles/variables.css +0 -175
  196. package/src/client/theme/styles.css +0 -39
  197. package/src/client/theme/ui/Breadcrumbs/Breadcrumbs.tsx +0 -68
  198. package/src/client/theme/ui/Breadcrumbs/index.ts +0 -1
  199. package/src/client/theme/ui/CopyMarkdown/CopyMarkdown.tsx +0 -82
  200. package/src/client/theme/ui/CopyMarkdown/copy-markdown.css +0 -112
  201. package/src/client/theme/ui/CopyMarkdown/index.ts +0 -1
  202. package/src/client/theme/ui/ErrorBoundary/ErrorBoundary.tsx +0 -50
  203. package/src/client/theme/ui/ErrorBoundary/error-boundary.css +0 -55
  204. package/src/client/theme/ui/ErrorBoundary/index.ts +0 -1
  205. package/src/client/theme/ui/Footer/footer.css +0 -32
  206. package/src/client/theme/ui/Head/Head.tsx +0 -69
  207. package/src/client/theme/ui/Head/index.ts +0 -1
  208. package/src/client/theme/ui/LanguageSwitcher/LanguageSwitcher.tsx +0 -125
  209. package/src/client/theme/ui/LanguageSwitcher/index.ts +0 -1
  210. package/src/client/theme/ui/LanguageSwitcher/language-switcher.css +0 -98
  211. package/src/client/theme/ui/Layout/Layout.tsx +0 -203
  212. package/src/client/theme/ui/Layout/base.css +0 -106
  213. package/src/client/theme/ui/Layout/index.ts +0 -2
  214. package/src/client/theme/ui/Layout/pagination.css +0 -72
  215. package/src/client/theme/ui/Layout/responsive.css +0 -47
  216. package/src/client/theme/ui/Link/Link.tsx +0 -392
  217. package/src/client/theme/ui/Link/LinkPreview.tsx +0 -59
  218. package/src/client/theme/ui/Link/index.ts +0 -2
  219. package/src/client/theme/ui/Link/link-preview.css +0 -48
  220. package/src/client/theme/ui/Loading/Loading.tsx +0 -10
  221. package/src/client/theme/ui/Loading/index.ts +0 -1
  222. package/src/client/theme/ui/Loading/loading.css +0 -30
  223. package/src/client/theme/ui/Navbar/GithubStars.tsx +0 -27
  224. package/src/client/theme/ui/Navbar/Navbar.tsx +0 -193
  225. package/src/client/theme/ui/Navbar/Tabs.tsx +0 -99
  226. package/src/client/theme/ui/Navbar/index.ts +0 -2
  227. package/src/client/theme/ui/Navbar/navbar.css +0 -347
  228. package/src/client/theme/ui/NotFound/NotFound.tsx +0 -19
  229. package/src/client/theme/ui/NotFound/index.ts +0 -1
  230. package/src/client/theme/ui/NotFound/not-found.css +0 -64
  231. package/src/client/theme/ui/OnThisPage/OnThisPage.tsx +0 -244
  232. package/src/client/theme/ui/OnThisPage/index.ts +0 -1
  233. package/src/client/theme/ui/OnThisPage/toc.css +0 -152
  234. package/src/client/theme/ui/PoweredBy/PoweredBy.tsx +0 -18
  235. package/src/client/theme/ui/PoweredBy/index.ts +0 -1
  236. package/src/client/theme/ui/PoweredBy/powered-by.css +0 -76
  237. package/src/client/theme/ui/ProgressBar/ProgressBar.css +0 -17
  238. package/src/client/theme/ui/ProgressBar/ProgressBar.tsx +0 -51
  239. package/src/client/theme/ui/ProgressBar/index.ts +0 -1
  240. package/src/client/theme/ui/SearchDialog/SearchDialog.tsx +0 -209
  241. package/src/client/theme/ui/SearchDialog/index.ts +0 -1
  242. package/src/client/theme/ui/SearchDialog/search.css +0 -152
  243. package/src/client/theme/ui/Sidebar/Sidebar.tsx +0 -244
  244. package/src/client/theme/ui/Sidebar/index.ts +0 -1
  245. package/src/client/theme/ui/Sidebar/sidebar.css +0 -230
  246. package/src/client/theme/ui/ThemeToggle/ThemeToggle.tsx +0 -69
  247. package/src/client/theme/ui/ThemeToggle/index.ts +0 -1
  248. package/src/client/theme/ui/VersionSwitcher/VersionSwitcher.tsx +0 -136
  249. package/src/client/theme/ui/VersionSwitcher/index.ts +0 -1
  250. package/src/client/utils.ts +0 -49
package/src/node/mdx.ts CHANGED
@@ -1,25 +1,183 @@
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 rehypePrettyCode from "rehype-pretty-code";
6
- import type { Plugin } from "vite";
7
- import crypto from "crypto";
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'
8
9
 
9
- import type { BoltdocsConfig } from "./config";
10
- import { TransformCache } from "./cache";
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'
11
169
 
12
170
  /**
13
171
  * Persistent cache for MDX transformations.
14
172
  * Saves results to `.boltdocs/transform-mdx.json.gz`.
15
173
  */
16
- const mdxCache = new TransformCache("mdx");
17
- let mdxCacheLoaded = false;
174
+ const mdxCache = new TransformCache('mdx')
175
+ let mdxCacheLoaded = false
18
176
 
19
177
  /**
20
178
  * Configures the MDX compiler for Vite using `@mdx-js/rollup`.
21
179
  * Includes standard remark and rehype plugins for GitHub Flavored Markdown (GFM),
22
- * frontmatter extraction, auto-linking headers, and syntax highlighting via `rehype-pretty-code`.
180
+ * frontmatter extraction, and auto-linking headers.
23
181
  *
24
182
  * Also wraps the plugin with a persistent cache to avoid re-compiling unchanged MDX files.
25
183
  *
@@ -32,62 +190,62 @@ export function boltdocsMdxPlugin(
32
190
  compiler = mdxPlugin,
33
191
  ): Plugin {
34
192
  const extraRemarkPlugins =
35
- config?.plugins?.flatMap((p) => p.remarkPlugins || []) || [];
193
+ config?.plugins?.flatMap((p) => p.remarkPlugins || []) || []
36
194
  const extraRehypePlugins =
37
- config?.plugins?.flatMap((p) => p.rehypePlugins || []) || [];
195
+ config?.plugins?.flatMap((p) => p.rehypePlugins || []) || []
38
196
 
39
197
  const baseMdxPlugin = compiler({
40
- remarkPlugins: [remarkGfm, remarkFrontmatter, ...extraRemarkPlugins],
198
+ remarkPlugins: [
199
+ remarkGfm,
200
+ remarkFrontmatter,
201
+ [remarkShiki, config],
202
+ ...(extraRemarkPlugins as any[]),
203
+ ],
41
204
  rehypePlugins: [
42
205
  rehypeSlug,
43
- ...extraRehypePlugins,
44
- [
45
- rehypePrettyCode,
46
- {
47
- theme: config?.themeConfig?.codeTheme || "one-dark-pro",
48
- keepBackground: false,
49
- },
50
- ],
206
+ [rehypeShiki, config],
207
+ ...(extraRehypePlugins as any[]),
51
208
  ],
52
- jsxRuntime: "automatic",
53
- providerImportSource: "@mdx-js/react",
54
- }) as Plugin;
209
+ jsxRuntime: 'automatic',
210
+ providerImportSource: '@mdx-js/react',
211
+ }) as Plugin
55
212
 
56
213
  // @ts-ignore
57
214
  if (baseMdxPlugin.isMock) {
58
- console.log("MDX PLUGIN IS MOCKED");
215
+ console.log('MDX PLUGIN IS MOCKED')
59
216
  }
60
217
 
61
218
  return {
62
219
  ...baseMdxPlugin,
63
- name: "vite-plugin-boltdocs-mdx",
220
+ name: 'vite-plugin-boltdocs-mdx',
64
221
 
65
222
  async buildStart() {
66
- hits = 0;
67
- total = 0;
223
+ hits = 0
224
+ total = 0
68
225
  if (!mdxCacheLoaded) {
69
- mdxCache.load();
70
- mdxCacheLoaded = true;
226
+ mdxCache.load()
227
+ mdxCacheLoaded = true
71
228
  }
72
229
  if (baseMdxPlugin.buildStart) {
73
- await (baseMdxPlugin.buildStart as any).call(this);
230
+ await (baseMdxPlugin.buildStart as any).call(this)
74
231
  }
75
232
  },
76
233
 
77
234
  async transform(code, id, options) {
78
- if (!id.endsWith(".md") && !id.endsWith(".mdx")) {
79
- return (baseMdxPlugin.transform as any)?.call(this, code, id, options);
235
+ if (!id.endsWith('.md') && !id.endsWith('.mdx')) {
236
+ return (baseMdxPlugin.transform as any)?.call(this, code, id, options)
80
237
  }
81
238
 
82
- total++;
83
- // Create a cache key based on path, content, and config (simplified)
84
- const contentHash = crypto.createHash("md5").update(code).digest("hex");
85
- const cacheKey = `${id}:${contentHash}`;
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}`
86
244
 
87
- const cached = mdxCache.get(cacheKey);
245
+ const cached = mdxCache.get(cacheKey)
88
246
  if (cached) {
89
- hits++;
90
- return { code: cached, map: null };
247
+ hits++
248
+ return { code: cached, map: null }
91
249
  }
92
250
 
93
251
  const result = await (baseMdxPlugin.transform as any).call(
@@ -95,33 +253,27 @@ export function boltdocsMdxPlugin(
95
253
  code,
96
254
  id,
97
255
  options,
98
- );
256
+ )
99
257
 
100
- if (result && typeof result === "object" && result.code) {
101
- mdxCache.set(cacheKey, result.code);
258
+ if (result && typeof result === 'object' && result.code) {
259
+ mdxCache.set(cacheKey, result.code)
102
260
  }
103
261
 
104
- return result;
262
+ return result
105
263
  },
106
264
 
107
265
  async buildEnd() {
108
- mdxCache.save();
109
- await mdxCache.flush(); // Use instance flush or global flushCache
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
110
271
  if (baseMdxPlugin.buildEnd) {
111
- await (baseMdxPlugin.buildEnd as any).call(this);
272
+ await (baseMdxPlugin.buildEnd as any).call(this)
112
273
  }
113
274
  },
114
- };
115
- }
116
-
117
- /**
118
- * Returns the current MDX cache statistics.
119
- * @returns An object with total and hit counts
120
- * @deprecated Removed for performance
121
- */
122
- export function getMdxCacheStats() {
123
- return { hits: 0, total: 0 };
275
+ }
124
276
  }
125
277
 
126
- let hits = 0;
127
- let total = 0;
278
+ let hits = 0
279
+ let total = 0
@@ -1,7 +1,7 @@
1
- import { normalizePath } from "../utils";
2
- import type { BoltdocsConfig } from "../config";
3
- import type { BoltdocsPluginOptions } from "./types";
4
- import path from "path";
1
+ import { normalizePath } from '../utils'
2
+ import type { BoltdocsConfig } from '../config'
3
+ import type { BoltdocsPluginOptions } from './types'
4
+ import path from 'path'
5
5
 
6
6
  /**
7
7
  * Generates the raw source code for the virtual entry file (`\0virtual:boltdocs-entry`).
@@ -17,14 +17,10 @@ export function generateEntryCode(
17
17
  ): string {
18
18
  const homeImport = options.homePage
19
19
  ? `import HomePage from '${normalizePath(options.homePage)}';`
20
- : "";
21
- const homeOption = options.homePage ? "homePage: HomePage," : "";
22
- const customCssImport = options.customCss
23
- ? `import '${normalizePath(options.customCss)}';`
24
- : "";
25
-
20
+ : ''
21
+ const homeOption = options.homePage ? 'homePage: HomePage,' : ''
26
22
  const pluginComponents =
27
- config?.plugins?.flatMap((p) => Object.entries(p.components || {})) || [];
23
+ config?.plugins?.flatMap((p) => Object.entries(p.components || {})) || []
28
24
 
29
25
  const componentImports = pluginComponents
30
26
  .map(
@@ -34,19 +30,33 @@ export function generateEntryCode(
34
30
  ]) => `import * as _comp_${name} from '${normalizePath(path)}';
35
31
  const ${name} = _comp_${name}.default || _comp_${name}['${name}'] || _comp_${name};`,
36
32
  )
37
- .join("\n");
38
- const componentMap = pluginComponents.map(([name]) => name).join(", ");
33
+ .join('\n')
34
+ const componentMap = pluginComponents.map(([name]) => name).join(', ')
35
+
36
+ const docsDirName = path.basename(options.docsDir || 'docs')
39
37
 
40
- const docsDirName = path.basename(options.docsDir || "docs");
38
+ const externalEntries = Object.entries(config?.external || {})
39
+ const externalImports = externalEntries
40
+ .map(
41
+ ([_routePath, compPath], i) =>
42
+ `import _ext_${i} from '${normalizePath(compPath)}';`,
43
+ )
44
+ .join('\n')
45
+ const externalOption =
46
+ externalEntries.length > 0
47
+ ? `externalPages: { ${externalEntries
48
+ .map(([path], i) => `"${path}": _ext_${i}`)
49
+ .join(', ')} },`
50
+ : ''
41
51
 
42
52
  return `
43
53
  import { createBoltdocsApp as _createApp } from 'boltdocs/client';
44
- import 'boltdocs/style.css';
45
- ${customCssImport}
46
54
  import _routes from 'virtual:boltdocs-routes';
47
55
  import _config from 'virtual:boltdocs-config';
56
+ import _user_mdx_components from 'virtual:boltdocs-mdx-components';
48
57
  ${homeImport}
49
58
  ${componentImports}
59
+ ${externalImports}
50
60
 
51
61
  _createApp({
52
62
  target: '#root',
@@ -56,7 +66,8 @@ _createApp({
56
66
  modules: import.meta.glob('/${docsDirName}/**/*.{md,mdx}'),
57
67
  hot: import.meta.hot,
58
68
  ${homeOption}
59
- components: { ${componentMap} },
69
+ ${externalOption}
70
+ components: { ${componentMap}${componentMap ? ', ' : ''} ...(_user_mdx_components || {}) },
60
71
  });
61
- `;
72
+ `
62
73
  }
@@ -1,4 +1,4 @@
1
- import type { BoltdocsConfig } from "../config";
1
+ import type { BoltdocsConfig } from '../config'
2
2
 
3
3
  /**
4
4
  * Injects OpenGraph, Twitter, and generic SEO meta tags into the final HTML output.
@@ -9,8 +9,8 @@ import type { BoltdocsConfig } from "../config";
9
9
  * @returns The modified HTML string with injected tags
10
10
  */
11
11
  export function injectHtmlMeta(html: string, config: BoltdocsConfig): string {
12
- const title = config.themeConfig?.title || "Boltdocs";
13
- const description = config.themeConfig?.description || "";
12
+ const title = config.themeConfig?.title || 'Boltdocs'
13
+ const description = config.themeConfig?.description || ''
14
14
 
15
15
  const seoTags = [
16
16
  `<meta name="description" content="${description}">`,
@@ -21,7 +21,7 @@ export function injectHtmlMeta(html: string, config: BoltdocsConfig): string {
21
21
  `<meta name="twitter:title" content="${title}">`,
22
22
  `<meta name="twitter:description" content="${description}">`,
23
23
  `<meta name="generator" content="Boltdocs">`,
24
- ].join("\n ");
24
+ ].join('\n ')
25
25
 
26
26
  const themeScript = `
27
27
  <script>
@@ -39,17 +39,17 @@ export function injectHtmlMeta(html: string, config: BoltdocsConfig): string {
39
39
  } catch (e) {}
40
40
  })();
41
41
  </script>
42
- `;
42
+ `
43
43
 
44
- html = html.replace(/<title>.*?<\/title>/, `<title>${title}</title>`);
45
- html = html.replace("</head>", ` ${seoTags}\n${themeScript} </head>`);
44
+ html = html.replace(/<title>.*?<\/title>/, `<title>${title}</title>`)
45
+ html = html.replace('</head>', ` ${seoTags}\n${themeScript} </head>`)
46
46
 
47
- if (!html.includes("src/main")) {
47
+ if (!html.includes('src/main')) {
48
48
  html = html.replace(
49
- "</body>",
49
+ '</body>',
50
50
  ' <script type="module">import "virtual:boltdocs-entry";</script>\n </body>',
51
- );
51
+ )
52
52
  }
53
53
 
54
- return html;
54
+ return html
55
55
  }