@uniweb/build 0.74.2 → 0.74.3
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 +6 -6
- package/src/prerender.js +9 -7
- package/src/uwx/site-project.js +15 -1
- package/src/uwx/site.js +15 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@uniweb/build",
|
|
3
|
-
"version": "0.74.
|
|
3
|
+
"version": "0.74.3",
|
|
4
4
|
"description": "Build tooling for the Uniweb Component Web Platform",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -57,15 +57,15 @@
|
|
|
57
57
|
"js-yaml": "^4.1.0",
|
|
58
58
|
"sharp": "^0.35.3",
|
|
59
59
|
"yaml": "^2.5.0",
|
|
60
|
+
"@uniweb/content-reader": "^1.2.8",
|
|
61
|
+
"@uniweb/content-writer": "^0.3.4",
|
|
60
62
|
"@uniweb/schemas": "^0.10.1",
|
|
61
63
|
"@uniweb/projections": "^0.7.11",
|
|
62
|
-
"@uniweb/content-writer": "^0.3.4",
|
|
63
|
-
"@uniweb/content-reader": "^1.2.8",
|
|
64
64
|
"@uniweb/theming": "^0.2.0",
|
|
65
65
|
"@uniweb/semantic-parser": "^1.5.1"
|
|
66
66
|
},
|
|
67
67
|
"optionalDependencies": {
|
|
68
|
-
"@uniweb/runtime": "^0.28.
|
|
68
|
+
"@uniweb/runtime": "^0.28.6"
|
|
69
69
|
},
|
|
70
70
|
"peerDependencies": {
|
|
71
71
|
"vite": "^5.0.0 || ^6.0.0 || ^7.0.0",
|
|
@@ -74,8 +74,8 @@
|
|
|
74
74
|
"@tailwindcss/vite": "^4.0.0",
|
|
75
75
|
"@vitejs/plugin-react": "^4.0.0 || ^5.0.0",
|
|
76
76
|
"vite-plugin-svgr": "^4.0.0",
|
|
77
|
-
"@uniweb/
|
|
78
|
-
"@uniweb/
|
|
77
|
+
"@uniweb/core": "^0.35.1",
|
|
78
|
+
"@uniweb/runtime": "^0.28.6"
|
|
79
79
|
},
|
|
80
80
|
"peerDependenciesMeta": {
|
|
81
81
|
"vite": {
|
package/src/prerender.js
CHANGED
|
@@ -279,10 +279,11 @@ export async function executeAllFetches(siteContent, siteDir, onProgress, locale
|
|
|
279
279
|
*
|
|
280
280
|
* Emitting the canonical route raw sent a reader who asked for `/fr/<container>`
|
|
281
281
|
* to the DEFAULT-locale page — a language switch they never asked for, from a
|
|
282
|
-
* URL that was correct. The
|
|
283
|
-
*
|
|
284
|
-
*
|
|
285
|
-
*
|
|
282
|
+
* URL that was correct. The in-app redirect had the identical bug and was fixed
|
|
283
|
+
* first. ⭐ Since 2026-09-30 that one is `resolveRoute`'s (`@uniweb/core/resolve-route`,
|
|
284
|
+
* `localeUrl`); this is the static twin of its destination — the same prefix and
|
|
285
|
+
* translated slug, with the deployment base this pass writes under — and the two
|
|
286
|
+
* must agree or a container behaves differently on a cold load than in the app.
|
|
286
287
|
*
|
|
287
288
|
* The DECISION to redirect stays canonical (`target !== page.route`) — only the
|
|
288
289
|
* destination is localized. Comparing a localized destination against a
|
|
@@ -1024,9 +1025,10 @@ export async function prerenderSite(siteDir, options = {}) {
|
|
|
1024
1025
|
continue
|
|
1025
1026
|
}
|
|
1026
1027
|
|
|
1027
|
-
// Content-less containers: auto-redirect to first descendant with content
|
|
1028
|
-
//
|
|
1029
|
-
//
|
|
1028
|
+
// Content-less containers: auto-redirect to first descendant with content —
|
|
1029
|
+
// `getNavigableRoute()`, which is `resolveRoute`'s landing rule
|
|
1030
|
+
// (`@uniweb/core/resolve-route`), so the stub goes where the app would.
|
|
1031
|
+
// A stub so the redirect works without JS (via <meta http-equiv="refresh">).
|
|
1030
1032
|
if (!page.hasContent()) {
|
|
1031
1033
|
const target = page.getNavigableRoute()
|
|
1032
1034
|
if (target && target !== page.route) {
|
package/src/uwx/site-project.js
CHANGED
|
@@ -839,7 +839,7 @@ function writePagesTree(pages, pagesDir, sourceLocale, report, ctx, routePrefix
|
|
|
839
839
|
// ⚖️ A pull adds and changes these, and never removes one: a page pushed by a CLI from before carries
|
|
840
840
|
// none, and reading that as "none" would delete what the author wrote.
|
|
841
841
|
function pageSlugToYml(record, canon, existing, sourceLocale, ctx) {
|
|
842
|
-
if (record.is_dynamic) return
|
|
842
|
+
if (record.is_dynamic) return dynamicOwnSlug(record, existing, sourceLocale)
|
|
843
843
|
const targets = localizedTargets(record.slug, sourceLocale)
|
|
844
844
|
const own = isPlainRecord(existing?.slug)
|
|
845
845
|
if (!own && ctx.routes?.siteMap && !record.is_index) {
|
|
@@ -851,6 +851,20 @@ function pageSlugToYml(record, canon, existing, sourceLocale, ctx) {
|
|
|
851
851
|
return own && stableJson(next) === stableJson(existing.slug) ? null : next
|
|
852
852
|
}
|
|
853
853
|
|
|
854
|
+
// A parametric page's folder is named by its param (`pageDirName`), so its OWN slug — where a page
|
|
855
|
+
// made in an app gives it one of its own (`slug: detail`, `param_name: id`) — has no other place on
|
|
856
|
+
// disk. It is kept in `page.yml` as a plain string, which the build never reads for a route (only a
|
|
857
|
+
// per-language map names URL segments) and the push sends back as the page's slug. A string written
|
|
858
|
+
// here before is rewritten to the stored slug, so it is never left stale.
|
|
859
|
+
// ⛔ Until 2026-09-30 a pull dropped it, and the next push sent the param in its place: an authored
|
|
860
|
+
// value lost on a round trip (`uwx-format.md` § THE ROUND-TRIP LAW).
|
|
861
|
+
function dynamicOwnSlug(record, existing, sourceLocale) {
|
|
862
|
+
const own = unwrapLocalized(record.slug, sourceLocale)
|
|
863
|
+
if (typeof own !== 'string' || !own || own === '...path') return null
|
|
864
|
+
if (own !== (record.param_name || own)) return own
|
|
865
|
+
return typeof existing?.slug === 'string' ? own : null
|
|
866
|
+
}
|
|
867
|
+
|
|
854
868
|
// The locales of a pulled localized `slug` other than the source one.
|
|
855
869
|
function localizedTargets(slug, sourceLocale) {
|
|
856
870
|
if (!isPlainRecord(slug)) return {}
|
package/src/uwx/site.js
CHANGED
|
@@ -224,7 +224,15 @@ function localizeRouteSlugs(pages, siteYml, sourceLocale) {
|
|
|
224
224
|
export function buildRouteOf(record, parentRoute, sourceLocale) {
|
|
225
225
|
if (record?.is_index) return parentRoute
|
|
226
226
|
const slug = unwrapLocalized(record?.slug, sourceLocale)
|
|
227
|
-
|
|
227
|
+
// A parametric page's segment is its PARAM — the name the pull gives its folder, `[param_name]`
|
|
228
|
+
// (`site-project.js::pageDirName`), which is the route the build then reads. A page pushed from
|
|
229
|
+
// files has one word for both; a page made in an app may not (`slug: detail`, `param_name: id`).
|
|
230
|
+
// ⛔ Until 2026-09-30 this used the slug, so such a page was addressed `/…/:detail` while its
|
|
231
|
+
// folder built `/…/:id`, and its translated title and description were filed under a route no
|
|
232
|
+
// build reads.
|
|
233
|
+
const segment = record?.is_dynamic
|
|
234
|
+
? (slug === CATCH_ALL_MARKER ? ':path*' : `:${record.param_name || slug}`)
|
|
235
|
+
: slug
|
|
228
236
|
return parentRoute === '/' ? `/${segment}` : `${parentRoute}/${segment}`
|
|
229
237
|
}
|
|
230
238
|
|
|
@@ -783,6 +791,12 @@ async function walkPagesNested(ctx, dirPath, parentSlugPath, inheritedMode, pare
|
|
|
783
791
|
// A page's own localized URL segments, for `localizeRouteSlugs` — under a symbol, so they
|
|
784
792
|
// are never serialized as a field of the record.
|
|
785
793
|
if (!dyn && isPlainRecord(f.config?.slug)) record[AUTHORED_SLUG] = f.config.slug
|
|
794
|
+
// A parametric page's OWN slug, where it is not its param — a page made in an app — is kept in
|
|
795
|
+
// its page.yml by the pull as a plain string (`site-project.js::dynamicOwnSlug`), since its folder
|
|
796
|
+
// is named by its param. The route, the folder and the page's identity stay the param's.
|
|
797
|
+
if (dyn && dyn[1] !== CATCH_ALL_MARKER && typeof f.config?.slug === 'string' && f.config.slug) {
|
|
798
|
+
record.slug = { ...record.slug, [sourceLocale]: f.config.slug }
|
|
799
|
+
}
|
|
786
800
|
|
|
787
801
|
if (mode === 'page') {
|
|
788
802
|
const sections = await collectPageSectionsNested(f.path, siteRoot, f.config)
|