@clarify-labs/cli 0.6.7 → 0.7.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/output/cli.cjs +5 -4
- package/output/cli.cjs.map +1 -1
- package/output/cli.js +5 -4
- package/output/cli.js.map +1 -1
- package/output/core/config-schema.d.ts +13 -4
- package/output/core/search-language.d.ts +1 -0
- package/output/core/ssg.d.ts +1 -1
- package/output/core/temp-dir.d.ts +2 -0
- package/output/core/virtual-modules.d.ts +8 -1
- package/output/index.cjs +1 -1
- package/output/index.js +1 -1
- package/output/{plugin-Cx9lFenc.js → plugin-BNzlJ4o7.js} +337 -92
- package/output/plugin-BNzlJ4o7.js.map +1 -0
- package/output/{plugin-hJcy-YdO.cjs → plugin-dzXRzjdX.cjs} +341 -90
- package/output/plugin-dzXRzjdX.cjs.map +1 -0
- package/output/plugins/openapi/virtual-modules.d.ts +1 -1
- package/output/plugins/search-index/index.d.ts +2 -0
- package/output/types.d.ts +3 -1
- package/package.json +5 -3
- package/output/plugin-Cx9lFenc.js.map +0 -1
- package/output/plugin-hJcy-YdO.cjs.map +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { existsSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, rmSync, writeFileSync } from "node:fs";
|
|
1
|
+
import { createReadStream, existsSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, rmSync, writeFileSync } from "node:fs";
|
|
2
2
|
import { dirname, extname, isAbsolute, join, relative, resolve } from "node:path";
|
|
3
3
|
import mdxPlugin from "@mdx-js/rollup";
|
|
4
4
|
import tailwindcss from "@tailwindcss/vite";
|
|
@@ -11,9 +11,9 @@ import { markdownRemarkPlugins } from "@clarify-labs/renderer";
|
|
|
11
11
|
import { remark } from "remark";
|
|
12
12
|
import matter from "gray-matter";
|
|
13
13
|
import SwaggerParser from "@apidevtools/swagger-parser";
|
|
14
|
+
import { tmpdir } from "node:os";
|
|
14
15
|
import { mkdir, writeFile } from "node:fs/promises";
|
|
15
16
|
import { z } from "zod";
|
|
16
|
-
import { tmpdir } from "node:os";
|
|
17
17
|
import { pathToFileURL } from "node:url";
|
|
18
18
|
import { build, loadConfigFromFile } from "vite";
|
|
19
19
|
import { createRequire } from "node:module";
|
|
@@ -232,8 +232,80 @@ function createContentArtifactsPlugin() {
|
|
|
232
232
|
};
|
|
233
233
|
}
|
|
234
234
|
//#endregion
|
|
235
|
+
//#region source/core/theme.ts
|
|
236
|
+
var clarifyThemePresets = {
|
|
237
|
+
default: {
|
|
238
|
+
preset: "default",
|
|
239
|
+
tokens: {
|
|
240
|
+
colors: {
|
|
241
|
+
primary: "#047857",
|
|
242
|
+
accent: "#0D9488",
|
|
243
|
+
background: "#ffffff",
|
|
244
|
+
foreground: "#111827",
|
|
245
|
+
surface: "#ffffff",
|
|
246
|
+
muted: "#64748b",
|
|
247
|
+
border: "rgb(15 23 42 / 0.12)",
|
|
248
|
+
codeBackground: "#f6fbf8"
|
|
249
|
+
},
|
|
250
|
+
radius: {
|
|
251
|
+
sm: "6px",
|
|
252
|
+
md: "10px",
|
|
253
|
+
lg: "14px",
|
|
254
|
+
xl: "18px"
|
|
255
|
+
}
|
|
256
|
+
},
|
|
257
|
+
layout: { maxWidth: "82rem" },
|
|
258
|
+
editor: false
|
|
259
|
+
},
|
|
260
|
+
base: {
|
|
261
|
+
preset: "base",
|
|
262
|
+
tokens: {
|
|
263
|
+
colors: {
|
|
264
|
+
primary: "#18181b",
|
|
265
|
+
accent: "#52525b",
|
|
266
|
+
background: "#ffffff",
|
|
267
|
+
foreground: "#18181b",
|
|
268
|
+
surface: "#ffffff",
|
|
269
|
+
muted: "#71717a",
|
|
270
|
+
border: "rgb(24 24 27 / 0.12)",
|
|
271
|
+
codeBackground: "#f4f4f5"
|
|
272
|
+
},
|
|
273
|
+
radius: {
|
|
274
|
+
sm: "6px",
|
|
275
|
+
md: "8px",
|
|
276
|
+
lg: "12px",
|
|
277
|
+
xl: "16px"
|
|
278
|
+
}
|
|
279
|
+
},
|
|
280
|
+
layout: { maxWidth: "80rem" },
|
|
281
|
+
editor: false
|
|
282
|
+
}
|
|
283
|
+
};
|
|
284
|
+
function resolveThemeConfig(theme = {}) {
|
|
285
|
+
const preset = theme.preset ?? "default";
|
|
286
|
+
const presetTheme = clarifyThemePresets[preset];
|
|
287
|
+
return {
|
|
288
|
+
preset,
|
|
289
|
+
tokens: {
|
|
290
|
+
colors: {
|
|
291
|
+
...presetTheme.tokens.colors,
|
|
292
|
+
...theme.tokens?.colors
|
|
293
|
+
},
|
|
294
|
+
radius: {
|
|
295
|
+
...presetTheme.tokens.radius,
|
|
296
|
+
...theme.tokens?.radius
|
|
297
|
+
}
|
|
298
|
+
},
|
|
299
|
+
layout: {
|
|
300
|
+
...presetTheme.layout,
|
|
301
|
+
...theme.layout
|
|
302
|
+
},
|
|
303
|
+
editor: theme.editor ?? presetTheme.editor
|
|
304
|
+
};
|
|
305
|
+
}
|
|
306
|
+
//#endregion
|
|
235
307
|
//#region source/plugins/html-shell/index.ts
|
|
236
|
-
var
|
|
308
|
+
var THEME_STORAGE_KEY = "clarify:theme";
|
|
237
309
|
var REL_ICON_RE = /<link\s+[^>]*rel=["'][^"']*\bicon\b[^"']*["'][^>]*>/i;
|
|
238
310
|
function inferIconType(href) {
|
|
239
311
|
const path = href.split(/[?#]/, 1)[0]?.toLowerCase() ?? href.toLowerCase();
|
|
@@ -263,6 +335,62 @@ function createIconTags(icon) {
|
|
|
263
335
|
if (lightIcon === darkIcon) return [createIconTag(lightIcon)];
|
|
264
336
|
return [createIconTag(lightIcon, "(prefers-color-scheme: light)"), createIconTag(darkIcon, "(prefers-color-scheme: dark)")];
|
|
265
337
|
}
|
|
338
|
+
function matchesPresetTheme(theme) {
|
|
339
|
+
const preset = clarifyThemePresets[theme.preset];
|
|
340
|
+
return JSON.stringify({
|
|
341
|
+
tokens: theme.tokens,
|
|
342
|
+
layout: theme.layout
|
|
343
|
+
}) === JSON.stringify({
|
|
344
|
+
tokens: preset.tokens,
|
|
345
|
+
layout: preset.layout
|
|
346
|
+
});
|
|
347
|
+
}
|
|
348
|
+
function effectiveTheme(theme, resolvedTheme) {
|
|
349
|
+
if (resolvedTheme !== "dark" || !matchesPresetTheme(theme)) return theme;
|
|
350
|
+
return {
|
|
351
|
+
...theme,
|
|
352
|
+
tokens: {
|
|
353
|
+
...theme.tokens,
|
|
354
|
+
colors: {
|
|
355
|
+
...theme.tokens.colors,
|
|
356
|
+
background: "#09090b",
|
|
357
|
+
foreground: "#ffffff",
|
|
358
|
+
surface: "#18181b",
|
|
359
|
+
muted: "#a1a1aa",
|
|
360
|
+
border: "rgb(255 255 255 / 0.1)",
|
|
361
|
+
codeBackground: "#18181b"
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
};
|
|
365
|
+
}
|
|
366
|
+
function resolveThemeColorValue(value, resolvedTheme) {
|
|
367
|
+
return typeof value === "string" ? value : value[resolvedTheme] ?? value.light ?? value.dark ?? "";
|
|
368
|
+
}
|
|
369
|
+
function themeToCssVariables(theme, resolvedTheme) {
|
|
370
|
+
const resolved = effectiveTheme(theme, resolvedTheme);
|
|
371
|
+
const { colors } = resolved.tokens;
|
|
372
|
+
const { radius } = resolved.tokens;
|
|
373
|
+
return {
|
|
374
|
+
"--clarify-theme-tokens-colors-primary": resolveThemeColorValue(colors.primary, resolvedTheme),
|
|
375
|
+
"--clarify-theme-tokens-colors-accent": resolveThemeColorValue(colors.accent, resolvedTheme),
|
|
376
|
+
"--clarify-theme-tokens-colors-background": resolveThemeColorValue(colors.background, resolvedTheme),
|
|
377
|
+
"--clarify-theme-tokens-colors-foreground": resolveThemeColorValue(colors.foreground, resolvedTheme),
|
|
378
|
+
"--clarify-theme-tokens-colors-surface": resolveThemeColorValue(colors.surface, resolvedTheme),
|
|
379
|
+
"--clarify-theme-tokens-colors-muted": resolveThemeColorValue(colors.muted, resolvedTheme),
|
|
380
|
+
"--clarify-theme-tokens-colors-border": resolveThemeColorValue(colors.border, resolvedTheme),
|
|
381
|
+
"--clarify-theme-tokens-colors-code-background": resolveThemeColorValue(colors.codeBackground, resolvedTheme),
|
|
382
|
+
"--clarify-theme-tokens-radius-sm": radius.sm,
|
|
383
|
+
"--clarify-theme-tokens-radius-md": radius.md,
|
|
384
|
+
"--clarify-theme-tokens-radius-lg": radius.lg,
|
|
385
|
+
"--clarify-theme-tokens-radius-xl": radius.xl,
|
|
386
|
+
"--clarify-theme-layout-max-width": resolved.layout.maxWidth
|
|
387
|
+
};
|
|
388
|
+
}
|
|
389
|
+
function themeBootstrapScript(theme) {
|
|
390
|
+
const darkVariables = themeToCssVariables(theme, "dark");
|
|
391
|
+
const lightVariables = themeToCssVariables(theme, "light");
|
|
392
|
+
return `(function(){try{var e=localStorage.getItem(${JSON.stringify(THEME_STORAGE_KEY)});var t=e==='dark'||e==='light'||e==='system'?e:'system';var r=t==='system'?window.matchMedia('(prefers-color-scheme: dark)').matches:t==='dark';var v=r?${JSON.stringify(darkVariables)}:${JSON.stringify(lightVariables)};var s=document.documentElement.style;for(var k in v)s.setProperty(k,v[k]);document.documentElement.classList.toggle('dark',r);document.documentElement.style.colorScheme=r?'dark':'light'}catch(e){}})();`;
|
|
393
|
+
}
|
|
266
394
|
function createHtmlShellPlugin() {
|
|
267
395
|
return {
|
|
268
396
|
name: "clarify:html-shell",
|
|
@@ -273,7 +401,7 @@ function createHtmlShellPlugin() {
|
|
|
273
401
|
...REL_ICON_RE.test(input.html) ? [] : createIconTags(ctx.projectConfig.favicon ?? ctx.projectConfig.logo),
|
|
274
402
|
{
|
|
275
403
|
tag: "script",
|
|
276
|
-
children:
|
|
404
|
+
children: themeBootstrapScript(ctx.projectConfig.theme),
|
|
277
405
|
injectTo: "head-prepend"
|
|
278
406
|
},
|
|
279
407
|
{
|
|
@@ -750,8 +878,10 @@ function generateRoutesModule(routes, resolvedNavigation, projectConfig, mode =
|
|
|
750
878
|
const navigation = resolvedNavigation ?? (projectConfig?.tabs ? projectConfig.i18n ? buildLocalizedNavigationFromTabsConfig(routes, projectConfig.tabs, projectConfig.i18n) ?? {} : buildNavigationFromTabsConfig(routes, projectConfig.tabs) : buildNavigation(routes));
|
|
751
879
|
return `${imports}\n\nexport const routes = [\n${routesArray}\n];\n\nexport const navigation = ${JSON.stringify(navigation, null, 2)};\n`;
|
|
752
880
|
}
|
|
753
|
-
function createRuntimeModule() {
|
|
754
|
-
return "
|
|
881
|
+
function createRuntimeModule(options = {}) {
|
|
882
|
+
return `${options.footerComponentSource === "path" && options.imports?.footerComponent ? `import FooterComponent from ${moduleSpecifier(options.imports.footerComponent)};` : ""}
|
|
883
|
+
export const openApis = {};
|
|
884
|
+
export const footerComponent = ${options.footerComponentSource === "path" ? "FooterComponent" : "undefined"};`;
|
|
755
885
|
}
|
|
756
886
|
function createClientEntryModule(options = {}) {
|
|
757
887
|
return `
|
|
@@ -759,16 +889,22 @@ import '@clarify-labs/renderer/style.css';
|
|
|
759
889
|
import { render } from '@clarify-labs/renderer/client';
|
|
760
890
|
import { routes, navigation } from '${VIRTUAL_ROUTES}';
|
|
761
891
|
import { config } from '${VIRTUAL_CONFIG}';
|
|
762
|
-
import { openApis } from '${VIRTUAL_RUNTIME}';
|
|
763
|
-
render({ config, routes, navigation, openApis, themeEditor: ${JSON.stringify(options.themeEditor ?? false)} });`;
|
|
892
|
+
import { openApis, footerComponent } from '${VIRTUAL_RUNTIME}';
|
|
893
|
+
render({ config, routes, navigation, openApis, footerComponent, themeEditor: ${JSON.stringify(options.themeEditor ?? false)} });`;
|
|
764
894
|
}
|
|
765
895
|
function buildVirtualModules(args) {
|
|
766
896
|
const modules = /* @__PURE__ */ new Map();
|
|
767
897
|
const clientEntryModule = createClientEntryModule({ themeEditor: args.themeEditor });
|
|
898
|
+
const footerComponent = args.projectConfig.footer;
|
|
899
|
+
const footerComponentSource = typeof footerComponent === "string" ? "path" : void 0;
|
|
900
|
+
const footerComponentImport = typeof footerComponent === "string" ? footerComponent : void 0;
|
|
768
901
|
modules.set(VIRTUAL_CONFIG, generateConfigModule(args.projectConfig, args.generateOptions));
|
|
769
902
|
modules.set(VIRTUAL_ROUTES, generateRoutesModule(args.routes, args.navigation, args.projectConfig, "client"));
|
|
770
903
|
modules.set(VIRTUAL_SERVER_ROUTES, generateRoutesModule(args.routes, args.navigation, args.projectConfig, "server"));
|
|
771
|
-
modules.set(VIRTUAL_RUNTIME, createRuntimeModule(
|
|
904
|
+
modules.set(VIRTUAL_RUNTIME, createRuntimeModule({
|
|
905
|
+
footerComponentSource,
|
|
906
|
+
imports: { footerComponent: footerComponentImport }
|
|
907
|
+
}));
|
|
772
908
|
modules.set(VIRTUAL_CLIENT_ENTRY, clientEntryModule);
|
|
773
909
|
modules.set(RESOLVED_CLIENT_ENTRY, clientEntryModule);
|
|
774
910
|
for (const route of args.routes) modules.set(route.virtualModuleId, `export { default } from ${moduleSpecifier(route.filePath)};`);
|
|
@@ -777,8 +913,12 @@ function buildVirtualModules(args) {
|
|
|
777
913
|
//#endregion
|
|
778
914
|
//#region source/plugins/openapi/virtual-modules.ts
|
|
779
915
|
var openApiRegistryModuleId = VIRTUAL_RUNTIME;
|
|
780
|
-
function generateOpenAPIRegistryModule(openApis) {
|
|
781
|
-
|
|
916
|
+
function generateOpenAPIRegistryModule(openApis, runtimeModule = "") {
|
|
917
|
+
const openApisExport = `export const openApis = ${JSON.stringify(openApis)};`;
|
|
918
|
+
const openApisPlaceholder = /export const openApis = \{\};?/;
|
|
919
|
+
if (!runtimeModule) return openApisExport;
|
|
920
|
+
if (openApisPlaceholder.test(runtimeModule)) return runtimeModule.replace(openApisPlaceholder, openApisExport);
|
|
921
|
+
return runtimeModule;
|
|
782
922
|
}
|
|
783
923
|
function generateOpenAPIModule(spec, tagFilter) {
|
|
784
924
|
return `import { createElement } from 'react';
|
|
@@ -906,7 +1046,7 @@ function createOpenAPIPlugin() {
|
|
|
906
1046
|
return nextRoutes;
|
|
907
1047
|
},
|
|
908
1048
|
"modules:before": (modules, ctx) => {
|
|
909
|
-
modules.set(openApiRegistryModuleId, generateOpenAPIRegistryModule(Object.fromEntries(Object.entries(specs).map(([moduleId, entry]) => [moduleId, entry.spec]))));
|
|
1049
|
+
modules.set(openApiRegistryModuleId, generateOpenAPIRegistryModule(Object.fromEntries(Object.entries(specs).map(([moduleId, entry]) => [moduleId, entry.spec])), modules.get(openApiRegistryModuleId)));
|
|
910
1050
|
for (const [moduleId, entry] of Object.entries(specs)) modules.set(moduleId, generateOpenAPIModule(entry.spec, entry.tagFilter));
|
|
911
1051
|
for (const route of ctx.routes.filter((route) => route.kind === "openapi" && route.diagnostic)) if (route.diagnostic) modules.set(route.virtualModuleId, generateOpenAPIErrorModule(route.diagnostic));
|
|
912
1052
|
return modules;
|
|
@@ -915,6 +1055,180 @@ function createOpenAPIPlugin() {
|
|
|
915
1055
|
};
|
|
916
1056
|
}
|
|
917
1057
|
//#endregion
|
|
1058
|
+
//#region source/core/search-language.ts
|
|
1059
|
+
function toPagefindLanguage(locale) {
|
|
1060
|
+
return locale?.trim().replace(/_/g, "-").split("-").filter(Boolean).join("-").toLowerCase() || "en";
|
|
1061
|
+
}
|
|
1062
|
+
//#endregion
|
|
1063
|
+
//#region source/core/temp-dir.ts
|
|
1064
|
+
function createClarifyTempDir(name) {
|
|
1065
|
+
return mkdtempSync(join(tmpdir(), `clarify-${name}-`));
|
|
1066
|
+
}
|
|
1067
|
+
function removeClarifyTempDir(path) {
|
|
1068
|
+
if (!path) return;
|
|
1069
|
+
rmSync(path, {
|
|
1070
|
+
recursive: true,
|
|
1071
|
+
force: true
|
|
1072
|
+
});
|
|
1073
|
+
}
|
|
1074
|
+
//#endregion
|
|
1075
|
+
//#region source/plugins/search-index/index.ts
|
|
1076
|
+
var pagefindContentTypes = {
|
|
1077
|
+
".css": "text/css; charset=utf-8",
|
|
1078
|
+
".js": "text/javascript; charset=utf-8",
|
|
1079
|
+
".json": "application/json; charset=utf-8",
|
|
1080
|
+
".wasm": "application/wasm"
|
|
1081
|
+
};
|
|
1082
|
+
function assertNoPagefindErrors(action, errors) {
|
|
1083
|
+
if (!errors?.length) return;
|
|
1084
|
+
throw new Error(`[clarify] Pagefind ${action} failed:\n${errors.join("\n")}`);
|
|
1085
|
+
}
|
|
1086
|
+
async function generatePagefindIndex(options) {
|
|
1087
|
+
const pagefind = await import("pagefind");
|
|
1088
|
+
const { errors, index } = await pagefind.createIndex({
|
|
1089
|
+
excludeSelectors: [
|
|
1090
|
+
"[data-pagefind-ignore]",
|
|
1091
|
+
"script",
|
|
1092
|
+
"style",
|
|
1093
|
+
"svg"
|
|
1094
|
+
],
|
|
1095
|
+
includeCharacters: "._-/#:@",
|
|
1096
|
+
keepIndexUrl: false,
|
|
1097
|
+
verbose: false,
|
|
1098
|
+
writePlayground: false
|
|
1099
|
+
});
|
|
1100
|
+
assertNoPagefindErrors("createIndex", errors);
|
|
1101
|
+
if (!index) throw new Error("[clarify] Pagefind did not create an index.");
|
|
1102
|
+
try {
|
|
1103
|
+
const addResult = await index.addDirectory({
|
|
1104
|
+
path: options.sourceRoot ?? options.outputRoot,
|
|
1105
|
+
glob: "**/*.html"
|
|
1106
|
+
});
|
|
1107
|
+
assertNoPagefindErrors("addDirectory", addResult.errors);
|
|
1108
|
+
assertNoPagefindErrors("writeFiles", (await index.writeFiles({ outputPath: join(options.outputRoot, "pagefind") })).errors);
|
|
1109
|
+
return addResult.page_count;
|
|
1110
|
+
} finally {
|
|
1111
|
+
await index.deleteIndex();
|
|
1112
|
+
await pagefind.close();
|
|
1113
|
+
}
|
|
1114
|
+
}
|
|
1115
|
+
function routeSearchContent(route) {
|
|
1116
|
+
return [
|
|
1117
|
+
route.title,
|
|
1118
|
+
route.description,
|
|
1119
|
+
route.keywords?.join(" "),
|
|
1120
|
+
route.sections?.map((section) => section.title).join(" "),
|
|
1121
|
+
route.content
|
|
1122
|
+
].filter(Boolean).join("\n\n");
|
|
1123
|
+
}
|
|
1124
|
+
async function generateDevSearchIndex(ctx, root) {
|
|
1125
|
+
const pagefind = await import("pagefind");
|
|
1126
|
+
const { errors, index } = await pagefind.createIndex({
|
|
1127
|
+
includeCharacters: "._-/#:@",
|
|
1128
|
+
keepIndexUrl: false,
|
|
1129
|
+
verbose: false,
|
|
1130
|
+
writePlayground: false
|
|
1131
|
+
});
|
|
1132
|
+
assertNoPagefindErrors("createIndex", errors);
|
|
1133
|
+
if (!index) throw new Error("[clarify] Pagefind did not create an index.");
|
|
1134
|
+
try {
|
|
1135
|
+
let pageCount = 0;
|
|
1136
|
+
for (const route of ctx.routes) {
|
|
1137
|
+
const content = routeSearchContent(route);
|
|
1138
|
+
if (!content.trim()) continue;
|
|
1139
|
+
const result = await index.addCustomRecord({
|
|
1140
|
+
url: route.path,
|
|
1141
|
+
content,
|
|
1142
|
+
language: toPagefindLanguage(route.locale ?? ctx.projectConfig.i18n?.defaultLocale),
|
|
1143
|
+
meta: { title: route.title }
|
|
1144
|
+
});
|
|
1145
|
+
assertNoPagefindErrors(`addCustomRecord ${route.path}`, result.errors);
|
|
1146
|
+
pageCount += 1;
|
|
1147
|
+
}
|
|
1148
|
+
assertNoPagefindErrors("writeFiles", (await index.writeFiles({ outputPath: join(root, "pagefind") })).errors);
|
|
1149
|
+
console.log(`[clarify] Dev search index generated for ${pageCount} pages.`);
|
|
1150
|
+
} finally {
|
|
1151
|
+
await index.deleteIndex();
|
|
1152
|
+
await pagefind.close();
|
|
1153
|
+
}
|
|
1154
|
+
}
|
|
1155
|
+
function normalizeDevPagefindPath(rawUrl, routePrefix) {
|
|
1156
|
+
const pathname = rawUrl?.split("?")[0];
|
|
1157
|
+
if (!pathname) return void 0;
|
|
1158
|
+
const normalizedPrefix = routePrefix && routePrefix !== "/" ? `/${routePrefix.replace(/^\/+|\/+$/g, "")}` : "";
|
|
1159
|
+
const pagefindPath = normalizedPrefix && pathname.startsWith(`${normalizedPrefix}/pagefind/`) ? pathname.slice(normalizedPrefix.length) : pathname;
|
|
1160
|
+
return pagefindPath.startsWith("/pagefind/") ? pagefindPath : void 0;
|
|
1161
|
+
}
|
|
1162
|
+
function serveDevPagefind(server, getRoot, ctx) {
|
|
1163
|
+
server.middlewares.use((req, res, next) => {
|
|
1164
|
+
const root = getRoot();
|
|
1165
|
+
const pagefindPath = normalizeDevPagefindPath(req.url, ctx.projectConfig.routePrefix);
|
|
1166
|
+
if (!root || !pagefindPath) {
|
|
1167
|
+
next();
|
|
1168
|
+
return;
|
|
1169
|
+
}
|
|
1170
|
+
const filePath = join(root, pagefindPath);
|
|
1171
|
+
const relativePath = relative(root, filePath);
|
|
1172
|
+
if (relativePath.startsWith("..") || relativePath === "" || !existsSync(filePath)) {
|
|
1173
|
+
next();
|
|
1174
|
+
return;
|
|
1175
|
+
}
|
|
1176
|
+
const contentType = pagefindContentTypes[extname(filePath)] ?? "application/octet-stream";
|
|
1177
|
+
res.setHeader("Content-Type", contentType);
|
|
1178
|
+
createReadStream(filePath).pipe(res);
|
|
1179
|
+
});
|
|
1180
|
+
}
|
|
1181
|
+
function createSearchIndexPlugin() {
|
|
1182
|
+
return {
|
|
1183
|
+
name: "clarify:search-index",
|
|
1184
|
+
hooks: {
|
|
1185
|
+
async "dev:configureServer"(server, ctx) {
|
|
1186
|
+
let currentRoot;
|
|
1187
|
+
const staleRoots = /* @__PURE__ */ new Set();
|
|
1188
|
+
const replaceDevIndex = async () => {
|
|
1189
|
+
const nextRoot = createClarifyTempDir("pagefind");
|
|
1190
|
+
await generateDevSearchIndex(ctx, nextRoot);
|
|
1191
|
+
const previousRoot = currentRoot;
|
|
1192
|
+
currentRoot = nextRoot;
|
|
1193
|
+
if (previousRoot) {
|
|
1194
|
+
staleRoots.add(previousRoot);
|
|
1195
|
+
setTimeout(() => {
|
|
1196
|
+
staleRoots.delete(previousRoot);
|
|
1197
|
+
removeClarifyTempDir(previousRoot);
|
|
1198
|
+
}, 3e4).unref?.();
|
|
1199
|
+
}
|
|
1200
|
+
};
|
|
1201
|
+
serveDevPagefind(server, () => currentRoot, ctx);
|
|
1202
|
+
await replaceDevIndex();
|
|
1203
|
+
let regenerateTimer;
|
|
1204
|
+
const regenerate = (filePath) => {
|
|
1205
|
+
if (!/\.(md|mdx|json|ya?ml)$/i.test(filePath)) return;
|
|
1206
|
+
if (regenerateTimer) clearTimeout(regenerateTimer);
|
|
1207
|
+
regenerateTimer = setTimeout(() => {
|
|
1208
|
+
replaceDevIndex().catch((err) => {
|
|
1209
|
+
console.error("[clarify] Failed to regenerate dev search index:", err);
|
|
1210
|
+
});
|
|
1211
|
+
}, 100);
|
|
1212
|
+
};
|
|
1213
|
+
server.watcher.on("add", regenerate);
|
|
1214
|
+
server.watcher.on("change", regenerate);
|
|
1215
|
+
server.watcher.on("unlink", regenerate);
|
|
1216
|
+
server.httpServer?.once("close", () => {
|
|
1217
|
+
if (regenerateTimer) clearTimeout(regenerateTimer);
|
|
1218
|
+
removeClarifyTempDir(currentRoot);
|
|
1219
|
+
for (const staleRoot of staleRoots) removeClarifyTempDir(staleRoot);
|
|
1220
|
+
});
|
|
1221
|
+
},
|
|
1222
|
+
async "build:done"(ctx) {
|
|
1223
|
+
const outputDirectory = ctx.generateOptions.outputDirectory;
|
|
1224
|
+
if (!outputDirectory) return;
|
|
1225
|
+
const pageCount = await generatePagefindIndex({ outputRoot: resolve(ctx.generateOptions.projectRoot, outputDirectory) });
|
|
1226
|
+
console.log(`[clarify] Search index generated for ${pageCount} pages.`);
|
|
1227
|
+
}
|
|
1228
|
+
}
|
|
1229
|
+
};
|
|
1230
|
+
}
|
|
1231
|
+
//#endregion
|
|
918
1232
|
//#region source/plugins/seo/artifacts.ts
|
|
919
1233
|
function trimTrailingSlash(value) {
|
|
920
1234
|
return value.replace(/\/+$/, "");
|
|
@@ -1010,7 +1324,8 @@ function createBuiltinPlugins(options = {}) {
|
|
|
1010
1324
|
createOpenAPIPlugin(),
|
|
1011
1325
|
createSourceLinksPlugin(),
|
|
1012
1326
|
createContentArtifactsPlugin(),
|
|
1013
|
-
createSeoPlugin()
|
|
1327
|
+
createSeoPlugin(),
|
|
1328
|
+
createSearchIndexPlugin()
|
|
1014
1329
|
];
|
|
1015
1330
|
if (options.htmlShell ?? true) plugins.push(createHtmlShellPlugin());
|
|
1016
1331
|
return plugins;
|
|
@@ -1068,11 +1383,12 @@ var clarifyBannerConfigSchema = z.object({
|
|
|
1068
1383
|
content: clarifyLocalizedTextSchema,
|
|
1069
1384
|
dismissible: z.boolean().optional()
|
|
1070
1385
|
});
|
|
1071
|
-
var
|
|
1386
|
+
var clarifyFooterLinksConfigSchema = z.object({
|
|
1072
1387
|
links: z.array(clarifyNavbarLinkSchema).optional(),
|
|
1073
1388
|
socials: z.record(z.string(), z.string()).optional(),
|
|
1074
1389
|
copyright: clarifyLocalizedTextSchema.optional()
|
|
1075
|
-
});
|
|
1390
|
+
}).strict();
|
|
1391
|
+
var clarifyFooterConfigSchema = z.union([clarifyFooterLinksConfigSchema, z.string()]);
|
|
1076
1392
|
var clarifySourceConfigSchema = z.object({
|
|
1077
1393
|
repository: z.string(),
|
|
1078
1394
|
branch: z.string().optional(),
|
|
@@ -1156,78 +1472,6 @@ var clarifyProjectConfigSchema = z.object({
|
|
|
1156
1472
|
tabs: clarifyTabsConfigSchema.optional()
|
|
1157
1473
|
});
|
|
1158
1474
|
//#endregion
|
|
1159
|
-
//#region source/core/theme.ts
|
|
1160
|
-
var clarifyThemePresets = {
|
|
1161
|
-
default: {
|
|
1162
|
-
preset: "default",
|
|
1163
|
-
tokens: {
|
|
1164
|
-
colors: {
|
|
1165
|
-
primary: "#047857",
|
|
1166
|
-
accent: "#0D9488",
|
|
1167
|
-
background: "#ffffff",
|
|
1168
|
-
foreground: "#111827",
|
|
1169
|
-
surface: "#ffffff",
|
|
1170
|
-
muted: "#64748b",
|
|
1171
|
-
border: "rgb(15 23 42 / 0.12)",
|
|
1172
|
-
codeBackground: "#f6fbf8"
|
|
1173
|
-
},
|
|
1174
|
-
radius: {
|
|
1175
|
-
sm: "6px",
|
|
1176
|
-
md: "10px",
|
|
1177
|
-
lg: "14px",
|
|
1178
|
-
xl: "18px"
|
|
1179
|
-
}
|
|
1180
|
-
},
|
|
1181
|
-
layout: { maxWidth: "82rem" },
|
|
1182
|
-
editor: false
|
|
1183
|
-
},
|
|
1184
|
-
base: {
|
|
1185
|
-
preset: "base",
|
|
1186
|
-
tokens: {
|
|
1187
|
-
colors: {
|
|
1188
|
-
primary: "#18181b",
|
|
1189
|
-
accent: "#52525b",
|
|
1190
|
-
background: "#ffffff",
|
|
1191
|
-
foreground: "#18181b",
|
|
1192
|
-
surface: "#ffffff",
|
|
1193
|
-
muted: "#71717a",
|
|
1194
|
-
border: "rgb(24 24 27 / 0.12)",
|
|
1195
|
-
codeBackground: "#f4f4f5"
|
|
1196
|
-
},
|
|
1197
|
-
radius: {
|
|
1198
|
-
sm: "6px",
|
|
1199
|
-
md: "8px",
|
|
1200
|
-
lg: "12px",
|
|
1201
|
-
xl: "16px"
|
|
1202
|
-
}
|
|
1203
|
-
},
|
|
1204
|
-
layout: { maxWidth: "80rem" },
|
|
1205
|
-
editor: false
|
|
1206
|
-
}
|
|
1207
|
-
};
|
|
1208
|
-
function resolveThemeConfig(theme = {}) {
|
|
1209
|
-
const preset = theme.preset ?? "default";
|
|
1210
|
-
const presetTheme = clarifyThemePresets[preset];
|
|
1211
|
-
return {
|
|
1212
|
-
preset,
|
|
1213
|
-
tokens: {
|
|
1214
|
-
colors: {
|
|
1215
|
-
...presetTheme.tokens.colors,
|
|
1216
|
-
...theme.tokens?.colors
|
|
1217
|
-
},
|
|
1218
|
-
radius: {
|
|
1219
|
-
...presetTheme.tokens.radius,
|
|
1220
|
-
...theme.tokens?.radius
|
|
1221
|
-
}
|
|
1222
|
-
},
|
|
1223
|
-
layout: {
|
|
1224
|
-
...presetTheme.layout,
|
|
1225
|
-
...theme.layout
|
|
1226
|
-
},
|
|
1227
|
-
editor: theme.editor ?? presetTheme.editor
|
|
1228
|
-
};
|
|
1229
|
-
}
|
|
1230
|
-
//#endregion
|
|
1231
1475
|
//#region source/core/config.ts
|
|
1232
1476
|
function formatIssuePath(path) {
|
|
1233
1477
|
return path.reduce((result, segment) => {
|
|
@@ -1521,13 +1765,13 @@ function routeOutputFiles(outputDirectory, route) {
|
|
|
1521
1765
|
var SSR_ENTRY_CODE = `import { renderToHTML } from '@clarify-labs/renderer/server';
|
|
1522
1766
|
import { routes, navigation } from 'virtual:clarify-routes/server';
|
|
1523
1767
|
import { config } from 'virtual:clarify-config';
|
|
1524
|
-
import { openApis } from 'virtual:clarify-runtime';
|
|
1768
|
+
import { openApis, footerComponent } from 'virtual:clarify-runtime';
|
|
1525
1769
|
|
|
1526
1770
|
export function render(url) {
|
|
1527
|
-
return renderToHTML({ config, routes, navigation, openApis, url, themeEditor: config.theme.editor });
|
|
1771
|
+
return renderToHTML({ config, routes, navigation, openApis, footerComponent, url, themeEditor: config.theme.editor });
|
|
1528
1772
|
}`;
|
|
1529
1773
|
function createTempEntryFile(content) {
|
|
1530
|
-
const entryPath = join(
|
|
1774
|
+
const entryPath = join(createClarifyTempDir("ssr"), "entry-server.ts");
|
|
1531
1775
|
writeFileSync(entryPath, content, "utf-8");
|
|
1532
1776
|
return entryPath;
|
|
1533
1777
|
}
|
|
@@ -1567,6 +1811,7 @@ async function renderSSGRoutes(routes, projectConfig, outputDirectory, ssrBundle
|
|
|
1567
1811
|
//#endregion
|
|
1568
1812
|
//#region source/core/user-config.ts
|
|
1569
1813
|
function defineConfig(config) {
|
|
1814
|
+
validateProjectConfig(config);
|
|
1570
1815
|
return config;
|
|
1571
1816
|
}
|
|
1572
1817
|
var CONFIG_FILENAMES = [
|
|
@@ -1817,6 +2062,6 @@ function clarifyPlugin(options = {}) {
|
|
|
1817
2062
|
].flat().filter(Boolean);
|
|
1818
2063
|
}
|
|
1819
2064
|
//#endregion
|
|
1820
|
-
export { resolveClarifySite as a, createClarifyRuntimeAliases as i, defineConfig as n, loadClarifyConfig as r, clarifyPlugin as t };
|
|
2065
|
+
export { resolveClarifySite as a, createClarifyRuntimeAliases as i, defineConfig as n, createClarifyTempDir as o, loadClarifyConfig as r, clarifyPlugin as t };
|
|
1821
2066
|
|
|
1822
|
-
//# sourceMappingURL=plugin-
|
|
2067
|
+
//# sourceMappingURL=plugin-BNzlJ4o7.js.map
|