boltdocs 1.3.0 → 1.3.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 (101) hide show
  1. package/dist/node/index.js +21 -6
  2. package/dist/node/index.mjs +21 -6
  3. package/package.json +1 -1
  4. package/src/client/app/index.tsx +344 -344
  5. package/src/client/app/preload.tsx +56 -56
  6. package/src/client/index.ts +40 -40
  7. package/src/client/ssr.tsx +51 -51
  8. package/src/client/theme/components/CodeBlock/CodeBlock.tsx +76 -76
  9. package/src/client/theme/components/CodeBlock/index.ts +1 -1
  10. package/src/client/theme/components/PackageManagerTabs/PackageManagerTabs.tsx +154 -154
  11. package/src/client/theme/components/PackageManagerTabs/index.ts +1 -1
  12. package/src/client/theme/components/PackageManagerTabs/pkg-tabs.css +64 -64
  13. package/src/client/theme/components/Playground/Playground.tsx +124 -124
  14. package/src/client/theme/components/Playground/index.ts +1 -1
  15. package/src/client/theme/components/Playground/playground.css +168 -168
  16. package/src/client/theme/components/Video/Video.tsx +84 -84
  17. package/src/client/theme/components/Video/index.ts +1 -1
  18. package/src/client/theme/components/Video/video.css +41 -41
  19. package/src/client/theme/components/mdx/Admonition.tsx +80 -80
  20. package/src/client/theme/components/mdx/Badge.tsx +31 -31
  21. package/src/client/theme/components/mdx/Button.tsx +50 -50
  22. package/src/client/theme/components/mdx/Card.tsx +80 -80
  23. package/src/client/theme/components/mdx/List.tsx +57 -57
  24. package/src/client/theme/components/mdx/Tabs.tsx +94 -94
  25. package/src/client/theme/components/mdx/index.ts +18 -18
  26. package/src/client/theme/components/mdx/mdx-components.css +424 -424
  27. package/src/client/theme/icons/bun.tsx +62 -62
  28. package/src/client/theme/icons/deno.tsx +20 -20
  29. package/src/client/theme/icons/discord.tsx +12 -12
  30. package/src/client/theme/icons/github.tsx +15 -15
  31. package/src/client/theme/icons/npm.tsx +13 -13
  32. package/src/client/theme/icons/pnpm.tsx +72 -72
  33. package/src/client/theme/icons/twitter.tsx +12 -12
  34. package/src/client/theme/styles/markdown.css +343 -343
  35. package/src/client/theme/styles/variables.css +162 -162
  36. package/src/client/theme/styles.css +37 -37
  37. package/src/client/theme/ui/BackgroundGradient/BackgroundGradient.tsx +10 -10
  38. package/src/client/theme/ui/BackgroundGradient/index.ts +1 -1
  39. package/src/client/theme/ui/Breadcrumbs/Breadcrumbs.tsx +68 -68
  40. package/src/client/theme/ui/Breadcrumbs/index.ts +1 -1
  41. package/src/client/theme/ui/Footer/footer.css +32 -32
  42. package/src/client/theme/ui/Head/Head.tsx +69 -69
  43. package/src/client/theme/ui/Head/index.ts +1 -1
  44. package/src/client/theme/ui/LanguageSwitcher/LanguageSwitcher.tsx +125 -125
  45. package/src/client/theme/ui/LanguageSwitcher/index.ts +1 -1
  46. package/src/client/theme/ui/LanguageSwitcher/language-switcher.css +98 -98
  47. package/src/client/theme/ui/Layout/Layout.tsx +202 -202
  48. package/src/client/theme/ui/Layout/base.css +76 -76
  49. package/src/client/theme/ui/Layout/index.ts +2 -2
  50. package/src/client/theme/ui/Layout/pagination.css +72 -72
  51. package/src/client/theme/ui/Layout/responsive.css +36 -36
  52. package/src/client/theme/ui/Link/Link.tsx +254 -254
  53. package/src/client/theme/ui/Link/index.ts +2 -2
  54. package/src/client/theme/ui/Loading/Loading.tsx +10 -10
  55. package/src/client/theme/ui/Loading/index.ts +1 -1
  56. package/src/client/theme/ui/Loading/loading.css +30 -30
  57. package/src/client/theme/ui/Navbar/GithubStars.tsx +27 -27
  58. package/src/client/theme/ui/Navbar/Navbar.tsx +145 -145
  59. package/src/client/theme/ui/Navbar/index.ts +2 -2
  60. package/src/client/theme/ui/Navbar/navbar.css +233 -233
  61. package/src/client/theme/ui/NotFound/NotFound.tsx +19 -19
  62. package/src/client/theme/ui/NotFound/index.ts +1 -1
  63. package/src/client/theme/ui/NotFound/not-found.css +64 -64
  64. package/src/client/theme/ui/OnThisPage/OnThisPage.tsx +235 -235
  65. package/src/client/theme/ui/OnThisPage/index.ts +1 -1
  66. package/src/client/theme/ui/OnThisPage/toc.css +132 -132
  67. package/src/client/theme/ui/PoweredBy/PoweredBy.tsx +18 -18
  68. package/src/client/theme/ui/PoweredBy/index.ts +1 -1
  69. package/src/client/theme/ui/PoweredBy/powered-by.css +76 -76
  70. package/src/client/theme/ui/SearchDialog/SearchDialog.tsx +199 -199
  71. package/src/client/theme/ui/SearchDialog/index.ts +1 -1
  72. package/src/client/theme/ui/SearchDialog/search.css +152 -152
  73. package/src/client/theme/ui/Sidebar/Sidebar.tsx +204 -204
  74. package/src/client/theme/ui/Sidebar/index.ts +1 -1
  75. package/src/client/theme/ui/Sidebar/sidebar.css +236 -236
  76. package/src/client/theme/ui/ThemeToggle/ThemeToggle.tsx +69 -69
  77. package/src/client/theme/ui/ThemeToggle/index.ts +1 -1
  78. package/src/client/theme/ui/VersionSwitcher/VersionSwitcher.tsx +136 -136
  79. package/src/client/theme/ui/VersionSwitcher/index.ts +1 -1
  80. package/src/client/types.ts +50 -50
  81. package/src/client/utils.ts +26 -26
  82. package/src/node/cache.ts +408 -408
  83. package/src/node/config.ts +192 -192
  84. package/src/node/index.ts +21 -21
  85. package/src/node/mdx.ts +120 -120
  86. package/src/node/plugin/entry.ts +58 -58
  87. package/src/node/plugin/html.ts +55 -55
  88. package/src/node/plugin/index.ts +193 -193
  89. package/src/node/plugin/types.ts +11 -11
  90. package/src/node/routes/cache.ts +28 -28
  91. package/src/node/routes/index.ts +167 -167
  92. package/src/node/routes/parser.ts +153 -127
  93. package/src/node/routes/sorter.ts +42 -42
  94. package/src/node/routes/types.ts +49 -49
  95. package/src/node/ssg/index.ts +114 -114
  96. package/src/node/ssg/meta.ts +34 -34
  97. package/src/node/ssg/options.ts +13 -13
  98. package/src/node/ssg/sitemap.ts +54 -54
  99. package/src/node/utils.ts +134 -134
  100. package/tsconfig.json +20 -20
  101. package/tsup.config.ts +22 -22
