@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.
Files changed (36) hide show
  1. package/.docu/components/Anchor.tsx +1 -1
  2. package/.docu/components/Breadcrumb.tsx +6 -1
  3. package/.docu/components/Context.tsx +2 -1
  4. package/.docu/components/Navbar.tsx +2 -2
  5. package/.docu/components/Pagination.tsx +15 -2
  6. package/.docu/components/Search.tsx +4 -10
  7. package/.docu/components/Sidebar.tsx +19 -4
  8. package/.docu/components/Sublink.tsx +6 -2
  9. package/.docu/components/Theme.tsx +1 -1
  10. package/.docu/components/registry.ts +21 -87
  11. package/.docu/node/build.ts +6 -2
  12. package/.docu/node/client.ts +1 -8
  13. package/.docu/node/html.ts +12 -0
  14. package/.docu/node/parse-tocs.ts +10 -0
  15. package/.docu/node/search-indexer.ts +17 -3
  16. package/.docu/node/server.ts +1 -13
  17. package/.docu/node/utils.ts +6 -4
  18. package/.docu/pages/docs/[[...slug]].tsx +6 -1
  19. package/.docu/styles/globals.css +8 -0
  20. package/README.md +2 -2
  21. package/package.json +8 -4
  22. package/template/docs/index.mdx +122 -16
  23. package/.docu/components/base/breadcrumbs.tsx +0 -64
  24. package/.docu/components/base/collapse.tsx +0 -186
  25. package/.docu/components/base/drawer.tsx +0 -164
  26. package/.docu/components/base/dropdown.tsx +0 -94
  27. package/.docu/components/base/input.tsx +0 -53
  28. package/.docu/components/base/kbd.tsx +0 -51
  29. package/.docu/components/base/modal.tsx +0 -56
  30. package/.docu/components/base/navbar.tsx +0 -132
  31. package/.docu/components/base/pagination/index.ts +0 -21
  32. package/.docu/components/base/pagination/pagination-docs.tsx +0 -39
  33. package/.docu/components/base/pagination/pagination-numbers.tsx +0 -379
  34. package/.docu/components/base/pagination/types.ts +0 -129
  35. package/.docu/components/base/theme-controller.tsx +0 -358
  36. 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
- "text-blue-600 hover:text-blue-800 hover:underline transition-colors",
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 { Breadcrumb, BreadcrumbItem, BreadcrumbList, BreadcrumbPage } from "./base/breadcrumbs";
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 "./base/dropdown";
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 "./base/navbar";
11
+ } from "@docubook/ui-react/navbar";
12
12
 
13
- export type { NavMenuItem } from "./base/navbar";
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 "./base/pagination";
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({ pathname, className }: PaginationProps) {
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 "./base/modal";
6
- import { Kbd, FnKey } from "./base/kbd";
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, DropdownLink } from "./base/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
- <DropdownLink key={item.href} href={item.href}>
143
- {item.title}
144
- </DropdownLink>
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
- level >= 2 && "border-l-2 pl-3",
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,7 +1,7 @@
1
1
  "use client";
2
2
 
3
3
  import { Moon, Sun } from "lucide-react";
4
- import { ThemeControllerToggle } from "./base/theme-controller";
4
+ import { ThemeControllerToggle } from "@docubook/ui-react/theme-controller";
5
5
 
6
6
  interface ThemeToggleProps {
7
7
  className?: string;
@@ -1,56 +1,32 @@
1
1
  import type { ComponentType } from "react";
2
2
  import { createMdxComponents } from "@docubook/mdx-content";
3
- import {
4
- Dropdown,
5
- DropdownItem,
6
- DropdownLink,
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 "./base/breadcrumbs";
34
- import Collapse, { Accordion } from "./base/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 "./base/drawer";
42
- import { Input, InputGroup } from "./base/input";
43
- import { Kbd, FnKey } from "./base/kbd";
44
- import { Modal, ModalAction, useModal } from "./base/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
- NavToggle,
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, DropdownLabel, DropdownDivider };
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 { ThemeController, ThemeControllerToggle, ThemeControllerSelect, ThemeControllerRadio };
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, ModalAction, useModal };
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
- mdxComponents = mdx;
223
- } catch {
224
- // MDX components not available
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();
@@ -83,7 +83,11 @@ async function findMdxFiles(dir: string, baseDir = ""): Promise<{ path: string;
83
83
  return files;
84
84
  }
85
85
 
86
- function shouldRebuild(path: string, mtime: number, cache: BuildCache): boolean {
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 = Math.max(1, parseInt(process.env.BUILD_CONCURRENCY || "10", 10) || 10);
219
+ const CONCURRENCY = parseConcurrency();
216
220
  const buildTasks = [];
217
221
  const errors: string[] = [];
218
222
 
@@ -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,
@@ -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
+ }
@@ -0,0 +1,10 @@
1
+ import type { TocItem } from "./types";
2
+
3
+ export function safeParseTocs(raw: string | undefined): TocItem[] {
4
+ try {
5
+ const parsed = JSON.parse(raw || "[]");
6
+ return Array.isArray(parsed) ? parsed : [];
7
+ } catch {
8
+ return [];
9
+ }
10
+ }
@@ -56,7 +56,19 @@ function slugify(text: string): string {
56
56
  .replace(/^-+|-+$/g, "");
57
57
  }
58
58
 
59
- function extractRecords(filePath: string, raw: string): SearchRecord[] {
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 lines = content.split("\n");
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
@@ -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;
@@ -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
- // fallback: return empty map, callers use frontmatter date
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 pathname={pathname} />
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>
@@ -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@beta
19
+ bun add @docubook/flame
20
20
  bunx flame init
21
21
  bun run dev
22
22
  ```
23
23
 
24
- > 📦 **Lightweight** — ~57 kB packed, ~207 kB unpacked. No bloat, just fire.
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.0-beta.80",
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/mdx-content": "^3.2.1"
56
+ "@docubook/ui-react": "^0.1.2"
53
57
  },
54
58
  "peerDependencies": {
55
59
  "@sentry/bun": "^9.0.0"