@uniweb/core 0.29.7 → 0.30.0
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 +1 -1
- package/src/fetch-config.js +1 -1
- package/src/locale-config.js +29 -10
- package/src/route-match.js +1 -1
- package/src/scope.js +1 -1
package/package.json
CHANGED
package/src/fetch-config.js
CHANGED
|
@@ -684,7 +684,7 @@ function bindWhere(where, variables) {
|
|
|
684
684
|
/**
|
|
685
685
|
* ⭐ `scope:` IS ITS OWN FIELD, on both lanes. The service takes it natively; on
|
|
686
686
|
* the compiled file the evaluators apply it to each record's placement (`path`,
|
|
687
|
-
* the folder `records.yml` put it in) — `@uniweb/core`'s `applyScope`, the one the
|
|
687
|
+
* the folder `records/folder.yml` put it in) — `@uniweb/core`'s `applyScope`, the one the
|
|
688
688
|
* build uses too. ⛔ Until 2026-09-11 it was folded here into
|
|
689
689
|
* `where: { path: { under } }`, an authored form that is now retired in its
|
|
690
690
|
* favour [Diego]: a branch is a scope, and `where` stays the author's predicate.
|
package/src/locale-config.js
CHANGED
|
@@ -17,9 +17,9 @@
|
|
|
17
17
|
|
|
18
18
|
/**
|
|
19
19
|
* Extract a locale code from a declared-language entry. The contract is
|
|
20
|
-
* strings-only; legacy `{ code, label }` objects are tolerated on
|
|
21
|
-
*
|
|
22
|
-
*
|
|
20
|
+
* strings-only; legacy `{ code, label }` objects are tolerated on READ — a
|
|
21
|
+
* payload built from an older config still renders — and refused where a site
|
|
22
|
+
* is built or pushed (`validateLanguageConfig`). The `'*'` wildcard marker
|
|
23
23
|
* (auto-discover from `locales/`) is not a locale code.
|
|
24
24
|
*
|
|
25
25
|
* @param {*} entry - Declared-language entry.
|
|
@@ -101,10 +101,22 @@ export const LOCALE_DISPLAY_NAMES = {
|
|
|
101
101
|
*/
|
|
102
102
|
export function localeLabel(entry) {
|
|
103
103
|
if (typeof entry === 'string') {
|
|
104
|
-
return LOCALE_DISPLAY_NAMES[entry] || entry.toUpperCase()
|
|
104
|
+
return LOCALE_DISPLAY_NAMES[entry] || nativeName(entry) || entry.toUpperCase()
|
|
105
105
|
}
|
|
106
106
|
if (!entry || typeof entry.code !== 'string' || !entry.code) return ''
|
|
107
|
-
return entry.label || LOCALE_DISPLAY_NAMES[entry.code] || entry.code.toUpperCase()
|
|
107
|
+
return entry.label || LOCALE_DISPLAY_NAMES[entry.code] || nativeName(entry.code) || entry.code.toUpperCase()
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// A language's name in itself (`sv` → `Svenska`, `pt-BR` → `Português (Brasil)`), where the
|
|
111
|
+
// platform knows it — so a code the table above does not list still has a name, and a site
|
|
112
|
+
// never needs to write one. Null when it does not know the code.
|
|
113
|
+
function nativeName(code) {
|
|
114
|
+
try {
|
|
115
|
+
const name = new Intl.DisplayNames([code], { type: 'language' }).of(code)
|
|
116
|
+
return name && name !== code ? name.charAt(0).toLocaleUpperCase(code) + name.slice(1) : null
|
|
117
|
+
} catch {
|
|
118
|
+
return null
|
|
119
|
+
}
|
|
108
120
|
}
|
|
109
121
|
|
|
110
122
|
export function isWildcardLanguages(value) {
|
|
@@ -189,9 +201,12 @@ export function resolvePublishableLocales(config = {}) {
|
|
|
189
201
|
* - `default-not-publishable` — the effective default is excluded from the
|
|
190
202
|
* publishable set.
|
|
191
203
|
*
|
|
204
|
+
* - `object-language-entry` — a `{ code, label }` entry: languages are named by
|
|
205
|
+
* their code (`localeLabel` gives the name). Read tolerantly, never built or pushed.
|
|
206
|
+
*
|
|
192
207
|
* Warnings:
|
|
193
|
-
* - `invalid-language-entry` / `invalid-publish-language-entry` —
|
|
194
|
-
*
|
|
208
|
+
* - `invalid-language-entry` / `invalid-publish-language-entry` — entries that
|
|
209
|
+
* name no code (dropped by normalization).
|
|
195
210
|
* - `duplicate-language` — repeated codes (deduped).
|
|
196
211
|
* - `dangling-publish-language` — listed but not declared (ignored at
|
|
197
212
|
* publish, preserved in the file/wire).
|
|
@@ -225,10 +240,14 @@ export function validateLanguageConfig(config = {}) {
|
|
|
225
240
|
})
|
|
226
241
|
continue
|
|
227
242
|
}
|
|
243
|
+
// ⛔ An object names a language by `code` and gives it a `label` — a label no sync can
|
|
244
|
+
// carry (a backend's list is of codes), so a site that pushed it lost it, and the push
|
|
245
|
+
// itself was refused (measured 2026-09-26). A language's name comes from its code
|
|
246
|
+
// (`localeLabel`), in every lane alike.
|
|
228
247
|
if (typeof entry !== 'string') {
|
|
229
|
-
|
|
230
|
-
code:
|
|
231
|
-
message: `${field} entry for '${code}'
|
|
248
|
+
errors.push({
|
|
249
|
+
code: 'object-language-entry',
|
|
250
|
+
message: `${field} entry for '${code}' is an object — write the plain string '${code}' (a language's name comes from its code)`
|
|
232
251
|
})
|
|
233
252
|
}
|
|
234
253
|
if (seen.has(code)) {
|
package/src/route-match.js
CHANGED
|
@@ -539,7 +539,7 @@ export function fillRoutePattern(pattern, values) {
|
|
|
539
539
|
// A catch-all is filled from the record's placement and handle — the split
|
|
540
540
|
// rule in reverse (`joinPathCapture`) — with each SEGMENT encoded and the
|
|
541
541
|
// slashes between them kept as structure. `dir` is the placement; a record
|
|
542
|
-
// carries it as `path` (the folder `records.yml` put it in), which is why
|
|
542
|
+
// carries it as `path` (the folder `records/folder.yml` put it in), which is why
|
|
543
543
|
// `path` here is read as the DIRECTORY and never as a composed capture.
|
|
544
544
|
const handle = recordHandle(values)
|
|
545
545
|
if (joinPathCapture({ dir: values.dir ?? values.path, slug: handle }) === null) return null
|
package/src/scope.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* A query's `scope:` — the folder branch it reads — evaluated over records that
|
|
3
3
|
* carry their placement.
|
|
4
4
|
*
|
|
5
|
-
* A record's `path` is the folder `records.yml` placed it in (`build/src/site/
|
|
5
|
+
* A record's `path` is the folder `records/folder.yml` placed it in (`build/src/site/
|
|
6
6
|
* query-processor.js`). A scope contains that folder and every folder below it, at
|
|
7
7
|
* SEGMENT boundaries: `field` holds `field` and `field/2025`, never `fieldwork`.
|
|
8
8
|
* The root (`''`) holds everything.
|