@@ -1,204 +1,204 @@
1
- import React, { useState } from "react";
2
- import { useLocation } from "react-router-dom";
3
- import { Link } from "../Link";
4
- import { BoltdocsConfig } from "../../../../node/config";
5
- import { PoweredBy } from "../PoweredBy";
6
- import { ChevronRight, ChevronLeft, PanelLeft } from "lucide-react";
7
-
8
- interface RouteItem {
9
- path: string;
10
- title: string;
11
- group?: string;
12
- groupTitle?: string;
13
- sidebarPosition?: number;
14
- badge?: string | { text: string; expires?: string };
15
- }
16
-
17
- interface SidebarGroup {
18
- slug: string;
19
- title: string;
20
- routes: RouteItem[];
21
- }
22
-
23
- /**
24
- * Renders a small badge next to sidebar items if one exists and hasn't expired.
25
- */
26
- function renderBadge(badgeRaw: RouteItem["badge"]) {
27
- if (!badgeRaw) return null;
28
-
29
- let text = "";
30
- let expires = "";
31
-
32
- if (typeof badgeRaw === "string") {
33
- text = badgeRaw;
34
- } else {
35
- text = badgeRaw.text;
36
- expires = badgeRaw.expires || "";
37
- }
38
-
39
- // Check expiration
40
- if (expires) {
41
- const expireDate = new Date(expires);
42
- const now = new Date();
43
- // Reset time components for accurate day comparison
44
- expireDate.setHours(0, 0, 0, 0);
45
- now.setHours(0, 0, 0, 0);
46
- if (now > expireDate) {
47
- return null;
48
- }
49
- }
50
-
51
- if (!text) return null;
52
-
53
- if (!text) return null;
54
-
55
- let typeClass = "badge-default";
56
- const lowerText = text.toLowerCase();
57
- if (lowerText === "new") {
58
- typeClass = "badge-new";
59
- } else if (lowerText === "experimental") {
60
- typeClass = "badge-experimental";
61
- } else if (lowerText === "updated") {
62
- typeClass = "badge-updated";
63
- }
64
-
65
- return <span className={`sidebar-badge ${typeClass}`}>{text}</span>;
66
- }
67
-
68
- /**
69
- * The sidebar navigation component.
70
- * Groups documentation routes logically based on the `group` property.
71
- * Highlights the active link based on the current URL path.
72
- *
73
- * @param routes - Array of all generated routes to be displayed
74
- * @param config - Global configuration (which can contain sidebar overrides)
75
- */
76
- export function Sidebar({
77
- routes,
78
- config,
79
- isCollapsed,
80
- onToggle,
81
- }: {
82
- routes: RouteItem[];
83
- config: BoltdocsConfig;
84
- isCollapsed?: boolean;
85
- onToggle?: () => void;
86
- }) {
87
- const location = useLocation();
88
-
89
- const ungrouped: RouteItem[] = [];
90
- const groupMap = new Map<string, SidebarGroup>();
91
-
92
- for (const route of routes) {
93
- if (!route.group) {
94
- ungrouped.push(route);
95
- } else {
96
- if (!groupMap.has(route.group)) {
97
- groupMap.set(route.group, {
98
- slug: route.group,
99
- title: route.groupTitle || route.group,
100
- routes: [],
101
- });
102
- }
103
- groupMap.get(route.group)!.routes.push(route);
104
- }
105
- }
106
-
107
- const groups = Array.from(groupMap.values());
108
-
109
- return (
110
- <aside className="boltdocs-sidebar">
111
- {onToggle && (
112
- <div className="sidebar-collapse">
113
- <button
114
- className="sidebar-collapse-btn"
115
- onClick={onToggle}
116
- aria-label={isCollapsed ? "Expand Sidebar" : "Collapse Sidebar"}
117
- title={isCollapsed ? "Expand Sidebar" : "Collapse Sidebar"}
118
- >
119
- <PanelLeft size={18} />
120
- </button>
121
- </div>
122
- )}
123
-
124
- {!isCollapsed && (
125
- <>
126
- <nav aria-label="Main Navigation">
127
- <ul className="sidebar-list">
128
- {ungrouped.map((route) => (
129
- <li key={route.path}>
130
- <Link
131
- to={route.path === "" ? "/" : route.path}
132
- className={`sidebar-link ${location.pathname === route.path ? "active" : ""}`}
133
- aria-current={
134
- location.pathname === route.path ? "page" : undefined
135
- }
136
- >
137
- <div className="sidebar-link-content">
138
- <span>{route.title}</span>
139
- {renderBadge(route.badge)}
140
- </div>
141
- </Link>
142
- </li>
143
- ))}
144
- </ul>
145
-
146
- {groups.map((group) => (
147
- <SidebarGroupSection
148
- key={group.slug}
149
- group={group}
150
- currentPath={location.pathname}
151
- />
152
- ))}
153
- </nav>
154
- {config.themeConfig?.poweredBy !== false && <PoweredBy />}
155
- </>
156
- )}
157
- </aside>
158
- );
159
- }
160
-
161
- function SidebarGroupSection({
162
- group,
163
- currentPath,
164
- }: {
165
- group: SidebarGroup;
166
- currentPath: string;
167
- }) {
168
- const isActive = group.routes.some((r) => currentPath === r.path);
169
- const [open, setOpen] = useState(true);
170
-
171
- return (
172
- <div className="sidebar-group">
173
- <button
174
- className={`sidebar-group-header ${isActive ? "active" : ""}`}
175
- onClick={() => setOpen(!open)}
176
- aria-expanded={open}
177
- aria-controls={`sidebar-group-${group.slug}`}
178
- >
179
- <span className="sidebar-group-title">{group.title}</span>
180
- <span className={`sidebar-group-chevron ${open ? "open" : ""}`}>
181
- <ChevronRight size={16} />
182
- </span>
183
- </button>
184
- {open && (
185
- <ul className="sidebar-group-list" id={`sidebar-group-${group.slug}`}>
186
- {group.routes.map((route) => (
187
- <li key={route.path}>
188
- <Link
189
- to={route.path === "" ? "/" : route.path}
190
- className={`sidebar-link sidebar-link-nested ${currentPath === route.path ? "active" : ""}`}
191
- aria-current={currentPath === route.path ? "page" : undefined}
192
- >
193
- <div className="sidebar-link-content">
194
- <span>{route.title}</span>
195
- {renderBadge(route.badge)}
196
- </div>
197
- </Link>
198
- </li>
199
- ))}
200
- </ul>
201
- )}
202
- </div>
203
- );
204
- }
1
+ import React, { useState } from "react";
2
+ import { useLocation } from "react-router-dom";
3
+ import { Link } from "../Link";
4
+ import { BoltdocsConfig } from "../../../../node/config";
5
+ import { PoweredBy } from "../PoweredBy";
6
+ import { ChevronRight, ChevronLeft, PanelLeft } from "lucide-react";
7
+
8
+ interface RouteItem {
9
+ path: string;
10
+ title: string;
11
+ group?: string;
12
+ groupTitle?: string;
13
+ sidebarPosition?: number;
14
+ badge?: string | { text: string; expires?: string };
15
+ }
16
+
17
+ interface SidebarGroup {
18
+ slug: string;
19
+ title: string;
20
+ routes: RouteItem[];
21
+ }
22
+
23
+ /**
24
+ * Renders a small badge next to sidebar items if one exists and hasn't expired.
25
+ */
26
+ function renderBadge(badgeRaw: RouteItem["badge"]) {
27
+ if (!badgeRaw) return null;
28
+
29
+ let text = "";
30
+ let expires = "";
31
+
32
+ if (typeof badgeRaw === "string") {
33
+ text = badgeRaw;
34
+ } else {
35
+ text = badgeRaw.text;
36
+ expires = badgeRaw.expires || "";
37
+ }
38
+
39
+ // Check expiration
40
+ if (expires) {
41
+ const expireDate = new Date(expires);
42
+ const now = new Date();
43
+ // Reset time components for accurate day comparison
44
+ expireDate.setHours(0, 0, 0, 0);
45
+ now.setHours(0, 0, 0, 0);
46
+ if (now > expireDate) {
47
+ return null;
48
+ }
49
+ }
50
+
51
+ if (!text) return null;
52
+
53
+ if (!text) return null;
54
+
55
+ let typeClass = "badge-default";
56
+ const lowerText = text.toLowerCase();
57
+ if (lowerText === "new") {
58
+ typeClass = "badge-new";
59
+ } else if (lowerText === "experimental") {
60
+ typeClass = "badge-experimental";
61
+ } else if (lowerText === "updated") {
62
+ typeClass = "badge-updated";
63
+ }
64
+
65
+ return <span className={`sidebar-badge ${typeClass}`}>{text}</span>;
66
+ }
67
+
68
+ /**
69
+ * The sidebar navigation component.
70
+ * Groups documentation routes logically based on the `group` property.
71
+ * Highlights the active link based on the current URL path.
72
+ *
73
+ * @param routes - Array of all generated routes to be displayed
74
+ * @param config - Global configuration (which can contain sidebar overrides)
75
+ */
76
+ export function Sidebar({
77
+ routes,
78
+ config,
79
+ isCollapsed,
80
+ onToggle,
81
+ }: {
82
+ routes: RouteItem[];
83
+ config: BoltdocsConfig;
84
+ isCollapsed?: boolean;
85
+ onToggle?: () => void;
86
+ }) {
87
+ const location = useLocation();
88
+
89
+ const ungrouped: RouteItem[] = [];
90
+ const groupMap = new Map<string, SidebarGroup>();
91
+
92
+ for (const route of routes) {
93
+ if (!route.group) {
94
+ ungrouped.push(route);
95
+ } else {
96
+ if (!groupMap.has(route.group)) {
97
+ groupMap.set(route.group, {
98
+ slug: route.group,
99
+ title: route.groupTitle || route.group,
100
+ routes: [],
101
+ });
102
+ }
103
+ groupMap.get(route.group)!.routes.push(route);
104
+ }
105
+ }
106
+
107
+ const groups = Array.from(groupMap.values());
108
+
109
+ return (
110
+ <aside className="boltdocs-sidebar">
111
+ {onToggle && (
112
+ <div className="sidebar-collapse">
113
+ <button
114
+ className="sidebar-collapse-btn"
115
+ onClick={onToggle}
116
+ aria-label={isCollapsed ? "Expand Sidebar" : "Collapse Sidebar"}
117
+ title={isCollapsed ? "Expand Sidebar" : "Collapse Sidebar"}
118
+ >
119
+ <PanelLeft size={18} />
120
+ </button>
121
+ </div>
122
+ )}
123
+
124
+ {!isCollapsed && (
125
+ <>
126
+ <nav aria-label="Main Navigation">
127
+ <ul className="sidebar-list">
128
+ {ungrouped.map((route) => (
129
+ <li key={route.path}>
130
+ <Link
131
+ to={route.path === "" ? "/" : route.path}
132
+ className={`sidebar-link ${location.pathname === route.path ? "active" : ""}`}
133
+ aria-current={
134
+ location.pathname === route.path ? "page" : undefined
135
+ }
136
+ >
137
+ <div className="sidebar-link-content">
138
+ <span>{route.title}</span>
139
+ {renderBadge(route.badge)}
140
+ </div>
141
+ </Link>
142
+ </li>
143
+ ))}
144
+ </ul>
145
+
146
+ {groups.map((group) => (
147
+ <SidebarGroupSection
148
+ key={group.slug}
149
+ group={group}
150
+ currentPath={location.pathname}
151
+ />
152
+ ))}
153
+ </nav>
154
+ {config.themeConfig?.poweredBy !== false && <PoweredBy />}
155
+ </>
156
+ )}
157
+ </aside>
158
+ );
159
+ }
160
+
161
+ function SidebarGroupSection({
162
+ group,
163
+ currentPath,
164
+ }: {
165
+ group: SidebarGroup;
166
+ currentPath: string;
167
+ }) {
168
+ const isActive = group.routes.some((r) => currentPath === r.path);
169
+ const [open, setOpen] = useState(true);
170
+
171
+ return (
172
+ <div className="sidebar-group">
173
+ <button
174
+ className={`sidebar-group-header ${isActive ? "active" : ""}`}
175
+ onClick={() => setOpen(!open)}
176
+ aria-expanded={open}
177
+ aria-controls={`sidebar-group-${group.slug}`}
178
+ >
179
+ <span className="sidebar-group-title">{group.title}</span>
180
+ <span className={`sidebar-group-chevron ${open ? "open" : ""}`}>
181
+ <ChevronRight size={16} />
182
+ </span>
183
+ </button>
184
+ {open && (
185
+ <ul className="sidebar-group-list" id={`sidebar-group-${group.slug}`}>
186
+ {group.routes.map((route) => (
187
+ <li key={route.path}>
188
+ <Link
189
+ to={route.path === "" ? "/" : route.path}
190
+ className={`sidebar-link sidebar-link-nested ${currentPath === route.path ? "active" : ""}`}
191
+ aria-current={currentPath === route.path ? "page" : undefined}
192
+ >
193
+ <div className="sidebar-link-content">
194
+ <span>{route.title}</span>
195
+ {renderBadge(route.badge)}
196
+ </div>
197
+ </Link>
198
+ </li>
199
+ ))}
200
+ </ul>
201
+ )}
202
+ </div>
203
+ );
204
+ }
@@ -1 +1 @@
1
- export { Sidebar } from "./Sidebar";
1
+ export { Sidebar } from "./Sidebar";