boltdocs 1.0.0

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 (137) hide show
  1. package/dist/CodeBlock-37XMKCYY.mjs +7 -0
  2. package/dist/PackageManagerTabs-4NWXLXQO.mjs +314 -0
  3. package/dist/Playground-OE2OE6B6.mjs +7 -0
  4. package/dist/SearchDialog-FTOQZ763.mjs +187 -0
  5. package/dist/SearchDialog-ZAZXYIFX.css +2147 -0
  6. package/dist/Video-I6QY4X7J.mjs +7 -0
  7. package/dist/chunk-2YRDWM6O.mjs +56 -0
  8. package/dist/chunk-PN4GCTYG.mjs +67 -0
  9. package/dist/chunk-X2TDGMTR.mjs +64 -0
  10. package/dist/chunk-X6BYQHVC.mjs +12 -0
  11. package/dist/chunk-Z7JHYNAS.mjs +57 -0
  12. package/dist/chunk-ZFCOLEXN.mjs +1644 -0
  13. package/dist/client/index.css +2147 -0
  14. package/dist/client/index.d.mts +298 -0
  15. package/dist/client/index.d.ts +298 -0
  16. package/dist/client/index.js +2793 -0
  17. package/dist/client/index.mjs +63 -0
  18. package/dist/client/ssr.css +2147 -0
  19. package/dist/client/ssr.d.mts +25 -0
  20. package/dist/client/ssr.d.ts +25 -0
  21. package/dist/client/ssr.js +2727 -0
  22. package/dist/client/ssr.mjs +32 -0
  23. package/dist/config-D2XmHJYe.d.mts +122 -0
  24. package/dist/config-D2XmHJYe.d.ts +122 -0
  25. package/dist/index-CRQKWAeo.d.mts +82 -0
  26. package/dist/index-CRQKWAeo.d.ts +82 -0
  27. package/dist/node/cli/index.d.mts +1 -0
  28. package/dist/node/cli/index.d.ts +1 -0
  29. package/dist/node/cli/index.js +199 -0
  30. package/dist/node/cli/index.mjs +154 -0
  31. package/dist/node/index.d.mts +79 -0
  32. package/dist/node/index.d.ts +79 -0
  33. package/dist/node/index.js +797 -0
  34. package/dist/node/index.mjs +719 -0
  35. package/package.json +79 -0
  36. package/src/client/app/index.tsx +422 -0
  37. package/src/client/app/preload.tsx +56 -0
  38. package/src/client/index.ts +40 -0
  39. package/src/client/ssr.tsx +50 -0
  40. package/src/client/theme/components/CodeBlock/CodeBlock.tsx +76 -0
  41. package/src/client/theme/components/CodeBlock/index.ts +1 -0
  42. package/src/client/theme/components/PackageManagerTabs/PackageManagerTabs.tsx +154 -0
  43. package/src/client/theme/components/PackageManagerTabs/index.ts +1 -0
  44. package/src/client/theme/components/PackageManagerTabs/pkg-tabs.css +64 -0
  45. package/src/client/theme/components/Playground/Playground.tsx +86 -0
  46. package/src/client/theme/components/Playground/index.ts +1 -0
  47. package/src/client/theme/components/Playground/playground.css +168 -0
  48. package/src/client/theme/components/Video/Video.tsx +84 -0
  49. package/src/client/theme/components/Video/index.ts +1 -0
  50. package/src/client/theme/components/Video/video.css +41 -0
  51. package/src/client/theme/components/mdx/Admonition.tsx +80 -0
  52. package/src/client/theme/components/mdx/Badge.tsx +31 -0
  53. package/src/client/theme/components/mdx/Button.tsx +50 -0
  54. package/src/client/theme/components/mdx/Card.tsx +80 -0
  55. package/src/client/theme/components/mdx/List.tsx +57 -0
  56. package/src/client/theme/components/mdx/Tabs.tsx +94 -0
  57. package/src/client/theme/components/mdx/index.ts +18 -0
  58. package/src/client/theme/components/mdx/mdx-components.css +405 -0
  59. package/src/client/theme/icons/bun.tsx +62 -0
  60. package/src/client/theme/icons/deno.tsx +20 -0
  61. package/src/client/theme/icons/discord.tsx +12 -0
  62. package/src/client/theme/icons/github.tsx +15 -0
  63. package/src/client/theme/icons/npm.tsx +13 -0
  64. package/src/client/theme/icons/pnpm.tsx +72 -0
  65. package/src/client/theme/icons/twitter.tsx +12 -0
  66. package/src/client/theme/styles/home.css +60 -0
  67. package/src/client/theme/styles/markdown.css +343 -0
  68. package/src/client/theme/styles/variables.css +162 -0
  69. package/src/client/theme/styles.css +38 -0
  70. package/src/client/theme/ui/BackgroundGradient/BackgroundGradient.tsx +10 -0
  71. package/src/client/theme/ui/BackgroundGradient/index.ts +1 -0
  72. package/src/client/theme/ui/Breadcrumbs/Breadcrumbs.tsx +68 -0
  73. package/src/client/theme/ui/Breadcrumbs/index.ts +1 -0
  74. package/src/client/theme/ui/Footer/footer.css +32 -0
  75. package/src/client/theme/ui/Head/Head.tsx +69 -0
  76. package/src/client/theme/ui/Head/index.ts +1 -0
  77. package/src/client/theme/ui/LanguageSwitcher/LanguageSwitcher.tsx +125 -0
  78. package/src/client/theme/ui/LanguageSwitcher/index.ts +1 -0
  79. package/src/client/theme/ui/LanguageSwitcher/language-switcher.css +98 -0
  80. package/src/client/theme/ui/Layout/Layout.tsx +213 -0
  81. package/src/client/theme/ui/Layout/base.css +76 -0
  82. package/src/client/theme/ui/Layout/index.ts +2 -0
  83. package/src/client/theme/ui/Layout/pagination.css +72 -0
  84. package/src/client/theme/ui/Layout/responsive.css +40 -0
  85. package/src/client/theme/ui/Link/Link.tsx +202 -0
  86. package/src/client/theme/ui/Link/index.ts +2 -0
  87. package/src/client/theme/ui/Loading/Loading.tsx +10 -0
  88. package/src/client/theme/ui/Loading/index.ts +1 -0
  89. package/src/client/theme/ui/Loading/loading.css +30 -0
  90. package/src/client/theme/ui/Navbar/GithubStars.tsx +27 -0
  91. package/src/client/theme/ui/Navbar/Navbar.tsx +145 -0
  92. package/src/client/theme/ui/Navbar/index.ts +2 -0
  93. package/src/client/theme/ui/Navbar/navbar.css +233 -0
  94. package/src/client/theme/ui/NotFound/NotFound.tsx +20 -0
  95. package/src/client/theme/ui/NotFound/index.ts +1 -0
  96. package/src/client/theme/ui/NotFound/not-found.css +64 -0
  97. package/src/client/theme/ui/OnThisPage/OnThisPage.tsx +192 -0
  98. package/src/client/theme/ui/OnThisPage/index.ts +1 -0
  99. package/src/client/theme/ui/OnThisPage/toc.css +132 -0
  100. package/src/client/theme/ui/PoweredBy/PoweredBy.tsx +18 -0
  101. package/src/client/theme/ui/PoweredBy/index.ts +1 -0
  102. package/src/client/theme/ui/PoweredBy/powered-by.css +76 -0
  103. package/src/client/theme/ui/SearchDialog/SearchDialog.tsx +199 -0
  104. package/src/client/theme/ui/SearchDialog/index.ts +1 -0
  105. package/src/client/theme/ui/SearchDialog/search.css +152 -0
  106. package/src/client/theme/ui/Sidebar/Sidebar.tsx +200 -0
  107. package/src/client/theme/ui/Sidebar/index.ts +1 -0
  108. package/src/client/theme/ui/Sidebar/sidebar.css +269 -0
  109. package/src/client/theme/ui/ThemeToggle/ThemeToggle.tsx +69 -0
  110. package/src/client/theme/ui/ThemeToggle/index.ts +1 -0
  111. package/src/client/theme/ui/VersionSwitcher/VersionSwitcher.tsx +136 -0
  112. package/src/client/theme/ui/VersionSwitcher/index.ts +1 -0
  113. package/src/client/utils.ts +26 -0
  114. package/src/node/cache.ts +94 -0
  115. package/src/node/cli/commands/config.ts +15 -0
  116. package/src/node/cli/commands/generate-css.ts +24 -0
  117. package/src/node/cli/constants.ts +70 -0
  118. package/src/node/cli/index.ts +22 -0
  119. package/src/node/config.ts +185 -0
  120. package/src/node/index.ts +21 -0
  121. package/src/node/mdx.ts +41 -0
  122. package/src/node/plugin/entry.ts +58 -0
  123. package/src/node/plugin/html.ts +55 -0
  124. package/src/node/plugin/index.ts +190 -0
  125. package/src/node/plugin/types.ts +11 -0
  126. package/src/node/routes/cache.ts +24 -0
  127. package/src/node/routes/index.ts +152 -0
  128. package/src/node/routes/parser.ts +127 -0
  129. package/src/node/routes/sorter.ts +42 -0
  130. package/src/node/routes/types.ts +49 -0
  131. package/src/node/ssg/index.ts +110 -0
  132. package/src/node/ssg/meta.ts +34 -0
  133. package/src/node/ssg/options.ts +13 -0
  134. package/src/node/ssg/sitemap.ts +54 -0
  135. package/src/node/utils.ts +134 -0
  136. package/tsconfig.json +20 -0
  137. package/tsup.config.ts +22 -0
