@uniweb/build 0.6.2 → 0.6.4

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": "@uniweb/build",
3
- "version": "0.6.2",
3
+ "version": "0.6.4",
4
4
  "description": "Build tooling for the Uniweb Component Web Platform",
5
5
  "type": "module",
6
6
  "exports": {
@@ -50,8 +50,8 @@
50
50
  "sharp": "^0.33.2"
51
51
  },
52
52
  "optionalDependencies": {
53
- "@uniweb/runtime": "0.5.13",
54
53
  "@uniweb/schemas": "0.2.1",
54
+ "@uniweb/runtime": "0.5.13",
55
55
  "@uniweb/content-reader": "1.1.2"
56
56
  },
57
57
  "peerDependencies": {
@@ -61,7 +61,7 @@
61
61
  "@tailwindcss/vite": "^4.0.0",
62
62
  "@vitejs/plugin-react": "^4.0.0 || ^5.0.0",
63
63
  "vite-plugin-svgr": "^4.0.0",
64
- "@uniweb/core": "0.4.1"
64
+ "@uniweb/core": "0.4.2"
65
65
  },
66
66
  "peerDependenciesMeta": {
67
67
  "vite": {
package/src/prerender.js CHANGED
@@ -26,19 +26,41 @@ let preparePropsSSR, getComponentMetaSSR
26
26
  * @param {Object} siteContent - The site content from site-content.json
27
27
  * @param {string} siteDir - Path to the site directory
28
28
  * @param {function} onProgress - Progress callback
29
+ * @param {Object} [localeInfo] - Locale info for collection data localization
30
+ * @param {string} [localeInfo.locale] - Active locale code
31
+ * @param {string} [localeInfo.defaultLocale] - Default locale code
32
+ * @param {string} [localeInfo.distDir] - Path to dist directory (where locale-specific data lives)
29
33
  * @returns {Object} { pageFetchedData, fetchedData } - Fetched data for dynamic route expansion and DataStore pre-population
30
34
  */
31
- async function executeAllFetches(siteContent, siteDir, onProgress) {
35
+ async function executeAllFetches(siteContent, siteDir, onProgress, localeInfo) {
32
36
  const fetchOptions = { siteRoot: siteDir, publicDir: 'public' }
33
37
  const fetchedData = [] // Collected for DataStore pre-population
34
38
 
39
+ // For non-default locales, translated collection data lives in dist/{locale}/data/
40
+ // instead of public/data/. Create a localized fetch helper.
41
+ const isNonDefaultLocale = localeInfo &&
42
+ localeInfo.locale !== localeInfo.defaultLocale &&
43
+ localeInfo.distDir
44
+
45
+ function localizeFetch(config) {
46
+ if (!isNonDefaultLocale || !config.path?.startsWith('/data/')) return config
47
+ return { ...config, path: `/${localeInfo.locale}${config.path}` }
48
+ }
49
+
50
+ // Fetch options pointing to dist/ for localized data
51
+ const localizedFetchOptions = isNonDefaultLocale
52
+ ? { siteRoot: localeInfo.distDir, publicDir: '.' }
53
+ : fetchOptions
54
+
35
55
  // 1. Site-level fetch
36
56
  const siteFetch = siteContent.config?.fetch
37
57
  if (siteFetch && siteFetch.prerender !== false) {
38
- onProgress(` Fetching site data: ${siteFetch.path || siteFetch.url}`)
39
- const result = await executeFetch(siteFetch, fetchOptions)
58
+ const cfg = localizeFetch(siteFetch)
59
+ const opts = cfg !== siteFetch ? localizedFetchOptions : fetchOptions
60
+ onProgress(` Fetching site data: ${cfg.path || cfg.url}`)
61
+ const result = await executeFetch(cfg, opts)
40
62
  if (result.data && !result.error) {
41
- fetchedData.push({ config: siteFetch, data: result.data })
63
+ fetchedData.push({ config: cfg, data: result.data })
42
64
  }
43
65
  }
44
66
 
@@ -49,10 +71,12 @@ async function executeAllFetches(siteContent, siteDir, onProgress) {
49
71
  // Page-level fetch
50
72
  const pageFetch = page.fetch
51
73
  if (pageFetch && pageFetch.prerender !== false) {
52
- onProgress(` Fetching page data for ${page.route}: ${pageFetch.path || pageFetch.url}`)
53
- const result = await executeFetch(pageFetch, fetchOptions)
74
+ const cfg = localizeFetch(pageFetch)
75
+ const opts = cfg !== pageFetch ? localizedFetchOptions : fetchOptions
76
+ onProgress(` Fetching page data for ${page.route}: ${cfg.path || cfg.url}`)
77
+ const result = await executeFetch(cfg, opts)
54
78
  if (result.data && !result.error) {
55
- fetchedData.push({ config: pageFetch, data: result.data })
79
+ fetchedData.push({ config: cfg, data: result.data })
56
80
  // Store for dynamic route expansion
57
81
  pageFetchedData.set(page.route, {
58
82
  schema: pageFetch.schema,
@@ -92,7 +116,8 @@ function expandDynamicPages(pages, pageFetchedData, onProgress) {
92
116
  const { paramName, parentSchema } = page
93
117
 
94
118
  if (!parentSchema) {
95
- onProgress(` Warning: Dynamic page ${page.route} has no parentSchema, skipping`)
119
+ onProgress(` Warning: Dynamic page ${page.route} has no parentSchema, keeping as template for runtime`)
120
+ expandedPages.push(page)
96
121
  continue
97
122
  }
98
123
 
@@ -102,7 +127,10 @@ function expandDynamicPages(pages, pageFetchedData, onProgress) {
102
127
  const parentData = pageFetchedData.get(parentRoute)
103
128
 
104
129
  if (!parentData || !Array.isArray(parentData.data)) {
105
- onProgress(` Warning: No data found for dynamic page ${page.route} (parent: ${parentRoute})`)
130
+ // No build-time data available (e.g., prerender: false on parent fetch).
131
+ // Keep the dynamic template so the runtime can match it client-side.
132
+ onProgress(` Keeping dynamic template ${page.route} for runtime (no build-time data)`)
133
+ expandedPages.push(page)
106
134
  continue
107
135
  }
108
136
 
@@ -652,8 +680,13 @@ export async function prerenderSite(siteDir, options = {}) {
652
680
  siteContent.config.activeLocale = locale
653
681
 
654
682
  // Execute data fetches (site, page, section levels)
683
+ // For non-default locales, collection data is read from dist/{locale}/data/
655
684
  onProgress('Executing data fetches...')
656
- const { pageFetchedData, fetchedData } = await executeAllFetches(siteContent, siteDir, onProgress)
685
+ const defaultLocale = defaultSiteContent.config?.defaultLanguage || 'en'
686
+ const { pageFetchedData, fetchedData } = await executeAllFetches(
687
+ siteContent, siteDir, onProgress,
688
+ { locale, defaultLocale, distDir }
689
+ )
657
690
 
658
691
  // Store fetchedData on siteContent for runtime DataStore pre-population
659
692
  siteContent.fetchedData = fetchedData
@@ -700,6 +733,10 @@ export async function prerenderSite(siteDir, options = {}) {
700
733
  const website = uniweb.activeWebsite
701
734
 
702
735
  for (const page of pages) {
736
+ // Skip dynamic template pages — they exist in the content for runtime
737
+ // route matching but can't be pre-rendered (no concrete route)
738
+ if (page.route.includes(':')) continue
739
+
703
740
  // Build the output route with locale prefix
704
741
  // For non-default locales, translate route slugs (e.g., /about → /acerca-de)
705
742
  const translatedPageRoute = isDefault ? page.route : website.translateRoute(page.route, locale)
@@ -17,7 +17,7 @@
17
17
  * // site.yml
18
18
  * collections:
19
19
  * articles:
20
- * path: library/articles
20
+ * path: collections/articles
21
21
  * sort: date desc
22
22
  *
23
23
  * // Usage
@@ -59,11 +59,11 @@ try {
59
59
  *
60
60
  * @example
61
61
  * // Simple form
62
- * parseCollectionConfig('articles', 'library/articles')
62
+ * parseCollectionConfig('articles', 'collections/articles')
63
63
  *
64
64
  * // Extended form
65
65
  * parseCollectionConfig('articles', {
66
- * path: 'library/articles',
66
+ * path: 'collections/articles',
67
67
  * route: '/blog',
68
68
  * sort: 'date desc',
69
69
  * filter: 'published != false',
@@ -213,7 +213,7 @@ function isExternalUrl(src) {
213
213
  /**
214
214
  * Process assets in collection content
215
215
  * - Resolves relative paths to site-root-relative paths
216
- * - Copies co-located assets to public/library/<collection>/
216
+ * - Copies co-located assets to public/collections/<collection>/
217
217
  * - Updates paths in the content in place
218
218
  *
219
219
  * @param {Object} content - ProseMirror document
@@ -226,7 +226,7 @@ async function processCollectionAssets(content, itemPath, siteRoot, collectionNa
226
226
  const assets = {}
227
227
  const itemDir = dirname(itemPath)
228
228
  const publicDir = join(siteRoot, 'public')
229
- const targetDir = join(publicDir, 'library', collectionName)
229
+ const targetDir = join(publicDir, 'collections', collectionName)
230
230
 
231
231
  // Walk content and collect asset paths
232
232
  const assetNodes = []
@@ -248,7 +248,7 @@ async function processCollectionAssets(content, itemPath, siteRoot, collectionNa
248
248
  if (src.startsWith('./') || src.startsWith('../')) {
249
249
  // Check if file exists at resolved location
250
250
  if (existsSync(result.resolved)) {
251
- // Copy to public/library/<collection>/
251
+ // Copy to public/collections/<collection>/
252
252
  const assetFilename = basename(result.resolved)
253
253
  const targetPath = join(targetDir, assetFilename)
254
254
 
@@ -259,7 +259,7 @@ async function processCollectionAssets(content, itemPath, siteRoot, collectionNa
259
259
  await copyFile(result.resolved, targetPath)
260
260
 
261
261
  // Update path to site-root-relative
262
- finalPath = `/library/${collectionName}/${assetFilename}`
262
+ finalPath = `/collections/${collectionName}/${assetFilename}`
263
263
 
264
264
  assets[src] = {
265
265
  original: src,
@@ -294,7 +294,7 @@ async function processCollectionAssets(content, itemPath, siteRoot, collectionNa
294
294
  const posterTarget = join(targetDir, posterFilename)
295
295
  await mkdir(targetDir, { recursive: true })
296
296
  await copyFile(posterResult.resolved, posterTarget)
297
- node.attrs.poster = `/library/${collectionName}/${posterFilename}`
297
+ node.attrs.poster = `/collections/${collectionName}/${posterFilename}`
298
298
  }
299
299
  }
300
300
 
@@ -305,7 +305,7 @@ async function processCollectionAssets(content, itemPath, siteRoot, collectionNa
305
305
  const previewTarget = join(targetDir, previewFilename)
306
306
  await mkdir(targetDir, { recursive: true })
307
307
  await copyFile(previewResult.resolved, previewTarget)
308
- node.attrs.preview = `/library/${collectionName}/${previewFilename}`
308
+ node.attrs.preview = `/collections/${collectionName}/${previewFilename}`
309
309
  }
310
310
  }
311
311
  }
@@ -491,8 +491,8 @@ async function collectItems(siteDir, config) {
491
491
  *
492
492
  * @example
493
493
  * const collections = await processCollections('/path/to/site', {
494
- * articles: { path: 'library/articles', sort: 'date desc' },
495
- * products: 'library/products'
494
+ * articles: { path: 'collections/articles', sort: 'date desc' },
495
+ * products: 'collections/products'
496
496
  * })
497
497
  * // { articles: [...], products: [...] }
498
498
  */