@tenphi/renderer 0.20.3 → 0.20.5

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.
@@ -1 +1 @@
1
- {"version":3,"file":"localization.d.ts","names":[],"sources":["../src/localization.ts"],"mappings":";;;KAMK;EACH,UAAU;EACV,gBAAgB;EAChB,eAAe;;iBAGD,YAAY,cAAc,SAAS;;iBAMnC,gBACd,kBACA,cACA,SAAS;iBAWK,WAAW,cAAc,SAAS;iBAQlC,eACd,cACA,gBACA,SAAS;;iBASK,aACd,cACA,gBACA,QAAQ,aACR,SAAS;iBAoBK,WACd,cACA,qBACA,QAAQ,aACR,SAAS,eACT;;iBAec,oBACd,QAAQ,0BACR,QAAQ,aACR,qBACA,SAAS;EACN,QAAQ;EAA0B,QAAQ;;cAiElC;WACX;WACA;WACA;WACA;WACA;WACA;WAEA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;;KAEU,0BAA0B;iBA0CtB,SACd,cACA,UAAS,gBACR,OAAO;iBAUM,iBACd,cACA,QAAQ,aACR,SAAS,gBACR;EAAQ;EAAc"}
1
+ {"version":3,"file":"localization.d.ts","names":[],"sources":["../src/localization.ts"],"mappings":";;;KAMK;EACH,UAAU;EACV,gBAAgB;EAChB,eAAe;;iBAGD,YAAY,cAAc,SAAS;;iBAMnC,gBACd,kBACA,cACA,SAAS;iBAWK,WAAW,cAAc,SAAS;iBAQlC,eACd,cACA,gBACA,SAAS;;iBASK,aACd,cACA,gBACA,QAAQ,aACR,SAAS;iBAoBK,WACd,cACA,qBACA,QAAQ,aACR,SAAS,eACT;;iBAec,oBACd,QAAQ,0BACR,QAAQ,aACR,qBACA,SAAS;EACN,QAAQ;EAA0B,QAAQ;;cA8FlC;WACX;WACA;WACA;WACA;WACA;WACA;WAEA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;;KAEU,0BAA0B;iBA0CtB,SACd,cACA,UAAS,gBACR,OAAO;iBAUM,iBACd,cACA,QAAQ,aACR,SAAS,gBACR;EAAQ;EAAc"}
@@ -51,24 +51,38 @@ function localizedNavigation(layout, routes, currentPath, options) {
51
51
  route: localePath(route.route, options)
52
52
  }));
53
53
  const available = new Set(localRoutes.filter((route) => route.discoverable !== false).map((route) => route.route));
