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,199 +1,199 @@
1
- import React, { useState, useEffect, useRef } from "react";
2
- import { createPortal } from "react-dom";
3
- import { Link } from "../Link";
4
- import { Search } from "lucide-react";
5
- import { ComponentRoute } from "../../../types";
6
-
7
- interface SearchResult {
8
- title: string;
9
- path: string;
10
- groupTitle?: string;
11
- isHeading?: boolean;
12
- }
13
-
14
- export function SearchDialog({ routes }: { routes: ComponentRoute[] }) {
15
- const [isOpen, setIsOpen] = useState(false);
16
- const [query, setQuery] = useState("");
17
- const inputRef = useRef<HTMLInputElement>(null);
18
-
19
- useEffect(() => {
20
- const handleKeyDown = (e: KeyboardEvent) => {
21
- if ((e.metaKey || e.ctrlKey) && e.key === "k") {
22
- e.preventDefault();
23
- setIsOpen((prev) => !prev);
24
- }
25
- if (e.key === "Escape" && isOpen) {
26
- setIsOpen(false);
27
- }
28
- };
29
- window.addEventListener("keydown", handleKeyDown);
30
- return () => window.removeEventListener("keydown", handleKeyDown);
31
- }, [isOpen]);
32
-
33
- useEffect(() => {
34
- if (isOpen) {
35
- setTimeout(() => inputRef.current?.focus(), 50);
36
- } else {
37
- setQuery("");
38
- }
39
- }, [isOpen]);
40
-
41
- const searchResults: SearchResult[] = React.useMemo(() => {
42
- if (!query) {
43
- return routes.slice(0, 10).map((r) => ({
44
- title: r.title,
45
- path: r.path,
46
- groupTitle: r.groupTitle,
47
- }));
48
- }
49
-
50
- const results: SearchResult[] = [];
51
- const lowerQuery = query.toLowerCase();
52
-
53
- for (const route of routes) {
54
- if (route.title && route.title.toLowerCase().includes(lowerQuery)) {
55
- results.push({
56
- title: route.title,
57
- path: route.path,
58
- groupTitle: route.groupTitle,
59
- });
60
- }
61
-
62
- if (route.headings) {
63
- for (const heading of route.headings) {
64
- if (heading.text.toLowerCase().includes(lowerQuery)) {
65
- results.push({
66
- title: heading.text,
67
- path: `${route.path}#${heading.id}`,
68
- groupTitle: route.title,
69
- isHeading: true,
70
- });
71
- }
72
- }
73
- }
74
- }
75
-
76
- // Deduplicate results by path
77
- const uniqueResults = [];
78
- const seenPaths = new Set();
79
- for (const res of results) {
80
- if (!seenPaths.has(res.path)) {
81
- seenPaths.add(res.path);
82
- uniqueResults.push(res);
83
- }
84
- }
85
-
86
- return uniqueResults.slice(0, 10);
87
- }, [routes, query]);
88
-
89
- return (
90
- <>
91
- <div
92
- className="navbar-search"
93
- role="button"
94
- tabIndex={0}
95
- onClick={() => setIsOpen(true)}
96
- onKeyDown={(e) => {
97
- if (e.key === "Enter" || e.key === " ") {
98
- e.preventDefault();
99
- setIsOpen(true);
100
- }
101
- }}
102
- aria-label="Open search dialog"
103
- >
104
- <Search className="boltdocs-search-icon" size={18} />
105
- Search docs...
106
- <kbd>⌘K</kbd>
107
- </div>
108
-
109
- {isOpen &&
110
- createPortal(
111
- <div
112
- className="boltdocs-search-overlay"
113
- onPointerDown={() => setIsOpen(false)}
114
- >
115
- <div
116
- className="boltdocs-search-modal"
117
- role="dialog"
118
- aria-modal="true"
119
- aria-label="Search"
120
- onPointerDown={(e) => e.stopPropagation()}
121
- >
122
- <div className="boltdocs-search-header">
123
- <Search size={18} />
124
- <input
125
- ref={inputRef}
126
- type="text"
127
- aria-label="Search documentation input"
128
- placeholder="Search documentation..."
129
- value={query}
130
- onChange={(e) => setQuery(e.target.value)}
131
- />
132
- <button
133
- className="boltdocs-search-close"
134
- onClick={() => setIsOpen(false)}
135
- aria-label="Close search"
136
- >
137
- ESC
138
- </button>
139
- </div>
140
-
141
- <div className="boltdocs-search-results">
142
- {searchResults.length > 0 ? (
143
- searchResults.map((result) => (
144
- <Link
145
- key={result.path}
146
- to={result.path === "" ? "/" : result.path}
147
- className={`boltdocs-search-result-item ${result.isHeading ? "is-heading" : ""}`}
148
- onClick={(e) => {
149
- const isSamePath =
150
- result.path.split("#")[0] ===
151
- window.location.pathname;
152
- if (isSamePath && result.isHeading) {
153
- e.preventDefault();
154
- const id = result.path.split("#")[1];
155
- const el = document.getElementById(id);
156
- if (el) {
157
- const offset = 80;
158
- const bodyRect =
159
- document.body.getBoundingClientRect().top;
160
- const elementRect = el.getBoundingClientRect().top;
161
- const elementPosition = elementRect - bodyRect;
162
- const offsetPosition = elementPosition - offset;
163
-
164
- window.scrollTo({
165
- top: offsetPosition,
166
- behavior: "smooth",
167
- });
168
- window.history.pushState(null, "", `#${id}`);
169
- }
170
- }
171
- setIsOpen(false);
172
- }}
173
- >
174
- <span className="boltdocs-search-result-title">
175
- {result.isHeading ? (
176
- <span className="heading-indicator">#</span>
177
- ) : null}
178
- {result.title}
179
- </span>
180
- {result.groupTitle && (
181
- <span className="boltdocs-search-result-group">
182
- {result.groupTitle}
183
- </span>
184
- )}
185
- </Link>
186
- ))
187
- ) : (
188
- <div className="boltdocs-search-empty">
189
- No results found for "{query}"
190
- </div>
191
- )}
192
- </div>
193
- </div>
194
- </div>,
195
- document.body,
196
- )}
197
- </>
198
- );
199
- }
1
+ import React, { useState, useEffect, useRef } from "react";
2
+ import { createPortal } from "react-dom";
3
+ import { Link } from "../Link";
4
+ import { Search } from "lucide-react";
5
+ import { ComponentRoute } from "../../../types";
6
+
7
+ interface SearchResult {
8
+ title: string;
9
+ path: string;
10
+ groupTitle?: string;
11
+ isHeading?: boolean;
12
+ }
13
+
14
+ export function SearchDialog({ routes }: { routes: ComponentRoute[] }) {
15
+ const [isOpen, setIsOpen] = useState(false);
16
+ const [query, setQuery] = useState("");
17
+ const inputRef = useRef<HTMLInputElement>(null);
18
+
19
+ useEffect(() => {
20
+ const handleKeyDown = (e: KeyboardEvent) => {
21
+ if ((e.metaKey || e.ctrlKey) && e.key === "k") {
22
+ e.preventDefault();
23
+ setIsOpen((prev) => !prev);
24
+ }
25
+ if (e.key === "Escape" && isOpen) {
26
+ setIsOpen(false);
27
+ }
28
+ };
29
+ window.addEventListener("keydown", handleKeyDown);
30
+ return () => window.removeEventListener("keydown", handleKeyDown);
31
+ }, [isOpen]);
32
+
33
+ useEffect(() => {
34
+ if (isOpen) {
35
+ setTimeout(() => inputRef.current?.focus(), 50);
36
+ } else {
37
+ setQuery("");
38
+ }
39
+ }, [isOpen]);
40
+
41
+ const searchResults: SearchResult[] = React.useMemo(() => {
42
+ if (!query) {
43
+ return routes.slice(0, 10).map((r) => ({
44
+ title: r.title,
45
+ path: r.path,
46
+ groupTitle: r.groupTitle,
47
+ }));
48
+ }
49
+
50
+ const results: SearchResult[] = [];
51
+ const lowerQuery = query.toLowerCase();
52
+
53
+ for (const route of routes) {
54
+ if (route.title && route.title.toLowerCase().includes(lowerQuery)) {
55
+ results.push({
56
+ title: route.title,
57
+ path: route.path,
58
+ groupTitle: route.groupTitle,
59
+ });
60
+ }
61
+
62
+ if (route.headings) {
63
+ for (const heading of route.headings) {
64
+ if (heading.text.toLowerCase().includes(lowerQuery)) {
65
+ results.push({
66
+ title: heading.text,
67
+ path: `${route.path}#${heading.id}`,
68
+ groupTitle: route.title,
69
+ isHeading: true,
70
+ });
71
+ }
72
+ }
73
+ }
74
+ }
75
+
76
+ // Deduplicate results by path
77
+ const uniqueResults = [];
78
+ const seenPaths = new Set();
79
+ for (const res of results) {
80
+ if (!seenPaths.has(res.path)) {
81
+ seenPaths.add(res.path);
82
+ uniqueResults.push(res);
83
+ }
84
+ }
85
+
86
+ return uniqueResults.slice(0, 10);
87
+ }, [routes, query]);
88
+
89
+ return (
90
+ <>
91
+ <div
92
+ className="navbar-search"
93
+ role="button"
94
+ tabIndex={0}
95
+ onClick={() => setIsOpen(true)}
96
+ onKeyDown={(e) => {
97
+ if (e.key === "Enter" || e.key === " ") {
98
+ e.preventDefault();
99
+ setIsOpen(true);
100
+ }
101
+ }}
102
+ aria-label="Open search dialog"
103
+ >
104
+ <Search className="boltdocs-search-icon" size={18} />
105
+ Search docs...
106
+ <kbd>⌘K</kbd>
107
+ </div>
108
+
109
+ {isOpen &&
110
+ createPortal(
111
+ <div
112
+ className="boltdocs-search-overlay"
113
+ onPointerDown={() => setIsOpen(false)}
114
+ >
115
+ <div
116
+ className="boltdocs-search-modal"
117
+ role="dialog"
118
+ aria-modal="true"
119
+ aria-label="Search"
120
+ onPointerDown={(e) => e.stopPropagation()}
121
+ >
122
+ <div className="boltdocs-search-header">
123
+ <Search size={18} />
124
+ <input
125
+ ref={inputRef}
126
+ type="text"
127
+ aria-label="Search documentation input"
128
+ placeholder="Search documentation..."
129
+ value={query}
130
+ onChange={(e) => setQuery(e.target.value)}
131
+ />
132
+ <button
133
+ className="boltdocs-search-close"
134
+ onClick={() => setIsOpen(false)}
135
+ aria-label="Close search"
136
+ >
137
+ ESC
138
+ </button>
139
+ </div>
140
+
141
+ <div className="boltdocs-search-results">
142
+ {searchResults.length > 0 ? (
143
+ searchResults.map((result) => (
144
+ <Link
145
+ key={result.path}
146
+ to={result.path === "" ? "/" : result.path}
147
+ className={`boltdocs-search-result-item ${result.isHeading ? "is-heading" : ""}`}
148
+ onClick={(e) => {
149
+ const isSamePath =
150
+ result.path.split("#")[0] ===
151
+ window.location.pathname;
152
+ if (isSamePath && result.isHeading) {
153
+ e.preventDefault();
154
+ const id = result.path.split("#")[1];
155
+ const el = document.getElementById(id);
156
+ if (el) {
157
+ const offset = 80;
158
+ const bodyRect =
159
+ document.body.getBoundingClientRect().top;
160
+ const elementRect = el.getBoundingClientRect().top;
161
+ const elementPosition = elementRect - bodyRect;
162
+ const offsetPosition = elementPosition - offset;
163
+
164
+ window.scrollTo({
165
+ top: offsetPosition,
166
+ behavior: "smooth",
167
+ });
168
+ window.history.pushState(null, "", `#${id}`);
169
+ }
170
+ }
171
+ setIsOpen(false);
172
+ }}
173
+ >
174
+ <span className="boltdocs-search-result-title">
175
+ {result.isHeading ? (
176
+ <span className="heading-indicator">#</span>
177
+ ) : null}
178
+ {result.title}
179
+ </span>
180
+ {result.groupTitle && (
181
+ <span className="boltdocs-search-result-group">
182
+ {result.groupTitle}
183
+ </span>
184
+ )}
185
+ </Link>
186
+ ))
187
+ ) : (
188
+ <div className="boltdocs-search-empty">
189
+ No results found for "{query}"
190
+ </div>
191
+ )}
192
+ </div>
193
+ </div>
194
+ </div>,
195
+ document.body,
196
+ )}
197
+ </>
198
+ );
199
+ }
@@ -1 +1 @@
1
- export { SearchDialog } from "./SearchDialog";
1
+ export { SearchDialog } from "./SearchDialog";