@xosen/site-sdk 0.0.5 → 0.0.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xosen/site-sdk",
3
- "version": "0.0.5",
3
+ "version": "0.0.6",
4
4
  "description": "Shared Vue components and composables for Xosen site templates",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -9,10 +9,10 @@
9
9
  <div class="x-nav__links" :class="{ 'x-nav__links--open': menuOpen }">
10
10
  <template v-for="item in navigation" :key="item.url">
11
11
  <a v-if="item.external" :href="item.url" class="x-nav__link" target="_blank" @click="menuOpen = false">
12
- {{ item.text }}
12
+ {{ navText(item) }}
13
13
  </a>
14
14
  <router-link v-else :to="item.url" class="x-nav__link" @click="menuOpen = false">
15
- {{ item.text }}
15
+ {{ navText(item) }}
16
16
  </router-link>
17
17
  </template>
18
18
 
@@ -30,11 +30,19 @@
30
30
 
31
31
  <script setup lang="ts">
32
32
  import { ref, onMounted, onUnmounted } from 'vue';
33
+ import { useI18n } from 'vue-i18n';
33
34
 
35
+ import type { NavItem } from '../../types/config.js';
34
36
  import { useSiteConfig } from '../../composables/useSiteConfig.js';
35
37
  import XLocaleSwitcher from '../common/XLocaleSwitcher.vue';
36
38
 
37
- const { navigation, branding, locales } = useSiteConfig();
39
+ const { locale } = useI18n();
40
+ const { navigation, branding, locales, defaultLocale } = useSiteConfig();
41
+
42
+ function navText(item: NavItem): string {
43
+ if (typeof item.text === 'string') return item.text;
44
+ return item.text[locale.value] || item.text[defaultLocale.value] || Object.values(item.text)[0] || '';
45
+ }
38
46
 
39
47
  const scrolled = ref(false);
40
48
  const menuOpen = ref(false);
@@ -54,10 +54,6 @@ export function useLivePreview() {
54
54
 
55
55
  onMounted(() => {
56
56
  window.addEventListener('message', handleMessage);
57
- // Notify parent that preview is ready
58
- if (isPreviewMode.value) {
59
- window.parent.postMessage({ type: 'xosen-preview-ready' }, '*');
60
- }
61
57
  });
62
58
 
63
59
  onUnmounted(() => {
@@ -9,6 +9,7 @@ export function useSiteConfig() {
9
9
  const siteData = (window as any).__SITE_DATA__ as SiteData | undefined;
10
10
 
11
11
  const config = computed<SiteConfig | null>(() => siteData?.config || null);
12
+ const components = computed<Record<string, any>>(() => (siteData as any)?.components || {});
12
13
 
13
14
  const navigation = computed(() => config.value?.navigation || []);
14
15
  const locales = computed(() => config.value?.locales || []);
@@ -26,6 +27,7 @@ export function useSiteConfig() {
26
27
 
27
28
  return {
28
29
  config,
30
+ components,
29
31
  navigation,
30
32
  locales,
31
33
  defaultLocale,
@@ -26,7 +26,7 @@ export interface SiteConfig {
26
26
  }
27
27
 
28
28
  export interface NavItem {
29
- text: string;
29
+ text: string | Record<string, string>;
30
30
  url: string;
31
31
  external?: boolean;
32
32
  children?: NavItem[];
@@ -17,7 +17,7 @@ function detectLocale(request: Request, config: WorkerConfig): string {
17
17
  return config.defaultLocale;
18
18
  }
19
19
 
20
- function handleContentApi(url: URL, env: WorkerEnv): Promise<Response> | null {
20
+ function handleContentApi(url: URL, env: WorkerEnv, defaultLocale: string): Promise<Response> | null {
21
21
  if (!url.pathname.startsWith('/api/content/')) return null;
22
22
 
23
23
  const key = decodeURIComponent(url.pathname.replace('/api/content/', ''));
@@ -26,7 +26,16 @@ function handleContentApi(url: URL, env: WorkerEnv): Promise<Response> | null {
26
26
  }
27
27
 
28
28
  return (async () => {
29
- const value = await env.SITE_CONTENT.get(key);
29
+ let value = await env.SITE_CONTENT.get(key);
30
+
31
+ // Fallback to default locale
32
+ if (!value) {
33
+ const lastColon = key.lastIndexOf(':');
34
+ if (lastColon > 0 && key.slice(lastColon + 1) !== defaultLocale) {
35
+ value = await env.SITE_CONTENT.get(key.slice(0, lastColon + 1) + defaultLocale);
36
+ }
37
+ }
38
+
30
39
  if (!value) {
31
40
  return Response.json({ error: 'Not found' }, { status: 404 });
32
41
  }
@@ -81,7 +90,7 @@ export function createSiteWorker(config: WorkerConfig): {
81
90
  const url = new URL(request.url);
82
91
 
83
92
  // API route: /api/content/:key
84
- const apiResponse = handleContentApi(url, env);
93
+ const apiResponse = handleContentApi(url, env, config.defaultLocale);
85
94
  if (apiResponse) return apiResponse;
86
95
 
87
96
  // Static assets
@@ -95,6 +104,8 @@ export function createSiteWorker(config: WorkerConfig): {
95
104
  const assetResponse = await env.ASSETS.fetch(new Request(indexUrl));
96
105
  let html = await assetResponse.text();
97
106
 
107
+ const fallbackLocale = config.defaultLocale;
108
+
98
109
  // Read 2 KV keys: config + content for locale
99
110
  const [configRaw, contentRaw] = await Promise.all([
100
111
  env.SITE_CONTENT.get('config'),
@@ -102,7 +113,13 @@ export function createSiteWorker(config: WorkerConfig): {
102
113
  ]);
103
114
 
104
115
  const siteConfig = configRaw ? JSON.parse(configRaw) : {};
105
- const content: Record<string, PageData> = contentRaw ? JSON.parse(contentRaw) : {};
116
+ let content: Record<string, PageData> = contentRaw ? JSON.parse(contentRaw) : {};
117
+
118
+ // Fallback to default locale if no content for requested locale
119
+ if (!contentRaw && locale !== fallbackLocale) {
120
+ const fallbackRaw = await env.SITE_CONTENT.get(`content:${fallbackLocale}`);
121
+ if (fallbackRaw) content = JSON.parse(fallbackRaw);
122
+ }
106
123
 
107
124
  const pageMatch = url.pathname.match(/^\/p\/(.+)$/);
108
125
 
@@ -110,7 +127,11 @@ export function createSiteWorker(config: WorkerConfig): {
110
127
  if (pageMatch) {
111
128
  const slug = pageMatch[1];
112
129
  if (!content[slug]) {
113
- const value = await env.SITE_CONTENT.get(`page:${slug}:${locale}`);
130
+ let value = await env.SITE_CONTENT.get(`page:${slug}:${locale}`);
131
+ // Fallback to default locale
132
+ if (!value && locale !== fallbackLocale) {
133
+ value = await env.SITE_CONTENT.get(`page:${slug}:${fallbackLocale}`);
134
+ }
114
135
  if (value) content[slug] = JSON.parse(value);
115
136
  }
116
137
  }