54
+ const visibleRoutes = new Map(routes.filter((route) => route.discoverable !== false).map((route) => [route.route, route]));
55
+ const fallbackLocale = options.defaultLocale ?? (options.locales.root ? "root" : Object.keys(options.locales)[0]);
54
56
  const convert = (items) => items.flatMap((item) => {
55
57
  const link = typeof item === "string" ? item : item.link;
56
58
  const internal = link?.startsWith("/") && !link.startsWith("//");
57
59
  const translated = internal ? localePath(link, options) : link;
58
- if (typeof item === "string") return !internal || available.has(translated) ? [translated] : [];
60
+ const fallback = internal ? localizedRoute(link, fallbackLocale, options) : void 0;
61
+ const target = !internal || available.has(translated) ? translated : fallback && visibleRoutes.has(fallback) ? fallback : void 0;
62
+ if (typeof item === "string") {
63
+ if (!target) return [];
64
+ if (!internal || available.has(translated)) return [target];
65
+ const route = visibleRoutes.get(target);
66
+ return [{
67
+ label: typeof route.sidebar === "object" && route.sidebar.label ? route.sidebar.label : route.title,
68
+ link: target
69
+ }];
70
+ }
59
71
  if ("items" in item || "autogenerate" in item) {
60
72
  const { link: _link, ...group } = item;
73
+ const children = "items" in item ? convert(item.items) : void 0;
74
+ if (children?.length === 0 && !target) return [];
61
75
  return [{
62
76
  ...group,
63
77
  label: label(group.label),
64
- ...translated && (!internal || available.has(translated)) ? { link: translated } : {},
65
- ..."items" in item ? { items: convert(item.items) } : { autogenerate: { directory: localePath(item.autogenerate.directory, options) } }
78
+ ...target ? { link: target } : {},
79
+ ..."items" in item ? { items: children } : { autogenerate: { directory: localePath(item.autogenerate.directory, options) } }
66
80
  }];
67
81
  }
68
- return !internal || available.has(translated) ? [{
82
+ return target ? [{
69
83
  ...item,
70
84
  label: label(item.label),
71
- link: translated
85
+ link: target
72
86
  }] : [];
73
87
  });
74
88
  return {
@@ -1 +1 @@
1
- {"version":3,"file":"localization.js","names":[],"sources":["../src/localization.ts"],"sourcesContent":["import type { DocsConfig, DocsRoute, NavigationItem } from \"@tenphi/docs\";\nimport {\n normalizeNavigationPath,\n type ResolvedNavigationLayout,\n} from \"./navigation.js\";\n\ntype LocaleOptions = {\n locales?: DocsConfig[\"locales\"] | undefined;\n defaultLocale?: DocsConfig[\"defaultLocale\"] | undefined;\n translations?: DocsConfig[\"translations\"] | undefined;\n};\n\nexport function routeLocale(path: string, options: LocaleOptions): string {\n const first = normalizeNavigationPath(path).split(\"/\")[1];\n return first && first !== \"root\" && options.locales?.[first] ? first : \"root\";\n}\n\n/** Author components can render before the page initializes route locals. */\nexport function requestLanguage(\n pathname: string,\n base: string,\n options: LocaleOptions,\n): string {\n const prefix = base.replace(/\\/$/, \"\");\n const path =\n prefix && (pathname === prefix || pathname.startsWith(`${prefix}/`))\n ? pathname.slice(prefix.length)\n : pathname;\n const locale = routeLocale(path, options);\n return options.locales?.[locale]?.lang ?? (locale === \"root\" ? \"en\" : locale);\n}\n\nexport function localePath(path: string, options: LocaleOptions): string {\n const route = normalizeNavigationPath(path);\n const locale = routeLocale(route, options);\n return locale === \"root\"\n ? route\n : normalizeNavigationPath(route.slice(locale.length + 1));\n}\n\nexport function localizedRoute(\n path: string,\n locale: string,\n options: LocaleOptions,\n): string {\n const suffix = localePath(path, options);\n return normalizeNavigationPath(\n `${locale === \"root\" ? \"\" : `/${locale}`}${suffix}`,\n );\n}\n\n/** Missing translations use a real default-language page, then a real locale home. */\nexport function localeTarget(\n path: string,\n locale: string,\n routes: DocsRoute[],\n options: LocaleOptions,\n): string | undefined {\n const visible = new Set(\n routes\n .filter((route) => route.discoverable !== false)\n .map((route) => route.route),\n );\n const fallback =\n options.defaultLocale ??\n (options.locales?.root\n ? \"root\"\n : (Object.keys(options.locales ?? {})[0] ?? \"root\"));\n return [\n localizedRoute(path, locale, options),\n localizedRoute(path, fallback, options),\n localizedRoute(\"/\", locale, options),\n localizedRoute(\"/\", fallback, options),\n ].find((route) => visible.has(route));\n}\n\nexport function localeHref(\n link: string,\n currentPath: string,\n routes: DocsRoute[],\n options: LocaleOptions,\n base = \"/\",\n): string {\n if (!link.startsWith(\"/\") || link.startsWith(\"//\")) return link;\n const suffix = /[?#].*$/.exec(link)?.[0] ?? \"\";\n const path = suffix ? link.slice(0, -suffix.length) : link;\n const target = options.locales\n ? localeTarget(path, routeLocale(currentPath, options), routes, options)\n : normalizeNavigationPath(path);\n return (\n `${base.replace(/\\/$/, \"\")}${target ?? normalizeNavigationPath(path)}${suffix}` ||\n \"/\"\n );\n}\n\n/** Resolve navigation against the current locale's available routes. */\nexport function localizedNavigation(\n layout: ResolvedNavigationLayout,\n routes: DocsRoute[],\n currentPath: string,\n options: LocaleOptions,\n): { layout: ResolvedNavigationLayout; routes: DocsRoute[] } {\n if (!options.locales) return { layout, routes };\n const locale = routeLocale(currentPath, options);\n const language =\n options.locales[locale]?.lang ?? (locale === \"root\" ? \"en\" : locale);\n const label = (value: string) =>\n options.translations?.[language]?.[`navigation.${value}`] ??\n options.translations?.[language.split(\"-\")[0]!]?.[`navigation.${value}`] ??\n value;\n const localRoutes = routes\n .filter((route) => routeLocale(route.route, options) === locale)\n .map((route) => ({ ...route, route: localePath(route.route, options) }));\n const available = new Set(\n localRoutes\n .filter((route) => route.discoverable !== false)\n .map((route) => route.route),\n );\n const convert = (items: NavigationItem[]): NavigationItem[] =>\n items.flatMap((item): NavigationItem[] => {\n const link = typeof item === \"string\" ? item : item.link;\n const internal = link?.startsWith(\"/\") && !link.startsWith(\"//\");\n const translated = internal ? localePath(link!, options) : link;\n if (typeof item === \"string\")\n return !internal || available.has(translated!) ? [translated!] : [];\n if (\"items\" in item || \"autogenerate\" in item) {\n const { link: _link, ...group } = item;\n return [\n {\n ...group,\n label: label(group.label),\n ...(translated && (!internal || available.has(translated))\n ? { link: translated }\n : {}),\n ...(\"items\" in item\n ? { items: convert(item.items) }\n : {\n autogenerate: {\n directory: localePath(item.autogenerate.directory, options),\n },\n }),\n },\n ];\n }\n return !internal || available.has(translated!)\n ? [{ ...item, label: label(item.label), link: translated! }]\n : [];\n });\n return {\n layout: {\n ...layout,\n ...(layout.items ? { items: convert(layout.items) } : {}),\n tabs: layout.tabs.map((tab) => ({\n ...tab,\n label: label(tab.label),\n link:\n tab.link.startsWith(\"/\") && !tab.link.startsWith(\"//\")\n ? localePath(tab.link, options)\n : tab.link,\n ...(tab.items ? { items: convert(tab.items) } : {}),\n })),\n },\n routes: localRoutes,\n };\n}\n\nexport const ENGLISH_MESSAGES = {\n copyPage: \"Copy page\",\n viewMarkdown: \"Download Markdown\",\n pageCopied: \"Page copied\",\n pageCopyError: \"Could not copy. Download Markdown to read or copy the text.\",\n draftTitle: \"Draft\",\n draftNotice:\n \"This page is available by direct link and excluded from navigation and indexes.\",\n searchError: \"Search could not load. Close and try again.\",\n appearance: \"Appearance\",\n colorScheme: \"Color scheme\",\n contrast: \"Contrast\",\n normalContrast: \"Normal\",\n highContrast: \"High\",\n auto: \"Auto\",\n closeNavigation: \"Close navigation\",\n primary: \"Primary\",\n sections: \"Sections\",\n chooseSection: \"Choose section\",\n headerLinks: \"Header links\",\n more: \"More\",\n closeMore: \"Close more menu\",\n moreLinks: \"More links\",\n versions: \"Versions\",\n documentationVersion: \"Documentation version\",\n documentationVersions: \"Documentation versions\",\n version: \"Version\",\n home: \"Home\",\n generatedWith: \"Generated with\",\n viewSource: \"View source\",\n copyCode: \"Copy code\",\n codeCopied: \"Code copied\",\n codeCopyError: \"Could not copy code\",\n copyHeading: \"Copy link to “{heading}”\",\n linkCopied: \"Link copied\",\n linkCopyError: \"Could not copy link\",\n notFound: \"Page not found\",\n notFoundDescription: \"The page you requested could not be found.\",\n fallback: \"fallback\",\n} as const;\nexport type MessageKey = keyof typeof ENGLISH_MESSAGES;\nconst FRENCH_MESSAGES: Record<MessageKey, string> = {\n copyPage: \"Copier la page\",\n viewMarkdown: \"Télécharger le Markdown\",\n pageCopied: \"Page copiée\",\n pageCopyError:\n \"Copie impossible. Téléchargez le Markdown pour lire ou copier le texte.\",\n draftTitle: \"Brouillon\",\n draftNotice:\n \"Cette page est accessible par son lien direct et exclue de la navigation et des index.\",\n searchError: \"La recherche n’a pas pu se charger. Fermez et réessayez.\",\n appearance: \"Apparence\",\n colorScheme: \"Thème de couleur\",\n contrast: \"Contraste\",\n normalContrast: \"Normal\",\n highContrast: \"Élevé\",\n auto: \"Auto\",\n closeNavigation: \"Fermer la navigation\",\n primary: \"Navigation principale\",\n sections: \"Sections\",\n chooseSection: \"Choisir une section\",\n headerLinks: \"Liens d’en-tête\",\n more: \"Plus\",\n closeMore: \"Fermer le menu\",\n moreLinks: \"Autres liens\",\n versions: \"Versions\",\n documentationVersion: \"Version de la documentation\",\n documentationVersions: \"Versions de la documentation\",\n version: \"Version\",\n home: \"Accueil\",\n generatedWith: \"Créé avec\",\n viewSource: \"Voir le code source\",\n copyCode: \"Copier le code\",\n codeCopied: \"Code copié\",\n codeCopyError: \"Impossible de copier le code\",\n copyHeading: \"Copier le lien vers « {heading} »\",\n linkCopied: \"Lien copié\",\n linkCopyError: \"Impossible de copier le lien\",\n notFound: \"Page introuvable\",\n notFoundDescription: \"La page demandée est introuvable.\",\n fallback: \"langue de secours\",\n};\nexport function messages(\n lang: string,\n options: LocaleOptions = {},\n): Record<MessageKey, string> {\n const language = lang.split(\"-\")[0] ?? \"en\";\n return {\n ...ENGLISH_MESSAGES,\n ...(language === \"fr\" ? FRENCH_MESSAGES : {}),\n ...options.translations?.[language],\n ...options.translations?.[lang],\n };\n}\n\nexport function localeAlternates(\n path: string,\n routes: DocsRoute[],\n options: LocaleOptions,\n): Array<{ lang: string; route: string }> {\n const available = new Set(\n routes\n .filter((route) => route.discoverable !== false)\n .map((route) => route.route),\n );\n if (!options.locales || !available.has(path)) return [];\n const alternates = Object.entries(options.locales).flatMap(\n ([locale, config]) => {\n const route = localizedRoute(path, locale, options);\n return available.has(route)\n ? [{ lang: config.lang ?? locale, route }]\n : [];\n },\n );\n const fallback = localizedRoute(\n path,\n options.defaultLocale ??\n (options.locales.root ? \"root\" : Object.keys(options.locales)[0]!),\n options,\n );\n if (available.has(fallback))\n alternates.push({ lang: \"x-default\", route: fallback });\n return alternates;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"localization.js","names":[],"sources":["../src/localization.ts"],"sourcesContent":["import type { DocsConfig, DocsRoute, NavigationItem } from \"@tenphi/docs\";\nimport {\n normalizeNavigationPath,\n type ResolvedNavigationLayout,\n} from \"./navigation.js\";\n\ntype LocaleOptions = {\n locales?: DocsConfig[\"locales\"] | undefined;\n defaultLocale?: DocsConfig[\"defaultLocale\"] | undefined;\n translations?: DocsConfig[\"translations\"] | undefined;\n};\n\nexport function routeLocale(path: string, options: LocaleOptions): string {\n const first = normalizeNavigationPath(path).split(\"/\")[1];\n return first && first !== \"root\" && options.locales?.[first] ? first : \"root\";\n}\n\n/** Author components can render before the page initializes route locals. */\nexport function requestLanguage(\n pathname: string,\n base: string,\n options: LocaleOptions,\n): string {\n const prefix = base.replace(/\\/$/, \"\");\n const path =\n prefix && (pathname === prefix || pathname.startsWith(`${prefix}/`))\n ? pathname.slice(prefix.length)\n : pathname;\n const locale = routeLocale(path, options);\n return options.locales?.[locale]?.lang ?? (locale === \"root\" ? \"en\" : locale);\n}\n\nexport function localePath(path: string, options: LocaleOptions): string {\n const route = normalizeNavigationPath(path);\n const locale = routeLocale(route, options);\n return locale === \"root\"\n ? route\n : normalizeNavigationPath(route.slice(locale.length + 1));\n}\n\nexport function localizedRoute(\n path: string,\n locale: string,\n options: LocaleOptions,\n): string {\n const suffix = localePath(path, options);\n return normalizeNavigationPath(\n `${locale === \"root\" ? \"\" : `/${locale}`}${suffix}`,\n );\n}\n\n/** Missing translations use a real default-language page, then a real locale home. */\nexport function localeTarget(\n path: string,\n locale: string,\n routes: DocsRoute[],\n options: LocaleOptions,\n): string | undefined {\n const visible = new Set(\n routes\n .filter((route) => route.discoverable !== false)\n .map((route) => route.route),\n );\n const fallback =\n options.defaultLocale ??\n (options.locales?.root\n ? \"root\"\n : (Object.keys(options.locales ?? {})[0] ?? \"root\"));\n return [\n localizedRoute(path, locale, options),\n localizedRoute(path, fallback, options),\n localizedRoute(\"/\", locale, options),\n localizedRoute(\"/\", fallback, options),\n ].find((route) => visible.has(route));\n}\n\nexport function localeHref(\n link: string,\n currentPath: string,\n routes: DocsRoute[],\n options: LocaleOptions,\n base = \"/\",\n): string {\n if (!link.startsWith(\"/\") || link.startsWith(\"//\")) return link;\n const suffix = /[?#].*$/.exec(link)?.[0] ?? \"\";\n const path = suffix ? link.slice(0, -suffix.length) : link;\n const target = options.locales\n ? localeTarget(path, routeLocale(currentPath, options), routes, options)\n : normalizeNavigationPath(path);\n return (\n `${base.replace(/\\/$/, \"\")}${target ?? normalizeNavigationPath(path)}${suffix}` ||\n \"/\"\n );\n}\n\n/** Resolve navigation against the current locale's available routes. */\nexport function localizedNavigation(\n layout: ResolvedNavigationLayout,\n routes: DocsRoute[],\n currentPath: string,\n options: LocaleOptions,\n): { layout: ResolvedNavigationLayout; routes: DocsRoute[] } {\n if (!options.locales) return { layout, routes };\n const locale = routeLocale(currentPath, options);\n const language =\n options.locales[locale]?.lang ?? (locale === \"root\" ? \"en\" : locale);\n const label = (value: string) =>\n options.translations?.[language]?.[`navigation.${value}`] ??\n options.translations?.[language.split(\"-\")[0]!]?.[`navigation.${value}`] ??\n value;\n const localRoutes = routes\n .filter((route) => routeLocale(route.route, options) === locale)\n .map((route) => ({ ...route, route: localePath(route.route, options) }));\n const available = new Set(\n localRoutes\n .filter((route) => route.discoverable !== false)\n .map((route) => route.route),\n );\n const visibleRoutes = new Map(\n routes\n .filter((route) => route.discoverable !== false)\n .map((route) => [route.route, route]),\n );\n const fallbackLocale =\n options.defaultLocale ??\n (options.locales.root ? \"root\" : Object.keys(options.locales)[0]!);\n const convert = (items: NavigationItem[]): NavigationItem[] =>\n items.flatMap((item): NavigationItem[] => {\n const link = typeof item === \"string\" ? item : item.link;\n const internal = link?.startsWith(\"/\") && !link.startsWith(\"//\");\n const translated = internal ? localePath(link!, options) : link;\n const fallback = internal\n ? localizedRoute(link!, fallbackLocale, options)\n : undefined;\n const target =\n !internal || available.has(translated!)\n ? translated\n : fallback && visibleRoutes.has(fallback)\n ? fallback\n : undefined;\n if (typeof item === \"string\") {\n if (!target) return [];\n if (!internal || available.has(translated!)) return [target];\n const route = visibleRoutes.get(target)!;\n return [\n {\n label:\n typeof route.sidebar === \"object\" && route.sidebar.label\n ? route.sidebar.label\n : route.title,\n link: target,\n },\n ];\n }\n if (\"items\" in item || \"autogenerate\" in item) {\n const { link: _link, ...group } = item;\n const children = \"items\" in item ? convert(item.items) : undefined;\n if (children?.length === 0 && !target) return [];\n return [\n {\n ...group,\n label: label(group.label),\n ...(target ? { link: target } : {}),\n ...(\"items\" in item\n ? { items: children! }\n : {\n autogenerate: {\n directory: localePath(item.autogenerate.directory, options),\n },\n }),\n },\n ];\n }\n return target\n ? [{ ...item, label: label(item.label), link: target }]\n : [];\n });\n return {\n layout: {\n ...layout,\n ...(layout.items ? { items: convert(layout.items) } : {}),\n tabs: layout.tabs.map((tab) => ({\n ...tab,\n label: label(tab.label),\n link:\n tab.link.startsWith(\"/\") && !tab.link.startsWith(\"//\")\n ? localePath(tab.link, options)\n : tab.link,\n ...(tab.items ? { items: convert(tab.items) } : {}),\n })),\n },\n routes: localRoutes,\n };\n}\n\nexport const ENGLISH_MESSAGES = {\n copyPage: \"Copy page\",\n viewMarkdown: \"Download Markdown\",\n pageCopied: \"Page copied\",\n pageCopyError: \"Could not copy. Download Markdown to read or copy the text.\",\n draftTitle: \"Draft\",\n draftNotice:\n \"This page is available by direct link and excluded from navigation and indexes.\",\n searchError: \"Search could not load. Close and try again.\",\n appearance: \"Appearance\",\n colorScheme: \"Color scheme\",\n contrast: \"Contrast\",\n normalContrast: \"Normal\",\n highContrast: \"High\",\n auto: \"Auto\",\n closeNavigation: \"Close navigation\",\n primary: \"Primary\",\n sections: \"Sections\",\n chooseSection: \"Choose section\",\n headerLinks: \"Header links\",\n more: \"More\",\n closeMore: \"Close more menu\",\n moreLinks: \"More links\",\n versions: \"Versions\",\n documentationVersion: \"Documentation version\",\n documentationVersions: \"Documentation versions\",\n version: \"Version\",\n home: \"Home\",\n generatedWith: \"Generated with\",\n viewSource: \"View source\",\n copyCode: \"Copy code\",\n codeCopied: \"Code copied\",\n codeCopyError: \"Could not copy code\",\n copyHeading: \"Copy link to “{heading}”\",\n linkCopied: \"Link copied\",\n linkCopyError: \"Could not copy link\",\n notFound: \"Page not found\",\n notFoundDescription: \"The page you requested could not be found.\",\n fallback: \"fallback\",\n} as const;\nexport type MessageKey = keyof typeof ENGLISH_MESSAGES;\nconst FRENCH_MESSAGES: Record<MessageKey, string> = {\n copyPage: \"Copier la page\",\n viewMarkdown: \"Télécharger le Markdown\",\n pageCopied: \"Page copiée\",\n pageCopyError:\n \"Copie impossible. Téléchargez le Markdown pour lire ou copier le texte.\",\n draftTitle: \"Brouillon\",\n draftNotice:\n \"Cette page est accessible par son lien direct et exclue de la navigation et des index.\",\n searchError: \"La recherche n’a pas pu se charger. Fermez et réessayez.\",\n appearance: \"Apparence\",\n colorScheme: \"Thème de couleur\",\n contrast: \"Contraste\",\n normalContrast: \"Normal\",\n highContrast: \"Élevé\",\n auto: \"Auto\",\n closeNavigation: \"Fermer la navigation\",\n primary: \"Navigation principale\",\n sections: \"Sections\",\n chooseSection: \"Choisir une section\",\n headerLinks: \"Liens d’en-tête\",\n more: \"Plus\",\n closeMore: \"Fermer le menu\",\n moreLinks: \"Autres liens\",\n versions: \"Versions\",\n documentationVersion: \"Version de la documentation\",\n documentationVersions: \"Versions de la documentation\",\n version: \"Version\",\n home: \"Accueil\",\n generatedWith: \"Créé avec\",\n viewSource: \"Voir le code source\",\n copyCode: \"Copier le code\",\n codeCopied: \"Code copié\",\n codeCopyError: \"Impossible de copier le code\",\n copyHeading: \"Copier le lien vers « {heading} »\",\n linkCopied: \"Lien copié\",\n linkCopyError: \"Impossible de copier le lien\",\n notFound: \"Page introuvable\",\n notFoundDescription: \"La page demandée est introuvable.\",\n fallback: \"langue de secours\",\n};\nexport function messages(\n lang: string,\n options: LocaleOptions = {},\n): Record<MessageKey, string> {\n const language = lang.split(\"-\")[0] ?? \"en\";\n return {\n ...ENGLISH_MESSAGES,\n ...(language === \"fr\" ? FRENCH_MESSAGES : {}),\n ...options.translations?.[language],\n ...options.translations?.[lang],\n };\n}\n\nexport function localeAlternates(\n path: string,\n routes: DocsRoute[],\n options: LocaleOptions,\n): Array<{ lang: string; route: string }> {\n const available = new Set(\n routes\n .filter((route) => route.discoverable !== false)\n .map((route) => route.route),\n );\n if (!options.locales || !available.has(path)) return [];\n const alternates = Object.entries(options.locales).flatMap(\n ([locale, config]) => {\n const route = localizedRoute(path, locale, options);\n return available.has(route)\n ? [{ lang: config.lang ?? locale, route }]\n : [];\n },\n );\n const fallback = localizedRoute(\n path,\n options.defaultLocale ??\n (options.locales.root ? \"root\" : Object.keys(options.locales)[0]!),\n options,\n );\n if (available.has(fallback))\n alternates.push({ lang: \"x-default\", route: fallback });\n return alternates;\n}\n"],"mappings":"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"}
@@ -107,6 +107,14 @@ const ui = messages(Astro.locals.cookbookRoute?.lang ?? "en", content);
107
107
  >
108
108
  <ThemeSelect />
109
109
  </div>
110
+ {
111
+ !Astro.locals.cookbookRoute.hasSidebar &&
112
+ Object.keys(content.locales ?? {}).length > 1 && (
113
+ <div class="td-header__mobile-language cookbook-print-hidden">
114
+ <LanguageSelect compact />
115
+ </div>
116
+ )
117
+ }
110
118
  <div
111
119
  class="td-header__tools cookbook-hidden md:cookbook-flex cookbook-print-hidden"
112
120
  >
@@ -2,10 +2,16 @@
2
2
  import { content } from "virtual:cookbook/config";
3
3
  import { localeTarget, routeLocale, messages } from "../localization.js";
4
4
  import { navigationPath } from "../navigation.js";
5
- import Icon from "../components/Icon.astro";
5
+ import SelectPopover from "../components/SelectPopover.astro";
6
+ interface Props {
7
+ compact?: boolean;
8
+ sidebar?: boolean;
9
+ }
10
+ const { compact = false, sidebar = false } = Astro.props;
6
11
  const current = navigationPath(Astro.url.pathname, content.base);
7
12
  const selected = routeLocale(current, content);
8
13
  const ui = messages(Astro.locals.cookbookRoute.lang, content);
14
+ const accessibleLabel = Astro.locals.t("languageSelect.accessibleLabel");
9
15
  const options = Object.entries(content.locales ?? {}).flatMap(
10
16
  ([locale, config]) => {
11
17
  const target = localeTarget(current, locale, content.routes, content);
@@ -14,50 +20,38 @@ const options = Object.entries(content.locales ?? {}).flatMap(
14
20
  ? [
15
21
  {
16
22
  locale,
17
- label: `${config.label}${fallback ? ` (${ui.fallback})` : ""}`,
23
+ label: config.label,
24
+ lang: config.lang ?? (locale === "root" ? "en" : locale),
25
+ fallback,
18
26
  href: `${content.base.replace(/\/$/, "")}${target === "/" ? "/" : `${target}/`}`,
19
27
  },
20
28
  ]
21
29
  : [];
22
30
  },
23
31
  );
32
+ const selectedOption = options.find((option) => option.locale === selected);
24
33
  ---
25
34
 
26
35
  {
27
36
  options.length > 1 && (
28
- <cookbook-language-select>
29
- <label>
30
- <Icon name="translate" class="label-icon" />
31
- <span class="sr-only">
32
- {Astro.locals.t("languageSelect.accessibleLabel")}
33
- </span>
34
- <select>
35
- {options.map((option) => (
36
- <option value={option.href} selected={option.locale === selected}>
37
- {option.label}
38
- </option>
39
- ))}
40
- </select>
41
- <Icon name="down-caret" class="caret" />
42
- </label>
37
+ <cookbook-language-select
38
+ data-compact={compact ? "" : undefined}
39
+ data-sidebar={sidebar ? "" : undefined}
40
+ data-tasty-anatomy="LanguageSelect"
41
+ >
42
+ <SelectPopover
43
+ triggerLabel={`${accessibleLabel}: ${selectedOption?.label ?? ""}`}
44
+ selectedLabel={selectedOption?.label ?? ""}
45
+ title={accessibleLabel}
46
+ icon="translate"
47
+ options={options.map((option) => ({
48
+ href: option.href,
49
+ label: option.label,
50
+ lang: option.lang,
51
+ hint: option.fallback ? ui.fallback : undefined,
52
+ current: option.locale === selected,
53
+ }))}
54
+ />
43
55
  </cookbook-language-select>
44
56
  )
45
57
  }
46
-
47
- <script>
48
- class CookbookLanguageSelect extends HTMLElement {
49
- connectedCallback() {
50
- const select = this.querySelector("select");
51
- select?.addEventListener("change", () => {
52
- window.location.href = select.value;
53
- });
54
- window.addEventListener("pageshow", () => {
55
- if (select)
56
- select.selectedIndex =
57
- select.querySelector("option[selected]")?.index ?? 0;
58
- });
59
- }
60
- }
61
- if (!customElements.get("cookbook-language-select"))
62
- customElements.define("cookbook-language-select", CookbookLanguageSelect);
63
- </script>
@@ -11,5 +11,5 @@ import { MobileMenuFooterRoot } from "../components/LayoutComponents.js";
11
11
  <div class="td-mobile-preferences__social">
12
12
  <SocialIcons />
13
13
  </div>
14
- <LanguageSelect />
14
+ <LanguageSelect sidebar />
15
15
  </MobileMenuFooterRoot>
@@ -33,9 +33,10 @@ const translations = {
33
33
  </button>
34
34
  <dialog aria-label={label}>
35
35
  <div class="dialog-frame">
36
- <button type="button" data-close-modal
37
- >{Astro.locals.t("search.cancelLabel")}</button
38
- >
36
+ <button
37
+ type="button"
38
+ data-close-modal
39
+ aria-label={Astro.locals.t("search.cancelLabel")}></button>
39
40
  {
40
41
  import.meta.env.DEV ? (
41
42
  <p data-search-status dir="ltr">
@@ -82,6 +82,7 @@ const contrasts = [
82
82
  parseScheme,
83
83
  parseContrast,
84
84
  } from "../components/appearance-preferences.js";
85
+ import { initializePopoverMotion } from "../client/popover-motion.js";
85
86
 
86
87
  let current = loadPreferences();
87
88
  const systemScheme = matchMedia("(prefers-color-scheme: light)");
@@ -127,6 +128,7 @@ const contrasts = [
127
128
  connectedCallback(): void {
128
129
  if (this.dataset.ready) return;
129
130
  this.dataset.ready = "true";
131
+ initializePopoverMotion(this.querySelector<HTMLElement>("[popover]")!);
130
132
  this.addEventListener("change", (event) => {
131
133
  const input = event.target;
132
134
  if (!(input instanceof HTMLInputElement)) return;
package/dist/ui.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"ui.d.ts","names":[],"sources":["../src/ui.ts"],"mappings":";;iBA4CgB,eACd,cACA,SAAS,KAAK,8BACb"}
1
+ {"version":3,"file":"ui.d.ts","names":[],"sources":["../src/ui.ts"],"mappings":";;iBAgDgB,eACd,cACA,SAAS,KAAK,8BACb"}
package/dist/ui.js CHANGED
@@ -17,9 +17,9 @@ const english = {
17
17
  "page.lastUpdated": "Last updated",
18
18
  "page.skipToContent": "Skip to content",
19
19
  "pagefind.search": "Search for",
20
- "pagefind.zero_results": "No results for",
21
- "pagefind.many_results": "results for",
22
- "pagefind.one_result": "result for"
20
+ "pagefind.zero_results": "No results",
21
+ "pagefind.many_results": "[COUNT] results",
22
+ "pagefind.one_result": "[COUNT] result"
23
23
  };
24
24
  const french = {
25
25
  "sidebarNav.accessibleLabel": "Navigation principale",
@@ -32,6 +32,10 @@ const french = {
32
32
  "search.label": "Rechercher",
33
33
  "search.cancelLabel": "Annuler",
34
34
  "search.devWarning": "La recherche est disponible après la génération du site.",
35
+ "pagefind.search": "Rechercher",
36
+ "pagefind.zero_results": "Aucun résultat",
37
+ "pagefind.many_results": "[COUNT] résultats",
38
+ "pagefind.one_result": "[COUNT] résultat",
35
39
  "page.nextLink": "Suivant",
36
40
  "page.previousLink": "Précédent",
37
41
  "page.editLink": "Modifier la page",
package/dist/ui.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"ui.js","names":[],"sources":["../src/ui.ts"],"sourcesContent":["import type { DocsConfig } from \"@tenphi/docs\";\n\nconst english: Record<string, string> = {\n \"sidebarNav.accessibleLabel\": \"Main navigation\",\n \"menuButton.accessibleLabel\": \"Menu\",\n \"tableOfContents.onThisPage\": \"On this page\",\n \"languageSelect.accessibleLabel\": \"Select language\",\n \"themeSelect.light\": \"Light\",\n \"themeSelect.dark\": \"Dark\",\n \"themeSelect.auto\": \"Auto\",\n \"search.label\": \"Search\",\n \"search.ctrlKey\": \"Ctrl+\",\n \"search.cancelLabel\": \"Cancel\",\n \"search.devWarning\": \"Search is available after building the site.\",\n \"page.nextLink\": \"Next\",\n \"page.previousLink\": \"Previous\",\n \"page.editLink\": \"Edit page\",\n \"page.lastUpdated\": \"Last updated\",\n \"page.skipToContent\": \"Skip to content\",\n \"pagefind.search\": \"Search for\",\n \"pagefind.zero_results\": \"No results for\",\n \"pagefind.many_results\": \"results for\",\n \"pagefind.one_result\": \"result for\",\n};\n\nconst french: Record<string, string> = {\n \"sidebarNav.accessibleLabel\": \"Navigation principale\",\n \"menuButton.accessibleLabel\": \"Menu\",\n \"tableOfContents.onThisPage\": \"Sur cette page\",\n \"languageSelect.accessibleLabel\": \"Choisir la langue\",\n \"themeSelect.light\": \"Clair\",\n \"themeSelect.dark\": \"Sombre\",\n \"themeSelect.auto\": \"Auto\",\n \"search.label\": \"Rechercher\",\n \"search.cancelLabel\": \"Annuler\",\n \"search.devWarning\":\n \"La recherche est disponible après la génération du site.\",\n \"page.nextLink\": \"Suivant\",\n \"page.previousLink\": \"Précédent\",\n \"page.editLink\": \"Modifier la page\",\n \"page.lastUpdated\": \"Dernière mise à jour\",\n \"page.skipToContent\": \"Aller au contenu\",\n};\n\nexport function uiTranslations(\n lang: string,\n options: Pick<DocsConfig, \"translations\">,\n): Record<string, string> {\n const language = lang.split(\"-\")[0] ?? \"en\";\n return {\n ...english,\n ...(language === \"fr\" ? french : {}),\n ...options.translations?.[language],\n ...options.translations?.[lang],\n };\n}\n"],"mappings":";AAEA,MAAM,UAAkC;CACtC,8BAA8B;CAC9B,8BAA8B;CAC9B,8BAA8B;CAC9B,kCAAkC;CAClC,qBAAqB;CACrB,oBAAoB;CACpB,oBAAoB;CACpB,gBAAgB;CAChB,kBAAkB;CAClB,sBAAsB;CACtB,qBAAqB;CACrB,iBAAiB;CACjB,qBAAqB;CACrB,iBAAiB;CACjB,oBAAoB;CACpB,sBAAsB;CACtB,mBAAmB;CACnB,yBAAyB;CACzB,yBAAyB;CACzB,uBAAuB;AACzB;AAEA,MAAM,SAAiC;CACrC,8BAA8B;CAC9B,8BAA8B;CAC9B,8BAA8B;CAC9B,kCAAkC;CAClC,qBAAqB;CACrB,oBAAoB;CACpB,oBAAoB;CACpB,gBAAgB;CAChB,sBAAsB;CACtB,qBACE;CACF,iBAAiB;CACjB,qBAAqB;CACrB,iBAAiB;CACjB,oBAAoB;CACpB,sBAAsB;AACxB;AAEA,SAAgB,eACd,MACA,SACwB;CACxB,MAAM,WAAW,KAAK,MAAM,GAAG,CAAC,CAAC,MAAM;CACvC,OAAO;EACL,GAAG;EACH,GAAI,aAAa,OAAO,SAAS,CAAC;EAClC,GAAG,QAAQ,eAAe;EAC1B,GAAG,QAAQ,eAAe;CAC5B;AACF"}
1
+ {"version":3,"file":"ui.js","names":[],"sources":["../src/ui.ts"],"sourcesContent":["import type { DocsConfig } from \"@tenphi/docs\";\n\nconst english: Record<string, string> = {\n \"sidebarNav.accessibleLabel\": \"Main navigation\",\n \"menuButton.accessibleLabel\": \"Menu\",\n \"tableOfContents.onThisPage\": \"On this page\",\n \"languageSelect.accessibleLabel\": \"Select language\",\n \"themeSelect.light\": \"Light\",\n \"themeSelect.dark\": \"Dark\",\n \"themeSelect.auto\": \"Auto\",\n \"search.label\": \"Search\",\n \"search.ctrlKey\": \"Ctrl+\",\n \"search.cancelLabel\": \"Cancel\",\n \"search.devWarning\": \"Search is available after building the site.\",\n \"page.nextLink\": \"Next\",\n \"page.previousLink\": \"Previous\",\n \"page.editLink\": \"Edit page\",\n \"page.lastUpdated\": \"Last updated\",\n \"page.skipToContent\": \"Skip to content\",\n \"pagefind.search\": \"Search for\",\n \"pagefind.zero_results\": \"No results\",\n \"pagefind.many_results\": \"[COUNT] results\",\n \"pagefind.one_result\": \"[COUNT] result\",\n};\n\nconst french: Record<string, string> = {\n \"sidebarNav.accessibleLabel\": \"Navigation principale\",\n \"menuButton.accessibleLabel\": \"Menu\",\n \"tableOfContents.onThisPage\": \"Sur cette page\",\n \"languageSelect.accessibleLabel\": \"Choisir la langue\",\n \"themeSelect.light\": \"Clair\",\n \"themeSelect.dark\": \"Sombre\",\n \"themeSelect.auto\": \"Auto\",\n \"search.label\": \"Rechercher\",\n \"search.cancelLabel\": \"Annuler\",\n \"search.devWarning\":\n \"La recherche est disponible après la génération du site.\",\n \"pagefind.search\": \"Rechercher\",\n \"pagefind.zero_results\": \"Aucun résultat\",\n \"pagefind.many_results\": \"[COUNT] résultats\",\n \"pagefind.one_result\": \"[COUNT] résultat\",\n \"page.nextLink\": \"Suivant\",\n \"page.previousLink\": \"Précédent\",\n \"page.editLink\": \"Modifier la page\",\n \"page.lastUpdated\": \"Dernière mise à jour\",\n \"page.skipToContent\": \"Aller au contenu\",\n};\n\nexport function uiTranslations(\n lang: string,\n options: Pick<DocsConfig, \"translations\">,\n): Record<string, string> {\n const language = lang.split(\"-\")[0] ?? \"en\";\n return {\n ...english,\n ...(language === \"fr\" ? french : {}),\n ...options.translations?.[language],\n ...options.translations?.[lang],\n };\n}\n"],"mappings":";AAEA,MAAM,UAAkC;CACtC,8BAA8B;CAC9B,8BAA8B;CAC9B,8BAA8B;CAC9B,kCAAkC;CAClC,qBAAqB;CACrB,oBAAoB;CACpB,oBAAoB;CACpB,gBAAgB;CAChB,kBAAkB;CAClB,sBAAsB;CACtB,qBAAqB;CACrB,iBAAiB;CACjB,qBAAqB;CACrB,iBAAiB;CACjB,oBAAoB;CACpB,sBAAsB;CACtB,mBAAmB;CACnB,yBAAyB;CACzB,yBAAyB;CACzB,uBAAuB;AACzB;AAEA,MAAM,SAAiC;CACrC,8BAA8B;CAC9B,8BAA8B;CAC9B,8BAA8B;CAC9B,kCAAkC;CAClC,qBAAqB;CACrB,oBAAoB;CACpB,oBAAoB;CACpB,gBAAgB;CAChB,sBAAsB;CACtB,qBACE;CACF,mBAAmB;CACnB,yBAAyB;CACzB,yBAAyB;CACzB,uBAAuB;CACvB,iBAAiB;CACjB,qBAAqB;CACrB,iBAAiB;CACjB,oBAAoB;CACpB,sBAAsB;AACxB;AAEA,SAAgB,eACd,MACA,SACwB;CACxB,MAAM,WAAW,KAAK,MAAM,GAAG,CAAC,CAAC,MAAM;CACvC,OAAO;EACL,GAAG;EACH,GAAI,aAAa,OAAO,SAAS,CAAC;EAClC,GAAG,QAAQ,eAAe;EAC1B,GAAG,QAAQ,eAAe;CAC5B;AACF"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tenphi/renderer",
3
- "version": "0.20.3",
3
+ "version": "0.20.5",
4
4
  "description": "Astro renderer and Tasty theme for Cookbook",
5
5
  "type": "module",
6
6
  "sideEffects": [
@@ -61,7 +61,7 @@
61
61
  "@fontsource-variable/jetbrains-mono": "^5.3.0",
62
62
  "@fontsource-variable/onest": "^5.3.0",
63
63
  "@pagefind/default-ui": "1.5.2",
64
- "@tenphi/docs": "0.20.3",
64
+ "@tenphi/docs": "0.20.5",
65
65
  "@tenphi/eslint-plugin-tasty": "1.1.0",
66
66
  "@tenphi/glaze": "2.0.0",
67
67
  "@tenphi/tasty": "3.8.0",