@docubook/flame 1.7.2 → 2.0.0-alpha.1
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/.docu/components/Context.tsx +1 -1
- package/.docu/components/Pagination.tsx +9 -1
- package/.docu/components/Search.tsx +6 -6
- package/.docu/components/Sidebar.tsx +37 -8
- package/.docu/components/Theme.tsx +2 -2
- package/.docu/components/Toc.tsx +52 -6
- package/.docu/components/Typography.tsx +1 -1
- package/.docu/components/home/Hero.tsx +4 -4
- package/.docu/components/registry.ts +1 -1
- package/.docu/lib/build.deno.js +3 -3
- package/.docu/lib/{build.impl-TSIF3F7O.js → build.impl-VXB4KL4D.js} +3 -3
- package/.docu/lib/build.node.js +3 -3
- package/.docu/lib/{chunk-SPHVBXRR.js → chunk-7PRQ3RQB.js} +6 -6
- package/.docu/lib/{chunk-DITXUPUV.js → chunk-A6FIEG3H.js} +61 -10
- package/.docu/lib/{chunk-PJIJEPNR.js → chunk-JRERMREW.js} +5 -4
- package/.docu/lib/{chunk-KMDGSD57.js → chunk-LZDEWK25.js} +3 -3
- package/.docu/lib/{chunk-HRO7ONJQ.js → chunk-MQWWCO6O.js} +70 -27
- package/.docu/lib/{chunk-B6LGUADD.js → chunk-TRT6WQZG.js} +346 -183
- package/.docu/lib/chunk-UISOJ4RW.js +114 -0
- package/.docu/lib/clean.js +1 -1
- package/.docu/lib/deploy.deno.js +1 -1
- package/.docu/lib/deploy.node.js +1 -1
- package/.docu/lib/preview.deno.js +5 -3
- package/.docu/lib/preview.node.js +5 -3
- package/.docu/lib/server.deno.js +6 -4
- package/.docu/lib/server.node.js +6 -4
- package/.docu/node/build.impl.ts +75 -26
- package/.docu/node/build.ts +70 -17
- package/.docu/node/client.ts +64 -27
- package/.docu/node/deploy.shared.ts +5 -5
- package/.docu/node/deploy.ts +1 -1
- package/.docu/node/html.shared.ts +7 -2
- package/.docu/node/html.ts +4 -2
- package/.docu/node/hydrate.node.ts +69 -4
- package/.docu/node/hydrate.ts +50 -1
- package/.docu/node/mdx-manifest.d.ts +5 -0
- package/.docu/node/mdx.ts +103 -17
- package/.docu/node/preview.deno.ts +1 -1
- package/.docu/node/preview.impl.ts +3 -3
- package/.docu/node/preview.node.ts +1 -1
- package/.docu/node/preview.ts +2 -2
- package/.docu/node/route.ts +57 -1
- package/.docu/node/runtime/bun.ts +28 -0
- package/.docu/node/runtime/deno.ts +34 -0
- package/.docu/node/runtime/index.ts +4 -0
- package/.docu/node/runtime/node.ts +107 -0
- package/.docu/node/runtime/types.ts +19 -0
- package/.docu/node/search-indexer.ts +3 -2
- package/.docu/node/seo.ts +2 -2
- package/.docu/node/server-routes.ts +32 -13
- package/.docu/node/server.deno.ts +1 -1
- package/.docu/node/server.impl.ts +49 -3
- package/.docu/node/server.node.ts +1 -1
- package/.docu/node/server.ts +45 -1
- package/.docu/pages/docs/[[...slug]].tsx +13 -4
- package/.docu/pages/index.tsx +1 -1
- package/.docu/styles/globals.css +38 -20
- package/README.md +7 -48
- package/bin/cli.js +25 -7
- package/package.json +7 -6
- package/template/README.md +7 -48
- package/template/docs/getting-started/configuration.mdx +16 -4
- package/template/docs/getting-started/overview.mdx +34 -42
- package/template/docs/guide/components.mdx +46 -228
- package/template/docs/guide/routing.mdx +8 -6
- package/template/docs/index.mdx +9 -8
- package/template/docu.json +4 -4
|
@@ -801,13 +801,12 @@ function collectAllLucideIcons() {
|
|
|
801
801
|
join2(FRAMEWORK_ROOT, "..", "mdx-content", "dist"),
|
|
802
802
|
join2(FRAMEWORK_ROOT, "..", "ui-react", "dist"),
|
|
803
803
|
join2(FRAMEWORK_ROOT, "..", "core", "dist"),
|
|
804
|
-
join2(FRAMEWORK_ROOT, "..", "runt", "dist"),
|
|
805
804
|
join2(FRAMEWORK_ROOT, "..", "themes-colors", "dist")
|
|
806
805
|
];
|
|
807
806
|
for (const d of depDirs) scanDirLucideIcons(resolve2(d), icons);
|
|
808
807
|
return [...icons];
|
|
809
808
|
}
|
|
810
|
-
async function buildClientBundle() {
|
|
809
|
+
async function buildClientBundle(mdxSources = {}) {
|
|
811
810
|
await mkdir(ASSETS_DIR, { recursive: true });
|
|
812
811
|
const twKey = tailwindCacheKey();
|
|
813
812
|
await cleanOldBundles(/* @__PURE__ */ new Set([`client-${twKey}.css`]));
|
|
@@ -854,7 +853,7 @@ async function buildClientBundle() {
|
|
|
854
853
|
}
|
|
855
854
|
if (args.importer) {
|
|
856
855
|
const normalized = normalizeImporterPath(args.importer);
|
|
857
|
-
if (normalized.includes("/
|
|
856
|
+
if (normalized.includes("/markdown/dist/")) {
|
|
858
857
|
return { path: getLucideRealEntry(), namespace: "file" };
|
|
859
858
|
}
|
|
860
859
|
}
|
|
@@ -895,6 +894,61 @@ async function buildClientBundle() {
|
|
|
895
894
|
};
|
|
896
895
|
});
|
|
897
896
|
}
|
|
897
|
+
},
|
|
898
|
+
{
|
|
899
|
+
// Serves per-page compiled MDX (program format) as real modules so
|
|
900
|
+
// the client hydrates the content island without `new Function`.
|
|
901
|
+
// client.ts imports `{ mdxModules } from "./mdx-manifest"`.
|
|
902
|
+
name: "mdx-hydrate",
|
|
903
|
+
setup(build2) {
|
|
904
|
+
const require2 = createRequire(import.meta.url);
|
|
905
|
+
const mdxModuleDeps = {
|
|
906
|
+
"react/jsx-runtime": require2.resolve("react/jsx-runtime"),
|
|
907
|
+
"react/jsx-dev-runtime": require2.resolve("react/jsx-dev-runtime"),
|
|
908
|
+
"@mdx-js/react": require2.resolve("@mdx-js/react")
|
|
909
|
+
};
|
|
910
|
+
build2.onResolve(
|
|
911
|
+
{ filter: /^(react\/jsx-runtime|react\/jsx-dev-runtime|@mdx-js\/react)$/ },
|
|
912
|
+
(args) => {
|
|
913
|
+
if (args.namespace !== "mdx-module") return;
|
|
914
|
+
return { path: mdxModuleDeps[args.path], namespace: "file" };
|
|
915
|
+
}
|
|
916
|
+
);
|
|
917
|
+
build2.onResolve({ filter: /^mdx-module:/ }, (args) => ({
|
|
918
|
+
path: args.path,
|
|
919
|
+
namespace: "mdx-module"
|
|
920
|
+
}));
|
|
921
|
+
build2.onLoad({ filter: /.*/, namespace: "mdx-module" }, (args) => {
|
|
922
|
+
const slug = args.path.slice("mdx-module:".length);
|
|
923
|
+
const contents = mdxSources[slug];
|
|
924
|
+
if (contents == null) {
|
|
925
|
+
return {
|
|
926
|
+
errors: [{ text: `unknown mdx module: ${slug}` }],
|
|
927
|
+
contents: "",
|
|
928
|
+
loader: "js"
|
|
929
|
+
};
|
|
930
|
+
}
|
|
931
|
+
return { contents, loader: "js" };
|
|
932
|
+
});
|
|
933
|
+
build2.onResolve({ filter: /mdx-manifest$/ }, (args) => ({
|
|
934
|
+
path: args.path,
|
|
935
|
+
namespace: "mdx-manifest"
|
|
936
|
+
}));
|
|
937
|
+
build2.onLoad({ filter: /.*/, namespace: "mdx-manifest" }, () => {
|
|
938
|
+
const slugs = Object.keys(mdxSources).sort();
|
|
939
|
+
const imports = slugs.map((slug, i) => {
|
|
940
|
+
const key = slug.replace(/["\\]/g, "");
|
|
941
|
+
return `import * as _mdx${i} from "mdx-module:${key}";`;
|
|
942
|
+
}).join("\n");
|
|
943
|
+
const map = slugs.map((slug, i) => `${JSON.stringify(slug)}: _mdx${i}`).join(", ");
|
|
944
|
+
return {
|
|
945
|
+
contents: `${imports}
|
|
946
|
+
export const mdxModules = { ${map} };
|
|
947
|
+
`,
|
|
948
|
+
loader: "js"
|
|
949
|
+
};
|
|
950
|
+
});
|
|
951
|
+
}
|
|
898
952
|
}
|
|
899
953
|
]
|
|
900
954
|
});
|
|
@@ -915,10 +969,196 @@ async function buildClientBundle() {
|
|
|
915
969
|
return { js: jsFile, css: cssFile };
|
|
916
970
|
}
|
|
917
971
|
|
|
972
|
+
// .docu/node/git.ts
|
|
973
|
+
import { execFile as execFile2 } from "node:child_process";
|
|
974
|
+
import { stat } from "node:fs/promises";
|
|
975
|
+
function runGit(args) {
|
|
976
|
+
return new Promise((resolve4, reject) => {
|
|
977
|
+
execFile2("git", args, { maxBuffer: 16 * 1024 * 1024 }, (err, stdout) => {
|
|
978
|
+
if (err) reject(err);
|
|
979
|
+
else resolve4(stdout);
|
|
980
|
+
});
|
|
981
|
+
});
|
|
982
|
+
}
|
|
983
|
+
function sanitizePath(filePath) {
|
|
984
|
+
const cleanPath = filePath.replace(/^\//, "");
|
|
985
|
+
if (!cleanPath || !/^[a-zA-Z0-9\-_/.\s]+$/.test(cleanPath) || /(^|\/)\.\.($|\/)/.test(cleanPath))
|
|
986
|
+
return null;
|
|
987
|
+
return cleanPath;
|
|
988
|
+
}
|
|
989
|
+
async function getGitLastModified(filePath) {
|
|
990
|
+
const cleanPath = sanitizePath(filePath);
|
|
991
|
+
if (!cleanPath) return null;
|
|
992
|
+
try {
|
|
993
|
+
const text = await runGit(["log", "-1", "--format=%cI", "--", cleanPath]);
|
|
994
|
+
const date = text.trim();
|
|
995
|
+
return date || null;
|
|
996
|
+
} catch {
|
|
997
|
+
return null;
|
|
998
|
+
}
|
|
999
|
+
}
|
|
1000
|
+
async function getFilesystemMtime(filePath) {
|
|
1001
|
+
try {
|
|
1002
|
+
const stats = await stat(filePath);
|
|
1003
|
+
return stats.mtime.toISOString();
|
|
1004
|
+
} catch {
|
|
1005
|
+
return null;
|
|
1006
|
+
}
|
|
1007
|
+
}
|
|
1008
|
+
async function getGitLastModifiedBatch(filePaths) {
|
|
1009
|
+
const result = /* @__PURE__ */ new Map();
|
|
1010
|
+
if (filePaths.length === 0) return result;
|
|
1011
|
+
const safePaths = [];
|
|
1012
|
+
for (const fp of filePaths) {
|
|
1013
|
+
const cleanPath = sanitizePath(fp);
|
|
1014
|
+
if (!cleanPath) {
|
|
1015
|
+
console.warn(`[git] getGitLastModifiedBatch: skipping invalid path "${fp}"`);
|
|
1016
|
+
continue;
|
|
1017
|
+
}
|
|
1018
|
+
safePaths.push(cleanPath);
|
|
1019
|
+
}
|
|
1020
|
+
if (safePaths.length === 0) return result;
|
|
1021
|
+
try {
|
|
1022
|
+
const text = await runGit([
|
|
1023
|
+
"log",
|
|
1024
|
+
"--format=%cI",
|
|
1025
|
+
"--name-only",
|
|
1026
|
+
"--diff-filter=ACMR",
|
|
1027
|
+
...safePaths
|
|
1028
|
+
]);
|
|
1029
|
+
let currentDate = "";
|
|
1030
|
+
for (const line of text.split("\n")) {
|
|
1031
|
+
const trimmed = line.trim();
|
|
1032
|
+
if (!trimmed) continue;
|
|
1033
|
+
if (/^\d{4}-\d{2}-\d{2}T/.test(trimmed)) {
|
|
1034
|
+
currentDate = trimmed;
|
|
1035
|
+
} else if (currentDate && !result.has(trimmed)) {
|
|
1036
|
+
result.set(trimmed, currentDate);
|
|
1037
|
+
}
|
|
1038
|
+
}
|
|
1039
|
+
} catch (err) {
|
|
1040
|
+
console.error("Failed to get git last modified batch for", filePaths, err);
|
|
1041
|
+
}
|
|
1042
|
+
return result;
|
|
1043
|
+
}
|
|
1044
|
+
|
|
1045
|
+
// .docu/node/mdx.ts
|
|
1046
|
+
import React from "react";
|
|
1047
|
+
import { z } from "zod";
|
|
1048
|
+
import {
|
|
1049
|
+
serialize,
|
|
1050
|
+
extractTocsFromRawMdx,
|
|
1051
|
+
extractFrontmatterWithContent,
|
|
1052
|
+
createDefaultRehypePlugins,
|
|
1053
|
+
createDefaultRemarkPlugins,
|
|
1054
|
+
MDXRemote
|
|
1055
|
+
} from "@docubook/core";
|
|
1056
|
+
import { createMdxComponents } from "@docubook/markdown";
|
|
1057
|
+
function appendHtml(value) {
|
|
1058
|
+
if (typeof value !== "string") return null;
|
|
1059
|
+
if (/^https?:\/\//.test(value)) return null;
|
|
1060
|
+
if (!value.startsWith("/docs/")) return null;
|
|
1061
|
+
if (value.includes("#")) return null;
|
|
1062
|
+
if (value.endsWith(".html")) return null;
|
|
1063
|
+
return `${value}.html`;
|
|
1064
|
+
}
|
|
1065
|
+
function rehypeDocsHtmlLinks() {
|
|
1066
|
+
return (tree) => {
|
|
1067
|
+
function walk(node) {
|
|
1068
|
+
if (node.type === "element" && node.tagName === "a") {
|
|
1069
|
+
const fixed = appendHtml(node.properties?.href);
|
|
1070
|
+
if (fixed) node.properties.href = fixed;
|
|
1071
|
+
}
|
|
1072
|
+
if (node.children) {
|
|
1073
|
+
for (const child of node.children) walk(child);
|
|
1074
|
+
}
|
|
1075
|
+
}
|
|
1076
|
+
walk(tree);
|
|
1077
|
+
return tree;
|
|
1078
|
+
};
|
|
1079
|
+
}
|
|
1080
|
+
function remarkMdxJsxDocsHtmlLinks() {
|
|
1081
|
+
return (tree) => {
|
|
1082
|
+
function walk(node) {
|
|
1083
|
+
if ((node.type === "mdxJsxFlowElement" || node.type === "mdxJsxTextElement") && node.attributes) {
|
|
1084
|
+
for (const attr of node.attributes) {
|
|
1085
|
+
if (attr.type === "mdxJsxAttribute" && attr.name === "href") {
|
|
1086
|
+
const fixed = appendHtml(attr.value);
|
|
1087
|
+
if (fixed) attr.value = fixed;
|
|
1088
|
+
}
|
|
1089
|
+
}
|
|
1090
|
+
}
|
|
1091
|
+
if (node.children) {
|
|
1092
|
+
for (const child of node.children) walk(child);
|
|
1093
|
+
}
|
|
1094
|
+
}
|
|
1095
|
+
walk(tree);
|
|
1096
|
+
return tree;
|
|
1097
|
+
};
|
|
1098
|
+
}
|
|
1099
|
+
var frontmatterSchema = z.object({
|
|
1100
|
+
title: z.coerce.string().optional(),
|
|
1101
|
+
description: z.coerce.string().optional(),
|
|
1102
|
+
image: z.coerce.string().optional(),
|
|
1103
|
+
date: z.coerce.string().optional()
|
|
1104
|
+
});
|
|
1105
|
+
function frontmatterField(frontmatter, key) {
|
|
1106
|
+
return typeof frontmatter[key] === "string" ? frontmatter[key] : "";
|
|
1107
|
+
}
|
|
1108
|
+
async function serializeWithDocPlugins(rawMdx, opts = {}) {
|
|
1109
|
+
const { strippedContent } = extractFrontmatterWithContent(
|
|
1110
|
+
rawMdx,
|
|
1111
|
+
opts.frontmatterSchema
|
|
1112
|
+
);
|
|
1113
|
+
const defaultRemark = createDefaultRemarkPlugins();
|
|
1114
|
+
const defaultRehype = createDefaultRehypePlugins();
|
|
1115
|
+
const finalRemark = [...defaultRemark, remarkMdxJsxDocsHtmlLinks, ...opts.remarkPlugins ?? []];
|
|
1116
|
+
const finalRehype = [...defaultRehype, rehypeDocsHtmlLinks, ...opts.rehypePlugins ?? []];
|
|
1117
|
+
return serialize(strippedContent, {
|
|
1118
|
+
outputFormat: opts.outputFormat,
|
|
1119
|
+
format: "md",
|
|
1120
|
+
mdxOptions: {
|
|
1121
|
+
rehypePlugins: finalRehype,
|
|
1122
|
+
remarkPlugins: finalRemark
|
|
1123
|
+
}
|
|
1124
|
+
});
|
|
1125
|
+
}
|
|
1126
|
+
async function compileMdx(rawMdx, filePath, gitDates, remarkPlugins, rehypePlugins, frontmatterSchema2) {
|
|
1127
|
+
const tocs = extractTocsFromRawMdx(rawMdx);
|
|
1128
|
+
const { frontmatter } = extractFrontmatterWithContent(rawMdx, frontmatterSchema2);
|
|
1129
|
+
const serialized = await serializeWithDocPlugins(rawMdx, {
|
|
1130
|
+
remarkPlugins,
|
|
1131
|
+
rehypePlugins,
|
|
1132
|
+
frontmatterSchema: frontmatterSchema2
|
|
1133
|
+
});
|
|
1134
|
+
const components = createMdxComponents();
|
|
1135
|
+
const content = React.createElement(MDXRemote, {
|
|
1136
|
+
compiledSource: serialized.compiledSource,
|
|
1137
|
+
scope: {},
|
|
1138
|
+
frontmatter: {},
|
|
1139
|
+
components
|
|
1140
|
+
});
|
|
1141
|
+
const date = frontmatter.date || gitDates?.get(filePath) || await getGitLastModified(filePath) || await getFilesystemMtime(filePath) || void 0;
|
|
1142
|
+
return {
|
|
1143
|
+
content,
|
|
1144
|
+
compiledSource: serialized.compiledSource,
|
|
1145
|
+
frontmatter: { ...frontmatter, date },
|
|
1146
|
+
tocs
|
|
1147
|
+
};
|
|
1148
|
+
}
|
|
1149
|
+
async function compileMdxModule(rawMdx, remarkPlugins, rehypePlugins) {
|
|
1150
|
+
const serialized = await serializeWithDocPlugins(rawMdx, {
|
|
1151
|
+
outputFormat: "program",
|
|
1152
|
+
remarkPlugins,
|
|
1153
|
+
rehypePlugins
|
|
1154
|
+
});
|
|
1155
|
+
return serialized.compiledSource;
|
|
1156
|
+
}
|
|
1157
|
+
|
|
918
1158
|
// .docu/node/search-indexer.ts
|
|
919
1159
|
import { readFile as readFile2, writeFile as writeFile2, mkdir as mkdir2 } from "node:fs/promises";
|
|
920
1160
|
import { resolve as resolve3, join as join3 } from "node:path";
|
|
921
|
-
import { extractFrontmatterWithContent } from "@docubook/core";
|
|
1161
|
+
import { extractFrontmatterWithContent as extractFrontmatterWithContent2 } from "@docubook/core";
|
|
922
1162
|
var docuConfig = loadDocuConfig();
|
|
923
1163
|
function getSectionTitle(filePath) {
|
|
924
1164
|
const parts = filePath.split("/");
|
|
@@ -943,11 +1183,11 @@ function stripJsx(content) {
|
|
|
943
1183
|
return result;
|
|
944
1184
|
}
|
|
945
1185
|
function extractRecords(filePath, raw) {
|
|
946
|
-
const { frontmatter, strippedContent: content } =
|
|
1186
|
+
const { frontmatter, strippedContent: content } = extractFrontmatterWithContent2(raw);
|
|
947
1187
|
const records = [];
|
|
948
1188
|
const url = docsHtmlHref(`/docs/${filePath}`);
|
|
949
1189
|
const lvl0 = getSectionTitle(filePath);
|
|
950
|
-
const lvl1 = frontmatter
|
|
1190
|
+
const lvl1 = frontmatterField(frontmatter, "title") || null;
|
|
951
1191
|
const hierarchy = {
|
|
952
1192
|
lvl0,
|
|
953
1193
|
lvl1,
|
|
@@ -961,7 +1201,7 @@ function extractRecords(filePath, raw) {
|
|
|
961
1201
|
records.push({
|
|
962
1202
|
url,
|
|
963
1203
|
hierarchy: { ...hierarchy },
|
|
964
|
-
content: frontmatter
|
|
1204
|
+
content: frontmatterField(frontmatter, "description") || null,
|
|
965
1205
|
type: "lvl1"
|
|
966
1206
|
});
|
|
967
1207
|
}
|
|
@@ -1071,161 +1311,6 @@ function captureException(err, context) {
|
|
|
1071
1311
|
sentry.captureException(err, context ? { extra: context } : void 0);
|
|
1072
1312
|
}
|
|
1073
1313
|
|
|
1074
|
-
// .docu/node/git.ts
|
|
1075
|
-
import { execFile as execFile2 } from "node:child_process";
|
|
1076
|
-
import { stat } from "node:fs/promises";
|
|
1077
|
-
function runGit(args) {
|
|
1078
|
-
return new Promise((resolve4, reject) => {
|
|
1079
|
-
execFile2("git", args, { maxBuffer: 16 * 1024 * 1024 }, (err, stdout) => {
|
|
1080
|
-
if (err) reject(err);
|
|
1081
|
-
else resolve4(stdout);
|
|
1082
|
-
});
|
|
1083
|
-
});
|
|
1084
|
-
}
|
|
1085
|
-
function sanitizePath(filePath) {
|
|
1086
|
-
const cleanPath = filePath.replace(/^\//, "");
|
|
1087
|
-
if (!cleanPath || !/^[a-zA-Z0-9\-_/.\s]+$/.test(cleanPath) || /(^|\/)\.\.($|\/)/.test(cleanPath))
|
|
1088
|
-
return null;
|
|
1089
|
-
return cleanPath;
|
|
1090
|
-
}
|
|
1091
|
-
async function getGitLastModified(filePath) {
|
|
1092
|
-
const cleanPath = sanitizePath(filePath);
|
|
1093
|
-
if (!cleanPath) return null;
|
|
1094
|
-
try {
|
|
1095
|
-
const text = await runGit(["log", "-1", "--format=%cI", "--", cleanPath]);
|
|
1096
|
-
const date = text.trim();
|
|
1097
|
-
return date || null;
|
|
1098
|
-
} catch {
|
|
1099
|
-
return null;
|
|
1100
|
-
}
|
|
1101
|
-
}
|
|
1102
|
-
async function getFilesystemMtime(filePath) {
|
|
1103
|
-
try {
|
|
1104
|
-
const stats = await stat(filePath);
|
|
1105
|
-
return stats.mtime.toISOString();
|
|
1106
|
-
} catch {
|
|
1107
|
-
return null;
|
|
1108
|
-
}
|
|
1109
|
-
}
|
|
1110
|
-
async function getGitLastModifiedBatch(filePaths) {
|
|
1111
|
-
const result = /* @__PURE__ */ new Map();
|
|
1112
|
-
if (filePaths.length === 0) return result;
|
|
1113
|
-
const safePaths = [];
|
|
1114
|
-
for (const fp of filePaths) {
|
|
1115
|
-
const cleanPath = sanitizePath(fp);
|
|
1116
|
-
if (!cleanPath) {
|
|
1117
|
-
console.warn(`[git] getGitLastModifiedBatch: skipping invalid path "${fp}"`);
|
|
1118
|
-
continue;
|
|
1119
|
-
}
|
|
1120
|
-
safePaths.push(cleanPath);
|
|
1121
|
-
}
|
|
1122
|
-
if (safePaths.length === 0) return result;
|
|
1123
|
-
try {
|
|
1124
|
-
const text = await runGit([
|
|
1125
|
-
"log",
|
|
1126
|
-
"--format=%cI",
|
|
1127
|
-
"--name-only",
|
|
1128
|
-
"--diff-filter=ACMR",
|
|
1129
|
-
...safePaths
|
|
1130
|
-
]);
|
|
1131
|
-
let currentDate = "";
|
|
1132
|
-
for (const line of text.split("\n")) {
|
|
1133
|
-
const trimmed = line.trim();
|
|
1134
|
-
if (!trimmed) continue;
|
|
1135
|
-
if (/^\d{4}-\d{2}-\d{2}T/.test(trimmed)) {
|
|
1136
|
-
currentDate = trimmed;
|
|
1137
|
-
} else if (currentDate && !result.has(trimmed)) {
|
|
1138
|
-
result.set(trimmed, currentDate);
|
|
1139
|
-
}
|
|
1140
|
-
}
|
|
1141
|
-
} catch (err) {
|
|
1142
|
-
console.error("Failed to get git last modified batch for", filePaths, err);
|
|
1143
|
-
}
|
|
1144
|
-
return result;
|
|
1145
|
-
}
|
|
1146
|
-
|
|
1147
|
-
// .docu/node/mdx.ts
|
|
1148
|
-
import React from "react";
|
|
1149
|
-
import {
|
|
1150
|
-
serialize,
|
|
1151
|
-
extractTocsFromRawMdx,
|
|
1152
|
-
extractFrontmatterWithContent as extractFrontmatterWithContent2,
|
|
1153
|
-
createDefaultRehypePlugins,
|
|
1154
|
-
createDefaultRemarkPlugins,
|
|
1155
|
-
MDXRemote
|
|
1156
|
-
} from "@docubook/core";
|
|
1157
|
-
import { createMdxComponents } from "@docubook/mdx-content";
|
|
1158
|
-
function appendHtml(value) {
|
|
1159
|
-
if (typeof value !== "string") return null;
|
|
1160
|
-
if (/^https?:\/\//.test(value)) return null;
|
|
1161
|
-
if (!value.startsWith("/docs/")) return null;
|
|
1162
|
-
if (value.includes("#")) return null;
|
|
1163
|
-
if (value.endsWith(".html")) return null;
|
|
1164
|
-
return `${value}.html`;
|
|
1165
|
-
}
|
|
1166
|
-
function rehypeDocsHtmlLinks() {
|
|
1167
|
-
return (tree) => {
|
|
1168
|
-
function walk(node) {
|
|
1169
|
-
if (node.type === "element" && node.tagName === "a") {
|
|
1170
|
-
const fixed = appendHtml(node.properties?.href);
|
|
1171
|
-
if (fixed) node.properties.href = fixed;
|
|
1172
|
-
}
|
|
1173
|
-
if (node.children) {
|
|
1174
|
-
for (const child of node.children) walk(child);
|
|
1175
|
-
}
|
|
1176
|
-
}
|
|
1177
|
-
walk(tree);
|
|
1178
|
-
return tree;
|
|
1179
|
-
};
|
|
1180
|
-
}
|
|
1181
|
-
function remarkMdxJsxDocsHtmlLinks() {
|
|
1182
|
-
return (tree) => {
|
|
1183
|
-
function walk(node) {
|
|
1184
|
-
if ((node.type === "mdxJsxFlowElement" || node.type === "mdxJsxTextElement") && node.attributes) {
|
|
1185
|
-
for (const attr of node.attributes) {
|
|
1186
|
-
if (attr.type === "mdxJsxAttribute" && attr.name === "href") {
|
|
1187
|
-
const fixed = appendHtml(attr.value);
|
|
1188
|
-
if (fixed) attr.value = fixed;
|
|
1189
|
-
}
|
|
1190
|
-
}
|
|
1191
|
-
}
|
|
1192
|
-
if (node.children) {
|
|
1193
|
-
for (const child of node.children) walk(child);
|
|
1194
|
-
}
|
|
1195
|
-
}
|
|
1196
|
-
walk(tree);
|
|
1197
|
-
return tree;
|
|
1198
|
-
};
|
|
1199
|
-
}
|
|
1200
|
-
async function compileMdx(rawMdx, filePath, gitDates, remarkPlugins, rehypePlugins) {
|
|
1201
|
-
const tocs = extractTocsFromRawMdx(rawMdx);
|
|
1202
|
-
const { frontmatter, strippedContent } = extractFrontmatterWithContent2(rawMdx);
|
|
1203
|
-
const defaultRemark = createDefaultRemarkPlugins();
|
|
1204
|
-
const defaultRehype = createDefaultRehypePlugins();
|
|
1205
|
-
const finalRemark = [...defaultRemark, remarkMdxJsxDocsHtmlLinks, ...remarkPlugins ?? []];
|
|
1206
|
-
const finalRehype = [...defaultRehype, rehypeDocsHtmlLinks, ...rehypePlugins ?? []];
|
|
1207
|
-
const serialized = await serialize(strippedContent, {
|
|
1208
|
-
mdxOptions: {
|
|
1209
|
-
rehypePlugins: finalRehype,
|
|
1210
|
-
remarkPlugins: finalRemark
|
|
1211
|
-
}
|
|
1212
|
-
});
|
|
1213
|
-
const components = createMdxComponents();
|
|
1214
|
-
const content = React.createElement(MDXRemote, {
|
|
1215
|
-
compiledSource: serialized.compiledSource,
|
|
1216
|
-
scope: {},
|
|
1217
|
-
frontmatter: {},
|
|
1218
|
-
components
|
|
1219
|
-
});
|
|
1220
|
-
const date = frontmatter.date || gitDates?.get(filePath) || await getGitLastModified(filePath) || await getFilesystemMtime(filePath) || void 0;
|
|
1221
|
-
return {
|
|
1222
|
-
content,
|
|
1223
|
-
compiledSource: serialized.compiledSource,
|
|
1224
|
-
frontmatter: { ...frontmatter, date },
|
|
1225
|
-
tocs
|
|
1226
|
-
};
|
|
1227
|
-
}
|
|
1228
|
-
|
|
1229
1314
|
// .docu/pages/docs/[[...slug]].tsx
|
|
1230
1315
|
import { ChevronLeft, ChevronRight } from "lucide-react";
|
|
1231
1316
|
|
|
@@ -1248,6 +1333,9 @@ function DocsBreadcrumb({ paths }) {
|
|
|
1248
1333
|
}
|
|
1249
1334
|
|
|
1250
1335
|
// .docu/node/route.ts
|
|
1336
|
+
import { readFileSync as readFileSync2 } from "node:fs";
|
|
1337
|
+
import { join as join4 } from "node:path";
|
|
1338
|
+
import { extractFrontmatter } from "@docubook/core";
|
|
1251
1339
|
var docuConfig2 = loadDocuConfig();
|
|
1252
1340
|
var routes = resolveRoutes(docuConfig2.routes);
|
|
1253
1341
|
function flattenRoutes() {
|
|
@@ -1276,8 +1364,42 @@ function getRouteMap() {
|
|
|
1276
1364
|
routes.forEach((route) => traverse(route));
|
|
1277
1365
|
return map;
|
|
1278
1366
|
}
|
|
1367
|
+
var descriptionCache = /* @__PURE__ */ new Map();
|
|
1368
|
+
function readDescription(href) {
|
|
1369
|
+
const cached = descriptionCache.get(href);
|
|
1370
|
+
if (cached !== void 0) return cached;
|
|
1371
|
+
let description = "";
|
|
1372
|
+
const rel = href.replace(/^\/|$/g, "");
|
|
1373
|
+
for (const ext of [".mdx", ".md"]) {
|
|
1374
|
+
for (const file of [join4(DOCS_DIR, `${rel}${ext}`), join4(DOCS_DIR, `${rel}/index${ext}`)]) {
|
|
1375
|
+
try {
|
|
1376
|
+
const fm = extractFrontmatter(readFileSync2(file, "utf-8"));
|
|
1377
|
+
description = typeof fm.description === "string" ? fm.description : "";
|
|
1378
|
+
if (description) break;
|
|
1379
|
+
} catch {
|
|
1380
|
+
}
|
|
1381
|
+
}
|
|
1382
|
+
if (description) break;
|
|
1383
|
+
}
|
|
1384
|
+
descriptionCache.set(href, description);
|
|
1385
|
+
return description;
|
|
1386
|
+
}
|
|
1279
1387
|
function getPreviousNext(pathname) {
|
|
1280
1388
|
const normalizedPath = pathname.replace(/^\/|$/g, "");
|
|
1389
|
+
if (normalizedPath === "docs" || normalizedPath === "") {
|
|
1390
|
+
const paths2 = flattenRoutes();
|
|
1391
|
+
const routeMap2 = getRouteMap();
|
|
1392
|
+
const first = paths2[0];
|
|
1393
|
+
if (!first) return { prev: null, next: null };
|
|
1394
|
+
return {
|
|
1395
|
+
prev: null,
|
|
1396
|
+
next: {
|
|
1397
|
+
href: first,
|
|
1398
|
+
title: routeMap2.get(first) || "",
|
|
1399
|
+
description: readDescription(first)
|
|
1400
|
+
}
|
|
1401
|
+
};
|
|
1402
|
+
}
|
|
1281
1403
|
const paths = flattenRoutes();
|
|
1282
1404
|
const index = paths.findIndex((href) => href === `/${normalizedPath}` || href === normalizedPath);
|
|
1283
1405
|
if (index === -1) {
|
|
@@ -1288,7 +1410,11 @@ function getPreviousNext(pathname) {
|
|
|
1288
1410
|
const nextHref = index < paths.length - 1 ? paths[index + 1] : null;
|
|
1289
1411
|
return {
|
|
1290
1412
|
prev: prevHref ? { href: prevHref, title: routeMap.get(prevHref) || "" } : null,
|
|
1291
|
-
next: nextHref ? {
|
|
1413
|
+
next: nextHref ? {
|
|
1414
|
+
href: nextHref,
|
|
1415
|
+
title: routeMap.get(nextHref) || "",
|
|
1416
|
+
description: readDescription(nextHref)
|
|
1417
|
+
} : null
|
|
1292
1418
|
};
|
|
1293
1419
|
}
|
|
1294
1420
|
|
|
@@ -1310,7 +1436,11 @@ function Pagination({
|
|
|
1310
1436
|
PaginationDocs,
|
|
1311
1437
|
{
|
|
1312
1438
|
prev: prev ? { href: docsHtmlHref(`/docs${prev.href}`), title: prev.title } : void 0,
|
|
1313
|
-
next: next ? {
|
|
1439
|
+
next: next ? {
|
|
1440
|
+
href: docsHtmlHref(`/docs${next.href}`),
|
|
1441
|
+
title: next.title,
|
|
1442
|
+
description: next.description
|
|
1443
|
+
} : void 0,
|
|
1314
1444
|
className,
|
|
1315
1445
|
prevIcon,
|
|
1316
1446
|
nextIcon,
|
|
@@ -1322,7 +1452,7 @@ function Pagination({
|
|
|
1322
1452
|
// .docu/components/Typography.tsx
|
|
1323
1453
|
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
1324
1454
|
function Typography({ children }) {
|
|
1325
|
-
return /* @__PURE__ */ jsx3("div", { className: "prose prose-zinc dark:prose-invert prose-code:font-code dark:prose-code:bg-stone-900/25 prose-code:bg-stone-50 prose-pre:bg-background max-lg:prose-headings:scroll-mt-
|
|
1455
|
+
return /* @__PURE__ */ jsx3("div", { className: "prose prose-zinc dark:prose-invert prose-code:font-code dark:prose-code:bg-stone-900/25 prose-code:bg-stone-50 prose-pre:bg-background max-lg:prose-headings:scroll-mt-16 prose-headings:scroll-mt-4 prose-code:text-sm prose-code:leading-6 dark:prose-code:text-white prose-code:text-stone-800 prose-code:p-1 prose-code:rounded-md prose-code:border prose-img:rounded-md prose-img:border prose-code:before:content-none prose-code:after:content-none prose-code:px-1.5 prose-code:overflow-x-auto prose-img:my-3 prose-h2:my-4 prose-h2:mt-8 w-full max-w-full! pt-2", children });
|
|
1326
1456
|
}
|
|
1327
1457
|
|
|
1328
1458
|
// .docu/components/EditWith.tsx
|
|
@@ -1586,12 +1716,19 @@ function Toc({ tocs }) {
|
|
|
1586
1716
|
useEffect2(() => {
|
|
1587
1717
|
activeIdRef.current = activeId;
|
|
1588
1718
|
}, [activeId]);
|
|
1719
|
+
const getAnchorOffset = useCallback2(() => {
|
|
1720
|
+
if (typeof window === "undefined") return 100;
|
|
1721
|
+
const first = tocs[0] ? document.getElementById(tocs[0].href.slice(1)) : null;
|
|
1722
|
+
const margin = first ? parseFloat(getComputedStyle(first).scrollMarginTop) : 0;
|
|
1723
|
+
return margin || 100;
|
|
1724
|
+
}, [tocs]);
|
|
1589
1725
|
useEffect2(() => {
|
|
1590
|
-
if (typeof
|
|
1726
|
+
if (typeof window === "undefined" || window.innerWidth < 1024) return;
|
|
1727
|
+
if (!tocs.length) return;
|
|
1591
1728
|
const isDesktop = window.innerWidth >= 1024;
|
|
1592
1729
|
const container = isDesktop ? document.getElementById("scroll-container") : null;
|
|
1593
1730
|
const scrollTarget = container || window;
|
|
1594
|
-
const offset =
|
|
1731
|
+
const offset = getAnchorOffset();
|
|
1595
1732
|
const handleScroll = () => {
|
|
1596
1733
|
if (clickedIdRef.current) return;
|
|
1597
1734
|
let currentId = null;
|
|
@@ -1625,7 +1762,7 @@ function Toc({ tocs }) {
|
|
|
1625
1762
|
scrollTarget.removeEventListener("scroll", listener);
|
|
1626
1763
|
if (throttleTimer) clearTimeout(throttleTimer);
|
|
1627
1764
|
};
|
|
1628
|
-
}, [tocs]);
|
|
1765
|
+
}, [tocs, getAnchorOffset]);
|
|
1629
1766
|
const handleLinkClick = useCallback2((id) => {
|
|
1630
1767
|
clickedIdRef.current = id;
|
|
1631
1768
|
setActiveId(id);
|
|
@@ -1647,7 +1784,7 @@ function Toc({ tocs }) {
|
|
|
1647
1784
|
/* @__PURE__ */ jsx8("h3", { className: "text-sm font-medium", children: "On this page" })
|
|
1648
1785
|
] }),
|
|
1649
1786
|
/* @__PURE__ */ jsx8("div", { className: "relative", children: /* @__PURE__ */ jsxs5("div", { className: "relative text-sm", children: [
|
|
1650
|
-
/* @__PURE__ */ jsx8("div", { className: "bg-base-300 absolute
|
|
1787
|
+
/* @__PURE__ */ jsx8("div", { className: "bg-base-300 absolute top-0 left-0 h-full w-px" }),
|
|
1651
1788
|
/* @__PURE__ */ jsx8("div", { className: "flex flex-col", children: tocs.map(({ href, level, text }) => {
|
|
1652
1789
|
const id = href.slice(1);
|
|
1653
1790
|
const isActive = activeId === id;
|
|
@@ -1697,14 +1834,29 @@ function Toc({ tocs }) {
|
|
|
1697
1834
|
e.preventDefault();
|
|
1698
1835
|
handleLinkClick(id);
|
|
1699
1836
|
const el = document.getElementById(id);
|
|
1700
|
-
if (el)
|
|
1837
|
+
if (el) {
|
|
1838
|
+
const offset = getAnchorOffset();
|
|
1839
|
+
const scroller = window.innerWidth >= 1024 ? document.getElementById("scroll-container") : null;
|
|
1840
|
+
const elTop = el.getBoundingClientRect().top;
|
|
1841
|
+
if (scroller) {
|
|
1842
|
+
scroller.scrollTo({
|
|
1843
|
+
top: elTop - scroller.getBoundingClientRect().top + scroller.scrollTop - offset,
|
|
1844
|
+
behavior: "smooth"
|
|
1845
|
+
});
|
|
1846
|
+
} else {
|
|
1847
|
+
window.scrollTo({
|
|
1848
|
+
top: elTop + window.scrollY - offset,
|
|
1849
|
+
behavior: "smooth"
|
|
1850
|
+
});
|
|
1851
|
+
}
|
|
1852
|
+
}
|
|
1701
1853
|
},
|
|
1702
1854
|
className: cn(
|
|
1703
1855
|
"flex flex-1 items-center py-2 transition-all duration-200",
|
|
1704
1856
|
isActive ? "text-primary font-medium" : "text-base-content/60 hover:text-base-content"
|
|
1705
1857
|
),
|
|
1706
1858
|
style: { paddingLeft: `${levelPadding + 6}px` },
|
|
1707
|
-
children: /* @__PURE__ */ jsx8("span", { className: "line-clamp-2 break-words
|
|
1859
|
+
children: /* @__PURE__ */ jsx8("span", { className: "line-clamp-2 text-sm break-words", children: text })
|
|
1708
1860
|
}
|
|
1709
1861
|
)
|
|
1710
1862
|
]
|
|
@@ -1728,6 +1880,7 @@ function DocsPage({
|
|
|
1728
1880
|
tocs,
|
|
1729
1881
|
filePath,
|
|
1730
1882
|
repoUrl,
|
|
1883
|
+
mdxSlug,
|
|
1731
1884
|
compiledSource
|
|
1732
1885
|
}) {
|
|
1733
1886
|
const pathname = slug.join("/");
|
|
@@ -1736,7 +1889,7 @@ function DocsPage({
|
|
|
1736
1889
|
"div",
|
|
1737
1890
|
{
|
|
1738
1891
|
id: "scroll-container",
|
|
1739
|
-
className: "bg-base-100 border-base-300
|
|
1892
|
+
className: "bg-base-100 border-base-300 relative flex w-full flex-col items-start rounded-b-3xl border shadow-md max-lg:scroll-p-54 lg:h-full lg:flex-row lg:overflow-y-auto lg:rounded-xl",
|
|
1740
1893
|
children: [
|
|
1741
1894
|
/* @__PURE__ */ jsx9(
|
|
1742
1895
|
"div",
|
|
@@ -1758,7 +1911,14 @@ function DocsPage({
|
|
|
1758
1911
|
/* @__PURE__ */ jsxs6(Typography, { children: [
|
|
1759
1912
|
/* @__PURE__ */ jsx9("h1", { className: "-mt-0.5 text-3xl", children: title }),
|
|
1760
1913
|
description && /* @__PURE__ */ jsx9("p", { className: "text-muted-foreground -mt-4 text-[16.5px]", children: description }),
|
|
1761
|
-
/* @__PURE__ */ jsx9(
|
|
1914
|
+
/* @__PURE__ */ jsx9(
|
|
1915
|
+
"div",
|
|
1916
|
+
{
|
|
1917
|
+
id: "mdx-content-island",
|
|
1918
|
+
"data-mdx-slug": mdxSlug,
|
|
1919
|
+
dangerouslySetInnerHTML: { __html: content }
|
|
1920
|
+
}
|
|
1921
|
+
),
|
|
1762
1922
|
compiledSource && /* @__PURE__ */ jsx9(
|
|
1763
1923
|
"script",
|
|
1764
1924
|
{
|
|
@@ -1842,8 +2002,8 @@ function renderActionButtonIcon(iconName, className) {
|
|
|
1842
2002
|
}
|
|
1843
2003
|
function ActionButton({ action }) {
|
|
1844
2004
|
const themeClasses = {
|
|
1845
|
-
primary: "bg-primary text-primary-
|
|
1846
|
-
secondary: "bg-secondary text-secondary-
|
|
2005
|
+
primary: "bg-primary text-primary-foreground hover:bg-primary/90",
|
|
2006
|
+
secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/90",
|
|
1847
2007
|
ghost: "bg-transparent text-muted-foreground border border-base-300 hover:bg-base-200"
|
|
1848
2008
|
};
|
|
1849
2009
|
const isExternal = isExternalLink(action.link);
|
|
@@ -1868,8 +2028,8 @@ function Hero({ hero, className }) {
|
|
|
1868
2028
|
const { tagline, headline, description, actions } = hero;
|
|
1869
2029
|
return /* @__PURE__ */ jsx12("div", { className: cn("mx-auto max-w-4xl px-6 py-32 sm:py-44", className), children: /* @__PURE__ */ jsxs8("div", { className: "text-center", children: [
|
|
1870
2030
|
tagline && /* @__PURE__ */ jsx12("p", { className: "text-primary mb-4 text-lg font-semibold", children: tagline }),
|
|
1871
|
-
/* @__PURE__ */ jsx12("h1", { className: "text-
|
|
1872
|
-
description && /* @__PURE__ */ jsx12("p", { className: "text-muted-foreground mt-8 text-
|
|
2031
|
+
/* @__PURE__ */ jsx12("h1", { className: "text-5xl font-semibold tracking-tight text-balance sm:text-7xl", children: headline }),
|
|
2032
|
+
description && /* @__PURE__ */ jsx12("p", { className: "text-muted-foreground mt-8 text-lg text-pretty sm:text-xl", children: description }),
|
|
1873
2033
|
actions && actions.length > 0 && /* @__PURE__ */ jsx12("div", { className: "mt-10 flex flex-wrap items-center justify-center gap-4", children: actions.map((action, index) => /* @__PURE__ */ jsx12(ActionButton, { action }, index)) })
|
|
1874
2034
|
] }) });
|
|
1875
2035
|
}
|
|
@@ -1956,7 +2116,7 @@ function IndexPage() {
|
|
|
1956
2116
|
description: meta.description
|
|
1957
2117
|
};
|
|
1958
2118
|
return /* @__PURE__ */ jsxs10("div", { className: "bg-base-100 relative isolate min-h-screen overflow-hidden", children: [
|
|
1959
|
-
/* @__PURE__ */ jsx14("div", { className: "absolute
|
|
2119
|
+
/* @__PURE__ */ jsx14("div", { className: "absolute top-4 right-4 z-10", id: "theme-island" }),
|
|
1960
2120
|
/* @__PURE__ */ jsx14(
|
|
1961
2121
|
"div",
|
|
1962
2122
|
{
|
|
@@ -2360,7 +2520,8 @@ function htmlShell(opts) {
|
|
|
2360
2520
|
themeCss,
|
|
2361
2521
|
depth = 0,
|
|
2362
2522
|
headExtra,
|
|
2363
|
-
bodyExtra
|
|
2523
|
+
bodyExtra,
|
|
2524
|
+
absoluteAssets = false
|
|
2364
2525
|
} = opts;
|
|
2365
2526
|
const nonceAttr = nonce ? ` nonce="${escapeHtml(nonce)}"` : "";
|
|
2366
2527
|
const themeStyle = themeCss ? `
|
|
@@ -2370,8 +2531,8 @@ function htmlShell(opts) {
|
|
|
2370
2531
|
const bodyInjection = bodyExtra?.length ? `
|
|
2371
2532
|
${bodyExtra.join("\n ")}` : "";
|
|
2372
2533
|
const depthPrefix = depth === 0 ? "" : "../".repeat(depth);
|
|
2373
|
-
const assetPrefix = depthPrefix + "assets/";
|
|
2374
|
-
const resolvePath = (path) => path.startsWith("/") ? depthPrefix + path.slice(1) : path;
|
|
2534
|
+
const assetPrefix = absoluteAssets ? "/assets/" : depthPrefix + "assets/";
|
|
2535
|
+
const resolvePath = (path) => absoluteAssets ? path : path.startsWith("/") ? depthPrefix + path.slice(1) : path;
|
|
2375
2536
|
let seoTags = "";
|
|
2376
2537
|
if (opts.seo) {
|
|
2377
2538
|
const s = opts.seo;
|
|
@@ -2452,11 +2613,13 @@ export {
|
|
|
2452
2613
|
BuildPluginBuilder,
|
|
2453
2614
|
computeInlineThemeCss,
|
|
2454
2615
|
buildClientBundle,
|
|
2616
|
+
getGitLastModifiedBatch,
|
|
2617
|
+
frontmatterField,
|
|
2618
|
+
compileMdx,
|
|
2619
|
+
compileMdxModule,
|
|
2455
2620
|
generateSearchIndex,
|
|
2456
2621
|
initSentry,
|
|
2457
2622
|
captureException,
|
|
2458
|
-
getGitLastModifiedBatch,
|
|
2459
|
-
compileMdx,
|
|
2460
2623
|
DocsPage,
|
|
2461
2624
|
NotFoundPage,
|
|
2462
2625
|
IndexPage,
|