@clarify-labs/cli 0.10.3 → 0.11.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 +1 -1
- package/output/cli.js +1 -1
- package/output/core/config/config-schema.d.ts +191 -92
- package/output/core/config/config.d.ts +2 -1
- package/output/core/config/options.d.ts +0 -8
- package/output/core/config/user-config.d.ts +4 -3
- package/output/core/project/project-info.d.ts +3 -3
- package/output/core/runtime/ssg.d.ts +1 -1
- package/output/core/runtime/virtual-modules.d.ts +1 -1
- package/output/{engine-BDdPszs2.cjs → engine-BfkoyVNo.cjs} +193 -146
- package/output/engine-BfkoyVNo.cjs.map +1 -0
- package/output/{engine-CyFtr8Pz.js → engine-DfF5RJjC.js} +193 -146
- package/output/engine-DfF5RJjC.js.map +1 -0
- package/output/index.cjs +1 -1
- package/output/index.js +1 -1
- package/output/parsers/routes/routes.d.ts +7 -7
- package/output/parsers/routes/routes.test-utils.d.ts +2 -2
- package/output/plugins/source-links/source-links.d.ts +3 -3
- package/output/types.d.ts +63 -33
- package/package.json +3 -3
- package/output/engine-BDdPszs2.cjs.map +0 -1
- package/output/engine-CyFtr8Pz.js.map +0 -1
|
@@ -410,10 +410,10 @@ function frontmatterKeywords(frontmatter) {
|
|
|
410
410
|
const keywords = Array.isArray(value) ? value.filter((item) => typeof item === "string") : typeof value === "string" ? value.split(",").map((keyword) => keyword.trim()).filter(Boolean) : [];
|
|
411
411
|
return keywords.length > 0 ? keywords : void 0;
|
|
412
412
|
}
|
|
413
|
-
function withAlternates(route, routes,
|
|
413
|
+
function withAlternates(route, routes, locales) {
|
|
414
414
|
const basePath = route.basePath ?? route.path;
|
|
415
415
|
const routeByLocaleAndBase = new Map(routes.filter((r) => !r.locale || r.path === `/${r.locale}` || r.path.startsWith(`/${r.locale}/`)).map((r) => [`${r.locale ?? ""}:${r.basePath ?? r.path}`, r]));
|
|
416
|
-
const alternates = Object.fromEntries(
|
|
416
|
+
const alternates = Object.fromEntries(locales.locales.flatMap((locale) => {
|
|
417
417
|
const alternate = routeByLocaleAndBase.get(`${locale.code}:${basePath}`);
|
|
418
418
|
return alternate ? [[locale.code, alternate.path]] : [];
|
|
419
419
|
}));
|
|
@@ -426,11 +426,11 @@ function withAlternates(route, routes, i18n) {
|
|
|
426
426
|
* 为默认语言的 locale-prefixed 路由生成无前缀的"裸路径别名",方便不带语言
|
|
427
427
|
* 前缀的 URL 也能访问。标记 `isBareAlias` 以便搜索索引生成时过滤重复索引。
|
|
428
428
|
*/
|
|
429
|
-
function generateBareAliases(routes,
|
|
429
|
+
function generateBareAliases(routes, locales) {
|
|
430
430
|
const bareRoutes = [];
|
|
431
431
|
const seenBare = new Set(routes.map((r) => r.path));
|
|
432
432
|
for (const route of routes) {
|
|
433
|
-
if (route.locale !==
|
|
433
|
+
if (route.locale !== locales.default) continue;
|
|
434
434
|
const bp = route.basePath ?? route.path;
|
|
435
435
|
if (bp === route.path || seenBare.has(bp)) continue;
|
|
436
436
|
seenBare.add(bp);
|
|
@@ -442,42 +442,42 @@ function generateBareAliases(routes, i18n) {
|
|
|
442
442
|
}
|
|
443
443
|
return bareRoutes;
|
|
444
444
|
}
|
|
445
|
-
async function findLocalizedContentRoutes(contentRoot,
|
|
446
|
-
if (!
|
|
445
|
+
async function findLocalizedContentRoutes(contentRoot, locales, options = {}) {
|
|
446
|
+
if (!locales) return findContentRoutes(contentRoot, contentRoot, options);
|
|
447
447
|
const localizedRoutes = [];
|
|
448
|
-
for (const locale of
|
|
448
|
+
for (const locale of locales.locales) {
|
|
449
449
|
const localeRoot = (0, node_path.join)(contentRoot, locale.code);
|
|
450
450
|
const discovered = await findContentRoutes(localeRoot, localeRoot, options);
|
|
451
451
|
for (const route of discovered) {
|
|
452
452
|
const basePath = route.basePath ?? route.path;
|
|
453
453
|
localizedRoutes.push({
|
|
454
454
|
...route,
|
|
455
|
-
path: localizedRoutePath(basePath, locale.code,
|
|
455
|
+
path: localizedRoutePath(basePath, locale.code, locales),
|
|
456
456
|
basePath,
|
|
457
457
|
locale: locale.code,
|
|
458
458
|
module: { virtualModuleId: virtualModuleIdForLocalizedRoute(contentRoot, route.source.filePath) }
|
|
459
459
|
});
|
|
460
460
|
}
|
|
461
461
|
}
|
|
462
|
-
if (
|
|
462
|
+
if (locales.missing === "fallback") {
|
|
463
463
|
const routeByLocaleAndBase = new Map(localizedRoutes.map((route) => [`${route.locale ?? ""}:${route.basePath ?? route.path}`, route]));
|
|
464
|
-
const defaultRoutes = localizedRoutes.filter((route) => route.locale ===
|
|
464
|
+
const defaultRoutes = localizedRoutes.filter((route) => route.locale === locales.default);
|
|
465
465
|
for (const sourceRoute of defaultRoutes) {
|
|
466
466
|
const basePath = sourceRoute.basePath ?? sourceRoute.path;
|
|
467
|
-
for (const locale of
|
|
467
|
+
for (const locale of locales.locales) {
|
|
468
468
|
const key = `${locale.code}:${basePath}`;
|
|
469
469
|
if (routeByLocaleAndBase.has(key)) continue;
|
|
470
470
|
localizedRoutes.push({
|
|
471
471
|
...sourceRoute,
|
|
472
|
-
path: localizedRoutePath(basePath, locale.code,
|
|
472
|
+
path: localizedRoutePath(basePath, locale.code, locales),
|
|
473
473
|
locale: locale.code,
|
|
474
474
|
isFallback: true
|
|
475
475
|
});
|
|
476
476
|
}
|
|
477
477
|
}
|
|
478
478
|
}
|
|
479
|
-
const routesWithAlternates = localizedRoutes.map((route) => withAlternates(route, localizedRoutes,
|
|
480
|
-
return [...routesWithAlternates, ...generateBareAliases(routesWithAlternates,
|
|
479
|
+
const routesWithAlternates = localizedRoutes.map((route) => withAlternates(route, localizedRoutes, locales));
|
|
480
|
+
return [...routesWithAlternates, ...generateBareAliases(routesWithAlternates, locales)];
|
|
481
481
|
}
|
|
482
482
|
function buildNavigation(routes) {
|
|
483
483
|
const root = [];
|
|
@@ -554,7 +554,7 @@ function collectExplicitPagePathIntents(tabs) {
|
|
|
554
554
|
}
|
|
555
555
|
return intents;
|
|
556
556
|
}
|
|
557
|
-
function applyConfiguredPageRoutePaths(routes, tabs,
|
|
557
|
+
function applyConfiguredPageRoutePaths(routes, tabs, locales) {
|
|
558
558
|
const pageIntents = collectExplicitPagePathIntents(tabs);
|
|
559
559
|
if (!pageIntents.length) return routes;
|
|
560
560
|
const additions = [];
|
|
@@ -570,15 +570,15 @@ function applyConfiguredPageRoutePaths(routes, tabs, i18n) {
|
|
|
570
570
|
existingKeys.add(key);
|
|
571
571
|
additions.push({
|
|
572
572
|
...route,
|
|
573
|
-
path: route.locale &&
|
|
573
|
+
path: route.locale && locales ? localizedRoutePath(targetBasePath, route.locale, locales) : targetBasePath,
|
|
574
574
|
basePath: targetBasePath
|
|
575
575
|
});
|
|
576
576
|
}
|
|
577
577
|
}
|
|
578
578
|
const nextRoutes = [...routes, ...additions];
|
|
579
|
-
const routesWithAlternates =
|
|
580
|
-
if (!
|
|
581
|
-
return [...routesWithAlternates, ...generateBareAliases(routesWithAlternates,
|
|
579
|
+
const routesWithAlternates = locales ? nextRoutes.map((route) => withAlternates(route, nextRoutes, locales)) : nextRoutes;
|
|
580
|
+
if (!locales) return routesWithAlternates;
|
|
581
|
+
return [...routesWithAlternates, ...generateBareAliases(routesWithAlternates, locales)];
|
|
582
582
|
}
|
|
583
583
|
function buildNavigationFromPagesConfig(routes, config) {
|
|
584
584
|
if (!config || config === "FileTree") return buildNavigation(routes);
|
|
@@ -641,25 +641,25 @@ function buildNavigationFromConfig(routes, config) {
|
|
|
641
641
|
};
|
|
642
642
|
});
|
|
643
643
|
}
|
|
644
|
-
function localizeNavigationPaths(nodes, locale,
|
|
644
|
+
function localizeNavigationPaths(nodes, locale, locales) {
|
|
645
645
|
return nodes.map((node) => ({
|
|
646
646
|
...node,
|
|
647
|
-
path: localizedRoutePath(node.path, locale,
|
|
648
|
-
children: node.children ? localizeNavigationPaths(node.children, locale,
|
|
647
|
+
path: localizedRoutePath(node.path, locale, locales),
|
|
648
|
+
children: node.children ? localizeNavigationPaths(node.children, locale, locales) : void 0
|
|
649
649
|
}));
|
|
650
650
|
}
|
|
651
|
-
function buildLocalizedNavigationForLocale(routes, config, locale,
|
|
651
|
+
function buildLocalizedNavigationForLocale(routes, config, locale, locales) {
|
|
652
652
|
if (!config || config === "FileTree") return localizeNavigationPaths(buildNavigation(routes.map((route) => ({
|
|
653
653
|
...route,
|
|
654
654
|
path: route.basePath ?? route.path
|
|
655
|
-
}))), locale,
|
|
655
|
+
}))), locale, locales);
|
|
656
656
|
const routeMap = new Map(routes.map((route) => [route.basePath ?? route.path, route]));
|
|
657
657
|
const buildItem = (item) => {
|
|
658
658
|
if (typeof item !== "string" && "group" in item) {
|
|
659
659
|
const children = item.pages.map(buildItem);
|
|
660
660
|
return {
|
|
661
661
|
path: firstNavigationPath(children),
|
|
662
|
-
title: resolveLocalizedText(item.group, locale,
|
|
662
|
+
title: resolveLocalizedText(item.group, locale, locales.default) ?? "",
|
|
663
663
|
icon: item.icon,
|
|
664
664
|
children
|
|
665
665
|
};
|
|
@@ -667,10 +667,10 @@ function buildLocalizedNavigationForLocale(routes, config, locale, i18n) {
|
|
|
667
667
|
const intent = routeIntentFromPagesItem(item);
|
|
668
668
|
const basePath = intent.kind === "openapi" ? openAPIPagePathFromRef(intent.ref, intent.tagFilter, intent.path) : routePathFromRef(intent.ref, intent.path);
|
|
669
669
|
const route = routeMap.get(basePath);
|
|
670
|
-
const path = route?.path ?? localizedRoutePath(basePath, locale,
|
|
670
|
+
const path = route?.path ?? localizedRoutePath(basePath, locale, locales);
|
|
671
671
|
return {
|
|
672
|
-
path: (intent.kind === "page" && intent.redirect ? localizedRoutePath(routePathFromRef(intent.redirect), locale,
|
|
673
|
-
title: resolveLocalizedText(intent.title, locale,
|
|
672
|
+
path: (intent.kind === "page" && intent.redirect ? localizedRoutePath(routePathFromRef(intent.redirect), locale, locales) : void 0) ?? path,
|
|
673
|
+
title: resolveLocalizedText(intent.title, locale, locales.default) ?? route?.meta.title ?? kebabToTitle(basePath.split("/").pop() ?? intent.ref),
|
|
674
674
|
icon: intent.icon,
|
|
675
675
|
sections: route?.meta.sections ? navigationSections(route.meta.sections) : void 0
|
|
676
676
|
};
|
|
@@ -678,24 +678,24 @@ function buildLocalizedNavigationForLocale(routes, config, locale, i18n) {
|
|
|
678
678
|
return config.map((group) => {
|
|
679
679
|
const children = group.pages.map(buildItem);
|
|
680
680
|
return {
|
|
681
|
-
path: children[0]?.path ?? localizedRoutePath("/", locale,
|
|
682
|
-
title: resolveLocalizedText(group.group, locale,
|
|
681
|
+
path: children[0]?.path ?? localizedRoutePath("/", locale, locales),
|
|
682
|
+
title: resolveLocalizedText(group.group, locale, locales.default) ?? "",
|
|
683
683
|
icon: group.icon,
|
|
684
684
|
children
|
|
685
685
|
};
|
|
686
686
|
});
|
|
687
687
|
}
|
|
688
|
-
function buildLocalizedNavigationFromTabsConfig(routes, tabs,
|
|
689
|
-
if (!
|
|
688
|
+
function buildLocalizedNavigationFromTabsConfig(routes, tabs, localesConfig) {
|
|
689
|
+
if (!localesConfig) return void 0;
|
|
690
690
|
const locales = {};
|
|
691
|
-
for (const locale of
|
|
691
|
+
for (const locale of localesConfig.locales) {
|
|
692
692
|
const localeRoutes = routes.filter((route) => route.locale === locale.code);
|
|
693
693
|
locales[locale.code] = { tabs: tabs.map((tab) => {
|
|
694
|
-
const children = buildLocalizedNavigationForLocale(localeRoutes, tab.pages, locale.code,
|
|
694
|
+
const children = buildLocalizedNavigationForLocale(localeRoutes, tab.pages, locale.code, localesConfig);
|
|
695
695
|
return {
|
|
696
696
|
type: "tab",
|
|
697
697
|
path: firstNavigationPath(children),
|
|
698
|
-
title: resolveLocalizedText(tab.tab, locale.code,
|
|
698
|
+
title: resolveLocalizedText(tab.tab, locale.code, localesConfig.default) ?? "",
|
|
699
699
|
icon: tab.icon,
|
|
700
700
|
children
|
|
701
701
|
};
|
|
@@ -762,7 +762,7 @@ function inferRouteForFile(filePath, contentRoot, defaultLocale) {
|
|
|
762
762
|
const localeSegmentIndex = fileLocale ? segments.indexOf(fileLocale) : -1;
|
|
763
763
|
const basePath = basePathFromRef(localeSegmentIndex >= 0 ? segments.slice(localeSegmentIndex + 1).join("/") : ref);
|
|
764
764
|
const path = fileLocale && defaultLocale ? localizedRoutePath(basePath, fileLocale, {
|
|
765
|
-
defaultLocale,
|
|
765
|
+
default: defaultLocale,
|
|
766
766
|
missing: "fallback",
|
|
767
767
|
locales: []
|
|
768
768
|
}) : basePath;
|
|
@@ -815,12 +815,12 @@ async function handleDevRouteRequest(req, res, routes, context) {
|
|
|
815
815
|
}
|
|
816
816
|
const file = typeof body === "object" && body !== null ? body.file : void 0;
|
|
817
817
|
if (typeof file === "string" && file.length > 0) {
|
|
818
|
-
const route = resolveRouteForFile(file, routes, context.projectConfig.
|
|
818
|
+
const route = resolveRouteForFile(file, routes, context.projectConfig.locales?.default);
|
|
819
819
|
if (route) {
|
|
820
820
|
res.end(JSON.stringify(toDevRouteEntry(route)));
|
|
821
821
|
return;
|
|
822
822
|
}
|
|
823
|
-
const inferred = inferRouteForFile(file, context.contentRoot, context.projectConfig.
|
|
823
|
+
const inferred = inferRouteForFile(file, context.contentRoot, context.projectConfig.locales?.default);
|
|
824
824
|
res.end(JSON.stringify(inferred));
|
|
825
825
|
return;
|
|
826
826
|
}
|
|
@@ -846,8 +846,7 @@ function resolveThemeConfig(theme = {}) {
|
|
|
846
846
|
layout: {
|
|
847
847
|
...presetTheme.layout,
|
|
848
848
|
...theme.layout
|
|
849
|
-
}
|
|
850
|
-
editor: theme.editor ?? presetTheme.editor
|
|
849
|
+
}
|
|
851
850
|
};
|
|
852
851
|
}
|
|
853
852
|
//#endregion
|
|
@@ -855,26 +854,26 @@ function resolveThemeConfig(theme = {}) {
|
|
|
855
854
|
var clarifyLogoConfigSchema = zod.z.union([zod.z.string(), zod.z.object({
|
|
856
855
|
light: zod.z.string().optional(),
|
|
857
856
|
dark: zod.z.string().optional()
|
|
858
|
-
})]);
|
|
857
|
+
}).strict()]);
|
|
859
858
|
var clarifyFaviconConfigSchema = zod.z.union([zod.z.string(), zod.z.object({
|
|
860
859
|
light: zod.z.string().optional(),
|
|
861
860
|
dark: zod.z.string().optional()
|
|
862
|
-
})]);
|
|
861
|
+
}).strict()]);
|
|
863
862
|
var clarifyLocalizedTextSchema = zod.z.union([zod.z.string(), zod.z.record(zod.z.string(), zod.z.string())]);
|
|
864
863
|
var clarifyLocaleConfigSchema = zod.z.object({
|
|
865
864
|
code: zod.z.string(),
|
|
866
865
|
label: zod.z.string(),
|
|
867
866
|
dir: zod.z.union([zod.z.literal("ltr"), zod.z.literal("rtl")]).optional()
|
|
868
|
-
});
|
|
869
|
-
var
|
|
870
|
-
|
|
867
|
+
}).strict();
|
|
868
|
+
var clarifyLocalesConfigSchema = zod.z.object({
|
|
869
|
+
default: zod.z.string().optional(),
|
|
871
870
|
missing: zod.z.union([
|
|
872
871
|
zod.z.literal("fallback"),
|
|
873
872
|
zod.z.literal("404"),
|
|
874
873
|
zod.z.literal("hide")
|
|
875
874
|
]).optional(),
|
|
876
875
|
locales: zod.z.array(clarifyLocaleConfigSchema).min(1)
|
|
877
|
-
}).superRefine((config, ctx) => {
|
|
876
|
+
}).strict().superRefine((config, ctx) => {
|
|
878
877
|
const localeCodes = /* @__PURE__ */ new Set();
|
|
879
878
|
for (const [index, locale] of config.locales.entries()) {
|
|
880
879
|
if (localeCodes.has(locale.code)) ctx.addIssue({
|
|
@@ -888,17 +887,17 @@ var clarifyI18nConfigSchema = zod.z.object({
|
|
|
888
887
|
});
|
|
889
888
|
localeCodes.add(locale.code);
|
|
890
889
|
}
|
|
891
|
-
if (config.
|
|
890
|
+
if (config.default && !localeCodes.has(config.default)) ctx.addIssue({
|
|
892
891
|
code: zod.z.ZodIssueCode.custom,
|
|
893
|
-
message: "
|
|
894
|
-
path: ["
|
|
892
|
+
message: "default must be one of locales.locales",
|
|
893
|
+
path: ["default"]
|
|
895
894
|
});
|
|
896
895
|
});
|
|
897
896
|
var clarifyNavbarLinkSchema = zod.z.object({
|
|
898
897
|
label: clarifyLocalizedTextSchema,
|
|
899
898
|
href: zod.z.string(),
|
|
900
899
|
external: zod.z.boolean().optional()
|
|
901
|
-
});
|
|
900
|
+
}).strict();
|
|
902
901
|
var clarifyBannerConfigOptionsSchema = zod.z.object({
|
|
903
902
|
content: clarifyLocalizedTextSchema,
|
|
904
903
|
dismissible: zod.z.boolean().optional(),
|
|
@@ -916,11 +915,11 @@ var clarifyVariableValueSchema = zod.z.lazy(() => zod.z.union([
|
|
|
916
915
|
zod.z.record(zod.z.string(), clarifyVariableValueSchema)
|
|
917
916
|
]));
|
|
918
917
|
var clarifyVariablesConfigSchema = zod.z.record(zod.z.string(), clarifyVariableValueSchema);
|
|
919
|
-
var
|
|
920
|
-
|
|
918
|
+
var clarifyRepositoryConfigSchema = zod.z.object({
|
|
919
|
+
url: zod.z.string().optional(),
|
|
921
920
|
branch: zod.z.string().optional(),
|
|
922
921
|
directory: zod.z.string().optional()
|
|
923
|
-
});
|
|
922
|
+
}).strict();
|
|
924
923
|
var clarifyPagesItemSchema = zod.z.lazy(() => zod.z.union([
|
|
925
924
|
zod.z.string(),
|
|
926
925
|
clarifyPagesGroupSchema,
|
|
@@ -930,32 +929,32 @@ var clarifyPagesItemSchema = zod.z.lazy(() => zod.z.union([
|
|
|
930
929
|
title: clarifyLocalizedTextSchema.optional(),
|
|
931
930
|
icon: zod.z.string().optional(),
|
|
932
931
|
redirect: zod.z.string().optional()
|
|
933
|
-
}),
|
|
932
|
+
}).strict(),
|
|
934
933
|
zod.z.object({
|
|
935
934
|
openapi: zod.z.string(),
|
|
936
935
|
path: zod.z.string().optional(),
|
|
937
936
|
icon: zod.z.string().optional(),
|
|
938
937
|
title: clarifyLocalizedTextSchema.optional(),
|
|
939
|
-
filter: zod.z.object({ tags: zod.z.array(zod.z.string()).optional() }).optional()
|
|
940
|
-
})
|
|
938
|
+
filter: zod.z.object({ tags: zod.z.array(zod.z.string()).optional() }).strict().optional()
|
|
939
|
+
}).strict()
|
|
941
940
|
]));
|
|
942
941
|
var clarifyPagesGroupSchema = zod.z.lazy(() => zod.z.object({
|
|
943
942
|
group: clarifyLocalizedTextSchema,
|
|
944
943
|
icon: zod.z.string().optional(),
|
|
945
944
|
pages: zod.z.array(clarifyPagesItemSchema)
|
|
946
|
-
}));
|
|
945
|
+
}).strict());
|
|
947
946
|
var clarifyPagesConfigSchema = zod.z.union([zod.z.array(clarifyPagesGroupSchema), zod.z.literal("FileTree")]);
|
|
948
947
|
var clarifyTabItemSchema = zod.z.object({
|
|
949
948
|
tab: clarifyLocalizedTextSchema,
|
|
950
949
|
icon: zod.z.string().optional(),
|
|
951
950
|
pages: clarifyPagesConfigSchema.optional()
|
|
952
|
-
});
|
|
951
|
+
}).strict();
|
|
953
952
|
var clarifyTabsConfigSchema = zod.z.array(clarifyTabItemSchema);
|
|
954
953
|
var clarifyThemePresetSchema = zod.z.enum(["default", "base"]);
|
|
955
954
|
var clarifyThemeModeColorValueSchema = zod.z.object({
|
|
956
955
|
light: zod.z.string().optional(),
|
|
957
956
|
dark: zod.z.string().optional()
|
|
958
|
-
});
|
|
957
|
+
}).strict();
|
|
959
958
|
var clarifyThemeColorValueSchema = zod.z.union([zod.z.string(), clarifyThemeModeColorValueSchema]);
|
|
960
959
|
var clarifyThemeColorTokensConfigSchema = zod.z.object({
|
|
961
960
|
primary: clarifyThemeColorValueSchema.optional(),
|
|
@@ -966,42 +965,65 @@ var clarifyThemeColorTokensConfigSchema = zod.z.object({
|
|
|
966
965
|
muted: clarifyThemeColorValueSchema.optional(),
|
|
967
966
|
border: clarifyThemeColorValueSchema.optional(),
|
|
968
967
|
codeBackground: clarifyThemeColorValueSchema.optional()
|
|
969
|
-
});
|
|
968
|
+
}).strict();
|
|
970
969
|
var clarifyThemeRadiusTokensConfigSchema = zod.z.object({
|
|
971
970
|
sm: zod.z.string().optional(),
|
|
972
971
|
md: zod.z.string().optional(),
|
|
973
972
|
lg: zod.z.string().optional(),
|
|
974
973
|
xl: zod.z.string().optional()
|
|
975
|
-
});
|
|
974
|
+
}).strict();
|
|
976
975
|
var clarifyThemeTokensConfigSchema = zod.z.object({
|
|
977
976
|
colors: clarifyThemeColorTokensConfigSchema.optional(),
|
|
978
977
|
radius: clarifyThemeRadiusTokensConfigSchema.optional()
|
|
979
|
-
});
|
|
980
|
-
var clarifyThemeLayoutConfigSchema = zod.z.object({ maxWidth: zod.z.string().optional() });
|
|
978
|
+
}).strict();
|
|
979
|
+
var clarifyThemeLayoutConfigSchema = zod.z.object({ maxWidth: zod.z.string().optional() }).strict();
|
|
981
980
|
var clarifyThemeConfigSchema = zod.z.object({
|
|
982
981
|
preset: clarifyThemePresetSchema.optional(),
|
|
983
982
|
tokens: clarifyThemeTokensConfigSchema.optional(),
|
|
984
|
-
layout: clarifyThemeLayoutConfigSchema.optional()
|
|
985
|
-
|
|
986
|
-
|
|
983
|
+
layout: clarifyThemeLayoutConfigSchema.optional()
|
|
984
|
+
}).strict();
|
|
985
|
+
function featureSchema(shape, defaults) {
|
|
986
|
+
const objectSchema = zod.z.object({
|
|
987
|
+
enabled: zod.z.boolean().default(true),
|
|
988
|
+
...shape
|
|
989
|
+
}).strict().default({
|
|
990
|
+
enabled: true,
|
|
991
|
+
...defaults
|
|
992
|
+
});
|
|
993
|
+
return zod.z.union([zod.z.boolean(), objectSchema]).default({
|
|
994
|
+
enabled: true,
|
|
995
|
+
...defaults
|
|
996
|
+
}).transform((value) => typeof value === "boolean" ? {
|
|
997
|
+
enabled: value,
|
|
998
|
+
...defaults
|
|
999
|
+
} : value);
|
|
1000
|
+
}
|
|
1001
|
+
var clarifyFeaturesConfigSchema = zod.z.object({
|
|
1002
|
+
search: featureSchema({ provider: zod.z.literal("pagefind").default("pagefind") }, { provider: "pagefind" }),
|
|
1003
|
+
repository: featureSchema(clarifyRepositoryConfigSchema.shape, {}),
|
|
1004
|
+
themeEditor: featureSchema({}, {}),
|
|
1005
|
+
openapi: featureSchema({ playground: zod.z.boolean().default(true) }, { playground: true })
|
|
1006
|
+
}).strict();
|
|
987
1007
|
var clarifyProjectConfigSchema = zod.z.object({
|
|
988
1008
|
title: zod.z.string().optional(),
|
|
989
1009
|
description: zod.z.string().optional(),
|
|
990
1010
|
siteUrl: zod.z.string().optional(),
|
|
991
|
-
|
|
1011
|
+
routePrefix: zod.z.string().default("/"),
|
|
1012
|
+
assetPrefix: zod.z.string().optional(),
|
|
992
1013
|
logo: clarifyLogoConfigSchema.optional(),
|
|
993
1014
|
homeUrl: zod.z.string().optional(),
|
|
994
1015
|
favicon: clarifyFaviconConfigSchema.optional(),
|
|
995
1016
|
theme: clarifyThemeConfigSchema.optional(),
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
1017
|
+
navigation: zod.z.object({
|
|
1018
|
+
links: zod.z.array(clarifyNavbarLinkSchema).optional(),
|
|
1019
|
+
tabs: clarifyTabsConfigSchema.optional()
|
|
1020
|
+
}).strict().optional(),
|
|
999
1021
|
banner: clarifyBannerConfigOptionsSchema.optional(),
|
|
1000
1022
|
footer: clarifyFooterConfigSchema.optional(),
|
|
1023
|
+
locales: clarifyLocalesConfigSchema.optional(),
|
|
1001
1024
|
variables: clarifyVariablesConfigSchema.optional(),
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
});
|
|
1025
|
+
features: clarifyFeaturesConfigSchema.optional()
|
|
1026
|
+
}).strict();
|
|
1005
1027
|
//#endregion
|
|
1006
1028
|
//#region source/core/config/config.ts
|
|
1007
1029
|
function formatIssuePath(path) {
|
|
@@ -1023,17 +1045,20 @@ function validateProjectConfig(value) {
|
|
|
1023
1045
|
if (!result.success) throw new Error(formatProjectConfigError(result.error));
|
|
1024
1046
|
return result.data;
|
|
1025
1047
|
}
|
|
1026
|
-
function
|
|
1027
|
-
if (!
|
|
1028
|
-
const firstLocale =
|
|
1029
|
-
const defaultLocale =
|
|
1048
|
+
function resolveLocalesConfig(locales) {
|
|
1049
|
+
if (!locales) return void 0;
|
|
1050
|
+
const firstLocale = locales.locales[0]?.code;
|
|
1051
|
+
const defaultLocale = locales.default ?? firstLocale;
|
|
1030
1052
|
if (!defaultLocale) return void 0;
|
|
1031
1053
|
return {
|
|
1032
|
-
defaultLocale,
|
|
1033
|
-
missing:
|
|
1034
|
-
locales:
|
|
1054
|
+
default: defaultLocale,
|
|
1055
|
+
missing: locales.missing ?? "fallback",
|
|
1056
|
+
locales: locales.locales
|
|
1035
1057
|
};
|
|
1036
1058
|
}
|
|
1059
|
+
function resolveFeaturesConfig(features = {}) {
|
|
1060
|
+
return clarifyFeaturesConfigSchema.parse(features);
|
|
1061
|
+
}
|
|
1037
1062
|
function resolveRoutePrefix(routePrefix) {
|
|
1038
1063
|
const trimmed = routePrefix?.trim();
|
|
1039
1064
|
if (!trimmed || trimmed === "/") return "/";
|
|
@@ -1054,26 +1079,24 @@ function resolveProjectConfig(config = {}) {
|
|
|
1054
1079
|
title: config.title ?? "Clarify Docs",
|
|
1055
1080
|
description: config.description ?? "",
|
|
1056
1081
|
siteUrl: config.siteUrl,
|
|
1057
|
-
|
|
1082
|
+
routePrefix,
|
|
1083
|
+
assetPrefix: resolveAssetPrefix(config.assetPrefix, routePrefix),
|
|
1058
1084
|
logo: config.logo,
|
|
1059
1085
|
homeUrl: config.homeUrl,
|
|
1060
1086
|
favicon: config.favicon,
|
|
1061
|
-
routePrefix,
|
|
1062
|
-
assetPrefix: resolveAssetPrefix(config.assetPrefix, routePrefix),
|
|
1063
1087
|
theme: resolveThemeConfig(config.theme),
|
|
1064
|
-
|
|
1088
|
+
navigation: config.navigation,
|
|
1065
1089
|
banner: config.banner,
|
|
1066
1090
|
footer: config.footer,
|
|
1091
|
+
locales: resolveLocalesConfig(config.locales),
|
|
1067
1092
|
variables: config.variables ?? {},
|
|
1068
|
-
|
|
1069
|
-
tabs: config.tabs
|
|
1093
|
+
features: resolveFeaturesConfig(config.features)
|
|
1070
1094
|
};
|
|
1071
1095
|
}
|
|
1072
1096
|
//#endregion
|
|
1073
1097
|
//#region source/core/config/user-config.ts
|
|
1074
1098
|
function defineConfig(config) {
|
|
1075
|
-
|
|
1076
|
-
return config;
|
|
1099
|
+
return validateClarifyConfig(config);
|
|
1077
1100
|
}
|
|
1078
1101
|
/**
|
|
1079
1102
|
* Config filenames Clarify CLI looks for at the project root, in resolution
|
|
@@ -1097,18 +1120,23 @@ function assertConfigObject(config, configFile) {
|
|
|
1097
1120
|
}
|
|
1098
1121
|
function loadJsonConfig(configFile) {
|
|
1099
1122
|
const config = assertConfigObject(JSON.parse((0, node_fs.readFileSync)(configFile, "utf-8")), configFile);
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1123
|
+
if ("plugins" in config) throw new Error("[clarify] clarify.json does not support plugins; use clarify.ts or clarify.js");
|
|
1124
|
+
return validateClarifyConfig(config);
|
|
1125
|
+
}
|
|
1126
|
+
function validateClarifyConfig(config) {
|
|
1127
|
+
const { plugins, ...projectConfigInput } = config;
|
|
1128
|
+
if (plugins !== void 0 && !Array.isArray(plugins)) throw new Error("[clarify] config field \"plugins\" is invalid: Expected an array");
|
|
1129
|
+
const projectConfig = validateProjectConfig(projectConfigInput);
|
|
1130
|
+
return plugins ? {
|
|
1103
1131
|
...projectConfig,
|
|
1104
|
-
|
|
1105
|
-
};
|
|
1132
|
+
plugins
|
|
1133
|
+
} : projectConfig;
|
|
1106
1134
|
}
|
|
1107
1135
|
async function loadClarifyConfig(root, env) {
|
|
1108
1136
|
const configFile = findClarifyConfigFile(root);
|
|
1109
1137
|
if (!configFile) return {};
|
|
1110
1138
|
if (configFile.endsWith(".json")) return loadJsonConfig(configFile);
|
|
1111
|
-
return assertConfigObject((await (0, vite.loadConfigFromFile)(env, configFile, root, "silent"))?.config, configFile);
|
|
1139
|
+
return validateClarifyConfig(assertConfigObject((await (0, vite.loadConfigFromFile)(env, configFile, root, "silent"))?.config, configFile));
|
|
1112
1140
|
}
|
|
1113
1141
|
/**
|
|
1114
1142
|
* File extensions Clarify treats as content files. Kept in sync with the
|
|
@@ -1134,9 +1162,9 @@ function buildProjectInfo(context) {
|
|
|
1134
1162
|
contentRoot: (contentRoot.startsWith(projectRoot) ? contentRoot.slice(projectRoot.length).replace(/^[/\\]+/, "") : contentRoot) || "source",
|
|
1135
1163
|
projectRoot
|
|
1136
1164
|
};
|
|
1137
|
-
if (projectConfig.
|
|
1138
|
-
|
|
1139
|
-
locales: projectConfig.
|
|
1165
|
+
if (projectConfig.locales) response.locales = {
|
|
1166
|
+
default: projectConfig.locales.default,
|
|
1167
|
+
locales: projectConfig.locales.locales.map((l) => l.code)
|
|
1140
1168
|
};
|
|
1141
1169
|
return response;
|
|
1142
1170
|
}
|
|
@@ -1196,10 +1224,23 @@ function resolveVirtualModuleId(id, modules, routes) {
|
|
|
1196
1224
|
if (route) return resolveVirtualId(route.module.virtualModuleId);
|
|
1197
1225
|
return null;
|
|
1198
1226
|
}
|
|
1199
|
-
function generateConfigModule(projectConfig,
|
|
1227
|
+
function generateConfigModule(projectConfig, version) {
|
|
1200
1228
|
const runtimeConfig = {
|
|
1201
|
-
|
|
1202
|
-
|
|
1229
|
+
title: projectConfig.title,
|
|
1230
|
+
description: projectConfig.description,
|
|
1231
|
+
siteUrl: projectConfig.siteUrl,
|
|
1232
|
+
routePrefix: projectConfig.routePrefix,
|
|
1233
|
+
assetPrefix: projectConfig.assetPrefix,
|
|
1234
|
+
logo: projectConfig.logo,
|
|
1235
|
+
homeUrl: projectConfig.homeUrl,
|
|
1236
|
+
favicon: projectConfig.favicon,
|
|
1237
|
+
theme: projectConfig.theme,
|
|
1238
|
+
navigation: projectConfig.navigation,
|
|
1239
|
+
banner: projectConfig.banner,
|
|
1240
|
+
footer: projectConfig.footer,
|
|
1241
|
+
locales: projectConfig.locales,
|
|
1242
|
+
variables: projectConfig.variables,
|
|
1243
|
+
features: projectConfig.features
|
|
1203
1244
|
};
|
|
1204
1245
|
if (version) runtimeConfig.version = version;
|
|
1205
1246
|
return `export const config = ${JSON.stringify(runtimeConfig)};`;
|
|
@@ -1303,7 +1344,7 @@ function buildVirtualModules(args) {
|
|
|
1303
1344
|
const modules = /* @__PURE__ */ new Map();
|
|
1304
1345
|
const clientEntryModule = createClientEntryModule({ themeEditor: args.themeEditor });
|
|
1305
1346
|
const allPlugins = [...args.plugins ?? []];
|
|
1306
|
-
modules.set(VIRTUAL_CONFIG, generateConfigModule(args.projectConfig, args.
|
|
1347
|
+
modules.set(VIRTUAL_CONFIG, generateConfigModule(args.projectConfig, args.version));
|
|
1307
1348
|
modules.set(VIRTUAL_ROUTES, generateRoutesModule(args.routes, args.navigation, "client"));
|
|
1308
1349
|
modules.set(VIRTUAL_SERVER_ROUTES, generateRoutesModule(args.routes, args.navigation, "server"));
|
|
1309
1350
|
modules.set(VIRTUAL_SLOTS, createRuntimeSlotsModule(allPlugins, args.generateOptions.projectRoot));
|
|
@@ -1528,7 +1569,7 @@ function createViteAdapter(engine) {
|
|
|
1528
1569
|
const compilePolicyPlugin = {
|
|
1529
1570
|
name: "clarify:content-compile-policy",
|
|
1530
1571
|
configResolved(config) {
|
|
1531
|
-
contentCompileErrorPolicy = config.command === "build"
|
|
1572
|
+
contentCompileErrorPolicy = config.command === "build" ? "throw" : "diagnostic";
|
|
1532
1573
|
}
|
|
1533
1574
|
};
|
|
1534
1575
|
const tailwind = (0, _tailwindcss_vite.default)();
|
|
@@ -1544,7 +1585,7 @@ function createViteAdapter(engine) {
|
|
|
1544
1585
|
}
|
|
1545
1586
|
var cliPackageVersion = {
|
|
1546
1587
|
name: "@clarify-labs/cli",
|
|
1547
|
-
version: "0.
|
|
1588
|
+
version: "0.11.0",
|
|
1548
1589
|
license: "AGPL-3.0-only",
|
|
1549
1590
|
type: "module",
|
|
1550
1591
|
repository: {
|
|
@@ -1624,8 +1665,7 @@ function resolveBuildOptions(options = {}) {
|
|
|
1624
1665
|
return {
|
|
1625
1666
|
projectRoot: options.projectRoot ?? process.cwd(),
|
|
1626
1667
|
rootDirectory: options.rootDirectory ?? "source",
|
|
1627
|
-
outputDirectory: options.outputDirectory
|
|
1628
|
-
ssg: { failOnError: options.ssg?.failOnError ?? true }
|
|
1668
|
+
outputDirectory: options.outputDirectory
|
|
1629
1669
|
};
|
|
1630
1670
|
}
|
|
1631
1671
|
//#endregion
|
|
@@ -1683,7 +1723,7 @@ function llmsTxtListItem(route, basePath) {
|
|
|
1683
1723
|
return description ? `- [${route.meta.title}](${basePath}${contentArtifactUrl}): ${description}` : `- [${route.meta.title}](${basePath}${contentArtifactUrl})`;
|
|
1684
1724
|
}
|
|
1685
1725
|
function llmsTxtLocaleLabel(locale, projectConfig) {
|
|
1686
|
-
return projectConfig.
|
|
1726
|
+
return projectConfig.locales?.locales.find((item) => item.code === locale)?.label ?? locale;
|
|
1687
1727
|
}
|
|
1688
1728
|
function groupRoutesByLocale(routes) {
|
|
1689
1729
|
const groups = /* @__PURE__ */ new Map();
|
|
@@ -1695,7 +1735,7 @@ function groupRoutesByLocale(routes) {
|
|
|
1695
1735
|
}
|
|
1696
1736
|
function groupLlmsTxtRoutesByLocale(routes, projectConfig) {
|
|
1697
1737
|
const routesBySource = /* @__PURE__ */ new Map();
|
|
1698
|
-
const defaultLocale = projectConfig.
|
|
1738
|
+
const defaultLocale = projectConfig.locales?.default;
|
|
1699
1739
|
for (const route of routes) {
|
|
1700
1740
|
const sourceKey = `${route.locale ?? defaultLocale ?? "default"}:${route.basePath ?? route.artifacts?.contentArtifactUrl ?? route.path}`;
|
|
1701
1741
|
const previousRoute = routesBySource.get(sourceKey);
|
|
@@ -2090,7 +2130,7 @@ function collectOpenAPIPageIntents(config) {
|
|
|
2090
2130
|
if (!pages || pages === "FileTree") return;
|
|
2091
2131
|
for (const group of pages) visitItems(group.pages);
|
|
2092
2132
|
}
|
|
2093
|
-
for (const tab of config.tabs ?? []) visitPages(tab.pages);
|
|
2133
|
+
for (const tab of config.navigation?.tabs ?? []) visitPages(tab.pages);
|
|
2094
2134
|
return intents;
|
|
2095
2135
|
}
|
|
2096
2136
|
function virtualModuleIdFromPath(path) {
|
|
@@ -2113,14 +2153,14 @@ function cloneOpenAPIRoute(route, overrides = {}) {
|
|
|
2113
2153
|
...overrides
|
|
2114
2154
|
};
|
|
2115
2155
|
}
|
|
2116
|
-
function findOpenAPIRoutesForContentRoot(contentRoot,
|
|
2117
|
-
if (!
|
|
2156
|
+
function findOpenAPIRoutesForContentRoot(contentRoot, locales) {
|
|
2157
|
+
if (!locales) return findOpenAPIRoutes(contentRoot);
|
|
2118
2158
|
const localizedRoutes = [];
|
|
2119
|
-
for (const locale of
|
|
2159
|
+
for (const locale of locales.locales) {
|
|
2120
2160
|
const localeRoot = (0, node_path.join)(contentRoot, locale.code);
|
|
2121
2161
|
for (const route of findOpenAPIRoutes(localeRoot, localeRoot)) {
|
|
2122
2162
|
const basePath = route.basePath ?? route.path;
|
|
2123
|
-
const path = localizedRoutePath(basePath, locale.code,
|
|
2163
|
+
const path = localizedRoutePath(basePath, locale.code, locales);
|
|
2124
2164
|
localizedRoutes.push({
|
|
2125
2165
|
...route,
|
|
2126
2166
|
path,
|
|
@@ -2130,15 +2170,15 @@ function findOpenAPIRoutesForContentRoot(contentRoot, i18n) {
|
|
|
2130
2170
|
});
|
|
2131
2171
|
}
|
|
2132
2172
|
}
|
|
2133
|
-
if (
|
|
2173
|
+
if (locales.missing === "fallback") {
|
|
2134
2174
|
const routeByLocaleAndBase = new Map(localizedRoutes.map((route) => [`${route.locale ?? ""}:${route.basePath ?? route.path}`, route]));
|
|
2135
|
-
const defaultRoutes = localizedRoutes.filter((route) => route.locale ===
|
|
2175
|
+
const defaultRoutes = localizedRoutes.filter((route) => route.locale === locales.default);
|
|
2136
2176
|
for (const sourceRoute of defaultRoutes) {
|
|
2137
2177
|
const basePath = sourceRoute.basePath ?? sourceRoute.path;
|
|
2138
|
-
for (const locale of
|
|
2178
|
+
for (const locale of locales.locales) {
|
|
2139
2179
|
const key = `${locale.code}:${basePath}`;
|
|
2140
2180
|
if (routeByLocaleAndBase.has(key)) continue;
|
|
2141
|
-
const path = localizedRoutePath(basePath, locale.code,
|
|
2181
|
+
const path = localizedRoutePath(basePath, locale.code, locales);
|
|
2142
2182
|
localizedRoutes.push(cloneOpenAPIRoute(sourceRoute, {
|
|
2143
2183
|
path,
|
|
2144
2184
|
locale: locale.code,
|
|
@@ -2165,7 +2205,7 @@ function createConfiguredOpenAPIRoutes(routes, config) {
|
|
|
2165
2205
|
const key = `${route.locale ?? ""}:${targetBasePath}`;
|
|
2166
2206
|
if (existingKeys.has(key)) continue;
|
|
2167
2207
|
existingKeys.add(key);
|
|
2168
|
-
const path = route.locale && config.
|
|
2208
|
+
const path = route.locale && config.locales ? localizedRoutePath(targetBasePath, route.locale, config.locales) : targetBasePath;
|
|
2169
2209
|
additions.push(cloneOpenAPIRoute(route, {
|
|
2170
2210
|
path,
|
|
2171
2211
|
basePath: targetBasePath,
|
|
@@ -2178,12 +2218,12 @@ function createConfiguredOpenAPIRoutes(routes, config) {
|
|
|
2178
2218
|
}
|
|
2179
2219
|
}
|
|
2180
2220
|
const nextRoutes = [...routes, ...additions];
|
|
2181
|
-
if (!config.
|
|
2182
|
-
const routesWithAlternates = nextRoutes.map((route) => withAlternates(route, nextRoutes, config.
|
|
2221
|
+
if (!config.locales) return nextRoutes;
|
|
2222
|
+
const routesWithAlternates = nextRoutes.map((route) => withAlternates(route, nextRoutes, config.locales));
|
|
2183
2223
|
const bareAliases = [];
|
|
2184
2224
|
const seenBare = new Set(routesWithAlternates.map((route) => route.path));
|
|
2185
2225
|
for (const route of routesWithAlternates) {
|
|
2186
|
-
if (route.locale !== config.
|
|
2226
|
+
if (route.locale !== config.locales.default) continue;
|
|
2187
2227
|
const basePath = route.basePath ?? route.path;
|
|
2188
2228
|
if (basePath === route.path || seenBare.has(basePath)) continue;
|
|
2189
2229
|
seenBare.add(basePath);
|
|
@@ -2222,7 +2262,7 @@ function createOpenAPIPlugin() {
|
|
|
2222
2262
|
hooks: {
|
|
2223
2263
|
"routes:discover": (input, ctx) => ({
|
|
2224
2264
|
...input,
|
|
2225
|
-
routes: [...input.routes, ...findOpenAPIRoutesForContentRoot(input.contentRoot, ctx.projectConfig.
|
|
2265
|
+
routes: [...input.routes, ...findOpenAPIRoutesForContentRoot(input.contentRoot, ctx.projectConfig.locales)]
|
|
2226
2266
|
}),
|
|
2227
2267
|
"routes:discovered": async (routes, ctx) => {
|
|
2228
2268
|
specs.clear();
|
|
@@ -2379,7 +2419,7 @@ async function generateDevSearchIndex(ctx, root, pagefind) {
|
|
|
2379
2419
|
const result = await index.addCustomRecord({
|
|
2380
2420
|
url: route.path,
|
|
2381
2421
|
content,
|
|
2382
|
-
language: toPagefindLanguage(route.locale ?? ctx.projectConfig.
|
|
2422
|
+
language: toPagefindLanguage(route.locale ?? ctx.projectConfig.locales?.default),
|
|
2383
2423
|
meta: { title: route.meta.title }
|
|
2384
2424
|
});
|
|
2385
2425
|
assertNoPagefindErrors(`addCustomRecord ${route.path}`, result.errors);
|
|
@@ -2422,6 +2462,7 @@ function createSearchIndexPlugin() {
|
|
|
2422
2462
|
name: "clarify:search-index",
|
|
2423
2463
|
hooks: {
|
|
2424
2464
|
async "dev:configureServer"(server, ctx) {
|
|
2465
|
+
if (!ctx.projectConfig.features.search.enabled) return;
|
|
2425
2466
|
const pagefind = await import("pagefind");
|
|
2426
2467
|
let currentRoot;
|
|
2427
2468
|
const staleRoots = /* @__PURE__ */ new Set();
|
|
@@ -2461,6 +2502,7 @@ function createSearchIndexPlugin() {
|
|
|
2461
2502
|
});
|
|
2462
2503
|
},
|
|
2463
2504
|
async "build:done"(ctx) {
|
|
2505
|
+
if (!ctx.projectConfig.features.search.enabled) return;
|
|
2464
2506
|
const outputDirectory = ctx.generateOptions.outputDirectory;
|
|
2465
2507
|
if (!outputDirectory) return;
|
|
2466
2508
|
const pageCount = await generatePagefindIndex({ outputRoot: (0, node_path.resolve)(ctx.generateOptions.projectRoot, outputDirectory) });
|
|
@@ -2513,16 +2555,18 @@ function createSeoPlugin() {
|
|
|
2513
2555
|
return {
|
|
2514
2556
|
name: "clarify:seo",
|
|
2515
2557
|
hooks: { "build:assets"(ctx) {
|
|
2558
|
+
const assets = [];
|
|
2516
2559
|
const sitemap = createSitemapXml(ctx.routes, ctx.projectConfig);
|
|
2517
2560
|
const robots = createRobotsTxt(ctx.projectConfig);
|
|
2518
|
-
if (
|
|
2519
|
-
return [{
|
|
2561
|
+
if (sitemap) assets.push({
|
|
2520
2562
|
fileName: "sitemap.xml",
|
|
2521
2563
|
source: sitemap
|
|
2522
|
-
}
|
|
2564
|
+
});
|
|
2565
|
+
if (robots) assets.push({
|
|
2523
2566
|
fileName: "robots.txt",
|
|
2524
2567
|
source: robots
|
|
2525
|
-
}
|
|
2568
|
+
});
|
|
2569
|
+
return assets;
|
|
2526
2570
|
} }
|
|
2527
2571
|
};
|
|
2528
2572
|
}
|
|
@@ -2538,7 +2582,8 @@ function encodePath(path) {
|
|
|
2538
2582
|
return path.split("/").filter(Boolean).map((segment) => encodeURIComponent(segment)).join("/");
|
|
2539
2583
|
}
|
|
2540
2584
|
function createSourceEditUrl(filePath, contentRoot, source) {
|
|
2541
|
-
|
|
2585
|
+
if (!source.url) return "";
|
|
2586
|
+
const repository = normalizeRepositoryUrl(source.url);
|
|
2542
2587
|
const branch = source.branch ?? "main";
|
|
2543
2588
|
const sourcePath = [source.directory ? trimSlashes(source.directory) : "", (0, node_path.relative)(contentRoot, filePath).replaceAll("\\", "/")].filter(Boolean).join("/");
|
|
2544
2589
|
return `${repository}/edit/${encodeURIComponent(branch)}/${encodePath(sourcePath)}`;
|
|
@@ -2556,7 +2601,8 @@ function createSourceLinksPlugin() {
|
|
|
2556
2601
|
return {
|
|
2557
2602
|
name: "clarify:source-links",
|
|
2558
2603
|
hooks: { "routes:discovered": (routes, ctx) => {
|
|
2559
|
-
|
|
2604
|
+
if (!ctx.projectConfig.features.repository.enabled) return routes;
|
|
2605
|
+
attachSourceEditUrls(routes, (0, node_path.join)(ctx.generateOptions.projectRoot, ctx.generateOptions.rootDirectory), ctx.projectConfig.features.repository);
|
|
2560
2606
|
return routes;
|
|
2561
2607
|
} }
|
|
2562
2608
|
};
|
|
@@ -2671,18 +2717,18 @@ async function resolveProjectContext(options = {}, env = {
|
|
|
2671
2717
|
}) {
|
|
2672
2718
|
const projectRoot = (0, node_path.resolve)(options.projectRoot ?? process.cwd());
|
|
2673
2719
|
const initialBuildOptions = resolveBuildOptions(options);
|
|
2674
|
-
const contentRoot = (0, node_path.join)(projectRoot, initialBuildOptions.rootDirectory);
|
|
2675
2720
|
const configFilePath = findClarifyConfigFile(projectRoot);
|
|
2676
2721
|
const config = configFilePath && (0, node_fs.existsSync)(configFilePath) ? await loadClarifyConfig(projectRoot, env) : {};
|
|
2677
2722
|
const mergedOptions = {
|
|
2678
2723
|
...config,
|
|
2679
2724
|
...options,
|
|
2680
2725
|
projectRoot,
|
|
2681
|
-
rootDirectory: initialBuildOptions.rootDirectory,
|
|
2682
|
-
outputDirectory: initialBuildOptions.outputDirectory
|
|
2726
|
+
rootDirectory: options.rootDirectory ?? initialBuildOptions.rootDirectory,
|
|
2727
|
+
outputDirectory: options.outputDirectory ?? initialBuildOptions.outputDirectory
|
|
2683
2728
|
};
|
|
2684
2729
|
const resolvedProjectConfig = resolveProjectConfig(mergedOptions);
|
|
2685
2730
|
const resolvedBuildOptions = resolveBuildOptions(mergedOptions);
|
|
2731
|
+
const contentRoot = (0, node_path.join)(projectRoot, resolvedBuildOptions.rootDirectory);
|
|
2686
2732
|
return {
|
|
2687
2733
|
projectRoot,
|
|
2688
2734
|
contentRoot,
|
|
@@ -2772,9 +2818,9 @@ function canonicalUrl(contextOrConfig, route) {
|
|
|
2772
2818
|
/** Inject `lang` (and optional `dir`) onto the `<html>` tag for the route locale. */
|
|
2773
2819
|
function injectHtmlLocaleAttributes(html, contextOrConfig, route) {
|
|
2774
2820
|
const projectConfig = resolveProjectConfigFromContext(contextOrConfig);
|
|
2775
|
-
const localeCode = route?.locale ?? projectConfig.
|
|
2821
|
+
const localeCode = route?.locale ?? projectConfig.locales?.default;
|
|
2776
2822
|
if (!localeCode) return html;
|
|
2777
|
-
const dir = (projectConfig.
|
|
2823
|
+
const dir = (projectConfig.locales?.locales.find((locale) => locale.code === localeCode))?.dir;
|
|
2778
2824
|
return html.replace(/<html\b([^>]*)>/i, (_match, attributes) => {
|
|
2779
2825
|
let nextAttributes = attributes.replace(/\s+lang=("[^"]*"|'[^']*'|[^\s>]*)/i, "").replace(/\s+dir=("[^"]*"|'[^']*'|[^\s>]*)/i, "");
|
|
2780
2826
|
nextAttributes = `${nextAttributes} lang="${escapeHtml(localeCode)}"`;
|
|
@@ -2952,7 +2998,7 @@ async function buildSSRBundle(root, ssrEntry, ssrOutDir, plugins) {
|
|
|
2952
2998
|
}
|
|
2953
2999
|
});
|
|
2954
3000
|
}
|
|
2955
|
-
async function renderSSGRoutes(routes, contextOrConfig, outputDirectory, ssrBundlePath
|
|
3001
|
+
async function renderSSGRoutes(routes, contextOrConfig, outputDirectory, ssrBundlePath) {
|
|
2956
3002
|
const { render } = await import((0, node_url.pathToFileURL)(ssrBundlePath).href);
|
|
2957
3003
|
const template = readIndexHtml(outputDirectory);
|
|
2958
3004
|
if (!template) throw new Error(`[clarify] index.html not found in outputDirectory "${outputDirectory}". Make sure Vite build produces it.`);
|
|
@@ -2964,7 +3010,7 @@ async function renderSSGRoutes(routes, contextOrConfig, outputDirectory, ssrBund
|
|
|
2964
3010
|
}
|
|
2965
3011
|
} catch (err) {
|
|
2966
3012
|
console.error(`[clarify] Failed to render route "${route.path}":`, err);
|
|
2967
|
-
|
|
3013
|
+
throw err;
|
|
2968
3014
|
}
|
|
2969
3015
|
}
|
|
2970
3016
|
//#endregion
|
|
@@ -3041,10 +3087,10 @@ var ClarifyContext = class {
|
|
|
3041
3087
|
this.currentPlugins = plugins;
|
|
3042
3088
|
}
|
|
3043
3089
|
get isI18n() {
|
|
3044
|
-
return Boolean(this.projectConfig.
|
|
3090
|
+
return Boolean(this.projectConfig.locales);
|
|
3045
3091
|
}
|
|
3046
3092
|
get defaultLocale() {
|
|
3047
|
-
return this.projectConfig.
|
|
3093
|
+
return this.projectConfig.locales?.default;
|
|
3048
3094
|
}
|
|
3049
3095
|
get(key) {
|
|
3050
3096
|
return this.values.get(key);
|
|
@@ -3238,10 +3284,10 @@ var ClarifyEngine = class {
|
|
|
3238
3284
|
async discoverSite() {
|
|
3239
3285
|
const plugins = this.ctx.plugins;
|
|
3240
3286
|
const contentRoot = this.ctx.contentRoot;
|
|
3241
|
-
const {
|
|
3287
|
+
const { locales, navigation: navigationConfig } = this.ctx.projectConfig;
|
|
3242
3288
|
let routes = await runPhase(plugins, "site:discover", this.ctx, async () => {
|
|
3243
3289
|
const options = { contentProcessor: createProjectContentProcessor(plugins, this.ctx) };
|
|
3244
|
-
const discovered =
|
|
3290
|
+
const discovered = locales ? await findLocalizedContentRoutes(contentRoot, locales, options) : await findContentRoutes(contentRoot, contentRoot, options);
|
|
3245
3291
|
const result = await runHooks(plugins, "routes:discover", {
|
|
3246
3292
|
contentRoot,
|
|
3247
3293
|
routes: discovered
|
|
@@ -3270,8 +3316,9 @@ var ClarifyEngine = class {
|
|
|
3270
3316
|
};
|
|
3271
3317
|
});
|
|
3272
3318
|
});
|
|
3273
|
-
|
|
3274
|
-
|
|
3319
|
+
const tabs = navigationConfig?.tabs;
|
|
3320
|
+
routes = applyConfiguredPageRoutePaths(routes, tabs, locales);
|
|
3321
|
+
const navigation = tabs ? locales ? buildLocalizedNavigationFromTabsConfig(routes, tabs, locales) ?? {
|
|
3275
3322
|
kind: "localized-tabbed",
|
|
3276
3323
|
locales: {}
|
|
3277
3324
|
} : buildNavigationFromTabsConfig(routes, tabs) : {
|
|
@@ -3301,7 +3348,7 @@ var ClarifyEngine = class {
|
|
|
3301
3348
|
routes: this.routes,
|
|
3302
3349
|
navigation: this.navigation,
|
|
3303
3350
|
plugins: this.plugins,
|
|
3304
|
-
themeEditor: this.runtime.command === "serve" || this.runtime.themeEditor === true || this.projectConfig.
|
|
3351
|
+
themeEditor: this.runtime.command === "serve" || this.runtime.themeEditor === true || this.projectConfig.features.themeEditor.enabled,
|
|
3305
3352
|
version: this.ctx.version
|
|
3306
3353
|
});
|
|
3307
3354
|
this.virtualModules = await runHooks(this.plugins, "modules:before", this.virtualModules, this.ctx);
|
|
@@ -3344,7 +3391,7 @@ var ClarifyEngine = class {
|
|
|
3344
3391
|
await runPhase(this.plugins, "ssg", this.ctx, async () => {
|
|
3345
3392
|
if (process.env.SKIP_CLARIFY_SSG) return;
|
|
3346
3393
|
if (!await runInterceptHooks(this.plugins, "ssg:shouldRun", this.ctx)) return;
|
|
3347
|
-
|
|
3394
|
+
assertNoContentDiagnostics(this.routes);
|
|
3348
3395
|
const outputDir = this.runtime.outputDirectory ?? this.generateOptions.outputDirectory;
|
|
3349
3396
|
if (!outputDir) throw new Error("[clarify] outputDirectory is required before SSG runs");
|
|
3350
3397
|
const ssrOutputDir = (0, node_path.join)(outputDir, ".ssr");
|
|
@@ -3358,10 +3405,10 @@ var ClarifyEngine = class {
|
|
|
3358
3405
|
plugins: this.runtime.ssrPlugins ?? []
|
|
3359
3406
|
});
|
|
3360
3407
|
const ssrBundlePath = (0, node_path.join)(ssrOutputDir, "entry-server.js");
|
|
3361
|
-
await renderSSGRoutes(this.routes, this.runtimeContext(), outputDir, ssrBundlePath
|
|
3408
|
+
await renderSSGRoutes(this.routes, this.runtimeContext(), outputDir, ssrBundlePath);
|
|
3362
3409
|
} catch (err) {
|
|
3363
3410
|
console.error("[clarify] SSG failed:", err);
|
|
3364
|
-
|
|
3411
|
+
throw err;
|
|
3365
3412
|
} finally {
|
|
3366
3413
|
if (tempEntryPath) try {
|
|
3367
3414
|
(0, node_fs.rmSync)(tempEntryPath, { force: true });
|
|
@@ -3452,4 +3499,4 @@ Object.defineProperty(exports, "defineConfig", {
|
|
|
3452
3499
|
}
|
|
3453
3500
|
});
|
|
3454
3501
|
|
|
3455
|
-
//# sourceMappingURL=engine-
|
|
3502
|
+
//# sourceMappingURL=engine-BfkoyVNo.cjs.map
|