@xosen/site-sdk 0.0.15 → 0.0.16
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/index.js +103 -98
- package/package.json +1 -1
- package/src/composables/useSiteComponents.ts +24 -7
package/dist/index.js
CHANGED
|
@@ -1,28 +1,28 @@
|
|
|
1
|
-
import { ref as v, onMounted as S, watch as _, computed as
|
|
1
|
+
import { ref as v, onMounted as S, watch as _, computed as f, onUnmounted as N, reactive as L, provide as P } from "vue";
|
|
2
2
|
import { useI18n as T } from "vue-i18n";
|
|
3
3
|
import { useRoute as I } from "vue-router";
|
|
4
4
|
function Z(o, a) {
|
|
5
5
|
const t = v(null), { locale: e } = T(), s = window.__SITE_DATA__, n = s?.locale;
|
|
6
|
-
function
|
|
6
|
+
function i() {
|
|
7
7
|
return s && s[o] && e.value === n ? (t.value = s[o], !0) : !1;
|
|
8
8
|
}
|
|
9
|
-
async function
|
|
9
|
+
async function l() {
|
|
10
10
|
try {
|
|
11
|
-
const
|
|
12
|
-
|
|
11
|
+
const r = await fetch(`/api/content/${a}:${e.value}`);
|
|
12
|
+
r.ok && (t.value = await r.json());
|
|
13
13
|
} catch {
|
|
14
14
|
}
|
|
15
15
|
}
|
|
16
16
|
return S(() => {
|
|
17
|
-
|
|
17
|
+
i() || l();
|
|
18
18
|
}), _(e, () => {
|
|
19
|
-
|
|
19
|
+
l();
|
|
20
20
|
}), t;
|
|
21
21
|
}
|
|
22
22
|
function q() {
|
|
23
|
-
const o = window.__SITE_DATA__, a =
|
|
24
|
-
function
|
|
25
|
-
const g =
|
|
23
|
+
const o = window.__SITE_DATA__, a = f(() => o?.config || null), t = f(() => o?.components || {}), e = f(() => a.value?.navigation || []), s = f(() => a.value?.locales || []), n = f(() => a.value?.defaultLocale || "en"), i = f(() => a.value?.branding || {}), l = f(() => a.value?.footer || {}), r = f(() => a.value?.features || {});
|
|
24
|
+
function u(m) {
|
|
25
|
+
const g = r.value[m];
|
|
26
26
|
return typeof g == "boolean" ? g : typeof g == "object";
|
|
27
27
|
}
|
|
28
28
|
return {
|
|
@@ -31,10 +31,10 @@ function q() {
|
|
|
31
31
|
navigation: e,
|
|
32
32
|
locales: s,
|
|
33
33
|
defaultLocale: n,
|
|
34
|
-
branding:
|
|
35
|
-
footer:
|
|
36
|
-
features:
|
|
37
|
-
hasFeature:
|
|
34
|
+
branding: i,
|
|
35
|
+
footer: l,
|
|
36
|
+
features: r,
|
|
37
|
+
hasFeature: u
|
|
38
38
|
};
|
|
39
39
|
}
|
|
40
40
|
function H(o) {
|
|
@@ -64,10 +64,10 @@ function D(o) {
|
|
|
64
64
|
function Q() {
|
|
65
65
|
const a = window.__SITE_DATA__?.apiBase || "";
|
|
66
66
|
async function t(n) {
|
|
67
|
-
const
|
|
68
|
-
if (!
|
|
69
|
-
throw new Error(`API error: ${
|
|
70
|
-
return
|
|
67
|
+
const i = await fetch(`${a}${n}`);
|
|
68
|
+
if (!i.ok)
|
|
69
|
+
throw new Error(`API error: ${i.status}`);
|
|
70
|
+
return i.json();
|
|
71
71
|
}
|
|
72
72
|
async function e() {
|
|
73
73
|
return t("/v1/billing/tariffs");
|
|
@@ -116,101 +116,106 @@ function j() {
|
|
|
116
116
|
}
|
|
117
117
|
j();
|
|
118
118
|
function ee(o) {
|
|
119
|
-
const { locale: a } = T(), { previewPage: t, isPreviewMode: e } = C(), s = window.__SITE_DATA__, n = v(null),
|
|
120
|
-
const
|
|
121
|
-
if (!
|
|
122
|
-
const { blocks:
|
|
119
|
+
const { locale: a } = T(), { previewPage: t, isPreviewMode: e } = C(), s = window.__SITE_DATA__, n = v(null), i = v(!0), l = v(!1), r = f(() => typeof o == "string" ? o : o.value), u = f(() => `page:${r.value}`), m = f(() => {
|
|
120
|
+
const c = e.value ? t.value : n.value;
|
|
121
|
+
if (!c) return {};
|
|
122
|
+
const { blocks: p, meta: d, slug: W, locale: J, ...E } = c;
|
|
123
123
|
return E;
|
|
124
124
|
});
|
|
125
125
|
P(R, m);
|
|
126
|
-
const g =
|
|
127
|
-
function b(
|
|
128
|
-
n.value =
|
|
126
|
+
const g = f(() => e.value && t.value?.slug === r.value ? t.value.blocks || [] : n.value?.blocks || []);
|
|
127
|
+
function b(c) {
|
|
128
|
+
n.value = c, c && (k[u.value] = c);
|
|
129
129
|
}
|
|
130
130
|
function y() {
|
|
131
|
-
const
|
|
132
|
-
return
|
|
131
|
+
const c = s?.[u.value];
|
|
132
|
+
return c && a.value === s?.locale ? (b(c), l.value = !1, w(), !0) : !1;
|
|
133
133
|
}
|
|
134
134
|
async function h() {
|
|
135
|
-
|
|
135
|
+
i.value = !0, l.value = !1;
|
|
136
136
|
try {
|
|
137
|
-
const
|
|
138
|
-
|
|
137
|
+
const c = await fetch(`/api/content/${u.value}:${a.value}`);
|
|
138
|
+
c.ok ? (b(await c.json()), w()) : (b(null), l.value = !0);
|
|
139
139
|
} catch {
|
|
140
|
-
b(null),
|
|
140
|
+
b(null), l.value = !0;
|
|
141
141
|
} finally {
|
|
142
|
-
|
|
142
|
+
i.value = !1;
|
|
143
143
|
}
|
|
144
144
|
}
|
|
145
145
|
function w() {
|
|
146
146
|
if (!n.value) return;
|
|
147
147
|
if (n.value.title) {
|
|
148
|
-
const
|
|
148
|
+
const p = s?.config?.branding, d = p?.siteName ? ` — ${p.siteName}` : "";
|
|
149
149
|
document.title = `${n.value.title}${d}`;
|
|
150
150
|
}
|
|
151
|
-
const
|
|
152
|
-
if (
|
|
153
|
-
const
|
|
154
|
-
|
|
151
|
+
const c = n.value.meta?.description;
|
|
152
|
+
if (c) {
|
|
153
|
+
const p = document.querySelector('meta[name="description"]');
|
|
154
|
+
p && p.setAttribute("content", c);
|
|
155
155
|
}
|
|
156
156
|
}
|
|
157
|
-
return _(t, (
|
|
158
|
-
|
|
157
|
+
return _(t, (c) => {
|
|
158
|
+
c?.slug === r.value && (i.value = !1, l.value = !1, (c.title || c.blocks) && (n.value = {
|
|
159
159
|
...n.value || {},
|
|
160
|
-
...
|
|
161
|
-
...
|
|
160
|
+
...c.title ? { title: c.title } : {},
|
|
161
|
+
...c.blocks ? { blocks: c.blocks } : {}
|
|
162
162
|
}, w()));
|
|
163
163
|
}), S(() => {
|
|
164
|
-
y() ?
|
|
165
|
-
}), _(a, () => h()), _(
|
|
166
|
-
y() ?
|
|
164
|
+
y() ? i.value = !1 : h();
|
|
165
|
+
}), _(a, () => h()), _(r, () => {
|
|
166
|
+
y() ? i.value = !1 : h();
|
|
167
167
|
}), {
|
|
168
168
|
page: n,
|
|
169
169
|
blocks: g,
|
|
170
170
|
pageContext: m,
|
|
171
|
-
loading:
|
|
172
|
-
notFound:
|
|
171
|
+
loading: i,
|
|
172
|
+
notFound: l,
|
|
173
173
|
isPreviewMode: e,
|
|
174
174
|
reload: h
|
|
175
175
|
};
|
|
176
176
|
}
|
|
177
177
|
function te() {
|
|
178
178
|
const { locale: o } = T(), a = window.__SITE_DATA__, t = a?.locale, e = v({ ...a?.components || {} });
|
|
179
|
-
|
|
180
|
-
|
|
179
|
+
let s = t, n = null;
|
|
180
|
+
async function i(r) {
|
|
181
|
+
if (!$() && r !== s) {
|
|
181
182
|
if (r === t) {
|
|
182
|
-
e.value = { ...a?.components || {} };
|
|
183
|
+
e.value = { ...a?.components || {} }, s = r;
|
|
183
184
|
return;
|
|
184
185
|
}
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
186
|
+
n || (n = (async () => {
|
|
187
|
+
try {
|
|
188
|
+
const u = await fetch(`/api/content/components:${r}`);
|
|
189
|
+
u.ok && (e.value = await u.json(), s = r);
|
|
190
|
+
} catch {
|
|
191
|
+
} finally {
|
|
192
|
+
n = null;
|
|
193
|
+
}
|
|
194
|
+
})(), await n);
|
|
190
195
|
}
|
|
191
196
|
}
|
|
192
|
-
_(o, (r) =>
|
|
193
|
-
o.value !== t &&
|
|
197
|
+
_(o, (r) => i(r)), S(() => {
|
|
198
|
+
o.value !== t && i(o.value);
|
|
194
199
|
});
|
|
195
|
-
function
|
|
196
|
-
return
|
|
200
|
+
function l(r) {
|
|
201
|
+
return f(() => e.value[r] || null);
|
|
197
202
|
}
|
|
198
203
|
return {
|
|
199
204
|
/** All components (reactive, locale-aware) */
|
|
200
205
|
components: e,
|
|
201
206
|
/** Get a single component by key */
|
|
202
|
-
getComponent:
|
|
207
|
+
getComponent: l,
|
|
203
208
|
/** Force refetch for current locale */
|
|
204
|
-
reload: () =>
|
|
209
|
+
reload: () => i(o.value)
|
|
205
210
|
};
|
|
206
211
|
}
|
|
207
212
|
function ae() {
|
|
208
|
-
const { locale: o } = T(), a = window.__SITE_DATA__, t =
|
|
209
|
-
function n(
|
|
210
|
-
o.value =
|
|
213
|
+
const { locale: o } = T(), a = window.__SITE_DATA__, t = f(() => a?.config?.locales || []), e = f(() => a?.config?.defaultLocale || "en"), s = f(() => t.value.length > 1);
|
|
214
|
+
function n(l) {
|
|
215
|
+
o.value = l, localStorage.setItem("x-site-locale", l);
|
|
211
216
|
}
|
|
212
|
-
function
|
|
213
|
-
return typeof
|
|
217
|
+
function i(l) {
|
|
218
|
+
return typeof l == "string" ? l : l[o.value] || l[e.value] || Object.values(l)[0] || "";
|
|
214
219
|
}
|
|
215
220
|
return {
|
|
216
221
|
locale: o,
|
|
@@ -218,7 +223,7 @@ function ae() {
|
|
|
218
223
|
defaultLocale: e,
|
|
219
224
|
hasMultipleLocales: s,
|
|
220
225
|
switchLocale: n,
|
|
221
|
-
resolveText:
|
|
226
|
+
resolveText: i
|
|
222
227
|
};
|
|
223
228
|
}
|
|
224
229
|
const O = {
|
|
@@ -267,32 +272,32 @@ function G(o, a) {
|
|
|
267
272
|
for (const s of ["sm", "md", "lg", "xl"]) {
|
|
268
273
|
const n = e[s];
|
|
269
274
|
if (!n) continue;
|
|
270
|
-
const
|
|
271
|
-
|
|
275
|
+
const i = x(n, a);
|
|
276
|
+
i && t.push(`@media (min-width: ${O[s]}px) { ${i} }`);
|
|
272
277
|
}
|
|
273
278
|
return t.join(`
|
|
274
279
|
`);
|
|
275
280
|
}
|
|
276
281
|
function oe() {
|
|
277
|
-
const o = I(), { previewPage: a, isPreviewMode: t } = C(), e = window.__SITE_DATA__, s = `dl-${Math.random().toString(36).slice(2, 8)}`, n =
|
|
282
|
+
const o = I(), { previewPage: a, isPreviewMode: t } = C(), e = window.__SITE_DATA__, s = `dl-${Math.random().toString(36).slice(2, 8)}`, n = f(() => ["dynamic-layout", s]), i = f(() => {
|
|
278
283
|
if (o.path === "/_preview_")
|
|
279
284
|
return a.value?.layout || "landing";
|
|
280
285
|
if (t.value && a.value?.layout)
|
|
281
286
|
return a.value.layout;
|
|
282
|
-
const
|
|
283
|
-
return (k[
|
|
284
|
-
}),
|
|
285
|
-
const
|
|
286
|
-
if (
|
|
287
|
-
const m =
|
|
287
|
+
const u = o.path === "/" ? "page:home" : `page:${o.params.slug || ""}`;
|
|
288
|
+
return (k[u] || e?.[u])?.layout || "default";
|
|
289
|
+
}), l = f(() => {
|
|
290
|
+
const u = e?.config?.layouts;
|
|
291
|
+
if (u) {
|
|
292
|
+
const m = u[i.value] || u.default;
|
|
288
293
|
if (m?.zones) return m;
|
|
289
294
|
}
|
|
290
|
-
return
|
|
291
|
-
}),
|
|
295
|
+
return i.value === "landing" ? F : z;
|
|
296
|
+
}), r = f(() => G(l.value, `.${s}`));
|
|
292
297
|
return {
|
|
293
|
-
layoutName:
|
|
294
|
-
layoutConfig:
|
|
295
|
-
layoutCSS:
|
|
298
|
+
layoutName: i,
|
|
299
|
+
layoutConfig: l,
|
|
300
|
+
layoutCSS: r,
|
|
296
301
|
layoutClass: n
|
|
297
302
|
};
|
|
298
303
|
}
|
|
@@ -453,39 +458,39 @@ function re(o) {
|
|
|
453
458
|
if (s) return s;
|
|
454
459
|
if (M.test(e.pathname))
|
|
455
460
|
return t.ASSETS.fetch(a);
|
|
456
|
-
const n = U(a, o),
|
|
457
|
-
let
|
|
458
|
-
const
|
|
461
|
+
const n = U(a, o), i = new URL("/index.html", a.url);
|
|
462
|
+
let r = await (await t.ASSETS.fetch(new Request(i))).text();
|
|
463
|
+
const u = o.defaultLocale, [m, g] = await Promise.all([
|
|
459
464
|
t.SITE_CONTENT.get("config"),
|
|
460
465
|
t.SITE_CONTENT.get(`content:${n}`)
|
|
461
466
|
]), b = m ? JSON.parse(m) : {};
|
|
462
467
|
let y = g ? JSON.parse(g) : {};
|
|
463
|
-
if (!g && n !==
|
|
464
|
-
const
|
|
465
|
-
|
|
468
|
+
if (!g && n !== u) {
|
|
469
|
+
const p = await t.SITE_CONTENT.get(`content:${u}`);
|
|
470
|
+
p && (y = JSON.parse(p));
|
|
466
471
|
}
|
|
467
472
|
const h = e.pathname.match(/^\/p\/(.+)$/);
|
|
468
473
|
if (h) {
|
|
469
|
-
const
|
|
470
|
-
if (!y[
|
|
471
|
-
let d = await t.SITE_CONTENT.get(`page:${
|
|
472
|
-
!d && n !==
|
|
474
|
+
const p = h[1];
|
|
475
|
+
if (!y[p]) {
|
|
476
|
+
let d = await t.SITE_CONTENT.get(`page:${p}:${n}`);
|
|
477
|
+
!d && n !== u && (d = await t.SITE_CONTENT.get(`page:${p}:${u}`)), d && (y[p] = JSON.parse(d));
|
|
473
478
|
}
|
|
474
479
|
}
|
|
475
480
|
const w = {
|
|
476
481
|
locale: n,
|
|
477
482
|
config: b
|
|
478
483
|
};
|
|
479
|
-
for (const [
|
|
480
|
-
w[`page:${
|
|
484
|
+
for (const [p, d] of Object.entries(y))
|
|
485
|
+
w[`page:${p}`] = d;
|
|
481
486
|
if (h) {
|
|
482
|
-
const
|
|
483
|
-
d && (
|
|
487
|
+
const p = h[1], d = w[`page:${p}`];
|
|
488
|
+
d && (r = A(r, d, o.siteName));
|
|
484
489
|
}
|
|
485
|
-
e.pathname === "/" && y.home && (
|
|
486
|
-
const
|
|
487
|
-
return
|
|
488
|
-
</head>`), new Response(
|
|
490
|
+
e.pathname === "/" && y.home && (r = A(r, y.home, o.siteName));
|
|
491
|
+
const c = `<script>window.__SITE_DATA__ = ${JSON.stringify(w)};<\/script>`;
|
|
492
|
+
return r = r.replace("</head>", `${c}
|
|
493
|
+
</head>`), new Response(r, {
|
|
489
494
|
headers: {
|
|
490
495
|
"Content-Type": "text/html;charset=utf-8",
|
|
491
496
|
"Cache-Control": "public, max-age=60"
|
package/package.json
CHANGED
|
@@ -16,24 +16,41 @@ export function useSiteComponents() {
|
|
|
16
16
|
const initialLocale = siteData?.locale;
|
|
17
17
|
|
|
18
18
|
const components = ref<Record<string, any>>({ ...((siteData as any)?.components || {}) });
|
|
19
|
+
let lastFetchedLocale: string | undefined = initialLocale;
|
|
20
|
+
let fetchPromise: Promise<void> | null = null;
|
|
19
21
|
|
|
20
22
|
async function fetchComponents(loc: string) {
|
|
21
23
|
// Skip fetching in preview mode — components come via postMessage
|
|
22
24
|
if (isInPreview()) return;
|
|
23
25
|
|
|
26
|
+
// Skip if already fetched/loaded for this locale
|
|
27
|
+
if (loc === lastFetchedLocale) return;
|
|
28
|
+
|
|
24
29
|
// If same as initial locale, use preloaded data
|
|
25
30
|
if (loc === initialLocale) {
|
|
26
31
|
components.value = { ...((siteData as any)?.components || {}) };
|
|
32
|
+
lastFetchedLocale = loc;
|
|
27
33
|
return;
|
|
28
34
|
}
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
35
|
+
|
|
36
|
+
// Deduplicate concurrent fetches
|
|
37
|
+
if (fetchPromise) return;
|
|
38
|
+
|
|
39
|
+
fetchPromise = (async () => {
|
|
40
|
+
try {
|
|
41
|
+
const res = await fetch(`/api/content/components:${loc}`);
|
|
42
|
+
if (res.ok) {
|
|
43
|
+
components.value = await res.json();
|
|
44
|
+
lastFetchedLocale = loc;
|
|
45
|
+
}
|
|
46
|
+
} catch {
|
|
47
|
+
// Keep current
|
|
48
|
+
} finally {
|
|
49
|
+
fetchPromise = null;
|
|
33
50
|
}
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
|
|
51
|
+
})();
|
|
52
|
+
|
|
53
|
+
await fetchPromise;
|
|
37
54
|
}
|
|
38
55
|
|
|
39
56
|
watch(locale, (newLocale) => fetchComponents(newLocale));
|