uniweb 1.7.1 → 1.7.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/partials/agents.md +14 -12
- package/src/commands/i18n.js +13 -2
- package/src/framework-index.json +4 -4
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "uniweb",
|
|
3
|
-
"version": "1.7.
|
|
3
|
+
"version": "1.7.3",
|
|
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.1.0",
|
|
42
42
|
"prompts": "^2.4.2",
|
|
43
43
|
"tar": "^7.0.0",
|
|
44
|
+
"@uniweb/content-writer": "~1.1.2",
|
|
44
45
|
"@uniweb/core": "~1.2.2",
|
|
45
|
-
"@uniweb/
|
|
46
|
-
"@uniweb/
|
|
47
|
-
"@uniweb/content-writer": "~1.1.2"
|
|
46
|
+
"@uniweb/schemas": "~1.3.1",
|
|
47
|
+
"@uniweb/semantic-parser": "~1.8.1"
|
|
48
48
|
},
|
|
49
49
|
"peerDependencies": {
|
|
50
|
-
"@uniweb/
|
|
50
|
+
"@uniweb/build": "~1.3.8",
|
|
51
51
|
"@uniweb/content-reader": "~1.4.0",
|
|
52
|
-
"@uniweb/
|
|
52
|
+
"@uniweb/semantic-parser": "~1.8.1"
|
|
53
53
|
},
|
|
54
54
|
"peerDependenciesMeta": {
|
|
55
55
|
"@uniweb/build": {
|
package/partials/agents.md
CHANGED
|
@@ -2517,16 +2517,17 @@ component that never needed one.
|
|
|
2517
2517
|
### Reading
|
|
2518
2518
|
|
|
2519
2519
|
```jsx
|
|
2520
|
-
const { status, records } = useRecords({ schema: '
|
|
2521
|
-
const { entity } = useEntity({ schema: '
|
|
2520
|
+
const { status, records } = useRecords({ schema: '@/track' }) // summaries: record.brief, no items
|
|
2521
|
+
const { entity } = useEntity({ schema: '@/track', uuid: record.uuid })
|
|
2522
2522
|
const sessions = entity?.hydrated?.items.filter((item) => item.section === 'sessions')
|
|
2523
2523
|
```
|
|
2524
2524
|
|
|
2525
|
-
|
|
2526
|
-
|
|
2527
|
-
`
|
|
2528
|
-
|
|
2529
|
-
|
|
2525
|
+
⭐ **Name your foundation's own types `@/track`**, as `meta.js` and `queries.yml` do. A built
|
|
2526
|
+
foundation sends one in the scope in its name — `@acme/track` for `@acme/marketing`, the name
|
|
2527
|
+
`register` stored it under — and `uniweb dev` sends it as written, which is how your mock's
|
|
2528
|
+
seed names it. Name any other type in full (`@std/person`). Real-backend testing is a job for a
|
|
2529
|
+
built foundation. Outside a Uniweb build nothing knows your scope, so `@/track` is refused
|
|
2530
|
+
before anything is sent (`kind: 'invalid'`).
|
|
2530
2531
|
|
|
2531
2532
|
⛔ **What a member wrote is text.** Render a field as `{record.brief.name}` or `<PlainText text={…} />` — never `<P text>`, `<H1>`–`<H6>` or `SafeHtml`, which render HTML: a member who typed `<img src=x onerror=…>` would run it as whoever views the page. A rich-text field (a ProseMirror document) renders through kit's `Render`, which escapes its text.
|
|
2532
2533
|
|
|
@@ -2546,7 +2547,7 @@ for the first tells a visitor their content is gone when it was never requested.
|
|
|
2546
2547
|
### Writing
|
|
2547
2548
|
|
|
2548
2549
|
```jsx
|
|
2549
|
-
const writer = useEntityWriter({ schema: '
|
|
2550
|
+
const writer = useEntityWriter({ schema: '@/track', uuid: track.uuid })
|
|
2550
2551
|
|
|
2551
2552
|
await writer.create({ title: 'Keynote' }, { section: 'sessions', position: 'last' })
|
|
2552
2553
|
await writer.update(itemId, { ...item.data, room: 'Hall A' }) // whole-data replace
|
|
@@ -2693,7 +2694,7 @@ it, and takes it back. An instructor enrolling students in a course is this; nam
|
|
|
2693
2694
|
your solution does ("enrolled", "course staff"):
|
|
2694
2695
|
|
|
2695
2696
|
```jsx
|
|
2696
|
-
const { status, grants, grant, revoke, working } = useAccess({ schema: '
|
|
2697
|
+
const { status, grants, grant, revoke, working } = useAccess({ schema: '@/course', uuid: course.uuid })
|
|
2697
2698
|
// status 'ready' for whoever administers it; 'forbidden' for everyone else — draw nothing
|
|
2698
2699
|
// grants: [{ account_id, permission, account: { handle, uuid, … }, … }]
|
|
2699
2700
|
await grant({ handle: 'sam' }, 'read') // or an account id: a candidate, a grant's account, an owner_id
|
|
@@ -2717,7 +2718,7 @@ viewer is placed in:
|
|
|
2717
2718
|
|
|
2718
2719
|
```jsx
|
|
2719
2720
|
const { units } = useUnits() // [{ unit, id, handle?, name?, parent?, depth, primary }]
|
|
2720
|
-
await createEntity({ schema: '
|
|
2721
|
+
await createEntity({ schema: '@/submission', unit: course.unit, items: [...] })
|
|
2721
2722
|
```
|
|
2722
2723
|
|
|
2723
2724
|
Landing decides where an entry is, not who may open it.
|
|
@@ -2748,7 +2749,8 @@ server's terminal, its link on your site's root — follow it to try your page.
|
|
|
2748
2749
|
`offers: [{ email, invitations: 1 }]` to try an invitation: mailed to an address no
|
|
2749
2750
|
account holds, or waiting at once for the seeded account whose address it is. A seeded
|
|
2750
2751
|
entity takes `grants: { member: 'read' }`, and `units: [{ handle, parent?, members, floor? }]`
|
|
2751
|
-
gives a create somewhere to land.
|
|
2752
|
+
gives a create somewhere to land. A seed names your own types `@/track`, as `uniweb dev` sends
|
|
2753
|
+
them, and any other in full; it matches a name exactly. State is in memory; restart to reset.
|
|
2752
2754
|
|
|
2753
2755
|
`uniweb create my-event --template conference` is a worked example of all of this.
|
|
2754
2756
|
|
|
@@ -2974,7 +2976,7 @@ uniweb build # merges translations, emits dist/es/, dist/fr/
|
|
|
2974
2976
|
|
|
2975
2977
|
Running `extract` before a build is the usual first mistake — it reads the compiled content, so a stale build yields a stale manifest. After content changes, `uniweb i18n sync` updates the manifest and `init` refreshes the language files; `status` and `audit` report coverage and stale entries.
|
|
2976
2978
|
|
|
2977
|
-
**A value is inline Markdown.** A sentence's links and bold go into its translation — `"Voir [Rôles](page:docs/roles)."` — or it renders without them, and coverage still counts it; `uniweb i18n status` lists these under *Loses markup*. A **button** — a line that is only a link — is the exception: translate its label alone and it keeps its link and options (`{role=primary}`). Buttons on consecutive lines are one string; give one label per line (`"Créer un groupe\nEn savoir plus"`).
|
|
2979
|
+
**A value is inline Markdown.** A sentence's links and bold go into its translation — `"Voir [Rôles](page:docs/roles)."` — or it renders without them, and coverage still counts it; `uniweb i18n status` lists these under *Loses markup*. A **button** — a line that is only a link — is the exception: translate its label alone and it keeps its link and options (`{role=primary}`). Buttons on consecutive lines are one string; give one label per line (`"Créer un groupe\nEn savoir plus"`). The same words are one string wherever they appear: where their places differ — a heading here, a link there — the manifest marks it `markupVaries`, `init` seeds the plain words, and the words alone are what to write: a link or button keeps its own target, and a link written into the value goes to every place the string appears.
|
|
2978
2980
|
|
|
2979
2981
|
**Two mechanisms.** *Hash-based strings* (the default) — `locales/{locale}.json` maps content hash → translation, so structure stays identical across languages. When one source string needs different translations depending on where it appears, the value takes an override form:
|
|
2980
2982
|
|
package/src/commands/i18n.js
CHANGED
|
@@ -384,12 +384,23 @@ async function runExtract(siteRoot, config, args) {
|
|
|
384
384
|
* translation value as inline markdown, so the value channel was lossless the whole
|
|
385
385
|
* time — only the prompt was lossy. Measured 2026-09-18, @uniweb/build 0.44.4.
|
|
386
386
|
*
|
|
387
|
+
* ⭐ Except where the unit's places disagree on markup (`markupVaries`, written by
|
|
388
|
+
* `@uniweb/build`'s extraction): one value serves every place, so such a unit starts
|
|
389
|
+
* with its plain words — which a plain place takes as they are, and a link or a button
|
|
390
|
+
* takes as its label, keeping its own target. ⛔ Until 2026-10-16 it started with the
|
|
391
|
+
* markup of whichever place had some, so an untouched file turned a header's heading
|
|
392
|
+
* into a link. A manifest from an extraction before that has no `markupVaries`, and
|
|
393
|
+
* seeds as it did.
|
|
394
|
+
*
|
|
387
395
|
* ⚠️ This fills MISSING keys only. A locale file already seeded from the flat source
|
|
388
396
|
* is not repaired by re-running; use `uniweb i18n generate <locale> --force` against
|
|
389
397
|
* a freshly extracted manifest to get the markup-bearing source back.
|
|
398
|
+
*
|
|
399
|
+
* @param {{ source: string, markup?: string, markupVaries?: boolean }} unit - a manifest unit
|
|
400
|
+
* @returns {string}
|
|
390
401
|
*/
|
|
391
|
-
function starterValue(unit) {
|
|
392
|
-
return unit.markup || unit.source
|
|
402
|
+
export function starterValue(unit) {
|
|
403
|
+
return unit.markupVaries ? unit.source : unit.markup || unit.source
|
|
393
404
|
}
|
|
394
405
|
|
|
395
406
|
/**
|
package/src/framework-index.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
|
-
"generatedAt": "2026-10-
|
|
3
|
+
"generatedAt": "2026-10-17T14:14:37.779Z",
|
|
4
4
|
"packages": {
|
|
5
5
|
"@uniweb/api": {
|
|
6
|
-
"version": "1.
|
|
6
|
+
"version": "1.4.0"
|
|
7
7
|
},
|
|
8
8
|
"@uniweb/build": {
|
|
9
|
-
"version": "1.3.
|
|
9
|
+
"version": "1.3.8"
|
|
10
10
|
},
|
|
11
11
|
"@uniweb/content-reader": {
|
|
12
12
|
"version": "1.4.0"
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
"version": "1.0.1"
|
|
43
43
|
},
|
|
44
44
|
"@uniweb/schemas": {
|
|
45
|
-
"version": "1.3.
|
|
45
|
+
"version": "1.3.1"
|
|
46
46
|
},
|
|
47
47
|
"@uniweb/scholar": {
|
|
48
48
|
"version": "1.1.0"
|