@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
|
@@ -379,10 +379,10 @@ function frontmatterKeywords(frontmatter) {
|
|
|
379
379
|
const keywords = Array.isArray(value) ? value.filter((item) => typeof item === "string") : typeof value === "string" ? value.split(",").map((keyword) => keyword.trim()).filter(Boolean) : [];
|
|
380
380
|
return keywords.length > 0 ? keywords : void 0;
|
|
381
381
|
}
|
|
382
|
-
function withAlternates(route, routes,
|
|
382
|
+
function withAlternates(route, routes, locales) {
|
|
383
383
|
const basePath = route.basePath ?? route.path;
|
|
384
384
|
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]));
|
|
385
|
-
const alternates = Object.fromEntries(
|
|
385
|
+
const alternates = Object.fromEntries(locales.locales.flatMap((locale) => {
|
|
386
386
|
const alternate = routeByLocaleAndBase.get(`${locale.code}:${basePath}`);
|
|
387
387
|
return alternate ? [[locale.code, alternate.path]] : [];
|
|
388
388
|
}));
|
|
@@ -395,11 +395,11 @@ function withAlternates(route, routes, i18n) {
|
|
|
395
395
|
* 为默认语言的 locale-prefixed 路由生成无前缀的"裸路径别名",方便不带语言
|
|
396
396
|
* 前缀的 URL 也能访问。标记 `isBareAlias` 以便搜索索引生成时过滤重复索引。
|
|
397
397
|
*/
|
|
398
|
-
function generateBareAliases(routes,
|
|
398
|
+
function generateBareAliases(routes, locales) {
|
|
399
399
|
const bareRoutes = [];
|
|
400
400
|
const seenBare = new Set(routes.map((r) => r.path));
|
|
401
401
|
for (const route of routes) {
|
|
402
|
-
if (route.locale !==
|
|
402
|
+
if (route.locale !== locales.default) continue;
|
|
403
403
|
const bp = route.basePath ?? route.path;
|
|
404
404
|
if (bp === route.path || seenBare.has(bp)) continue;
|
|
405
405
|
seenBare.add(bp);
|
|
@@ -411,42 +411,42 @@ function generateBareAliases(routes, i18n) {
|
|
|
411
411
|
}
|
|
412
412
|
return bareRoutes;
|
|
413
413
|
}
|
|
414
|
-
async function findLocalizedContentRoutes(contentRoot,
|
|
415
|
-
if (!
|
|
414
|
+
async function findLocalizedContentRoutes(contentRoot, locales, options = {}) {
|
|
415
|
+
if (!locales) return findContentRoutes(contentRoot, contentRoot, options);
|
|
416
416
|
const localizedRoutes = [];
|
|
417
|
-
for (const locale of
|
|
417
|
+
for (const locale of locales.locales) {
|
|
418
418
|
const localeRoot = join(contentRoot, locale.code);
|
|
419
419
|
const discovered = await findContentRoutes(localeRoot, localeRoot, options);
|
|
420
420
|
for (const route of discovered) {
|
|
421
421
|
const basePath = route.basePath ?? route.path;
|
|
422
422
|
localizedRoutes.push({
|
|
423
423
|
...route,
|
|
424
|
-
path: localizedRoutePath(basePath, locale.code,
|
|
424
|
+
path: localizedRoutePath(basePath, locale.code, locales),
|
|
425
425
|
basePath,
|
|
426
426
|
locale: locale.code,
|
|
427
427
|
module: { virtualModuleId: virtualModuleIdForLocalizedRoute(contentRoot, route.source.filePath) }
|
|
428
428
|
});
|
|
429
429
|
}
|
|
430
430
|
}
|
|
431
|
-
if (
|
|
431
|
+
if (locales.missing === "fallback") {
|
|
432
432
|
const routeByLocaleAndBase = new Map(localizedRoutes.map((route) => [`${route.locale ?? ""}:${route.basePath ?? route.path}`, route]));
|
|
433
|
-
const defaultRoutes = localizedRoutes.filter((route) => route.locale ===
|
|
433
|
+
const defaultRoutes = localizedRoutes.filter((route) => route.locale === locales.default);
|
|
434
434
|
for (const sourceRoute of defaultRoutes) {
|
|
435
435
|
const basePath = sourceRoute.basePath ?? sourceRoute.path;
|
|
436
|
-
for (const locale of
|
|
436
|
+
for (const locale of locales.locales) {
|
|
437
437
|
const key = `${locale.code}:${basePath}`;
|
|
438
438
|
if (routeByLocaleAndBase.has(key)) continue;
|
|
439
439
|
localizedRoutes.push({
|
|
440
440
|
...sourceRoute,
|
|
441
|
-
path: localizedRoutePath(basePath, locale.code,
|
|
441
|
+
path: localizedRoutePath(basePath, locale.code, locales),
|
|
442
442
|
locale: locale.code,
|
|
443
443
|
isFallback: true
|
|
444
444
|
});
|
|
445
445
|
}
|
|
446
446
|
}
|
|
447
447
|
}
|
|
448
|
-
const routesWithAlternates = localizedRoutes.map((route) => withAlternates(route, localizedRoutes,
|
|
449
|
-
return [...routesWithAlternates, ...generateBareAliases(routesWithAlternates,
|
|
448
|
+
const routesWithAlternates = localizedRoutes.map((route) => withAlternates(route, localizedRoutes, locales));
|
|
449
|
+
return [...routesWithAlternates, ...generateBareAliases(routesWithAlternates, locales)];
|
|
450
450
|
}
|
|
451
451
|
function buildNavigation(routes) {
|
|
452
452
|
const root = [];
|
|
@@ -523,7 +523,7 @@ function collectExplicitPagePathIntents(tabs) {
|
|
|
523
523
|
}
|
|
524
524
|
return intents;
|
|
525
525
|
}
|
|
526
|
-
function applyConfiguredPageRoutePaths(routes, tabs,
|
|
526
|
+
function applyConfiguredPageRoutePaths(routes, tabs, locales) {
|
|
527
527
|
const pageIntents = collectExplicitPagePathIntents(tabs);
|
|
528
528
|
if (!pageIntents.length) return routes;
|
|
529
529
|
const additions = [];
|
|
@@ -539,15 +539,15 @@ function applyConfiguredPageRoutePaths(routes, tabs, i18n) {
|
|
|
539
539
|
existingKeys.add(key);
|
|
540
540
|
additions.push({
|
|
541
541
|
...route,
|
|
542
|
-
path: route.locale &&
|
|
542
|
+
path: route.locale && locales ? localizedRoutePath(targetBasePath, route.locale, locales) : targetBasePath,
|
|
543
543
|
basePath: targetBasePath
|
|
544
544
|
});
|
|
545
545
|
}
|
|
546
546
|
}
|
|
547
547
|
const nextRoutes = [...routes, ...additions];
|
|
548
|
-
const routesWithAlternates =
|
|
549
|
-
if (!
|
|
550
|
-
return [...routesWithAlternates, ...generateBareAliases(routesWithAlternates,
|
|
548
|
+
const routesWithAlternates = locales ? nextRoutes.map((route) => withAlternates(route, nextRoutes, locales)) : nextRoutes;
|
|
549
|
+
if (!locales) return routesWithAlternates;
|
|
550
|
+
return [...routesWithAlternates, ...generateBareAliases(routesWithAlternates, locales)];
|
|
551
551
|
}
|
|
552
552
|
function buildNavigationFromPagesConfig(routes, config) {
|
|
553
553
|
if (!config || config === "FileTree") return buildNavigation(routes);
|
|
@@ -610,25 +610,25 @@ function buildNavigationFromConfig(routes, config) {
|
|
|
610
610
|
};
|
|
611
611
|
});
|
|
612
612
|
}
|
|
613
|
-
function localizeNavigationPaths(nodes, locale,
|
|
613
|
+
function localizeNavigationPaths(nodes, locale, locales) {
|
|
614
614
|
return nodes.map((node) => ({
|
|
615
615
|
...node,
|
|
616
|
-
path: localizedRoutePath(node.path, locale,
|
|
617
|
-
children: node.children ? localizeNavigationPaths(node.children, locale,
|
|
616
|
+
path: localizedRoutePath(node.path, locale, locales),
|
|
617
|
+
children: node.children ? localizeNavigationPaths(node.children, locale, locales) : void 0
|
|
618
618
|
}));
|
|
619
619
|
}
|
|
620
|
-
function buildLocalizedNavigationForLocale(routes, config, locale,
|
|
620
|
+
function buildLocalizedNavigationForLocale(routes, config, locale, locales) {
|
|
621
621
|
if (!config || config === "FileTree") return localizeNavigationPaths(buildNavigation(routes.map((route) => ({
|
|
622
622
|
...route,
|
|
623
623
|
path: route.basePath ?? route.path
|
|
624
|
-
}))), locale,
|
|
624
|
+
}))), locale, locales);
|
|
625
625
|
const routeMap = new Map(routes.map((route) => [route.basePath ?? route.path, route]));
|
|
626
626
|
const buildItem = (item) => {
|
|
627
627
|
if (typeof item !== "string" && "group" in item) {
|
|
628
628
|
const children = item.pages.map(buildItem);
|
|
629
629
|
return {
|
|
630
630
|
path: firstNavigationPath(children),
|
|
631
|
-
title: resolveLocalizedText(item.group, locale,
|
|
631
|
+
title: resolveLocalizedText(item.group, locale, locales.default) ?? "",
|
|
632
632
|
icon: item.icon,
|
|
633
633
|
children
|
|
634
634
|
};
|
|
@@ -636,10 +636,10 @@ function buildLocalizedNavigationForLocale(routes, config, locale, i18n) {
|
|
|
636
636
|
const intent = routeIntentFromPagesItem(item);
|
|
637
637
|
const basePath = intent.kind === "openapi" ? openAPIPagePathFromRef(intent.ref, intent.tagFilter, intent.path) : routePathFromRef(intent.ref, intent.path);
|
|
638
638
|
const route = routeMap.get(basePath);
|
|
639
|
-
const path = route?.path ?? localizedRoutePath(basePath, locale,
|
|
639
|
+
const path = route?.path ?? localizedRoutePath(basePath, locale, locales);
|
|
640
640
|
return {
|
|
641
|
-
path: (intent.kind === "page" && intent.redirect ? localizedRoutePath(routePathFromRef(intent.redirect), locale,
|
|
642
|
-
title: resolveLocalizedText(intent.title, locale,
|
|
641
|
+
path: (intent.kind === "page" && intent.redirect ? localizedRoutePath(routePathFromRef(intent.redirect), locale, locales) : void 0) ?? path,
|
|
642
|
+
title: resolveLocalizedText(intent.title, locale, locales.default) ?? route?.meta.title ?? kebabToTitle(basePath.split("/").pop() ?? intent.ref),
|
|
643
643
|
icon: intent.icon,
|
|
644
644
|
sections: route?.meta.sections ? navigationSections(route.meta.sections) : void 0
|
|
645
645
|
};
|
|
@@ -647,24 +647,24 @@ function buildLocalizedNavigationForLocale(routes, config, locale, i18n) {
|
|
|
647
647
|
return config.map((group) => {
|
|
648
648
|
const children = group.pages.map(buildItem);
|
|
649
649
|
return {
|
|
650
|
-
path: children[0]?.path ?? localizedRoutePath("/", locale,
|
|
651
|
-
title: resolveLocalizedText(group.group, locale,
|
|
650
|
+
path: children[0]?.path ?? localizedRoutePath("/", locale, locales),
|
|
651
|
+
title: resolveLocalizedText(group.group, locale, locales.default) ?? "",
|
|
652
652
|
icon: group.icon,
|
|
653
653
|
children
|
|
654
654
|
};
|
|
655
655
|
});
|
|
656
656
|
}
|
|
657
|
-
function buildLocalizedNavigationFromTabsConfig(routes, tabs,
|
|
658
|
-
if (!
|
|
657
|
+
function buildLocalizedNavigationFromTabsConfig(routes, tabs, localesConfig) {
|
|
658
|
+
if (!localesConfig) return void 0;
|
|
659
659
|
const locales = {};
|
|
660
|
-
for (const locale of
|
|
660
|
+
for (const locale of localesConfig.locales) {
|
|
661
661
|
const localeRoutes = routes.filter((route) => route.locale === locale.code);
|
|
662
662
|
locales[locale.code] = { tabs: tabs.map((tab) => {
|
|
663
|
-
const children = buildLocalizedNavigationForLocale(localeRoutes, tab.pages, locale.code,
|
|
663
|
+
const children = buildLocalizedNavigationForLocale(localeRoutes, tab.pages, locale.code, localesConfig);
|
|
664
664
|
return {
|
|
665
665
|
type: "tab",
|
|
666
666
|
path: firstNavigationPath(children),
|
|
667
|
-
title: resolveLocalizedText(tab.tab, locale.code,
|
|
667
|
+
title: resolveLocalizedText(tab.tab, locale.code, localesConfig.default) ?? "",
|
|
668
668
|
icon: tab.icon,
|
|
669
669
|
children
|
|
670
670
|
};
|
|
@@ -731,7 +731,7 @@ function inferRouteForFile(filePath, contentRoot, defaultLocale) {
|
|
|
731
731
|
const localeSegmentIndex = fileLocale ? segments.indexOf(fileLocale) : -1;
|
|
732
732
|
const basePath = basePathFromRef(localeSegmentIndex >= 0 ? segments.slice(localeSegmentIndex + 1).join("/") : ref);
|
|
733
733
|
const path = fileLocale && defaultLocale ? localizedRoutePath(basePath, fileLocale, {
|
|
734
|
-
defaultLocale,
|
|
734
|
+
default: defaultLocale,
|
|
735
735
|
missing: "fallback",
|
|
736
736
|
locales: []
|
|
737
737
|
}) : basePath;
|
|
@@ -784,12 +784,12 @@ async function handleDevRouteRequest(req, res, routes, context) {
|
|
|
784
784
|
}
|
|
785
785
|
const file = typeof body === "object" && body !== null ? body.file : void 0;
|
|
786
786
|
if (typeof file === "string" && file.length > 0) {
|
|
787
|
-
const route = resolveRouteForFile(file, routes, context.projectConfig.
|
|
787
|
+
const route = resolveRouteForFile(file, routes, context.projectConfig.locales?.default);
|
|
788
788
|
if (route) {
|
|
789
789
|
res.end(JSON.stringify(toDevRouteEntry(route)));
|
|
790
790
|
return;
|
|
791
791
|
}
|
|
792
|
-
const inferred = inferRouteForFile(file, context.contentRoot, context.projectConfig.
|
|
792
|
+
const inferred = inferRouteForFile(file, context.contentRoot, context.projectConfig.locales?.default);
|
|
793
793
|
res.end(JSON.stringify(inferred));
|
|
794
794
|
return;
|
|
795
795
|
}
|
|
@@ -815,8 +815,7 @@ function resolveThemeConfig(theme = {}) {
|
|
|
815
815
|
layout: {
|
|
816
816
|
...presetTheme.layout,
|
|
817
817
|
...theme.layout
|
|
818
|
-
}
|
|
819
|
-
editor: theme.editor ?? presetTheme.editor
|
|
818
|
+
}
|
|
820
819
|
};
|
|
821
820
|
}
|
|
822
821
|
//#endregion
|
|
@@ -824,26 +823,26 @@ function resolveThemeConfig(theme = {}) {
|
|
|
824
823
|
var clarifyLogoConfigSchema = z.union([z.string(), z.object({
|
|
825
824
|
light: z.string().optional(),
|
|
826
825
|
dark: z.string().optional()
|
|
827
|
-
})]);
|
|
826
|
+
}).strict()]);
|
|
828
827
|
var clarifyFaviconConfigSchema = z.union([z.string(), z.object({
|
|
829
828
|
light: z.string().optional(),
|
|
830
829
|
dark: z.string().optional()
|
|
831
|
-
})]);
|
|
830
|
+
}).strict()]);
|
|
832
831
|
var clarifyLocalizedTextSchema = z.union([z.string(), z.record(z.string(), z.string())]);
|
|
833
832
|
var clarifyLocaleConfigSchema = z.object({
|
|
834
833
|
code: z.string(),
|
|
835
834
|
label: z.string(),
|
|
836
835
|
dir: z.union([z.literal("ltr"), z.literal("rtl")]).optional()
|
|
837
|
-
});
|
|
838
|
-
var
|
|
839
|
-
|
|
836
|
+
}).strict();
|
|
837
|
+
var clarifyLocalesConfigSchema = z.object({
|
|
838
|
+
default: z.string().optional(),
|
|
840
839
|
missing: z.union([
|
|
841
840
|
z.literal("fallback"),
|
|
842
841
|
z.literal("404"),
|
|
843
842
|
z.literal("hide")
|
|
844
843
|
]).optional(),
|
|
845
844
|
locales: z.array(clarifyLocaleConfigSchema).min(1)
|
|
846
|
-
}).superRefine((config, ctx) => {
|
|
845
|
+
}).strict().superRefine((config, ctx) => {
|
|
847
846
|
const localeCodes = /* @__PURE__ */ new Set();
|
|
848
847
|
for (const [index, locale] of config.locales.entries()) {
|
|
849
848
|
if (localeCodes.has(locale.code)) ctx.addIssue({
|
|
@@ -857,17 +856,17 @@ var clarifyI18nConfigSchema = z.object({
|
|
|
857
856
|
});
|
|
858
857
|
localeCodes.add(locale.code);
|
|
859
858
|
}
|
|
860
|
-
if (config.
|
|
859
|
+
if (config.default && !localeCodes.has(config.default)) ctx.addIssue({
|
|
861
860
|
code: z.ZodIssueCode.custom,
|
|
862
|
-
message: "
|
|
863
|
-
path: ["
|
|
861
|
+
message: "default must be one of locales.locales",
|
|
862
|
+
path: ["default"]
|
|
864
863
|
});
|
|
865
864
|
});
|
|
866
865
|
var clarifyNavbarLinkSchema = z.object({
|
|
867
866
|
label: clarifyLocalizedTextSchema,
|
|
868
867
|
href: z.string(),
|
|
869
868
|
external: z.boolean().optional()
|
|
870
|
-
});
|
|
869
|
+
}).strict();
|
|
871
870
|
var clarifyBannerConfigOptionsSchema = z.object({
|
|
872
871
|
content: clarifyLocalizedTextSchema,
|
|
873
872
|
dismissible: z.boolean().optional(),
|
|
@@ -885,11 +884,11 @@ var clarifyVariableValueSchema = z.lazy(() => z.union([
|
|
|
885
884
|
z.record(z.string(), clarifyVariableValueSchema)
|
|
886
885
|
]));
|
|
887
886
|
var clarifyVariablesConfigSchema = z.record(z.string(), clarifyVariableValueSchema);
|
|
888
|
-
var
|
|
889
|
-
|
|
887
|
+
var clarifyRepositoryConfigSchema = z.object({
|
|
888
|
+
url: z.string().optional(),
|
|
890
889
|
branch: z.string().optional(),
|
|
891
890
|
directory: z.string().optional()
|
|
892
|
-
});
|
|
891
|
+
}).strict();
|
|
893
892
|
var clarifyPagesItemSchema = z.lazy(() => z.union([
|
|
894
893
|
z.string(),
|
|
895
894
|
clarifyPagesGroupSchema,
|
|
@@ -899,32 +898,32 @@ var clarifyPagesItemSchema = z.lazy(() => z.union([
|
|
|
899
898
|
title: clarifyLocalizedTextSchema.optional(),
|
|
900
899
|
icon: z.string().optional(),
|
|
901
900
|
redirect: z.string().optional()
|
|
902
|
-
}),
|
|
901
|
+
}).strict(),
|
|
903
902
|
z.object({
|
|
904
903
|
openapi: z.string(),
|
|
905
904
|
path: z.string().optional(),
|
|
906
905
|
icon: z.string().optional(),
|
|
907
906
|
title: clarifyLocalizedTextSchema.optional(),
|
|
908
|
-
filter: z.object({ tags: z.array(z.string()).optional() }).optional()
|
|
909
|
-
})
|
|
907
|
+
filter: z.object({ tags: z.array(z.string()).optional() }).strict().optional()
|
|
908
|
+
}).strict()
|
|
910
909
|
]));
|
|
911
910
|
var clarifyPagesGroupSchema = z.lazy(() => z.object({
|
|
912
911
|
group: clarifyLocalizedTextSchema,
|
|
913
912
|
icon: z.string().optional(),
|
|
914
913
|
pages: z.array(clarifyPagesItemSchema)
|
|
915
|
-
}));
|
|
914
|
+
}).strict());
|
|
916
915
|
var clarifyPagesConfigSchema = z.union([z.array(clarifyPagesGroupSchema), z.literal("FileTree")]);
|
|
917
916
|
var clarifyTabItemSchema = z.object({
|
|
918
917
|
tab: clarifyLocalizedTextSchema,
|
|
919
918
|
icon: z.string().optional(),
|
|
920
919
|
pages: clarifyPagesConfigSchema.optional()
|
|
921
|
-
});
|
|
920
|
+
}).strict();
|
|
922
921
|
var clarifyTabsConfigSchema = z.array(clarifyTabItemSchema);
|
|
923
922
|
var clarifyThemePresetSchema = z.enum(["default", "base"]);
|
|
924
923
|
var clarifyThemeModeColorValueSchema = z.object({
|
|
925
924
|
light: z.string().optional(),
|
|
926
925
|
dark: z.string().optional()
|
|
927
|
-
});
|
|
926
|
+
}).strict();
|
|
928
927
|
var clarifyThemeColorValueSchema = z.union([z.string(), clarifyThemeModeColorValueSchema]);
|
|
929
928
|
var clarifyThemeColorTokensConfigSchema = z.object({
|
|
930
929
|
primary: clarifyThemeColorValueSchema.optional(),
|
|
@@ -935,42 +934,65 @@ var clarifyThemeColorTokensConfigSchema = z.object({
|
|
|
935
934
|
muted: clarifyThemeColorValueSchema.optional(),
|
|
936
935
|
border: clarifyThemeColorValueSchema.optional(),
|
|
937
936
|
codeBackground: clarifyThemeColorValueSchema.optional()
|
|
938
|
-
});
|
|
937
|
+
}).strict();
|
|
939
938
|
var clarifyThemeRadiusTokensConfigSchema = z.object({
|
|
940
939
|
sm: z.string().optional(),
|
|
941
940
|
md: z.string().optional(),
|
|
942
941
|
lg: z.string().optional(),
|
|
943
942
|
xl: z.string().optional()
|
|
944
|
-
});
|
|
943
|
+
}).strict();
|
|
945
944
|
var clarifyThemeTokensConfigSchema = z.object({
|
|
946
945
|
colors: clarifyThemeColorTokensConfigSchema.optional(),
|
|
947
946
|
radius: clarifyThemeRadiusTokensConfigSchema.optional()
|
|
948
|
-
});
|
|
949
|
-
var clarifyThemeLayoutConfigSchema = z.object({ maxWidth: z.string().optional() });
|
|
947
|
+
}).strict();
|
|
948
|
+
var clarifyThemeLayoutConfigSchema = z.object({ maxWidth: z.string().optional() }).strict();
|
|
950
949
|
var clarifyThemeConfigSchema = z.object({
|
|
951
950
|
preset: clarifyThemePresetSchema.optional(),
|
|
952
951
|
tokens: clarifyThemeTokensConfigSchema.optional(),
|
|
953
|
-
layout: clarifyThemeLayoutConfigSchema.optional()
|
|
954
|
-
|
|
955
|
-
|
|
952
|
+
layout: clarifyThemeLayoutConfigSchema.optional()
|
|
953
|
+
}).strict();
|
|
954
|
+
function featureSchema(shape, defaults) {
|
|
955
|
+
const objectSchema = z.object({
|
|
956
|
+
enabled: z.boolean().default(true),
|
|
957
|
+
...shape
|
|
958
|
+
}).strict().default({
|
|
959
|
+
enabled: true,
|
|
960
|
+
...defaults
|
|
961
|
+
});
|
|
962
|
+
return z.union([z.boolean(), objectSchema]).default({
|
|
963
|
+
enabled: true,
|
|
964
|
+
...defaults
|
|
965
|
+
}).transform((value) => typeof value === "boolean" ? {
|
|
966
|
+
enabled: value,
|
|
967
|
+
...defaults
|
|
968
|
+
} : value);
|
|
969
|
+
}
|
|
970
|
+
var clarifyFeaturesConfigSchema = z.object({
|
|
971
|
+
search: featureSchema({ provider: z.literal("pagefind").default("pagefind") }, { provider: "pagefind" }),
|
|
972
|
+
repository: featureSchema(clarifyRepositoryConfigSchema.shape, {}),
|
|
973
|
+
themeEditor: featureSchema({}, {}),
|
|
974
|
+
openapi: featureSchema({ playground: z.boolean().default(true) }, { playground: true })
|
|
975
|
+
}).strict();
|
|
956
976
|
var clarifyProjectConfigSchema = z.object({
|
|
957
977
|
title: z.string().optional(),
|
|
958
978
|
description: z.string().optional(),
|
|
959
979
|
siteUrl: z.string().optional(),
|
|
960
|
-
|
|
980
|
+
routePrefix: z.string().default("/"),
|
|
981
|
+
assetPrefix: z.string().optional(),
|
|
961
982
|
logo: clarifyLogoConfigSchema.optional(),
|
|
962
983
|
homeUrl: z.string().optional(),
|
|
963
984
|
favicon: clarifyFaviconConfigSchema.optional(),
|
|
964
985
|
theme: clarifyThemeConfigSchema.optional(),
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
986
|
+
navigation: z.object({
|
|
987
|
+
links: z.array(clarifyNavbarLinkSchema).optional(),
|
|
988
|
+
tabs: clarifyTabsConfigSchema.optional()
|
|
989
|
+
}).strict().optional(),
|
|
968
990
|
banner: clarifyBannerConfigOptionsSchema.optional(),
|
|
969
991
|
footer: clarifyFooterConfigSchema.optional(),
|
|
992
|
+
locales: clarifyLocalesConfigSchema.optional(),
|
|
970
993
|
variables: clarifyVariablesConfigSchema.optional(),
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
});
|
|
994
|
+
features: clarifyFeaturesConfigSchema.optional()
|
|
995
|
+
}).strict();
|
|
974
996
|
//#endregion
|
|
975
997
|
//#region source/core/config/config.ts
|
|
976
998
|
function formatIssuePath(path) {
|
|
@@ -992,17 +1014,20 @@ function validateProjectConfig(value) {
|
|
|
992
1014
|
if (!result.success) throw new Error(formatProjectConfigError(result.error));
|
|
993
1015
|
return result.data;
|
|
994
1016
|
}
|
|
995
|
-
function
|
|
996
|
-
if (!
|
|
997
|
-
const firstLocale =
|
|
998
|
-
const defaultLocale =
|
|
1017
|
+
function resolveLocalesConfig(locales) {
|
|
1018
|
+
if (!locales) return void 0;
|
|
1019
|
+
const firstLocale = locales.locales[0]?.code;
|
|
1020
|
+
const defaultLocale = locales.default ?? firstLocale;
|
|
999
1021
|
if (!defaultLocale) return void 0;
|
|
1000
1022
|
return {
|
|
1001
|
-
defaultLocale,
|
|
1002
|
-
missing:
|
|
1003
|
-
locales:
|
|
1023
|
+
default: defaultLocale,
|
|
1024
|
+
missing: locales.missing ?? "fallback",
|
|
1025
|
+
locales: locales.locales
|
|
1004
1026
|
};
|
|
1005
1027
|
}
|
|
1028
|
+
function resolveFeaturesConfig(features = {}) {
|
|
1029
|
+
return clarifyFeaturesConfigSchema.parse(features);
|
|
1030
|
+
}
|
|
1006
1031
|
function resolveRoutePrefix(routePrefix) {
|
|
1007
1032
|
const trimmed = routePrefix?.trim();
|
|
1008
1033
|
if (!trimmed || trimmed === "/") return "/";
|
|
@@ -1023,26 +1048,24 @@ function resolveProjectConfig(config = {}) {
|
|
|
1023
1048
|
title: config.title ?? "Clarify Docs",
|
|
1024
1049
|
description: config.description ?? "",
|
|
1025
1050
|
siteUrl: config.siteUrl,
|
|
1026
|
-
|
|
1051
|
+
routePrefix,
|
|
1052
|
+
assetPrefix: resolveAssetPrefix(config.assetPrefix, routePrefix),
|
|
1027
1053
|
logo: config.logo,
|
|
1028
1054
|
homeUrl: config.homeUrl,
|
|
1029
1055
|
favicon: config.favicon,
|
|
1030
|
-
routePrefix,
|
|
1031
|
-
assetPrefix: resolveAssetPrefix(config.assetPrefix, routePrefix),
|
|
1032
1056
|
theme: resolveThemeConfig(config.theme),
|
|
1033
|
-
|
|
1057
|
+
navigation: config.navigation,
|
|
1034
1058
|
banner: config.banner,
|
|
1035
1059
|
footer: config.footer,
|
|
1060
|
+
locales: resolveLocalesConfig(config.locales),
|
|
1036
1061
|
variables: config.variables ?? {},
|
|
1037
|
-
|
|
1038
|
-
tabs: config.tabs
|
|
1062
|
+
features: resolveFeaturesConfig(config.features)
|
|
1039
1063
|
};
|
|
1040
1064
|
}
|
|
1041
1065
|
//#endregion
|
|
1042
1066
|
//#region source/core/config/user-config.ts
|
|
1043
1067
|
function defineConfig(config) {
|
|
1044
|
-
|
|
1045
|
-
return config;
|
|
1068
|
+
return validateClarifyConfig(config);
|
|
1046
1069
|
}
|
|
1047
1070
|
/**
|
|
1048
1071
|
* Config filenames Clarify CLI looks for at the project root, in resolution
|
|
@@ -1066,18 +1089,23 @@ function assertConfigObject(config, configFile) {
|
|
|
1066
1089
|
}
|
|
1067
1090
|
function loadJsonConfig(configFile) {
|
|
1068
1091
|
const config = assertConfigObject(JSON.parse(readFileSync(configFile, "utf-8")), configFile);
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1092
|
+
if ("plugins" in config) throw new Error("[clarify] clarify.json does not support plugins; use clarify.ts or clarify.js");
|
|
1093
|
+
return validateClarifyConfig(config);
|
|
1094
|
+
}
|
|
1095
|
+
function validateClarifyConfig(config) {
|
|
1096
|
+
const { plugins, ...projectConfigInput } = config;
|
|
1097
|
+
if (plugins !== void 0 && !Array.isArray(plugins)) throw new Error("[clarify] config field \"plugins\" is invalid: Expected an array");
|
|
1098
|
+
const projectConfig = validateProjectConfig(projectConfigInput);
|
|
1099
|
+
return plugins ? {
|
|
1072
1100
|
...projectConfig,
|
|
1073
|
-
|
|
1074
|
-
};
|
|
1101
|
+
plugins
|
|
1102
|
+
} : projectConfig;
|
|
1075
1103
|
}
|
|
1076
1104
|
async function loadClarifyConfig(root, env) {
|
|
1077
1105
|
const configFile = findClarifyConfigFile(root);
|
|
1078
1106
|
if (!configFile) return {};
|
|
1079
1107
|
if (configFile.endsWith(".json")) return loadJsonConfig(configFile);
|
|
1080
|
-
return assertConfigObject((await loadConfigFromFile(env, configFile, root, "silent"))?.config, configFile);
|
|
1108
|
+
return validateClarifyConfig(assertConfigObject((await loadConfigFromFile(env, configFile, root, "silent"))?.config, configFile));
|
|
1081
1109
|
}
|
|
1082
1110
|
/**
|
|
1083
1111
|
* File extensions Clarify treats as content files. Kept in sync with the
|
|
@@ -1103,9 +1131,9 @@ function buildProjectInfo(context) {
|
|
|
1103
1131
|
contentRoot: (contentRoot.startsWith(projectRoot) ? contentRoot.slice(projectRoot.length).replace(/^[/\\]+/, "") : contentRoot) || "source",
|
|
1104
1132
|
projectRoot
|
|
1105
1133
|
};
|
|
1106
|
-
if (projectConfig.
|
|
1107
|
-
|
|
1108
|
-
locales: projectConfig.
|
|
1134
|
+
if (projectConfig.locales) response.locales = {
|
|
1135
|
+
default: projectConfig.locales.default,
|
|
1136
|
+
locales: projectConfig.locales.locales.map((l) => l.code)
|
|
1109
1137
|
};
|
|
1110
1138
|
return response;
|
|
1111
1139
|
}
|
|
@@ -1165,10 +1193,23 @@ function resolveVirtualModuleId(id, modules, routes) {
|
|
|
1165
1193
|
if (route) return resolveVirtualId(route.module.virtualModuleId);
|
|
1166
1194
|
return null;
|
|
1167
1195
|
}
|
|
1168
|
-
function generateConfigModule(projectConfig,
|
|
1196
|
+
function generateConfigModule(projectConfig, version) {
|
|
1169
1197
|
const runtimeConfig = {
|
|
1170
|
-
|
|
1171
|
-
|
|
1198
|
+
title: projectConfig.title,
|
|
1199
|
+
description: projectConfig.description,
|
|
1200
|
+
siteUrl: projectConfig.siteUrl,
|
|
1201
|
+
routePrefix: projectConfig.routePrefix,
|
|
1202
|
+
assetPrefix: projectConfig.assetPrefix,
|
|
1203
|
+
logo: projectConfig.logo,
|
|
1204
|
+
homeUrl: projectConfig.homeUrl,
|
|
1205
|
+
favicon: projectConfig.favicon,
|
|
1206
|
+
theme: projectConfig.theme,
|
|
1207
|
+
navigation: projectConfig.navigation,
|
|
1208
|
+
banner: projectConfig.banner,
|
|
1209
|
+
footer: projectConfig.footer,
|
|
1210
|
+
locales: projectConfig.locales,
|
|
1211
|
+
variables: projectConfig.variables,
|
|
1212
|
+
features: projectConfig.features
|
|
1172
1213
|
};
|
|
1173
1214
|
if (version) runtimeConfig.version = version;
|
|
1174
1215
|
return `export const config = ${JSON.stringify(runtimeConfig)};`;
|
|
@@ -1272,7 +1313,7 @@ function buildVirtualModules(args) {
|
|
|
1272
1313
|
const modules = /* @__PURE__ */ new Map();
|
|
1273
1314
|
const clientEntryModule = createClientEntryModule({ themeEditor: args.themeEditor });
|
|
1274
1315
|
const allPlugins = [...args.plugins ?? []];
|
|
1275
|
-
modules.set(VIRTUAL_CONFIG, generateConfigModule(args.projectConfig, args.
|
|
1316
|
+
modules.set(VIRTUAL_CONFIG, generateConfigModule(args.projectConfig, args.version));
|
|
1276
1317
|
modules.set(VIRTUAL_ROUTES, generateRoutesModule(args.routes, args.navigation, "client"));
|
|
1277
1318
|
modules.set(VIRTUAL_SERVER_ROUTES, generateRoutesModule(args.routes, args.navigation, "server"));
|
|
1278
1319
|
modules.set(VIRTUAL_SLOTS, createRuntimeSlotsModule(allPlugins, args.generateOptions.projectRoot));
|
|
@@ -1497,7 +1538,7 @@ function createViteAdapter(engine) {
|
|
|
1497
1538
|
const compilePolicyPlugin = {
|
|
1498
1539
|
name: "clarify:content-compile-policy",
|
|
1499
1540
|
configResolved(config) {
|
|
1500
|
-
contentCompileErrorPolicy = config.command === "build"
|
|
1541
|
+
contentCompileErrorPolicy = config.command === "build" ? "throw" : "diagnostic";
|
|
1501
1542
|
}
|
|
1502
1543
|
};
|
|
1503
1544
|
const tailwind = tailwindcss();
|
|
@@ -1513,7 +1554,7 @@ function createViteAdapter(engine) {
|
|
|
1513
1554
|
}
|
|
1514
1555
|
var cliPackageVersion = {
|
|
1515
1556
|
name: "@clarify-labs/cli",
|
|
1516
|
-
version: "0.
|
|
1557
|
+
version: "0.11.0",
|
|
1517
1558
|
license: "AGPL-3.0-only",
|
|
1518
1559
|
type: "module",
|
|
1519
1560
|
repository: {
|
|
@@ -1593,8 +1634,7 @@ function resolveBuildOptions(options = {}) {
|
|
|
1593
1634
|
return {
|
|
1594
1635
|
projectRoot: options.projectRoot ?? process.cwd(),
|
|
1595
1636
|
rootDirectory: options.rootDirectory ?? "source",
|
|
1596
|
-
outputDirectory: options.outputDirectory
|
|
1597
|
-
ssg: { failOnError: options.ssg?.failOnError ?? true }
|
|
1637
|
+
outputDirectory: options.outputDirectory
|
|
1598
1638
|
};
|
|
1599
1639
|
}
|
|
1600
1640
|
//#endregion
|
|
@@ -1652,7 +1692,7 @@ function llmsTxtListItem(route, basePath) {
|
|
|
1652
1692
|
return description ? `- [${route.meta.title}](${basePath}${contentArtifactUrl}): ${description}` : `- [${route.meta.title}](${basePath}${contentArtifactUrl})`;
|
|
1653
1693
|
}
|
|
1654
1694
|
function llmsTxtLocaleLabel(locale, projectConfig) {
|
|
1655
|
-
return projectConfig.
|
|
1695
|
+
return projectConfig.locales?.locales.find((item) => item.code === locale)?.label ?? locale;
|
|
1656
1696
|
}
|
|
1657
1697
|
function groupRoutesByLocale(routes) {
|
|
1658
1698
|
const groups = /* @__PURE__ */ new Map();
|
|
@@ -1664,7 +1704,7 @@ function groupRoutesByLocale(routes) {
|
|
|
1664
1704
|
}
|
|
1665
1705
|
function groupLlmsTxtRoutesByLocale(routes, projectConfig) {
|
|
1666
1706
|
const routesBySource = /* @__PURE__ */ new Map();
|
|
1667
|
-
const defaultLocale = projectConfig.
|
|
1707
|
+
const defaultLocale = projectConfig.locales?.default;
|
|
1668
1708
|
for (const route of routes) {
|
|
1669
1709
|
const sourceKey = `${route.locale ?? defaultLocale ?? "default"}:${route.basePath ?? route.artifacts?.contentArtifactUrl ?? route.path}`;
|
|
1670
1710
|
const previousRoute = routesBySource.get(sourceKey);
|
|
@@ -2059,7 +2099,7 @@ function collectOpenAPIPageIntents(config) {
|
|
|
2059
2099
|
if (!pages || pages === "FileTree") return;
|
|
2060
2100
|
for (const group of pages) visitItems(group.pages);
|
|
2061
2101
|
}
|
|
2062
|
-
for (const tab of config.tabs ?? []) visitPages(tab.pages);
|
|
2102
|
+
for (const tab of config.navigation?.tabs ?? []) visitPages(tab.pages);
|
|
2063
2103
|
return intents;
|
|
2064
2104
|
}
|
|
2065
2105
|
function virtualModuleIdFromPath(path) {
|
|
@@ -2082,14 +2122,14 @@ function cloneOpenAPIRoute(route, overrides = {}) {
|
|
|
2082
2122
|
...overrides
|
|
2083
2123
|
};
|
|
2084
2124
|
}
|
|
2085
|
-
function findOpenAPIRoutesForContentRoot(contentRoot,
|
|
2086
|
-
if (!
|
|
2125
|
+
function findOpenAPIRoutesForContentRoot(contentRoot, locales) {
|
|
2126
|
+
if (!locales) return findOpenAPIRoutes(contentRoot);
|
|
2087
2127
|
const localizedRoutes = [];
|
|
2088
|
-
for (const locale of
|
|
2128
|
+
for (const locale of locales.locales) {
|
|
2089
2129
|
const localeRoot = join(contentRoot, locale.code);
|
|
2090
2130
|
for (const route of findOpenAPIRoutes(localeRoot, localeRoot)) {
|
|
2091
2131
|
const basePath = route.basePath ?? route.path;
|
|
2092
|
-
const path = localizedRoutePath(basePath, locale.code,
|
|
2132
|
+
const path = localizedRoutePath(basePath, locale.code, locales);
|
|
2093
2133
|
localizedRoutes.push({
|
|
2094
2134
|
...route,
|
|
2095
2135
|
path,
|
|
@@ -2099,15 +2139,15 @@ function findOpenAPIRoutesForContentRoot(contentRoot, i18n) {
|
|
|
2099
2139
|
});
|
|
2100
2140
|
}
|
|
2101
2141
|
}
|
|
2102
|
-
if (
|
|
2142
|
+
if (locales.missing === "fallback") {
|
|
2103
2143
|
const routeByLocaleAndBase = new Map(localizedRoutes.map((route) => [`${route.locale ?? ""}:${route.basePath ?? route.path}`, route]));
|
|
2104
|
-
const defaultRoutes = localizedRoutes.filter((route) => route.locale ===
|
|
2144
|
+
const defaultRoutes = localizedRoutes.filter((route) => route.locale === locales.default);
|
|
2105
2145
|
for (const sourceRoute of defaultRoutes) {
|
|
2106
2146
|
const basePath = sourceRoute.basePath ?? sourceRoute.path;
|
|
2107
|
-
for (const locale of
|
|
2147
|
+
for (const locale of locales.locales) {
|
|
2108
2148
|
const key = `${locale.code}:${basePath}`;
|
|
2109
2149
|
if (routeByLocaleAndBase.has(key)) continue;
|
|
2110
|
-
const path = localizedRoutePath(basePath, locale.code,
|
|
2150
|
+
const path = localizedRoutePath(basePath, locale.code, locales);
|
|
2111
2151
|
localizedRoutes.push(cloneOpenAPIRoute(sourceRoute, {
|
|
2112
2152
|
path,
|
|
2113
2153
|
locale: locale.code,
|
|
@@ -2134,7 +2174,7 @@ function createConfiguredOpenAPIRoutes(routes, config) {
|
|
|
2134
2174
|
const key = `${route.locale ?? ""}:${targetBasePath}`;
|
|
2135
2175
|
if (existingKeys.has(key)) continue;
|
|
2136
2176
|
existingKeys.add(key);
|
|
2137
|
-
const path = route.locale && config.
|
|
2177
|
+
const path = route.locale && config.locales ? localizedRoutePath(targetBasePath, route.locale, config.locales) : targetBasePath;
|
|
2138
2178
|
additions.push(cloneOpenAPIRoute(route, {
|
|
2139
2179
|
path,
|
|
2140
2180
|
basePath: targetBasePath,
|
|
@@ -2147,12 +2187,12 @@ function createConfiguredOpenAPIRoutes(routes, config) {
|
|
|
2147
2187
|
}
|
|
2148
2188
|
}
|
|
2149
2189
|
const nextRoutes = [...routes, ...additions];
|
|
2150
|
-
if (!config.
|
|
2151
|
-
const routesWithAlternates = nextRoutes.map((route) => withAlternates(route, nextRoutes, config.
|
|
2190
|
+
if (!config.locales) return nextRoutes;
|
|
2191
|
+
const routesWithAlternates = nextRoutes.map((route) => withAlternates(route, nextRoutes, config.locales));
|
|
2152
2192
|
const bareAliases = [];
|
|
2153
2193
|
const seenBare = new Set(routesWithAlternates.map((route) => route.path));
|
|
2154
2194
|
for (const route of routesWithAlternates) {
|
|
2155
|
-
if (route.locale !== config.
|
|
2195
|
+
if (route.locale !== config.locales.default) continue;
|
|
2156
2196
|
const basePath = route.basePath ?? route.path;
|
|
2157
2197
|
if (basePath === route.path || seenBare.has(basePath)) continue;
|
|
2158
2198
|
seenBare.add(basePath);
|
|
@@ -2191,7 +2231,7 @@ function createOpenAPIPlugin() {
|
|
|
2191
2231
|
hooks: {
|
|
2192
2232
|
"routes:discover": (input, ctx) => ({
|
|
2193
2233
|
...input,
|
|
2194
|
-
routes: [...input.routes, ...findOpenAPIRoutesForContentRoot(input.contentRoot, ctx.projectConfig.
|
|
2234
|
+
routes: [...input.routes, ...findOpenAPIRoutesForContentRoot(input.contentRoot, ctx.projectConfig.locales)]
|
|
2195
2235
|
}),
|
|
2196
2236
|
"routes:discovered": async (routes, ctx) => {
|
|
2197
2237
|
specs.clear();
|
|
@@ -2348,7 +2388,7 @@ async function generateDevSearchIndex(ctx, root, pagefind) {
|
|
|
2348
2388
|
const result = await index.addCustomRecord({
|
|
2349
2389
|
url: route.path,
|
|
2350
2390
|
content,
|
|
2351
|
-
language: toPagefindLanguage(route.locale ?? ctx.projectConfig.
|
|
2391
|
+
language: toPagefindLanguage(route.locale ?? ctx.projectConfig.locales?.default),
|
|
2352
2392
|
meta: { title: route.meta.title }
|
|
2353
2393
|
});
|
|
2354
2394
|
assertNoPagefindErrors(`addCustomRecord ${route.path}`, result.errors);
|
|
@@ -2391,6 +2431,7 @@ function createSearchIndexPlugin() {
|
|
|
2391
2431
|
name: "clarify:search-index",
|
|
2392
2432
|
hooks: {
|
|
2393
2433
|
async "dev:configureServer"(server, ctx) {
|
|
2434
|
+
if (!ctx.projectConfig.features.search.enabled) return;
|
|
2394
2435
|
const pagefind = await import("pagefind");
|
|
2395
2436
|
let currentRoot;
|
|
2396
2437
|
const staleRoots = /* @__PURE__ */ new Set();
|
|
@@ -2430,6 +2471,7 @@ function createSearchIndexPlugin() {
|
|
|
2430
2471
|
});
|
|
2431
2472
|
},
|
|
2432
2473
|
async "build:done"(ctx) {
|
|
2474
|
+
if (!ctx.projectConfig.features.search.enabled) return;
|
|
2433
2475
|
const outputDirectory = ctx.generateOptions.outputDirectory;
|
|
2434
2476
|
if (!outputDirectory) return;
|
|
2435
2477
|
const pageCount = await generatePagefindIndex({ outputRoot: resolve(ctx.generateOptions.projectRoot, outputDirectory) });
|
|
@@ -2482,16 +2524,18 @@ function createSeoPlugin() {
|
|
|
2482
2524
|
return {
|
|
2483
2525
|
name: "clarify:seo",
|
|
2484
2526
|
hooks: { "build:assets"(ctx) {
|
|
2527
|
+
const assets = [];
|
|
2485
2528
|
const sitemap = createSitemapXml(ctx.routes, ctx.projectConfig);
|
|
2486
2529
|
const robots = createRobotsTxt(ctx.projectConfig);
|
|
2487
|
-
if (
|
|
2488
|
-
return [{
|
|
2530
|
+
if (sitemap) assets.push({
|
|
2489
2531
|
fileName: "sitemap.xml",
|
|
2490
2532
|
source: sitemap
|
|
2491
|
-
}
|
|
2533
|
+
});
|
|
2534
|
+
if (robots) assets.push({
|
|
2492
2535
|
fileName: "robots.txt",
|
|
2493
2536
|
source: robots
|
|
2494
|
-
}
|
|
2537
|
+
});
|
|
2538
|
+
return assets;
|
|
2495
2539
|
} }
|
|
2496
2540
|
};
|
|
2497
2541
|
}
|
|
@@ -2507,7 +2551,8 @@ function encodePath(path) {
|
|
|
2507
2551
|
return path.split("/").filter(Boolean).map((segment) => encodeURIComponent(segment)).join("/");
|
|
2508
2552
|
}
|
|
2509
2553
|
function createSourceEditUrl(filePath, contentRoot, source) {
|
|
2510
|
-
|
|
2554
|
+
if (!source.url) return "";
|
|
2555
|
+
const repository = normalizeRepositoryUrl(source.url);
|
|
2511
2556
|
const branch = source.branch ?? "main";
|
|
2512
2557
|
const sourcePath = [source.directory ? trimSlashes(source.directory) : "", relative(contentRoot, filePath).replaceAll("\\", "/")].filter(Boolean).join("/");
|
|
2513
2558
|
return `${repository}/edit/${encodeURIComponent(branch)}/${encodePath(sourcePath)}`;
|
|
@@ -2525,7 +2570,8 @@ function createSourceLinksPlugin() {
|
|
|
2525
2570
|
return {
|
|
2526
2571
|
name: "clarify:source-links",
|
|
2527
2572
|
hooks: { "routes:discovered": (routes, ctx) => {
|
|
2528
|
-
|
|
2573
|
+
if (!ctx.projectConfig.features.repository.enabled) return routes;
|
|
2574
|
+
attachSourceEditUrls(routes, join(ctx.generateOptions.projectRoot, ctx.generateOptions.rootDirectory), ctx.projectConfig.features.repository);
|
|
2529
2575
|
return routes;
|
|
2530
2576
|
} }
|
|
2531
2577
|
};
|
|
@@ -2640,18 +2686,18 @@ async function resolveProjectContext(options = {}, env = {
|
|
|
2640
2686
|
}) {
|
|
2641
2687
|
const projectRoot = resolve(options.projectRoot ?? process.cwd());
|
|
2642
2688
|
const initialBuildOptions = resolveBuildOptions(options);
|
|
2643
|
-
const contentRoot = join(projectRoot, initialBuildOptions.rootDirectory);
|
|
2644
2689
|
const configFilePath = findClarifyConfigFile(projectRoot);
|
|
2645
2690
|
const config = configFilePath && existsSync(configFilePath) ? await loadClarifyConfig(projectRoot, env) : {};
|
|
2646
2691
|
const mergedOptions = {
|
|
2647
2692
|
...config,
|
|
2648
2693
|
...options,
|
|
2649
2694
|
projectRoot,
|
|
2650
|
-
rootDirectory: initialBuildOptions.rootDirectory,
|
|
2651
|
-
outputDirectory: initialBuildOptions.outputDirectory
|
|
2695
|
+
rootDirectory: options.rootDirectory ?? initialBuildOptions.rootDirectory,
|
|
2696
|
+
outputDirectory: options.outputDirectory ?? initialBuildOptions.outputDirectory
|
|
2652
2697
|
};
|
|
2653
2698
|
const resolvedProjectConfig = resolveProjectConfig(mergedOptions);
|
|
2654
2699
|
const resolvedBuildOptions = resolveBuildOptions(mergedOptions);
|
|
2700
|
+
const contentRoot = join(projectRoot, resolvedBuildOptions.rootDirectory);
|
|
2655
2701
|
return {
|
|
2656
2702
|
projectRoot,
|
|
2657
2703
|
contentRoot,
|
|
@@ -2741,9 +2787,9 @@ function canonicalUrl(contextOrConfig, route) {
|
|
|
2741
2787
|
/** Inject `lang` (and optional `dir`) onto the `<html>` tag for the route locale. */
|
|
2742
2788
|
function injectHtmlLocaleAttributes(html, contextOrConfig, route) {
|
|
2743
2789
|
const projectConfig = resolveProjectConfigFromContext(contextOrConfig);
|
|
2744
|
-
const localeCode = route?.locale ?? projectConfig.
|
|
2790
|
+
const localeCode = route?.locale ?? projectConfig.locales?.default;
|
|
2745
2791
|
if (!localeCode) return html;
|
|
2746
|
-
const dir = (projectConfig.
|
|
2792
|
+
const dir = (projectConfig.locales?.locales.find((locale) => locale.code === localeCode))?.dir;
|
|
2747
2793
|
return html.replace(/<html\b([^>]*)>/i, (_match, attributes) => {
|
|
2748
2794
|
let nextAttributes = attributes.replace(/\s+lang=("[^"]*"|'[^']*'|[^\s>]*)/i, "").replace(/\s+dir=("[^"]*"|'[^']*'|[^\s>]*)/i, "");
|
|
2749
2795
|
nextAttributes = `${nextAttributes} lang="${escapeHtml(localeCode)}"`;
|
|
@@ -2921,7 +2967,7 @@ async function buildSSRBundle(root, ssrEntry, ssrOutDir, plugins) {
|
|
|
2921
2967
|
}
|
|
2922
2968
|
});
|
|
2923
2969
|
}
|
|
2924
|
-
async function renderSSGRoutes(routes, contextOrConfig, outputDirectory, ssrBundlePath
|
|
2970
|
+
async function renderSSGRoutes(routes, contextOrConfig, outputDirectory, ssrBundlePath) {
|
|
2925
2971
|
const { render } = await import(pathToFileURL(ssrBundlePath).href);
|
|
2926
2972
|
const template = readIndexHtml(outputDirectory);
|
|
2927
2973
|
if (!template) throw new Error(`[clarify] index.html not found in outputDirectory "${outputDirectory}". Make sure Vite build produces it.`);
|
|
@@ -2933,7 +2979,7 @@ async function renderSSGRoutes(routes, contextOrConfig, outputDirectory, ssrBund
|
|
|
2933
2979
|
}
|
|
2934
2980
|
} catch (err) {
|
|
2935
2981
|
console.error(`[clarify] Failed to render route "${route.path}":`, err);
|
|
2936
|
-
|
|
2982
|
+
throw err;
|
|
2937
2983
|
}
|
|
2938
2984
|
}
|
|
2939
2985
|
//#endregion
|
|
@@ -3010,10 +3056,10 @@ var ClarifyContext = class {
|
|
|
3010
3056
|
this.currentPlugins = plugins;
|
|
3011
3057
|
}
|
|
3012
3058
|
get isI18n() {
|
|
3013
|
-
return Boolean(this.projectConfig.
|
|
3059
|
+
return Boolean(this.projectConfig.locales);
|
|
3014
3060
|
}
|
|
3015
3061
|
get defaultLocale() {
|
|
3016
|
-
return this.projectConfig.
|
|
3062
|
+
return this.projectConfig.locales?.default;
|
|
3017
3063
|
}
|
|
3018
3064
|
get(key) {
|
|
3019
3065
|
return this.values.get(key);
|
|
@@ -3207,10 +3253,10 @@ var ClarifyEngine = class {
|
|
|
3207
3253
|
async discoverSite() {
|
|
3208
3254
|
const plugins = this.ctx.plugins;
|
|
3209
3255
|
const contentRoot = this.ctx.contentRoot;
|
|
3210
|
-
const {
|
|
3256
|
+
const { locales, navigation: navigationConfig } = this.ctx.projectConfig;
|
|
3211
3257
|
let routes = await runPhase(plugins, "site:discover", this.ctx, async () => {
|
|
3212
3258
|
const options = { contentProcessor: createProjectContentProcessor(plugins, this.ctx) };
|
|
3213
|
-
const discovered =
|
|
3259
|
+
const discovered = locales ? await findLocalizedContentRoutes(contentRoot, locales, options) : await findContentRoutes(contentRoot, contentRoot, options);
|
|
3214
3260
|
const result = await runHooks(plugins, "routes:discover", {
|
|
3215
3261
|
contentRoot,
|
|
3216
3262
|
routes: discovered
|
|
@@ -3239,8 +3285,9 @@ var ClarifyEngine = class {
|
|
|
3239
3285
|
};
|
|
3240
3286
|
});
|
|
3241
3287
|
});
|
|
3242
|
-
|
|
3243
|
-
|
|
3288
|
+
const tabs = navigationConfig?.tabs;
|
|
3289
|
+
routes = applyConfiguredPageRoutePaths(routes, tabs, locales);
|
|
3290
|
+
const navigation = tabs ? locales ? buildLocalizedNavigationFromTabsConfig(routes, tabs, locales) ?? {
|
|
3244
3291
|
kind: "localized-tabbed",
|
|
3245
3292
|
locales: {}
|
|
3246
3293
|
} : buildNavigationFromTabsConfig(routes, tabs) : {
|
|
@@ -3270,7 +3317,7 @@ var ClarifyEngine = class {
|
|
|
3270
3317
|
routes: this.routes,
|
|
3271
3318
|
navigation: this.navigation,
|
|
3272
3319
|
plugins: this.plugins,
|
|
3273
|
-
themeEditor: this.runtime.command === "serve" || this.runtime.themeEditor === true || this.projectConfig.
|
|
3320
|
+
themeEditor: this.runtime.command === "serve" || this.runtime.themeEditor === true || this.projectConfig.features.themeEditor.enabled,
|
|
3274
3321
|
version: this.ctx.version
|
|
3275
3322
|
});
|
|
3276
3323
|
this.virtualModules = await runHooks(this.plugins, "modules:before", this.virtualModules, this.ctx);
|
|
@@ -3313,7 +3360,7 @@ var ClarifyEngine = class {
|
|
|
3313
3360
|
await runPhase(this.plugins, "ssg", this.ctx, async () => {
|
|
3314
3361
|
if (process.env.SKIP_CLARIFY_SSG) return;
|
|
3315
3362
|
if (!await runInterceptHooks(this.plugins, "ssg:shouldRun", this.ctx)) return;
|
|
3316
|
-
|
|
3363
|
+
assertNoContentDiagnostics(this.routes);
|
|
3317
3364
|
const outputDir = this.runtime.outputDirectory ?? this.generateOptions.outputDirectory;
|
|
3318
3365
|
if (!outputDir) throw new Error("[clarify] outputDirectory is required before SSG runs");
|
|
3319
3366
|
const ssrOutputDir = join(outputDir, ".ssr");
|
|
@@ -3327,10 +3374,10 @@ var ClarifyEngine = class {
|
|
|
3327
3374
|
plugins: this.runtime.ssrPlugins ?? []
|
|
3328
3375
|
});
|
|
3329
3376
|
const ssrBundlePath = join(ssrOutputDir, "entry-server.js");
|
|
3330
|
-
await renderSSGRoutes(this.routes, this.runtimeContext(), outputDir, ssrBundlePath
|
|
3377
|
+
await renderSSGRoutes(this.routes, this.runtimeContext(), outputDir, ssrBundlePath);
|
|
3331
3378
|
} catch (err) {
|
|
3332
3379
|
console.error("[clarify] SSG failed:", err);
|
|
3333
|
-
|
|
3380
|
+
throw err;
|
|
3334
3381
|
} finally {
|
|
3335
3382
|
if (tempEntryPath) try {
|
|
3336
3383
|
rmSync(tempEntryPath, { force: true });
|
|
@@ -3374,4 +3421,4 @@ function createClarifyEngine(options = {}) {
|
|
|
3374
3421
|
//#endregion
|
|
3375
3422
|
export { cliPackageVersion as a, defineConfig as c, createClarifyTempDir as i, createClarifyEngine as n, cliPackageVersionWithCaret as o, createClarifyRuntimeAliases as r, createViteAdapter as s, ClarifyEngine as t };
|
|
3376
3423
|
|
|
3377
|
-
//# sourceMappingURL=engine-
|
|
3424
|
+
//# sourceMappingURL=engine-DfF5RJjC.js.map
|