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.
- package/dist/{CodeBlock-37XMKCYY.mjs → CodeBlock-V3Z5EKGR.mjs} +0 -1
- package/dist/{PackageManagerTabs-4NWXLXQO.mjs → PackageManagerTabs-XEKI3L7P.mjs} +0 -2
- package/dist/{SearchDialog-FTOQZ763.mjs → SearchDialog-5EDRACEG.mjs} +1 -2
- package/dist/{SearchDialog-ZAZXYIFX.css → SearchDialog-X57WPTNN.css} +57 -129
- package/dist/{Video-I6QY4X7J.mjs → Video-KNTY5BNO.mjs} +0 -1
- package/dist/cache-EHR7SXRU.mjs +12 -0
- package/dist/chunk-GSYECEZY.mjs +381 -0
- package/dist/{chunk-ZFCOLEXN.mjs → chunk-NS7WHDYA.mjs} +234 -426
- package/dist/client/index.css +57 -129
- package/dist/client/index.d.mts +39 -8
- package/dist/client/index.d.ts +39 -8
- package/dist/client/index.js +557 -564
- package/dist/client/index.mjs +305 -18
- package/dist/client/ssr.css +57 -129
- package/dist/client/ssr.d.mts +1 -1
- package/dist/client/ssr.d.ts +1 -1
- package/dist/client/ssr.js +257 -558
- package/dist/client/ssr.mjs +1 -2
- package/dist/{config-D2XmHJYe.d.mts → config-BD5ZHz15.d.mts} +7 -0
- package/dist/{config-D2XmHJYe.d.ts → config-BD5ZHz15.d.ts} +7 -0
- package/dist/node/index.d.mts +2 -2
- package/dist/node/index.d.ts +2 -2
- package/dist/node/index.js +457 -118
- package/dist/node/index.mjs +144 -147
- package/dist/{index-CRQKWAeo.d.mts → types-CvrzTbEX.d.mts} +1 -28
- package/dist/{index-CRQKWAeo.d.ts → types-CvrzTbEX.d.ts} +1 -28
- package/package.json +2 -2
- package/src/client/app/index.tsx +32 -110
- package/src/client/app/preload.tsx +1 -1
- package/src/client/index.ts +1 -1
- package/src/client/ssr.tsx +2 -1
- package/src/client/theme/components/Playground/Playground.tsx +40 -2
- package/src/client/theme/components/mdx/mdx-components.css +39 -20
- package/src/client/theme/styles/markdown.css +4 -4
- package/src/client/theme/styles.css +0 -1
- package/src/client/theme/ui/Breadcrumbs/Breadcrumbs.tsx +1 -1
- package/src/client/theme/ui/LanguageSwitcher/LanguageSwitcher.tsx +1 -1
- package/src/client/theme/ui/Layout/Layout.tsx +3 -14
- package/src/client/theme/ui/Layout/responsive.css +0 -4
- package/src/client/theme/ui/Link/Link.tsx +52 -0
- package/src/client/theme/ui/Navbar/Navbar.tsx +1 -1
- package/src/client/theme/ui/NotFound/NotFound.tsx +0 -1
- package/src/client/theme/ui/OnThisPage/OnThisPage.tsx +45 -2
- package/src/client/theme/ui/SearchDialog/SearchDialog.tsx +1 -1
- package/src/client/theme/ui/Sidebar/Sidebar.tsx +44 -40
- package/src/client/theme/ui/Sidebar/sidebar.css +25 -58
- package/src/client/theme/ui/VersionSwitcher/VersionSwitcher.tsx +1 -1
- package/src/client/types.ts +50 -0
- package/src/node/cache.ts +360 -46
- package/src/node/config.ts +7 -0
- package/src/node/mdx.ts +83 -4
- package/src/node/plugin/index.ts +3 -0
- package/src/node/routes/cache.ts +5 -1
- package/src/node/routes/index.ts +17 -2
- package/src/node/ssg/index.ts +4 -0
- package/dist/Playground-OE2OE6B6.mjs +0 -7
- package/dist/chunk-PN4GCTYG.mjs +0 -67
- package/dist/chunk-X2TDGMTR.mjs +0 -64
- package/dist/chunk-X6BYQHVC.mjs +0 -12
- package/dist/node/cli/index.d.mts +0 -1
- package/dist/node/cli/index.d.ts +0 -1
- package/dist/node/cli/index.js +0 -199
- package/dist/node/cli/index.mjs +0 -154
- package/src/client/theme/styles/home.css +0 -60
|
@@ -422,73 +422,43 @@ a {
|
|
|
422
422
|
flex: 1;
|
|
423
423
|
}
|
|
424
424
|
.boltdocs-main-container.sidebar-collapsed .boltdocs-sidebar {
|
|
425
|
-
width:
|
|
426
|
-
padding
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
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-
|
|
434
|
-
|
|
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:
|
|
446
|
-
|
|
447
|
-
|
|
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-
|
|
461
|
-
|
|
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
|
-
|
|
477
|
-
width:
|
|
478
|
-
|
|
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
|
-
|
|
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-
|
|
491
|
-
color: var(--ld-
|
|
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
|
-
|
|
1146
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
1258
|
-
|
|
1236
|
+
user-select: none;
|
|
1237
|
+
position: relative;
|
|
1259
1238
|
}
|
|
1260
1239
|
.ld-btn:hover {
|
|
1261
|
-
transform:
|
|
1240
|
+
transform: translateY(-1px);
|
|
1262
1241
|
}
|
|
1263
1242
|
.ld-btn:active {
|
|
1264
|
-
transform: scale(0.
|
|
1243
|
+
transform: translateY(0) scale(0.98);
|
|
1265
1244
|
}
|
|
1266
1245
|
.ld-btn--sm {
|
|
1267
|
-
|
|
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
|
-
|
|
1252
|
+
min-height: 2.625rem;
|
|
1253
|
+
padding: 0 1.6rem;
|
|
1273
1254
|
font-size: 0.9375rem;
|
|
1274
1255
|
}
|
|
1275
1256
|
.ld-btn--lg {
|
|
1276
|
-
|
|
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
|
-
|
|
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
|
}
|
|
@@ -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, "&").replace(/"/g, """).replace(/</g, "<").replace(/>/g, ">");
|
|
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
|
+
};
|