@clarify-labs/cli 0.8.0 → 0.8.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -0
- package/output/cli/program.d.ts +2 -0
- package/output/cli.cjs +32 -10
- package/output/cli.cjs.map +1 -1
- package/output/cli.js +32 -10
- package/output/cli.js.map +1 -1
- package/output/core/config-schema.d.ts +5 -0
- package/output/core/content.d.ts +5 -0
- package/output/core/options.d.ts +1 -1
- package/output/index.cjs +1 -1
- package/output/index.js +1 -1
- package/output/parsers/content.d.ts +11 -0
- package/output/parsers/routes.d.ts +6 -2
- package/output/parsers/variables.d.ts +2 -0
- package/output/{plugin-CcD5HeTN.js → plugin-D5EF3pYl.js} +259 -71
- package/output/plugin-D5EF3pYl.js.map +1 -0
- package/output/{plugin-B7c0iHMy.cjs → plugin-DyceHdXd.cjs} +259 -71
- package/output/plugin-DyceHdXd.cjs.map +1 -0
- package/output/plugins/openapi/parser.d.ts +2 -1
- package/output/plugins/variables/index.d.ts +2 -0
- package/output/types.d.ts +20 -0
- package/package.json +3 -3
- package/output/plugin-B7c0iHMy.cjs.map +0 -1
- package/output/plugin-CcD5HeTN.js.map +0 -1
|
@@ -9,12 +9,12 @@ import shiki from "shiki";
|
|
|
9
9
|
import { visit } from "unist-util-visit";
|
|
10
10
|
import { markdownRemarkPlugins, themeBootstrapScript, themePresets } from "@clarify-labs/renderer";
|
|
11
11
|
import { stringify } from "yaml";
|
|
12
|
-
import { remark } from "remark";
|
|
13
12
|
import matter from "gray-matter";
|
|
13
|
+
import { remark } from "remark";
|
|
14
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
14
15
|
import SwaggerParser from "@apidevtools/swagger-parser";
|
|
15
16
|
import { tmpdir } from "node:os";
|
|
16
17
|
import { z } from "zod";
|
|
17
|
-
import { pathToFileURL } from "node:url";
|
|
18
18
|
import { build, loadConfigFromFile } from "vite";
|
|
19
19
|
import { createRequire } from "node:module";
|
|
20
20
|
//#region source/core/utils.ts
|
|
@@ -140,23 +140,76 @@ function readRouteArtifactContent(route) {
|
|
|
140
140
|
const content = readRouteContent(route);
|
|
141
141
|
return shouldUseUtf8Signature(route) ? withUtf8Signature(content) : content;
|
|
142
142
|
}
|
|
143
|
+
function isLlmsTxtRoute(route) {
|
|
144
|
+
return !route.path.split("/").includes("404");
|
|
145
|
+
}
|
|
146
|
+
function llmsTxtDescription(route) {
|
|
147
|
+
if (route.description) return route.description;
|
|
148
|
+
const sections = route.sections?.filter((section) => section.level === 2).slice(0, 3).map((section) => section.title);
|
|
149
|
+
if (sections?.length) return `Covers ${sections.join(", ")}.`;
|
|
150
|
+
if (route.keywords?.length) return `Related topics: ${route.keywords.join(", ")}.`;
|
|
151
|
+
if (route.kind === "openapi") return "OpenAPI artifact for machine-readable API reference data.";
|
|
152
|
+
}
|
|
153
|
+
function llmsTxtListItem(route, basePath) {
|
|
154
|
+
if (!route.contentArtifactUrl) return void 0;
|
|
155
|
+
const description = llmsTxtDescription(route);
|
|
156
|
+
return description ? `- [${route.title}](${basePath}${route.contentArtifactUrl}): ${description}` : `- [${route.title}](${basePath}${route.contentArtifactUrl})`;
|
|
157
|
+
}
|
|
158
|
+
function llmsTxtLocaleLabel(locale, projectConfig) {
|
|
159
|
+
return projectConfig.i18n?.locales.find((item) => item.code === locale)?.label ?? locale;
|
|
160
|
+
}
|
|
161
|
+
function groupRoutesByLocale(routes) {
|
|
162
|
+
const groups = /* @__PURE__ */ new Map();
|
|
163
|
+
for (const route of routes) {
|
|
164
|
+
const key = route.locale ?? "default";
|
|
165
|
+
groups.set(key, [...groups.get(key) ?? [], route]);
|
|
166
|
+
}
|
|
167
|
+
return groups;
|
|
168
|
+
}
|
|
169
|
+
function groupLlmsTxtRoutesByLocale(routes, projectConfig) {
|
|
170
|
+
const routesBySource = /* @__PURE__ */ new Map();
|
|
171
|
+
const defaultLocale = projectConfig.i18n?.defaultLocale;
|
|
172
|
+
for (const route of routes) {
|
|
173
|
+
const sourceKey = `${route.locale ?? defaultLocale ?? "default"}:${route.basePath ?? route.contentArtifactUrl ?? route.path}`;
|
|
174
|
+
const previousRoute = routesBySource.get(sourceKey);
|
|
175
|
+
if (!previousRoute || previousRoute.locale && !route.locale) routesBySource.set(sourceKey, route);
|
|
176
|
+
}
|
|
177
|
+
return groupRoutesByLocale([...routesBySource.values()].map((route) => ({
|
|
178
|
+
...route,
|
|
179
|
+
locale: route.locale ?? defaultLocale
|
|
180
|
+
})));
|
|
181
|
+
}
|
|
182
|
+
function llmsTxtDocsSectionTitle(locale, groupCount, projectConfig) {
|
|
183
|
+
if (groupCount <= 1) return "Docs";
|
|
184
|
+
return `Docs - ${locale === "default" ? "Default" : llmsTxtLocaleLabel(locale, projectConfig)}`;
|
|
185
|
+
}
|
|
143
186
|
function createLlmsTxt(routes, projectConfig) {
|
|
144
187
|
const basePath = normalizeBasePath(projectConfig.routePrefix);
|
|
145
188
|
const lines = [`# ${projectConfig.title}`, ""];
|
|
146
189
|
if (projectConfig.description) lines.push(`> ${projectConfig.description}`, "");
|
|
147
|
-
lines.push("
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
190
|
+
lines.push("This file lists the source-ready Markdown and OpenAPI artifacts for this documentation site.", "");
|
|
191
|
+
const mdxRoutes = routes.filter((route) => route.kind === "mdx" && isLlmsTxtRoute(route));
|
|
192
|
+
if (mdxRoutes.length > 0) {
|
|
193
|
+
const localizedGroups = groupLlmsTxtRoutesByLocale(mdxRoutes, projectConfig);
|
|
194
|
+
for (const [locale, localeRoutes] of localizedGroups) {
|
|
195
|
+
lines.push(`## ${llmsTxtDocsSectionTitle(locale, localizedGroups.size, projectConfig)}`);
|
|
196
|
+
for (const route of localeRoutes) {
|
|
197
|
+
const item = llmsTxtListItem(route, basePath);
|
|
198
|
+
if (item) lines.push(item);
|
|
199
|
+
}
|
|
200
|
+
lines.push("");
|
|
201
|
+
}
|
|
151
202
|
}
|
|
152
|
-
const openApiRoutes = routes.filter((route) => route.kind === "openapi");
|
|
203
|
+
const openApiRoutes = routes.filter((route) => route.kind === "openapi" && isLlmsTxtRoute(route));
|
|
153
204
|
if (openApiRoutes.length > 0) {
|
|
154
|
-
lines.
|
|
205
|
+
if (lines.at(-1) !== "") lines.push("");
|
|
206
|
+
lines.push("## OpenAPI");
|
|
155
207
|
for (const route of openApiRoutes) {
|
|
156
|
-
|
|
157
|
-
lines.push(
|
|
208
|
+
const item = llmsTxtListItem(route, basePath);
|
|
209
|
+
if (item) lines.push(item);
|
|
158
210
|
}
|
|
159
211
|
}
|
|
212
|
+
while (lines.at(-1) === "") lines.pop();
|
|
160
213
|
return `${lines.join("\n")}\n`;
|
|
161
214
|
}
|
|
162
215
|
function createLlmsTxtArtifact(routes, projectConfig) {
|
|
@@ -316,6 +369,101 @@ function parseFrontmatter(content) {
|
|
|
316
369
|
};
|
|
317
370
|
}
|
|
318
371
|
//#endregion
|
|
372
|
+
//#region source/parsers/content.ts
|
|
373
|
+
async function transformContent(transform, input) {
|
|
374
|
+
return transform ? await transform(input) : input;
|
|
375
|
+
}
|
|
376
|
+
function createContentProcessor(transform) {
|
|
377
|
+
return {
|
|
378
|
+
async processMdx(source, filePath) {
|
|
379
|
+
const { frontmatter, content } = parseFrontmatter(source);
|
|
380
|
+
const transformed = await transformContent(transform, {
|
|
381
|
+
kind: "mdx",
|
|
382
|
+
source,
|
|
383
|
+
filePath,
|
|
384
|
+
frontmatter,
|
|
385
|
+
content
|
|
386
|
+
});
|
|
387
|
+
return {
|
|
388
|
+
frontmatter: transformed.frontmatter,
|
|
389
|
+
content: transformed.content
|
|
390
|
+
};
|
|
391
|
+
},
|
|
392
|
+
async processText(source, kind, filePath) {
|
|
393
|
+
return (await transformContent(transform, {
|
|
394
|
+
kind,
|
|
395
|
+
source,
|
|
396
|
+
filePath,
|
|
397
|
+
frontmatter: {},
|
|
398
|
+
content: source
|
|
399
|
+
})).content;
|
|
400
|
+
}
|
|
401
|
+
};
|
|
402
|
+
}
|
|
403
|
+
//#endregion
|
|
404
|
+
//#region source/core/hooks.ts
|
|
405
|
+
async function runHooks(plugins, hookName, input, ctx) {
|
|
406
|
+
let result = input;
|
|
407
|
+
for (const plugin of plugins) {
|
|
408
|
+
const hook = plugin.hooks?.[hookName];
|
|
409
|
+
if (!hook) continue;
|
|
410
|
+
try {
|
|
411
|
+
result = await hook(result, ctx);
|
|
412
|
+
} catch (err) {
|
|
413
|
+
throw new Error(`[clarify] plugin "${plugin.name}" hook "${hookName}" failed: ${err}`, { cause: err });
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
return result;
|
|
417
|
+
}
|
|
418
|
+
async function runDevConfigureServerHooks(plugins, server, ctx) {
|
|
419
|
+
for (const plugin of plugins) {
|
|
420
|
+
const hook = plugin.hooks?.["dev:configureServer"];
|
|
421
|
+
if (!hook) continue;
|
|
422
|
+
try {
|
|
423
|
+
await hook(server, ctx);
|
|
424
|
+
} catch (err) {
|
|
425
|
+
throw new Error(`[clarify] plugin "${plugin.name}" hook "dev:configureServer" failed: ${err}`, { cause: err });
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
async function runBuildAssetsHooks(plugins, ctx) {
|
|
430
|
+
const assets = [];
|
|
431
|
+
for (const plugin of plugins) {
|
|
432
|
+
const hook = plugin.hooks?.["build:assets"];
|
|
433
|
+
if (!hook) continue;
|
|
434
|
+
try {
|
|
435
|
+
const pluginAssets = await hook(ctx);
|
|
436
|
+
assets.push(...pluginAssets);
|
|
437
|
+
} catch (err) {
|
|
438
|
+
throw new Error(`[clarify] plugin "${plugin.name}" hook "build:assets" failed: ${err}`, { cause: err });
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
return assets;
|
|
442
|
+
}
|
|
443
|
+
async function runBuildDoneHooks(plugins, ctx) {
|
|
444
|
+
for (const plugin of plugins) {
|
|
445
|
+
const hook = plugin.hooks?.["build:done"];
|
|
446
|
+
if (!hook) continue;
|
|
447
|
+
try {
|
|
448
|
+
await hook(ctx);
|
|
449
|
+
} catch (err) {
|
|
450
|
+
throw new Error(`[clarify] plugin "${plugin.name}" hook "build:done" failed: ${err}`, { cause: err });
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
//#endregion
|
|
455
|
+
//#region source/core/content.ts
|
|
456
|
+
var contentProcessors = /* @__PURE__ */ new WeakMap();
|
|
457
|
+
function createProjectContentProcessor(plugins, ctx) {
|
|
458
|
+
return createContentProcessor((input) => runHooks(plugins, "content:transform", input, ctx));
|
|
459
|
+
}
|
|
460
|
+
function setProjectContentProcessor(ctx, processor) {
|
|
461
|
+
contentProcessors.set(ctx, processor);
|
|
462
|
+
}
|
|
463
|
+
function getProjectContentProcessor(ctx) {
|
|
464
|
+
return contentProcessors.get(ctx);
|
|
465
|
+
}
|
|
466
|
+
//#endregion
|
|
319
467
|
//#region source/parsers/routes.ts
|
|
320
468
|
function kebabToTitle(str) {
|
|
321
469
|
return str.split("-").map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
|
|
@@ -392,18 +540,19 @@ function resolveLocalizedText(text, locale, fallbackLocale) {
|
|
|
392
540
|
if (text === void 0) return void 0;
|
|
393
541
|
return text[locale] ?? (fallbackLocale ? text[fallbackLocale] : void 0) ?? Object.values(text)[0];
|
|
394
542
|
}
|
|
395
|
-
function findContentRoutes(dir, base = dir) {
|
|
543
|
+
async function findContentRoutes(dir, base = dir, options = {}) {
|
|
396
544
|
const routes = [];
|
|
397
545
|
if (!existsSync(dir)) return routes;
|
|
398
546
|
const entries = readdirSync(dir, { withFileTypes: true });
|
|
399
547
|
for (const entry of entries) {
|
|
400
548
|
const fullPath = join(dir, entry.name);
|
|
401
|
-
if (entry.isDirectory()) routes.push(...findContentRoutes(fullPath, base));
|
|
549
|
+
if (entry.isDirectory()) routes.push(...await findContentRoutes(fullPath, base, options));
|
|
402
550
|
else if (entry.isFile() && /\.mdx?$/.test(entry.name)) {
|
|
403
551
|
const relativePath = relative(base, fullPath);
|
|
404
552
|
const pathParts = relativePath.replace(/\.mdx?$/, "").split("/");
|
|
405
553
|
const cleanPath = ("/" + pathParts.map((p) => p === "index" ? "" : p).filter(Boolean).join("/")).replace(/\/+/g, "/").replace(/\/$/, "") || "/";
|
|
406
|
-
const
|
|
554
|
+
const source = readFileSync(fullPath, "utf-8");
|
|
555
|
+
const { frontmatter, content } = await (options.contentProcessor ?? createContentProcessor()).processMdx(source, fullPath);
|
|
407
556
|
let title = typeof frontmatter.title === "string" ? frontmatter.title : "";
|
|
408
557
|
if (!title) {
|
|
409
558
|
const lastPart = pathParts[pathParts.length - 1] ?? "";
|
|
@@ -660,6 +809,13 @@ var OPENAPI_HTTP_METHODS = [
|
|
|
660
809
|
function errorMessage(error) {
|
|
661
810
|
return error instanceof Error ? error.message : String(error);
|
|
662
811
|
}
|
|
812
|
+
function isSameOpenAPIFile(url, filePath) {
|
|
813
|
+
try {
|
|
814
|
+
return resolve(fileURLToPath(url)) === resolve(filePath);
|
|
815
|
+
} catch {
|
|
816
|
+
return resolve(url) === resolve(filePath);
|
|
817
|
+
}
|
|
818
|
+
}
|
|
663
819
|
function findOpenAPIRoutes(dir, base = dir) {
|
|
664
820
|
const routes = [];
|
|
665
821
|
if (!existsSync(dir)) return routes;
|
|
@@ -723,12 +879,26 @@ function extractOpenAPISections(spec, filterTags) {
|
|
|
723
879
|
}
|
|
724
880
|
return sections;
|
|
725
881
|
}
|
|
726
|
-
async function readOpenAPISpec(filePath) {
|
|
882
|
+
async function readOpenAPISpec(filePath, contentProcessor) {
|
|
727
883
|
try {
|
|
728
|
-
return {
|
|
884
|
+
if (!contentProcessor) return {
|
|
729
885
|
ok: true,
|
|
730
886
|
spec: await SwaggerParser.dereference(filePath)
|
|
731
887
|
};
|
|
888
|
+
const source = readFileSync(filePath, "utf-8");
|
|
889
|
+
const transformedSource = await contentProcessor.processText(source, "openapi", filePath);
|
|
890
|
+
if (transformedSource === source) return {
|
|
891
|
+
ok: true,
|
|
892
|
+
spec: await SwaggerParser.dereference(filePath)
|
|
893
|
+
};
|
|
894
|
+
return {
|
|
895
|
+
ok: true,
|
|
896
|
+
spec: await SwaggerParser.dereference(filePath, { resolve: { transformedOpenAPISource: {
|
|
897
|
+
order: 1,
|
|
898
|
+
canRead: (file) => isSameOpenAPIFile(file.url, filePath),
|
|
899
|
+
read: () => transformedSource
|
|
900
|
+
} } })
|
|
901
|
+
};
|
|
732
902
|
} catch (error) {
|
|
733
903
|
return {
|
|
734
904
|
ok: false,
|
|
@@ -989,7 +1159,7 @@ function createOpenAPIPlugin() {
|
|
|
989
1159
|
const result = specFromCache ? {
|
|
990
1160
|
ok: true,
|
|
991
1161
|
spec: specFromCache
|
|
992
|
-
} : await readOpenAPISpec(route.filePath);
|
|
1162
|
+
} : await readOpenAPISpec(route.filePath, getProjectContentProcessor(ctx));
|
|
993
1163
|
if (!result.ok) {
|
|
994
1164
|
route.diagnostic = result.diagnostic;
|
|
995
1165
|
route.title = route.title || "OpenAPI parse error";
|
|
@@ -1306,9 +1476,51 @@ function createSourceLinksPlugin() {
|
|
|
1306
1476
|
};
|
|
1307
1477
|
}
|
|
1308
1478
|
//#endregion
|
|
1479
|
+
//#region source/parsers/variables.ts
|
|
1480
|
+
var variablePattern = /{{\s*([A-Za-z0-9_-]+(?:\.[A-Za-z0-9_-]+)*)\s*}}/g;
|
|
1481
|
+
function getVariableValue(variables, path) {
|
|
1482
|
+
let current = variables;
|
|
1483
|
+
for (const segment of path.split(".")) {
|
|
1484
|
+
if (!current || typeof current !== "object" || Array.isArray(current)) return void 0;
|
|
1485
|
+
current = current[segment];
|
|
1486
|
+
}
|
|
1487
|
+
return current;
|
|
1488
|
+
}
|
|
1489
|
+
function stringifyVariableValue(variables, path, stack) {
|
|
1490
|
+
if (stack.includes(path)) throw new Error(`[clarify] variable "${path}" contains a circular reference: ${[...stack, path].join(" -> ")}`);
|
|
1491
|
+
const value = getVariableValue(variables, path);
|
|
1492
|
+
if (value === void 0 || typeof value === "object") return void 0;
|
|
1493
|
+
if (typeof value !== "string") return String(value);
|
|
1494
|
+
return value.replace(variablePattern, (match, nestedPath) => stringifyVariableValue(variables, nestedPath, [...stack, path]) ?? match);
|
|
1495
|
+
}
|
|
1496
|
+
function applyVariables(content, variables = {}) {
|
|
1497
|
+
return content.replace(variablePattern, (match, path) => stringifyVariableValue(variables, path, []) ?? match);
|
|
1498
|
+
}
|
|
1499
|
+
//#endregion
|
|
1500
|
+
//#region source/plugins/variables/index.ts
|
|
1501
|
+
function applyVariablesToFrontmatter(frontmatter, variables) {
|
|
1502
|
+
const nextFrontmatter = { ...frontmatter };
|
|
1503
|
+
for (const key of ["title", "description"]) {
|
|
1504
|
+
if (typeof nextFrontmatter[key] !== "string") continue;
|
|
1505
|
+
nextFrontmatter[key] = applyVariables(nextFrontmatter[key], variables);
|
|
1506
|
+
}
|
|
1507
|
+
return nextFrontmatter;
|
|
1508
|
+
}
|
|
1509
|
+
function createVariablesPlugin() {
|
|
1510
|
+
return {
|
|
1511
|
+
name: "clarify:variables",
|
|
1512
|
+
hooks: { "content:transform": (input, ctx) => ({
|
|
1513
|
+
...input,
|
|
1514
|
+
frontmatter: applyVariablesToFrontmatter(input.frontmatter, ctx.projectConfig.variables),
|
|
1515
|
+
content: applyVariables(input.content, ctx.projectConfig.variables)
|
|
1516
|
+
}) }
|
|
1517
|
+
};
|
|
1518
|
+
}
|
|
1519
|
+
//#endregion
|
|
1309
1520
|
//#region source/core/builtin.ts
|
|
1310
1521
|
function createBuiltinPlugins(options = {}) {
|
|
1311
1522
|
const plugins = [
|
|
1523
|
+
createVariablesPlugin(),
|
|
1312
1524
|
createOpenAPIPlugin(),
|
|
1313
1525
|
createSourceLinksPlugin(),
|
|
1314
1526
|
createContentArtifactsPlugin(),
|
|
@@ -1377,6 +1589,13 @@ var clarifyFooterConfigSchema = z.object({
|
|
|
1377
1589
|
socials: z.record(z.string(), z.string()).optional(),
|
|
1378
1590
|
copyright: clarifyLocalizedTextSchema.optional()
|
|
1379
1591
|
}).strict();
|
|
1592
|
+
var clarifyVariableValueSchema = z.lazy(() => z.union([
|
|
1593
|
+
z.string(),
|
|
1594
|
+
z.number(),
|
|
1595
|
+
z.boolean(),
|
|
1596
|
+
z.record(z.string(), clarifyVariableValueSchema)
|
|
1597
|
+
]));
|
|
1598
|
+
var clarifyVariablesConfigSchema = z.record(z.string(), clarifyVariableValueSchema);
|
|
1380
1599
|
var clarifySourceConfigSchema = z.object({
|
|
1381
1600
|
repository: z.string(),
|
|
1382
1601
|
branch: z.string().optional(),
|
|
@@ -1454,9 +1673,11 @@ var clarifyProjectConfigSchema = z.object({
|
|
|
1454
1673
|
favicon: clarifyFaviconConfigSchema.optional(),
|
|
1455
1674
|
theme: clarifyThemeConfigSchema.optional(),
|
|
1456
1675
|
routePrefix: z.string().optional(),
|
|
1676
|
+
assetPrefix: z.string().optional(),
|
|
1457
1677
|
navbar: z.object({ links: z.array(clarifyNavbarLinkSchema).optional() }).optional(),
|
|
1458
1678
|
banner: clarifyBannerConfigSchema.optional(),
|
|
1459
1679
|
footer: clarifyFooterConfigSchema.optional(),
|
|
1680
|
+
variables: clarifyVariablesConfigSchema.optional(),
|
|
1460
1681
|
i18n: clarifyI18nConfigSchema.optional(),
|
|
1461
1682
|
tabs: clarifyTabsConfigSchema.optional()
|
|
1462
1683
|
});
|
|
@@ -1516,7 +1737,22 @@ function resolveI18nConfig(i18n) {
|
|
|
1516
1737
|
locales: i18n.locales
|
|
1517
1738
|
};
|
|
1518
1739
|
}
|
|
1740
|
+
function resolveRoutePrefix(routePrefix) {
|
|
1741
|
+
const trimmed = routePrefix?.trim();
|
|
1742
|
+
if (!trimmed || trimmed === "/") return "/";
|
|
1743
|
+
return `/${trimmed.replace(/^\/+|\/+$/g, "")}/`;
|
|
1744
|
+
}
|
|
1745
|
+
function resolveAssetPrefix(assetPrefix, routePrefix) {
|
|
1746
|
+
const trimmed = assetPrefix?.trim();
|
|
1747
|
+
if (trimmed === void 0) return routePrefix;
|
|
1748
|
+
if (trimmed === "./" || trimmed === "") return trimmed || "/";
|
|
1749
|
+
if (!trimmed || trimmed === "/") return "/";
|
|
1750
|
+
if (/^[a-z][a-z\d+.-]*:\/\//i.test(trimmed)) return trimmed.endsWith("/") ? trimmed : `${trimmed}/`;
|
|
1751
|
+
if (trimmed.startsWith("./") || trimmed.startsWith("../")) return trimmed.endsWith("/") ? trimmed : `${trimmed}/`;
|
|
1752
|
+
return `/${trimmed.replace(/^\/+|\/+$/g, "")}/`;
|
|
1753
|
+
}
|
|
1519
1754
|
function resolveProjectConfig(config = {}) {
|
|
1755
|
+
const routePrefix = resolveRoutePrefix(config.routePrefix);
|
|
1520
1756
|
return {
|
|
1521
1757
|
title: config.title ?? "Clarify Docs",
|
|
1522
1758
|
description: config.description ?? "",
|
|
@@ -1525,11 +1761,13 @@ function resolveProjectConfig(config = {}) {
|
|
|
1525
1761
|
logo: config.logo,
|
|
1526
1762
|
homeUrl: config.homeUrl,
|
|
1527
1763
|
favicon: config.favicon,
|
|
1528
|
-
routePrefix
|
|
1764
|
+
routePrefix,
|
|
1765
|
+
assetPrefix: resolveAssetPrefix(config.assetPrefix, routePrefix),
|
|
1529
1766
|
theme: resolveThemeConfig(config.theme),
|
|
1530
1767
|
navbar: config.navbar,
|
|
1531
1768
|
banner: config.banner,
|
|
1532
1769
|
footer: config.footer,
|
|
1770
|
+
variables: config.variables ?? {},
|
|
1533
1771
|
i18n: resolveI18nConfig(config.i18n),
|
|
1534
1772
|
tabs: config.tabs
|
|
1535
1773
|
};
|
|
@@ -1583,57 +1821,6 @@ function writeClarifyEnvDts(projectRoot, plugins) {
|
|
|
1583
1821
|
writeFileSync(filePath, next, "utf-8");
|
|
1584
1822
|
}
|
|
1585
1823
|
//#endregion
|
|
1586
|
-
//#region source/core/hooks.ts
|
|
1587
|
-
async function runHooks(plugins, hookName, input, ctx) {
|
|
1588
|
-
let result = input;
|
|
1589
|
-
for (const plugin of plugins) {
|
|
1590
|
-
const hook = plugin.hooks?.[hookName];
|
|
1591
|
-
if (!hook) continue;
|
|
1592
|
-
try {
|
|
1593
|
-
result = await hook(result, ctx);
|
|
1594
|
-
} catch (err) {
|
|
1595
|
-
throw new Error(`[clarify] plugin "${plugin.name}" hook "${hookName}" failed: ${err}`, { cause: err });
|
|
1596
|
-
}
|
|
1597
|
-
}
|
|
1598
|
-
return result;
|
|
1599
|
-
}
|
|
1600
|
-
async function runDevConfigureServerHooks(plugins, server, ctx) {
|
|
1601
|
-
for (const plugin of plugins) {
|
|
1602
|
-
const hook = plugin.hooks?.["dev:configureServer"];
|
|
1603
|
-
if (!hook) continue;
|
|
1604
|
-
try {
|
|
1605
|
-
await hook(server, ctx);
|
|
1606
|
-
} catch (err) {
|
|
1607
|
-
throw new Error(`[clarify] plugin "${plugin.name}" hook "dev:configureServer" failed: ${err}`, { cause: err });
|
|
1608
|
-
}
|
|
1609
|
-
}
|
|
1610
|
-
}
|
|
1611
|
-
async function runBuildAssetsHooks(plugins, ctx) {
|
|
1612
|
-
const assets = [];
|
|
1613
|
-
for (const plugin of plugins) {
|
|
1614
|
-
const hook = plugin.hooks?.["build:assets"];
|
|
1615
|
-
if (!hook) continue;
|
|
1616
|
-
try {
|
|
1617
|
-
const pluginAssets = await hook(ctx);
|
|
1618
|
-
assets.push(...pluginAssets);
|
|
1619
|
-
} catch (err) {
|
|
1620
|
-
throw new Error(`[clarify] plugin "${plugin.name}" hook "build:assets" failed: ${err}`, { cause: err });
|
|
1621
|
-
}
|
|
1622
|
-
}
|
|
1623
|
-
return assets;
|
|
1624
|
-
}
|
|
1625
|
-
async function runBuildDoneHooks(plugins, ctx) {
|
|
1626
|
-
for (const plugin of plugins) {
|
|
1627
|
-
const hook = plugin.hooks?.["build:done"];
|
|
1628
|
-
if (!hook) continue;
|
|
1629
|
-
try {
|
|
1630
|
-
await hook(ctx);
|
|
1631
|
-
} catch (err) {
|
|
1632
|
-
throw new Error(`[clarify] plugin "${plugin.name}" hook "build:done" failed: ${err}`, { cause: err });
|
|
1633
|
-
}
|
|
1634
|
-
}
|
|
1635
|
-
}
|
|
1636
|
-
//#endregion
|
|
1637
1824
|
//#region source/core/options.ts
|
|
1638
1825
|
function resolveBuildOptions(options = {}) {
|
|
1639
1826
|
return {
|
|
@@ -1649,7 +1836,7 @@ async function discoverRoutesForRoot(routeRoot, locale, plugins, ctx) {
|
|
|
1649
1836
|
return (await runHooks(plugins, "routes:discover", {
|
|
1650
1837
|
contentRoot: routeRoot,
|
|
1651
1838
|
locale,
|
|
1652
|
-
routes: findContentRoutes(routeRoot)
|
|
1839
|
+
routes: await findContentRoutes(routeRoot, routeRoot, { contentProcessor: getProjectContentProcessor(ctx) })
|
|
1653
1840
|
}, ctx)).routes;
|
|
1654
1841
|
}
|
|
1655
1842
|
async function discoverRoutes(root, contentRoot, plugins, ctx) {
|
|
@@ -1714,6 +1901,7 @@ async function resolveClarifySite(options = {}, resolveOptions = {}) {
|
|
|
1714
1901
|
routes: [],
|
|
1715
1902
|
navigation: []
|
|
1716
1903
|
};
|
|
1904
|
+
setProjectContentProcessor(ctx, createProjectContentProcessor(plugins, ctx));
|
|
1717
1905
|
let routes = await discoverRoutes(root, contentRoot, plugins, ctx);
|
|
1718
1906
|
routes = await runHooks(plugins, "routes:discovered", routes, ctx);
|
|
1719
1907
|
routes = applyConfiguredPageRoutePaths(routes, projectConfig.tabs, projectConfig.i18n);
|
|
@@ -2042,7 +2230,7 @@ function clarifyPlugin(options = {}) {
|
|
|
2042
2230
|
async config() {
|
|
2043
2231
|
await resolveRoutesAndSpecs();
|
|
2044
2232
|
return {
|
|
2045
|
-
base: projectConfig.
|
|
2233
|
+
base: projectConfig.assetPrefix,
|
|
2046
2234
|
build: {
|
|
2047
2235
|
...generateOptions.outputDirectory ? { outDir: generateOptions.outputDirectory } : {},
|
|
2048
2236
|
manifest: true
|
|
@@ -2182,4 +2370,4 @@ function clarifyPlugin(options = {}) {
|
|
|
2182
2370
|
//#endregion
|
|
2183
2371
|
export { resolveClarifySite as a, createClarifyRuntimeAliases as i, defineConfig as n, createClarifyTempDir as o, loadClarifyConfig as r, clarifyPlugin as t };
|
|
2184
2372
|
|
|
2185
|
-
//# sourceMappingURL=plugin-
|
|
2373
|
+
//# sourceMappingURL=plugin-D5EF3pYl.js.map
|