@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.
@@ -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, i18n) {
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(i18n.locales.flatMap((locale) => {
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, i18n) {
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 !== i18n.defaultLocale) continue;
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, i18n, options = {}) {
415
- if (!i18n) return findContentRoutes(contentRoot, contentRoot, options);
414
+ async function findLocalizedContentRoutes(contentRoot, locales, options = {}) {
415
+ if (!locales) return findContentRoutes(contentRoot, contentRoot, options);
416
416
  const localizedRoutes = [];
417
- for (const locale of i18n.locales) {
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, i18n),
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 (i18n.missing === "fallback") {
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 === i18n.defaultLocale);
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 i18n.locales) {
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, i18n),
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, i18n));
449
- return [...routesWithAlternates, ...generateBareAliases(routesWithAlternates, i18n)];
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, i18n) {
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 && i18n ? localizedRoutePath(targetBasePath, route.locale, i18n) : targetBasePath,
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 = i18n ? nextRoutes.map((route) => withAlternates(route, nextRoutes, i18n)) : nextRoutes;
549
- if (!i18n) return routesWithAlternates;
550
- return [...routesWithAlternates, ...generateBareAliases(routesWithAlternates, i18n)];
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, i18n) {
613
+ function localizeNavigationPaths(nodes, locale, locales) {
614
614
  return nodes.map((node) => ({
615
615
  ...node,
616
- path: localizedRoutePath(node.path, locale, i18n),
617
- children: node.children ? localizeNavigationPaths(node.children, locale, i18n) : void 0
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, i18n) {
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, i18n);
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, i18n.defaultLocale) ?? "",
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, i18n);
639
+ const path = route?.path ?? localizedRoutePath(basePath, locale, locales);
640
640
  return {
641
- path: (intent.kind === "page" && intent.redirect ? localizedRoutePath(routePathFromRef(intent.redirect), locale, i18n) : void 0) ?? path,
642
- title: resolveLocalizedText(intent.title, locale, i18n.defaultLocale) ?? route?.meta.title ?? kebabToTitle(basePath.split("/").pop() ?? intent.ref),
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, i18n),
651
- title: resolveLocalizedText(group.group, locale, i18n.defaultLocale) ?? "",
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, i18n) {
658
- if (!i18n) return void 0;
657
+ function buildLocalizedNavigationFromTabsConfig(routes, tabs, localesConfig) {
658
+ if (!localesConfig) return void 0;
659
659
  const locales = {};
660
- for (const locale of i18n.locales) {
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, i18n);
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, i18n.defaultLocale) ?? "",
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.i18n?.defaultLocale);
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.i18n?.defaultLocale);
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 clarifyI18nConfigSchema = z.object({
839
- defaultLocale: z.string().optional(),
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.defaultLocale && !localeCodes.has(config.defaultLocale)) ctx.addIssue({
859
+ if (config.default && !localeCodes.has(config.default)) ctx.addIssue({
861
860
  code: z.ZodIssueCode.custom,
862
- message: "defaultLocale must be one of i18n.locales",
863
- path: ["defaultLocale"]
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 clarifySourceConfigSchema = z.object({
889
- repository: z.string(),
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
- editor: z.boolean().optional()
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
- source: clarifySourceConfigSchema.optional(),
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
- routePrefix: z.string().optional(),
966
- assetPrefix: z.string().optional(),
967
- navbar: z.object({ links: z.array(clarifyNavbarLinkSchema).optional() }).optional(),
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
- i18n: clarifyI18nConfigSchema.optional(),
972
- tabs: clarifyTabsConfigSchema.optional()
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 resolveI18nConfig(i18n) {
996
- if (!i18n) return void 0;
997
- const firstLocale = i18n.locales[0]?.code;
998
- const defaultLocale = i18n.defaultLocale ?? firstLocale;
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: i18n.missing ?? "fallback",
1003
- locales: i18n.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
- source: config.source,
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
- navbar: config.navbar,
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
- i18n: resolveI18nConfig(config.i18n),
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
- validateProjectConfig(config);
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
- const projectConfig = validateProjectConfig(config);
1070
- const ssg = config.ssg && typeof config.ssg === "object" && !Array.isArray(config.ssg) ? config.ssg : void 0;
1071
- return {
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
- ...ssg ? { ssg } : {}
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.i18n) response.i18n = {
1107
- defaultLocale: projectConfig.i18n.defaultLocale,
1108
- locales: projectConfig.i18n.locales.map((l) => l.code)
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, buildOptions, version) {
1196
+ function generateConfigModule(projectConfig, version) {
1169
1197
  const runtimeConfig = {
1170
- ...projectConfig,
1171
- ...buildOptions
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.generateOptions, args.version));
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" && engine.generateOptions.ssg.failOnError ? "throw" : "diagnostic";
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.10.3",
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.i18n?.locales.find((item) => item.code === locale)?.label ?? locale;
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.i18n?.defaultLocale;
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, i18n) {
2086
- if (!i18n) return findOpenAPIRoutes(contentRoot);
2125
+ function findOpenAPIRoutesForContentRoot(contentRoot, locales) {
2126
+ if (!locales) return findOpenAPIRoutes(contentRoot);
2087
2127
  const localizedRoutes = [];
2088
- for (const locale of i18n.locales) {
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, i18n);
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 (i18n.missing === "fallback") {
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 === i18n.defaultLocale);
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 i18n.locales) {
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, i18n);
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.i18n ? localizedRoutePath(targetBasePath, route.locale, config.i18n) : targetBasePath;
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.i18n) return nextRoutes;
2151
- const routesWithAlternates = nextRoutes.map((route) => withAlternates(route, nextRoutes, config.i18n));
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.i18n.defaultLocale) continue;
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.i18n)]
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.i18n?.defaultLocale),
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 (!sitemap || !robots) return [];
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
- const repository = normalizeRepositoryUrl(source.repository);
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
- attachSourceEditUrls(routes, join(ctx.generateOptions.projectRoot, ctx.generateOptions.rootDirectory), ctx.projectConfig.source);
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.i18n?.defaultLocale;
2790
+ const localeCode = route?.locale ?? projectConfig.locales?.default;
2745
2791
  if (!localeCode) return html;
2746
- const dir = (projectConfig.i18n?.locales.find((locale) => locale.code === localeCode))?.dir;
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, failOnError = true) {
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
- if (failOnError) throw err;
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.i18n);
3059
+ return Boolean(this.projectConfig.locales);
3014
3060
  }
3015
3061
  get defaultLocale() {
3016
- return this.projectConfig.i18n?.defaultLocale;
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 { i18n, tabs } = this.ctx.projectConfig;
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 = i18n ? await findLocalizedContentRoutes(contentRoot, i18n, options) : await findContentRoutes(contentRoot, contentRoot, options);
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
- routes = applyConfiguredPageRoutePaths(routes, tabs, i18n);
3243
- const navigation = tabs ? i18n ? buildLocalizedNavigationFromTabsConfig(routes, tabs, i18n) ?? {
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.theme.editor,
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
- if (this.generateOptions.ssg.failOnError) assertNoContentDiagnostics(this.routes);
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, this.generateOptions.ssg.failOnError);
3377
+ await renderSSGRoutes(this.routes, this.runtimeContext(), outputDir, ssrBundlePath);
3331
3378
  } catch (err) {
3332
3379
  console.error("[clarify] SSG failed:", err);
3333
- if (this.generateOptions.ssg.failOnError) throw err;
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-CyFtr8Pz.js.map
3424
+ //# sourceMappingURL=engine-DfF5RJjC.js.map