uniweb 1.22.0 → 1.22.2
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/partials/agents.md +8 -5
- package/src/commands/build.js +17 -30
- package/src/framework-index.json +3 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "uniweb",
|
|
3
|
-
"version": "1.22.
|
|
3
|
+
"version": "1.22.2",
|
|
4
4
|
"description": "Create structured Vite + React sites with content/code separation",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -41,15 +41,15 @@
|
|
|
41
41
|
"js-yaml": "^4.3.2",
|
|
42
42
|
"prompts": "^2.4.2",
|
|
43
43
|
"tar": "^7.5.21",
|
|
44
|
-
"@uniweb/schemas": "~1.6.5",
|
|
45
|
-
"@uniweb/content-writer": "~1.3.1",
|
|
46
44
|
"@uniweb/semantic-parser": "~1.13.0",
|
|
47
|
-
"@uniweb/core": "~1.4.12"
|
|
45
|
+
"@uniweb/core": "~1.4.12",
|
|
46
|
+
"@uniweb/content-writer": "~1.3.1",
|
|
47
|
+
"@uniweb/schemas": "~1.6.6"
|
|
48
48
|
},
|
|
49
49
|
"peerDependencies": {
|
|
50
50
|
"@uniweb/semantic-parser": "~1.13.0",
|
|
51
|
-
"@uniweb/
|
|
52
|
-
"@uniweb/
|
|
51
|
+
"@uniweb/build": "~1.11.2",
|
|
52
|
+
"@uniweb/content-reader": "~1.5.7"
|
|
53
53
|
},
|
|
54
54
|
"peerDependenciesMeta": {
|
|
55
55
|
"@uniweb/build": {
|
package/partials/agents.md
CHANGED
|
@@ -546,7 +546,7 @@ Optional attributes: `{size=20}`, `{color=red}`. Custom SVGs: ` on an image or a video; a table takes it on its **caption line**, the paragraph after the table, after a blank line — `: Plans and prices {placement=wide #tbl-plans}`, which also gives the table a caption and a cross-reference id. It is the author's intent, not a size: kit's `<Render>`, `<Prose>` and `<Article>` lay all four out (`data-placement`, styled by `prose-tokens.css`), and any other component ignores it. A section type says which it honours in `meta.js` — `sequence: { label, placement: true }` — and the build warns when a file asks for one its type does not offer.
|
|
552
552
|
|
|
@@ -952,7 +952,7 @@ The body — the value of the schema's content field, `body.content`.
|
|
|
952
952
|
|
|
953
953
|
A path under a folder is relative to `records/`, naming one file or matching many. A record's entry can instead be `{ path, tags, label }` — what the folder says about the record: a component receives them beside it as `$tags` (in the order written) and `$label`, and a query reads them like any key (`where: { $tags: featured }`); such an entry may sit at the top level, where a bare path is refused. A `label` — a record entry's or a folder's — is one text in the site's language, or one per language (`label: { en: Launch video, fr: Vidéo de lancement }`); `$label` is the page's language, else its base language, else the site's. A folder takes `tags:` too. A query reads one folder with `scope: archive` — the folder and everything inside it. A record sits in one folder; if you want a computed subset, that is a query, not a second placement. Structure is for querying, not for navigation — and `folder.yml` never lists a record at the top level (the build refuses it: every file in `records/` is a record already).
|
|
954
954
|
|
|
955
|
-
⚠️ **With a backend, `records/` is what `uniweb push` sends** — every record in it. A site with no `records/` at all leaves the backend's records alone; an *empty* `records/` removes them, and the CLI asks before it does. Records pushed to a backend are served once the site is published.
|
|
955
|
+
⚠️ **With a backend, `records/` is what `uniweb push` sends** — every record in it. A site with no `records/` at all leaves the backend's records alone; an *empty* `records/` removes them, and the CLI asks before it does. Records pushed to a backend are served once the site is published: a record with a data schema reaches the published pages only when `services:` asks for `records: true`, and one with none travels as the published site's files.
|
|
956
956
|
|
|
957
957
|
**`queries.yml` — how content is reached.** A bare map of name → query. A query names a schema and the site's records of that schema are its rows:
|
|
958
958
|
|
|
@@ -2948,8 +2948,9 @@ YAML, not switches — write `true` or `false`. On a site you push or publish it
|
|
|
2948
2948
|
its service, `false` asks it to turn its service off, and an address asks it to leave its own off so
|
|
2949
2949
|
yours answers. **On a site your host publishes, a service is off unless `services:` asks for it** —
|
|
2950
2950
|
list the ones the site uses (the templates list theirs). `records: true` asks for your records to be
|
|
2951
|
-
delivered live to the published pages
|
|
2952
|
-
|
|
2951
|
+
delivered live to the published pages. Turn it on before the first publish of a page that shows
|
|
2952
|
+
records with a data schema: without it those records never reach the published page, and `publish`
|
|
2953
|
+
warns. A static build reads records from files and ignores it. An entry
|
|
2953
2954
|
says everything about its service: a setting you remove from it is removed on the next push, and
|
|
2954
2955
|
removing the entry switches the service off. `uniweb push` and `uniweb publish` send each service
|
|
2955
2956
|
`site.yml` lists; a service the site has that this copy has never seen (turned on in the app since
|
|
@@ -3076,10 +3077,12 @@ These are **body only — no frontmatter**; params and config still come from th
|
|
|
3076
3077
|
|
|
3077
3078
|
**A tagged data block translates by the shape its key declares** in the component's `meta.js` `data:` — a data schema or an inline field map: its text fields, never an enum, a URL or a `translatable: false` field. A key declared `{}` leaves its blocks to a heuristic that offers any string whose field name and value don't look structural, so a `style: display-black` naming one of your component's looks gets translated too. Declare the shape of every block a translator will see — `{ name: 'string', style: { type: 'string', enum: [...] } }`.
|
|
3078
3079
|
|
|
3079
|
-
**An image translates by its alt text.** Words alone give it its alt text in that language and keep its file. A translation that is an image also names the file that language shows: `"2d093636": ""`. Name it with a `/` path, a file in `public
|
|
3080
|
+
**An image translates by its alt text.** Words alone give it its alt text in that language and keep its file. A translation that is an image also names the file that language shows: `"2d093636": ""`. Name it with a `/` path, a file in `public/`, and a build processes it as it does the page's own images; a `./` path has no page's folder to start from, and the build reports it. A caption or a video's `poster` can be given the same way. An image with no alt text has nothing to translate, so give every image one.
|
|
3080
3081
|
|
|
3081
3082
|
**Records translate in the same `extract` run**, into their own manifest at `locales/records/manifest.json` — keyed by the RECORD, so a record translated once is found by every query that returns it. A record whose query has a data schema translates exactly the fields the schema says are text — never an enum, a URL, a date, a number, a file, a reference or a `translatable: false` field — which are the fields a push carries in each language; mark a string that is a code or a key `translatable: false` and no translator is asked for it. An excerpt the build derives is re-derived from each language's body.
|
|
3082
3083
|
|
|
3084
|
+
**A data schema's own labels are not in `locales/`.** The schema's `label`, `plural`, `description` and its sections' and fields' labels are written once, in its `source_locale`; their other languages go in the schema's `i18n`, keyed by path: `i18n: { fr: { model.label: Séance, section.brief.field.title.label: Titre } }`. A section is named by its full path (`contributions/publications`), and a `fields:` schema's one section is `brief`. See `development/data-schemas.md`.
|
|
3085
|
+
|
|
3083
3086
|
**Component side.** Nothing to do: `content.title` arrives in the active language. The one thing a foundation builds is a switcher.
|
|
3084
3087
|
|
|
3085
3088
|
```jsx
|
package/src/commands/build.js
CHANGED
|
@@ -69,10 +69,6 @@ import {
|
|
|
69
69
|
isExtensionPackage,
|
|
70
70
|
detectFoundationType
|
|
71
71
|
} from '@uniweb/build'
|
|
72
|
-
import {
|
|
73
|
-
resolveDefaultLocale,
|
|
74
|
-
normalizeLanguageList
|
|
75
|
-
} from '@uniweb/core/locale-config'
|
|
76
72
|
import { readSiteConfig } from '@uniweb/build/site'
|
|
77
73
|
import { workspacePackages } from '../utils/workspace-packages.js'
|
|
78
74
|
|
|
@@ -424,34 +420,25 @@ async function loadI18nConfig(projectDir, siteConfig = null) {
|
|
|
424
420
|
const localesDir = config.i18n?.localesDir || 'locales'
|
|
425
421
|
const localesPath = join(projectDir, localesDir)
|
|
426
422
|
|
|
427
|
-
//
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
//
|
|
432
|
-
//
|
|
433
|
-
//
|
|
434
|
-
//
|
|
435
|
-
//
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
}
|
|
423
|
+
// The site's locales (undefined/'*' → all available, array → specific), with
|
|
424
|
+
// two filters, by the rule the bundle uses to decide whose files to process
|
|
425
|
+
// (`localesToBuild`):
|
|
426
|
+
// - Publish: build outputs are visitor artifacts. With an explicit
|
|
427
|
+
// `publishLanguages:`, only listed locales get dist/{locale}/ content,
|
|
428
|
+
// per-locale HTML, hreflang, and translated collections. Draft locales
|
|
429
|
+
// stay previewable in dev, which doesn't run this path. Intersecting the
|
|
430
|
+
// DISK-resolved list also covers wildcard (`languages: '*'`) sites.
|
|
431
|
+
// - ⛔ The default locale is the root tree, not `dist/<default>/`. An explicit
|
|
432
|
+
// `languages: [en, fr]` resolves verbatim — default included — so the DECLARED
|
|
433
|
+
// form (the one the contract tells authors to use) minted a duplicate copy of
|
|
434
|
+
// every page, while the wildcard form did not. Dropping it keeps content,
|
|
435
|
+
// per-locale HTML and translated records agreeing on one set.
|
|
436
|
+
const { localesToBuild } = await import('@uniweb/build/i18n')
|
|
437
|
+
const { locales, skipped, defaultLocale } = localesToBuild(config, localesPath)
|
|
438
|
+
if (skipped.length > 0) {
|
|
439
|
+
info(`Skipping non-publishable locale(s): ${skipped.join(', ')} (not in publishLanguages)`)
|
|
445
440
|
}
|
|
446
441
|
|
|
447
|
-
// ⛔ The default locale is the root tree, not `dist/<default>/`. An explicit
|
|
448
|
-
// `languages: [en, fr]` resolves verbatim — default included — so the DECLARED
|
|
449
|
-
// form (the one the contract tells authors to use) minted a duplicate copy of
|
|
450
|
-
// every page, while the wildcard form did not. Dropping it here keeps content,
|
|
451
|
-
// per-locale HTML and translated records agreeing on one set.
|
|
452
|
-
const defaultLocale = resolveDefaultLocale(config)
|
|
453
|
-
locales = locales.filter((l) => l !== defaultLocale)
|
|
454
|
-
|
|
455
442
|
if (locales.length === 0) return null
|
|
456
443
|
|
|
457
444
|
return {
|
package/src/framework-index.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
|
-
"generatedAt": "2026-10-
|
|
3
|
+
"generatedAt": "2026-10-29T14:12:43.968Z",
|
|
4
4
|
"packages": {
|
|
5
5
|
"@uniweb/api": {
|
|
6
6
|
"version": "1.6.5"
|
|
7
7
|
},
|
|
8
8
|
"@uniweb/build": {
|
|
9
|
-
"version": "1.11.
|
|
9
|
+
"version": "1.11.2"
|
|
10
10
|
},
|
|
11
11
|
"@uniweb/content-reader": {
|
|
12
12
|
"version": "1.5.7"
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
"version": "1.0.1"
|
|
43
43
|
},
|
|
44
44
|
"@uniweb/schemas": {
|
|
45
|
-
"version": "1.6.
|
|
45
|
+
"version": "1.6.6"
|
|
46
46
|
},
|
|
47
47
|
"@uniweb/scholar": {
|
|
48
48
|
"version": "1.1.0"
|