boltdocs 1.0.1 → 1.3.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 (64) hide show
  1. package/dist/{CodeBlock-37XMKCYY.mjs → CodeBlock-V3Z5EKGR.mjs} +0 -1
  2. package/dist/{PackageManagerTabs-4NWXLXQO.mjs → PackageManagerTabs-XEKI3L7P.mjs} +0 -2
  3. package/dist/{SearchDialog-FTOQZ763.mjs → SearchDialog-5EDRACEG.mjs} +1 -2
  4. package/dist/{SearchDialog-ZAZXYIFX.css → SearchDialog-X57WPTNN.css} +57 -129
  5. package/dist/{Video-I6QY4X7J.mjs → Video-KNTY5BNO.mjs} +0 -1
  6. package/dist/cache-EHR7SXRU.mjs +12 -0
  7. package/dist/chunk-GSYECEZY.mjs +381 -0
  8. package/dist/{chunk-ZFCOLEXN.mjs → chunk-NS7WHDYA.mjs} +234 -426
  9. package/dist/client/index.css +57 -129
  10. package/dist/client/index.d.mts +39 -8
  11. package/dist/client/index.d.ts +39 -8
  12. package/dist/client/index.js +557 -564
  13. package/dist/client/index.mjs +305 -18
  14. package/dist/client/ssr.css +57 -129
  15. package/dist/client/ssr.d.mts +1 -1
  16. package/dist/client/ssr.d.ts +1 -1
  17. package/dist/client/ssr.js +257 -558
  18. package/dist/client/ssr.mjs +1 -2
  19. package/dist/{config-D2XmHJYe.d.mts → config-BD5ZHz15.d.mts} +7 -0
  20. package/dist/{config-D2XmHJYe.d.ts → config-BD5ZHz15.d.ts} +7 -0
  21. package/dist/node/index.d.mts +2 -2
  22. package/dist/node/index.d.ts +2 -2
  23. package/dist/node/index.js +457 -118
  24. package/dist/node/index.mjs +144 -147
  25. package/dist/{index-CRQKWAeo.d.mts → types-CvrzTbEX.d.mts} +1 -28
  26. package/dist/{index-CRQKWAeo.d.ts → types-CvrzTbEX.d.ts} +1 -28
  27. package/package.json +2 -2
  28. package/src/client/app/index.tsx +32 -110
  29. package/src/client/app/preload.tsx +1 -1
  30. package/src/client/index.ts +1 -1
  31. package/src/client/ssr.tsx +2 -1
  32. package/src/client/theme/components/Playground/Playground.tsx +40 -2
  33. package/src/client/theme/components/mdx/mdx-components.css +39 -20
  34. package/src/client/theme/styles/markdown.css +4 -4
  35. package/src/client/theme/styles.css +0 -1
  36. package/src/client/theme/ui/Breadcrumbs/Breadcrumbs.tsx +1 -1
  37. package/src/client/theme/ui/LanguageSwitcher/LanguageSwitcher.tsx +1 -1
  38. package/src/client/theme/ui/Layout/Layout.tsx +3 -14
  39. package/src/client/theme/ui/Layout/responsive.css +0 -4
  40. package/src/client/theme/ui/Link/Link.tsx +52 -0
  41. package/src/client/theme/ui/Navbar/Navbar.tsx +1 -1
  42. package/src/client/theme/ui/NotFound/NotFound.tsx +0 -1
  43. package/src/client/theme/ui/OnThisPage/OnThisPage.tsx +45 -2
  44. package/src/client/theme/ui/SearchDialog/SearchDialog.tsx +1 -1
  45. package/src/client/theme/ui/Sidebar/Sidebar.tsx +44 -40
  46. package/src/client/theme/ui/Sidebar/sidebar.css +25 -58
  47. package/src/client/theme/ui/VersionSwitcher/VersionSwitcher.tsx +1 -1
  48. package/src/client/types.ts +50 -0
  49. package/src/node/cache.ts +360 -46
  50. package/src/node/config.ts +7 -0
  51. package/src/node/mdx.ts +83 -4
  52. package/src/node/plugin/index.ts +3 -0
  53. package/src/node/routes/cache.ts +5 -1
  54. package/src/node/routes/index.ts +17 -2
  55. package/src/node/ssg/index.ts +4 -0
  56. package/dist/Playground-OE2OE6B6.mjs +0 -7
  57. package/dist/chunk-PN4GCTYG.mjs +0 -67
  58. package/dist/chunk-X2TDGMTR.mjs +0 -64
  59. package/dist/chunk-X6BYQHVC.mjs +0 -12
  60. package/dist/node/cli/index.d.mts +0 -1
  61. package/dist/node/cli/index.d.ts +0 -1
  62. package/dist/node/cli/index.js +0 -199
  63. package/dist/node/cli/index.mjs +0 -154
  64. package/src/client/theme/styles/home.css +0 -60
