boltdocs 2.6.2 → 2.7.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/bin/boltdocs.js +0 -1
- package/dist/cache-CQKlT4fI.mjs +6 -0
- package/dist/cache-DorPMFgW.cjs +6 -0
- package/dist/cards-BLoSiRuL.d.ts +30 -0
- package/dist/cards-CQn9mXZS.d.cts +30 -0
- package/dist/chunk-Ds5LZdWN.cjs +6 -0
- package/dist/client/index.cjs +1 -1
- package/dist/client/index.d.cts +167 -1338
- package/dist/client/index.d.ts +166 -1337
- package/dist/client/index.js +1 -1
- package/dist/{package-CFP44vfn.cjs → client/mdx.cjs} +1 -1
- package/dist/client/mdx.d.cts +128 -0
- package/dist/client/mdx.d.ts +129 -0
- package/dist/client/mdx.js +6 -0
- package/dist/client/primitives.cjs +6 -0
- package/dist/client/primitives.d.cts +818 -0
- package/dist/client/primitives.d.ts +818 -0
- package/dist/client/primitives.js +6 -0
- package/dist/client/theme/neutral.css +74 -361
- package/dist/client/theme/reset.css +189 -0
- package/dist/docs-layout-BlDhcQRv.cjs +6 -0
- package/dist/docs-layout-BvAOWEJw.js +6 -0
- package/dist/doctor-BQiQhCTl.cjs +6 -0
- package/dist/doctor-COpf35L2.cjs +20 -0
- package/dist/doctor-Dh1XP7Pz.mjs +20 -0
- package/dist/generator-DGW6pkCC.cjs +22 -0
- package/dist/generator-Dv3wEmhZ.mjs +22 -0
- package/dist/icons-dev-CrQLjoQp.js +6 -0
- package/dist/icons-dev-rzdz6Lf3.cjs +6 -0
- package/dist/image-BkIfa9oo.js +6 -0
- package/dist/image-DIGjCPe6.cjs +6 -0
- package/dist/mdx-K0WYBAJ3.js +7 -0
- package/dist/mdx-hpErbRUe.cjs +7 -0
- package/dist/meta-loader-0gJ4PtBC.cjs +6 -0
- package/dist/meta-loader-9IpAHWDS.mjs +6 -0
- package/dist/node/cli-entry.cjs +1 -2
- package/dist/node/cli-entry.mjs +1 -2
- package/dist/node/index.cjs +1 -1
- package/dist/node/index.d.cts +55 -11
- package/dist/node/index.d.mts +55 -12
- package/dist/node/index.mjs +1 -1
- package/dist/node/routes/worker.cjs +6 -0
- package/dist/node/routes/worker.d.cts +2 -0
- package/dist/node/routes/worker.d.mts +2 -0
- package/dist/node/routes/worker.mjs +6 -0
- package/dist/node-C2nWXElP.mjs +112 -0
- package/dist/node-CinkUtxV.cjs +112 -0
- package/dist/package-BMYLDBBP.cjs +6 -0
- package/dist/{package-Bqbn1AYK.mjs → package-HegMOTL_.mjs} +1 -1
- package/dist/parser-Bh11BsdA.cjs +6 -0
- package/dist/parser-D8eQvE7N.mjs +6 -0
- package/dist/parser-DYRzXWmA.cjs +6 -0
- package/dist/routes-CHf76Ye4.cjs +6 -0
- package/dist/routes-CMUZGI6T.mjs +6 -0
- package/dist/routes-Co1mRM58.cjs +6 -0
- package/dist/search-dialog-BACuzoVX.cjs +6 -0
- package/dist/search-dialog-BKagVT17.js +6 -0
- package/dist/search-dialog-C8w12eUx.js +6 -0
- package/dist/search-dialog-CGyrozZE.cjs +6 -0
- package/dist/search-dialog-D26rUnJ_.cjs +6 -0
- package/dist/sidebar-DKvg6KOc.d.cts +491 -0
- package/dist/sidebar-Dr1TiRIy.d.ts +491 -0
- package/dist/utils-BxNAXhZZ.mjs +7 -0
- package/dist/utils-Clzu7jvb.cjs +7 -0
- package/dist/worker-pool-Bd8Y9KDv.mjs +6 -0
- package/dist/worker-pool-BwU8ckrg.cjs +6 -0
- package/package.json +27 -8
- package/src/client/app/doc-page.tsx +9 -5
- package/src/client/app/docs-layout.tsx +17 -3
- package/src/client/app/head.tsx +122 -0
- package/src/client/app/helmet-compat.tsx +36 -0
- package/src/client/app/mdx-component.tsx +5 -52
- package/src/client/app/mdx-components-context.tsx +32 -8
- package/src/client/app/routes-context.tsx +2 -2
- package/src/client/app/scroll-handler.tsx +1 -1
- package/src/client/app/theme-context.tsx +5 -5
- package/src/client/app/ui-context.tsx +42 -0
- package/src/client/components/docs-layout-default.tsx +85 -0
- package/src/client/components/icons-dev.tsx +38 -15
- package/src/client/components/mdx/callout.tsx +97 -0
- package/src/client/components/mdx/card.tsx +73 -98
- package/src/client/components/mdx/cards.tsx +27 -0
- package/src/client/components/mdx/code-block.tsx +37 -17
- package/src/client/components/mdx/field.tsx +24 -56
- package/src/client/components/mdx/image.tsx +36 -15
- package/src/client/components/mdx/index.ts +19 -53
- package/src/client/components/mdx/table.tsx +46 -148
- package/src/client/components/mdx/typographics.tsx +120 -0
- package/src/client/components/mdx/{hooks/use-code-block.ts → use-code-block.ts} +5 -7
- package/src/client/components/primitives/breadcrumbs.tsx +5 -24
- package/src/client/components/primitives/button.tsx +3 -142
- package/src/client/components/primitives/code-block.tsx +104 -97
- package/src/client/components/{docs-layout.tsx → primitives/docs-layout.tsx} +15 -24
- package/src/client/components/primitives/error-boundary.tsx +107 -0
- package/src/client/components/primitives/heading.tsx +128 -0
- package/src/client/components/primitives/helpers/observer.ts +62 -32
- package/src/client/components/primitives/image.tsx +26 -0
- package/src/client/components/primitives/link.tsx +50 -52
- package/src/client/components/primitives/menu.tsx +25 -49
- package/src/client/components/primitives/navbar.tsx +234 -59
- package/src/client/components/primitives/on-this-page.tsx +169 -40
- package/src/client/components/primitives/page-nav.tsx +11 -39
- package/src/client/components/primitives/popover.tsx +12 -30
- package/src/client/components/primitives/search-dialog.tsx +77 -71
- package/src/client/components/primitives/sidebar.tsx +312 -119
- package/src/client/components/primitives/skeleton.tsx +1 -1
- package/src/client/components/primitives/tabs.tsx +5 -16
- package/src/client/components/primitives/tooltip.tsx +1 -1
- package/src/client/components/ui-base/banner.tsx +66 -0
- package/src/client/components/ui-base/breadcrumbs.tsx +26 -20
- package/src/client/components/ui-base/copy-markdown.tsx +43 -35
- package/src/client/components/ui-base/error-boundary.tsx +9 -46
- package/src/client/components/ui-base/github-stars.tsx +5 -3
- package/src/client/components/ui-base/index.ts +3 -3
- package/src/client/components/ui-base/last-updated.tsx +27 -0
- package/src/client/components/ui-base/navbar.tsx +183 -89
- package/src/client/components/ui-base/not-found.tsx +11 -9
- package/src/client/components/ui-base/on-this-page.tsx +8 -104
- package/src/client/components/ui-base/page-nav.tsx +23 -9
- package/src/client/components/ui-base/search-dialog.tsx +111 -36
- package/src/client/components/ui-base/search-highlight.tsx +10 -0
- package/src/client/components/ui-base/sidebar.tsx +77 -154
- package/src/client/components/ui-base/tabs.tsx +20 -7
- package/src/client/components/ui-base/theme-toggle.tsx +88 -10
- package/src/client/components/ui-base/version-i18n.tsx +80 -0
- package/src/client/hooks/index.ts +2 -1
- package/src/client/hooks/use-analytics.ts +272 -0
- package/src/client/hooks/use-i18n.ts +116 -50
- package/src/client/hooks/use-localized-to.ts +70 -27
- package/src/client/hooks/use-navbar.ts +69 -39
- package/src/client/hooks/use-page-nav.ts +28 -25
- package/src/client/hooks/use-routes.ts +63 -80
- package/src/client/hooks/use-search-highlight.ts +185 -0
- package/src/client/hooks/use-search.ts +12 -3
- package/src/client/hooks/use-sidebar.ts +183 -80
- package/src/client/hooks/use-tabs.ts +3 -4
- package/src/client/hooks/use-version.ts +44 -29
- package/src/client/index.ts +13 -87
- package/src/client/mdx.ts +2 -0
- package/src/client/primitives.ts +19 -0
- package/src/client/ssg/boltdocs-shell.tsx +68 -79
- package/src/client/ssg/create-routes.tsx +268 -72
- package/src/client/ssg/mdx-page.tsx +2 -1
- package/src/client/store/boltdocs-context.tsx +72 -20
- package/src/client/theme/neutral.css +74 -361
- package/src/client/theme/reset.css +189 -0
- package/src/client/types.ts +10 -2
- package/src/client/utils/path.ts +9 -0
- package/src/client/utils/react-to-text.ts +24 -24
- package/src/client/virtual.d.ts +1 -1
- package/src/shared/types.ts +82 -22
- package/dist/node-Bogvkxao.mjs +0 -101
- package/dist/node-CXaog6St.cjs +0 -101
- package/dist/search-dialog-CV3eJzMm.cjs +0 -6
- package/dist/search-dialog-DNTomKgu.js +0 -6
- package/dist/use-search-CS3gH19M.js +0 -6
- package/dist/use-search-DBpJZQuw.cjs +0 -6
- package/src/client/components/mdx/admonition.tsx +0 -91
- package/src/client/components/mdx/badge.tsx +0 -41
- package/src/client/components/mdx/button.tsx +0 -35
- package/src/client/components/mdx/component-preview.tsx +0 -37
- package/src/client/components/mdx/component-props.tsx +0 -83
- package/src/client/components/mdx/file-tree.tsx +0 -325
- package/src/client/components/mdx/hooks/use-component-preview.ts +0 -16
- package/src/client/components/mdx/hooks/useTable.ts +0 -74
- package/src/client/components/mdx/hooks/useTabs.ts +0 -68
- package/src/client/components/mdx/link.tsx +0 -38
- package/src/client/components/mdx/list.tsx +0 -192
- package/src/client/components/mdx/tabs.tsx +0 -135
- package/src/client/components/mdx/video.tsx +0 -68
- package/src/client/components/primitives/index.ts +0 -19
- package/src/client/components/primitives/navigation-menu.tsx +0 -114
- package/src/client/components/ui-base/head.tsx +0 -83
- package/src/client/components/ui-base/loading.tsx +0 -57
- package/src/client/components/ui-base/powered-by.tsx +0 -25
- package/src/client/hooks/use-onthispage.ts +0 -23
- package/src/client/utils/use-on-change.ts +0 -15
|
@@ -1,102 +1,205 @@
|
|
|
1
|
+
import { useMemo } from 'react'
|
|
1
2
|
import { useLocation } from 'react-router-dom'
|
|
2
3
|
import { useConfig } from '../app/config-context'
|
|
3
4
|
import type { ComponentRoute } from '../types'
|
|
5
|
+
import { normalizePath } from '../utils/path'
|
|
4
6
|
|
|
5
7
|
export function useSidebar(routes: ComponentRoute[]) {
|
|
6
8
|
const config = useConfig()
|
|
7
9
|
const location = useLocation()
|
|
8
10
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
if (!route.filePath && !route.group) continue
|
|
31
|
-
|
|
32
|
-
if (!route.group) {
|
|
33
|
-
ungrouped.push(route)
|
|
34
|
-
} else {
|
|
35
|
-
if (!groupsMap.has(route.group)) {
|
|
36
|
-
groupsMap.set(route.group, {
|
|
37
|
-
slug: route.group,
|
|
38
|
-
title: route.groupTitle || route.group,
|
|
39
|
-
routes: [],
|
|
40
|
-
icon: route.groupIcon,
|
|
41
|
-
})
|
|
11
|
+
const currentPath = normalizePath(location.pathname)
|
|
12
|
+
|
|
13
|
+
return useMemo(() => {
|
|
14
|
+
const activeRoute = routes.find(
|
|
15
|
+
(r) => normalizePath(r.path) === currentPath,
|
|
16
|
+
)
|
|
17
|
+
const activeTabId = activeRoute?.tab?.toLowerCase()
|
|
18
|
+
|
|
19
|
+
const filteredRoutes = activeTabId
|
|
20
|
+
? routes.filter((r) => !r.tab || r.tab.toLowerCase() === activeTabId)
|
|
21
|
+
: routes
|
|
22
|
+
|
|
23
|
+
const directoryMeta: Record<string, any> = {}
|
|
24
|
+
if (config.directoryMeta) {
|
|
25
|
+
for (const [key, value] of Object.entries(config.directoryMeta)) {
|
|
26
|
+
const cleanKey = key
|
|
27
|
+
.split('/')
|
|
28
|
+
.filter((part) => !part.startsWith('(') || !part.endsWith(')'))
|
|
29
|
+
.map((part) => part.replace(/^\d+-/, ''))
|
|
30
|
+
.join('/')
|
|
31
|
+
directoryMeta[cleanKey === '' ? '.' : cleanKey] = value
|
|
42
32
|
}
|
|
43
|
-
groupsMap.get(route.group)!.routes.push(route)
|
|
44
33
|
}
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
34
|
+
|
|
35
|
+
// 1. Helper to format labels
|
|
36
|
+
const capitalize = (str: string) =>
|
|
37
|
+
str.charAt(0).toUpperCase() + str.slice(1).replace(/-/g, ' ')
|
|
38
|
+
|
|
39
|
+
// 2. Define recursive tree builder
|
|
40
|
+
const rootNodesMap = new Map<string, ComponentRoute>()
|
|
41
|
+
const ungrouped: ComponentRoute[] = []
|
|
42
|
+
|
|
43
|
+
// Helper to find or create nested folders recursively
|
|
44
|
+
const getOrCreateNode = (
|
|
45
|
+
parts: string[],
|
|
46
|
+
rootStore: Map<string, ComponentRoute>,
|
|
47
|
+
) => {
|
|
48
|
+
let currentMap = rootStore
|
|
49
|
+
let parentPath = ''
|
|
50
|
+
let lastNode: ComponentRoute | null = null
|
|
51
|
+
|
|
52
|
+
for (let i = 0; i < parts.length; i++) {
|
|
53
|
+
const segment = parts[i]
|
|
54
|
+
const currentRelPath = parentPath ? `${parentPath}/${segment}` : segment
|
|
55
|
+
|
|
56
|
+
if (!currentMap.has(segment)) {
|
|
57
|
+
const meta = directoryMeta[currentRelPath] || {}
|
|
58
|
+
const newNode: ComponentRoute = {
|
|
59
|
+
path: '#', // Placeholder
|
|
60
|
+
title: meta.title || capitalize(segment),
|
|
61
|
+
componentPath: '',
|
|
62
|
+
filePath: '',
|
|
63
|
+
icon: meta.icon,
|
|
64
|
+
groupPosition: typeof meta.order === 'number' ? meta.order : 999,
|
|
65
|
+
subRoutes: [],
|
|
63
66
|
}
|
|
64
|
-
|
|
67
|
+
currentMap.set(segment, newNode)
|
|
65
68
|
}
|
|
69
|
+
|
|
70
|
+
lastNode = currentMap.get(segment)!
|
|
71
|
+
|
|
72
|
+
// Create inner subRoutes mapping helper
|
|
73
|
+
if (!(lastNode as any)._subMap) {
|
|
74
|
+
;(lastNode as any)._subMap = new Map<string, ComponentRoute>()
|
|
75
|
+
}
|
|
76
|
+
currentMap = (lastNode as any)._subMap as Map<string, ComponentRoute>
|
|
77
|
+
parentPath = currentRelPath
|
|
66
78
|
}
|
|
79
|
+
return lastNode
|
|
67
80
|
}
|
|
68
81
|
|
|
69
|
-
|
|
70
|
-
const
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
82
|
+
// 3. Sort input routes initially by their internal position/ordering
|
|
83
|
+
const sortedRoutes = [...filteredRoutes].sort((a, b) => {
|
|
84
|
+
const posA = a.sidebarPosition ?? a.order ?? 999
|
|
85
|
+
const posB = b.sidebarPosition ?? b.order ?? 999
|
|
86
|
+
return posA - posB
|
|
87
|
+
})
|
|
88
|
+
|
|
89
|
+
// 4. Distribute routes into tree
|
|
90
|
+
for (const route of sortedRoutes) {
|
|
91
|
+
if (route.sidebarHidden) continue
|
|
92
|
+
|
|
93
|
+
const parts = route.slugParts || []
|
|
94
|
+
const fileName = route.filePath.split('/').pop() || ''
|
|
95
|
+
const isIndex = /^index\.mdx?$/.test(fileName)
|
|
96
|
+
|
|
97
|
+
if (parts.length === 0) {
|
|
98
|
+
// Top level route (not in subfolder)
|
|
99
|
+
if (route.filePath) ungrouped.push(route)
|
|
100
|
+
continue
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
if (isIndex) {
|
|
104
|
+
// Index files populate the CONTAINER object itself
|
|
105
|
+
const containerNode = getOrCreateNode(parts, rootNodesMap)
|
|
106
|
+
if (containerNode) {
|
|
107
|
+
// Merge properties onto the container so it becomes clickable
|
|
108
|
+
containerNode.path = route.path
|
|
109
|
+
containerNode.title = route.title || containerNode.title
|
|
110
|
+
containerNode.icon = route.icon || containerNode.icon
|
|
111
|
+
containerNode.badge = route.badge
|
|
112
|
+
containerNode.sidebarPosition = route.sidebarPosition
|
|
113
|
+
containerNode.frontmatter = route.frontmatter
|
|
86
114
|
}
|
|
87
115
|
} else {
|
|
88
|
-
|
|
116
|
+
// Normal leaf file nested under path
|
|
117
|
+
const parentNode = getOrCreateNode(parts, rootNodesMap)
|
|
118
|
+
if (parentNode) {
|
|
119
|
+
parentNode.subRoutes!.push(route)
|
|
120
|
+
}
|
|
89
121
|
}
|
|
90
122
|
}
|
|
91
123
|
|
|
92
|
-
|
|
93
|
-
|
|
124
|
+
// 5. Recursive sorting and cleanup helper
|
|
125
|
+
const finalizeTree = (
|
|
126
|
+
nodes: ComponentRoute[],
|
|
127
|
+
currentPathPrefix: string = '',
|
|
128
|
+
): ComponentRoute[] => {
|
|
129
|
+
nodes.forEach((node) => {
|
|
130
|
+
// 1. Pull child nodes from internal Map store into subRoutes
|
|
131
|
+
if ((node as any)._subMap) {
|
|
132
|
+
const childDirs = Array.from(
|
|
133
|
+
((node as any)._subMap as Map<string, ComponentRoute>).values(),
|
|
134
|
+
)
|
|
135
|
+
node.subRoutes = [...(node.subRoutes || []), ...childDirs]
|
|
136
|
+
delete (node as any)._subMap
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// 2. Recursively process grandchildren
|
|
140
|
+
if (node.subRoutes && node.subRoutes.length > 0) {
|
|
141
|
+
node.subRoutes = finalizeTree(node.subRoutes)
|
|
142
|
+
}
|
|
143
|
+
})
|
|
144
|
+
|
|
145
|
+
// 3. Sort this specific depth layer
|
|
146
|
+
return nodes.sort((a, b) => {
|
|
147
|
+
// Position ordering
|
|
148
|
+
const posA = a.sidebarPosition ?? a.groupPosition ?? 999
|
|
149
|
+
const posB = b.sidebarPosition ?? b.groupPosition ?? 999
|
|
150
|
+
|
|
151
|
+
if (posA !== posB) return posA - posB
|
|
152
|
+
|
|
153
|
+
// Fallback alphabetical
|
|
154
|
+
return a.title.localeCompare(b.title)
|
|
155
|
+
})
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// Finalize top-level groups
|
|
159
|
+
const rawGroups = Array.from(rootNodesMap.values())
|
|
160
|
+
const finalizedTopNodes = finalizeTree(rawGroups)
|
|
161
|
+
|
|
162
|
+
// Map finalized top nodes to expected format [{ title, routes }]
|
|
163
|
+
const groups = finalizedTopNodes.map((node) => {
|
|
164
|
+
// To match current primitives expectations, a 'group' is the top-level container.
|
|
165
|
+
// If the top node is already structured as a ComponentRoute, we wrap it.
|
|
166
|
+
return {
|
|
167
|
+
slug: node.title.toLowerCase().replace(/\s+/g, '-'),
|
|
168
|
+
title: node.title,
|
|
169
|
+
icon: node.icon,
|
|
170
|
+
routes: [node], // The primitives sidebar renderer iterates topGroup.routes and recurses inside.
|
|
171
|
+
}
|
|
172
|
+
})
|
|
173
|
+
|
|
174
|
+
// Wait, actually the legacy Sidebar.tsx treats "groups" as visual wrappers with headers,
|
|
175
|
+
// and "routes" inside as the start of items. If we want top-level direct items, they map to 'ungrouped'.
|
|
176
|
+
// Let's return grouped items natively.
|
|
94
177
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
178
|
+
// RE-DESIGN LEGACY COMPATIBILITY:
|
|
179
|
+
// If user wants strict backwards layout, we unwrap the very top layer!
|
|
180
|
+
const legacyCompatibleGroups = finalizedTopNodes
|
|
181
|
+
.map((node) => {
|
|
182
|
+
// Check if it's a container with subitems. If it is, make IT the group header!
|
|
183
|
+
if (node.subRoutes && node.subRoutes.length > 0) {
|
|
184
|
+
return {
|
|
185
|
+
slug: node.title.toLowerCase().replace(/\s+/g, '-'),
|
|
186
|
+
title: node.title,
|
|
187
|
+
icon: node.icon,
|
|
188
|
+
routes: node.subRoutes, // Unwrap children as top-level list underneath the visual group title!
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
// If it's standalone, send it to ungrouped
|
|
192
|
+
ungrouped.push(node)
|
|
193
|
+
return null
|
|
194
|
+
})
|
|
195
|
+
.filter(Boolean) as any[]
|
|
196
|
+
|
|
197
|
+
return {
|
|
198
|
+
groups: legacyCompatibleGroups,
|
|
199
|
+
ungrouped: finalizeTree(ungrouped),
|
|
200
|
+
activeRoute,
|
|
201
|
+
activePath: currentPath,
|
|
202
|
+
config,
|
|
203
|
+
}
|
|
204
|
+
}, [routes, config, currentPath])
|
|
102
205
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { useLocation } from 'react-router-dom'
|
|
2
2
|
import { useEffect, useState, useRef } from 'react'
|
|
3
3
|
import type { ComponentRoute, BoltdocsTab } from '../types'
|
|
4
|
+
import { normalizePath } from '../utils/path'
|
|
4
5
|
|
|
5
6
|
export function useTabs(
|
|
6
7
|
tabs: BoltdocsTab[] = [],
|
|
@@ -14,11 +15,9 @@ export function useTabs(
|
|
|
14
15
|
width: 0,
|
|
15
16
|
})
|
|
16
17
|
|
|
17
|
-
const
|
|
18
|
-
p.endsWith('/') && p.length > 1 ? p.slice(0, -1) : p
|
|
19
|
-
const currentPath = normalize(location.pathname)
|
|
18
|
+
const currentPath = normalizePath(location.pathname)
|
|
20
19
|
|
|
21
|
-
const activeRoute = routes.find((r) =>
|
|
20
|
+
const activeRoute = routes.find((r) => normalizePath(r.path) === currentPath)
|
|
22
21
|
const activeTabId = activeRoute?.tab?.toLowerCase()
|
|
23
22
|
const activeIndex = tabs.findIndex(
|
|
24
23
|
(tab) => tab.id.toLowerCase() === activeTabId,
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
import { useMemo } from 'react'
|
|
1
2
|
import { useNavigate } from 'react-router-dom'
|
|
2
3
|
import { getBaseFilePath } from '../utils/get-base-file-path'
|
|
3
4
|
import { useRoutes } from './use-routes'
|
|
5
|
+
import { useConfig } from '../app/config-context'
|
|
4
6
|
import { useBoltdocsContext } from '../store/boltdocs-context'
|
|
5
7
|
import type { BoltdocsVersion } from '../../shared/types'
|
|
6
8
|
|
|
@@ -23,9 +25,8 @@ export interface UseVersionReturn {
|
|
|
23
25
|
*/
|
|
24
26
|
export function useVersion(): UseVersionReturn {
|
|
25
27
|
const navigate = useNavigate()
|
|
26
|
-
const
|
|
27
|
-
const { allRoutes, currentRoute, currentVersion, currentLocale
|
|
28
|
-
routeContext
|
|
28
|
+
const config = useConfig()
|
|
29
|
+
const { allRoutes, currentRoute, currentVersion, currentLocale } = useRoutes()
|
|
29
30
|
const versions = config.versions
|
|
30
31
|
const { setVersion } = useBoltdocsContext()
|
|
31
32
|
|
|
@@ -35,21 +36,12 @@ export function useVersion(): UseVersionReturn {
|
|
|
35
36
|
// Update store
|
|
36
37
|
setVersion(version)
|
|
37
38
|
|
|
38
|
-
//
|
|
39
|
-
|
|
40
|
-
const
|
|
41
|
-
|
|
42
|
-
currentRoute.path === '/' ||
|
|
43
|
-
currentRoute.path === config.base ||
|
|
44
|
-
currentRoute.path === '' ||
|
|
45
|
-
localePaths.includes(currentRoute.path)
|
|
46
|
-
|
|
47
|
-
if (isHome) {
|
|
48
|
-
return
|
|
49
|
-
}
|
|
39
|
+
// 3. Attempt derivation or deployment of navigation target
|
|
40
|
+
const base = config.base || '/docs'
|
|
41
|
+
const safeBase = base.replace(/\/$/, '')
|
|
42
|
+
let targetPath = `${safeBase}/${version}${currentLocale ? `/${currentLocale}` : ''}`
|
|
50
43
|
|
|
51
44
|
if (currentRoute) {
|
|
52
|
-
let targetPath = `/docs/${version}`
|
|
53
45
|
const baseFile = getBaseFilePath(
|
|
54
46
|
currentRoute.filePath,
|
|
55
47
|
currentRoute.version,
|
|
@@ -60,7 +52,8 @@ export function useVersion(): UseVersionReturn {
|
|
|
60
52
|
(r) =>
|
|
61
53
|
getBaseFilePath(r.filePath, r.version, r.locale) === baseFile &&
|
|
62
54
|
(r.version || versions.defaultVersion) === version &&
|
|
63
|
-
(
|
|
55
|
+
(!config.i18n ||
|
|
56
|
+
(r.locale || config.i18n.defaultLocale) === currentLocale),
|
|
64
57
|
)
|
|
65
58
|
|
|
66
59
|
if (targetRoute) {
|
|
@@ -70,26 +63,48 @@ export function useVersion(): UseVersionReturn {
|
|
|
70
63
|
(r) =>
|
|
71
64
|
getBaseFilePath(r.filePath, r.version, r.locale) === 'index.md' &&
|
|
72
65
|
(r.version || versions.defaultVersion) === version &&
|
|
73
|
-
(
|
|
66
|
+
(!config.i18n ||
|
|
67
|
+
(r.locale || config.i18n.defaultLocale) === currentLocale),
|
|
74
68
|
)
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
69
|
+
if (versionIndexRoute) {
|
|
70
|
+
targetPath = versionIndexRoute.path
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
} else {
|
|
74
|
+
// Recovery mode: if currently on a 404, attempt to find ANY document in the target version
|
|
75
|
+
const fallbackRoute = allRoutes.find(
|
|
76
|
+
(r) =>
|
|
77
|
+
(r.version || versions.defaultVersion) === version &&
|
|
78
|
+
(!config.i18n ||
|
|
79
|
+
(r.locale || config.i18n.defaultLocale) === currentLocale),
|
|
80
|
+
)
|
|
81
|
+
if (fallbackRoute) {
|
|
82
|
+
targetPath = fallbackRoute.path
|
|
78
83
|
}
|
|
79
|
-
|
|
80
|
-
navigate(targetPath)
|
|
81
84
|
}
|
|
85
|
+
|
|
86
|
+
navigate(targetPath)
|
|
82
87
|
}
|
|
83
88
|
|
|
84
|
-
const
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
+
const currentVersionConfig = versions?.versions?.find?.(
|
|
90
|
+
(v) => v.path === currentVersion,
|
|
91
|
+
)
|
|
92
|
+
const currentVersionLabel = currentVersionConfig?.label || currentVersion
|
|
93
|
+
|
|
94
|
+
const availableVersions = useMemo(() => {
|
|
95
|
+
return versions
|
|
96
|
+
? versions.versions.map((v) => ({
|
|
97
|
+
key: v.path as BoltdocsVersion,
|
|
98
|
+
label: v.label,
|
|
99
|
+
value: v.path,
|
|
100
|
+
isCurrent: v.path === currentVersion,
|
|
101
|
+
}))
|
|
102
|
+
: []
|
|
103
|
+
}, [versions, currentVersion])
|
|
89
104
|
|
|
90
105
|
return {
|
|
91
106
|
currentVersion,
|
|
92
|
-
currentVersionLabel
|
|
107
|
+
currentVersionLabel,
|
|
93
108
|
availableVersions,
|
|
94
109
|
handleVersionChange,
|
|
95
110
|
}
|
package/src/client/index.ts
CHANGED
|
@@ -1,105 +1,31 @@
|
|
|
1
|
+
export type * from './types'
|
|
1
2
|
export type {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
BoltdocsLocale,
|
|
4
|
+
BoltdocsVersion,
|
|
5
|
+
BoltdocsTypes,
|
|
6
|
+
} from '../shared/types'
|
|
6
7
|
export * from './ssg'
|
|
7
8
|
export { useConfig } from './app/config-context'
|
|
8
9
|
export { useTheme } from './app/theme-context'
|
|
9
|
-
export { useRoutes } from './hooks/use-routes'
|
|
10
10
|
export { useMdxComponents } from './app/mdx-components-context'
|
|
11
|
-
|
|
12
|
-
// Hooks
|
|
11
|
+
export { useUI } from './app/ui-context'
|
|
13
12
|
export * from './hooks/index'
|
|
14
|
-
|
|
15
|
-
export { DocsLayout } from './components/docs-layout'
|
|
16
|
-
|
|
17
|
-
// Default UI components (for use in custom layout.tsx)
|
|
13
|
+
export { DocsLayout } from './components/docs-layout-default'
|
|
18
14
|
export { Navbar } from './components/ui-base/navbar'
|
|
19
15
|
export { Sidebar } from './components/ui-base/sidebar'
|
|
20
16
|
export { OnThisPage } from './components/ui-base/on-this-page'
|
|
21
|
-
export { Head } from './components/ui-base/head'
|
|
22
17
|
export { Breadcrumbs } from './components/ui-base/breadcrumbs'
|
|
23
18
|
export { PageNav } from './components/ui-base/page-nav'
|
|
24
19
|
export { ErrorBoundary } from './components/ui-base/error-boundary'
|
|
25
20
|
export { CopyMarkdown } from './components/ui-base/copy-markdown'
|
|
26
|
-
|
|
21
|
+
export { SearchDialog } from './components/ui-base/search-dialog'
|
|
27
22
|
export { NotFound } from './components/ui-base/not-found'
|
|
28
|
-
export {
|
|
29
|
-
export {
|
|
30
|
-
export { Video } from './components/mdx/video'
|
|
31
|
-
|
|
32
|
-
// MDX Components
|
|
33
|
-
export {
|
|
34
|
-
Button,
|
|
35
|
-
Badge,
|
|
36
|
-
Card,
|
|
37
|
-
Cards,
|
|
38
|
-
Tabs,
|
|
39
|
-
Tab,
|
|
40
|
-
Admonition,
|
|
41
|
-
Note,
|
|
42
|
-
Tip,
|
|
43
|
-
Warning,
|
|
44
|
-
Danger,
|
|
45
|
-
InfoBox,
|
|
46
|
-
ComponentProps,
|
|
47
|
-
ComponentPreview,
|
|
48
|
-
Important,
|
|
49
|
-
Caution,
|
|
50
|
-
List,
|
|
51
|
-
FileTree,
|
|
52
|
-
Table,
|
|
53
|
-
Field,
|
|
54
|
-
Link,
|
|
55
|
-
Image,
|
|
56
|
-
} from './components/mdx'
|
|
57
|
-
|
|
58
|
-
export type {
|
|
59
|
-
ButtonProps,
|
|
60
|
-
BadgeProps,
|
|
61
|
-
CardProps,
|
|
62
|
-
CardsProps,
|
|
63
|
-
TabsProps,
|
|
64
|
-
TabProps,
|
|
65
|
-
AdmonitionProps,
|
|
66
|
-
ComponentPropsProps,
|
|
67
|
-
ComponentPreviewProps,
|
|
68
|
-
ListProps,
|
|
69
|
-
FileTreeProps,
|
|
70
|
-
TableProps,
|
|
71
|
-
FieldProps,
|
|
72
|
-
LinkProps,
|
|
73
|
-
ImageProps,
|
|
74
|
-
} from './components/mdx'
|
|
75
|
-
|
|
76
|
-
// Primitives
|
|
77
|
-
export { Navbar as PrimitiveNavbar } from './components/primitives/navbar'
|
|
78
|
-
export { NavigationMenu as PrimitiveNavigationMenu } from './components/primitives/navigation-menu'
|
|
79
|
-
export { SearchDialog as SearchDialogPrimitive } from './components/primitives/search-dialog'
|
|
80
|
-
export {
|
|
81
|
-
OnThisPage as PrimitiveOnThisPage,
|
|
82
|
-
AnchorProvider,
|
|
83
|
-
ScrollProvider,
|
|
84
|
-
useActiveAnchor,
|
|
85
|
-
useActiveAnchors,
|
|
86
|
-
useItems,
|
|
87
|
-
} from './components/primitives/on-this-page'
|
|
88
|
-
export { PageNav as PrimitivePageNav } from './components/primitives/page-nav'
|
|
89
|
-
export { Tabs as PrimitiveTabs } from './components/primitives/tabs'
|
|
90
|
-
export { Sidebar as PrimitiveSidebar } from './components/primitives/sidebar'
|
|
91
|
-
export { Breadcrumbs as PrimitiveBreadcrumbs } from './components/primitives/breadcrumbs'
|
|
92
|
-
export { Button as PrimitiveButton } from './components/primitives/button'
|
|
93
|
-
export { ButtonGroup } from './components/primitives/button-group'
|
|
94
|
-
export { Menu as PrimitiveMenu } from './components/primitives/menu'
|
|
95
|
-
export { Popover as PrimitivePopover } from './components/primitives/popover'
|
|
96
|
-
export { Tooltip as PrimitiveTooltip } from './components/primitives/tooltip'
|
|
97
|
-
export {
|
|
98
|
-
Link as PrimitiveLink,
|
|
99
|
-
NavLink as PrimitiveNavLink,
|
|
100
|
-
} from './components/primitives/link'
|
|
101
|
-
export { Skeleton as PrimitiveSkeleton } from './components/primitives/skeleton'
|
|
23
|
+
export { Card } from './components/mdx/card'
|
|
24
|
+
export { Cards } from './components/mdx/cards'
|
|
102
25
|
|
|
103
26
|
// Utilities
|
|
104
27
|
export { cn } from './utils/cn'
|
|
105
28
|
export { getTranslated } from './utils/i18n'
|
|
29
|
+
export { reactToText } from './utils/react-to-text'
|
|
30
|
+
export { copyToClipboard } from './utils/copy-clipboard'
|
|
31
|
+
export { getStarsRepo } from './utils/github'
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export * from './components/primitives/docs-layout'
|
|
2
|
+
export * from './components/primitives/button-group'
|
|
3
|
+
export * from './components/primitives/tabs'
|
|
4
|
+
export * from './components/primitives/sidebar'
|
|
5
|
+
export * from './components/primitives/on-this-page'
|
|
6
|
+
export * from './components/primitives/code-block'
|
|
7
|
+
export * from './components/primitives/button'
|
|
8
|
+
export * from './components/primitives/popover'
|
|
9
|
+
export * from './components/primitives/tooltip'
|
|
10
|
+
export * from './components/primitives/link'
|
|
11
|
+
export * from './components/primitives/error-boundary'
|
|
12
|
+
export * from './components/primitives/heading'
|
|
13
|
+
export * from './components/primitives/image'
|
|
14
|
+
export * from './components/primitives/menu'
|
|
15
|
+
export * from './components/primitives/page-nav'
|
|
16
|
+
export * from './components/primitives/search-dialog'
|
|
17
|
+
export * from './components/primitives/skeleton'
|
|
18
|
+
export * from './components/primitives/breadcrumbs'
|
|
19
|
+
export * from './components/primitives/navbar'
|