uniweb 0.79.3 → 0.80.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 +7 -7
- package/partials/agents.md +22 -12
- package/src/commands/starter.js +9 -5
- package/src/framework-index.json +8 -8
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "uniweb",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.80.0",
|
|
4
4
|
"description": "Create structured Vite + React sites with content/code separation",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -41,17 +41,17 @@
|
|
|
41
41
|
"js-yaml": "^4.1.0",
|
|
42
42
|
"prompts": "^2.4.2",
|
|
43
43
|
"tar": "^7.0.0",
|
|
44
|
+
"@uniweb/runtime": "^0.28.4",
|
|
44
45
|
"@uniweb/content-writer": "^0.3.4",
|
|
45
46
|
"@uniweb/core": "^0.35.0",
|
|
46
|
-
"@uniweb/
|
|
47
|
-
"@uniweb/
|
|
48
|
-
"@uniweb/
|
|
49
|
-
"@uniweb/semantic-parser": "^1.5.0"
|
|
47
|
+
"@uniweb/kit": "^0.19.13",
|
|
48
|
+
"@uniweb/schemas": "^0.10.0",
|
|
49
|
+
"@uniweb/semantic-parser": "^1.5.1"
|
|
50
50
|
},
|
|
51
51
|
"peerDependencies": {
|
|
52
|
-
"@uniweb/build": "^0.
|
|
52
|
+
"@uniweb/build": "^0.74.0",
|
|
53
53
|
"@uniweb/content-reader": "^1.2.7",
|
|
54
|
-
"@uniweb/semantic-parser": "^1.5.
|
|
54
|
+
"@uniweb/semantic-parser": "^1.5.1"
|
|
55
55
|
},
|
|
56
56
|
"peerDependenciesMeta": {
|
|
57
57
|
"@uniweb/build": {
|
package/partials/agents.md
CHANGED
|
@@ -531,7 +531,7 @@ Optional attributes: `{size=20}`, `{color=red}`. Custom SVGs: `{href=/products} <!-- Clickable media: href + target ride along -->
|
|
532
532
|
```
|
|
533
533
|
|
|
534
|
-
Sizing and loading ride on the image: `{width=800 height=600 loading=lazy fit=cover position=center}`. A video adds `{poster=./thumb.jpg autoplay muted loop controls}`; a `{role=pdf}` document adds `{preview=./cover.jpg author=… description=…}` and arrives in `content.documents` — declare it in `content:` as `documents`.
|
|
534
|
+
Sizing and loading ride on the image: `{width=800 height=600 loading=lazy fit=cover position=center}`. A video adds `{poster=./thumb.jpg autoplay muted loop controls}`; a `{role=pdf}` document adds `{preview=./cover.jpg author=… description=…}` and arrives in `content.documents` — `{ url, name, mime, size?, alt, caption, … }` — declare it in `content:` as `documents`.
|
|
535
535
|
|
|
536
536
|
**Quote values containing spaces:** `{note="Ready to go"}`, not `{note=Ready to go}` — unquoted values end at the first space.
|
|
537
537
|
|
|
@@ -1089,7 +1089,7 @@ Names only — for signatures and props, read the package: it's on disk at `node
|
|
|
1089
1089
|
|
|
1090
1090
|
**Text:** `H1`–`H6`, `P`, `Span`, `Div`, `Text` (with `as`)
|
|
1091
1091
|
**Content:** `Section`, `Prose`, `Article`, `Render` (ProseMirror → React), `ChildBlocks`, `splitContent()`
|
|
1092
|
-
**Media:** `Visual` (first
|
|
1092
|
+
**Media:** `Visual` (a `content.media` item by its kind; or the first of inset/video/image), `Image`, `Media` (video), `Icon`, `Asset`
|
|
1093
1093
|
**Navigation:** `Link`, `useActiveRoute()`, `useWebsite()`, `useRouting()`
|
|
1094
1094
|
**Header/layout:** `useScrolled(threshold)`, `useMobileMenu()`, `useAppearance()`
|
|
1095
1095
|
**Overlays:** `Overlay` (modals, palettes, drawers, toasts — portals out of the layout, contains focus; read the note below before hand-rolling one)
|
|
@@ -1162,21 +1162,23 @@ Header.as = 'header'
|
|
|
1162
1162
|
export default {
|
|
1163
1163
|
title: 'Feature Grid',
|
|
1164
1164
|
description: 'Grid of feature cards with icons',
|
|
1165
|
-
|
|
1166
|
-
//
|
|
1167
|
-
//
|
|
1168
|
-
// site: a genre like 'marketing' belongs to a template
|
|
1169
|
-
purpose: 'Explain', // free-form; a single verb reads well
|
|
1165
|
+
family: 'features', // the standard section type it is — the editor's
|
|
1166
|
+
// illustration and label (`uniweb families`). Optional;
|
|
1167
|
+
// a name like `Features` resolves on its own
|
|
1170
1168
|
// hidden: true, // Exclude from export entirely (internal helpers)
|
|
1171
1169
|
// background: 'self', // Component renders its own background
|
|
1172
1170
|
// inset: true, // Available for @ComponentName in markdown
|
|
1173
|
-
// visuals: 1, // Expects 1 visual
|
|
1174
1171
|
// children: true, // Accepts child sections
|
|
1175
1172
|
|
|
1176
1173
|
content: {
|
|
1177
1174
|
title: 'Section heading',
|
|
1178
1175
|
paragraphs: 'Introduction [0-1]',
|
|
1179
|
-
items:
|
|
1176
|
+
items: {
|
|
1177
|
+
label: 'Feature cards [3-6]',
|
|
1178
|
+
content: { icon: 'Icon [1]', title: 'Feature', paragraphs: 'Description' }, // one entry
|
|
1179
|
+
},
|
|
1180
|
+
// media: 'Photo, video or diagram [1]', // an image, a video, or an embedded component
|
|
1181
|
+
// sequence: 'Prose and media', // renders content.sequence — the section as written
|
|
1180
1182
|
},
|
|
1181
1183
|
|
|
1182
1184
|
params: {
|
|
@@ -1197,6 +1199,13 @@ export default {
|
|
|
1197
1199
|
|
|
1198
1200
|
**All defaults belong in `meta.js`, not inline in component code.** `meta.js` is also the catalog entry another agent reads to discover your section type (Part 2, step 2) — write `description` and `content:` for that reader.
|
|
1199
1201
|
|
|
1202
|
+
**`content:` names what the component reads**, each as a label for the author with an optional count (`'Cards [3-6]'`): `title`, `pretitle`, `subtitle`, `paragraphs`, `links`, `lists`, `items`, `media`, `icons`, `documents`, `snippets`, `tables`, `math`, `quotes`, `sequence`.
|
|
1203
|
+
|
|
1204
|
+
- **`media` is an image, a video, or an embedded component.** `media: 'Hero media [1]'` takes any of the three; `media: { label, types: ['image'] }` narrows it; `image:`, `videos:` and `insets:` are the same slot narrowed to one type. Read it as `content.media` — the author's order, each item with its `kind` — and render it with `<Visual media={content.media} block={block} />`. Rendering the slot with `<Image>` drops a diagram an author placed there, and kit's `<Media>` is a video player.
|
|
1205
|
+
- **`sequence`** says the component renders `content.sequence` — the whole section as written, headline included. `{ label, except: ['table', 'math'] }` names the kinds it leaves out.
|
|
1206
|
+
- **`items: { label, content: { … } }`** says what each entry holds, in the same vocabulary.
|
|
1207
|
+
- The build warns on what it can't read, and refuses `visuals:` (declare `media`) and the `content:` element `data` (declare the block's tag in `data:`).
|
|
1208
|
+
|
|
1200
1209
|
> **`meta.js` is a user interface, not just metadata.** When a foundation is published, every `meta.js` is registered as the foundation's schema, and the visual editor builds its controls from it: the build generates a `schema.json` from every `meta.js` in the foundation, and the editor renders it: a `select` param with `options` becomes a dropdown, a `boolean` becomes a toggle, `label` and `description` become the words a non-technical author reads, and each entry in `presets` becomes a one-click choice. That's the real reason param naming matters — `variant: centered` and `renderMode: flex-center` aren't a style preference, they're the difference between a legible control and a baffling one. Write `meta.js` as though someone who will never see your code has to use it, because that's exactly who does.
|
|
1201
1210
|
|
|
1202
1211
|
### Two worlds: section types and your own components
|
|
@@ -1619,7 +1628,7 @@ Back up your database **before** running this. It is not reversible.
|
|
|
1619
1628
|
|
|
1620
1629
|
That makes one distinction worth holding onto. You **may** declare a schema describing the form *definition's envelope* — `title`, `description`, `fields` as a map — and get build-time validation that an authored form is well-formed. What you can't declare is a schema whose fields are *the form's* fields (`name`, `email`, …); that's describing the visitor's answers, which arrive at runtime and belong to a form you've never seen. Declare the key either way — it is what delivers the block — and give it a schema only if you want it checked, and only of the envelope (`{}` declares the key with none).
|
|
1621
1630
|
|
|
1622
|
-
**Reading one in a component.** Declare the
|
|
1631
|
+
**Reading one in a component.** Declare it the way the author writes the fence — `data: { 'md:faq': 'Questions and answers [3+]' }`. The value is the author's label (its count counts the entries), or `{ label, hint, content: { title: 'Question', paragraphs: 'Answer' } }` to say what each entry holds. The component still reads `content.data.faq`, which gives you both views: `items` for anything row-shaped (an accordion, a step list), `sequence` when you don't recognize the tag and want to render it faithfully in document order. Both are derived, so nothing is stored twice. (`faq: {}` also declares the key, saying nothing about the block.)
|
|
1623
1632
|
|
|
1624
1633
|
```jsx
|
|
1625
1634
|
function Faq({ content }) {
|
|
@@ -1637,10 +1646,11 @@ function Faq({ content }) {
|
|
|
1637
1646
|
{variant=compact}
|
|
1638
1647
|
```
|
|
1639
1648
|
|
|
1640
|
-
The developer builds `NetworkDiagram` as an ordinary React component with `inset: true` in `meta.js`.
|
|
1649
|
+
The developer builds `NetworkDiagram` as an ordinary React component with `inset: true` in `meta.js`. The section that hosts it declares a `media` slot, and kit's `<Visual>` renders the author's item by its kind — so one section type works whether the author supplies an image, a video, or an interactive component:
|
|
1641
1650
|
|
|
1642
1651
|
```jsx
|
|
1643
|
-
|
|
1652
|
+
// meta.js: content: { title: 'Headline', media: 'Illustration [1]' }
|
|
1653
|
+
<Visual media={content.media} block={block} className="rounded-2xl" />
|
|
1644
1654
|
```
|
|
1645
1655
|
|
|
1646
1656
|
**Insets are full section types** — they receive `{ content, params, block }`. The alt text becomes `content.title` and attributes become `params`: `{note="Ready to go"}` → `content.title = "npm create uniweb"`, `params.note = "Ready to go"`.
|
package/src/commands/starter.js
CHANGED
|
@@ -90,6 +90,8 @@ export async function generateStarter({ name, sectionDir, preset, json, write })
|
|
|
90
90
|
const metaPath = join(sectionDir, 'meta.js')
|
|
91
91
|
const meta = existsSync(metaPath) ? await loadMeta(metaPath) : {}
|
|
92
92
|
const result = starterContent({ name, ...meta }, { preset })
|
|
93
|
+
// What the declaration says that could not be read — the build warns the same way.
|
|
94
|
+
result.problems = describeContent({ name, ...meta }).problems
|
|
93
95
|
|
|
94
96
|
const doc = buildDoc(result.content)
|
|
95
97
|
const markdown = doc ? serializeSection(result.params, doc) : ''
|
|
@@ -157,11 +159,14 @@ export function reportStarter(result, { write } = {}) {
|
|
|
157
159
|
console.log('')
|
|
158
160
|
console.log(` ${c.yellow}!${c.reset} Not filled: ${result.unfilled.join(', ')}`)
|
|
159
161
|
console.log(
|
|
160
|
-
` ${c.dim}
|
|
161
|
-
)
|
|
162
|
-
console.log(
|
|
163
|
-
` ${c.dim}A \`data\` block needs a schema: a @/ ref resolves at build, and an empty {} declares no shape.${c.reset}`,
|
|
162
|
+
` ${c.dim}A starter makes up no file, video or embedded component, and writes no table, equation,${c.reset}`,
|
|
164
163
|
)
|
|
164
|
+
console.log(` ${c.dim}quote or concept block (md:<tag>) — add those in the section.${c.reset}`)
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
if (result.problems?.length) {
|
|
168
|
+
console.log('')
|
|
169
|
+
for (const problem of result.problems) console.log(` ${c.yellow}!${c.reset} ${problem}`)
|
|
165
170
|
}
|
|
166
171
|
|
|
167
172
|
if (write) {
|
|
@@ -189,7 +194,6 @@ export async function declarationFor(result) {
|
|
|
189
194
|
icons: 'Icon [1]',
|
|
190
195
|
videos: 'Video [1]',
|
|
191
196
|
snippets: 'Code sample [1]',
|
|
192
|
-
data: 'The data block the author writes',
|
|
193
197
|
}
|
|
194
198
|
// ⛔ The slot → declaration spelling comes from @uniweb/schemas, not from a
|
|
195
199
|
// copy here. `image` declares and `images` delivers; that mapping is the
|
package/src/framework-index.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
|
-
"generatedAt": "2026-09-
|
|
3
|
+
"generatedAt": "2026-09-29T20:02:35.777Z",
|
|
4
4
|
"packages": {
|
|
5
5
|
"@uniweb/api": {
|
|
6
6
|
"version": "0.6.8",
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
]
|
|
11
11
|
},
|
|
12
12
|
"@uniweb/build": {
|
|
13
|
-
"version": "0.
|
|
13
|
+
"version": "0.74.0",
|
|
14
14
|
"path": "framework/build",
|
|
15
15
|
"deps": [
|
|
16
16
|
"@uniweb/content-reader",
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
]
|
|
56
56
|
},
|
|
57
57
|
"@uniweb/kit": {
|
|
58
|
-
"version": "0.19.
|
|
58
|
+
"version": "0.19.13",
|
|
59
59
|
"path": "framework/kit",
|
|
60
60
|
"deps": [
|
|
61
61
|
"@uniweb/core",
|
|
@@ -84,7 +84,7 @@
|
|
|
84
84
|
]
|
|
85
85
|
},
|
|
86
86
|
"@uniweb/runtime": {
|
|
87
|
-
"version": "0.28.
|
|
87
|
+
"version": "0.28.4",
|
|
88
88
|
"path": "framework/runtime",
|
|
89
89
|
"deps": [
|
|
90
90
|
"@uniweb/core",
|
|
@@ -97,7 +97,7 @@
|
|
|
97
97
|
"deps": []
|
|
98
98
|
},
|
|
99
99
|
"@uniweb/schemas": {
|
|
100
|
-
"version": "0.
|
|
100
|
+
"version": "0.10.0",
|
|
101
101
|
"path": "framework/schemas",
|
|
102
102
|
"deps": []
|
|
103
103
|
},
|
|
@@ -107,7 +107,7 @@
|
|
|
107
107
|
"deps": []
|
|
108
108
|
},
|
|
109
109
|
"@uniweb/semantic-parser": {
|
|
110
|
-
"version": "1.5.
|
|
110
|
+
"version": "1.5.1",
|
|
111
111
|
"path": "framework/semantic-parser",
|
|
112
112
|
"deps": []
|
|
113
113
|
},
|
|
@@ -117,7 +117,7 @@
|
|
|
117
117
|
"deps": []
|
|
118
118
|
},
|
|
119
119
|
"@uniweb/templates": {
|
|
120
|
-
"version": "0.17.
|
|
120
|
+
"version": "0.17.9",
|
|
121
121
|
"path": "framework/templates",
|
|
122
122
|
"deps": []
|
|
123
123
|
},
|
|
@@ -127,7 +127,7 @@
|
|
|
127
127
|
"deps": []
|
|
128
128
|
},
|
|
129
129
|
"@uniweb/unipress": {
|
|
130
|
-
"version": "0.10.
|
|
130
|
+
"version": "0.10.17",
|
|
131
131
|
"path": "framework/unipress",
|
|
132
132
|
"deps": [
|
|
133
133
|
"@uniweb/build",
|