@@ -1,7 +1,6 @@
1
1
  import {
2
2
  CodeBlock
3
3
  } from "./chunk-2YRDWM6O.mjs";
4
- import "./chunk-X6BYQHVC.mjs";
5
4
  export {
6
5
  CodeBlock
7
6
  };
@@ -1,5 +1,3 @@
1
- import "./chunk-X6BYQHVC.mjs";
2
-
3
1
  // src/client/theme/components/PackageManagerTabs/PackageManagerTabs.tsx
4
2
  import { useState, useCallback } from "react";
5
3
  import { Copy, Check } from "lucide-react";
@@ -1,7 +1,6 @@
1
1
  import {
2
2
  Link
3
- } from "./chunk-ZFCOLEXN.mjs";
4
- import "./chunk-X6BYQHVC.mjs";
3
+ } from "./chunk-NS7WHDYA.mjs";
5
4
 
6
5
  // src/client/theme/ui/SearchDialog/SearchDialog.tsx
7
6
  import React, { useState, useEffect, useRef } from "react";
@@ -422,73 +422,43 @@ a {
422
422
  flex: 1;
423
423
  }
424
424
  .boltdocs-main-container.sidebar-collapsed .boltdocs-sidebar {
425
- width: 0;
426
- padding-left: 0;
427
- padding-right: 0;
428
- border-right-color: transparent;
429
- opacity: 0;
430
- pointer-events: none;
425
+ width: 54px;
426
+ padding: 1rem 0;
427
+ border-right: 1px solid var(--ld-border-subtle);
428
+ opacity: 1;
429
+ pointer-events: auto;
431
430
  overflow: hidden;
432
431
  }
