@docubook/flame 2.0.0-alpha.1 → 2.0.0-beta.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/Menu.tsx +38 -32
- package/.docu/components/Sublink.tsx +72 -9
- package/.docu/lib/build.deno.js +3 -3
- package/.docu/lib/{build.impl-VXB4KL4D.js → build.impl-S4DS5XPH.js} +3 -3
- package/.docu/lib/build.node.js +3 -3
- package/.docu/lib/{chunk-MQWWCO6O.js → chunk-C3RCUTUE.js} +37 -13
- package/.docu/lib/{chunk-A6FIEG3H.js → chunk-D3QTSBR4.js} +2 -2
- package/.docu/lib/{chunk-JRERMREW.js → chunk-IVM5UM44.js} +6 -4
- package/.docu/lib/{chunk-LZDEWK25.js → chunk-JMQI3FKV.js} +1 -1
- package/.docu/lib/{chunk-TRT6WQZG.js → chunk-LXJLSXQI.js} +105 -44
- package/.docu/lib/{chunk-7PRQ3RQB.js → chunk-O326MYJE.js} +1 -1
- 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 +2 -2
- package/.docu/lib/preview.node.js +2 -2
- package/.docu/lib/server.deno.js +3 -3
- package/.docu/lib/server.node.js +3 -3
- package/.docu/node/build.impl.ts +50 -11
- package/.docu/node/build.ts +50 -11
- package/.docu/node/logger.ts +7 -3
- package/.docu/node/mdx.ts +87 -21
- package/.docu/node/route.ts +27 -19
- package/.docu/node/search-indexer.ts +4 -1
- package/.docu/styles/globals.css +1 -1
- package/package.json +5 -5
|
@@ -1101,15 +1101,12 @@ var frontmatterSchema = z.object({
|
|
|
1101
1101
|
description: z.coerce.string().optional(),
|
|
1102
1102
|
image: z.coerce.string().optional(),
|
|
1103
1103
|
date: z.coerce.string().optional()
|
|
1104
|
-
});
|
|
1104
|
+
}).passthrough();
|
|
1105
1105
|
function frontmatterField(frontmatter, key) {
|
|
1106
1106
|
return typeof frontmatter[key] === "string" ? frontmatter[key] : "";
|
|
1107
1107
|
}
|
|
1108
|
-
async function serializeWithDocPlugins(rawMdx, opts = {}) {
|
|
1109
|
-
const { strippedContent } = extractFrontmatterWithContent(
|
|
1110
|
-
rawMdx,
|
|
1111
|
-
opts.frontmatterSchema
|
|
1112
|
-
);
|
|
1108
|
+
async function serializeWithDocPlugins(rawMdx, opts = {}, pre) {
|
|
1109
|
+
const { strippedContent, frontmatter } = pre ?? extractFrontmatterWithContent(rawMdx, opts.frontmatterSchema);
|
|
1113
1110
|
const defaultRemark = createDefaultRemarkPlugins();
|
|
1114
1111
|
const defaultRehype = createDefaultRehypePlugins();
|
|
1115
1112
|
const finalRemark = [...defaultRemark, remarkMdxJsxDocsHtmlLinks, ...opts.remarkPlugins ?? []];
|
|
@@ -1121,16 +1118,16 @@ async function serializeWithDocPlugins(rawMdx, opts = {}) {
|
|
|
1121
1118
|
rehypePlugins: finalRehype,
|
|
1122
1119
|
remarkPlugins: finalRemark
|
|
1123
1120
|
}
|
|
1124
|
-
});
|
|
1121
|
+
}).then((serialized) => ({ ...serialized, frontmatter, strippedContent }));
|
|
1125
1122
|
}
|
|
1126
|
-
async function compileMdx(rawMdx, filePath, gitDates, remarkPlugins, rehypePlugins, frontmatterSchema2) {
|
|
1123
|
+
async function compileMdx(rawMdx, filePath, gitDates, remarkPlugins, rehypePlugins, frontmatterSchema2, pre) {
|
|
1127
1124
|
const tocs = extractTocsFromRawMdx(rawMdx);
|
|
1128
|
-
const
|
|
1129
|
-
const serialized = await serializeWithDocPlugins(
|
|
1130
|
-
|
|
1131
|
-
rehypePlugins,
|
|
1132
|
-
|
|
1133
|
-
|
|
1125
|
+
const frontmatter = pre?.frontmatter ?? extractFrontmatterWithContent(rawMdx, frontmatterSchema2).frontmatter;
|
|
1126
|
+
const serialized = await serializeWithDocPlugins(
|
|
1127
|
+
rawMdx,
|
|
1128
|
+
{ remarkPlugins, rehypePlugins, frontmatterSchema: frontmatterSchema2 },
|
|
1129
|
+
pre
|
|
1130
|
+
);
|
|
1134
1131
|
const components = createMdxComponents();
|
|
1135
1132
|
const content = React.createElement(MDXRemote, {
|
|
1136
1133
|
compiledSource: serialized.compiledSource,
|
|
@@ -1146,12 +1143,37 @@ async function compileMdx(rawMdx, filePath, gitDates, remarkPlugins, rehypePlugi
|
|
|
1146
1143
|
tocs
|
|
1147
1144
|
};
|
|
1148
1145
|
}
|
|
1149
|
-
|
|
1146
|
+
var pageFrontmatter = /* @__PURE__ */ new Map();
|
|
1147
|
+
function registerPageFrontmatter(href, frontmatter) {
|
|
1148
|
+
pageFrontmatter.set(href, frontmatter);
|
|
1149
|
+
}
|
|
1150
|
+
function getPageFrontmatter(href) {
|
|
1151
|
+
return pageFrontmatter.get(href);
|
|
1152
|
+
}
|
|
1153
|
+
var pageStripped = /* @__PURE__ */ new Map();
|
|
1154
|
+
function registerPageStripped(href, stripped) {
|
|
1155
|
+
pageStripped.set(href, stripped);
|
|
1156
|
+
}
|
|
1157
|
+
function getPageStripped(href) {
|
|
1158
|
+
return pageStripped.get(href);
|
|
1159
|
+
}
|
|
1160
|
+
var pageContent = /* @__PURE__ */ new Map();
|
|
1161
|
+
function registerPageContent(href, raw) {
|
|
1162
|
+
pageContent.set(href, raw);
|
|
1163
|
+
}
|
|
1164
|
+
function getPageContent(href) {
|
|
1165
|
+
return pageContent.get(href);
|
|
1166
|
+
}
|
|
1167
|
+
async function compileMdxModule(rawMdx, remarkPlugins, rehypePlugins, href) {
|
|
1150
1168
|
const serialized = await serializeWithDocPlugins(rawMdx, {
|
|
1151
1169
|
outputFormat: "program",
|
|
1152
1170
|
remarkPlugins,
|
|
1153
1171
|
rehypePlugins
|
|
1154
1172
|
});
|
|
1173
|
+
if (href) {
|
|
1174
|
+
registerPageFrontmatter(href, serialized.frontmatter);
|
|
1175
|
+
registerPageStripped(href, serialized.strippedContent);
|
|
1176
|
+
}
|
|
1155
1177
|
return serialized.compiledSource;
|
|
1156
1178
|
}
|
|
1157
1179
|
|
|
@@ -1278,7 +1300,7 @@ async function generateSearchIndex(docsDir, outputDir) {
|
|
|
1278
1300
|
const mdxFiles = await scanMdxFiles(docs);
|
|
1279
1301
|
const results = await Promise.all(
|
|
1280
1302
|
mdxFiles.map(async (file) => {
|
|
1281
|
-
const raw = await readFile2(file.absPath, "utf-8");
|
|
1303
|
+
const raw = getPageContent(`/${file.path}`) ?? await readFile2(file.absPath, "utf-8");
|
|
1282
1304
|
return extractRecords(file.path, raw);
|
|
1283
1305
|
})
|
|
1284
1306
|
);
|
|
@@ -1364,25 +1386,23 @@ function getRouteMap() {
|
|
|
1364
1386
|
routes.forEach((route) => traverse(route));
|
|
1365
1387
|
return map;
|
|
1366
1388
|
}
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
let description = "";
|
|
1389
|
+
function readPageFrontmatter(href) {
|
|
1390
|
+
const registered = getPageFrontmatter(href);
|
|
1391
|
+
if (registered) return registered;
|
|
1392
|
+
let fm = {};
|
|
1372
1393
|
const rel = href.replace(/^\/|$/g, "");
|
|
1373
1394
|
for (const ext of [".mdx", ".md"]) {
|
|
1374
1395
|
for (const file of [join4(DOCS_DIR, `${rel}${ext}`), join4(DOCS_DIR, `${rel}/index${ext}`)]) {
|
|
1375
1396
|
try {
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
if (description) break;
|
|
1397
|
+
fm = extractFrontmatter(readFileSync2(file, "utf-8"));
|
|
1398
|
+
break;
|
|
1379
1399
|
} catch {
|
|
1380
1400
|
}
|
|
1381
1401
|
}
|
|
1382
|
-
if (
|
|
1402
|
+
if (Object.keys(fm).length) break;
|
|
1383
1403
|
}
|
|
1384
|
-
|
|
1385
|
-
return
|
|
1404
|
+
registerPageFrontmatter(href, fm);
|
|
1405
|
+
return fm;
|
|
1386
1406
|
}
|
|
1387
1407
|
function getPreviousNext(pathname) {
|
|
1388
1408
|
const normalizedPath = pathname.replace(/^\/|$/g, "");
|
|
@@ -1391,12 +1411,13 @@ function getPreviousNext(pathname) {
|
|
|
1391
1411
|
const routeMap2 = getRouteMap();
|
|
1392
1412
|
const first = paths2[0];
|
|
1393
1413
|
if (!first) return { prev: null, next: null };
|
|
1414
|
+
const fm = readPageFrontmatter(first);
|
|
1394
1415
|
return {
|
|
1395
1416
|
prev: null,
|
|
1396
1417
|
next: {
|
|
1397
1418
|
href: first,
|
|
1398
|
-
title: routeMap2.get(first) || "",
|
|
1399
|
-
description:
|
|
1419
|
+
title: fm.title || routeMap2.get(first) || "",
|
|
1420
|
+
description: fm.description || ""
|
|
1400
1421
|
}
|
|
1401
1422
|
};
|
|
1402
1423
|
}
|
|
@@ -1408,12 +1429,14 @@ function getPreviousNext(pathname) {
|
|
|
1408
1429
|
const routeMap = getRouteMap();
|
|
1409
1430
|
const prevHref = index > 0 ? paths[index - 1] : null;
|
|
1410
1431
|
const nextHref = index < paths.length - 1 ? paths[index + 1] : null;
|
|
1432
|
+
const prevFm = prevHref ? readPageFrontmatter(prevHref) : null;
|
|
1433
|
+
const nextFm = nextHref ? readPageFrontmatter(nextHref) : null;
|
|
1411
1434
|
return {
|
|
1412
|
-
prev: prevHref ? { href: prevHref, title: routeMap.get(prevHref) || "" } : null,
|
|
1435
|
+
prev: prevHref ? { href: prevHref, title: prevFm?.title || routeMap.get(prevHref) || "" } : null,
|
|
1413
1436
|
next: nextHref ? {
|
|
1414
1437
|
href: nextHref,
|
|
1415
|
-
title: routeMap.get(nextHref) || "",
|
|
1416
|
-
description:
|
|
1438
|
+
title: nextFm?.title || routeMap.get(nextHref) || "",
|
|
1439
|
+
description: nextFm?.description || ""
|
|
1417
1440
|
} : null
|
|
1418
1441
|
};
|
|
1419
1442
|
}
|
|
@@ -2161,7 +2184,14 @@ import React2 from "react";
|
|
|
2161
2184
|
import { useState as useState4 } from "react";
|
|
2162
2185
|
|
|
2163
2186
|
// .docu/components/Sublink.tsx
|
|
2164
|
-
import {
|
|
2187
|
+
import {
|
|
2188
|
+
createContext,
|
|
2189
|
+
useContext,
|
|
2190
|
+
useState as useState3,
|
|
2191
|
+
useRef as useRef2,
|
|
2192
|
+
useEffect as useEffect3,
|
|
2193
|
+
useCallback as useCallback3
|
|
2194
|
+
} from "react";
|
|
2165
2195
|
import { ChevronDown } from "lucide-react";
|
|
2166
2196
|
|
|
2167
2197
|
// .docu/components/Anchor.tsx
|
|
@@ -2212,6 +2242,15 @@ var config = docuConfig5;
|
|
|
2212
2242
|
|
|
2213
2243
|
// .docu/components/Sublink.tsx
|
|
2214
2244
|
import { jsx as jsx16, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
2245
|
+
var GroupAccordionContext = createContext({ openId: null, open: () => {
|
|
2246
|
+
}, toggle: () => {
|
|
2247
|
+
} });
|
|
2248
|
+
function GroupAccordionProvider({ children }) {
|
|
2249
|
+
const [openId, setOpenId] = useState3(null);
|
|
2250
|
+
const open = useCallback3((id) => setOpenId(id), []);
|
|
2251
|
+
const toggle = useCallback3((id) => setOpenId((prev) => prev === id ? null : id), []);
|
|
2252
|
+
return /* @__PURE__ */ jsx16(GroupAccordionContext.Provider, { value: { openId, open, toggle }, children });
|
|
2253
|
+
}
|
|
2215
2254
|
function Sublink({
|
|
2216
2255
|
title,
|
|
2217
2256
|
href,
|
|
@@ -2224,11 +2263,24 @@ function Sublink({
|
|
|
2224
2263
|
}) {
|
|
2225
2264
|
const fullHref = parentHref ? `${parentHref}${href}` : `/docs${href}`;
|
|
2226
2265
|
const currentPathname = pathnameProp || (typeof window !== "undefined" ? window.location.pathname : "/docs");
|
|
2266
|
+
const isSeparator = config.sidebar?.context === "separator";
|
|
2267
|
+
const { openId, open, toggle } = useContext(GroupAccordionContext);
|
|
2268
|
+
const isAccordionGroup = Boolean(items) && (isSeparator || level >= 1);
|
|
2269
|
+
const treeLevel = level + (isSeparator ? 2 : 1);
|
|
2227
2270
|
const [isOpen, setIsOpen] = useState3(() => {
|
|
2271
|
+
if (isAccordionGroup) return false;
|
|
2228
2272
|
if (level === 0) return true;
|
|
2229
|
-
|
|
2230
|
-
return currentPathname.startsWith(fullHref) && currentPathname !== fullHref;
|
|
2273
|
+
return false;
|
|
2231
2274
|
});
|
|
2275
|
+
const effectiveOpen = isAccordionGroup ? openId === fullHref : isOpen;
|
|
2276
|
+
const handleToggle = () => {
|
|
2277
|
+
if (isAccordionGroup) toggle(fullHref);
|
|
2278
|
+
else setIsOpen((o) => !o);
|
|
2279
|
+
};
|
|
2280
|
+
const isInsideActive = currentPathname.startsWith(fullHref) && currentPathname !== fullHref;
|
|
2281
|
+
useEffect3(() => {
|
|
2282
|
+
if (isAccordionGroup && isInsideActive) open(fullHref);
|
|
2283
|
+
}, [isAccordionGroup, isInsideActive, fullHref, open]);
|
|
2232
2284
|
const levelPadding = cn(level === 1 && "pl-4", level === 2 && "pl-8", level >= 3 && "pl-12");
|
|
2233
2285
|
const isActive = currentPathname === fullHref || currentPathname === `${fullHref}.html`;
|
|
2234
2286
|
const activeRef = useRef2(null);
|
|
@@ -2287,10 +2339,13 @@ function Sublink({
|
|
|
2287
2339
|
"button",
|
|
2288
2340
|
{
|
|
2289
2341
|
type: "button",
|
|
2290
|
-
onClick:
|
|
2342
|
+
onClick: handleToggle,
|
|
2291
2343
|
className: cn(
|
|
2292
2344
|
"flex w-full cursor-pointer items-center justify-between py-1 text-left text-sm transition-colors",
|
|
2293
|
-
|
|
2345
|
+
// Only the top-level section label (routes-tree level 1) is bold.
|
|
2346
|
+
// Deeper groups (e.g. Search at level 2) are children that happen to
|
|
2347
|
+
// have items — style them like links, no header weight.
|
|
2348
|
+
noLink && treeLevel === 1 ? "text-base-content font-semibold" : "text-foreground hover:text-foreground/80"
|
|
2294
2349
|
),
|
|
2295
2350
|
children: [
|
|
2296
2351
|
noLink ? /* @__PURE__ */ jsx16("span", { children: title }) : /* @__PURE__ */ jsx16(
|
|
@@ -2309,14 +2364,16 @@ function Sublink({
|
|
|
2309
2364
|
{
|
|
2310
2365
|
className: cn(
|
|
2311
2366
|
"text-base-content/40 h-4 w-4 shrink-0 transition-transform duration-200",
|
|
2312
|
-
|
|
2367
|
+
// Tree convention: closed = chevron pointing right (expandable),
|
|
2368
|
+
// open = pointing down — a 90° turn instead of the 180° flip.
|
|
2369
|
+
effectiveOpen ? "rotate-0" : "-rotate-90"
|
|
2313
2370
|
)
|
|
2314
2371
|
}
|
|
2315
2372
|
)
|
|
2316
2373
|
]
|
|
2317
2374
|
}
|
|
2318
2375
|
),
|
|
2319
|
-
|
|
2376
|
+
effectiveOpen && /* @__PURE__ */ jsx16("div", { className: "flex flex-col py-1", children: items.map((item) => /* @__PURE__ */ jsx16(
|
|
2320
2377
|
Sublink,
|
|
2321
2378
|
{
|
|
2322
2379
|
...item,
|
|
@@ -2391,9 +2448,9 @@ function Menu({ onNavigate, className = "", pathname, routes: routes3 = [] }) {
|
|
|
2391
2448
|
if (mode === "separator") {
|
|
2392
2449
|
const contextRoutes = menuRoutes.filter((r) => r.context);
|
|
2393
2450
|
if (contextRoutes.length === 0) {
|
|
2394
|
-
return /* @__PURE__ */ jsx18("nav", { ...navProps, children: /* @__PURE__ */ jsx18("ul", { className: sharedUlClasses, children: menuRoutes.map((route) => renderBorderItem(route, "", route.href)) }) });
|
|
2451
|
+
return /* @__PURE__ */ jsx18(GroupAccordionProvider, { children: /* @__PURE__ */ jsx18("nav", { ...navProps, children: /* @__PURE__ */ jsx18("ul", { className: sharedUlClasses, children: menuRoutes.map((route) => renderBorderItem(route, "", route.href)) }) }) });
|
|
2395
2452
|
}
|
|
2396
|
-
return /* @__PURE__ */ jsx18("nav", { ...navProps, children: contextRoutes.map((route, i) => /* @__PURE__ */ jsxs14("div", { className: i > 0 ? "mt-6 lg:mt-8" : "", children: [
|
|
2453
|
+
return /* @__PURE__ */ jsx18(GroupAccordionProvider, { children: /* @__PURE__ */ jsx18("nav", { ...navProps, children: contextRoutes.map((route, i) => /* @__PURE__ */ jsxs14("div", { className: i > 0 ? "mt-6 lg:mt-8" : "", children: [
|
|
2397
2454
|
/* @__PURE__ */ jsx18(
|
|
2398
2455
|
SidebarGroupHeader,
|
|
2399
2456
|
{
|
|
@@ -2402,13 +2459,13 @@ function Menu({ onNavigate, className = "", pathname, routes: routes3 = [] }) {
|
|
|
2402
2459
|
}
|
|
2403
2460
|
),
|
|
2404
2461
|
/* @__PURE__ */ jsx18("ul", { className: sharedUlClasses, children: route.items?.map((item) => renderBorderItem(item, route.href, item.href)) })
|
|
2405
|
-
] }, route.href)) });
|
|
2462
|
+
] }, route.href)) }) });
|
|
2406
2463
|
}
|
|
2407
2464
|
const isDocsRoot = currentPath === "/docs" || currentPath === "/docs/";
|
|
2408
2465
|
const currentContext = isDocsRoot ? menuRoutes[0]?.href.replace(/^\/+|\/+$/, "") : getCurrentContext(currentPath);
|
|
2409
2466
|
const contextRoute = isDocsRoot && menuRoutes[0] ? currentContext ? getContextRoute(currentContext, menuRoutes) : menuRoutes[0] : currentContext ? getContextRoute(currentContext, menuRoutes) : void 0;
|
|
2410
2467
|
if (!contextRoute) return null;
|
|
2411
|
-
return /* @__PURE__ */ jsx18("nav", { ...navProps, children: /* @__PURE__ */ jsx18("ul", { className: "flex flex-col gap-0.5 py-4", children: /* @__PURE__ */ jsx18("li", { children: /* @__PURE__ */ jsx18(
|
|
2468
|
+
return /* @__PURE__ */ jsx18(GroupAccordionProvider, { children: /* @__PURE__ */ jsx18("nav", { ...navProps, children: /* @__PURE__ */ jsx18("ul", { className: "flex flex-col gap-0.5 py-4", children: /* @__PURE__ */ jsx18("li", { children: /* @__PURE__ */ jsx18(
|
|
2412
2469
|
Sublink,
|
|
2413
2470
|
{
|
|
2414
2471
|
...contextRoute,
|
|
@@ -2417,7 +2474,7 @@ function Menu({ onNavigate, className = "", pathname, routes: routes3 = [] }) {
|
|
|
2417
2474
|
onNavigate,
|
|
2418
2475
|
parentHref: "/docs"
|
|
2419
2476
|
}
|
|
2420
|
-
) }, contextRoute.title) }) });
|
|
2477
|
+
) }, contextRoute.title) }) }) });
|
|
2421
2478
|
}
|
|
2422
2479
|
|
|
2423
2480
|
// .docu/components/DocsLayout.tsx
|
|
@@ -2616,6 +2673,10 @@ export {
|
|
|
2616
2673
|
getGitLastModifiedBatch,
|
|
2617
2674
|
frontmatterField,
|
|
2618
2675
|
compileMdx,
|
|
2676
|
+
getPageFrontmatter,
|
|
2677
|
+
getPageStripped,
|
|
2678
|
+
registerPageContent,
|
|
2679
|
+
getPageContent,
|
|
2619
2680
|
compileMdxModule,
|
|
2620
2681
|
generateSearchIndex,
|
|
2621
2682
|
initSentry,
|
|
@@ -137,7 +137,7 @@ async function runBuild() {
|
|
|
137
137
|
process.env.FLAME_BUILD_SILENT = "1";
|
|
138
138
|
process.env.LOG_LEVEL = "error";
|
|
139
139
|
}
|
|
140
|
-
const { runBuildCli } = await import("./build.impl-
|
|
140
|
+
const { runBuildCli } = await import("./build.impl-S4DS5XPH.js");
|
|
141
141
|
await runBuildCli();
|
|
142
142
|
}
|
|
143
143
|
async function writeDockerFiles() {
|
package/.docu/lib/clean.js
CHANGED
package/.docu/lib/deploy.deno.js
CHANGED
package/.docu/lib/deploy.node.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
runPreview
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-JMQI3FKV.js";
|
|
4
4
|
import {
|
|
5
5
|
denoAdapter
|
|
6
6
|
} from "./chunk-UISOJ4RW.js";
|
|
7
7
|
import "./chunk-EOK6KATZ.js";
|
|
8
|
-
import "./chunk-
|
|
8
|
+
import "./chunk-IVM5UM44.js";
|
|
9
9
|
import "./chunk-4IQXHHPF.js";
|
|
10
10
|
|
|
11
11
|
// .docu/node/preview.deno.ts
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
runPreview
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-JMQI3FKV.js";
|
|
4
4
|
import {
|
|
5
5
|
nodeAdapter
|
|
6
6
|
} from "./chunk-UISOJ4RW.js";
|
|
7
7
|
import "./chunk-EOK6KATZ.js";
|
|
8
|
-
import "./chunk-
|
|
8
|
+
import "./chunk-IVM5UM44.js";
|
|
9
9
|
import "./chunk-4IQXHHPF.js";
|
|
10
10
|
|
|
11
11
|
// .docu/node/preview.node.ts
|
package/.docu/lib/server.deno.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
runServer
|
|
3
|
-
} from "./chunk-
|
|
4
|
-
import "./chunk-
|
|
3
|
+
} from "./chunk-D3QTSBR4.js";
|
|
4
|
+
import "./chunk-LXJLSXQI.js";
|
|
5
5
|
import {
|
|
6
6
|
denoAdapter
|
|
7
7
|
} from "./chunk-UISOJ4RW.js";
|
|
8
8
|
import "./chunk-EOK6KATZ.js";
|
|
9
|
-
import "./chunk-
|
|
9
|
+
import "./chunk-IVM5UM44.js";
|
|
10
10
|
import "./chunk-4IQXHHPF.js";
|
|
11
11
|
|
|
12
12
|
// .docu/node/server.deno.ts
|
package/.docu/lib/server.node.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
runServer
|
|
3
|
-
} from "./chunk-
|
|
4
|
-
import "./chunk-
|
|
3
|
+
} from "./chunk-D3QTSBR4.js";
|
|
4
|
+
import "./chunk-LXJLSXQI.js";
|
|
5
5
|
import {
|
|
6
6
|
nodeAdapter
|
|
7
7
|
} from "./chunk-UISOJ4RW.js";
|
|
8
8
|
import "./chunk-EOK6KATZ.js";
|
|
9
|
-
import "./chunk-
|
|
9
|
+
import "./chunk-IVM5UM44.js";
|
|
10
10
|
import "./chunk-4IQXHHPF.js";
|
|
11
11
|
|
|
12
12
|
// .docu/node/server.node.ts
|
package/.docu/node/build.impl.ts
CHANGED
|
@@ -12,7 +12,16 @@ import { createHash } from "node:crypto";
|
|
|
12
12
|
import { join, dirname } from "node:path";
|
|
13
13
|
import React from "react";
|
|
14
14
|
import { renderToString } from "react-dom/server";
|
|
15
|
-
import {
|
|
15
|
+
import {
|
|
16
|
+
compileMdx,
|
|
17
|
+
compileMdxModule,
|
|
18
|
+
frontmatterField,
|
|
19
|
+
getGitLastModifiedBatch,
|
|
20
|
+
getPageContent,
|
|
21
|
+
getPageFrontmatter,
|
|
22
|
+
getPageStripped,
|
|
23
|
+
registerPageContent,
|
|
24
|
+
} from "./mdx";
|
|
16
25
|
import {
|
|
17
26
|
DOCS_DIR,
|
|
18
27
|
DIST_DIR,
|
|
@@ -105,7 +114,24 @@ async function renderDocsPage(
|
|
|
105
114
|
try {
|
|
106
115
|
const remarkPlugins = builder?.collectRemarkPlugins();
|
|
107
116
|
const rehypePlugins = builder?.collectRehypePlugins();
|
|
108
|
-
|
|
117
|
+
// Parse-once: reuse the prePass frontmatter + stripped content so the
|
|
118
|
+
// SSR phase does not re-extract them. Only when the prePass actually
|
|
119
|
+
// registered them — otherwise compileMdx does its own extraction.
|
|
120
|
+
const preFm = getPageFrontmatter(`/${slug}`);
|
|
121
|
+
const preStripped = getPageStripped(`/${slug}`);
|
|
122
|
+
const pre =
|
|
123
|
+
preFm !== undefined && preStripped !== undefined
|
|
124
|
+
? { frontmatter: preFm, strippedContent: preStripped }
|
|
125
|
+
: undefined;
|
|
126
|
+
result = await compileMdx(
|
|
127
|
+
content,
|
|
128
|
+
filePath,
|
|
129
|
+
gitDates,
|
|
130
|
+
remarkPlugins,
|
|
131
|
+
rehypePlugins,
|
|
132
|
+
undefined,
|
|
133
|
+
pre
|
|
134
|
+
);
|
|
109
135
|
} catch (err) {
|
|
110
136
|
const msg = err instanceof Error ? err.message : "Unknown MDX error";
|
|
111
137
|
throw new Error(`MDX Error in: docs/${slug}.mdx\n${msg}`, { cause: err });
|
|
@@ -241,6 +267,9 @@ export async function runBuild(): Promise<void> {
|
|
|
241
267
|
} catch {
|
|
242
268
|
return;
|
|
243
269
|
}
|
|
270
|
+
// Cache the original content so the page loop does not re-read the file
|
|
271
|
+
// (one disk read per file — the frontmatter is parsed once here too).
|
|
272
|
+
registerPageContent(`/${file.path}`, raw);
|
|
244
273
|
let content = raw;
|
|
245
274
|
if (builder) {
|
|
246
275
|
const relPath = file.absPath.replace(PROJECT_ROOT + "/", "");
|
|
@@ -249,7 +278,12 @@ export async function runBuild(): Promise<void> {
|
|
|
249
278
|
}
|
|
250
279
|
const remarkPlugins = builder?.collectRemarkPlugins();
|
|
251
280
|
const rehypePlugins = builder?.collectRehypePlugins();
|
|
252
|
-
mdxSources[file.path] = await compileMdxModule(
|
|
281
|
+
mdxSources[file.path] = await compileMdxModule(
|
|
282
|
+
content,
|
|
283
|
+
remarkPlugins,
|
|
284
|
+
rehypePlugins,
|
|
285
|
+
`/${file.path}`
|
|
286
|
+
);
|
|
253
287
|
});
|
|
254
288
|
await Promise.all(prePassTasks);
|
|
255
289
|
|
|
@@ -319,12 +353,14 @@ export async function runBuild(): Promise<void> {
|
|
|
319
353
|
}
|
|
320
354
|
}
|
|
321
355
|
|
|
322
|
-
let rawMdx
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
356
|
+
let rawMdx = getPageContent(`/${file.path}`);
|
|
357
|
+
if (rawMdx === undefined) {
|
|
358
|
+
try {
|
|
359
|
+
rawMdx = await readFile(file.absPath, "utf-8");
|
|
360
|
+
} catch (err) {
|
|
361
|
+
if ((err as NodeJS.ErrnoException).code !== "ENOENT") throw err;
|
|
362
|
+
continue;
|
|
363
|
+
}
|
|
328
364
|
}
|
|
329
365
|
|
|
330
366
|
if (rebuildDecision === "hash_check") {
|
|
@@ -458,8 +494,11 @@ export async function runBuild(): Promise<void> {
|
|
|
458
494
|
|
|
459
495
|
logger.indexStart();
|
|
460
496
|
t = performance.now();
|
|
461
|
-
|
|
462
|
-
|
|
497
|
+
// No content changed (all pages cached) → the aggregated index is
|
|
498
|
+
// unchanged too; reuse the existing file instead of regenerating it.
|
|
499
|
+
const indexSkipped = built === 0 && existsSync(join(ASSETS_DIR, "search-index.json"));
|
|
500
|
+
const indexCount = indexSkipped ? 0 : await generateSearchIndex();
|
|
501
|
+
logger.indexDone(indexCount, Math.round(performance.now() - t), indexSkipped);
|
|
463
502
|
|
|
464
503
|
logger.routes();
|
|
465
504
|
|
package/.docu/node/build.ts
CHANGED
|
@@ -4,7 +4,16 @@ import { createHash } from "node:crypto";
|
|
|
4
4
|
import { join, dirname } from "node:path";
|
|
5
5
|
import React from "react";
|
|
6
6
|
import { renderToString } from "react-dom/server";
|
|
7
|
-
import {
|
|
7
|
+
import {
|
|
8
|
+
compileMdx,
|
|
9
|
+
compileMdxModule,
|
|
10
|
+
frontmatterField,
|
|
11
|
+
getGitLastModifiedBatch,
|
|
12
|
+
getPageContent,
|
|
13
|
+
getPageFrontmatter,
|
|
14
|
+
getPageStripped,
|
|
15
|
+
registerPageContent,
|
|
16
|
+
} from "./mdx";
|
|
8
17
|
import {
|
|
9
18
|
DOCS_DIR,
|
|
10
19
|
DIST_DIR,
|
|
@@ -98,7 +107,24 @@ async function renderDocsPage(
|
|
|
98
107
|
try {
|
|
99
108
|
const remarkPlugins = builder?.collectRemarkPlugins();
|
|
100
109
|
const rehypePlugins = builder?.collectRehypePlugins();
|
|
101
|
-
|
|
110
|
+
// Parse-once: reuse the prePass frontmatter + stripped content so the
|
|
111
|
+
// SSR phase does not re-extract them. Only when the prePass actually
|
|
112
|
+
// registered them — otherwise compileMdx does its own extraction.
|
|
113
|
+
const preFm = getPageFrontmatter(`/${slug}`);
|
|
114
|
+
const preStripped = getPageStripped(`/${slug}`);
|
|
115
|
+
const pre =
|
|
116
|
+
preFm !== undefined && preStripped !== undefined
|
|
117
|
+
? { frontmatter: preFm, strippedContent: preStripped }
|
|
118
|
+
: undefined;
|
|
119
|
+
result = await compileMdx(
|
|
120
|
+
content,
|
|
121
|
+
filePath,
|
|
122
|
+
gitDates,
|
|
123
|
+
remarkPlugins,
|
|
124
|
+
rehypePlugins,
|
|
125
|
+
undefined,
|
|
126
|
+
pre
|
|
127
|
+
);
|
|
102
128
|
} catch (err) {
|
|
103
129
|
const msg = err instanceof Error ? err.message : "Unknown MDX error";
|
|
104
130
|
throw new Error(`MDX Error in: docs/${slug}.mdx\n${msg}`, { cause: err });
|
|
@@ -229,6 +255,9 @@ async function build() {
|
|
|
229
255
|
} catch {
|
|
230
256
|
return;
|
|
231
257
|
}
|
|
258
|
+
// Cache the original content so the page loop does not re-read the file
|
|
259
|
+
// (one disk read per file — the frontmatter is parsed once here too).
|
|
260
|
+
registerPageContent(`/${file.path}`, raw);
|
|
232
261
|
let content = raw;
|
|
233
262
|
if (builder) {
|
|
234
263
|
const relPath = file.absPath.replace(PROJECT_ROOT + "/", "");
|
|
@@ -237,7 +266,12 @@ async function build() {
|
|
|
237
266
|
}
|
|
238
267
|
const remarkPlugins = builder?.collectRemarkPlugins();
|
|
239
268
|
const rehypePlugins = builder?.collectRehypePlugins();
|
|
240
|
-
mdxSources[file.path] = await compileMdxModule(
|
|
269
|
+
mdxSources[file.path] = await compileMdxModule(
|
|
270
|
+
content,
|
|
271
|
+
remarkPlugins,
|
|
272
|
+
rehypePlugins,
|
|
273
|
+
`/${file.path}`
|
|
274
|
+
);
|
|
241
275
|
});
|
|
242
276
|
await Promise.all(prePassTasks);
|
|
243
277
|
|
|
@@ -307,12 +341,14 @@ async function build() {
|
|
|
307
341
|
}
|
|
308
342
|
}
|
|
309
343
|
|
|
310
|
-
let rawMdx
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
344
|
+
let rawMdx = getPageContent(`/${file.path}`);
|
|
345
|
+
if (rawMdx === undefined) {
|
|
346
|
+
try {
|
|
347
|
+
rawMdx = await readFile(file.absPath, "utf-8");
|
|
348
|
+
} catch (err) {
|
|
349
|
+
if ((err as NodeJS.ErrnoException).code !== "ENOENT") throw err;
|
|
350
|
+
continue;
|
|
351
|
+
}
|
|
316
352
|
}
|
|
317
353
|
|
|
318
354
|
if (rebuildDecision === "hash_check") {
|
|
@@ -440,8 +476,11 @@ async function build() {
|
|
|
440
476
|
|
|
441
477
|
logger.indexStart();
|
|
442
478
|
t = performance.now();
|
|
443
|
-
|
|
444
|
-
|
|
479
|
+
// No content changed (all pages cached) → the aggregated index is
|
|
480
|
+
// unchanged too; reuse the existing file instead of regenerating it.
|
|
481
|
+
const indexSkipped = built === 0 && existsSync(join(ASSETS_DIR, "search-index.json"));
|
|
482
|
+
const indexCount = indexSkipped ? 0 : await generateSearchIndex();
|
|
483
|
+
logger.indexDone(indexCount, Math.round(performance.now() - t), indexSkipped);
|
|
445
484
|
|
|
446
485
|
logger.routes();
|
|
447
486
|
console.log("");
|
package/.docu/node/logger.ts
CHANGED
|
@@ -179,9 +179,13 @@ export const logger = {
|
|
|
179
179
|
this.spinner.start("Generating search index...");
|
|
180
180
|
},
|
|
181
181
|
|
|
182
|
-
indexDone(records: number, ms: number) {
|
|
183
|
-
if (guard("info", "index_done", { records, duration_ms: ms })) return;
|
|
184
|
-
this.spinner.stop(
|
|
182
|
+
indexDone(records: number, ms: number, skipped = false) {
|
|
183
|
+
if (guard("info", "index_done", { records, duration_ms: ms, skipped })) return;
|
|
184
|
+
this.spinner.stop(
|
|
185
|
+
skipped
|
|
186
|
+
? `Search index cached ${c.dim}(${ms}ms)${c.reset}`
|
|
187
|
+
: `Search index generated ${c.dim}(${records} records, ${ms}ms)${c.reset}`
|
|
188
|
+
);
|
|
185
189
|
},
|
|
186
190
|
|
|
187
191
|
routes() {
|