@@ -0,0 +1,797 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/node/index.ts
31
+ var node_exports = {};
32
+ __export(node_exports, {
33
+ default: () => boltdocs,
34
+ generateStaticPages: () => generateStaticPages
35
+ });
36
+ module.exports = __toCommonJS(node_exports);
37
+
38
+ // src/node/plugin/index.ts
39
+ var import_vite = require("vite");
40
+
41
+ // src/node/routes/index.ts
42
+ var import_fast_glob = __toESM(require("fast-glob"));
43
+
44
+ // src/node/utils.ts
45
+ var import_fs = __toESM(require("fs"));
46
+ var import_gray_matter = __toESM(require("gray-matter"));
47
+ function normalizePath(p) {
48
+ return p.replace(/\\/g, "/");
49
+ }
50
+ function stripNumberPrefix(name) {
51
+ return name.replace(/^\d+\./, "");
52
+ }
53
+ function extractNumberPrefix(name) {
54
+ const match = name.match(/^(\d+)\./);
55
+ return match ? parseInt(match[1], 10) : void 0;
56
+ }
57
+ function isDocFile(filePath) {
58
+ return /\.mdx?$/.test(filePath);
59
+ }
60
+ function getFileMtime(filePath) {
61
+ try {
62
+ return import_fs.default.statSync(filePath).mtimeMs;
63
+ } catch {
64
+ return 0;
65
+ }
66
+ }
67
+ function parseFrontmatter(filePath) {
68
+ const raw = import_fs.default.readFileSync(filePath, "utf-8");
69
+ const { data, content } = (0, import_gray_matter.default)(raw);
70
+ return { data, content };
71
+ }
72
+ function escapeHtml(str) {
73
+ return str.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
74
+ }
75
+ function fileToRoutePath(relativePath) {
76
+ let cleanedPath = relativePath.split("/").map(stripNumberPrefix).join("/");
77
+ let routePath = cleanedPath.replace(/\.mdx?$/, "");
78
+ if (routePath === "index" || routePath.endsWith("/index")) {
79
+ routePath = routePath.replace(/index$/, "");
80
+ }
81
+ if (!routePath.startsWith("/")) {
82
+ routePath = "/" + routePath;
83
+ }
84
+ if (routePath.length > 1 && routePath.endsWith("/")) {
85
+ routePath = routePath.slice(0, -1);
86
+ }
87
+ return routePath;
88
+ }
89
+ function capitalize(str) {
90
+ return str.charAt(0).toUpperCase() + str.slice(1);
91
+ }
92
+
93
+ // src/node/cache.ts
94
+ var FileCache = class {
95
+ entries = /* @__PURE__ */ new Map();
96
+ /**
97
+ * Retrieves parsed data for a file from the cache.
98
+ * Compares the current filesystem mtime with the cached mtime.
99
+ *
100
+ * @param filePath - The absolute path of the file
101
+ * @returns The cached data if valid, or `null` if the file has changed or doesn't exist
102
+ */
103
+ get(filePath) {
104
+ const entry = this.entries.get(filePath);
105
+ if (!entry) return null;
106
+ const currentMtime = getFileMtime(filePath);
107
+ if (currentMtime !== entry.mtime) return null;
108
+ return entry.data;
109
+ }
110
+ /**
111
+ * Stores parsed data for a file in the cache, recording its current mtime.
112
+ *
113
+ * @param filePath - The absolute path to the file
114
+ * @param data - The parsed data to store
115
+ */
116
+ set(filePath, data) {
117
+ this.entries.set(filePath, {
118
+ data,
119
+ mtime: getFileMtime(filePath)
120
+ });
121
+ }
122
+ /**
123
+ * Checks if a specific file's cache is still valid (based on its mtime).
124
+ *
125
+ * @param filePath - The absolute path to the file
126
+ * @returns `true` if the cache is valid, `false` otherwise
127
+ */
128
+ isValid(filePath) {
129
+ return this.get(filePath) !== null;
130
+ }
131
+ /**
132
+ * Manually removes a specific file from the cache.
133
+ * Useful when forcefully invalidating a single updated file.
134
+ *
135
+ * @param filePath - The absolute path to the file
136
+ */
137
+ invalidate(filePath) {
138
+ this.entries.delete(filePath);
139
+ }
140
+ /**
141
+ * Clears the entire cache, forcing all files to be re-parsed on the next request.
142
+ * Useful when global dependencies (like config) change.
143
+ */
144
+ invalidateAll() {
145
+ this.entries.clear();
146
+ }
147
+ /**
148
+ * Removes cached entries for files that no longer exist on the filesystem.
149
+ * Prevents memory leaks from deleted files.
150
+ *
151
+ * @param currentFiles - A Set of absolute file paths currently discovered on the disk
152
+ */
153
+ pruneStale(currentFiles) {
154
+ for (const key of this.entries.keys()) {
155
+ if (!currentFiles.has(key)) {
156
+ this.entries.delete(key);
157
+ }
158
+ }
159
+ }
160
+ /** Number of cached entries */
161
+ get size() {
162
+ return this.entries.size;
163
+ }
164
+ };
165
+
166
+ // src/node/routes/cache.ts
167
+ var docCache = new FileCache();
168
+ function invalidateRouteCache() {
169
+ docCache.invalidateAll();
170
+ }
171
+ function invalidateFile(filePath) {
172
+ docCache.invalidate(filePath);
173
+ }
174
+
175
+ // src/node/routes/parser.ts
176
+ var import_path = __toESM(require("path"));
177
+ var import_github_slugger = __toESM(require("github-slugger"));
178
+ function parseDocFile(file, docsDir, basePath, config) {
179
+ const { data, content } = parseFrontmatter(file);
180
+ const relativePath = normalizePath(import_path.default.relative(docsDir, file));
181
+ let parts = relativePath.split("/");
182
+ let locale;
183
+ let version;
184
+ if (config?.versions && parts.length > 0) {
185
+ const potentialVersion = parts[0];
186
+ if (config.versions.versions[potentialVersion]) {
187
+ version = potentialVersion;
188
+ parts = parts.slice(1);
189
+ }
190
+ }
191
+ if (config?.i18n && parts.length > 0) {
192
+ const potentialLocale = parts[0];
193
+ if (config.i18n.locales[potentialLocale]) {
194
+ locale = potentialLocale;
195
+ parts = parts.slice(1);
196
+ }
197
+ }
198
+ const cleanRelativePath = parts.join("/");
199
+ const cleanRoutePath = fileToRoutePath(cleanRelativePath || "index.md");
200
+ let finalPath = basePath;
201
+ if (version) {
202
+ finalPath += "/" + version;
203
+ }
204
+ if (locale) {
205
+ finalPath += "/" + locale;
206
+ }
207
+ finalPath += cleanRoutePath === "/" ? "" : cleanRoutePath;
208
+ if (!finalPath || finalPath === "") finalPath = "/";
209
+ const rawFileName = parts[parts.length - 1];
210
+ const cleanFileName = stripNumberPrefix(rawFileName);
211
+ const inferredTitle = stripNumberPrefix(
212
+ import_path.default.basename(file, import_path.default.extname(file))
213
+ );
214
+ const sidebarPosition = data.sidebarPosition ?? extractNumberPrefix(rawFileName);
215
+ const rawDirName = parts.length >= 2 ? parts[0] : void 0;
216
+ const cleanDirName = rawDirName ? stripNumberPrefix(rawDirName) : void 0;
217
+ const isGroupIndex = parts.length >= 2 && /^index\.mdx?$/.test(cleanFileName);
218
+ const headings = [];
219
+ const slugger = new import_github_slugger.default();
220
+ const headingsRegex = /^(#{2,4})\s+(.+)$/gm;
221
+ let match;
222
+ while ((match = headingsRegex.exec(content)) !== null) {
223
+ const level = match[1].length;
224
+ const text = match[2].replace(/\[([^\]]+)\]\([^\)]+\)/g, "$1").replace(/[_*`]/g, "").trim();
225
+ const id = slugger.slug(text);
226
+ headings.push({ level, text, id });
227
+ }
228
+ return {
229
+ route: {
230
+ path: finalPath,
231
+ componentPath: file,
232
+ filePath: relativePath,
233
+ title: data.title || inferredTitle,
234
+ description: data.description || "",
235
+ sidebarPosition,
236
+ headings,
237
+ locale,
238
+ version,
239
+ badge: data.badge
240
+ },
241
+ relativeDir: cleanDirName,
242
+ isGroupIndex,
243
+ groupMeta: isGroupIndex ? {
244
+ title: data.groupTitle || data.title || (cleanDirName ? capitalize(cleanDirName) : ""),
245
+ position: data.groupPosition ?? data.sidebarPosition ?? (rawDirName ? extractNumberPrefix(rawDirName) : void 0)
246
+ } : void 0,
247
+ inferredGroupPosition: rawDirName ? extractNumberPrefix(rawDirName) : void 0
248
+ };
249
+ }
250
+
251
+ // src/node/routes/sorter.ts
252
+ function sortRoutes(routes) {
253
+ return routes.sort((a, b) => {
254
+ if (!a.group && !b.group) return compareByPosition(a, b);
255
+ if (!a.group) return -1;
256
+ if (!b.group) return 1;
257
+ if (a.group !== b.group) {
258
+ return compareByGroupPosition(a, b);
259
+ }
260
+ return compareByPosition(a, b);
261
+ });
262
+ }
263
+ function compareByPosition(a, b) {
264
+ if (a.sidebarPosition !== void 0 && b.sidebarPosition !== void 0)
265
+ return a.sidebarPosition - b.sidebarPosition;
266
+ if (a.sidebarPosition !== void 0) return -1;
267
+ if (b.sidebarPosition !== void 0) return 1;
268
+ return a.title.localeCompare(b.title);
269
+ }
270
+ function compareByGroupPosition(a, b) {
271
+ if (a.groupPosition !== void 0 && b.groupPosition !== void 0)
272
+ return a.groupPosition - b.groupPosition;
273
+ if (a.groupPosition !== void 0) return -1;
274
+ if (b.groupPosition !== void 0) return 1;
275
+ return (a.groupTitle || a.group).localeCompare(b.groupTitle || b.group);
276
+ }
277
+
278
+ // src/node/routes/index.ts
279
+ async function generateRoutes(docsDir, config, basePath = "/docs") {
280
+ const files = await (0, import_fast_glob.default)(["**/*.md", "**/*.mdx"], {
281
+ cwd: docsDir,
282
+ absolute: true
283
+ });
284
+ docCache.pruneStale(new Set(files));
285
+ if (config?.i18n) {
286
+ docCache.invalidateAll();
287
+ }
288
+ const parsed = await Promise.all(
289
+ files.map(async (file) => {
290
+ const cached = docCache.get(file);
291
+ if (cached) return cached;
292
+ const result = parseDocFile(file, docsDir, basePath, config);
293
+ docCache.set(file, result);
294
+ return result;
295
+ })
296
+ );
297
+ const groupMeta = /* @__PURE__ */ new Map();
298
+ for (const p of parsed) {
299
+ if (p.relativeDir) {
300
+ if (!groupMeta.has(p.relativeDir)) {
301
+ groupMeta.set(p.relativeDir, {
302
+ title: capitalize(p.relativeDir),
303
+ position: p.inferredGroupPosition
304
+ });
305
+ } else {
306
+ const entry = groupMeta.get(p.relativeDir);
307
+ if (entry.position === void 0 && p.inferredGroupPosition !== void 0) {
308
+ entry.position = p.inferredGroupPosition;
309
+ }
310
+ }
311
+ }
312
+ if (p.isGroupIndex && p.relativeDir && p.groupMeta) {
313
+ const entry = groupMeta.get(p.relativeDir);
314
+ entry.title = p.groupMeta.title;
315
+ if (p.groupMeta.position !== void 0) {
316
+ entry.position = p.groupMeta.position;
317
+ }
318
+ }
319
+ }
320
+ const routes = parsed.map((p) => {
321
+ const dir = p.relativeDir;
322
+ const meta = dir ? groupMeta.get(dir) : void 0;
323
+ return {
324
+ ...p.route,
325
+ group: dir,
326
+ groupTitle: meta?.title || (dir ? capitalize(dir) : void 0),
327
+ groupPosition: meta?.position
328
+ };
329
+ });
330
+ if (config?.i18n) {
331
+ const defaultLocale = config.i18n.defaultLocale;
332
+ const allLocales = Object.keys(config.i18n.locales);
333
+ const fallbackRoutes = [];
334
+ const defaultRoutes = routes.filter(
335
+ (r) => (r.locale || defaultLocale) === defaultLocale
336
+ );
337
+ for (const locale of allLocales) {
338
+ if (locale === defaultLocale) continue;
339
+ const localeRoutePaths = new Set(
340
+ routes.filter((r) => r.locale === locale).map((r) => r.path)
341
+ );
342
+ for (const defRoute of defaultRoutes) {
343
+ let prefix = basePath;
344
+ if (defRoute.version) {
345
+ prefix += "/" + defRoute.version;
346
+ }
347
+ let pathAfterVersion = defRoute.path.substring(prefix.length);
348
+ if (pathAfterVersion.startsWith("/" + defaultLocale + "/")) {
349
+ pathAfterVersion = pathAfterVersion.substring(
350
+ defaultLocale.length + 1
351
+ );
352
+ } else if (pathAfterVersion === "/" + defaultLocale) {
353
+ pathAfterVersion = "/";
354
+ }
355
+ const targetPath = prefix + "/" + locale + (pathAfterVersion === "/" || pathAfterVersion === "" ? "" : pathAfterVersion);
356
+ if (!localeRoutePaths.has(targetPath)) {
357
+ fallbackRoutes.push({
358
+ ...defRoute,
359
+ path: targetPath,
360
+ locale
361
+ });
362
+ }
363
+ }
364
+ }
365
+ return sortRoutes([...routes, ...fallbackRoutes]);
366
+ }
367
+ return sortRoutes(routes);
368
+ }
369
+
370
+ // src/node/plugin/index.ts
371
+ var import_vite_plugin_image_optimizer = require("vite-plugin-image-optimizer");
372
+
373
+ // src/node/config.ts
374
+ var import_path2 = __toESM(require("path"));
375
+ var import_url = require("url");
376
+ var import_fs2 = __toESM(require("fs"));
377
+ var CONFIG_FILES = [
378
+ "boltdocs.config.js",
379
+ "boltdocs.config.mjs",
380
+ "boltdocs.config.ts"
381
+ ];
382
+ async function resolveConfig(docsDir) {
383
+ const projectRoot = process.cwd();
384
+ const defaults = {
385
+ docsDir: import_path2.default.resolve(docsDir),
386
+ themeConfig: {
387
+ title: "Boltdocs",
388
+ description: "A Vite documentation framework",
389
+ navbar: [
390
+ { text: "Home", link: "/" },
391
+ { text: "Documentation", link: "/docs" }
392
+ ]
393
+ }
394
+ };
395
+ for (const filename of CONFIG_FILES) {
396
+ const configPath = import_path2.default.resolve(projectRoot, filename);
397
+ if (import_fs2.default.existsSync(configPath)) {
398
+ try {
399
+ const fileUrl = (0, import_url.pathToFileURL)(configPath).href + "?t=" + Date.now();
400
+ const mod = await import(fileUrl);
401
+ const userConfig = mod.default || mod;
402
+ const userThemeConfig = userConfig.themeConfig || userConfig;
403
+ return {
404
+ docsDir: import_path2.default.resolve(docsDir),
405
+ themeConfig: {
406
+ ...defaults.themeConfig,
407
+ ...userThemeConfig
408
+ },
409
+ i18n: userConfig.i18n,
410
+ versions: userConfig.versions,
411
+ siteUrl: userConfig.siteUrl,
412
+ plugins: userConfig.plugins || []
413
+ };
414
+ } catch (e) {
415
+ console.warn(`[boltdocs] Failed to load config from ${filename}:`, e);
416
+ }
417
+ }
418
+ }
419
+ return defaults;
420
+ }
421
+
422
+ // src/node/ssg/index.ts
423
+ var import_fs3 = __toESM(require("fs"));
424
+ var import_path3 = __toESM(require("path"));
425
+ var import_url2 = require("url");
426
+ var import_module = require("module");
427
+
428
+ // src/node/ssg/meta.ts
429
+ function replaceMetaTags(html, meta) {
430
+ return html.replace(/<title>.*?<\/title>/, `<title>${meta.title}</title>`).replace(
431
+ /(<meta name="description" content=")[^"]*(")/,
432
+ `$1${meta.description}$2`
433
+ ).replace(
434
+ /(<meta property="og:title" content=")[^"]*(")/,
435
+ `$1${meta.title}$2`
436
+ ).replace(
437
+ /(<meta property="og:description" content=")[^"]*(")/,
438
+ `$1${meta.description}$2`
439
+ ).replace(
440
+ /(<meta name="twitter:title" content=")[^"]*(")/,
441
+ `$1${meta.title}$2`
442
+ ).replace(
443
+ /(<meta name="twitter:description" content=")[^"]*(")/,
444
+ `$1${meta.description}$2`
445
+ );
446
+ }
447
+
448
+ // src/node/ssg/sitemap.ts
449
+ function generateSitemap(routePaths, config) {
450
+ const baseUrl = config?.siteUrl?.replace(/\/$/, "") || "https://example.com";
451
+ const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
452
+ const rootEntries = [{ url: "/", priority: "1.0", changefreq: "daily" }];
453
+ if (config?.i18n) {
454
+ const defaultLocale = config.i18n.defaultLocale;
455
+ for (const locale of Object.keys(config.i18n.locales)) {
456
+ if (locale !== defaultLocale) {
457
+ rootEntries.push({
458
+ url: `/${locale}/`,
459
+ priority: "1.0",
460
+ changefreq: "daily"
461
+ });
462
+ }
463
+ }
464
+ }
465
+ const entries = [
466
+ ...rootEntries,
467
+ ...routePaths.map((p) => ({
468
+ url: p,
469
+ priority: "0.8",
470
+ changefreq: "weekly"
471
+ }))
472
+ ];
473
+ return `<?xml version="1.0" encoding="UTF-8"?>
474
+ <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
475
+ ${entries.map(
476
+ (e) => ` <url>
477
+ <loc>${baseUrl}${e.url}</loc>
478
+ <lastmod>${today}</lastmod>
479
+ <changefreq>${e.changefreq}</changefreq>
480
+ <priority>${e.priority}</priority>
481
+ </url>`
482
+ ).join("\n")}
483
+ </urlset>`;
484
+ }
485
+
486
+ // src/node/ssg/index.ts
487
+ var import_meta2 = {};
488
+ var _filename = (0, import_url2.fileURLToPath)(import_meta2.url);
489
+ var _dirname = import_path3.default.dirname(_filename);
490
+ var _require = (0, import_module.createRequire)(import_meta2.url);
491
+ async function generateStaticPages(options) {
492
+ const { docsDir, outDir, config } = options;
493
+ const routes = await generateRoutes(docsDir, config);
494
+ const siteTitle = config?.themeConfig?.title || "Boltdocs";
495
+ const siteDescription = config?.themeConfig?.description || "";
496
+ const ssrModulePath = import_path3.default.resolve(_dirname, "../client/ssr.js");
497
+ if (!import_fs3.default.existsSync(ssrModulePath)) {
498
+ console.error(
499
+ "[boltdocs] SSR module not found at",
500
+ ssrModulePath,
501
+ "- Did you build the core package?"
502
+ );
503
+ return;
504
+ }
505
+ const { render } = _require(ssrModulePath);
506
+ const templatePath = import_path3.default.join(outDir, "index.html");
507
+ if (!import_fs3.default.existsSync(templatePath)) {
508
+ console.warn("[boltdocs] No index.html found in outDir, skipping SSG.");
509
+ return;
510
+ }
511
+ const template = import_fs3.default.readFileSync(templatePath, "utf-8");
512
+ let homePageComp;
513
+ if (config?._homePagePath) {
514
+ try {
515
+ } catch (e) {
516
+ }
517
+ }
518
+ await Promise.all(
519
+ routes.map(async (route) => {
520
+ const pageTitle = `${route.title} | ${siteTitle}`;
521
+ const pageDescription = route.description || siteDescription;
522
+ const fakeModules = {};
523
+ fakeModules[route.componentPath] = { default: () => {
524
+ } };
525
+ try {
526
+ const appHtml = await render({
527
+ path: route.path,
528
+ routes,
529
+ config: config || {},
530
+ modules: fakeModules,
531
+ homePage: homePageComp
532
+ });
533
+ const html = replaceMetaTags(template, {
534
+ title: escapeHtml(pageTitle),
535
+ description: escapeHtml(pageDescription)
536
+ }).replace("<!--app-html-->", appHtml).replace(`<div id="root"></div>`, `<div id="root">${appHtml}</div>`);
537
+ const routeDir = import_path3.default.join(outDir, route.path);
538
+ await import_fs3.default.promises.mkdir(routeDir, { recursive: true });
539
+ await import_fs3.default.promises.writeFile(
540
+ import_path3.default.join(routeDir, "index.html"),
541
+ html,
542
+ "utf-8"
543
+ );
544
+ } catch (e) {
545
+ console.error(`[boltdocs] Error SSR rendering route ${route.path}:`, e);
546
+ }
547
+ })
548
+ );
549
+ const sitemap = generateSitemap(
550
+ routes.map((r) => r.path),
551
+ config
552
+ );
553
+ import_fs3.default.writeFileSync(import_path3.default.join(outDir, "sitemap.xml"), sitemap, "utf-8");
554
+ console.log(
555
+ `[boltdocs] Generated ${routes.length} static pages + sitemap.xml`
556
+ );
557
+ }
558
+
559
+ // src/node/plugin/index.ts
560
+ var import_path4 = __toESM(require("path"));
561
+
562
+ // src/node/plugin/entry.ts
563
+ function generateEntryCode(options, config) {
564
+ const homeImport = options.homePage ? `import HomePage from '${normalizePath(options.homePage)}';` : "";
565
+ const homeOption = options.homePage ? "homePage: HomePage," : "";
566
+ const customCssImport = options.customCss ? `import '${normalizePath(options.customCss)}';` : "";
567
+ const pluginComponents = config?.plugins?.flatMap((p) => Object.entries(p.components || {})) || [];
568
+ const componentImports = pluginComponents.map(
569
+ ([
570
+ name,
571
+ path5
572
+ ]) => `import * as _comp_${name} from '${normalizePath(path5)}';
573
+ const ${name} = _comp_${name}.default || _comp_${name}['${name}'] || _comp_${name};`
574
+ ).join("\n");
575
+ const componentMap = pluginComponents.map(([name]) => name).join(", ");
576
+ return `
577
+ import { createBoltdocsApp as _createApp } from 'boltdocs/client';
578
+ import 'boltdocs/style.css';
579
+ ${customCssImport}
580
+ import _routes from 'virtual:boltdocs-routes';
581
+ import _config from 'virtual:boltdocs-config';
582
+ ${homeImport}
583
+ ${componentImports}
584
+
585
+ _createApp({
586
+ target: '#root',
587
+ routes: _routes,
588
+ config: _config,
589
+ modules: import.meta.glob('/docs/**/*.{md,mdx}'),
590
+ hot: import.meta.hot,
591
+ ${homeOption}
592
+ components: { ${componentMap} },
593
+ });
594
+ `;
595
+ }
596
+
597
+ // src/node/plugin/html.ts
598
+ function injectHtmlMeta(html, config) {
599
+ const title = config.themeConfig?.title || "Boltdocs";
600
+ const description = config.themeConfig?.description || "";
601
+ const seoTags = [
602
+ `<meta name="description" content="${description}">`,
603
+ `<meta property="og:title" content="${title}">`,
604
+ `<meta property="og:description" content="${description}">`,
605
+ `<meta property="og:type" content="website">`,
606
+ `<meta name="twitter:card" content="summary">`,
607
+ `<meta name="twitter:title" content="${title}">`,
608
+ `<meta name="twitter:description" content="${description}">`,
609
+ `<meta name="generator" content="Boltdocs">`
610
+ ].join("\n ");
611
+ const themeScript = `
612
+ <script>
613
+ (function() {
614
+ try {
615
+ var stored = localStorage.getItem("boltdocs-theme");
616
+ var theme = stored || (window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light");
617
+ if (theme === "light") {
618
+ document.documentElement.classList.add("theme-light");
619
+ document.documentElement.dataset.theme = "light";
620
+ } else {
621
+ document.documentElement.classList.remove("theme-light");
622
+ document.documentElement.dataset.theme = "dark";
623
+ }
624
+ } catch (e) {}
625
+ })();
626
+ </script>
627
+ `;
628
+ html = html.replace(/<title>.*?<\/title>/, `<title>${title}</title>`);
629
+ html = html.replace("</head>", ` ${seoTags}
630
+ ${themeScript} </head>`);
631
+ if (!html.includes("src/main")) {
632
+ html = html.replace(
633
+ "</body>",
634
+ ' <script type="module">import "virtual:boltdocs-entry";</script>\n </body>'
635
+ );
636
+ }
637
+ return html;
638
+ }
639
+
640
+ // src/node/plugin/index.ts
641
+ function boltdocsPlugin(options = {}, passedConfig) {
642
+ const docsDir = import_path4.default.resolve(process.cwd(), options.docsDir || "docs");
643
+ const normalizedDocsDir = normalizePath(docsDir);
644
+ let config = passedConfig;
645
+ let viteConfig;
646
+ let isBuild = false;
647
+ const extraVitePlugins = config?.plugins?.flatMap((p) => p.vitePlugins || []) || [];
648
+ return [
649
+ {
650
+ name: "vite-plugin-boltdocs",
651
+ enforce: "pre",
652
+ async config(userConfig, env) {
653
+ isBuild = env.command === "build";
654
+ const envDir = userConfig.envDir || process.cwd();
655
+ const envs = (0, import_vite.loadEnv)(env.mode, envDir, "");
656
+ Object.assign(process.env, envs);
657
+ if (!config) {
658
+ config = await resolveConfig(docsDir);
659
+ }
660
+ if (!options.customCss && config.themeConfig?.customCss) {
661
+ options.customCss = config.themeConfig.customCss;
662
+ }
663
+ return {
664
+ optimizeDeps: { include: ["react", "react-dom"] }
665
+ };
666
+ },
667
+ configResolved(resolved) {
668
+ viteConfig = resolved;
669
+ },
670
+ configureServer(server) {
671
+ const configPaths = CONFIG_FILES.map(
672
+ (c) => import_path4.default.resolve(process.cwd(), c)
673
+ );
674
+ server.watcher.add(configPaths);
675
+ const handleFileEvent = async (file, type) => {
676
+ const normalized = normalizePath(file);
677
+ if (CONFIG_FILES.some((c) => normalized.endsWith(c))) {
678
+ server.restart();
679
+ return;
680
+ }
681
+ if (!normalized.startsWith(normalizedDocsDir) || !isDocFile(normalized))
682
+ return;
683
+ if (type === "add" || type === "unlink") {
684
+ invalidateRouteCache();
685
+ } else {
686
+ invalidateFile(file);
687
+ }
688
+ const newRoutes = await generateRoutes(docsDir, config);
689
+ const routesMod = server.moduleGraph.getModuleById(
690
+ "\0virtual:boltdocs-routes"
691
+ );
692
+ if (routesMod) server.moduleGraph.invalidateModule(routesMod);
693
+ server.ws.send({
694
+ type: "custom",
695
+ event: "boltdocs:routes-update",
696
+ data: newRoutes
697
+ });
698
+ };
699
+ server.watcher.on("add", (f) => handleFileEvent(f, "add"));
700
+ server.watcher.on("unlink", (f) => handleFileEvent(f, "unlink"));
701
+ server.watcher.on("change", (f) => handleFileEvent(f, "change"));
702
+ },
703
+ resolveId(id) {
704
+ if (id === "virtual:boltdocs-routes" || id === "virtual:boltdocs-config" || id === "virtual:boltdocs-entry") {
705
+ return "\0" + id;
706
+ }
707
+ },
708
+ async load(id) {
709
+ if (id === "\0virtual:boltdocs-routes") {
710
+ const routes = await generateRoutes(docsDir, config);
711
+ return `export default ${JSON.stringify(routes, null, 2)};`;
712
+ }
713
+ if (id === "\0virtual:boltdocs-config") {
714
+ const clientConfig = {
715
+ themeConfig: config?.themeConfig,
716
+ i18n: config?.i18n,
717
+ versions: config?.versions,
718
+ siteUrl: config?.siteUrl
719
+ };
720
+ return `export default ${JSON.stringify(clientConfig, null, 2)};`;
721
+ }
722
+ if (id === "\0virtual:boltdocs-entry") {
723
+ const code = generateEntryCode(options, config);
724
+ return code;
725
+ }
726
+ },
727
+ transformIndexHtml: {
728
+ order: "pre",
729
+ handler(html) {
730
+ return injectHtmlMeta(html, config);
731
+ }
732
+ },
733
+ async closeBundle() {
734
+ if (!isBuild) return;
735
+ const outDir = viteConfig?.build?.outDir ? import_path4.default.resolve(viteConfig.root, viteConfig.build.outDir) : import_path4.default.resolve(process.cwd(), "dist");
736
+ await generateStaticPages({ docsDir, outDir, config });
737
+ }
738
+ },
739
+ (0, import_vite_plugin_image_optimizer.ViteImageOptimizer)({
740
+ includePublic: true,
741
+ png: { quality: 80 },
742
+ jpeg: { quality: 80 },
743
+ jpg: { quality: 80 },
744
+ webp: { quality: 80 },
745
+ avif: { quality: 80 },
746
+ svg: {
747
+ multipass: true,
748
+ plugins: [
749
+ {
750
+ name: "preset-default",
751
+ params: { overrides: { removeViewBox: false } }
752
+ }
753
+ ]
754
+ }
755
+ }),
756
+ ...extraVitePlugins.filter((p) => !!p)
757
+ ];
758
+ }
759
+
760
+ // src/node/mdx.ts
761
+ var import_rollup = __toESM(require("@mdx-js/rollup"));
762
+ var import_remark_gfm = __toESM(require("remark-gfm"));
763
+ var import_remark_frontmatter = __toESM(require("remark-frontmatter"));
764
+ var import_rehype_slug = __toESM(require("rehype-slug"));
765
+ var import_rehype_pretty_code = __toESM(require("rehype-pretty-code"));
766
+ function boltdocsMdxPlugin(config) {
767
+ const extraRemarkPlugins = config?.plugins?.flatMap((p) => p.remarkPlugins || []) || [];
768
+ const extraRehypePlugins = config?.plugins?.flatMap((p) => p.rehypePlugins || []) || [];
769
+ return (0, import_rollup.default)({
770
+ remarkPlugins: [import_remark_gfm.default, import_remark_frontmatter.default, ...extraRemarkPlugins],
771
+ rehypePlugins: [
772
+ import_rehype_slug.default,
773
+ ...extraRehypePlugins,
774
+ [
775
+ import_rehype_pretty_code.default,
776
+ {
777
+ theme: "one-dark-pro",
778
+ keepBackground: false
779
+ }
780
+ ]
781
+ ],
782
+ // Provide React as default for JSX
783
+ jsxRuntime: "automatic",
784
+ providerImportSource: "@mdx-js/react"
785
+ });
786
+ }
787
+
788
+ // src/node/index.ts
789
+ async function boltdocs(options) {
790
+ const docsDir = options?.docsDir || "docs";
791
+ const config = await resolveConfig(docsDir);
792
+ return [...boltdocsPlugin(options, config), boltdocsMdxPlugin(config)];
793
+ }
794
+ // Annotate the CommonJS export names for ESM import in node:
795
+ 0 && (module.exports = {
796
+ generateStaticPages
797
+ });