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.
- package/dist/{cache-EHR7SXRU.mjs → cache-GQHF6BXI.mjs} +1 -1
- package/dist/{chunk-GSYECEZY.mjs → chunk-CYBWLFOG.mjs} +5 -1
- package/dist/node/index.js +36 -20
- package/dist/node/index.mjs +34 -22
- package/package.json +1 -1
- package/src/client/app/index.tsx +344 -344
- package/src/client/app/preload.tsx +56 -56
- package/src/client/index.ts +40 -40
- package/src/client/ssr.tsx +51 -51
- package/src/client/theme/components/CodeBlock/CodeBlock.tsx +76 -76
- package/src/client/theme/components/CodeBlock/index.ts +1 -1
- package/src/client/theme/components/PackageManagerTabs/PackageManagerTabs.tsx +154 -154
- package/src/client/theme/components/PackageManagerTabs/index.ts +1 -1
- package/src/client/theme/components/PackageManagerTabs/pkg-tabs.css +64 -64
- package/src/client/theme/components/Playground/Playground.tsx +124 -124
- package/src/client/theme/components/Playground/index.ts +1 -1
- package/src/client/theme/components/Playground/playground.css +168 -168
- package/src/client/theme/components/Video/Video.tsx +84 -84
- package/src/client/theme/components/Video/index.ts +1 -1
- package/src/client/theme/components/Video/video.css +41 -41
- package/src/client/theme/components/mdx/Admonition.tsx +80 -80
- package/src/client/theme/components/mdx/Badge.tsx +31 -31
- package/src/client/theme/components/mdx/Button.tsx +50 -50
- package/src/client/theme/components/mdx/Card.tsx +80 -80
- package/src/client/theme/components/mdx/List.tsx +57 -57
- package/src/client/theme/components/mdx/Tabs.tsx +94 -94
- package/src/client/theme/components/mdx/index.ts +18 -18
- package/src/client/theme/components/mdx/mdx-components.css +424 -424
- package/src/client/theme/icons/bun.tsx +62 -62
- package/src/client/theme/icons/deno.tsx +20 -20
- package/src/client/theme/icons/discord.tsx +12 -12
- package/src/client/theme/icons/github.tsx +15 -15
- package/src/client/theme/icons/npm.tsx +13 -13
- package/src/client/theme/icons/pnpm.tsx +72 -72
- package/src/client/theme/icons/twitter.tsx +12 -12
- package/src/client/theme/styles/markdown.css +343 -343
- package/src/client/theme/styles/variables.css +162 -162
- package/src/client/theme/styles.css +37 -37
- package/src/client/theme/ui/BackgroundGradient/BackgroundGradient.tsx +10 -10
- package/src/client/theme/ui/BackgroundGradient/index.ts +1 -1
- package/src/client/theme/ui/Breadcrumbs/Breadcrumbs.tsx +68 -68
- package/src/client/theme/ui/Breadcrumbs/index.ts +1 -1
- package/src/client/theme/ui/Footer/footer.css +32 -32
- package/src/client/theme/ui/Head/Head.tsx +69 -69
- package/src/client/theme/ui/Head/index.ts +1 -1
- package/src/client/theme/ui/LanguageSwitcher/LanguageSwitcher.tsx +125 -125
- package/src/client/theme/ui/LanguageSwitcher/index.ts +1 -1
- package/src/client/theme/ui/LanguageSwitcher/language-switcher.css +98 -98
- package/src/client/theme/ui/Layout/Layout.tsx +202 -202
- package/src/client/theme/ui/Layout/base.css +76 -76
- package/src/client/theme/ui/Layout/index.ts +2 -2
- package/src/client/theme/ui/Layout/pagination.css +72 -72
- package/src/client/theme/ui/Layout/responsive.css +36 -36
- package/src/client/theme/ui/Link/Link.tsx +254 -254
- package/src/client/theme/ui/Link/index.ts +2 -2
- package/src/client/theme/ui/Loading/Loading.tsx +10 -10
- package/src/client/theme/ui/Loading/index.ts +1 -1
- package/src/client/theme/ui/Loading/loading.css +30 -30
- package/src/client/theme/ui/Navbar/GithubStars.tsx +27 -27
- package/src/client/theme/ui/Navbar/Navbar.tsx +145 -145
- package/src/client/theme/ui/Navbar/index.ts +2 -2
- package/src/client/theme/ui/Navbar/navbar.css +233 -233
- package/src/client/theme/ui/NotFound/NotFound.tsx +19 -19
- package/src/client/theme/ui/NotFound/index.ts +1 -1
- package/src/client/theme/ui/NotFound/not-found.css +64 -64
- package/src/client/theme/ui/OnThisPage/OnThisPage.tsx +235 -235
- package/src/client/theme/ui/OnThisPage/index.ts +1 -1
- package/src/client/theme/ui/OnThisPage/toc.css +132 -132
- package/src/client/theme/ui/PoweredBy/PoweredBy.tsx +18 -18
- package/src/client/theme/ui/PoweredBy/index.ts +1 -1
- package/src/client/theme/ui/PoweredBy/powered-by.css +76 -76
- package/src/client/theme/ui/SearchDialog/SearchDialog.tsx +199 -199
- package/src/client/theme/ui/SearchDialog/index.ts +1 -1
- package/src/client/theme/ui/SearchDialog/search.css +152 -152
- package/src/client/theme/ui/Sidebar/Sidebar.tsx +204 -204
- package/src/client/theme/ui/Sidebar/index.ts +1 -1
- package/src/client/theme/ui/Sidebar/sidebar.css +236 -236
- package/src/client/theme/ui/ThemeToggle/ThemeToggle.tsx +69 -69
- package/src/client/theme/ui/ThemeToggle/index.ts +1 -1
- package/src/client/theme/ui/VersionSwitcher/VersionSwitcher.tsx +136 -136
- package/src/client/theme/ui/VersionSwitcher/index.ts +1 -1
- package/src/client/types.ts +50 -50
- package/src/client/utils.ts +26 -26
- package/src/node/cache.ts +408 -408
- package/src/node/config.ts +192 -192
- package/src/node/index.ts +21 -21
- package/src/node/mdx.ts +120 -120
- package/src/node/plugin/entry.ts +58 -58
- package/src/node/plugin/html.ts +55 -55
- package/src/node/plugin/index.ts +193 -193
- package/src/node/plugin/types.ts +11 -11
- package/src/node/routes/cache.ts +28 -28
- package/src/node/routes/index.ts +167 -167
- package/src/node/routes/parser.ts +153 -127
- package/src/node/routes/sorter.ts +42 -42
- package/src/node/routes/types.ts +49 -49
- package/src/node/ssg/index.ts +114 -114
- package/src/node/ssg/meta.ts +33 -34
- package/src/node/ssg/options.ts +13 -13
- package/src/node/ssg/sitemap.ts +55 -54
- package/src/node/utils.ts +145 -134
- package/tsconfig.json +20 -20
- package/tsup.config.ts +22 -22
|
@@ -34,7 +34,10 @@ function parseFrontmatter(filePath) {
|
|
|
34
34
|
return { data, content };
|
|
35
35
|
}
|
|
36
36
|
function escapeHtml(str) {
|
|
37
|
-
return str.replace(/&/g, "&").replace(/"/g, """).replace(/</g, "<").replace(/>/g, ">");
|
|
37
|
+
return str.replace(/&/g, "&").replace(/"/g, """).replace(/'/g, "'").replace(/</g, "<").replace(/>/g, ">");
|
|
38
|
+
}
|
|
39
|
+
function escapeXml(str) {
|
|
40
|
+
return escapeHtml(str);
|
|
38
41
|
}
|
|
39
42
|
function fileToRoutePath(relativePath) {
|
|
40
43
|
let cleanedPath = relativePath.split("/").map(stripNumberPrefix).join("/");
|
|
@@ -372,6 +375,7 @@ export {
|
|
|
372
375
|
isDocFile,
|
|
373
376
|
parseFrontmatter,
|
|
374
377
|
escapeHtml,
|
|
378
|
+
escapeXml,
|
|
375
379
|
fileToRoutePath,
|
|
376
380
|
capitalize,
|
|
377
381
|
FileCache,
|
package/dist/node/index.js
CHANGED
|
@@ -57,7 +57,10 @@ function parseFrontmatter(filePath) {
|
|
|
57
57
|
return { data, content };
|
|
58
58
|
}
|
|
59
59
|
function escapeHtml(str) {
|
|
60
|
-
return str.replace(/&/g, "&").replace(/"/g, """).replace(/</g, "<").replace(/>/g, ">");
|
|
60
|
+
return str.replace(/&/g, "&").replace(/"/g, """).replace(/'/g, "'").replace(/</g, "<").replace(/>/g, ">");
|
|
61
|
+
}
|
|
62
|
+
function escapeXml(str) {
|
|
63
|
+
return escapeHtml(str);
|
|
61
64
|
}
|
|
62
65
|
function fileToRoutePath(relativePath) {
|
|
63
66
|
let cleanedPath = relativePath.split("/").map(stripNumberPrefix).join("/");
|
|
@@ -445,8 +448,18 @@ var import_path2 = __toESM(require("path"));
|
|
|
445
448
|
var import_github_slugger = __toESM(require("github-slugger"));
|
|
446
449
|
init_utils();
|
|
447
450
|
function parseDocFile(file, docsDir, basePath, config) {
|
|
451
|
+
const decodedFile = decodeURIComponent(file);
|
|
452
|
+
const absoluteFile = import_path2.default.resolve(decodedFile);
|
|
453
|
+
const absoluteDocsDir = import_path2.default.resolve(docsDir);
|
|
454
|
+
const relativePath = normalizePath(
|
|
455
|
+
import_path2.default.relative(absoluteDocsDir, absoluteFile)
|
|
456
|
+
);
|
|
457
|
+
if (relativePath.startsWith("../") || relativePath === ".." || absoluteFile.includes("\0")) {
|
|
458
|
+
throw new Error(
|
|
459
|
+
`Security breach: File is outside of docs directory or contains null bytes: ${file}`
|
|
460
|
+
);
|
|
461
|
+
}
|
|
448
462
|
const { data, content } = parseFrontmatter(file);
|
|
449
|
-
const relativePath = normalizePath(import_path2.default.relative(docsDir, file));
|
|
450
463
|
let parts = relativePath.split("/");
|
|
451
464
|
let locale;
|
|
452
465
|
let version;
|
|
@@ -492,25 +505,30 @@ function parseDocFile(file, docsDir, basePath, config) {
|
|
|
492
505
|
const level = match[1].length;
|
|
493
506
|
const text = match[2].replace(/\[([^\]]+)\]\([^\)]+\)/g, "$1").replace(/[_*`]/g, "").trim();
|
|
494
507
|
const id = slugger.slug(text);
|
|
495
|
-
headings.push({ level, text, id });
|
|
508
|
+
headings.push({ level, text: escapeHtml(text), id });
|
|
496
509
|
}
|
|
510
|
+
const sanitizedTitle = data.title ? escapeHtml(data.title) : inferredTitle;
|
|
511
|
+
const sanitizedDescription = data.description ? escapeHtml(data.description) : "";
|
|
512
|
+
const sanitizedBadge = data.badge ? escapeHtml(data.badge) : void 0;
|
|
497
513
|
return {
|
|
498
514
|
route: {
|
|
499
515
|
path: finalPath,
|
|
500
516
|
componentPath: file,
|
|
501
517
|
filePath: relativePath,
|
|
502
|
-
title:
|
|
503
|
-
description:
|
|
518
|
+
title: sanitizedTitle,
|
|
519
|
+
description: sanitizedDescription,
|
|
504
520
|
sidebarPosition,
|
|
505
521
|
headings,
|
|
506
522
|
locale,
|
|
507
523
|
version,
|
|
508
|
-
badge:
|
|
524
|
+
badge: sanitizedBadge
|
|
509
525
|
},
|
|
510
526
|
relativeDir: cleanDirName,
|
|
511
527
|
isGroupIndex,
|
|
512
528
|
groupMeta: isGroupIndex ? {
|
|
513
|
-
title:
|
|
529
|
+
title: escapeHtml(
|
|
530
|
+
data.groupTitle || data.title || (cleanDirName ? capitalize(cleanDirName) : "")
|
|
531
|
+
),
|
|
514
532
|
position: data.groupPosition ?? data.sidebarPosition ?? (rawDirName ? extractNumberPrefix(rawDirName) : void 0)
|
|
515
533
|
} : void 0,
|
|
516
534
|
inferredGroupPosition: rawDirName ? extractNumberPrefix(rawDirName) : void 0
|
|
@@ -707,26 +725,24 @@ var import_url2 = require("url");
|
|
|
707
725
|
var import_module = require("module");
|
|
708
726
|
|
|
709
727
|
// src/node/ssg/meta.ts
|
|
728
|
+
init_utils();
|
|
710
729
|
function replaceMetaTags(html, meta) {
|
|
711
|
-
|
|
730
|
+
const title = escapeHtml(meta.title);
|
|
731
|
+
const description = escapeHtml(meta.description);
|
|
732
|
+
return html.replace(/<title>.*?<\/title>/, `<title>${title}</title>`).replace(
|
|
712
733
|
/(<meta name="description" content=")[^"]*(")/,
|
|
713
|
-
`$1${
|
|
714
|
-
).replace(
|
|
715
|
-
/(<meta property="og:title" content=")[^"]*(")/,
|
|
716
|
-
`$1${meta.title}$2`
|
|
717
|
-
).replace(
|
|
734
|
+
`$1${description}$2`
|
|
735
|
+
).replace(/(<meta property="og:title" content=")[^"]*(")/, `$1${title}$2`).replace(
|
|
718
736
|
/(<meta property="og:description" content=")[^"]*(")/,
|
|
719
|
-
`$1${
|
|
720
|
-
).replace(
|
|
721
|
-
/(<meta name="twitter:title" content=")[^"]*(")/,
|
|
722
|
-
`$1${meta.title}$2`
|
|
723
|
-
).replace(
|
|
737
|
+
`$1${description}$2`
|
|
738
|
+
).replace(/(<meta name="twitter:title" content=")[^"]*(")/, `$1${title}$2`).replace(
|
|
724
739
|
/(<meta name="twitter:description" content=")[^"]*(")/,
|
|
725
|
-
`$1${
|
|
740
|
+
`$1${description}$2`
|
|
726
741
|
);
|
|
727
742
|
}
|
|
728
743
|
|
|
729
744
|
// src/node/ssg/sitemap.ts
|
|
745
|
+
init_utils();
|
|
730
746
|
function generateSitemap(routePaths, config) {
|
|
731
747
|
const baseUrl = config?.siteUrl?.replace(/\/$/, "") || "https://example.com";
|
|
732
748
|
const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
@@ -755,7 +771,7 @@ function generateSitemap(routePaths, config) {
|
|
|
755
771
|
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
|
756
772
|
${entries.map(
|
|
757
773
|
(e) => ` <url>
|
|
758
|
-
<loc>${baseUrl}${e.url}</loc>
|
|
774
|
+
<loc>${escapeXml(baseUrl)}${escapeXml(e.url)}</loc>
|
|
759
775
|
<lastmod>${today}</lastmod>
|
|
760
776
|
<changefreq>${e.changefreq}</changefreq>
|
|
761
777
|
<priority>${e.priority}</priority>
|
package/dist/node/index.mjs
CHANGED
|
@@ -3,13 +3,14 @@ import {
|
|
|
3
3
|
TransformCache,
|
|
4
4
|
capitalize,
|
|
5
5
|
escapeHtml,
|
|
6
|
+
escapeXml,
|
|
6
7
|
extractNumberPrefix,
|
|
7
8
|
fileToRoutePath,
|
|
8
9
|
isDocFile,
|
|
9
10
|
normalizePath,
|
|
10
11
|
parseFrontmatter,
|
|
11
12
|
stripNumberPrefix
|
|
12
|
-
} from "../chunk-
|
|
13
|
+
} from "../chunk-CYBWLFOG.mjs";
|
|
13
14
|
|
|
14
15
|
// src/node/plugin/index.ts
|
|
15
16
|
import { loadEnv } from "vite";
|
|
@@ -30,8 +31,18 @@ function invalidateFile(filePath) {
|
|
|
30
31
|
import path from "path";
|
|
31
32
|
import GithubSlugger from "github-slugger";
|
|
32
33
|
function parseDocFile(file, docsDir, basePath, config) {
|
|
34
|
+
const decodedFile = decodeURIComponent(file);
|
|
35
|
+
const absoluteFile = path.resolve(decodedFile);
|
|
36
|
+
const absoluteDocsDir = path.resolve(docsDir);
|
|
37
|
+
const relativePath = normalizePath(
|
|
38
|
+
path.relative(absoluteDocsDir, absoluteFile)
|
|
39
|
+
);
|
|
40
|
+
if (relativePath.startsWith("../") || relativePath === ".." || absoluteFile.includes("\0")) {
|
|
41
|
+
throw new Error(
|
|
42
|
+
`Security breach: File is outside of docs directory or contains null bytes: ${file}`
|
|
43
|
+
);
|
|
44
|
+
}
|
|
33
45
|
const { data, content } = parseFrontmatter(file);
|
|
34
|
-
const relativePath = normalizePath(path.relative(docsDir, file));
|
|
35
46
|
let parts = relativePath.split("/");
|
|
36
47
|
let locale;
|
|
37
48
|
let version;
|
|
@@ -77,25 +88,30 @@ function parseDocFile(file, docsDir, basePath, config) {
|
|
|
77
88
|
const level = match[1].length;
|
|
78
89
|
const text = match[2].replace(/\[([^\]]+)\]\([^\)]+\)/g, "$1").replace(/[_*`]/g, "").trim();
|
|
79
90
|
const id = slugger.slug(text);
|
|
80
|
-
headings.push({ level, text, id });
|
|
91
|
+
headings.push({ level, text: escapeHtml(text), id });
|
|
81
92
|
}
|
|
93
|
+
const sanitizedTitle = data.title ? escapeHtml(data.title) : inferredTitle;
|
|
94
|
+
const sanitizedDescription = data.description ? escapeHtml(data.description) : "";
|
|
95
|
+
const sanitizedBadge = data.badge ? escapeHtml(data.badge) : void 0;
|
|
82
96
|
return {
|
|
83
97
|
route: {
|
|
84
98
|
path: finalPath,
|
|
85
99
|
componentPath: file,
|
|
86
100
|
filePath: relativePath,
|
|
87
|
-
title:
|
|
88
|
-
description:
|
|
101
|
+
title: sanitizedTitle,
|
|
102
|
+
description: sanitizedDescription,
|
|
89
103
|
sidebarPosition,
|
|
90
104
|
headings,
|
|
91
105
|
locale,
|
|
92
106
|
version,
|
|
93
|
-
badge:
|
|
107
|
+
badge: sanitizedBadge
|
|
94
108
|
},
|
|
95
109
|
relativeDir: cleanDirName,
|
|
96
110
|
isGroupIndex,
|
|
97
111
|
groupMeta: isGroupIndex ? {
|
|
98
|
-
title:
|
|
112
|
+
title: escapeHtml(
|
|
113
|
+
data.groupTitle || data.title || (cleanDirName ? capitalize(cleanDirName) : "")
|
|
114
|
+
),
|
|
99
115
|
position: data.groupPosition ?? data.sidebarPosition ?? (rawDirName ? extractNumberPrefix(rawDirName) : void 0)
|
|
100
116
|
} : void 0,
|
|
101
117
|
inferredGroupPosition: rawDirName ? extractNumberPrefix(rawDirName) : void 0
|
|
@@ -292,21 +308,17 @@ import { createRequire } from "module";
|
|
|
292
308
|
|
|
293
309
|
// src/node/ssg/meta.ts
|
|
294
310
|
function replaceMetaTags(html, meta) {
|
|
295
|
-
|
|
311
|
+
const title = escapeHtml(meta.title);
|
|
312
|
+
const description = escapeHtml(meta.description);
|
|
313
|
+
return html.replace(/<title>.*?<\/title>/, `<title>${title}</title>`).replace(
|
|
296
314
|
/(<meta name="description" content=")[^"]*(")/,
|
|
297
|
-
`$1${
|
|
298
|
-
).replace(
|
|
299
|
-
/(<meta property="og:title" content=")[^"]*(")/,
|
|
300
|
-
`$1${meta.title}$2`
|
|
301
|
-
).replace(
|
|
315
|
+
`$1${description}$2`
|
|
316
|
+
).replace(/(<meta property="og:title" content=")[^"]*(")/, `$1${title}$2`).replace(
|
|
302
317
|
/(<meta property="og:description" content=")[^"]*(")/,
|
|
303
|
-
`$1${
|
|
304
|
-
).replace(
|
|
305
|
-
/(<meta name="twitter:title" content=")[^"]*(")/,
|
|
306
|
-
`$1${meta.title}$2`
|
|
307
|
-
).replace(
|
|
318
|
+
`$1${description}$2`
|
|
319
|
+
).replace(/(<meta name="twitter:title" content=")[^"]*(")/, `$1${title}$2`).replace(
|
|
308
320
|
/(<meta name="twitter:description" content=")[^"]*(")/,
|
|
309
|
-
`$1${
|
|
321
|
+
`$1${description}$2`
|
|
310
322
|
);
|
|
311
323
|
}
|
|
312
324
|
|
|
@@ -339,7 +351,7 @@ function generateSitemap(routePaths, config) {
|
|
|
339
351
|
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
|
340
352
|
${entries.map(
|
|
341
353
|
(e) => ` <url>
|
|
342
|
-
<loc>${baseUrl}${e.url}</loc>
|
|
354
|
+
<loc>${escapeXml(baseUrl)}${escapeXml(e.url)}</loc>
|
|
343
355
|
<lastmod>${today}</lastmod>
|
|
344
356
|
<changefreq>${e.changefreq}</changefreq>
|
|
345
357
|
<priority>${e.priority}</priority>
|
|
@@ -418,7 +430,7 @@ async function generateStaticPages(options) {
|
|
|
418
430
|
console.log(
|
|
419
431
|
`[boltdocs] Generated ${routes.length} static pages + sitemap.xml`
|
|
420
432
|
);
|
|
421
|
-
const { flushCache } = await import("../cache-
|
|
433
|
+
const { flushCache } = await import("../cache-GQHF6BXI.mjs");
|
|
422
434
|
await flushCache();
|
|
423
435
|
}
|
|
424
436
|
|
|
@@ -600,7 +612,7 @@ function boltdocsPlugin(options = {}, passedConfig) {
|
|
|
600
612
|
if (!isBuild) return;
|
|
601
613
|
const outDir = viteConfig?.build?.outDir ? path4.resolve(viteConfig.root, viteConfig.build.outDir) : path4.resolve(process.cwd(), "dist");
|
|
602
614
|
await generateStaticPages({ docsDir, outDir, config });
|
|
603
|
-
const { flushCache } = await import("../cache-
|
|
615
|
+
const { flushCache } = await import("../cache-GQHF6BXI.mjs");
|
|
604
616
|
await flushCache();
|
|
605
617
|
}
|
|
606
618
|
},
|