@docubook/flame 1.7.2 → 2.0.0-alpha.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/.docu/components/Context.tsx +1 -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 +51 -5
- 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-WR24HDUT.js} +3 -3
- package/.docu/lib/build.node.js +3 -3
- package/.docu/lib/{chunk-HRO7ONJQ.js → chunk-2EYRWRDP.js} +66 -26
- package/.docu/lib/{chunk-PJIJEPNR.js → chunk-AJV2GEDF.js} +5 -4
- package/.docu/lib/{chunk-KMDGSD57.js → chunk-KEWRVASF.js} +3 -3
- package/.docu/lib/{chunk-B6LGUADD.js → chunk-QPF4DPZQ.js} +294 -177
- package/.docu/lib/chunk-UISOJ4RW.js +114 -0
- package/.docu/lib/{chunk-DITXUPUV.js → chunk-VPV7KP7K.js} +56 -9
- package/.docu/lib/{chunk-SPHVBXRR.js → chunk-X7KPVCDN.js} +6 -6
- 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 +72 -26
- package/.docu/node/build.ts +67 -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/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/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 +28 -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 +29 -20
- package/README.md +7 -48
- package/bin/cli.js +25 -7
- package/package.json +7 -6
- package/template/README.md +7 -48
|
@@ -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
|
|
|
@@ -1322,7 +1407,7 @@ function Pagination({
|
|
|
1322
1407
|
// .docu/components/Typography.tsx
|
|
1323
1408
|
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
1324
1409
|
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-
|
|
1410
|
+
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
1411
|
}
|
|
1327
1412
|
|
|
1328
1413
|
// .docu/components/EditWith.tsx
|
|
@@ -1586,12 +1671,19 @@ function Toc({ tocs }) {
|
|
|
1586
1671
|
useEffect2(() => {
|
|
1587
1672
|
activeIdRef.current = activeId;
|
|
1588
1673
|
}, [activeId]);
|
|
1674
|
+
function getAnchorOffset() {
|
|
1675
|
+
if (typeof window === "undefined") return 100;
|
|
1676
|
+
const first = tocs[0] ? document.getElementById(tocs[0].href.slice(1)) : null;
|
|
1677
|
+
const margin = first ? parseFloat(getComputedStyle(first).scrollMarginTop) : 0;
|
|
1678
|
+
return margin || 100;
|
|
1679
|
+
}
|
|
1589
1680
|
useEffect2(() => {
|
|
1590
|
-
if (typeof
|
|
1681
|
+
if (typeof window === "undefined" || window.innerWidth < 1024) return;
|
|
1682
|
+
if (!tocs.length) return;
|
|
1591
1683
|
const isDesktop = window.innerWidth >= 1024;
|
|
1592
1684
|
const container = isDesktop ? document.getElementById("scroll-container") : null;
|
|
1593
1685
|
const scrollTarget = container || window;
|
|
1594
|
-
const offset =
|
|
1686
|
+
const offset = getAnchorOffset();
|
|
1595
1687
|
const handleScroll = () => {
|
|
1596
1688
|
if (clickedIdRef.current) return;
|
|
1597
1689
|
let currentId = null;
|
|
@@ -1647,7 +1739,7 @@ function Toc({ tocs }) {
|
|
|
1647
1739
|
/* @__PURE__ */ jsx8("h3", { className: "text-sm font-medium", children: "On this page" })
|
|
1648
1740
|
] }),
|
|
1649
1741
|
/* @__PURE__ */ jsx8("div", { className: "relative", children: /* @__PURE__ */ jsxs5("div", { className: "relative text-sm", children: [
|
|
1650
|
-
/* @__PURE__ */ jsx8("div", { className: "bg-base-300 absolute
|
|
1742
|
+
/* @__PURE__ */ jsx8("div", { className: "bg-base-300 absolute top-0 left-0 h-full w-px" }),
|
|
1651
1743
|
/* @__PURE__ */ jsx8("div", { className: "flex flex-col", children: tocs.map(({ href, level, text }) => {
|
|
1652
1744
|
const id = href.slice(1);
|
|
1653
1745
|
const isActive = activeId === id;
|
|
@@ -1697,14 +1789,29 @@ function Toc({ tocs }) {
|
|
|
1697
1789
|
e.preventDefault();
|
|
1698
1790
|
handleLinkClick(id);
|
|
1699
1791
|
const el = document.getElementById(id);
|
|
1700
|
-
if (el)
|
|
1792
|
+
if (el) {
|
|
1793
|
+
const offset = getAnchorOffset();
|
|
1794
|
+
const scroller = window.innerWidth >= 1024 ? document.getElementById("scroll-container") : null;
|
|
1795
|
+
const elTop = el.getBoundingClientRect().top;
|
|
1796
|
+
if (scroller) {
|
|
1797
|
+
scroller.scrollTo({
|
|
1798
|
+
top: elTop - scroller.getBoundingClientRect().top + scroller.scrollTop - offset,
|
|
1799
|
+
behavior: "smooth"
|
|
1800
|
+
});
|
|
1801
|
+
} else {
|
|
1802
|
+
window.scrollTo({
|
|
1803
|
+
top: elTop + window.scrollY - offset,
|
|
1804
|
+
behavior: "smooth"
|
|
1805
|
+
});
|
|
1806
|
+
}
|
|
1807
|
+
}
|
|
1701
1808
|
},
|
|
1702
1809
|
className: cn(
|
|
1703
1810
|
"flex flex-1 items-center py-2 transition-all duration-200",
|
|
1704
1811
|
isActive ? "text-primary font-medium" : "text-base-content/60 hover:text-base-content"
|
|
1705
1812
|
),
|
|
1706
1813
|
style: { paddingLeft: `${levelPadding + 6}px` },
|
|
1707
|
-
children: /* @__PURE__ */ jsx8("span", { className: "line-clamp-2 break-words
|
|
1814
|
+
children: /* @__PURE__ */ jsx8("span", { className: "line-clamp-2 text-sm break-words", children: text })
|
|
1708
1815
|
}
|
|
1709
1816
|
)
|
|
1710
1817
|
]
|
|
@@ -1728,6 +1835,7 @@ function DocsPage({
|
|
|
1728
1835
|
tocs,
|
|
1729
1836
|
filePath,
|
|
1730
1837
|
repoUrl,
|
|
1838
|
+
mdxSlug,
|
|
1731
1839
|
compiledSource
|
|
1732
1840
|
}) {
|
|
1733
1841
|
const pathname = slug.join("/");
|
|
@@ -1736,7 +1844,7 @@ function DocsPage({
|
|
|
1736
1844
|
"div",
|
|
1737
1845
|
{
|
|
1738
1846
|
id: "scroll-container",
|
|
1739
|
-
className: "bg-base-100 border-base-300
|
|
1847
|
+
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
1848
|
children: [
|
|
1741
1849
|
/* @__PURE__ */ jsx9(
|
|
1742
1850
|
"div",
|
|
@@ -1758,7 +1866,14 @@ function DocsPage({
|
|
|
1758
1866
|
/* @__PURE__ */ jsxs6(Typography, { children: [
|
|
1759
1867
|
/* @__PURE__ */ jsx9("h1", { className: "-mt-0.5 text-3xl", children: title }),
|
|
1760
1868
|
description && /* @__PURE__ */ jsx9("p", { className: "text-muted-foreground -mt-4 text-[16.5px]", children: description }),
|
|
1761
|
-
/* @__PURE__ */ jsx9(
|
|
1869
|
+
/* @__PURE__ */ jsx9(
|
|
1870
|
+
"div",
|
|
1871
|
+
{
|
|
1872
|
+
id: "mdx-content-island",
|
|
1873
|
+
"data-mdx-slug": mdxSlug,
|
|
1874
|
+
dangerouslySetInnerHTML: { __html: content }
|
|
1875
|
+
}
|
|
1876
|
+
),
|
|
1762
1877
|
compiledSource && /* @__PURE__ */ jsx9(
|
|
1763
1878
|
"script",
|
|
1764
1879
|
{
|
|
@@ -1842,8 +1957,8 @@ function renderActionButtonIcon(iconName, className) {
|
|
|
1842
1957
|
}
|
|
1843
1958
|
function ActionButton({ action }) {
|
|
1844
1959
|
const themeClasses = {
|
|
1845
|
-
primary: "bg-primary text-primary-
|
|
1846
|
-
secondary: "bg-secondary text-secondary-
|
|
1960
|
+
primary: "bg-primary text-primary-foreground hover:bg-primary/90",
|
|
1961
|
+
secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/90",
|
|
1847
1962
|
ghost: "bg-transparent text-muted-foreground border border-base-300 hover:bg-base-200"
|
|
1848
1963
|
};
|
|
1849
1964
|
const isExternal = isExternalLink(action.link);
|
|
@@ -1868,8 +1983,8 @@ function Hero({ hero, className }) {
|
|
|
1868
1983
|
const { tagline, headline, description, actions } = hero;
|
|
1869
1984
|
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
1985
|
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-
|
|
1986
|
+
/* @__PURE__ */ jsx12("h1", { className: "text-5xl font-semibold tracking-tight text-balance sm:text-7xl", children: headline }),
|
|
1987
|
+
description && /* @__PURE__ */ jsx12("p", { className: "text-muted-foreground mt-8 text-lg text-pretty sm:text-xl", children: description }),
|
|
1873
1988
|
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
1989
|
] }) });
|
|
1875
1990
|
}
|
|
@@ -1956,7 +2071,7 @@ function IndexPage() {
|
|
|
1956
2071
|
description: meta.description
|
|
1957
2072
|
};
|
|
1958
2073
|
return /* @__PURE__ */ jsxs10("div", { className: "bg-base-100 relative isolate min-h-screen overflow-hidden", children: [
|
|
1959
|
-
/* @__PURE__ */ jsx14("div", { className: "absolute
|
|
2074
|
+
/* @__PURE__ */ jsx14("div", { className: "absolute top-4 right-4 z-10", id: "theme-island" }),
|
|
1960
2075
|
/* @__PURE__ */ jsx14(
|
|
1961
2076
|
"div",
|
|
1962
2077
|
{
|
|
@@ -2452,11 +2567,13 @@ export {
|
|
|
2452
2567
|
BuildPluginBuilder,
|
|
2453
2568
|
computeInlineThemeCss,
|
|
2454
2569
|
buildClientBundle,
|
|
2570
|
+
getGitLastModifiedBatch,
|
|
2571
|
+
frontmatterField,
|
|
2572
|
+
compileMdx,
|
|
2573
|
+
compileMdxModule,
|
|
2455
2574
|
generateSearchIndex,
|
|
2456
2575
|
initSentry,
|
|
2457
2576
|
captureException,
|
|
2458
|
-
getGitLastModifiedBatch,
|
|
2459
|
-
compileMdx,
|
|
2460
2577
|
DocsPage,
|
|
2461
2578
|
NotFoundPage,
|
|
2462
2579
|
IndexPage,
|