uniweb 1.14.2 → 1.15.1
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 +7 -7
- package/partials/agents.md +8 -4
- package/src/commands/i18n.js +9 -4
- package/src/framework-index.json +12 -12
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "uniweb",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.15.1",
|
|
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/
|
|
45
|
-
"@uniweb/
|
|
46
|
-
"@uniweb/
|
|
47
|
-
"@uniweb/
|
|
44
|
+
"@uniweb/core": "~1.4.0",
|
|
45
|
+
"@uniweb/semantic-parser": "~1.12.2",
|
|
46
|
+
"@uniweb/schemas": "~1.6.0",
|
|
47
|
+
"@uniweb/content-writer": "~1.3.0"
|
|
48
48
|
},
|
|
49
49
|
"peerDependencies": {
|
|
50
|
-
"@uniweb/
|
|
50
|
+
"@uniweb/build": "~1.7.1",
|
|
51
51
|
"@uniweb/semantic-parser": "~1.12.2",
|
|
52
|
-
"@uniweb/
|
|
52
|
+
"@uniweb/content-reader": "~1.5.4"
|
|
53
53
|
},
|
|
54
54
|
"peerDependenciesMeta": {
|
|
55
55
|
"@uniweb/build": {
|
package/partials/agents.md
CHANGED
|
@@ -309,7 +309,7 @@ Paths are relative to the site package you identified in step 1 — `site/` in t
|
|
|
309
309
|
|
|
310
310
|
**Change the brand color.** `<site>/theme.yml` → `colors.primary`. One line, and every component follows. Do **not** edit Tailwind color classes in components to change brand color — that is the exact anti-pattern this system removes.
|
|
311
311
|
|
|
312
|
-
**Change how code blocks look.** `<site>/theme.yml` → `code:`. Name one of Shiki's 65 bundled themes (`code: dracula`), name one per scheme (`code: { light: github-light, dark: github-dark }`), or take a theme and adjust it (`code: { theme: github-dark, background: '#0D0D0D' }`). Hand-picking every syntax colour is possible and is the last thing to reach for.
|
|
312
|
+
**Change how code blocks look.** `<site>/theme.yml` → `code:`. Name one of Shiki's 65 bundled themes (`code: dracula`), name one per scheme (`code: { light: github-light, dark: github-dark }`), or take a theme and adjust it (`code: { theme: github-dark, background: '#0D0D0D' }`). Hand-picking every syntax colour is possible and is the last thing to reach for. A block paints its theme's background and text colour before the highlighter loads when they are known — the default theme's, or the `background` and `foreground` the site declares — so declare both beside a named theme to paint them from the start.
|
|
313
313
|
|
|
314
314
|
**Change a nav item.** First check how nav is produced. If `<site>/layout/header.md` lists the links (a markdown list, or a `yaml:nav` block), edit it there. If it doesn't, the Header is generating nav from the page hierarchy — change page titles and order in `site.yml` / `page.yml` instead.
|
|
315
315
|
|
|
@@ -1064,7 +1064,7 @@ function MyComponent({ content, params, block }) {
|
|
|
1064
1064
|
|---|---|---|
|
|
1065
1065
|
| `type`, `id`, `hidden` | the section itself — its section type, its id, and a draft (`hidden: true`: left out of a published build, kept by `uniweb dev`) | — |
|
|
1066
1066
|
| `query`, `fetch` | the section's data | `content.data`, under the keys its `meta.js` `data:` declares |
|
|
1067
|
-
| `theme`, `background`, `grid`, `vars` | the section's settings, which framework applies — the color context and the background around your component, the section's theme and your component's CSS variables in the page stylesheet, the child layout | `block`, when the component needs one for its own logic: `useColorContext(block)` for the context (a light vs. dark logo, say), `<SectionBackground block={block} />` to draw the background itself, `<ChildGrid from={block} />` for the grid |
|
|
1067
|
+
| `theme`, `background`, `grid`, `vars`, `sticky` | the section's settings, which framework applies — the color context and the background around your component, the section's theme and your component's CSS variables in the page stylesheet, the child layout, and whether the section stays in view as the page scrolls | `block`, when the component needs one for its own logic: `useColorContext(block)` for the context (a light vs. dark logo, say), `<SectionBackground block={block} />` to draw the background itself, `<ChildGrid from={block} />` for the grid, `block.sticky` for whether it sticks |
|
|
1068
1068
|
| `props` | params written as one map | `params` — its keys are merged in, one by one |
|
|
1069
1069
|
| `data`, `preset`, `input` | nothing: `data:` is refused (it was `query:`'s old name); `preset:` and `input:` are ignored with a warning | — |
|
|
1070
1070
|
|
|
@@ -1137,7 +1137,7 @@ Four things you won't discover by reading exports:
|
|
|
1137
1137
|
|
|
1138
1138
|
> **Kit hooks are SSR-safe by design.** If you hit "document is not defined" during a build, don't add `typeof document` guards — reach for the hook instead (`useAppearance()` for scheme, `useScrolled()` for scroll position).
|
|
1139
1139
|
|
|
1140
|
-
> **A modal needs `<Overlay>`, not a bigger z-index.** The runtime gives each layout area its own `view-transition-name` so header, rails and body animate independently
|
|
1140
|
+
> **A modal needs `<Overlay>`, not a bigger z-index.** The runtime gives each layout area its own `view-transition-name` so header, rails and body animate independently, and that makes each area a stacking context: a `fixed` dialog inside one is still placed against the viewport, but whatever z-index it carries, it paints at its area's place in the stack. Areas sit above the body, so a dialog opened from a section paints *under* the header and footer, and one opened from your Header paints under a footer or sidebar on the header's layer that comes after it. Raising the number looks like it should work and never does. `<Overlay onClose={close}>…</Overlay>` renders into `document.body`, where the z-index means what you expect.
|
|
1141
1141
|
>
|
|
1142
1142
|
> It also does the part that is easy to skip: a modal overlay **contains focus** — moves focus in, cycles Tab within, marks the rest of the page `inert`, and returns focus to whatever opened it. That is what makes the `role="dialog" aria-modal="true"` on your box true rather than merely asserted; without it a keyboard user Tabs straight out into a page a screen-reader user has been told is unreachable. Plus Escape, the scrim click, the scroll lock, and a dimmed scrim you override with `className` (`bg-transparent` removes it). `modal={false}` for a toast: it escapes the stacking context and nothing else, so the page stays usable. Your dialog's markup stays yours.
|
|
1143
1143
|
|
|
@@ -1173,6 +1173,8 @@ Header.className = 'p-0'
|
|
|
1173
1173
|
Header.as = 'header'
|
|
1174
1174
|
```
|
|
1175
1175
|
|
|
1176
|
+
**A header that stays in view is a setting, not a class.** `sticky top-0` on your component's markup does nothing: a sticky element moves only within its parent, and the section's wrapper and the area's are as tall as your header. Declare `sticky: true` in the type's `meta.js` — an author turns it off with `sticky: false` — and the runtime makes sticky the box that can stay in view. A section in the body sticks the same way and stays below the stuck header by itself: the runtime measures how far the header reaches and publishes it as `--uw-sticky-top` (a type's `top` overrides it). A child section in kit's `<ChildGrid>` stays in view beside the column it sits next to, and on a phone, at one column, scrolls with the page. A sticky section inside a box with `overflow: hidden` cannot stick — clip with `overflow: clip`. A layout of your own that wraps an area in an element makes that element sticky when `page.isSticky('header')`. `uniweb dev` names a sticky element that cannot move in the console.
|
|
1177
|
+
|
|
1176
1178
|
### meta.js
|
|
1177
1179
|
|
|
1178
1180
|
```javascript
|
|
@@ -1781,7 +1783,7 @@ Layouts are full components with their own `params` in `meta.js`, not just struc
|
|
|
1781
1783
|
|
|
1782
1784
|
**Layout `meta.js`** declares areas and optional scroll behavior: `{ areas: ['header', 'footer', 'left'], scroll: 'self' }`. Area names are arbitrary. `areas` tells an editor what to offer; a page renders the areas its site's `layout/` folder fills. `scroll` controls scroll restoration: unset = runtime manages `window` (default), `'self'` = the layout scrolls itself, or a CSS selector (`'main'`) = runtime manages that element.
|
|
1783
1785
|
|
|
1784
|
-
Two optional keys tune how areas behave across a navigation. `transitions` renames or opts regions out of per-area view transitions (`{ left: null }`, or `false` for the whole layout). `layers` sets which area paints on top — every area is stacked above the body by default, so a fixed header works without declaring anything,
|
|
1786
|
+
Two optional keys tune how areas behave across a navigation. `transitions` renames or opts regions out of per-area view transitions (`{ left: null }`, or `false` for the whole layout). `layers` sets which area paints on top — every area is stacked above the body by default, so a fixed header works without declaring anything, and a sticky area (one with a `sticky` section) above every area that does not stick, since the page scrolls under it. Otherwise areas are equal to each other, so a layout whose chrome overlaps says which wins: `layers: { header: 2, left: 1 }`, which also ranks a sticky area it names. Both take an object to override per region, or `false` to opt out. **A `z-index` inside an area cannot lift it past another area** — each area is its own stacking context — so reach for `layers` rather than a bigger number, and for `<Overlay>` when a modal needs to escape the area entirely.
|
|
1785
1787
|
|
|
1786
1788
|
**Layout content** lives in `site/layout/` — `header.md`, `footer.md` for the default layout, or a named subdirectory (`site/layout/marketing/`) for named layouts. Named subdirectories are self-contained — no inheritance. Cascade: `page.yml` → `folder.yml` → `site.yml` → foundation `defaultLayout` → `"default"`. The structure alone decides what an entry is: every folder directly under `layout/` is a named layout (its name matched regardless of case and of a trailing `Layout` — `site/layout/docs/` serves the foundation's `DocsLayout`), and an area with several sections is a folder inside a layout's folder — `site/layout/default/header/1-topbar.md` for the default layout. An area has no `page.yml`; its sections render in filename order.
|
|
1787
1789
|
|
|
@@ -3080,6 +3082,8 @@ Most Uniweb failures are **silent** — the build succeeds and the page is wrong
|
|
|
3080
3082
|
|
|
3081
3083
|
**A var in frontmatter does nothing** — component vars only apply when declared in that section type's `meta.js` `vars:`. Unknown names are ignored silently.
|
|
3082
3084
|
|
|
3085
|
+
**A sticky header scrolls away** — it is `sticky top-0` on the component's own markup, which has no room to move. Make the section sticky instead: `sticky: true` in its type's `meta.js`. A sticky section that still scrolls away sits in a box with `overflow: hidden` — clip with `overflow: clip`. `uniweb dev` names the element in the console.
|
|
3086
|
+
|
|
3083
3087
|
Loud failures:
|
|
3084
3088
|
|
|
3085
3089
|
**"Could not load foundation"** — check that the site's `package.json` depends on the foundation *by its workspace package name*. For the default layout that's `"src": "file:../src"`; for a co-located project (`docs/src` + `docs/site`) it's `"docs-src": "file:../src"`. The key must match the foundation's `package.json::name`, not the folder it happens to sit in.
|
package/src/commands/i18n.js
CHANGED
|
@@ -211,10 +211,10 @@ async function findSiteRoot(target) {
|
|
|
211
211
|
/**
|
|
212
212
|
* Load site configuration
|
|
213
213
|
*
|
|
214
|
-
* Resolves locales from config:
|
|
214
|
+
* Resolves the locales to translate into from config — every language but the default:
|
|
215
215
|
* - undefined → all available locales (from locales/*.json)
|
|
216
216
|
* - '*' → explicitly all available locales
|
|
217
|
-
* - ['es', 'fr'] →
|
|
217
|
+
* - ['en', 'es', 'fr'] → those languages
|
|
218
218
|
*/
|
|
219
219
|
async function loadSiteConfig(siteRoot) {
|
|
220
220
|
const configPath = join(siteRoot, 'site.yml')
|
|
@@ -226,10 +226,15 @@ async function loadSiteConfig(siteRoot) {
|
|
|
226
226
|
|
|
227
227
|
// Resolve locales (undefined/'*' → all available, array → specific)
|
|
228
228
|
const { resolveLocales } = await import('@uniweb/build/i18n')
|
|
229
|
-
const
|
|
229
|
+
const defaultLocale = resolveDefaultLocale(config)
|
|
230
|
+
// ⛔ The default language is the source, never a translation. A declared
|
|
231
|
+
// `languages: [en, es]` lists it, and `status` and `audit` reported "en: No translation
|
|
232
|
+
// file — 75 strings need translation" until 2026-10-19 (the build skips it the same way,
|
|
233
|
+
// `buildLocalizedContent`).
|
|
234
|
+
const locales = (await resolveLocales(config.languages, localesPath)).filter((l) => l !== defaultLocale)
|
|
230
235
|
|
|
231
236
|
return {
|
|
232
|
-
defaultLocale
|
|
237
|
+
defaultLocale,
|
|
233
238
|
locales,
|
|
234
239
|
localesDir,
|
|
235
240
|
...config.i18n
|
package/src/framework-index.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
|
-
"generatedAt": "2026-10-
|
|
3
|
+
"generatedAt": "2026-10-20T04:24:35.767Z",
|
|
4
4
|
"packages": {
|
|
5
5
|
"@uniweb/api": {
|
|
6
|
-
"version": "1.6.
|
|
6
|
+
"version": "1.6.2"
|
|
7
7
|
},
|
|
8
8
|
"@uniweb/build": {
|
|
9
|
-
"version": "1.
|
|
9
|
+
"version": "1.7.1"
|
|
10
10
|
},
|
|
11
11
|
"@uniweb/content-reader": {
|
|
12
12
|
"version": "1.5.4"
|
|
@@ -15,16 +15,16 @@
|
|
|
15
15
|
"version": "1.3.0"
|
|
16
16
|
},
|
|
17
17
|
"@uniweb/core": {
|
|
18
|
-
"version": "1.
|
|
18
|
+
"version": "1.4.0"
|
|
19
19
|
},
|
|
20
20
|
"@uniweb/frame-bridge": {
|
|
21
21
|
"version": "1.0.2"
|
|
22
22
|
},
|
|
23
23
|
"@uniweb/icons": {
|
|
24
|
-
"version": "1.0.
|
|
24
|
+
"version": "1.0.5"
|
|
25
25
|
},
|
|
26
26
|
"@uniweb/kit": {
|
|
27
|
-
"version": "1.
|
|
27
|
+
"version": "1.6.0"
|
|
28
28
|
},
|
|
29
29
|
"@uniweb/loom": {
|
|
30
30
|
"version": "1.1.0"
|
|
@@ -33,16 +33,16 @@
|
|
|
33
33
|
"version": "1.1.3"
|
|
34
34
|
},
|
|
35
35
|
"@uniweb/projections": {
|
|
36
|
-
"version": "1.1.
|
|
36
|
+
"version": "1.1.6"
|
|
37
37
|
},
|
|
38
38
|
"@uniweb/runtime": {
|
|
39
|
-
"version": "1.1.
|
|
39
|
+
"version": "1.1.14"
|
|
40
40
|
},
|
|
41
41
|
"@uniweb/scene": {
|
|
42
42
|
"version": "1.0.1"
|
|
43
43
|
},
|
|
44
44
|
"@uniweb/schemas": {
|
|
45
|
-
"version": "1.
|
|
45
|
+
"version": "1.6.0"
|
|
46
46
|
},
|
|
47
47
|
"@uniweb/scholar": {
|
|
48
48
|
"version": "1.1.0"
|
|
@@ -54,13 +54,13 @@
|
|
|
54
54
|
"version": "1.1.0"
|
|
55
55
|
},
|
|
56
56
|
"@uniweb/templates": {
|
|
57
|
-
"version": "1.1.
|
|
57
|
+
"version": "1.1.4"
|
|
58
58
|
},
|
|
59
59
|
"@uniweb/theming": {
|
|
60
|
-
"version": "1.2.
|
|
60
|
+
"version": "1.2.1"
|
|
61
61
|
},
|
|
62
62
|
"@uniweb/unipress": {
|
|
63
|
-
"version": "1.1.
|
|
63
|
+
"version": "1.1.11"
|
|
64
64
|
}
|
|
65
65
|
},
|
|
66
66
|
"templates": {
|