@docubook/flame 1.0.0-beta.80 → 1.0.1
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/.docu/components/Anchor.tsx +1 -1
- package/.docu/components/Breadcrumb.tsx +6 -1
- package/.docu/components/Context.tsx +2 -1
- package/.docu/components/Navbar.tsx +2 -2
- package/.docu/components/Pagination.tsx +15 -2
- package/.docu/components/Search.tsx +4 -10
- package/.docu/components/Sidebar.tsx +19 -4
- package/.docu/components/Sublink.tsx +6 -2
- package/.docu/components/Theme.tsx +1 -1
- package/.docu/components/registry.ts +21 -87
- package/.docu/node/build.ts +6 -2
- package/.docu/node/client.ts +1 -8
- package/.docu/node/html.ts +12 -0
- package/.docu/node/parse-tocs.ts +10 -0
- package/.docu/node/search-indexer.ts +17 -3
- package/.docu/node/server.ts +1 -13
- package/.docu/node/utils.ts +6 -4
- package/.docu/pages/docs/[[...slug]].tsx +6 -1
- package/.docu/styles/globals.css +8 -0
- package/README.md +2 -2
- package/package.json +8 -4
- package/template/docs/index.mdx +122 -16
- package/.docu/components/base/breadcrumbs.tsx +0 -64
- package/.docu/components/base/collapse.tsx +0 -186
- package/.docu/components/base/drawer.tsx +0 -164
- package/.docu/components/base/dropdown.tsx +0 -94
- package/.docu/components/base/input.tsx +0 -53
- package/.docu/components/base/kbd.tsx +0 -51
- package/.docu/components/base/modal.tsx +0 -56
- package/.docu/components/base/navbar.tsx +0 -132
- package/.docu/components/base/pagination/index.ts +0 -21
- package/.docu/components/base/pagination/pagination-docs.tsx +0 -39
- package/.docu/components/base/pagination/pagination-numbers.tsx +0 -379
- package/.docu/components/base/pagination/types.ts +0 -129
- package/.docu/components/base/theme-controller.tsx +0 -358
- package/.docu/components/base/toggle.tsx +0 -172
|
@@ -34,7 +34,7 @@ export default function Anchor({
|
|
|
34
34
|
|
|
35
35
|
const activeClass = isActive ? activeClassName : "";
|
|
36
36
|
const baseClasses = cn(
|
|
37
|
-
"
|
|
37
|
+
"hover:underline transition-colors",
|
|
38
38
|
className,
|
|
39
39
|
activeClass,
|
|
40
40
|
disabled && "cursor-not-allowed opacity-50"
|
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
Breadcrumb,
|
|
3
|
+
BreadcrumbItem,
|
|
4
|
+
BreadcrumbList,
|
|
5
|
+
BreadcrumbPage,
|
|
6
|
+
} from "@docubook/ui-react/breadcrumbs";
|
|
2
7
|
|
|
3
8
|
export interface DocsBreadcrumbProps {
|
|
4
9
|
paths: string[];
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import { useState } from "react";
|
|
4
4
|
import { cn } from "../node/utils";
|
|
5
|
-
import { Dropdown, DropdownItem } from "
|
|
5
|
+
import { Dropdown, DropdownItem } from "@docubook/ui-react/dropdown";
|
|
6
6
|
import { routes } from "../node/client-routes";
|
|
7
7
|
import { ChevronsUpDown, Check, type LucideIcon } from "lucide-react";
|
|
8
8
|
import * as LucideIcons from "lucide-react";
|
|
@@ -51,6 +51,7 @@ export function Context({ className }: ContextProps) {
|
|
|
51
51
|
<Dropdown
|
|
52
52
|
className={cn("w-full", className)}
|
|
53
53
|
align="start"
|
|
54
|
+
menuClassName="w-full"
|
|
54
55
|
trigger={
|
|
55
56
|
<div className="border-base-300 flex items-center justify-between rounded-lg border px-3 py-2 text-sm font-semibold">
|
|
56
57
|
<div className="flex min-w-0 items-center gap-2">
|
|
@@ -8,9 +8,9 @@ import {
|
|
|
8
8
|
NavMenu as BaseNavMenu,
|
|
9
9
|
NavMenuLink as BaseNavMenuLink,
|
|
10
10
|
type NavMenuItem as BaseNavMenuItem,
|
|
11
|
-
} from "
|
|
11
|
+
} from "@docubook/ui-react/navbar";
|
|
12
12
|
|
|
13
|
-
export type { NavMenuItem } from "
|
|
13
|
+
export type { NavMenuItem } from "@docubook/ui-react/navbar";
|
|
14
14
|
|
|
15
15
|
interface AppNavMenuItem {
|
|
16
16
|
title: string;
|
|
@@ -1,14 +1,24 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
|
+
import type { ReactNode } from "react";
|
|
3
4
|
import { getPreviousNext } from "../node/route";
|
|
4
|
-
import { PaginationDocs } from "
|
|
5
|
+
import { PaginationDocs } from "@docubook/ui-react/pagination";
|
|
5
6
|
|
|
6
7
|
interface PaginationProps {
|
|
7
8
|
pathname: string;
|
|
8
9
|
className?: string;
|
|
10
|
+
prevIcon?: ReactNode;
|
|
11
|
+
nextIcon?: ReactNode;
|
|
12
|
+
linkClassName?: string;
|
|
9
13
|
}
|
|
10
14
|
|
|
11
|
-
export default function Pagination({
|
|
15
|
+
export default function Pagination({
|
|
16
|
+
pathname,
|
|
17
|
+
className,
|
|
18
|
+
prevIcon,
|
|
19
|
+
nextIcon,
|
|
20
|
+
linkClassName,
|
|
21
|
+
}: PaginationProps) {
|
|
12
22
|
const { prev, next } = getPreviousNext(pathname);
|
|
13
23
|
|
|
14
24
|
if (!prev && !next) {
|
|
@@ -20,6 +30,9 @@ export default function Pagination({ pathname, className }: PaginationProps) {
|
|
|
20
30
|
prev={prev ? { href: `/docs${prev.href}`, title: prev.title } : undefined}
|
|
21
31
|
next={next ? { href: `/docs${next.href}`, title: next.title } : undefined}
|
|
22
32
|
className={className}
|
|
33
|
+
prevIcon={prevIcon}
|
|
34
|
+
nextIcon={nextIcon}
|
|
35
|
+
linkClassName={linkClassName}
|
|
23
36
|
/>
|
|
24
37
|
);
|
|
25
38
|
}
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
import { useState, useEffect, useRef, useCallback } from "react";
|
|
4
4
|
import { Search as SearchIcon, FileText, CornerDownLeft, Hash, AlignLeft } from "lucide-react";
|
|
5
|
-
import { Modal, useModal } from "
|
|
6
|
-
import { Kbd, FnKey } from "
|
|
5
|
+
import { Modal, useModal } from "@docubook/ui-react/modal";
|
|
6
|
+
import { Kbd, FnKey } from "@docubook/ui-react/kbd";
|
|
7
7
|
import { cn } from "../node/utils";
|
|
8
8
|
import { search, type SearchResult } from "../node/search";
|
|
9
9
|
import type { SearchRecord } from "../node/search-indexer";
|
|
@@ -217,16 +217,10 @@ function SearchTrigger({ onClick }: { onClick: () => void }) {
|
|
|
217
217
|
<SearchIcon className="h-4 w-4 shrink-0" />
|
|
218
218
|
<span className="flex-1 text-left">Search</span>
|
|
219
219
|
<div className="flex items-center gap-0.5">
|
|
220
|
-
<Kbd
|
|
221
|
-
size="s"
|
|
222
|
-
className="bg-primary text-[12px text-base-300 dark:text-foreground rounded-md p-1.5 font-medium"
|
|
223
|
-
>
|
|
220
|
+
<Kbd className="bg-primary text-[12px text-base-300 dark:text-foreground rounded-md p-1.5 font-medium">
|
|
224
221
|
<FnKey.Cmd />
|
|
225
222
|
</Kbd>
|
|
226
|
-
<Kbd
|
|
227
|
-
size="s"
|
|
228
|
-
className="bg-primary text-base-300 dark:text-foreground rounded-md p-1.5 text-[12px] font-medium"
|
|
229
|
-
>
|
|
223
|
+
<Kbd className="bg-primary text-base-300 dark:text-foreground rounded-md p-1.5 text-[12px] font-medium">
|
|
230
224
|
K
|
|
231
225
|
</Kbd>
|
|
232
226
|
</div>
|
|
@@ -9,8 +9,9 @@ import {
|
|
|
9
9
|
PanelRightClose,
|
|
10
10
|
FileText,
|
|
11
11
|
} from "lucide-react";
|
|
12
|
-
import { Dropdown
|
|
12
|
+
import { Dropdown } from "@docubook/ui-react/dropdown";
|
|
13
13
|
import { cn } from "../node/utils";
|
|
14
|
+
import Anchor from "./Anchor";
|
|
14
15
|
import { Context } from "./Context";
|
|
15
16
|
import Menu from "./Menu";
|
|
16
17
|
import { ThemeToggle } from "./Theme";
|
|
@@ -132,6 +133,7 @@ export function MobileBar({
|
|
|
132
133
|
<div className="flex items-center gap-1 p-2">
|
|
133
134
|
<Dropdown
|
|
134
135
|
align="start"
|
|
136
|
+
menuClassName="w-52 min-w-0"
|
|
135
137
|
trigger={
|
|
136
138
|
<span className="btn btn-ghost btn-sm btn-square">
|
|
137
139
|
<EllipsisVertical className="text-base-content/60 h-5 w-5" />
|
|
@@ -139,9 +141,22 @@ export function MobileBar({
|
|
|
139
141
|
}
|
|
140
142
|
>
|
|
141
143
|
{(docuConfig.navbar?.menu || []).map((item) => (
|
|
142
|
-
<
|
|
143
|
-
{item.
|
|
144
|
-
|
|
144
|
+
<li
|
|
145
|
+
key={item.href}
|
|
146
|
+
role="menuitem"
|
|
147
|
+
className="text-base-content/80 hover:text-base-content hover:bg-base-200 cursor-pointer"
|
|
148
|
+
>
|
|
149
|
+
<Anchor
|
|
150
|
+
href={item.href}
|
|
151
|
+
activeWhen={(path: string) =>
|
|
152
|
+
path === item.href || path.startsWith(item.href + "/")
|
|
153
|
+
}
|
|
154
|
+
activeClassName="text-primary font-semibold"
|
|
155
|
+
className="block rounded px-2 py-2 text-sm"
|
|
156
|
+
>
|
|
157
|
+
{item.title}
|
|
158
|
+
</Anchor>
|
|
159
|
+
</li>
|
|
145
160
|
))}
|
|
146
161
|
</Dropdown>
|
|
147
162
|
|
|
@@ -33,6 +33,9 @@ export default function Sublink({
|
|
|
33
33
|
return currentPathname.startsWith(fullHref) && currentPathname !== fullHref;
|
|
34
34
|
});
|
|
35
35
|
|
|
36
|
+
// Shared padding based on nesting level
|
|
37
|
+
const levelPadding = cn(level === 1 && "pl-2", level === 2 && "pl-4", level >= 3 && "pl-6");
|
|
38
|
+
|
|
36
39
|
// Leaf node (no children)
|
|
37
40
|
if (!items) {
|
|
38
41
|
const isActive = currentPathname === fullHref || currentPathname === `${fullHref}.html`;
|
|
@@ -52,7 +55,8 @@ export default function Sublink({
|
|
|
52
55
|
<div
|
|
53
56
|
className={cn(
|
|
54
57
|
"py-1.5",
|
|
55
|
-
|
|
58
|
+
levelPadding,
|
|
59
|
+
level >= 2 && "border-l-2",
|
|
56
60
|
level >= 2 && (isActive ? "border-primary" : "border-base-300")
|
|
57
61
|
)}
|
|
58
62
|
>
|
|
@@ -63,7 +67,7 @@ export default function Sublink({
|
|
|
63
67
|
|
|
64
68
|
// Section with children
|
|
65
69
|
return (
|
|
66
|
-
<div className="flex flex-col">
|
|
70
|
+
<div className={cn("flex flex-col", levelPadding)}>
|
|
67
71
|
{/* Section header */}
|
|
68
72
|
<button
|
|
69
73
|
type="button"
|
|
@@ -1,56 +1,32 @@
|
|
|
1
1
|
import type { ComponentType } from "react";
|
|
2
2
|
import { createMdxComponents } from "@docubook/mdx-content";
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
DropdownLabel,
|
|
8
|
-
DropdownDivider,
|
|
9
|
-
} from "./base/dropdown";
|
|
10
|
-
import {
|
|
11
|
-
Pagination,
|
|
12
|
-
PaginationItem,
|
|
13
|
-
PaginationButtons,
|
|
14
|
-
PaginationRange,
|
|
15
|
-
PaginationInfo,
|
|
16
|
-
PaginationFull,
|
|
17
|
-
PaginationDocs,
|
|
18
|
-
} from "./base/pagination";
|
|
19
|
-
import { Toggle, ToggleGroup } from "./base/toggle";
|
|
20
|
-
import {
|
|
21
|
-
ThemeController,
|
|
22
|
-
ThemeControllerToggle,
|
|
23
|
-
ThemeControllerSelect,
|
|
24
|
-
ThemeControllerRadio,
|
|
25
|
-
} from "./base/theme-controller";
|
|
3
|
+
import { Dropdown, DropdownItem, DropdownLink } from "@docubook/ui-react/dropdown";
|
|
4
|
+
import { PaginationDocs } from "@docubook/ui-react/pagination";
|
|
5
|
+
import { Toggle, ToggleGroup } from "@docubook/ui-react/toggle";
|
|
6
|
+
import { ThemeControllerToggle } from "@docubook/ui-react/theme-controller";
|
|
26
7
|
import {
|
|
27
8
|
Breadcrumb,
|
|
28
9
|
BreadcrumbItem,
|
|
29
|
-
BreadcrumbLink,
|
|
30
10
|
BreadcrumbPage,
|
|
31
|
-
BreadcrumbSeparator,
|
|
32
11
|
BreadcrumbList,
|
|
33
|
-
} from "
|
|
34
|
-
import Collapse,
|
|
12
|
+
} from "@docubook/ui-react/breadcrumbs";
|
|
13
|
+
import { Collapse, Accordion } from "@docubook/ui-react/collapse";
|
|
35
14
|
import {
|
|
36
15
|
Drawer,
|
|
37
16
|
useDrawerState,
|
|
38
17
|
DrawerTrigger,
|
|
39
18
|
DrawerContent,
|
|
40
19
|
DrawerSidePanel,
|
|
41
|
-
} from "
|
|
42
|
-
import { Input, InputGroup } from "
|
|
43
|
-
import { Kbd, FnKey } from "
|
|
44
|
-
import { Modal,
|
|
20
|
+
} from "@docubook/ui-react/drawer";
|
|
21
|
+
import { Input, InputGroup } from "@docubook/ui-react/input";
|
|
22
|
+
import { Kbd, FnKey } from "@docubook/ui-react/kbd";
|
|
23
|
+
import { Modal, useModal } from "@docubook/ui-react/modal";
|
|
45
24
|
import {
|
|
46
25
|
Navbar as BaseNavbar,
|
|
47
|
-
NavbarContainer,
|
|
48
26
|
Logo as BaseLogo,
|
|
49
27
|
NavMenu as BaseNavMenu,
|
|
50
28
|
NavMenuLink,
|
|
51
|
-
|
|
52
|
-
NavbarVersion,
|
|
53
|
-
} from "./base/navbar";
|
|
29
|
+
} from "@docubook/ui-react/navbar";
|
|
54
30
|
import PaginationComp from "./Pagination";
|
|
55
31
|
import Anchor from "./Anchor";
|
|
56
32
|
import { Footer } from "./Footer";
|
|
@@ -71,40 +47,17 @@ import {
|
|
|
71
47
|
import Search from "./Search";
|
|
72
48
|
import Sidebar from "./Sidebar";
|
|
73
49
|
|
|
74
|
-
export { Dropdown, DropdownItem, DropdownLink
|
|
75
|
-
export {
|
|
76
|
-
Pagination,
|
|
77
|
-
PaginationItem,
|
|
78
|
-
PaginationButtons,
|
|
79
|
-
PaginationRange,
|
|
80
|
-
PaginationInfo,
|
|
81
|
-
PaginationFull,
|
|
82
|
-
PaginationDocs,
|
|
83
|
-
};
|
|
50
|
+
export { Dropdown, DropdownItem, DropdownLink };
|
|
51
|
+
export { PaginationDocs };
|
|
84
52
|
export { Toggle, ToggleGroup };
|
|
85
|
-
export {
|
|
86
|
-
export {
|
|
87
|
-
Breadcrumb,
|
|
88
|
-
BreadcrumbItem,
|
|
89
|
-
BreadcrumbLink,
|
|
90
|
-
BreadcrumbPage,
|
|
91
|
-
BreadcrumbSeparator,
|
|
92
|
-
BreadcrumbList,
|
|
93
|
-
};
|
|
53
|
+
export { ThemeControllerToggle };
|
|
54
|
+
export { Breadcrumb, BreadcrumbItem, BreadcrumbPage, BreadcrumbList };
|
|
94
55
|
export { Collapse, Accordion };
|
|
95
56
|
export { Drawer, useDrawerState, DrawerTrigger, DrawerContent, DrawerSidePanel };
|
|
96
57
|
export { Input, InputGroup };
|
|
97
58
|
export { Kbd, FnKey };
|
|
98
|
-
export { Modal,
|
|
99
|
-
export {
|
|
100
|
-
BaseNavbar,
|
|
101
|
-
NavbarContainer,
|
|
102
|
-
BaseLogo,
|
|
103
|
-
BaseNavMenu,
|
|
104
|
-
NavMenuLink,
|
|
105
|
-
NavToggle,
|
|
106
|
-
NavbarVersion,
|
|
107
|
-
};
|
|
59
|
+
export { Modal, useModal };
|
|
60
|
+
export { BaseNavbar, BaseLogo, BaseNavMenu, NavMenuLink };
|
|
108
61
|
export { Footer };
|
|
109
62
|
export { ThemeToggle };
|
|
110
63
|
export { Context };
|
|
@@ -122,16 +75,8 @@ const BASE_COMPONENTS = {
|
|
|
122
75
|
Dropdown,
|
|
123
76
|
DropdownItem,
|
|
124
77
|
DropdownLink,
|
|
125
|
-
DropdownLabel,
|
|
126
|
-
DropdownDivider,
|
|
127
78
|
|
|
128
79
|
// Pagination
|
|
129
|
-
Pagination,
|
|
130
|
-
PaginationItem,
|
|
131
|
-
PaginationButtons,
|
|
132
|
-
PaginationRange,
|
|
133
|
-
PaginationInfo,
|
|
134
|
-
PaginationFull,
|
|
135
80
|
PaginationDocs,
|
|
136
81
|
|
|
137
82
|
// Toggle
|
|
@@ -139,17 +84,12 @@ const BASE_COMPONENTS = {
|
|
|
139
84
|
ToggleGroup,
|
|
140
85
|
|
|
141
86
|
// Theme
|
|
142
|
-
ThemeController,
|
|
143
87
|
ThemeControllerToggle,
|
|
144
|
-
ThemeControllerSelect,
|
|
145
|
-
ThemeControllerRadio,
|
|
146
88
|
|
|
147
89
|
// Breadcrumb
|
|
148
90
|
Breadcrumb,
|
|
149
91
|
BreadcrumbItem,
|
|
150
|
-
BreadcrumbLink,
|
|
151
92
|
BreadcrumbPage,
|
|
152
|
-
BreadcrumbSeparator,
|
|
153
93
|
BreadcrumbList,
|
|
154
94
|
|
|
155
95
|
// Accordion
|
|
@@ -173,17 +113,13 @@ const BASE_COMPONENTS = {
|
|
|
173
113
|
|
|
174
114
|
// Modal
|
|
175
115
|
Modal,
|
|
176
|
-
ModalAction,
|
|
177
116
|
useModal,
|
|
178
117
|
|
|
179
118
|
// Base Navbar
|
|
180
119
|
BaseNavbar,
|
|
181
|
-
NavbarContainer,
|
|
182
120
|
BaseLogo,
|
|
183
121
|
BaseNavMenu,
|
|
184
122
|
NavMenuLink,
|
|
185
|
-
NavToggle,
|
|
186
|
-
NavbarVersion,
|
|
187
123
|
} as const;
|
|
188
124
|
|
|
189
125
|
const APP_COMPONENTS = {
|
|
@@ -216,15 +152,13 @@ export function createComponentsRegistry(): Record<string, unknown> {
|
|
|
216
152
|
export async function createFullComponentsRegistry(): Promise<Record<string, unknown>> {
|
|
217
153
|
const baseComponents = createComponentsRegistry();
|
|
218
154
|
|
|
219
|
-
let mdxComponents: ComponentRegistry = {};
|
|
220
155
|
try {
|
|
221
156
|
const mdx = createMdxComponents() as unknown as ComponentRegistry;
|
|
222
|
-
|
|
223
|
-
} catch {
|
|
224
|
-
|
|
157
|
+
return { ...baseComponents, ...mdx };
|
|
158
|
+
} catch (error) {
|
|
159
|
+
console.error("Failed to load MDX components:", error);
|
|
160
|
+
return { ...baseComponents };
|
|
225
161
|
}
|
|
226
|
-
|
|
227
|
-
return { ...baseComponents, ...mdxComponents };
|
|
228
162
|
}
|
|
229
163
|
|
|
230
164
|
export const componentsRegistry = createComponentsRegistry();
|
package/.docu/node/build.ts
CHANGED
|
@@ -83,7 +83,11 @@ async function findMdxFiles(dir: string, baseDir = ""): Promise<{ path: string;
|
|
|
83
83
|
return files;
|
|
84
84
|
}
|
|
85
85
|
|
|
86
|
-
function
|
|
86
|
+
export function parseConcurrency(): number {
|
|
87
|
+
return Math.max(1, parseInt(process.env.BUILD_CONCURRENCY || "10", 10) || 10);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export function shouldRebuild(path: string, mtime: number, cache: BuildCache): boolean {
|
|
87
91
|
const cached = cache[path];
|
|
88
92
|
if (!cached) return true;
|
|
89
93
|
return mtime > cached.builtAt;
|
|
@@ -212,7 +216,7 @@ async function build() {
|
|
|
212
216
|
.filter((p): p is string => p !== null);
|
|
213
217
|
const gitDates = await getGitLastModifiedBatch(allRelPaths);
|
|
214
218
|
|
|
215
|
-
const CONCURRENCY =
|
|
219
|
+
const CONCURRENCY = parseConcurrency();
|
|
216
220
|
const buildTasks = [];
|
|
217
221
|
const errors: string[] = [];
|
|
218
222
|
|
package/.docu/node/client.ts
CHANGED
|
@@ -5,16 +5,9 @@ import { createMdxComponents } from "@docubook/mdx-content";
|
|
|
5
5
|
import Sidebar, { MobileBar } from "../components/Sidebar";
|
|
6
6
|
import Toc from "../components/Toc";
|
|
7
7
|
import { ThemeToggle } from "../components/Theme";
|
|
8
|
+
import { safeParseTocs } from "./parse-tocs";
|
|
8
9
|
import type { TocItem } from "./types";
|
|
9
10
|
|
|
10
|
-
function safeParseTocs(raw: string | undefined): TocItem[] {
|
|
11
|
-
try {
|
|
12
|
-
return JSON.parse(raw || "[]");
|
|
13
|
-
} catch {
|
|
14
|
-
return [];
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
|
|
18
11
|
function mountIsland(
|
|
19
12
|
id: string,
|
|
20
13
|
render: (el: HTMLElement) => React.ReactElement,
|
package/.docu/node/html.ts
CHANGED
|
@@ -29,3 +29,15 @@ export function htmlShell(opts: HtmlShellOptions): string {
|
|
|
29
29
|
</body>
|
|
30
30
|
</html>`;
|
|
31
31
|
}
|
|
32
|
+
|
|
33
|
+
export function hmrScript(nonce: string): string {
|
|
34
|
+
return `<script nonce="${Bun.escapeHTML(nonce)}">
|
|
35
|
+
(function(){
|
|
36
|
+
const es = new EventSource("/__hmr");
|
|
37
|
+
es.onmessage = function(e) {
|
|
38
|
+
if (e.data === "reload") window.location.reload();
|
|
39
|
+
};
|
|
40
|
+
es.onerror = function() { es.close(); setTimeout(() => { window.location.reload(); }, 2000); };
|
|
41
|
+
})();
|
|
42
|
+
</script>`;
|
|
43
|
+
}
|
|
@@ -56,7 +56,19 @@ function slugify(text: string): string {
|
|
|
56
56
|
.replace(/^-+|-+$/g, "");
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
-
function
|
|
59
|
+
export function stripJsx(content: string): string {
|
|
60
|
+
let result = content;
|
|
61
|
+
let prev = "";
|
|
62
|
+
while (result !== prev) {
|
|
63
|
+
prev = result;
|
|
64
|
+
result = result
|
|
65
|
+
.replace(/<[A-Z][\w.]*[\s\S]*?\/>/g, "")
|
|
66
|
+
.replace(/<[A-Z][\w.]*[\s\S]*?>([\s\S]*?)<\/[A-Z][\w.]*>/g, "$1");
|
|
67
|
+
}
|
|
68
|
+
return result;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export function extractRecords(filePath: string, raw: string): SearchRecord[] {
|
|
60
72
|
const { frontmatter, strippedContent: content } = extractFrontmatterWithContent<Frontmatter>(raw);
|
|
61
73
|
const records: SearchRecord[] = [];
|
|
62
74
|
const url = `/docs/${filePath}`;
|
|
@@ -82,7 +94,8 @@ function extractRecords(filePath: string, raw: string): SearchRecord[] {
|
|
|
82
94
|
});
|
|
83
95
|
}
|
|
84
96
|
|
|
85
|
-
const
|
|
97
|
+
const plainContent = stripJsx(content);
|
|
98
|
+
const lines = plainContent.split("\n");
|
|
86
99
|
let currentParagraph: string[] = [];
|
|
87
100
|
let inCodeBlock = false;
|
|
88
101
|
|
|
@@ -119,7 +132,6 @@ function extractRecords(filePath: string, raw: string): SearchRecord[] {
|
|
|
119
132
|
if (inCodeBlock) continue;
|
|
120
133
|
|
|
121
134
|
if (/^import\s+[\w{*]/.test(trimmed) || /^export\s+[\w{*]/.test(trimmed)) continue;
|
|
122
|
-
if (/^<\/?[A-Z][\w.]*[\s/>]/.test(trimmed) && !/>(.+)<\//.test(trimmed)) continue;
|
|
123
135
|
|
|
124
136
|
const headingMatch = trimmed.match(/^(#{1,6})\s+(.+)$/);
|
|
125
137
|
if (headingMatch) {
|
|
@@ -152,6 +164,8 @@ function extractRecords(filePath: string, raw: string): SearchRecord[] {
|
|
|
152
164
|
continue;
|
|
153
165
|
}
|
|
154
166
|
|
|
167
|
+
if (/^\|.+\|/.test(trimmed)) continue;
|
|
168
|
+
|
|
155
169
|
const cleaned = trimmed
|
|
156
170
|
.replace(/^[-*+]\s+/, "") // list markers
|
|
157
171
|
.replace(/^\d+\.\s+/, "") // ordered list
|
package/.docu/node/server.ts
CHANGED
|
@@ -16,7 +16,7 @@ import { generateSearchIndex } from "./search-indexer";
|
|
|
16
16
|
import { logger } from "./logger";
|
|
17
17
|
import { initSentry, captureException } from "./sentry";
|
|
18
18
|
import { SECURITY_HEADERS, generateNonce, htmlResponse } from "./security";
|
|
19
|
-
import { htmlShell as createHtmlShell } from "./html";
|
|
19
|
+
import { htmlShell as createHtmlShell, hmrScript } from "./html";
|
|
20
20
|
|
|
21
21
|
const docuConfig = loadDocuConfig();
|
|
22
22
|
|
|
@@ -50,18 +50,6 @@ try {
|
|
|
50
50
|
|
|
51
51
|
const hmrClients = new Set<ReadableStreamDefaultController>();
|
|
52
52
|
|
|
53
|
-
function hmrScript(nonce: string): string {
|
|
54
|
-
return `<script nonce="${Bun.escapeHTML(nonce)}">
|
|
55
|
-
(function(){
|
|
56
|
-
const es = new EventSource("/__hmr");
|
|
57
|
-
es.onmessage = function(e) {
|
|
58
|
-
if (e.data === "reload") window.location.reload();
|
|
59
|
-
};
|
|
60
|
-
es.onerror = function() { es.close(); setTimeout(() => { window.location.reload(); }, 2000); };
|
|
61
|
-
})();
|
|
62
|
-
</script>`;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
53
|
let hmrTimeout: ReturnType<typeof setTimeout> | null = null;
|
|
66
54
|
const watcher = watch(DOCS_DIR, { recursive: true }, (_event, filename) => {
|
|
67
55
|
if (!filename || (!filename.endsWith(".mdx") && !filename.endsWith(".md"))) return;
|
package/.docu/node/utils.ts
CHANGED
|
@@ -7,7 +7,8 @@ export function isExternalUrl(url: string): boolean {
|
|
|
7
7
|
export function getPath(url: string): string {
|
|
8
8
|
try {
|
|
9
9
|
return new URL(url).pathname;
|
|
10
|
-
} catch {
|
|
10
|
+
} catch (err) {
|
|
11
|
+
console.error("Failed to parse URL", url, err);
|
|
11
12
|
return url;
|
|
12
13
|
}
|
|
13
14
|
}
|
|
@@ -28,7 +29,8 @@ export async function getGitLastModified(filePath: string): Promise<string | nul
|
|
|
28
29
|
const text = await new Response(proc.stdout).text();
|
|
29
30
|
const date = text.trim();
|
|
30
31
|
return date || null;
|
|
31
|
-
} catch {
|
|
32
|
+
} catch (err) {
|
|
33
|
+
console.error("Failed to get git last modified for", filePath, err);
|
|
32
34
|
return null;
|
|
33
35
|
}
|
|
34
36
|
}
|
|
@@ -55,8 +57,8 @@ export async function getGitLastModifiedBatch(filePaths: string[]): Promise<Map<
|
|
|
55
57
|
result.set(trimmed, currentDate);
|
|
56
58
|
}
|
|
57
59
|
}
|
|
58
|
-
} catch {
|
|
59
|
-
|
|
60
|
+
} catch (err) {
|
|
61
|
+
console.error("Failed to get git last modified batch for", filePaths, err);
|
|
60
62
|
}
|
|
61
63
|
|
|
62
64
|
return result;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { ReactNode } from "react";
|
|
2
|
+
import { ChevronLeft, ChevronRight } from "lucide-react";
|
|
2
3
|
import DocsBreadcrumb from "../../components/Breadcrumb";
|
|
3
4
|
import Pagination from "../../components/Pagination";
|
|
4
5
|
import { Typography } from "../../components/Typography";
|
|
@@ -72,7 +73,11 @@ export default function DocsPage({
|
|
|
72
73
|
</p>
|
|
73
74
|
)}
|
|
74
75
|
</div>
|
|
75
|
-
<Pagination
|
|
76
|
+
<Pagination
|
|
77
|
+
pathname={pathname}
|
|
78
|
+
prevIcon={<ChevronLeft className="h-3 w-3" />}
|
|
79
|
+
nextIcon={<ChevronRight className="h-3 w-3" />}
|
|
80
|
+
/>
|
|
76
81
|
<Footer />
|
|
77
82
|
</Typography>
|
|
78
83
|
</div>
|
package/.docu/styles/globals.css
CHANGED
|
@@ -126,6 +126,14 @@
|
|
|
126
126
|
background-color 0.2s ease,
|
|
127
127
|
color 0.2s ease;
|
|
128
128
|
}
|
|
129
|
+
|
|
130
|
+
/* Remove default summary marker from details elements */
|
|
131
|
+
summary::-webkit-details-marker {
|
|
132
|
+
display: none;
|
|
133
|
+
}
|
|
134
|
+
summary::marker {
|
|
135
|
+
display: none;
|
|
136
|
+
}
|
|
129
137
|
}
|
|
130
138
|
|
|
131
139
|
/* Code block utilities */
|
package/README.md
CHANGED
|
@@ -16,12 +16,12 @@
|
|
|
16
16
|
|
|
17
17
|
```bash
|
|
18
18
|
mkdir my-docs && cd my-docs
|
|
19
|
-
bun add @docubook/flame
|
|
19
|
+
bun add @docubook/flame
|
|
20
20
|
bunx flame init
|
|
21
21
|
bun run dev
|
|
22
22
|
```
|
|
23
23
|
|
|
24
|
-
>
|
|
24
|
+
> **Lightweight** — 📦 ~57 kB packed, ~207 kB unpacked. No bloat, just fire.
|
|
25
25
|
|
|
26
26
|
## Features
|
|
27
27
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@docubook/flame",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.1",
|
|
4
4
|
"description": "A blazing-fast React + MDX framework powered by Bun, built for modern documentation experiences.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -30,12 +30,15 @@
|
|
|
30
30
|
"static-site",
|
|
31
31
|
"daisyui",
|
|
32
32
|
"bun",
|
|
33
|
-
"docs framework"
|
|
33
|
+
"docs framework",
|
|
34
|
+
"react",
|
|
35
|
+
"react-dom"
|
|
34
36
|
],
|
|
35
37
|
"homepage": "https://docubook.pro/",
|
|
36
38
|
"repository": {
|
|
37
39
|
"type": "git",
|
|
38
|
-
"url": "git+https://github.com/DocuBook/docubook.git"
|
|
40
|
+
"url": "git+https://github.com/DocuBook/docubook.git",
|
|
41
|
+
"directory": "packages/flame"
|
|
39
42
|
},
|
|
40
43
|
"author": "wildan.nrs",
|
|
41
44
|
"author-url": "https://wildan.dev",
|
|
@@ -48,8 +51,9 @@
|
|
|
48
51
|
"lucide-react": "^1.14.0",
|
|
49
52
|
"react": "^19.0.0",
|
|
50
53
|
"react-dom": "^19.0.0",
|
|
54
|
+
"@docubook/mdx-content": "^3.2.1",
|
|
51
55
|
"@docubook/core": "^1.7.0",
|
|
52
|
-
"@docubook/
|
|
56
|
+
"@docubook/ui-react": "^0.1.2"
|
|
53
57
|
},
|
|
54
58
|
"peerDependencies": {
|
|
55
59
|
"@sentry/bun": "^9.0.0"
|