433
- .sidebar-toggle-floating {
434
- position: fixed;
435
- bottom: 2rem;
436
- left: 2rem;
437
- width: 2.75rem;
438
- height: 2.75rem;
439
- border-radius: 50%;
440
- background-color: var(--ld-surface);
441
- border: 1px solid var(--ld-border-strong);
442
- color: var(--ld-text-muted);
432
+ .sidebar-collapse {
433
+ width: 100%;
443
434
  display: flex;
444
435
  align-items: center;
445
- justify-content: center;
446
- cursor: pointer;
447
- z-index: 100;
448
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
449
- transition: all 0.3s cubic-bezier(0.16, 1, 0.3, 1);
450
- opacity: 0;
451
- pointer-events: none;
452
- transform: translateY(20px) scale(0.9);
453
- }
454
- .sidebar-toggle-floating:hover {
455
- background-color: var(--ld-bg-soft);
456
- color: var(--ld-text-main);
457
- transform: translateY(0px) scale(1.05);
458
- border-color: var(--ld-color-primary);
436
+ justify-content: flex-end;
437
+ padding: 0 0.75rem 1rem;
438
+ transition: justify-content 0.3s ease;
459
439
  }
460
- .sidebar-toggle-floating:active {
461
- transform: translateY(0px) scale(0.95);
462
- }
463
- .boltdocs-main-container.sidebar-collapsed .sidebar-toggle-floating {
464
- opacity: 1;
465
- pointer-events: auto;
466
- transform: translateY(0) scale(1);
467
- }
468
- .sidebar-footer {
469
- margin-top: 2rem;
470
- padding-top: 1rem;
471
- border-top: 1px solid var(--ld-border-subtle);
440
+ .boltdocs-main-container.sidebar-collapsed .sidebar-collapse {
441
+ justify-content: center;
442
+ padding: 0 0 1rem;
472
443
  }
473
444
  .sidebar-collapse-btn {
445
+ color: var(--ld-text-muted);
446
+ border: none;
447
+ box-shadow: none;
448
+ background-color: transparent;
449
+ cursor: pointer;
474
450
  display: flex;
475
451
  align-items: center;
476
- gap: 0.5rem;
477
- width: 100%;
478
- padding: 0.5rem 0.75rem;
479
- background: none;
480
- border: none;
452
+ justify-content: center;
453
+ width: 32px;
454
+ height: 32px;
481
455
  border-radius: var(--ld-radius-md);
482
- color: var(--ld-text-muted);
483
- font-family: var(--ld-font-sans);
484
- font-size: 0.8125rem;
485
- font-weight: 500;
486
- cursor: pointer;
487
- transition: all 0.2s ease;
456
+ transition: all 0.2s cubic-bezier(0.16, 1, 0.3, 1);
488
457
  }
489
458
  .sidebar-collapse-btn:hover {
490
- background-color: var(--ld-bg-soft);
491
- color: var(--ld-color-primary);
459
+ background-color: var(--ld-bg-mute);
460
+ color: var(--ld-text-main);
461
+ transform: scale(1.05);
492
462
  }
493
463
  .boltdocs-sidebar::-webkit-scrollbar {
494
464
  width: 4px;
@@ -1142,11 +1112,11 @@ a {
1142
1112
  background-color: transparent !important;
1143
1113
  }
1144
1114
  .code-block-wrapper pre > code {
1145
- padding: 1.25rem !important;
1146
- display: block !important;
1115
+ display: grid !important;
1116
+ padding: 1.25rem 1rem !important;
1147
1117
  }
1148
1118
  .code-block-wrapper pre > code .line {
1149
- padding: 0;
1119
+ padding: 0 1.25rem;
1150
1120
  }
1151
1121
  .boltdocs-page pre {
1152
1122
  margin: 1.5rem 0;
@@ -1161,7 +1131,7 @@ a {
1161
1131
  }
1162
1132
  .boltdocs-page pre > code {
1163
1133
  display: grid;
1164
- padding: 1rem 0;
1134
+ padding: 1rem 1rem;
1165
1135
  background-color: transparent;
1166
1136
  border: none;
1167
1137
  color: inherit;
@@ -1245,57 +1215,68 @@ a {
1245
1215
 
1246
1216
  /* src/client/theme/components/mdx/mdx-components.css */
1247
1217
  .ld-btn {
1218
+ all: unset;
1219
+ box-sizing: border-box !important;
1248
1220
  display: inline-flex;
1249
1221
  align-items: center;
1250
- gap: 0.4rem;
1222
+ justify-content: center;
1223
+ gap: 0.5rem;
1224
+ font-family: var(--ld-font-sans);
1251
1225
  font-weight: 600;
1226
+ font-size: 0.9375rem;
1227
+ line-height: normal;
1228
+ letter-spacing: -0.01em;
1229
+ text-align: center;
1230
+ text-decoration: none !important;
1231
+ white-space: nowrap;
1252
1232
  border-radius: var(--ld-radius-md);
1253
1233
  cursor: pointer;
1254
- transition: all 300ms cubic-bezier(0.16, 1, 0.3, 1);
1255
- font-family: var(--ld-font-sans);
1234
+ transition: all 250ms cubic-bezier(0.4, 0, 0.2, 1);
1256
1235
  border: 1px solid transparent;
1257
- line-height: 1;
1258
- letter-spacing: -0.01em;
1236
+ user-select: none;
1237
+ position: relative;
1259
1238
  }
1260
1239
  .ld-btn:hover {
1261
- transform: scale(1.05);
1240
+ transform: translateY(-1px);
1262
1241
  }
1263
1242
  .ld-btn:active {
1264
- transform: scale(0.95);
1243
+ transform: translateY(0) scale(0.98);
1265
1244
  }
1266
1245
  .ld-btn--sm {
1267
- padding: 0.45rem 1.1rem;
1246
+ min-height: 2rem;
1247
+ padding: 0 1rem;
1268
1248
  font-size: 0.8125rem;
1269
1249
  border-radius: var(--ld-radius-md);
1270
1250
  }
1271
1251
  .ld-btn--md {
1272
- padding: 0.7rem 1.6rem;
1252
+ min-height: 2.625rem;
1253
+ padding: 0 1.6rem;
1273
1254
  font-size: 0.9375rem;
1274
1255
  }
1275
1256
  .ld-btn--lg {
1276
- padding: 0.85rem 2.1rem;
1257
+ min-height: 3.25rem;
1258
+ padding: 0 2.2rem;
1277
1259
  font-size: 1.05rem;
1278
1260
  }
1279
1261
  .ld-btn--primary {
1280
- background-color: var(--ld-ui-btn-primary-bg, var(--ld-btn-primary-bg));
1262
+ background-color: var( --ld-ui-btn-primary-bg, var(--ld-btn-primary-bg) ) !important;
1281
1263
  color: var(--ld-ui-btn-primary-text, var(--ld-btn-primary-text)) !important;
1264
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
1282
1265
  }
1283
1266
  .ld-btn--primary:hover {
1284
- opacity: 0.92;
1285
- color: var(--ld-ui-btn-primary-text, var(--ld-btn-primary-text)) !important;
1267
+ filter: brightness(1.1);
1286
1268
  }
1287
1269
  .ld-btn--secondary {
1288
- background-color: var(--ld-ui-btn-secondary-bg, var(--ld-btn-secondary-bg));
1270
+ background-color: var( --ld-ui-btn-secondary-bg, var(--ld-btn-secondary-bg) ) !important;
1289
1271
  color: var( --ld-ui-btn-secondary-text, var(--ld-btn-secondary-text) ) !important;
1290
1272
  border-color: var(--ld-border-subtle);
1291
1273
  }
1292
1274
  .ld-btn--secondary:hover {
1293
1275
  background-color: var(--ld-bg-mute);
1294
1276
  border-color: var(--ld-border-strong);
1295
- color: var( --ld-ui-btn-secondary-text, var(--ld-btn-secondary-text) ) !important;
1296
1277
  }
1297
1278
  .ld-btn--outline {
1298
- background: transparent;
1279
+ background: transparent !important;
1299
1280
  color: var(--ld-text-main) !important;
1300
1281
  border-color: var(--ld-border-strong);
1301
1282
  }
@@ -1304,7 +1285,7 @@ a {
1304
1285
  border-color: var(--ld-color-primary);
1305
1286
  }
1306
1287
  .ld-btn--ghost {
1307
- background: transparent;
1288
+ background: transparent !important;
1308
1289
  color: var(--ld-text-muted) !important;
1309
1290
  }
1310
1291
  .ld-btn--ghost:hover {
@@ -1840,56 +1821,6 @@ a {
1840
1821
  color: var(--ld-color-primary);
1841
1822
  }
1842
1823
 
1843
- /* src/client/theme/styles/home.css */
1844
- .boltdocs-home {
1845
- min-height: calc(100vh - var(--ld-navbar-height));
1846
- }
1847
- .home-hero {
1848
- display: flex;
1849
- align-items: center;
1850
- justify-content: center;
1851
- padding: 6rem 2rem 4rem;
1852
- text-align: center;
1853
- }
1854
- .hero-content {
1855
- max-width: 680px;
1856
- }
1857
- .hero-title {
1858
- font-size: 3.5rem;
1859
- font-weight: 900;
1860
- line-height: 1.1;
1861
- margin: 0 0 1.25rem;
1862
- letter-spacing: -0.03em;
1863
- color: var(--ld-text-main);
1864
- }
1865
- .hero-highlight {
1866
- background:
1867
- linear-gradient(
1868
- 135deg,
1869
- var(--ld-gradient-from),
1870
- var(--ld-gradient-to));
1871
- -webkit-background-clip: text;
1872
- -webkit-text-fill-color: transparent;
1873
- background-clip: text;
1874
- }
1875
- .hero-description {
1876
- font-size: 1.125rem;
1877
- color: var(--ld-text-muted);
1878
- line-height: 1.7;
1879
- margin-bottom: 2rem;
1880
- }
1881
- .hero-actions {
1882
- display: flex;
1883
- gap: 0.75rem;
1884
- justify-content: center;
1885
- flex-wrap: wrap;
1886
- }
1887
- .home-features {
1888
- padding: 2rem 2rem 6rem;
1889
- max-width: 1000px;
1890
- margin: 0 auto;
1891
- }
1892
-
1893
1824
  /* src/client/theme/ui/NotFound/not-found.css */
1894
1825
  .boltdocs-not-found {
1895
1826
  display: flex;
@@ -2122,9 +2053,6 @@ a.not-found-link:hover {
2122
2053
  .boltdocs-sidebar {
2123
2054
  display: none;
2124
2055
  }
2125
- .sidebar-toggle-floating {
2126
- display: none !important;
2127
- }
2128
2056
  .boltdocs-content {
2129
2057
  padding: 1.5rem 1rem 3rem;
2130
2058
  }
@@ -1,7 +1,6 @@
1
1
  import {
2
2
  Video
3
3
  } from "./chunk-Z7JHYNAS.mjs";
4
- import "./chunk-X6BYQHVC.mjs";
5
4
  export {
6
5
  Video
7
6
  };
@@ -0,0 +1,12 @@
1
+ import {
2
+ AssetCache,
3
+ FileCache,
4
+ TransformCache,
5
+ flushCache
6
+ } from "./chunk-GSYECEZY.mjs";
7
+ export {
8
+ AssetCache,
9
+ FileCache,
10
+ TransformCache,
11
+ flushCache
12
+ };
@@ -0,0 +1,381 @@
1
+ // src/node/cache.ts
2
+ import fs2 from "fs";
3
+ import path from "path";
4
+ import crypto from "crypto";
5
+ import zlib from "zlib";
6
+ import { promisify } from "util";
7
+
8
+ // src/node/utils.ts
9
+ import fs from "fs";
10
+ import matter from "gray-matter";
11
+ function normalizePath(p) {
12
+ return p.replace(/\\/g, "/");
13
+ }
14
+ function stripNumberPrefix(name) {
15
+ return name.replace(/^\d+\./, "");
16
+ }
17
+ function extractNumberPrefix(name) {
18
+ const match = name.match(/^(\d+)\./);
19
+ return match ? parseInt(match[1], 10) : void 0;
20
+ }
21
+ function isDocFile(filePath) {
22
+ return /\.mdx?$/.test(filePath);
23
+ }
24
+ function getFileMtime(filePath) {
25
+ try {
26
+ return fs.statSync(filePath).mtimeMs;
27
+ } catch {
28
+ return 0;
29
+ }
30
+ }
31
+ function parseFrontmatter(filePath) {
32
+ const raw = fs.readFileSync(filePath, "utf-8");
33
+ const { data, content } = matter(raw);
34
+ return { data, content };
35
+ }
36
+ function escapeHtml(str) {
37
+ return str.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
38
+ }
39
+ function fileToRoutePath(relativePath) {
40
+ let cleanedPath = relativePath.split("/").map(stripNumberPrefix).join("/");
41
+ let routePath = cleanedPath.replace(/\.mdx?$/, "");
42
+ if (routePath === "index" || routePath.endsWith("/index")) {
43
+ routePath = routePath.replace(/index$/, "");
44
+ }
45
+ if (!routePath.startsWith("/")) {
46
+ routePath = "/" + routePath;
47
+ }
48
+ if (routePath.length > 1 && routePath.endsWith("/")) {
49
+ routePath = routePath.slice(0, -1);
50
+ }
51
+ return routePath;
52
+ }
53
+ function capitalize(str) {
54
+ return str.charAt(0).toUpperCase() + str.slice(1);
55
+ }
56
+
57
+ // src/node/cache.ts
58
+ var writeFile = promisify(fs2.writeFile);
59
+ var readFile = promisify(fs2.readFile);
60
+ var mkdir = promisify(fs2.mkdir);
61
+ var rename = promisify(fs2.rename);
62
+ var unlink = promisify(fs2.unlink);
63
+ var CACHE_DIR = process.env.BOLTDOCS_CACHE_DIR || ".boltdocs";
64
+ var ASSETS_DIR = "assets";
65
+ var SHARDS_DIR = "shards";
66
+ var DEFAULT_LRU_LIMIT = parseInt(
67
+ process.env.BOLTDOCS_CACHE_LRU_LIMIT || "2000",
68
+ 10
69
+ );
70
+ var DEFAULT_COMPRESS = process.env.BOLTDOCS_CACHE_COMPRESS !== "0";
71
+ var LRUCache = class {
72
+ constructor(limit) {
73
+ this.limit = limit;
74
+ }
75
+ cache = /* @__PURE__ */ new Map();
76
+ get(key) {
77
+ const val = this.cache.get(key);
78
+ if (val !== void 0) {
79
+ this.cache.delete(key);
80
+ this.cache.set(key, val);
81
+ }
82
+ return val;
83
+ }
84
+ set(key, value) {
85
+ if (this.cache.has(key)) {
86
+ this.cache.delete(key);
87
+ } else if (this.cache.size >= this.limit) {
88
+ const firstKey = this.cache.keys().next().value;
89
+ if (firstKey !== void 0) {
90
+ this.cache.delete(firstKey);
91
+ }
92
+ }
93
+ this.cache.set(key, value);
94
+ }
95
+ get size() {
96
+ return this.cache.size;
97
+ }
98
+ clear() {
99
+ this.cache.clear();
100
+ }
101
+ };
102
+ var BackgroundQueue = class {
103
+ queue = Promise.resolve();
104
+ pendingCount = 0;
105
+ add(task) {
106
+ this.pendingCount++;
107
+ this.queue = this.queue.then(task).finally(() => {
108
+ this.pendingCount--;
109
+ });
110
+ }
111
+ async flush() {
112
+ await this.queue;
113
+ }
114
+ get pending() {
115
+ return this.pendingCount;
116
+ }
117
+ };
118
+ var backgroundQueue = new BackgroundQueue();
119
+ var FileCache = class {
120
+ entries = /* @__PURE__ */ new Map();
121
+ cachePath = null;
122
+ compress;
123
+ constructor(options = {}) {
124
+ this.compress = options.compress !== void 0 ? options.compress : DEFAULT_COMPRESS;
125
+ if (options.name) {
126
+ const root = options.root || process.cwd();
127
+ const ext = this.compress ? "json.gz" : "json";
128
+ this.cachePath = path.resolve(root, CACHE_DIR, `${options.name}.${ext}`);
129
+ }
130
+ }
131
+ /**
132
+ * Loads the cache. Synchronous for startup simplicity but uses fast I/O.
133
+ */
134
+ load() {
135
+ if (process.env.BOLTDOCS_NO_CACHE === "1") return;
136
+ if (!this.cachePath || !fs2.existsSync(this.cachePath)) return;
137
+ try {
138
+ let raw = fs2.readFileSync(this.cachePath);
139
+ if (this.cachePath.endsWith(".gz")) {
140
+ raw = zlib.gunzipSync(raw);
141
+ }
142
+ const data = JSON.parse(raw.toString("utf-8"));
143
+ this.entries = new Map(Object.entries(data));
144
+ } catch (e) {
145
+ }
146
+ }
147
+ /**
148
+ * Saves the cache in the background.
149
+ */
150
+ save() {
151
+ if (process.env.BOLTDOCS_NO_CACHE === "1") return;
152
+ if (!this.cachePath) return;
153
+ const data = Object.fromEntries(this.entries);
154
+ const content = JSON.stringify(data);
155
+ const target = this.cachePath;
156
+ const useCompress = this.compress;
157
+ backgroundQueue.add(async () => {
158
+ try {
159
+ await mkdir(path.dirname(target), { recursive: true });
160
+ let buffer = Buffer.from(content);
161
+ if (useCompress) {
162
+ buffer = zlib.gzipSync(buffer);
163
+ }
164
+ const tempPath = `${target}.${crypto.randomBytes(4).toString("hex")}.tmp`;
165
+ await writeFile(tempPath, buffer);
166
+ await rename(tempPath, target);
167
+ } catch (e) {
168
+ }
169
+ });
170
+ }
171
+ get(filePath) {
172
+ const entry = this.entries.get(filePath);
173
+ if (!entry) return null;
174
+ if (getFileMtime(filePath) !== entry.mtime) return null;
175
+ return entry.data;
176
+ }
177
+ set(filePath, data) {
178
+ this.entries.set(filePath, {
179
+ data,
180
+ mtime: getFileMtime(filePath)
181
+ });
182
+ }
183
+ isValid(filePath) {
184
+ const entry = this.entries.get(filePath);
185
+ if (!entry) return false;
186
+ return getFileMtime(filePath) === entry.mtime;
187
+ }
188
+ invalidate(filePath) {
189
+ this.entries.delete(filePath);
190
+ }
191
+ invalidateAll() {
192
+ this.entries.clear();
193
+ }
194
+ pruneStale(currentFiles) {
195
+ for (const key of this.entries.keys()) {
196
+ if (!currentFiles.has(key)) {
197
+ this.entries.delete(key);
198
+ }
199
+ }
200
+ }
201
+ get size() {
202
+ return this.entries.size;
203
+ }
204
+ async flush() {
205
+ await backgroundQueue.flush();
206
+ }
207
+ };
208
+ var TransformCache = class {
209
+ index = /* @__PURE__ */ new Map();
210
+ // key -> hash
211
+ memoryCache = new LRUCache(DEFAULT_LRU_LIMIT);
212
+ baseDir;
213
+ shardsDir;
214
+ indexPath;
215
+ constructor(name, root = process.cwd()) {
216
+ this.baseDir = path.resolve(root, CACHE_DIR, `transform-${name}`);
217
+ this.shardsDir = path.resolve(this.baseDir, SHARDS_DIR);
218
+ this.indexPath = path.resolve(this.baseDir, "index.json");
219
+ }
220
+ /**
221
+ * Loads the index into memory.
222
+ */
223
+ load() {
224
+ if (process.env.BOLTDOCS_NO_CACHE === "1") return;
225
+ if (!fs2.existsSync(this.indexPath)) return;
226
+ try {
227
+ const data = fs2.readFileSync(this.indexPath, "utf-8");
228
+ this.index = new Map(Object.entries(JSON.parse(data)));
229
+ } catch (e) {
230
+ }
231
+ }
232
+ /**
233
+ * Persists the index in background.
234
+ */
235
+ save() {
236
+ if (process.env.BOLTDOCS_NO_CACHE === "1") return;
237
+ const data = JSON.stringify(Object.fromEntries(this.index));
238
+ const target = this.indexPath;
239
+ backgroundQueue.add(async () => {
240
+ await mkdir(path.dirname(target), { recursive: true });
241
+ await writeFile(target, data);
242
+ });
243
+ }
244
+ /**
245
+ * Batch Read: Retrieves multiple transformation results concurrently.
246
+ */
247
+ async getMany(keys) {
248
+ const results = /* @__PURE__ */ new Map();
249
+ const toLoad = [];
250
+ for (const key of keys) {
251
+ const mem = this.memoryCache.get(key);
252
+ if (mem) results.set(key, mem);
253
+ else if (this.index.has(key)) toLoad.push(key);
254
+ }
255
+ if (toLoad.length > 0) {
256
+ const shards = await Promise.all(
257
+ toLoad.map(async (key) => {
258
+ const hash = this.index.get(key);
259
+ const shardPath = path.resolve(this.shardsDir, `${hash}.gz`);
260
+ try {
261
+ const compressed = await readFile(shardPath);
262
+ const decompressed = zlib.gunzipSync(compressed).toString("utf-8");
263
+ this.memoryCache.set(key, decompressed);
264
+ return { key, val: decompressed };
265
+ } catch (e) {
266
+ return null;
267
+ }
268
+ })
269
+ );
270
+ for (const s of shards) {
271
+ if (s) results.set(s.key, s.val);
272
+ }
273
+ }
274
+ return results;
275
+ }
276
+ /**
277
+ * Retrieves a cached transformation. Fast lookup via index, lazy loading from disk.
278
+ */
279
+ get(key) {
280
+ const mem = this.memoryCache.get(key);
281
+ if (mem) return mem;
282
+ const hash = this.index.get(key);
283
+ if (!hash) return null;
284
+ const shardPath = path.resolve(this.shardsDir, `${hash}.gz`);
285
+ if (!fs2.existsSync(shardPath)) return null;
286
+ try {
287
+ const compressed = fs2.readFileSync(shardPath);
288
+ const decompressed = zlib.gunzipSync(compressed).toString("utf-8");
289
+ this.memoryCache.set(key, decompressed);
290
+ return decompressed;
291
+ } catch (e) {
292
+ return null;
293
+ }
294
+ }
295
+ /**
296
+ * Stores a transformation result.
297
+ */
298
+ set(key, result) {
299
+ const hash = crypto.createHash("md5").update(result).digest("hex");
300
+ this.index.set(key, hash);
301
+ this.memoryCache.set(key, result);
302
+ const shardPath = path.resolve(this.shardsDir, `${hash}.gz`);
303
+ backgroundQueue.add(async () => {
304
+ if (fs2.existsSync(shardPath)) return;
305
+ await mkdir(this.shardsDir, { recursive: true });
306
+ const compressed = zlib.gzipSync(Buffer.from(result));
307
+ const tempPath = `${shardPath}.${crypto.randomBytes(4).toString("hex")}.tmp`;
308
+ await writeFile(tempPath, compressed);
309
+ await rename(tempPath, shardPath);
310
+ });
311
+ }
312
+ get size() {
313
+ return this.index.size;
314
+ }
315
+ async flush() {
316
+ await backgroundQueue.flush();
317
+ }
318
+ };
319
+ var AssetCache = class {
320
+ assetsDir;
321
+ constructor(root = process.cwd()) {
322
+ this.assetsDir = path.resolve(root, CACHE_DIR, ASSETS_DIR);
323
+ }
324
+ getFileHash(filePath) {
325
+ return crypto.createHash("md5").update(fs2.readFileSync(filePath)).digest("hex");
326
+ }
327
+ get(sourcePath, cacheKey) {
328
+ if (!fs2.existsSync(sourcePath)) return null;
329
+ const sourceHash = this.getFileHash(sourcePath);
330
+ const cachedPath = this.getCachedPath(
331
+ sourcePath,
332
+ `${cacheKey}-${sourceHash}`
333
+ );
334
+ return fs2.existsSync(cachedPath) ? cachedPath : null;
335
+ }
336
+ set(sourcePath, cacheKey, content) {
337
+ const sourceHash = this.getFileHash(sourcePath);
338
+ const cachedPath = this.getCachedPath(
339
+ sourcePath,
340
+ `${cacheKey}-${sourceHash}`
341
+ );
342
+ backgroundQueue.add(async () => {
343
+ await mkdir(this.assetsDir, { recursive: true });
344
+ const tempPath = `${cachedPath}.${crypto.randomBytes(4).toString("hex")}.tmp`;
345
+ await writeFile(tempPath, content);
346
+ await rename(tempPath, cachedPath);
347
+ });
348
+ }
349
+ getCachedPath(sourcePath, cacheKey) {
350
+ const ext = path.extname(sourcePath);
351
+ const name = path.basename(sourcePath, ext);
352
+ const safeKey = cacheKey.replace(/[^a-z0-9]/gi, "-").toLowerCase();
353
+ return path.join(this.assetsDir, `${name}.${safeKey}${ext}`);
354
+ }
355
+ clear() {
356
+ if (fs2.existsSync(this.assetsDir)) {
357
+ fs2.rmSync(this.assetsDir, { recursive: true, force: true });
358
+ }
359
+ }
360
+ async flush() {
361
+ await backgroundQueue.flush();
362
+ }
363
+ };
364
+ async function flushCache() {
365
+ await backgroundQueue.flush();
366
+ }
367
+
368
+ export {
369
+ normalizePath,
370
+ stripNumberPrefix,
371
+ extractNumberPrefix,
372
+ isDocFile,
373
+ parseFrontmatter,
374
+ escapeHtml,
375
+ fileToRoutePath,
376
+ capitalize,
377
+ FileCache,
378
+ TransformCache,
379
+ AssetCache,
380
+ flushCache
381
+ };