boltdocs 1.10.2 → 1.11.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.
- package/package.json +29 -7
- package/src/client/app/config-context.tsx +18 -0
- package/src/client/app/docs-layout.tsx +14 -0
- package/src/client/app/index.tsx +132 -260
- package/src/client/app/mdx-component.tsx +52 -0
- package/src/client/app/mdx-components-context.tsx +23 -0
- package/src/client/app/mdx-page.tsx +20 -0
- package/src/client/app/preload.tsx +38 -30
- package/src/client/app/router.tsx +30 -0
- package/src/client/app/scroll-handler.tsx +40 -0
- package/src/client/app/theme-context.tsx +75 -0
- package/src/client/components/default-layout.tsx +80 -0
- package/src/client/components/docs-layout.tsx +105 -0
- package/src/client/components/icons-dev.tsx +74 -0
- package/src/client/components/mdx/admonition.tsx +107 -0
- package/src/client/components/mdx/badge.tsx +41 -0
- package/src/client/components/mdx/button.tsx +35 -0
- package/src/client/components/mdx/card.tsx +124 -0
- package/src/client/components/mdx/code-block.tsx +119 -0
- package/src/client/components/mdx/component-preview.tsx +47 -0
- package/src/client/components/mdx/component-props.tsx +83 -0
- package/src/client/components/mdx/field.tsx +66 -0
- package/src/client/components/mdx/file-tree.tsx +287 -0
- package/src/client/components/mdx/hooks/use-code-block.ts +56 -0
- package/src/client/components/mdx/hooks/use-component-preview.ts +16 -0
- package/src/client/components/mdx/hooks/useTable.ts +74 -0
- package/src/client/components/mdx/hooks/useTabs.ts +68 -0
- package/src/client/components/mdx/image.tsx +23 -0
- package/src/client/components/mdx/index.ts +53 -0
- package/src/client/components/mdx/link.tsx +38 -0
- package/src/client/components/mdx/list.tsx +192 -0
- package/src/client/components/mdx/table.tsx +156 -0
- package/src/client/components/mdx/tabs.tsx +135 -0
- package/src/client/components/mdx/video.tsx +68 -0
- package/src/client/components/primitives/breadcrumbs.tsx +79 -0
- package/src/client/components/primitives/button-group.tsx +54 -0
- package/src/client/components/primitives/button.tsx +145 -0
- package/src/client/components/primitives/helpers/observer.ts +120 -0
- package/src/client/components/primitives/index.ts +17 -0
- package/src/client/components/primitives/link.tsx +122 -0
- package/src/client/components/primitives/menu.tsx +159 -0
- package/src/client/components/primitives/navbar.tsx +359 -0
- package/src/client/components/primitives/navigation-menu.tsx +116 -0
- package/src/client/components/primitives/on-this-page.tsx +461 -0
- package/src/client/components/primitives/page-nav.tsx +87 -0
- package/src/client/components/primitives/popover.tsx +47 -0
- package/src/client/components/primitives/search-dialog.tsx +183 -0
- package/src/client/components/primitives/sidebar.tsx +154 -0
- package/src/client/components/primitives/tabs.tsx +90 -0
- package/src/client/components/primitives/tooltip.tsx +83 -0
- package/src/client/components/primitives/types.ts +11 -0
- package/src/client/components/ui-base/breadcrumbs.tsx +42 -0
- package/src/client/components/ui-base/copy-markdown.tsx +112 -0
- package/src/client/components/ui-base/error-boundary.tsx +52 -0
- package/src/client/components/ui-base/github-stars.tsx +27 -0
- package/src/client/components/ui-base/head.tsx +69 -0
- package/src/client/components/ui-base/loading.tsx +87 -0
- package/src/client/components/ui-base/navbar.tsx +138 -0
- package/src/client/components/ui-base/not-found.tsx +24 -0
- package/src/client/components/ui-base/on-this-page.tsx +152 -0
- package/src/client/components/ui-base/page-nav.tsx +39 -0
- package/src/client/components/ui-base/powered-by.tsx +19 -0
- package/src/client/components/ui-base/progress-bar.tsx +67 -0
- package/src/client/components/ui-base/search-dialog.tsx +82 -0
- package/src/client/components/ui-base/sidebar.tsx +104 -0
- package/src/client/components/ui-base/tabs.tsx +65 -0
- package/src/client/components/ui-base/theme-toggle.tsx +32 -0
- package/src/client/hooks/index.ts +12 -0
- package/src/client/hooks/use-breadcrumbs.ts +22 -0
- package/src/client/hooks/use-i18n.ts +84 -0
- package/src/client/hooks/use-localized-to.ts +95 -0
- package/src/client/hooks/use-location.ts +5 -0
- package/src/client/hooks/use-navbar.ts +60 -0
- package/src/client/hooks/use-onthispage.ts +23 -0
- package/src/client/hooks/use-page-nav.ts +22 -0
- package/src/client/hooks/use-routes.ts +72 -0
- package/src/client/hooks/use-search.ts +71 -0
- package/src/client/hooks/use-sidebar.ts +49 -0
- package/src/client/hooks/use-tabs.ts +43 -0
- package/src/client/hooks/use-version.ts +78 -0
- package/src/client/index.ts +55 -17
- package/src/client/integrations/codesandbox.ts +179 -0
- package/src/client/ssr.tsx +27 -16
- package/src/client/theme/neutral.css +360 -0
- package/src/client/types.ts +131 -27
- package/src/client/utils/cn.ts +6 -0
- package/src/client/utils/copy-clipboard.ts +22 -0
- package/src/client/utils/get-base-file-path.ts +21 -0
- package/src/client/utils/github.ts +121 -0
- package/src/client/utils/use-on-change.ts +15 -0
- package/src/client/virtual.d.ts +24 -0
- package/src/node/cache.ts +156 -156
- package/src/node/config.ts +159 -103
- package/src/node/index.ts +13 -13
- package/src/node/mdx.ts +213 -61
- package/src/node/plugin/entry.ts +29 -18
- package/src/node/plugin/html.ts +11 -11
- package/src/node/plugin/index.ts +161 -83
- package/src/node/plugin/types.ts +2 -4
- package/src/node/routes/cache.ts +6 -6
- package/src/node/routes/index.ts +206 -113
- package/src/node/routes/parser.ts +106 -81
- package/src/node/routes/sorter.ts +15 -15
- package/src/node/routes/types.ts +24 -24
- package/src/node/ssg/index.ts +46 -46
- package/src/node/ssg/meta.ts +4 -4
- package/src/node/ssg/options.ts +5 -5
- package/src/node/ssg/sitemap.ts +14 -14
- package/src/node/utils.ts +31 -31
- package/tsconfig.json +25 -20
- package/tsup.config.ts +23 -14
- package/dist/PackageManagerTabs-NVT7G625.mjs +0 -99
- package/dist/SearchDialog-AGVF6JBO.mjs +0 -194
- package/dist/SearchDialog-YPDOM7Q6.css +0 -2847
- package/dist/Video-KNTY5BNO.mjs +0 -6
- package/dist/cache-KNL5B4EE.mjs +0 -12
- package/dist/chunk-7SFUJWTB.mjs +0 -211
- package/dist/chunk-FFBNU6IJ.mjs +0 -386
- package/dist/chunk-FMTOYQLO.mjs +0 -37
- package/dist/chunk-TKLQWU7H.mjs +0 -1920
- package/dist/chunk-Z7JHYNAS.mjs +0 -57
- package/dist/client/index.css +0 -2847
- package/dist/client/index.d.mts +0 -372
- package/dist/client/index.d.ts +0 -372
- package/dist/client/index.js +0 -3630
- package/dist/client/index.mjs +0 -697
- package/dist/client/ssr.css +0 -2847
- package/dist/client/ssr.d.mts +0 -27
- package/dist/client/ssr.d.ts +0 -27
- package/dist/client/ssr.js +0 -2928
- package/dist/client/ssr.mjs +0 -33
- package/dist/config-BsFQ-ErD.d.mts +0 -159
- package/dist/config-BsFQ-ErD.d.ts +0 -159
- package/dist/node/index.d.mts +0 -91
- package/dist/node/index.d.ts +0 -91
- package/dist/node/index.js +0 -1187
- package/dist/node/index.mjs +0 -762
- package/dist/types-Dj-bfnC3.d.mts +0 -74
- package/dist/types-Dj-bfnC3.d.ts +0 -74
- package/src/client/theme/components/CodeBlock/CodeBlock.tsx +0 -61
- package/src/client/theme/components/CodeBlock/index.ts +0 -1
- package/src/client/theme/components/PackageManagerTabs/PackageManagerTabs.tsx +0 -131
- package/src/client/theme/components/PackageManagerTabs/index.ts +0 -1
- package/src/client/theme/components/PackageManagerTabs/pkg-tabs.css +0 -64
- package/src/client/theme/components/Playground/Playground.tsx +0 -180
- package/src/client/theme/components/Playground/index.ts +0 -1
- package/src/client/theme/components/Playground/playground.css +0 -238
- package/src/client/theme/components/Video/Video.tsx +0 -84
- package/src/client/theme/components/Video/index.ts +0 -1
- package/src/client/theme/components/Video/video.css +0 -41
- package/src/client/theme/components/mdx/Admonition.tsx +0 -80
- package/src/client/theme/components/mdx/Badge.tsx +0 -31
- package/src/client/theme/components/mdx/Button.tsx +0 -50
- package/src/client/theme/components/mdx/Card.tsx +0 -80
- package/src/client/theme/components/mdx/Field.tsx +0 -60
- package/src/client/theme/components/mdx/FileTree.tsx +0 -229
- package/src/client/theme/components/mdx/List.tsx +0 -57
- package/src/client/theme/components/mdx/Table.tsx +0 -151
- package/src/client/theme/components/mdx/Tabs.tsx +0 -123
- package/src/client/theme/components/mdx/index.ts +0 -27
- package/src/client/theme/components/mdx/mdx-components.css +0 -764
- package/src/client/theme/icons/bun.tsx +0 -62
- package/src/client/theme/icons/deno.tsx +0 -20
- package/src/client/theme/icons/discord.tsx +0 -12
- package/src/client/theme/icons/github.tsx +0 -15
- package/src/client/theme/icons/npm.tsx +0 -13
- package/src/client/theme/icons/pnpm.tsx +0 -72
- package/src/client/theme/icons/twitter.tsx +0 -12
- package/src/client/theme/styles/markdown.css +0 -394
- package/src/client/theme/styles/variables.css +0 -175
- package/src/client/theme/styles.css +0 -39
- package/src/client/theme/ui/Breadcrumbs/Breadcrumbs.tsx +0 -68
- package/src/client/theme/ui/Breadcrumbs/index.ts +0 -1
- package/src/client/theme/ui/CopyMarkdown/CopyMarkdown.tsx +0 -82
- package/src/client/theme/ui/CopyMarkdown/copy-markdown.css +0 -112
- package/src/client/theme/ui/CopyMarkdown/index.ts +0 -1
- package/src/client/theme/ui/ErrorBoundary/ErrorBoundary.tsx +0 -50
- package/src/client/theme/ui/ErrorBoundary/error-boundary.css +0 -55
- package/src/client/theme/ui/ErrorBoundary/index.ts +0 -1
- package/src/client/theme/ui/Footer/footer.css +0 -32
- package/src/client/theme/ui/Head/Head.tsx +0 -69
- package/src/client/theme/ui/Head/index.ts +0 -1
- package/src/client/theme/ui/LanguageSwitcher/LanguageSwitcher.tsx +0 -125
- package/src/client/theme/ui/LanguageSwitcher/index.ts +0 -1
- package/src/client/theme/ui/LanguageSwitcher/language-switcher.css +0 -98
- package/src/client/theme/ui/Layout/Layout.tsx +0 -203
- package/src/client/theme/ui/Layout/base.css +0 -106
- package/src/client/theme/ui/Layout/index.ts +0 -2
- package/src/client/theme/ui/Layout/pagination.css +0 -72
- package/src/client/theme/ui/Layout/responsive.css +0 -47
- package/src/client/theme/ui/Link/Link.tsx +0 -392
- package/src/client/theme/ui/Link/LinkPreview.tsx +0 -59
- package/src/client/theme/ui/Link/index.ts +0 -2
- package/src/client/theme/ui/Link/link-preview.css +0 -48
- package/src/client/theme/ui/Loading/Loading.tsx +0 -10
- package/src/client/theme/ui/Loading/index.ts +0 -1
- package/src/client/theme/ui/Loading/loading.css +0 -30
- package/src/client/theme/ui/Navbar/GithubStars.tsx +0 -27
- package/src/client/theme/ui/Navbar/Navbar.tsx +0 -193
- package/src/client/theme/ui/Navbar/Tabs.tsx +0 -99
- package/src/client/theme/ui/Navbar/index.ts +0 -2
- package/src/client/theme/ui/Navbar/navbar.css +0 -347
- package/src/client/theme/ui/NotFound/NotFound.tsx +0 -19
- package/src/client/theme/ui/NotFound/index.ts +0 -1
- package/src/client/theme/ui/NotFound/not-found.css +0 -64
- package/src/client/theme/ui/OnThisPage/OnThisPage.tsx +0 -244
- package/src/client/theme/ui/OnThisPage/index.ts +0 -1
- package/src/client/theme/ui/OnThisPage/toc.css +0 -152
- package/src/client/theme/ui/PoweredBy/PoweredBy.tsx +0 -18
- package/src/client/theme/ui/PoweredBy/index.ts +0 -1
- package/src/client/theme/ui/PoweredBy/powered-by.css +0 -76
- package/src/client/theme/ui/ProgressBar/ProgressBar.css +0 -17
- package/src/client/theme/ui/ProgressBar/ProgressBar.tsx +0 -51
- package/src/client/theme/ui/ProgressBar/index.ts +0 -1
- package/src/client/theme/ui/SearchDialog/SearchDialog.tsx +0 -209
- package/src/client/theme/ui/SearchDialog/index.ts +0 -1
- package/src/client/theme/ui/SearchDialog/search.css +0 -152
- package/src/client/theme/ui/Sidebar/Sidebar.tsx +0 -244
- package/src/client/theme/ui/Sidebar/index.ts +0 -1
- package/src/client/theme/ui/Sidebar/sidebar.css +0 -230
- package/src/client/theme/ui/ThemeToggle/ThemeToggle.tsx +0 -69
- package/src/client/theme/ui/ThemeToggle/index.ts +0 -1
- package/src/client/theme/ui/VersionSwitcher/VersionSwitcher.tsx +0 -136
- package/src/client/theme/ui/VersionSwitcher/index.ts +0 -1
- package/src/client/utils.ts +0 -49
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "boltdocs",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.11.0",
|
|
4
4
|
"description": "A lightweight documentation generator for React projects.",
|
|
5
5
|
"main": "dist/node/index.js",
|
|
6
6
|
"module": "dist/node/index.mjs",
|
|
@@ -19,11 +19,29 @@
|
|
|
19
19
|
"import": "./dist/client/index.mjs",
|
|
20
20
|
"require": "./dist/client/index.js"
|
|
21
21
|
},
|
|
22
|
-
"./
|
|
22
|
+
"./client/hooks": {
|
|
23
|
+
"types": "./dist/client/hooks/index.d.ts",
|
|
24
|
+
"import": "./dist/client/hooks/index.mjs",
|
|
25
|
+
"require": "./dist/client/hooks/index.js"
|
|
26
|
+
},
|
|
27
|
+
"./client/primitives": {
|
|
28
|
+
"types": "./dist/client/components/primitives/index.d.ts",
|
|
29
|
+
"import": "./dist/client/components/primitives/index.mjs",
|
|
30
|
+
"require": "./dist/client/components/primitives/index.js"
|
|
31
|
+
},
|
|
32
|
+
"./client/types": {
|
|
33
|
+
"types": "./dist/client/types.d.ts",
|
|
34
|
+
"import": "./dist/client/types.mjs",
|
|
35
|
+
"require": "./dist/client/types.js"
|
|
36
|
+
},
|
|
37
|
+
"./theme/neutral.css": "./src/client/theme/neutral.css"
|
|
23
38
|
},
|
|
24
39
|
"scripts": {
|
|
25
40
|
"build": "tsup",
|
|
26
|
-
"dev": "tsup --watch"
|
|
41
|
+
"dev": "tsup --watch",
|
|
42
|
+
"format": "pnpm exec biome format --write",
|
|
43
|
+
"lint": "pnpm exec biome lint --write",
|
|
44
|
+
"check": "pnpm exec biome check --write"
|
|
27
45
|
},
|
|
28
46
|
"keywords": [
|
|
29
47
|
"docs",
|
|
@@ -42,26 +60,30 @@
|
|
|
42
60
|
"dependencies": {
|
|
43
61
|
"@mdx-js/react": "^3.1.1",
|
|
44
62
|
"@mdx-js/rollup": "^3.1.1",
|
|
63
|
+
"class-variance-authority": "^0.7.1",
|
|
64
|
+
"clsx": "^2.1.1",
|
|
65
|
+
"codesandbox": "^2.2.3",
|
|
45
66
|
"fast-glob": "^3.3.3",
|
|
46
67
|
"github-slugger": "^2.0.0",
|
|
47
68
|
"gray-matter": "^4.0.3",
|
|
48
69
|
"lucide-react": "^0.575.0",
|
|
49
|
-
"react-
|
|
70
|
+
"react-aria-components": "^1.16.0",
|
|
50
71
|
"react-router-dom": "^6.30.3",
|
|
51
|
-
"rehype-pretty-code": "^0.14.1",
|
|
52
72
|
"rehype-slug": "^6.0.0",
|
|
53
73
|
"remark-frontmatter": "^5.0.0",
|
|
54
74
|
"remark-gfm": "^4.0.1",
|
|
75
|
+
"scroll-into-view-if-needed": "^3.1.0",
|
|
55
76
|
"sharp": "^0.34.5",
|
|
56
77
|
"shiki": "^3.23.0",
|
|
57
78
|
"svgo": "^4.0.1",
|
|
79
|
+
"tailwind-merge": "^3.5.0",
|
|
58
80
|
"unist-util-visit": "^5.1.0",
|
|
59
81
|
"vite": "^7.3.1",
|
|
60
82
|
"vite-plugin-image-optimizer": "^2.0.3"
|
|
61
83
|
},
|
|
62
84
|
"peerDependencies": {
|
|
63
|
-
"react": "^
|
|
64
|
-
"react-dom": "^
|
|
85
|
+
"react": "^19.1.0",
|
|
86
|
+
"react-dom": "^19.1.0"
|
|
65
87
|
},
|
|
66
88
|
"packageManager": "pnpm@10.30.2",
|
|
67
89
|
"devDependencies": {
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { createContext, use } from 'react'
|
|
2
|
+
import type { BoltdocsConfig } from '@node/config'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Context for the global documentation configuration.
|
|
6
|
+
*/
|
|
7
|
+
export const ConfigContext = createContext<BoltdocsConfig | null>(null)
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Hook to access the Boltdocs configuration.
|
|
11
|
+
*/
|
|
12
|
+
export function useConfig() {
|
|
13
|
+
const context = use(ConfigContext)
|
|
14
|
+
if (!context) {
|
|
15
|
+
throw new Error('useConfig must be used within a ConfigProvider')
|
|
16
|
+
}
|
|
17
|
+
return context
|
|
18
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Outlet } from 'react-router-dom'
|
|
2
|
+
import UserLayout from 'virtual:boltdocs-layout'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Wraps the docs Outlet with the user's (or default) layout component.
|
|
6
|
+
* The Layout receives the routed page as `children`.
|
|
7
|
+
*/
|
|
8
|
+
export function DocsLayout() {
|
|
9
|
+
return (
|
|
10
|
+
<UserLayout>
|
|
11
|
+
<Outlet />
|
|
12
|
+
</UserLayout>
|
|
13
|
+
)
|
|
14
|
+
}
|
package/src/client/app/index.tsx
CHANGED
|
@@ -1,90 +1,22 @@
|
|
|
1
|
-
import React, { useEffect, useState } from
|
|
2
|
-
import ReactDOM from
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
import
|
|
11
|
-
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
useLayoutEffect,
|
|
21
|
-
} from "react";
|
|
22
|
-
import { Link as LucideLink } from "lucide-react";
|
|
23
|
-
|
|
24
|
-
export const ConfigContext = createContext<any>(null);
|
|
25
|
-
|
|
26
|
-
export function useConfig() {
|
|
27
|
-
return useContext(ConfigContext);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
import { CodeBlock } from "../theme/components/CodeBlock";
|
|
31
|
-
const Video = lazy(() =>
|
|
32
|
-
import("../theme/components/Video").then((m) => ({ default: m.Video })),
|
|
33
|
-
);
|
|
34
|
-
const PackageManagerTabs = lazy(() =>
|
|
35
|
-
import("../theme/components/PackageManagerTabs").then((m) => ({
|
|
36
|
-
default: m.PackageManagerTabs,
|
|
37
|
-
})),
|
|
38
|
-
);
|
|
39
|
-
declare global {
|
|
40
|
-
interface ImportMeta {
|
|
41
|
-
env: Record<string, any>;
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
import { PreloadProvider } from "./preload";
|
|
46
|
-
|
|
47
|
-
const Heading = ({
|
|
48
|
-
level,
|
|
49
|
-
id,
|
|
50
|
-
children,
|
|
51
|
-
}: {
|
|
52
|
-
level: number;
|
|
53
|
-
id?: string;
|
|
54
|
-
children: React.ReactNode;
|
|
55
|
-
}) => {
|
|
56
|
-
const Tag = `h${level}` as keyof JSX.IntrinsicElements;
|
|
57
|
-
return (
|
|
58
|
-
<Tag id={id} className="boltdocs-heading">
|
|
59
|
-
{children}
|
|
60
|
-
{id && (
|
|
61
|
-
<a href={`#${id}`} className="header-anchor" aria-label="Anchor">
|
|
62
|
-
<LucideLink size={16} />
|
|
63
|
-
</a>
|
|
64
|
-
)}
|
|
65
|
-
</Tag>
|
|
66
|
-
);
|
|
67
|
-
};
|
|
68
|
-
|
|
69
|
-
const mdxComponents = {
|
|
70
|
-
h1: (props: any) => <Heading level={1} {...props} />,
|
|
71
|
-
h2: (props: any) => <Heading level={2} {...props} />,
|
|
72
|
-
h3: (props: any) => <Heading level={3} {...props} />,
|
|
73
|
-
h4: (props: any) => <Heading level={4} {...props} />,
|
|
74
|
-
h5: (props: any) => <Heading level={5} {...props} />,
|
|
75
|
-
h6: (props: any) => <Heading level={6} {...props} />,
|
|
76
|
-
pre: (props: any) => <CodeBlock {...props}>{props.children}</CodeBlock>,
|
|
77
|
-
video: (props: any) => (
|
|
78
|
-
<Suspense fallback={<div className="video-skeleton" />}>
|
|
79
|
-
<Video {...props} />
|
|
80
|
-
</Suspense>
|
|
81
|
-
),
|
|
82
|
-
PackageManagerTabs: (props: any) => (
|
|
83
|
-
<Suspense fallback={<div className="pkg-tabs-skeleton" />}>
|
|
84
|
-
<PackageManagerTabs {...props} />
|
|
85
|
-
</Suspense>
|
|
86
|
-
),
|
|
87
|
-
};
|
|
1
|
+
import React, { useEffect, useState, useMemo } from 'react'
|
|
2
|
+
import ReactDOM from 'react-dom/client'
|
|
3
|
+
import { BrowserRouter, Routes, Route } from 'react-router-dom'
|
|
4
|
+
import { NotFound } from '@components/ui-base/not-found'
|
|
5
|
+
import { Loading } from '@components/ui-base/loading'
|
|
6
|
+
import { ThemeProvider } from './theme-context'
|
|
7
|
+
import type { ComponentRoute, CreateBoltdocsAppOptions } from '../types'
|
|
8
|
+
import type { BoltdocsConfig } from '@node/config'
|
|
9
|
+
|
|
10
|
+
import UserLayout from 'virtual:boltdocs-layout'
|
|
11
|
+
|
|
12
|
+
import { PreloadProvider } from './preload'
|
|
13
|
+
import { BoltdocsRouterProvider } from './router'
|
|
14
|
+
import { ConfigContext } from './config-context'
|
|
15
|
+
import { ScrollHandler } from './scroll-handler'
|
|
16
|
+
import { DocsLayout } from './docs-layout'
|
|
17
|
+
import { MdxPage } from './mdx-page'
|
|
18
|
+
import { MdxComponentsProvider } from './mdx-components-context'
|
|
19
|
+
import { mdxComponentsDefault } from './mdx-component'
|
|
88
20
|
|
|
89
21
|
export function AppShell({
|
|
90
22
|
initialRoutes,
|
|
@@ -93,194 +25,124 @@ export function AppShell({
|
|
|
93
25
|
modules,
|
|
94
26
|
hot,
|
|
95
27
|
homePage: HomePage,
|
|
28
|
+
externalPages,
|
|
96
29
|
components: customComponents = {},
|
|
97
30
|
}: {
|
|
98
|
-
initialRoutes: ComponentRoute[]
|
|
99
|
-
initialConfig:
|
|
100
|
-
docsDirName: string
|
|
101
|
-
modules: Record<string, () => Promise<
|
|
102
|
-
hot?:
|
|
103
|
-
homePage?: React.ComponentType
|
|
104
|
-
|
|
31
|
+
initialRoutes: ComponentRoute[]
|
|
32
|
+
initialConfig: BoltdocsConfig
|
|
33
|
+
docsDirName: string
|
|
34
|
+
modules: Record<string, () => Promise<{ default: React.ComponentType }>>
|
|
35
|
+
hot?: CreateBoltdocsAppOptions['hot']
|
|
36
|
+
homePage?: React.ComponentType
|
|
37
|
+
externalPages?: Record<string, React.ComponentType>
|
|
38
|
+
components?: Record<string, React.ComponentType>
|
|
105
39
|
}) {
|
|
106
|
-
const [routesInfo, setRoutesInfo] = useState<ComponentRoute[]>(initialRoutes)
|
|
107
|
-
const [config] = useState(initialConfig)
|
|
40
|
+
const [routesInfo, setRoutesInfo] = useState<ComponentRoute[]>(initialRoutes)
|
|
41
|
+
const [config] = useState(initialConfig)
|
|
42
|
+
const computedExternalPages = externalPages || {}
|
|
108
43
|
|
|
109
|
-
const
|
|
110
|
-
return
|
|
44
|
+
const resolvedRoutes = useMemo(() => {
|
|
45
|
+
return routesInfo
|
|
111
46
|
.filter(
|
|
112
|
-
(route) =>
|
|
47
|
+
(route) =>
|
|
48
|
+
!(HomePage && (route.path === '/' || route.path === '')) &&
|
|
49
|
+
!computedExternalPages[route.path === '' ? '/' : route.path],
|
|
113
50
|
)
|
|
114
51
|
.map((route) => {
|
|
115
52
|
const loaderKey = Object.keys(modules).find(
|
|
116
53
|
(k) => k === `/${docsDirName}/${route.filePath}`,
|
|
117
|
-
)
|
|
118
|
-
const loader = loaderKey ? modules[loaderKey] : null
|
|
54
|
+
)
|
|
55
|
+
const loader = loaderKey ? modules[loaderKey] : null
|
|
119
56
|
|
|
120
57
|
return {
|
|
121
58
|
...route,
|
|
122
59
|
Component: React.lazy(() => {
|
|
123
|
-
if (!loader)
|
|
124
|
-
|
|
125
|
-
return loader() as any;
|
|
60
|
+
if (!loader) return Promise.resolve({ default: NotFound })
|
|
61
|
+
return loader() as any
|
|
126
62
|
}),
|
|
127
|
-
}
|
|
128
|
-
})
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
const [resolvedRoutes, setResolvedRoutes] = useState<any[]>(() =>
|
|
132
|
-
resolveRoutes(initialRoutes),
|
|
133
|
-
);
|
|
63
|
+
}
|
|
64
|
+
})
|
|
65
|
+
}, [routesInfo, modules, docsDirName, HomePage, computedExternalPages])
|
|
134
66
|
|
|
135
67
|
// Subscribe to HMR events
|
|
136
68
|
useEffect(() => {
|
|
137
69
|
if (hot) {
|
|
138
|
-
hot.on(
|
|
139
|
-
setRoutesInfo(newRoutes)
|
|
140
|
-
})
|
|
70
|
+
hot.on('boltdocs:routes-update', (newRoutes: ComponentRoute[]) => {
|
|
71
|
+
setRoutesInfo(newRoutes)
|
|
72
|
+
})
|
|
141
73
|
}
|
|
142
|
-
}, [hot])
|
|
74
|
+
}, [hot])
|
|
143
75
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
76
|
+
const allComponents = useMemo(
|
|
77
|
+
() => ({ ...mdxComponentsDefault, ...customComponents }),
|
|
78
|
+
[customComponents],
|
|
79
|
+
)
|
|
148
80
|
|
|
149
81
|
return (
|
|
150
|
-
<
|
|
151
|
-
<
|
|
152
|
-
<
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
key={route.path}
|
|
181
|
-
path={route.path === "" ? "/" : route.path}
|
|
182
|
-
element={
|
|
183
|
-
<React.Suspense fallback={<Loading />}>
|
|
184
|
-
<MdxPage
|
|
185
|
-
Component={route.Component}
|
|
186
|
-
customComponents={customComponents}
|
|
82
|
+
<ThemeProvider>
|
|
83
|
+
<MdxComponentsProvider components={allComponents}>
|
|
84
|
+
<ConfigContext.Provider value={config}>
|
|
85
|
+
<BoltdocsRouterProvider>
|
|
86
|
+
<PreloadProvider routes={routesInfo} modules={modules}>
|
|
87
|
+
<ScrollHandler />
|
|
88
|
+
<Routes>
|
|
89
|
+
{/* Custom home page with user layout */}
|
|
90
|
+
{HomePage && (
|
|
91
|
+
<Route
|
|
92
|
+
path="/"
|
|
93
|
+
element={
|
|
94
|
+
<UserLayout>
|
|
95
|
+
<HomePage />
|
|
96
|
+
</UserLayout>
|
|
97
|
+
}
|
|
98
|
+
/>
|
|
99
|
+
)}
|
|
100
|
+
|
|
101
|
+
{/* Custom External Pages with user layout */}
|
|
102
|
+
{Object.entries(computedExternalPages).map(
|
|
103
|
+
([extPath, ExtComponent]) => (
|
|
104
|
+
<Route
|
|
105
|
+
key={extPath}
|
|
106
|
+
path={extPath}
|
|
107
|
+
element={
|
|
108
|
+
<UserLayout>
|
|
109
|
+
<ExtComponent />
|
|
110
|
+
</UserLayout>
|
|
111
|
+
}
|
|
187
112
|
/>
|
|
188
|
-
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
if (hash) {
|
|
223
|
-
const id = hash.replace("#", "");
|
|
224
|
-
const element = document.getElementById(id);
|
|
225
|
-
if (element) {
|
|
226
|
-
const offset = 80;
|
|
227
|
-
const containerRect = container.getBoundingClientRect().top;
|
|
228
|
-
const elementRect = element.getBoundingClientRect().top;
|
|
229
|
-
const elementPosition = elementRect - containerRect;
|
|
230
|
-
const offsetPosition = elementPosition - offset + container.scrollTop;
|
|
231
|
-
|
|
232
|
-
container.scrollTo({
|
|
233
|
-
top: offsetPosition,
|
|
234
|
-
behavior: "smooth",
|
|
235
|
-
});
|
|
236
|
-
return;
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
container.scrollTo(0, 0);
|
|
240
|
-
}, [pathname, hash]);
|
|
241
|
-
|
|
242
|
-
return null;
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
/** Wrapper layout for doc pages (sidebar + content + TOC) */
|
|
246
|
-
function DocsLayout({
|
|
247
|
-
config,
|
|
248
|
-
routes,
|
|
249
|
-
}: {
|
|
250
|
-
config: any;
|
|
251
|
-
routes: ComponentRoute[];
|
|
252
|
-
}) {
|
|
253
|
-
return (
|
|
254
|
-
<ThemeLayout
|
|
255
|
-
config={config}
|
|
256
|
-
routes={routes}
|
|
257
|
-
{...config.themeConfig?.layoutProps}
|
|
258
|
-
>
|
|
259
|
-
<Outlet />
|
|
260
|
-
</ThemeLayout>
|
|
261
|
-
);
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
/**
|
|
265
|
-
* Renders an MDX page securely, injecting required custom components.
|
|
266
|
-
* For example, this overrides the default `<pre>` HTML tags emitted by MDX
|
|
267
|
-
* with the Boltdocs `CodeBlock` component for syntax highlighting.
|
|
268
|
-
*
|
|
269
|
-
* @param props - Contains the dynamically loaded React component representing the MDX page
|
|
270
|
-
*/
|
|
271
|
-
function MdxPage({
|
|
272
|
-
Component,
|
|
273
|
-
customComponents = {},
|
|
274
|
-
}: {
|
|
275
|
-
Component: React.LazyExoticComponent<any>;
|
|
276
|
-
customComponents?: Record<string, React.ComponentType<any>>;
|
|
277
|
-
}) {
|
|
278
|
-
const allComponents = { ...mdxComponents, ...customComponents };
|
|
279
|
-
return (
|
|
280
|
-
<MDXProvider components={allComponents}>
|
|
281
|
-
<Component />
|
|
282
|
-
</MDXProvider>
|
|
283
|
-
);
|
|
113
|
+
),
|
|
114
|
+
)}
|
|
115
|
+
|
|
116
|
+
{/* Documentation pages WITH sidebar + TOC layout */}
|
|
117
|
+
<Route key="docs-layout" element={<DocsLayout />}>
|
|
118
|
+
{resolvedRoutes.map((route) => (
|
|
119
|
+
<Route
|
|
120
|
+
key={route.path}
|
|
121
|
+
path={route.path === '' ? '/' : route.path}
|
|
122
|
+
element={
|
|
123
|
+
<React.Suspense fallback={<Loading />}>
|
|
124
|
+
<MdxPage Component={route.Component} />
|
|
125
|
+
</React.Suspense>
|
|
126
|
+
}
|
|
127
|
+
/>
|
|
128
|
+
))}
|
|
129
|
+
</Route>
|
|
130
|
+
|
|
131
|
+
<Route
|
|
132
|
+
path="*"
|
|
133
|
+
element={
|
|
134
|
+
<UserLayout>
|
|
135
|
+
<NotFound />
|
|
136
|
+
</UserLayout>
|
|
137
|
+
}
|
|
138
|
+
/>
|
|
139
|
+
</Routes>
|
|
140
|
+
</PreloadProvider>
|
|
141
|
+
</BoltdocsRouterProvider>
|
|
142
|
+
</ConfigContext.Provider>
|
|
143
|
+
</MdxComponentsProvider>
|
|
144
|
+
</ThemeProvider>
|
|
145
|
+
)
|
|
284
146
|
}
|
|
285
147
|
|
|
286
148
|
/**
|
|
@@ -305,13 +167,22 @@ function MdxPage({
|
|
|
305
167
|
* ```
|
|
306
168
|
*/
|
|
307
169
|
export function createBoltdocsApp(options: CreateBoltdocsAppOptions) {
|
|
308
|
-
const {
|
|
309
|
-
|
|
310
|
-
|
|
170
|
+
const {
|
|
171
|
+
target,
|
|
172
|
+
routes,
|
|
173
|
+
docsDirName,
|
|
174
|
+
config,
|
|
175
|
+
modules,
|
|
176
|
+
hot,
|
|
177
|
+
homePage,
|
|
178
|
+
externalPages,
|
|
179
|
+
components,
|
|
180
|
+
} = options
|
|
181
|
+
const container = document.querySelector(target)
|
|
311
182
|
if (!container) {
|
|
312
183
|
throw new Error(
|
|
313
184
|
`[boltdocs] Mount target "${target}" not found in document.`,
|
|
314
|
-
)
|
|
185
|
+
)
|
|
315
186
|
}
|
|
316
187
|
|
|
317
188
|
const app = (
|
|
@@ -324,16 +195,17 @@ export function createBoltdocsApp(options: CreateBoltdocsAppOptions) {
|
|
|
324
195
|
modules={modules}
|
|
325
196
|
hot={hot}
|
|
326
197
|
homePage={homePage}
|
|
327
|
-
|
|
198
|
+
externalPages={externalPages}
|
|
199
|
+
components={components}
|
|
328
200
|
/>
|
|
329
201
|
</BrowserRouter>
|
|
330
202
|
</React.StrictMode>
|
|
331
|
-
)
|
|
203
|
+
)
|
|
332
204
|
|
|
333
205
|
// SSG pre-renders a shell with mock components for SEO crawlers.
|
|
334
206
|
// We always use createRoot because the SSG output doesn't match the
|
|
335
207
|
// real client-side component tree (components are lazy/dynamic).
|
|
336
208
|
// Clear any SSG placeholder content before mounting.
|
|
337
|
-
container.innerHTML =
|
|
338
|
-
ReactDOM.createRoot(container as HTMLElement).render(app)
|
|
209
|
+
container.innerHTML = ''
|
|
210
|
+
ReactDOM.createRoot(container as HTMLElement).render(app)
|
|
339
211
|
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type React from 'react'
|
|
2
|
+
import { Link as LucideLink } from 'lucide-react'
|
|
3
|
+
import * as MdxComponents from '@components/mdx'
|
|
4
|
+
|
|
5
|
+
const Heading = ({
|
|
6
|
+
level,
|
|
7
|
+
id,
|
|
8
|
+
children,
|
|
9
|
+
}: {
|
|
10
|
+
level: number
|
|
11
|
+
id?: string
|
|
12
|
+
children?: React.ReactNode
|
|
13
|
+
}) => {
|
|
14
|
+
const Tag = `h${level}` as keyof JSX.IntrinsicElements
|
|
15
|
+
return (
|
|
16
|
+
<Tag id={id} className="boltdocs-heading">
|
|
17
|
+
{children}
|
|
18
|
+
{id && (
|
|
19
|
+
<a href={`#${id}`} className="header-anchor" aria-label="Anchor">
|
|
20
|
+
<LucideLink size={16} />
|
|
21
|
+
</a>
|
|
22
|
+
)}
|
|
23
|
+
</Tag>
|
|
24
|
+
)
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export const mdxComponentsDefault = {
|
|
28
|
+
...MdxComponents,
|
|
29
|
+
h1: (props: React.HTMLAttributes<HTMLHeadingElement>) => (
|
|
30
|
+
<Heading level={1} {...props} />
|
|
31
|
+
),
|
|
32
|
+
h2: (props: React.HTMLAttributes<HTMLHeadingElement>) => (
|
|
33
|
+
<Heading level={2} {...props} />
|
|
34
|
+
),
|
|
35
|
+
h3: (props: React.HTMLAttributes<HTMLHeadingElement>) => (
|
|
36
|
+
<Heading level={3} {...props} />
|
|
37
|
+
),
|
|
38
|
+
h4: (props: React.HTMLAttributes<HTMLHeadingElement>) => (
|
|
39
|
+
<Heading level={4} {...props} />
|
|
40
|
+
),
|
|
41
|
+
h5: (props: React.HTMLAttributes<HTMLHeadingElement>) => (
|
|
42
|
+
<Heading level={5} {...props} />
|
|
43
|
+
),
|
|
44
|
+
h6: (props: React.HTMLAttributes<HTMLHeadingElement>) => (
|
|
45
|
+
<Heading level={6} {...props} />
|
|
46
|
+
),
|
|
47
|
+
pre: (props: React.HTMLAttributes<HTMLPreElement>) => (
|
|
48
|
+
<MdxComponents.CodeBlock {...props}>
|
|
49
|
+
{props.children}
|
|
50
|
+
</MdxComponents.CodeBlock>
|
|
51
|
+
),
|
|
52
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import React, { createContext, useContext } from 'react'
|
|
2
|
+
|
|
3
|
+
export type MdxComponentsType = Record<string, React.ComponentType<any>>
|
|
4
|
+
|
|
5
|
+
const MdxComponentsContext = createContext<MdxComponentsType>({})
|
|
6
|
+
|
|
7
|
+
export function useMdxComponents() {
|
|
8
|
+
return useContext(MdxComponentsContext)
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function MdxComponentsProvider({
|
|
12
|
+
components,
|
|
13
|
+
children,
|
|
14
|
+
}: {
|
|
15
|
+
components: MdxComponentsType
|
|
16
|
+
children: React.ReactNode
|
|
17
|
+
}) {
|
|
18
|
+
return (
|
|
19
|
+
<MdxComponentsContext.Provider value={components}>
|
|
20
|
+
{children}
|
|
21
|
+
</MdxComponentsContext.Provider>
|
|
22
|
+
)
|
|
23
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import { MDXProvider } from '@mdx-js/react'
|
|
3
|
+
import { useMdxComponents } from './mdx-components-context'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Renders an MDX page securely, injecting required custom components.
|
|
7
|
+
* This overrides the default HTML tags emitted by MDX with stylized components.
|
|
8
|
+
*/
|
|
9
|
+
export function MdxPage({
|
|
10
|
+
Component,
|
|
11
|
+
}: {
|
|
12
|
+
Component: React.ComponentType<any>
|
|
13
|
+
}) {
|
|
14
|
+
const allComponents = useMdxComponents()
|
|
15
|
+
return (
|
|
16
|
+
<MDXProvider components={allComponents as any}>
|
|
17
|
+
<Component />
|
|
18
|
+
</MDXProvider>
|
|
19
|
+
)
|
|
20
|
+
}
|