@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 +3 -3
- package/src/prerender.js +47 -10
- package/src/site/collection-processor.js +11 -11
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@uniweb/build",
|
|
3
|
-
"version": "0.6.
|
|
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.
|
|
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
|
-
|
|
39
|
-
const
|
|
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:
|
|
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
|
-
|
|
53
|
-
const
|
|
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:
|
|
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,
|
|
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
|
-
|
|
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
|
|
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:
|
|
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', '
|
|
62
|
+
* parseCollectionConfig('articles', 'collections/articles')
|
|
63
63
|
*
|
|
64
64
|
* // Extended form
|
|
65
65
|
* parseCollectionConfig('articles', {
|
|
66
|
-
* path: '
|
|
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/
|
|
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, '
|
|
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/
|
|
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 = `/
|
|
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 = `/
|
|
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 = `/
|
|
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: '
|
|
495
|
-
* products: '
|
|
494
|
+
* articles: { path: 'collections/articles', sort: 'date desc' },
|
|
495
|
+
* products: 'collections/products'
|
|
496
496
|
* })
|
|
497
497
|
* // { articles: [...], products: [...] }
|
|
498
498
|
*/
|