@bagelink/blox 1.17.6 → 1.18.6
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/dist/{PreviewApp-BKrLRDBC.js → PreviewApp-9H9-jLVN.js} +1 -1
- package/dist/{PreviewApp-Kb3uTwtH.cjs → PreviewApp-D8ZBTG0j.cjs} +1 -1
- package/dist/{PreviewApp.vue_vue_type_style_index_0_lang-AC3W0NSJ.cjs → PreviewApp.vue_vue_type_style_index_0_lang-BYCayJs0.cjs} +1 -1
- package/dist/{PreviewApp.vue_vue_type_style_index_0_lang-BMGv1eSR.js → PreviewApp.vue_vue_type_style_index_0_lang-BwiLyRBw.js} +1 -1
- package/dist/{appRuntime-CWlPH_5r.js → appRuntime-DZSCSsnS.js} +39 -156
- package/dist/{appRuntime-BU2Ls-Y7.cjs → appRuntime-Z0AxTPxf.cjs} +17 -134
- package/dist/composables/useLocale.d.ts +3 -0
- package/dist/composables/useLocale.d.ts.map +1 -1
- package/dist/composables/useLocaleNav.d.ts.map +1 -1
- package/dist/createBloxApp.d.ts.map +1 -1
- package/dist/hydration.d.ts +2 -0
- package/dist/hydration.d.ts.map +1 -1
- package/dist/index.cjs +16 -9
- package/dist/index.mjs +44 -36
- package/dist/localeStrategy-OwRIn35C.cjs +207 -0
- package/dist/localeStrategy-hXlNof1E.js +208 -0
- package/dist/localeStrategy.d.ts +21 -0
- package/dist/localeStrategy.d.ts.map +1 -1
- package/dist/{shard-runner-DXjScXLk.cjs → shard-runner-DF3K3Ze_.cjs} +14 -7
- package/dist/{shard-runner-f05p1VMY.js → shard-runner-DFrc8d4O.js} +15 -8
- package/dist/ssg/cli.cjs +9 -2
- package/dist/ssg/cli.mjs +9 -2
- package/dist/ssg/cms-routes.d.ts +7 -0
- package/dist/ssg/cms-routes.d.ts.map +1 -1
- package/dist/ssg/index.cjs +4 -2
- package/dist/ssg/index.mjs +5 -3
- package/dist/ssg/prerender.d.ts +3 -1
- package/dist/ssg/prerender.d.ts.map +1 -1
- package/dist/ssg/render-resolved-page.d.ts +2 -0
- package/dist/ssg/render-resolved-page.d.ts.map +1 -1
- package/dist/ssg/seo.d.ts.map +1 -1
- package/dist/ssg/shard-runner.d.ts +3 -0
- package/dist/ssg/shard-runner.d.ts.map +1 -1
- package/dist/{validate-output-C94Qpxw3.cjs → validate-output-BymMbrA5.cjs} +45 -13
- package/dist/{validate-output-CuX33CnX.js → validate-output-yDJYYYzK.js} +41 -9
- package/package.json +125 -124
- package/LICENSE +0 -21
- package/dist/pageTitle-B1mtDJKn.js +0 -59
- package/dist/pageTitle-wobGhtiZ.cjs +0 -58
package/dist/index.mjs
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import { useBloxApi, getItemBySlug, getItemById, provideBloxApi } from "./index-I81QTzv-.js";
|
|
2
2
|
import { configureApi, createBloxApi, getCollectionResolver, getWebsiteId, getWebsiteIdSync, listItems, resolvePath, setApiOrigin, setCollectionResolver } from "./index-I81QTzv-.js";
|
|
3
|
-
import { _, P, s, a } from "./PreviewApp.vue_vue_type_style_index_0_lang-
|
|
4
|
-
import { f as BLOX_LOCALE_STRATEGY_KEY, u as useLocale, n as normalizeLink, e as BLOX_RUNTIME_KEY, g as useSeo, h as getRegistryData, j as getContentRoute, p as provideBloxData, b as provideBloxLocale, i as installBloxRuntime, s as setActiveLocale, k as isMissingPageDocument, l as installSmartLinks, m as
|
|
5
|
-
import { _ as _2, t, v, w, x, y, z, A,
|
|
3
|
+
import { _, P, s, a } from "./PreviewApp.vue_vue_type_style_index_0_lang-BwiLyRBw.js";
|
|
4
|
+
import { f as BLOX_LOCALE_STRATEGY_KEY, u as useLocale, n as normalizeLink, e as BLOX_RUNTIME_KEY, g as useSeo, h as getRegistryData, j as getContentRoute, p as provideBloxData, b as provideBloxLocale, i as installBloxRuntime, s as setActiveLocale, k as isMissingPageDocument, l as installSmartLinks, m as BLOX_CMS_ROUTE_NAME, o as BLOX_PREVIEW_ROUTE_NAME } from "./appRuntime-DZSCSsnS.js";
|
|
5
|
+
import { _ as _2, q, t, v, w, x, y, z, A, P as P2, C, D, c, a as a2, E, F, G, H, I, J, K, L, M, N, O, r, Q, R, S, T } from "./appRuntime-DZSCSsnS.js";
|
|
6
6
|
import { defineComponent, resolveComponent, openBlock, createBlock, withCtx, Transition, resolveDynamicComponent, inject, ref, watch, onMounted, onUnmounted, computed, onServerPrefetch, toValue, h, Suspense, createSSRApp, createApp } from "vue";
|
|
7
7
|
import { r as readBloxHydration } from "./client-Ce9fRCGH.js";
|
|
8
8
|
import { useRouter, useRoute } from "vue-router";
|
|
9
|
+
import { s as setPageSlugMap, a as consumePendingLocaleSwitch } from "./localeStrategy-hXlNof1E.js";
|
|
10
|
+
import { g, l } from "./localeStrategy-hXlNof1E.js";
|
|
9
11
|
const FORM_CONTROL_SELECTOR = "button, input, select, textarea, label, option";
|
|
10
12
|
function isEditorPreview$1() {
|
|
11
13
|
try {
|
|
@@ -129,7 +131,7 @@ function useGlobalBlock(blockType) {
|
|
|
129
131
|
function useLocaleNav() {
|
|
130
132
|
const strategy = inject(BLOX_LOCALE_STRATEGY_KEY, null);
|
|
131
133
|
const router = useRouter();
|
|
132
|
-
const { locale, currentAlternates } = useLocale();
|
|
134
|
+
const { locale, currentAlternates, currentLocaleFallbacks } = useLocale();
|
|
133
135
|
const availableLocales = computed(() => {
|
|
134
136
|
var _a;
|
|
135
137
|
const alts = Object.keys(currentAlternates.value ?? {});
|
|
@@ -141,8 +143,10 @@ function useLocaleNav() {
|
|
|
141
143
|
strategy.switchTo(targetLocale, alternatePath(targetLocale), router);
|
|
142
144
|
}
|
|
143
145
|
function alternatePath(targetLocale) {
|
|
144
|
-
var _a;
|
|
145
|
-
|
|
146
|
+
var _a, _b, _c;
|
|
147
|
+
const exact = (_a = currentAlternates.value) == null ? void 0 : _a[targetLocale];
|
|
148
|
+
if (exact) return exact;
|
|
149
|
+
return ((_c = (_b = currentLocaleFallbacks.value) == null ? void 0 : _b[targetLocale]) == null ? void 0 : _c.find(Boolean)) ?? "/";
|
|
146
150
|
}
|
|
147
151
|
function toPath(slug) {
|
|
148
152
|
const normalized = normalizeLink(slug) ?? slug;
|
|
@@ -212,7 +216,7 @@ function useContentSeo(item, head) {
|
|
|
212
216
|
if (!entity) return;
|
|
213
217
|
const id = String(entity.id ?? entity._id ?? "");
|
|
214
218
|
const supported = (strategy == null ? void 0 : strategy.locales) ?? [locale.value];
|
|
215
|
-
const locales = (Array.isArray(entity.available_locales) ? entity.available_locales : []).filter((
|
|
219
|
+
const locales = (Array.isArray(entity.available_locales) ? entity.available_locales : []).filter((l2) => supported.includes(l2));
|
|
216
220
|
if (!id || !locales.length) return;
|
|
217
221
|
const built = {};
|
|
218
222
|
await Promise.all(locales.map(async (loc) => {
|
|
@@ -323,7 +327,7 @@ function injectPlausible(config) {
|
|
|
323
327
|
document.head.appendChild(el);
|
|
324
328
|
}
|
|
325
329
|
function createBloxApp(options) {
|
|
326
|
-
var _a, _b, _c;
|
|
330
|
+
var _a, _b, _c, _d;
|
|
327
331
|
const {
|
|
328
332
|
rootComponent,
|
|
329
333
|
router,
|
|
@@ -349,6 +353,7 @@ function createBloxApp(options) {
|
|
|
349
353
|
options.createApi({ baseURL: apiBaseURL });
|
|
350
354
|
}
|
|
351
355
|
const hasSsgState = readBloxHydration() != null;
|
|
356
|
+
setPageSlugMap((_a = readBloxHydration()) == null ? void 0 : _a.pageSlugMap);
|
|
352
357
|
const createVueApp = hasSsgState ? createSSRApp : createApp;
|
|
353
358
|
const app = createVueApp({
|
|
354
359
|
name: "BloxRoot",
|
|
@@ -404,12 +409,12 @@ function createBloxApp(options) {
|
|
|
404
409
|
setActiveLocale(localeOf(toPath), localeState);
|
|
405
410
|
return true;
|
|
406
411
|
});
|
|
407
|
-
const initialPath = typeof window !== "undefined" && ((
|
|
412
|
+
const initialPath = typeof window !== "undefined" && ((_b = window.location) == null ? void 0 : _b.pathname) ? window.location.pathname : router.currentRoute.value.path;
|
|
408
413
|
setActiveLocale(localeOf(initialPath), localeState);
|
|
409
414
|
setActiveLocale(localeOf(initialPath), localeState);
|
|
410
415
|
if (hasSsgState && strategy && typeof window !== "undefined" && !isEditorPreview()) {
|
|
411
416
|
const hostname = window.location.hostname;
|
|
412
|
-
const hydratedPath = (
|
|
417
|
+
const hydratedPath = (_d = (_c = readBloxHydration()) == null ? void 0 : _c.route) == null ? void 0 : _d.path;
|
|
413
418
|
const requestedSlug = strategy.detect(hostname, initialPath).slug;
|
|
414
419
|
if (isMissingPageDocument({
|
|
415
420
|
hydratedSlug: hydratedPath ? strategy.detect(hostname, hydratedPath).slug : "",
|
|
@@ -450,7 +455,7 @@ function defineBlock(meta) {
|
|
|
450
455
|
}
|
|
451
456
|
function withLocaleRoutes(path, component, supportedLocales, defaultLocale = "en") {
|
|
452
457
|
const normalized = path.startsWith("/") ? path : `/${path}`;
|
|
453
|
-
const prefixed = supportedLocales.filter((
|
|
458
|
+
const prefixed = supportedLocales.filter((l2) => l2 !== defaultLocale);
|
|
454
459
|
const make = (p) => ({ path: p, component });
|
|
455
460
|
const routes = [make(normalized)];
|
|
456
461
|
if (prefixed.length) {
|
|
@@ -495,56 +500,58 @@ function buildBloxManifest(blox) {
|
|
|
495
500
|
}
|
|
496
501
|
export {
|
|
497
502
|
_2 as AdminEditBar,
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
503
|
+
q as BLOX_ADMIN_CONFIG_KEY,
|
|
504
|
+
t as BLOX_CONFIG_KEY,
|
|
505
|
+
v as BLOX_DATA_KEY,
|
|
506
|
+
w as BLOX_LAYOUT_KEY,
|
|
502
507
|
BLOX_LOCALE_STRATEGY_KEY,
|
|
503
508
|
BLOX_RUNTIME_KEY,
|
|
504
|
-
|
|
509
|
+
x as BloxInstance,
|
|
505
510
|
_sfc_main as BloxRouterView,
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
511
|
+
y as CmsPageView,
|
|
512
|
+
z as ContentDetailView,
|
|
513
|
+
A as ContentHost,
|
|
509
514
|
P2 as PageRenderer,
|
|
510
515
|
_ as PreviewApp,
|
|
511
516
|
P as PreviewRenderer,
|
|
512
|
-
|
|
517
|
+
C as applyLayoutChrome,
|
|
513
518
|
buildBloxManifest,
|
|
514
|
-
|
|
519
|
+
D as classifyLink,
|
|
515
520
|
c as collectBloxData,
|
|
516
521
|
a2 as collectBloxSeo,
|
|
517
522
|
configureApi,
|
|
518
|
-
|
|
519
|
-
|
|
523
|
+
E as contentRoutes,
|
|
524
|
+
F as createBlox,
|
|
520
525
|
createBloxApi,
|
|
521
526
|
createBloxApp,
|
|
522
527
|
defineBlock,
|
|
523
528
|
defineBloxSite,
|
|
524
|
-
|
|
525
|
-
|
|
529
|
+
G as defineContent,
|
|
530
|
+
H as generateContentRoutes,
|
|
526
531
|
getCollectionResolver,
|
|
527
532
|
getContentRoute,
|
|
528
|
-
|
|
533
|
+
I as getContentRouteByCollection,
|
|
529
534
|
getItemById,
|
|
530
535
|
getItemBySlug,
|
|
536
|
+
g as getPageSlugMap,
|
|
531
537
|
getWebsiteId,
|
|
532
538
|
getWebsiteIdSync,
|
|
533
539
|
injectGtm,
|
|
534
540
|
injectPlausible,
|
|
535
|
-
|
|
541
|
+
J as installContentFallback,
|
|
536
542
|
installDocumentNavigation,
|
|
537
543
|
installGtm,
|
|
538
544
|
installSmartLinks,
|
|
539
|
-
|
|
545
|
+
K as isAbsoluteExternal,
|
|
540
546
|
isGtmInstalled,
|
|
541
|
-
|
|
542
|
-
|
|
547
|
+
L as isSoloContentPage,
|
|
548
|
+
M as isSpecialScheme,
|
|
543
549
|
listItems,
|
|
550
|
+
l as localizePageSlug,
|
|
544
551
|
normalizeLink,
|
|
545
|
-
|
|
552
|
+
N as normalizeTo,
|
|
546
553
|
provideBloxData,
|
|
547
|
-
|
|
554
|
+
O as provideContentItem,
|
|
548
555
|
readBloxHydration,
|
|
549
556
|
r as resolveBlockProps,
|
|
550
557
|
resolvePath,
|
|
@@ -553,13 +560,14 @@ export {
|
|
|
553
560
|
serializeRegistry,
|
|
554
561
|
setApiOrigin,
|
|
555
562
|
setCollectionResolver,
|
|
556
|
-
|
|
563
|
+
setPageSlugMap,
|
|
564
|
+
Q as toInternalPath,
|
|
557
565
|
useBloxApi,
|
|
558
|
-
|
|
566
|
+
R as useBloxEdit,
|
|
559
567
|
useBloxRuntime,
|
|
560
|
-
|
|
568
|
+
S as useContentItem,
|
|
561
569
|
useContentSeo,
|
|
562
|
-
|
|
570
|
+
T as useData,
|
|
563
571
|
useGlobalBlock,
|
|
564
572
|
useLocale,
|
|
565
573
|
useLocaleNav,
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
const PREFERRED_CONTEXT_KEYS = ["$page", "$post", "$item", "$article", "$product", "$event", "$author"];
|
|
3
|
+
const TITLE_FIELDS = ["meta_title", "metaTitle", "title", "name", "productName", "displayName"];
|
|
4
|
+
function primaryPageContext(contexts) {
|
|
5
|
+
if (!contexts) return null;
|
|
6
|
+
const keys = [
|
|
7
|
+
...PREFERRED_CONTEXT_KEYS.filter((key) => key in contexts),
|
|
8
|
+
...Object.keys(contexts).filter((key) => key !== "$website" && !PREFERRED_CONTEXT_KEYS.includes(key)).sort()
|
|
9
|
+
];
|
|
10
|
+
for (const key of keys) {
|
|
11
|
+
const ctx = contexts[key];
|
|
12
|
+
if (ctx != null && typeof ctx === "object") return { key, ctx };
|
|
13
|
+
}
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
16
|
+
function contextPageTitle(context) {
|
|
17
|
+
if (!context) return null;
|
|
18
|
+
for (const field of TITLE_FIELDS) {
|
|
19
|
+
const value = context[field];
|
|
20
|
+
if (typeof value === "string" && value.trim()) return value.trim();
|
|
21
|
+
}
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
function siteNameFromContexts(contexts) {
|
|
25
|
+
const website = contexts == null ? void 0 : contexts.$website;
|
|
26
|
+
const seo = website == null ? void 0 : website.seo;
|
|
27
|
+
const siteName = seo && typeof seo === "object" ? seo.site_name : website == null ? void 0 : website.site_name;
|
|
28
|
+
return typeof siteName === "string" && siteName.trim() ? siteName.trim() : null;
|
|
29
|
+
}
|
|
30
|
+
function withSiteName(title, siteName) {
|
|
31
|
+
if (!siteName || title.includes(siteName)) return title;
|
|
32
|
+
return `${title} · ${siteName}`;
|
|
33
|
+
}
|
|
34
|
+
function resolvePageTitle(resolved, options = {}) {
|
|
35
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
36
|
+
const hasBinding = !!((_a = resolved.page) == null ? void 0 : _a.data_bindings) && Object.keys(resolved.page.data_bindings).length > 0;
|
|
37
|
+
const contextTitle = hasBinding ? contextPageTitle((_b = primaryPageContext(resolved.contexts)) == null ? void 0 : _b.ctx) : null;
|
|
38
|
+
const overrideTitle = (_c = options.override) == null ? void 0 : _c.trim();
|
|
39
|
+
if (overrideTitle) return overrideTitle;
|
|
40
|
+
if (contextTitle) return withSiteName(contextTitle, options.siteName);
|
|
41
|
+
if ((_e = (_d = resolved.page) == null ? void 0 : _d.meta_title) == null ? void 0 : _e.trim()) return resolved.page.meta_title.trim();
|
|
42
|
+
if ((_g = (_f = resolved.page) == null ? void 0 : _f.title) == null ? void 0 : _g.trim()) return withSiteName(resolved.page.title.trim(), options.siteName);
|
|
43
|
+
if ((_h = options.defaultTitle) == null ? void 0 : _h.trim()) return options.defaultTitle.trim();
|
|
44
|
+
if (options.siteName) return options.siteName;
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
function preserveCurrentSiteSuffix(title, currentTitle) {
|
|
48
|
+
const separator = " · ";
|
|
49
|
+
const suffixIndex = currentTitle.lastIndexOf(separator);
|
|
50
|
+
if (suffixIndex < 0) return title;
|
|
51
|
+
const siteName = currentTitle.slice(suffixIndex + separator.length).trim();
|
|
52
|
+
return withSiteName(title, siteName);
|
|
53
|
+
}
|
|
54
|
+
let _pendingLocaleSwitch = null;
|
|
55
|
+
function consumePendingLocaleSwitch() {
|
|
56
|
+
const next = _pendingLocaleSwitch;
|
|
57
|
+
_pendingLocaleSwitch = null;
|
|
58
|
+
return next;
|
|
59
|
+
}
|
|
60
|
+
function markLocaleSwitch(locale) {
|
|
61
|
+
_pendingLocaleSwitch = locale;
|
|
62
|
+
}
|
|
63
|
+
let _pageSlugMap = {};
|
|
64
|
+
function setPageSlugMap(map) {
|
|
65
|
+
_pageSlugMap = map && typeof map === "object" ? map : {};
|
|
66
|
+
}
|
|
67
|
+
function getPageSlugMap() {
|
|
68
|
+
return _pageSlugMap;
|
|
69
|
+
}
|
|
70
|
+
function localizePageSlug(path, locale) {
|
|
71
|
+
const locales = _pageSlugMap[path];
|
|
72
|
+
if (locales) return locales[locale] ?? locales.en ?? path;
|
|
73
|
+
for (const [canonical, byLocale] of Object.entries(_pageSlugMap)) {
|
|
74
|
+
for (const [code, localized] of Object.entries(byLocale)) {
|
|
75
|
+
if (code !== locale && localized === path) return byLocale[locale] ?? canonical;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return path;
|
|
79
|
+
}
|
|
80
|
+
function createPathStrategy(options) {
|
|
81
|
+
const { defaultLocale, supportedLocales } = options;
|
|
82
|
+
let _currentLocale = defaultLocale;
|
|
83
|
+
return {
|
|
84
|
+
get locales() {
|
|
85
|
+
return supportedLocales;
|
|
86
|
+
},
|
|
87
|
+
get defaultLocale() {
|
|
88
|
+
return defaultLocale;
|
|
89
|
+
},
|
|
90
|
+
get currentLocale() {
|
|
91
|
+
return _currentLocale;
|
|
92
|
+
},
|
|
93
|
+
detect(_hostname, path) {
|
|
94
|
+
const segments = path.replace(/^\//, "").split("/");
|
|
95
|
+
const first = segments[0];
|
|
96
|
+
if (supportedLocales.includes(first)) {
|
|
97
|
+
_currentLocale = first;
|
|
98
|
+
const rest = segments.slice(1).join("/");
|
|
99
|
+
return {
|
|
100
|
+
locale: first,
|
|
101
|
+
slug: rest ? `/${rest}` : "/"
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
_currentLocale = defaultLocale;
|
|
105
|
+
return { locale: defaultLocale, slug: path || "/" };
|
|
106
|
+
},
|
|
107
|
+
toPath(slug, locale) {
|
|
108
|
+
const loc = locale || _currentLocale;
|
|
109
|
+
let s = slug ? slug.startsWith("/") ? slug : `/${slug}` : "/";
|
|
110
|
+
const segments = s.replace(/^\//, "").split("/").filter(Boolean);
|
|
111
|
+
if (segments[0] && supportedLocales.includes(segments[0])) {
|
|
112
|
+
const rest = segments.slice(1).join("/");
|
|
113
|
+
s = rest ? `/${rest}` : "/";
|
|
114
|
+
}
|
|
115
|
+
const suffixAt = s.search(/[?#]/);
|
|
116
|
+
const pathname = suffixAt === -1 ? s : s.slice(0, suffixAt);
|
|
117
|
+
const suffix = suffixAt === -1 ? "" : s.slice(suffixAt);
|
|
118
|
+
s = `${localizePageSlug(pathname || "/", loc)}${suffix}`;
|
|
119
|
+
if (loc === defaultLocale) return s;
|
|
120
|
+
return s === "/" ? `/${loc}` : `/${loc}${s}`;
|
|
121
|
+
},
|
|
122
|
+
switchTo(locale, slug, router) {
|
|
123
|
+
_currentLocale = locale;
|
|
124
|
+
const s = slug || "/";
|
|
125
|
+
const bare = (() => {
|
|
126
|
+
const segments = s.replace(/^\//, "").split("/").filter(Boolean);
|
|
127
|
+
if (segments[0] && supportedLocales.includes(segments[0])) {
|
|
128
|
+
const rest = segments.slice(1).join("/");
|
|
129
|
+
return rest ? `/${rest}` : "/";
|
|
130
|
+
}
|
|
131
|
+
return s;
|
|
132
|
+
})();
|
|
133
|
+
const target = locale === defaultLocale ? bare : bare === "/" ? `/${locale}` : `/${locale}${bare}`;
|
|
134
|
+
markLocaleSwitch(locale);
|
|
135
|
+
router.push(target);
|
|
136
|
+
},
|
|
137
|
+
normalize(path, intendedLocale) {
|
|
138
|
+
const p = path || "/";
|
|
139
|
+
const [pathname, ...restQ] = p.split(/(?=[?#])/);
|
|
140
|
+
const suffix = restQ.join("");
|
|
141
|
+
const segments = (pathname || "/").replace(/^\//, "").split("/").filter(Boolean);
|
|
142
|
+
const first = segments[0];
|
|
143
|
+
if (first && supportedLocales.includes(first)) return null;
|
|
144
|
+
if (intendedLocale === defaultLocale) return null;
|
|
145
|
+
const bare = segments.length ? `/${segments.join("/")}` : "/";
|
|
146
|
+
const rebuilt = bare === "/" ? `/${intendedLocale}` : `/${intendedLocale}${bare}`;
|
|
147
|
+
return `${rebuilt}${suffix}`;
|
|
148
|
+
}
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
function createDomainStrategy(options) {
|
|
152
|
+
const { localeDomains } = options;
|
|
153
|
+
const locales = Object.keys(localeDomains);
|
|
154
|
+
const _defaultLocale = locales[0] ?? "en";
|
|
155
|
+
const _currentLocale = locales.find((l) => localeDomains[l] === window.location.hostname) ?? _defaultLocale;
|
|
156
|
+
return {
|
|
157
|
+
get locales() {
|
|
158
|
+
return locales;
|
|
159
|
+
},
|
|
160
|
+
get defaultLocale() {
|
|
161
|
+
return _defaultLocale;
|
|
162
|
+
},
|
|
163
|
+
get currentLocale() {
|
|
164
|
+
return _currentLocale;
|
|
165
|
+
},
|
|
166
|
+
detect(_hostname, path) {
|
|
167
|
+
return { locale: _currentLocale, slug: path || "/" };
|
|
168
|
+
},
|
|
169
|
+
toPath(slug) {
|
|
170
|
+
return slug || "/";
|
|
171
|
+
},
|
|
172
|
+
switchTo(locale, slug, _router) {
|
|
173
|
+
const domain = localeDomains[locale];
|
|
174
|
+
if (!domain) return;
|
|
175
|
+
if (locale === _currentLocale) {
|
|
176
|
+
markLocaleSwitch(locale);
|
|
177
|
+
_router.push(slug || "/");
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
const { protocol } = window.location;
|
|
181
|
+
const s = slug || "/";
|
|
182
|
+
window.location.href = `${protocol}//${domain}${s}`;
|
|
183
|
+
},
|
|
184
|
+
normalize() {
|
|
185
|
+
return null;
|
|
186
|
+
}
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
function createLocaleStrategy(options) {
|
|
190
|
+
if (options.localeStrategy === "domain" && options.localeDomains) {
|
|
191
|
+
return createDomainStrategy({ localeDomains: options.localeDomains });
|
|
192
|
+
}
|
|
193
|
+
return createPathStrategy({
|
|
194
|
+
defaultLocale: options.defaultLocale ?? "en",
|
|
195
|
+
supportedLocales: options.supportedLocales ?? []
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
exports.consumePendingLocaleSwitch = consumePendingLocaleSwitch;
|
|
199
|
+
exports.contextPageTitle = contextPageTitle;
|
|
200
|
+
exports.createLocaleStrategy = createLocaleStrategy;
|
|
201
|
+
exports.getPageSlugMap = getPageSlugMap;
|
|
202
|
+
exports.localizePageSlug = localizePageSlug;
|
|
203
|
+
exports.preserveCurrentSiteSuffix = preserveCurrentSiteSuffix;
|
|
204
|
+
exports.primaryPageContext = primaryPageContext;
|
|
205
|
+
exports.resolvePageTitle = resolvePageTitle;
|
|
206
|
+
exports.setPageSlugMap = setPageSlugMap;
|
|
207
|
+
exports.siteNameFromContexts = siteNameFromContexts;
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
const PREFERRED_CONTEXT_KEYS = ["$page", "$post", "$item", "$article", "$product", "$event", "$author"];
|
|
2
|
+
const TITLE_FIELDS = ["meta_title", "metaTitle", "title", "name", "productName", "displayName"];
|
|
3
|
+
function primaryPageContext(contexts) {
|
|
4
|
+
if (!contexts) return null;
|
|
5
|
+
const keys = [
|
|
6
|
+
...PREFERRED_CONTEXT_KEYS.filter((key) => key in contexts),
|
|
7
|
+
...Object.keys(contexts).filter((key) => key !== "$website" && !PREFERRED_CONTEXT_KEYS.includes(key)).sort()
|
|
8
|
+
];
|
|
9
|
+
for (const key of keys) {
|
|
10
|
+
const ctx = contexts[key];
|
|
11
|
+
if (ctx != null && typeof ctx === "object") return { key, ctx };
|
|
12
|
+
}
|
|
13
|
+
return null;
|
|
14
|
+
}
|
|
15
|
+
function contextPageTitle(context) {
|
|
16
|
+
if (!context) return null;
|
|
17
|
+
for (const field of TITLE_FIELDS) {
|
|
18
|
+
const value = context[field];
|
|
19
|
+
if (typeof value === "string" && value.trim()) return value.trim();
|
|
20
|
+
}
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
function siteNameFromContexts(contexts) {
|
|
24
|
+
const website = contexts == null ? void 0 : contexts.$website;
|
|
25
|
+
const seo = website == null ? void 0 : website.seo;
|
|
26
|
+
const siteName = seo && typeof seo === "object" ? seo.site_name : website == null ? void 0 : website.site_name;
|
|
27
|
+
return typeof siteName === "string" && siteName.trim() ? siteName.trim() : null;
|
|
28
|
+
}
|
|
29
|
+
function withSiteName(title, siteName) {
|
|
30
|
+
if (!siteName || title.includes(siteName)) return title;
|
|
31
|
+
return `${title} · ${siteName}`;
|
|
32
|
+
}
|
|
33
|
+
function resolvePageTitle(resolved, options = {}) {
|
|
34
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
35
|
+
const hasBinding = !!((_a = resolved.page) == null ? void 0 : _a.data_bindings) && Object.keys(resolved.page.data_bindings).length > 0;
|
|
36
|
+
const contextTitle = hasBinding ? contextPageTitle((_b = primaryPageContext(resolved.contexts)) == null ? void 0 : _b.ctx) : null;
|
|
37
|
+
const overrideTitle = (_c = options.override) == null ? void 0 : _c.trim();
|
|
38
|
+
if (overrideTitle) return overrideTitle;
|
|
39
|
+
if (contextTitle) return withSiteName(contextTitle, options.siteName);
|
|
40
|
+
if ((_e = (_d = resolved.page) == null ? void 0 : _d.meta_title) == null ? void 0 : _e.trim()) return resolved.page.meta_title.trim();
|
|
41
|
+
if ((_g = (_f = resolved.page) == null ? void 0 : _f.title) == null ? void 0 : _g.trim()) return withSiteName(resolved.page.title.trim(), options.siteName);
|
|
42
|
+
if ((_h = options.defaultTitle) == null ? void 0 : _h.trim()) return options.defaultTitle.trim();
|
|
43
|
+
if (options.siteName) return options.siteName;
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
function preserveCurrentSiteSuffix(title, currentTitle) {
|
|
47
|
+
const separator = " · ";
|
|
48
|
+
const suffixIndex = currentTitle.lastIndexOf(separator);
|
|
49
|
+
if (suffixIndex < 0) return title;
|
|
50
|
+
const siteName = currentTitle.slice(suffixIndex + separator.length).trim();
|
|
51
|
+
return withSiteName(title, siteName);
|
|
52
|
+
}
|
|
53
|
+
let _pendingLocaleSwitch = null;
|
|
54
|
+
function consumePendingLocaleSwitch() {
|
|
55
|
+
const next = _pendingLocaleSwitch;
|
|
56
|
+
_pendingLocaleSwitch = null;
|
|
57
|
+
return next;
|
|
58
|
+
}
|
|
59
|
+
function markLocaleSwitch(locale) {
|
|
60
|
+
_pendingLocaleSwitch = locale;
|
|
61
|
+
}
|
|
62
|
+
let _pageSlugMap = {};
|
|
63
|
+
function setPageSlugMap(map) {
|
|
64
|
+
_pageSlugMap = map && typeof map === "object" ? map : {};
|
|
65
|
+
}
|
|
66
|
+
function getPageSlugMap() {
|
|
67
|
+
return _pageSlugMap;
|
|
68
|
+
}
|
|
69
|
+
function localizePageSlug(path, locale) {
|
|
70
|
+
const locales = _pageSlugMap[path];
|
|
71
|
+
if (locales) return locales[locale] ?? locales.en ?? path;
|
|
72
|
+
for (const [canonical, byLocale] of Object.entries(_pageSlugMap)) {
|
|
73
|
+
for (const [code, localized] of Object.entries(byLocale)) {
|
|
74
|
+
if (code !== locale && localized === path) return byLocale[locale] ?? canonical;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return path;
|
|
78
|
+
}
|
|
79
|
+
function createPathStrategy(options) {
|
|
80
|
+
const { defaultLocale, supportedLocales } = options;
|
|
81
|
+
let _currentLocale = defaultLocale;
|
|
82
|
+
return {
|
|
83
|
+
get locales() {
|
|
84
|
+
return supportedLocales;
|
|
85
|
+
},
|
|
86
|
+
get defaultLocale() {
|
|
87
|
+
return defaultLocale;
|
|
88
|
+
},
|
|
89
|
+
get currentLocale() {
|
|
90
|
+
return _currentLocale;
|
|
91
|
+
},
|
|
92
|
+
detect(_hostname, path) {
|
|
93
|
+
const segments = path.replace(/^\//, "").split("/");
|
|
94
|
+
const first = segments[0];
|
|
95
|
+
if (supportedLocales.includes(first)) {
|
|
96
|
+
_currentLocale = first;
|
|
97
|
+
const rest = segments.slice(1).join("/");
|
|
98
|
+
return {
|
|
99
|
+
locale: first,
|
|
100
|
+
slug: rest ? `/${rest}` : "/"
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
_currentLocale = defaultLocale;
|
|
104
|
+
return { locale: defaultLocale, slug: path || "/" };
|
|
105
|
+
},
|
|
106
|
+
toPath(slug, locale) {
|
|
107
|
+
const loc = locale || _currentLocale;
|
|
108
|
+
let s = slug ? slug.startsWith("/") ? slug : `/${slug}` : "/";
|
|
109
|
+
const segments = s.replace(/^\//, "").split("/").filter(Boolean);
|
|
110
|
+
if (segments[0] && supportedLocales.includes(segments[0])) {
|
|
111
|
+
const rest = segments.slice(1).join("/");
|
|
112
|
+
s = rest ? `/${rest}` : "/";
|
|
113
|
+
}
|
|
114
|
+
const suffixAt = s.search(/[?#]/);
|
|
115
|
+
const pathname = suffixAt === -1 ? s : s.slice(0, suffixAt);
|
|
116
|
+
const suffix = suffixAt === -1 ? "" : s.slice(suffixAt);
|
|
117
|
+
s = `${localizePageSlug(pathname || "/", loc)}${suffix}`;
|
|
118
|
+
if (loc === defaultLocale) return s;
|
|
119
|
+
return s === "/" ? `/${loc}` : `/${loc}${s}`;
|
|
120
|
+
},
|
|
121
|
+
switchTo(locale, slug, router) {
|
|
122
|
+
_currentLocale = locale;
|
|
123
|
+
const s = slug || "/";
|
|
124
|
+
const bare = (() => {
|
|
125
|
+
const segments = s.replace(/^\//, "").split("/").filter(Boolean);
|
|
126
|
+
if (segments[0] && supportedLocales.includes(segments[0])) {
|
|
127
|
+
const rest = segments.slice(1).join("/");
|
|
128
|
+
return rest ? `/${rest}` : "/";
|
|
129
|
+
}
|
|
130
|
+
return s;
|
|
131
|
+
})();
|
|
132
|
+
const target = locale === defaultLocale ? bare : bare === "/" ? `/${locale}` : `/${locale}${bare}`;
|
|
133
|
+
markLocaleSwitch(locale);
|
|
134
|
+
router.push(target);
|
|
135
|
+
},
|
|
136
|
+
normalize(path, intendedLocale) {
|
|
137
|
+
const p = path || "/";
|
|
138
|
+
const [pathname, ...restQ] = p.split(/(?=[?#])/);
|
|
139
|
+
const suffix = restQ.join("");
|
|
140
|
+
const segments = (pathname || "/").replace(/^\//, "").split("/").filter(Boolean);
|
|
141
|
+
const first = segments[0];
|
|
142
|
+
if (first && supportedLocales.includes(first)) return null;
|
|
143
|
+
if (intendedLocale === defaultLocale) return null;
|
|
144
|
+
const bare = segments.length ? `/${segments.join("/")}` : "/";
|
|
145
|
+
const rebuilt = bare === "/" ? `/${intendedLocale}` : `/${intendedLocale}${bare}`;
|
|
146
|
+
return `${rebuilt}${suffix}`;
|
|
147
|
+
}
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
function createDomainStrategy(options) {
|
|
151
|
+
const { localeDomains } = options;
|
|
152
|
+
const locales = Object.keys(localeDomains);
|
|
153
|
+
const _defaultLocale = locales[0] ?? "en";
|
|
154
|
+
const _currentLocale = locales.find((l) => localeDomains[l] === window.location.hostname) ?? _defaultLocale;
|
|
155
|
+
return {
|
|
156
|
+
get locales() {
|
|
157
|
+
return locales;
|
|
158
|
+
},
|
|
159
|
+
get defaultLocale() {
|
|
160
|
+
return _defaultLocale;
|
|
161
|
+
},
|
|
162
|
+
get currentLocale() {
|
|
163
|
+
return _currentLocale;
|
|
164
|
+
},
|
|
165
|
+
detect(_hostname, path) {
|
|
166
|
+
return { locale: _currentLocale, slug: path || "/" };
|
|
167
|
+
},
|
|
168
|
+
toPath(slug) {
|
|
169
|
+
return slug || "/";
|
|
170
|
+
},
|
|
171
|
+
switchTo(locale, slug, _router) {
|
|
172
|
+
const domain = localeDomains[locale];
|
|
173
|
+
if (!domain) return;
|
|
174
|
+
if (locale === _currentLocale) {
|
|
175
|
+
markLocaleSwitch(locale);
|
|
176
|
+
_router.push(slug || "/");
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
const { protocol } = window.location;
|
|
180
|
+
const s = slug || "/";
|
|
181
|
+
window.location.href = `${protocol}//${domain}${s}`;
|
|
182
|
+
},
|
|
183
|
+
normalize() {
|
|
184
|
+
return null;
|
|
185
|
+
}
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
function createLocaleStrategy(options) {
|
|
189
|
+
if (options.localeStrategy === "domain" && options.localeDomains) {
|
|
190
|
+
return createDomainStrategy({ localeDomains: options.localeDomains });
|
|
191
|
+
}
|
|
192
|
+
return createPathStrategy({
|
|
193
|
+
defaultLocale: options.defaultLocale ?? "en",
|
|
194
|
+
supportedLocales: options.supportedLocales ?? []
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
export {
|
|
198
|
+
consumePendingLocaleSwitch as a,
|
|
199
|
+
siteNameFromContexts as b,
|
|
200
|
+
contextPageTitle as c,
|
|
201
|
+
preserveCurrentSiteSuffix as d,
|
|
202
|
+
createLocaleStrategy as e,
|
|
203
|
+
getPageSlugMap as g,
|
|
204
|
+
localizePageSlug as l,
|
|
205
|
+
primaryPageContext as p,
|
|
206
|
+
resolvePageTitle as r,
|
|
207
|
+
setPageSlugMap as s
|
|
208
|
+
};
|
package/dist/localeStrategy.d.ts
CHANGED
|
@@ -39,6 +39,27 @@ export interface LocaleStrategy {
|
|
|
39
39
|
/** The locale active on this deployment/URL. */
|
|
40
40
|
readonly currentLocale: string;
|
|
41
41
|
}
|
|
42
|
+
/**
|
|
43
|
+
* Localized path per locale for one CMS page, keyed by its DEFAULT-locale
|
|
44
|
+
* (canonical) path, e.g.
|
|
45
|
+
*
|
|
46
|
+
* { "/about-us": { en: "/about-us", es: "/quienes-somos", it: "/chi-siamo" } }
|
|
47
|
+
*
|
|
48
|
+
* Built from the CMS bundle (every page's per-locale slug) and used by
|
|
49
|
+
* `toPath()` so author-written links (CMS nav/footer/block props, which hold
|
|
50
|
+
* default-locale paths) resolve straight to the localized URL. Without it every
|
|
51
|
+
* localized link is `/es/about-us`, which only works via a redirect alias.
|
|
52
|
+
*/
|
|
53
|
+
export type PageSlugMap = Record<string, Record<string, string>>;
|
|
54
|
+
/** Install/refresh the page slug map (SSG before render, client from hydration). */
|
|
55
|
+
export declare function setPageSlugMap(map: PageSlugMap | null | undefined): void;
|
|
56
|
+
export declare function getPageSlugMap(): PageSlugMap;
|
|
57
|
+
/**
|
|
58
|
+
* Translate a default-locale (or already-localized) path to `locale`'s canonical
|
|
59
|
+
* path. Returns the input unchanged when the path isn't a CMS page, so content
|
|
60
|
+
* routes (`/event/:slug`), anchors and unknown paths pass straight through.
|
|
61
|
+
*/
|
|
62
|
+
export declare function localizePageSlug(path: string, locale: string): string;
|
|
42
63
|
export interface PathStrategyOptions {
|
|
43
64
|
defaultLocale: string;
|
|
44
65
|
supportedLocales: string[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"localeStrategy.d.ts","sourceRoot":"","sources":["../src/localeStrategy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AAUxC,6EAA6E;AAC7E,wBAAgB,0BAA0B,IAAI,MAAM,GAAG,IAAI,CAI1D;AAMD,MAAM,WAAW,cAAc;IAC9B,gEAAgE;IAChE,MAAM,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAA;IAC5E;;;;;OAKG;IACH,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,KAAK,MAAM,CAAA;IACjD;;;OAGG;IACH,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,CAAA;IAChE;;;;;;;;;;;OAWG;IACH,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAA;IAClE,yBAAyB;IACzB,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,CAAA;IAC1B,wEAAwE;IACxE,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAA;IAC9B,gDAAgD;IAChD,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAA;CAC9B;AAMD,MAAM,WAAW,mBAAmB;IACnC,aAAa,EAAE,MAAM,CAAA;IACrB,gBAAgB,EAAE,MAAM,EAAE,CAAA;CAC1B;
|
|
1
|
+
{"version":3,"file":"localeStrategy.d.ts","sourceRoot":"","sources":["../src/localeStrategy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AAUxC,6EAA6E;AAC7E,wBAAgB,0BAA0B,IAAI,MAAM,GAAG,IAAI,CAI1D;AAMD,MAAM,WAAW,cAAc;IAC9B,gEAAgE;IAChE,MAAM,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAA;IAC5E;;;;;OAKG;IACH,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,KAAK,MAAM,CAAA;IACjD;;;OAGG;IACH,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,CAAA;IAChE;;;;;;;;;;;OAWG;IACH,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAA;IAClE,yBAAyB;IACzB,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,CAAA;IAC1B,wEAAwE;IACxE,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAA;IAC9B,gDAAgD;IAChD,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAA;CAC9B;AAMD;;;;;;;;;;GAUG;AACH,MAAM,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;AAIhE,oFAAoF;AACpF,wBAAgB,cAAc,CAAC,GAAG,EAAE,WAAW,GAAG,IAAI,GAAG,SAAS,GAAG,IAAI,CAExE;AAED,wBAAgB,cAAc,IAAI,WAAW,CAE5C;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAWrE;AAMD,MAAM,WAAW,mBAAmB;IACnC,aAAa,EAAE,MAAM,CAAA;IACrB,gBAAgB,EAAE,MAAM,EAAE,CAAA;CAC1B;AAiGD,MAAM,WAAW,qBAAqB;IACrC,+EAA+E;IAC/E,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CACrC;AAoDD,MAAM,WAAW,eAAe;IAC/B,cAAc,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAA;IAClC,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAA;IAC3B,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CACtC;AAED,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,eAAe,GAAG,cAAc,CAQ7E"}
|