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.
- package/CHANGELOG.md +7 -0
- package/LICENSE +21 -0
- package/dist/cache-7G6D532T.mjs +1 -0
- package/dist/chunk-A4HQPEPU.mjs +1 -0
- package/dist/chunk-BA5NH5HU.mjs +1 -0
- package/dist/chunk-BQCD3DWG.mjs +1 -0
- package/dist/chunk-H63UMKYF.mjs +1 -0
- package/dist/chunk-IWHRQHS7.mjs +1 -0
- package/dist/chunk-JZXLCA2E.mjs +1 -0
- package/dist/chunk-MFU7Q6WF.mjs +1 -0
- package/dist/chunk-QYPNX5UN.mjs +1 -0
- package/dist/chunk-XEAPSFMB.mjs +1 -0
- package/dist/client/components/mdx/index.d.mts +209 -0
- package/dist/client/components/mdx/index.d.ts +209 -0
- package/dist/client/components/mdx/index.js +1 -0
- package/dist/client/components/mdx/index.mjs +1 -0
- package/dist/client/hooks/index.d.mts +133 -0
- package/dist/client/hooks/index.d.ts +133 -0
- package/dist/client/hooks/index.js +1 -0
- package/dist/client/hooks/index.mjs +1 -0
- package/dist/client/index.d.mts +138 -298
- package/dist/client/index.d.ts +138 -298
- package/dist/client/index.js +1 -3630
- package/dist/client/index.mjs +1 -697
- package/dist/client/ssr.d.mts +7 -3
- package/dist/client/ssr.d.ts +7 -3
- package/dist/client/ssr.js +1 -2928
- package/dist/client/ssr.mjs +1 -33
- package/dist/{config-BsFQ-ErD.d.ts → config-CX4l-ZNp.d.mts} +42 -35
- package/dist/{config-BsFQ-ErD.d.mts → config-CX4l-ZNp.d.ts} +42 -35
- package/dist/node/index.d.mts +2 -4
- package/dist/node/index.d.ts +2 -4
- package/dist/node/index.js +31 -1161
- package/dist/node/index.mjs +31 -736
- package/dist/search-dialog-EB3N4TYM.mjs +1 -0
- package/dist/types-BuZWFT7r.d.ts +159 -0
- package/dist/types-CvT-SGbK.d.mts +159 -0
- package/dist/use-routes-5bAtAAYX.d.mts +30 -0
- package/dist/use-routes-BefRXY3v.d.ts +30 -0
- package/package.json +34 -12
- package/src/client/app/config-context.tsx +18 -0
- package/src/client/app/docs-layout.tsx +14 -0
- package/src/client/app/index.tsx +137 -262
- 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 -84
- 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 +102 -82
- package/src/node/routes/sorter.ts +15 -15
- package/src/node/routes/types.ts +24 -24
- package/src/node/ssg/index.ts +73 -47
- 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 +54 -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/ssr.css +0 -2847
- 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/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,127 @@ 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<any
|
|
102
|
-
hot?:
|
|
103
|
-
homePage?: React.ComponentType
|
|
104
|
-
|
|
31
|
+
initialRoutes: ComponentRoute[]
|
|
32
|
+
initialConfig: BoltdocsConfig
|
|
33
|
+
docsDirName: string
|
|
34
|
+
modules: Record<string, () => Promise<{ default: React.ComponentType<any> }>>
|
|
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
|
-
(k) =>
|
|
117
|
-
|
|
118
|
-
|
|
53
|
+
(k) =>
|
|
54
|
+
k === `/${docsDirName}/${route.filePath}` || // Vite dev/build relative path
|
|
55
|
+
k.endsWith(`/${docsDirName}/${route.filePath}`) || // SSG absolute path fallback
|
|
56
|
+
k.endsWith(`/${docsDirName}\\${route.filePath.replace(/\\/g, '/')}`), // Windows fallback
|
|
57
|
+
)
|
|
58
|
+
const loader = loaderKey ? modules[loaderKey] : null
|
|
119
59
|
|
|
120
60
|
return {
|
|
121
61
|
...route,
|
|
122
|
-
Component: React.lazy(() => {
|
|
123
|
-
if (!loader)
|
|
124
|
-
|
|
125
|
-
return
|
|
62
|
+
Component: React.lazy<React.ComponentType<any>>(async () => {
|
|
63
|
+
if (!loader) return { default: NotFound as React.ComponentType<any> }
|
|
64
|
+
const mod = await loader()
|
|
65
|
+
return mod
|
|
126
66
|
}),
|
|
127
|
-
}
|
|
128
|
-
})
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
const [resolvedRoutes, setResolvedRoutes] = useState<any[]>(() =>
|
|
132
|
-
resolveRoutes(initialRoutes),
|
|
133
|
-
);
|
|
67
|
+
}
|
|
68
|
+
})
|
|
69
|
+
}, [routesInfo, modules, docsDirName, HomePage, computedExternalPages])
|
|
134
70
|
|
|
135
71
|
// Subscribe to HMR events
|
|
136
72
|
useEffect(() => {
|
|
137
73
|
if (hot) {
|
|
138
|
-
hot.on(
|
|
139
|
-
setRoutesInfo(newRoutes)
|
|
140
|
-
})
|
|
74
|
+
hot.on('boltdocs:routes-update', (newRoutes: ComponentRoute[]) => {
|
|
75
|
+
setRoutesInfo(newRoutes)
|
|
76
|
+
})
|
|
141
77
|
}
|
|
142
|
-
}, [hot])
|
|
78
|
+
}, [hot])
|
|
143
79
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
80
|
+
const allComponents = useMemo(
|
|
81
|
+
() => ({ ...mdxComponentsDefault, ...customComponents }),
|
|
82
|
+
[customComponents],
|
|
83
|
+
)
|
|
148
84
|
|
|
149
85
|
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}
|
|
86
|
+
<ThemeProvider>
|
|
87
|
+
<MdxComponentsProvider components={allComponents}>
|
|
88
|
+
<ConfigContext.Provider value={config}>
|
|
89
|
+
<BoltdocsRouterProvider>
|
|
90
|
+
<PreloadProvider routes={routesInfo} modules={modules}>
|
|
91
|
+
<ScrollHandler />
|
|
92
|
+
<Routes>
|
|
93
|
+
{/* Custom home page with user layout */}
|
|
94
|
+
{HomePage && (
|
|
95
|
+
<Route
|
|
96
|
+
path="/"
|
|
97
|
+
element={
|
|
98
|
+
<UserLayout>
|
|
99
|
+
<HomePage />
|
|
100
|
+
</UserLayout>
|
|
101
|
+
}
|
|
102
|
+
/>
|
|
103
|
+
)}
|
|
104
|
+
|
|
105
|
+
{/* Custom External Pages with user layout */}
|
|
106
|
+
{Object.entries(computedExternalPages).map(
|
|
107
|
+
([extPath, ExtComponent]) => (
|
|
108
|
+
<Route
|
|
109
|
+
key={extPath}
|
|
110
|
+
path={extPath}
|
|
111
|
+
element={
|
|
112
|
+
<UserLayout>
|
|
113
|
+
<ExtComponent />
|
|
114
|
+
</UserLayout>
|
|
115
|
+
}
|
|
187
116
|
/>
|
|
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
|
-
if (!container) return;
|
|
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
|
-
);
|
|
117
|
+
),
|
|
118
|
+
)}
|
|
119
|
+
|
|
120
|
+
<Route key="docs-layout" element={<DocsLayout />}>
|
|
121
|
+
{resolvedRoutes.map((route) => (
|
|
122
|
+
<Route
|
|
123
|
+
key={route.path}
|
|
124
|
+
path={route.path === '' ? '/' : route.path}
|
|
125
|
+
element={
|
|
126
|
+
<React.Suspense fallback={<Loading />}>
|
|
127
|
+
<MdxPage Component={route.Component} />
|
|
128
|
+
</React.Suspense>
|
|
129
|
+
}
|
|
130
|
+
/>
|
|
131
|
+
))}
|
|
132
|
+
</Route>
|
|
133
|
+
|
|
134
|
+
<Route
|
|
135
|
+
path="*"
|
|
136
|
+
element={
|
|
137
|
+
<UserLayout>
|
|
138
|
+
<NotFound />
|
|
139
|
+
</UserLayout>
|
|
140
|
+
}
|
|
141
|
+
/>
|
|
142
|
+
</Routes>
|
|
143
|
+
</PreloadProvider>
|
|
144
|
+
</BoltdocsRouterProvider>
|
|
145
|
+
</ConfigContext.Provider>
|
|
146
|
+
</MdxComponentsProvider>
|
|
147
|
+
</ThemeProvider>
|
|
148
|
+
)
|
|
284
149
|
}
|
|
285
150
|
|
|
286
151
|
/**
|
|
@@ -305,13 +170,22 @@ function MdxPage({
|
|
|
305
170
|
* ```
|
|
306
171
|
*/
|
|
307
172
|
export function createBoltdocsApp(options: CreateBoltdocsAppOptions) {
|
|
308
|
-
const {
|
|
309
|
-
|
|
310
|
-
|
|
173
|
+
const {
|
|
174
|
+
target,
|
|
175
|
+
routes,
|
|
176
|
+
docsDirName,
|
|
177
|
+
config,
|
|
178
|
+
modules,
|
|
179
|
+
hot,
|
|
180
|
+
homePage,
|
|
181
|
+
externalPages,
|
|
182
|
+
components,
|
|
183
|
+
} = options
|
|
184
|
+
const container = document.querySelector(target)
|
|
311
185
|
if (!container) {
|
|
312
186
|
throw new Error(
|
|
313
187
|
`[boltdocs] Mount target "${target}" not found in document.`,
|
|
314
|
-
)
|
|
188
|
+
)
|
|
315
189
|
}
|
|
316
190
|
|
|
317
191
|
const app = (
|
|
@@ -324,16 +198,17 @@ export function createBoltdocsApp(options: CreateBoltdocsAppOptions) {
|
|
|
324
198
|
modules={modules}
|
|
325
199
|
hot={hot}
|
|
326
200
|
homePage={homePage}
|
|
327
|
-
|
|
201
|
+
externalPages={externalPages}
|
|
202
|
+
components={components}
|
|
328
203
|
/>
|
|
329
204
|
</BrowserRouter>
|
|
330
205
|
</React.StrictMode>
|
|
331
|
-
)
|
|
206
|
+
)
|
|
332
207
|
|
|
333
208
|
// SSG pre-renders a shell with mock components for SEO crawlers.
|
|
334
209
|
// We always use createRoot because the SSG output doesn't match the
|
|
335
210
|
// real client-side component tree (components are lazy/dynamic).
|
|
336
211
|
// Clear any SSG placeholder content before mounting.
|
|
337
|
-
container.innerHTML =
|
|
338
|
-
ReactDOM.createRoot(container as HTMLElement).render(app)
|
|
212
|
+
container.innerHTML = ''
|
|
213
|
+
ReactDOM.createRoot(container as HTMLElement).render(app)
|
|
339
214
|
}
|
|
@@ -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
|
+
}
|
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { ComponentRoute } from
|
|
1
|
+
import { createContext, use, useCallback, useRef } from 'react'
|
|
2
|
+
import type { ComponentRoute } from '../types'
|
|
3
3
|
|
|
4
4
|
interface PreloadContextType {
|
|
5
|
-
preload: (path: string) => void
|
|
6
|
-
routes: ComponentRoute[]
|
|
5
|
+
preload: (path: string) => void
|
|
6
|
+
routes: ComponentRoute[]
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
const PreloadContext = createContext<PreloadContextType>({
|
|
10
10
|
preload: () => {},
|
|
11
11
|
routes: [],
|
|
12
|
-
})
|
|
12
|
+
})
|
|
13
13
|
|
|
14
14
|
export function usePreload() {
|
|
15
|
-
return
|
|
15
|
+
return use(PreloadContext)
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
export function PreloadProvider({
|
|
@@ -20,39 +20,47 @@ export function PreloadProvider({
|
|
|
20
20
|
modules,
|
|
21
21
|
children,
|
|
22
22
|
}: {
|
|
23
|
-
routes: ComponentRoute[]
|
|
24
|
-
modules: Record<string, () => Promise<
|
|
25
|
-
children: React.ReactNode
|
|
23
|
+
routes: ComponentRoute[]
|
|
24
|
+
modules: Record<string, () => Promise<unknown>>
|
|
25
|
+
children: React.ReactNode
|
|
26
26
|
}) {
|
|
27
|
+
const preloadTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null)
|
|
28
|
+
|
|
27
29
|
const preload = useCallback(
|
|
28
30
|
(path: string) => {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
// Support index routes matching "/"
|
|
33
|
-
const route = routes.find(
|
|
34
|
-
(r) => r.path === cleanPath || (cleanPath === "/" && r.path === ""),
|
|
35
|
-
);
|
|
36
|
-
|
|
37
|
-
if (route && route.filePath) {
|
|
38
|
-
const loaderKey = Object.keys(modules).find((k) =>
|
|
39
|
-
k.endsWith("/" + route.filePath),
|
|
40
|
-
);
|
|
41
|
-
|
|
42
|
-
if (loaderKey) {
|
|
43
|
-
// Trigger the dynamic import
|
|
44
|
-
modules[loaderKey]().catch((err: any) => {
|
|
45
|
-
console.error(`[boltdocs] Failed to preload route ${path}:`, err);
|
|
46
|
-
});
|
|
47
|
-
}
|
|
31
|
+
if (preloadTimerRef.current) {
|
|
32
|
+
clearTimeout(preloadTimerRef.current)
|
|
48
33
|
}
|
|
34
|
+
|
|
35
|
+
preloadTimerRef.current = setTimeout(() => {
|
|
36
|
+
// Normalize path (remove hash and search)
|
|
37
|
+
const cleanPath = path.split('#')[0].split('?')[0]
|
|
38
|
+
|
|
39
|
+
// Support index routes matching "/"
|
|
40
|
+
const route = routes.find(
|
|
41
|
+
(r) => r.path === cleanPath || (cleanPath === '/' && r.path === ''),
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
if (route?.filePath) {
|
|
45
|
+
const loaderKey = Object.keys(modules).find((k) =>
|
|
46
|
+
k.endsWith('/' + route.filePath),
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
if (loaderKey) {
|
|
50
|
+
// Trigger the dynamic import
|
|
51
|
+
modules[loaderKey]().catch((err: unknown) => {
|
|
52
|
+
console.error(`[boltdocs] Failed to preload route ${path}:`, err)
|
|
53
|
+
})
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}, 100) // 100ms debounce
|
|
49
57
|
},
|
|
50
58
|
[routes, modules],
|
|
51
|
-
)
|
|
59
|
+
)
|
|
52
60
|
|
|
53
61
|
return (
|
|
54
62
|
<PreloadContext.Provider value={{ preload, routes }}>
|
|
55
63
|
{children}
|
|
56
64
|
</PreloadContext.Provider>
|
|
57
|
-
)
|
|
65
|
+
)
|
|
58
66
|
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type React from 'react'
|
|
2
|
+
import { startTransition } from 'react'
|
|
3
|
+
import { RouterProvider } from 'react-aria-components'
|
|
4
|
+
import { useNavigate, useHref } from 'react-router-dom'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Connects React Aria Components (RAC) to React Router.
|
|
8
|
+
* This ensures all RAC links and buttons use client-side navigation
|
|
9
|
+
* instead of full page reloads.
|
|
10
|
+
*/
|
|
11
|
+
export function BoltdocsRouterProvider({
|
|
12
|
+
children,
|
|
13
|
+
}: {
|
|
14
|
+
children: React.ReactNode
|
|
15
|
+
}) {
|
|
16
|
+
const navigate = useNavigate()
|
|
17
|
+
|
|
18
|
+
return (
|
|
19
|
+
<RouterProvider
|
|
20
|
+
navigate={(to, options) => {
|
|
21
|
+
startTransition(() => {
|
|
22
|
+
navigate(to, options)
|
|
23
|
+
})
|
|
24
|
+
}}
|
|
25
|
+
useHref={useHref}
|
|
26
|
+
>
|
|
27
|
+
{children as any}
|
|
28
|
+
</RouterProvider>
|
|
29
|
+
)
|
|
30
|
+
}
|