boltdocs 1.3.0 → 1.3.2

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 (103) hide show
  1. package/dist/{cache-EHR7SXRU.mjs → cache-GQHF6BXI.mjs} +1 -1
  2. package/dist/{chunk-GSYECEZY.mjs → chunk-CYBWLFOG.mjs} +5 -1
  3. package/dist/node/index.js +36 -20
  4. package/dist/node/index.mjs +34 -22
  5. package/package.json +1 -1
  6. package/src/client/app/index.tsx +344 -344
  7. package/src/client/app/preload.tsx +56 -56
  8. package/src/client/index.ts +40 -40
  9. package/src/client/ssr.tsx +51 -51
  10. package/src/client/theme/components/CodeBlock/CodeBlock.tsx +76 -76
  11. package/src/client/theme/components/CodeBlock/index.ts +1 -1
  12. package/src/client/theme/components/PackageManagerTabs/PackageManagerTabs.tsx +154 -154
  13. package/src/client/theme/components/PackageManagerTabs/index.ts +1 -1
  14. package/src/client/theme/components/PackageManagerTabs/pkg-tabs.css +64 -64
  15. package/src/client/theme/components/Playground/Playground.tsx +124 -124
  16. package/src/client/theme/components/Playground/index.ts +1 -1
  17. package/src/client/theme/components/Playground/playground.css +168 -168
  18. package/src/client/theme/components/Video/Video.tsx +84 -84
  19. package/src/client/theme/components/Video/index.ts +1 -1
  20. package/src/client/theme/components/Video/video.css +41 -41
  21. package/src/client/theme/components/mdx/Admonition.tsx +80 -80
  22. package/src/client/theme/components/mdx/Badge.tsx +31 -31
  23. package/src/client/theme/components/mdx/Button.tsx +50 -50
  24. package/src/client/theme/components/mdx/Card.tsx +80 -80
  25. package/src/client/theme/components/mdx/List.tsx +57 -57
  26. package/src/client/theme/components/mdx/Tabs.tsx +94 -94
  27. package/src/client/theme/components/mdx/index.ts +18 -18
  28. package/src/client/theme/components/mdx/mdx-components.css +424 -424
  29. package/src/client/theme/icons/bun.tsx +62 -62
  30. package/src/client/theme/icons/deno.tsx +20 -20
  31. package/src/client/theme/icons/discord.tsx +12 -12
  32. package/src/client/theme/icons/github.tsx +15 -15
  33. package/src/client/theme/icons/npm.tsx +13 -13
  34. package/src/client/theme/icons/pnpm.tsx +72 -72
  35. package/src/client/theme/icons/twitter.tsx +12 -12
  36. package/src/client/theme/styles/markdown.css +343 -343
  37. package/src/client/theme/styles/variables.css +162 -162
  38. package/src/client/theme/styles.css +37 -37
  39. package/src/client/theme/ui/BackgroundGradient/BackgroundGradient.tsx +10 -10
  40. package/src/client/theme/ui/BackgroundGradient/index.ts +1 -1
  41. package/src/client/theme/ui/Breadcrumbs/Breadcrumbs.tsx +68 -68
  42. package/src/client/theme/ui/Breadcrumbs/index.ts +1 -1
  43. package/src/client/theme/ui/Footer/footer.css +32 -32
  44. package/src/client/theme/ui/Head/Head.tsx +69 -69
  45. package/src/client/theme/ui/Head/index.ts +1 -1
  46. package/src/client/theme/ui/LanguageSwitcher/LanguageSwitcher.tsx +125 -125
  47. package/src/client/theme/ui/LanguageSwitcher/index.ts +1 -1
  48. package/src/client/theme/ui/LanguageSwitcher/language-switcher.css +98 -98
  49. package/src/client/theme/ui/Layout/Layout.tsx +202 -202
  50. package/src/client/theme/ui/Layout/base.css +76 -76
  51. package/src/client/theme/ui/Layout/index.ts +2 -2
  52. package/src/client/theme/ui/Layout/pagination.css +72 -72
  53. package/src/client/theme/ui/Layout/responsive.css +36 -36
  54. package/src/client/theme/ui/Link/Link.tsx +254 -254
  55. package/src/client/theme/ui/Link/index.ts +2 -2
  56. package/src/client/theme/ui/Loading/Loading.tsx +10 -10
  57. package/src/client/theme/ui/Loading/index.ts +1 -1
  58. package/src/client/theme/ui/Loading/loading.css +30 -30
  59. package/src/client/theme/ui/Navbar/GithubStars.tsx +27 -27
  60. package/src/client/theme/ui/Navbar/Navbar.tsx +145 -145
  61. package/src/client/theme/ui/Navbar/index.ts +2 -2
  62. package/src/client/theme/ui/Navbar/navbar.css +233 -233
  63. package/src/client/theme/ui/NotFound/NotFound.tsx +19 -19
  64. package/src/client/theme/ui/NotFound/index.ts +1 -1
  65. package/src/client/theme/ui/NotFound/not-found.css +64 -64
  66. package/src/client/theme/ui/OnThisPage/OnThisPage.tsx +235 -235
  67. package/src/client/theme/ui/OnThisPage/index.ts +1 -1
  68. package/src/client/theme/ui/OnThisPage/toc.css +132 -132
  69. package/src/client/theme/ui/PoweredBy/PoweredBy.tsx +18 -18
  70. package/src/client/theme/ui/PoweredBy/index.ts +1 -1
  71. package/src/client/theme/ui/PoweredBy/powered-by.css +76 -76
  72. package/src/client/theme/ui/SearchDialog/SearchDialog.tsx +199 -199
  73. package/src/client/theme/ui/SearchDialog/index.ts +1 -1
  74. package/src/client/theme/ui/SearchDialog/search.css +152 -152
  75. package/src/client/theme/ui/Sidebar/Sidebar.tsx +204 -204
  76. package/src/client/theme/ui/Sidebar/index.ts +1 -1
  77. package/src/client/theme/ui/Sidebar/sidebar.css +236 -236
  78. package/src/client/theme/ui/ThemeToggle/ThemeToggle.tsx +69 -69
  79. package/src/client/theme/ui/ThemeToggle/index.ts +1 -1
  80. package/src/client/theme/ui/VersionSwitcher/VersionSwitcher.tsx +136 -136
  81. package/src/client/theme/ui/VersionSwitcher/index.ts +1 -1
  82. package/src/client/types.ts +50 -50
  83. package/src/client/utils.ts +26 -26
  84. package/src/node/cache.ts +408 -408
  85. package/src/node/config.ts +192 -192
  86. package/src/node/index.ts +21 -21
  87. package/src/node/mdx.ts +120 -120
  88. package/src/node/plugin/entry.ts +58 -58
  89. package/src/node/plugin/html.ts +55 -55
  90. package/src/node/plugin/index.ts +193 -193
  91. package/src/node/plugin/types.ts +11 -11
  92. package/src/node/routes/cache.ts +28 -28
  93. package/src/node/routes/index.ts +167 -167
  94. package/src/node/routes/parser.ts +153 -127
  95. package/src/node/routes/sorter.ts +42 -42
  96. package/src/node/routes/types.ts +49 -49
  97. package/src/node/ssg/index.ts +114 -114
  98. package/src/node/ssg/meta.ts +33 -34
  99. package/src/node/ssg/options.ts +13 -13
  100. package/src/node/ssg/sitemap.ts +55 -54
  101. package/src/node/utils.ts +145 -134
  102. package/tsconfig.json +20 -20
  103. 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";