@uniweb/core 0.36.0 → 0.37.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 +3 -3
- package/src/index.js +4 -1
- package/src/route-match.js +21 -0
- package/src/website.js +7 -2
- package/src/schemas.js +0 -45
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@uniweb/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.37.1",
|
|
4
4
|
"description": "Core classes for the Uniweb platform - Uniweb, Website, Page, Block",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -49,8 +49,8 @@
|
|
|
49
49
|
"vitest": "^4.1.7"
|
|
50
50
|
},
|
|
51
51
|
"dependencies": {
|
|
52
|
-
"@uniweb/
|
|
53
|
-
"@uniweb/
|
|
52
|
+
"@uniweb/theming": "^0.2.0",
|
|
53
|
+
"@uniweb/semantic-parser": "^1.5.1"
|
|
54
54
|
},
|
|
55
55
|
"scripts": {
|
|
56
56
|
"test": "vitest run"
|
package/src/index.js
CHANGED
|
@@ -93,7 +93,10 @@ export {
|
|
|
93
93
|
landingRoute,
|
|
94
94
|
RESOLUTION_STATUS,
|
|
95
95
|
} from './resolve-route.js'
|
|
96
|
-
|
|
96
|
+
// ⛔ No `isRichSchema` (removed 2026-10-05). It told a form-shaped `data:` value from a field
|
|
97
|
+
// map for the runtime's field defaults and the build's runtime schema; both went when the
|
|
98
|
+
// runtime stopped filling field defaults. A registered schema says it outright — `kind: 'form'`
|
|
99
|
+
// in format 3 (`@uniweb/schemas/foundation`) — and the editor, its last reader, reads that.
|
|
97
100
|
// ⛔ `Tracker` is NOT on the package entry. It is a FEATURE, not part of the
|
|
98
101
|
// object graph this package exists to define, and putting it here made every
|
|
99
102
|
// consumer of core carry 1,576 gzip of it -- press, unipress, `@uniweb/api`
|
package/src/route-match.js
CHANGED
|
@@ -297,6 +297,27 @@ export function recordTitle(record) {
|
|
|
297
297
|
return undefined
|
|
298
298
|
}
|
|
299
299
|
|
|
300
|
+
/**
|
|
301
|
+
* A record's SHARED IMAGE — what a link to the page about it shows (its `og:image`).
|
|
302
|
+
*
|
|
303
|
+
* ONE RULE, read where `recordTitle` is: the parametric page (`Website._createDynamicPage`)
|
|
304
|
+
* and the static build's page expansion. It is the record's `image` — the card's picture,
|
|
305
|
+
* which a page names itself from as it does from the card's title — and it takes the
|
|
306
|
+
* place of the page's own `seo.image`, which then serves a record that has none. A site's
|
|
307
|
+
* `seo.image` comes last (`Page.getHeadMeta`).
|
|
308
|
+
*
|
|
309
|
+
* Only a non-empty string is an image: a localized map or an object is structure this
|
|
310
|
+
* rule cannot write into a meta tag.
|
|
311
|
+
*
|
|
312
|
+
* @param {Object} record
|
|
313
|
+
* @returns {string|undefined}
|
|
314
|
+
*/
|
|
315
|
+
export function recordImage(record) {
|
|
316
|
+
if (!record || typeof record !== 'object') return undefined
|
|
317
|
+
const image = record.image
|
|
318
|
+
return typeof image === 'string' && image.trim() !== '' ? image : undefined
|
|
319
|
+
}
|
|
320
|
+
|
|
300
321
|
/**
|
|
301
322
|
* The record field a route param is matched on — ONE MAP, read by the local match
|
|
302
323
|
* (`routeParamValue`, below) and by the records service's record question (`match`,
|
package/src/website.js
CHANGED
|
@@ -11,7 +11,7 @@ import FetcherDispatcher from './fetcher-dispatcher.js'
|
|
|
11
11
|
import ObservableState from './observable-state.js'
|
|
12
12
|
import { normalizeSeo } from './seo.js'
|
|
13
13
|
import { resolveDefaultLocale, localeLabel } from './locale-config.js'
|
|
14
|
-
import { matchDynamicRoute, recordTitle, routeBinding, routeParamName, parentRouteOf } from './route-match.js'
|
|
14
|
+
import { matchDynamicRoute, recordTitle, recordImage, routeBinding, routeParamName, parentRouteOf } from './route-match.js'
|
|
15
15
|
import { resolveFetchConfigs, pageRouteQuery, recordPages } from './fetch-config.js'
|
|
16
16
|
import { declaredKeys } from './data-keys.js'
|
|
17
17
|
import { pageRecordConfig, planFor, runPlanSync } from './page-data.js'
|
|
@@ -636,6 +636,11 @@ export default class Website {
|
|
|
636
636
|
if (currentItem.description || currentItem.excerpt) {
|
|
637
637
|
pageData.description = currentItem.description || currentItem.excerpt
|
|
638
638
|
}
|
|
639
|
+
// ⭐ And by its picture: a link to the page shows the record's image (`recordImage`).
|
|
640
|
+
// ⛔ Until 2026-10-05 it showed the page's or the site's `seo.image`, the same for
|
|
641
|
+
// every record.
|
|
642
|
+
const image = recordImage(currentItem)
|
|
643
|
+
if (image) pageData.seo = { ...(pageData.seo || {}), image }
|
|
639
644
|
} else if (answered) {
|
|
640
645
|
// The cache answered and the record is not there: the set is loaded and this ID is
|
|
641
646
|
// not in it, or the record question answered `[]` — definitive not found.
|
|
@@ -755,7 +760,7 @@ export default class Website {
|
|
|
755
760
|
/**
|
|
756
761
|
* Get layout metadata from foundation config
|
|
757
762
|
* @param {string} layoutName - Layout name
|
|
758
|
-
* @returns {Object|null} Layout meta {
|
|
763
|
+
* @returns {Object|null} Layout meta { transitions, layers, scroll, defaults } — a page's areas are its site's `layout/` folder (`getLayoutAreas`)
|
|
759
764
|
*/
|
|
760
765
|
getLayoutMeta(layoutName) {
|
|
761
766
|
return findLayoutEntry(globalThis.uniweb?.foundationConfig?.layoutMeta, layoutName) || null
|
package/src/schemas.js
DELETED
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The rich-form-schema predicate. One function, and deliberately only one.
|
|
3
|
-
*
|
|
4
|
-
* Rich schemas live under `data.schemas` in a component's meta.js. They drive
|
|
5
|
-
* two author input paths that both land at `content.data[schema-id]`: tagged
|
|
6
|
-
* markdown blocks (``` ```yaml:<id> ``` ```) and the editor's FormBlock widget.
|
|
7
|
-
*
|
|
8
|
-
* `isRichSchema` is a **dispatch** predicate — "is this already the rich shape?"
|
|
9
|
-
* — and it is read at render by `runtime/src/prepare-props.js` (`applySchemas`)
|
|
10
|
-
* and at build by `build/src/runtime-schema.js`. Both are on the hot path of
|
|
11
|
-
* every site, which is what earns it a place in this package.
|
|
12
|
-
*
|
|
13
|
-
* ⛔ **Do not add editor-side schema code here.** `normalizeSchema` — "can this
|
|
14
|
-
* be edited, and as what?" — sat beside this function until 2026-09-01 purely
|
|
15
|
-
* because the two were adjacent; it never called `isRichSchema` and had no
|
|
16
|
-
* consumer outside the editor. `@uniweb/core` loads on every site in every lane
|
|
17
|
-
* and is not tree-shaken on the hosted one, so an editor-only function on its
|
|
18
|
-
* entry is paid for by every visitor of every site. It now lives in the
|
|
19
|
-
* zero-dependency leaf that owns what a data-schema *means*:
|
|
20
|
-
* **`@uniweb/schemas/editor-form`**.
|
|
21
|
-
*
|
|
22
|
-
* Conditional field visibility (a rich-schema feature) is likewise editor-only
|
|
23
|
-
* and is not implemented here — the editor owns its own evaluator.
|
|
24
|
-
*/
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Does a `data.schemas` entry look like a rich form schema?
|
|
28
|
-
*
|
|
29
|
-
* Rich schemas have an ordered `fields` array (composite arrays and
|
|
30
|
-
* nested objects), distinct from simple keyed-object schemas used for
|
|
31
|
-
* tagged blocks. Markers (any of):
|
|
32
|
-
* - `fields` is an array
|
|
33
|
-
* - `isComposite: true`
|
|
34
|
-
* - `childSchema` present
|
|
35
|
-
*
|
|
36
|
-
* @param {*} schema - Schema value to inspect.
|
|
37
|
-
* @returns {boolean}
|
|
38
|
-
*/
|
|
39
|
-
export function isRichSchema(schema) {
|
|
40
|
-
if (!schema || typeof schema !== 'object') return false
|
|
41
|
-
if (Array.isArray(schema.fields)) return true
|
|
42
|
-
if (schema.isComposite === true) return true
|
|
43
|
-
if (schema.childSchema && typeof schema.childSchema === 'object') return true
|
|
44
|
-
return false
|
|
45
|
-
}
|