@uniweb/runtime 0.8.40 → 0.8.42
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/dist/app/_importmap/@uniweb-core.js +1 -1
- package/dist/app/_importmap/@uniweb-core.js.map +1 -1
- package/dist/app/assets/core-CSPVyulX.js +133 -0
- package/dist/app/assets/core-CSPVyulX.js.map +1 -0
- package/dist/app/assets/index-C2Sw5X24.js +64 -0
- package/dist/app/assets/index-C2Sw5X24.js.map +1 -0
- package/dist/app/index.html +2 -2
- package/dist/app/manifest.json +4 -4
- package/dist/shims/react-dom.js +18 -0
- package/dist/shims/uniweb-core.js +6 -0
- package/dist/ssr.js +36 -1
- package/dist/ssr.js.map +1 -1
- package/dist/worker-runtime-entry.js +8 -6
- package/dist/worker-runtime.js +1812 -467
- package/package.json +4 -4
- package/src/setup.js +13 -1
- package/src/ssr-renderer.js +37 -1
- package/src/wire-foundation.js +70 -0
- package/dist/app/assets/index-Ca9aM7z2.js +0 -16
- package/dist/app/assets/index-Ca9aM7z2.js.map +0 -1
- package/dist/app/assets/index-DesPD4M1.js +0 -133
- package/dist/app/assets/index-DesPD4M1.js.map +0 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@uniweb/runtime",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.42",
|
|
4
4
|
"description": "Minimal runtime for loading Uniweb foundations",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -35,15 +35,15 @@
|
|
|
35
35
|
"node": ">=20.19"
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@uniweb/core": "0.7.
|
|
39
|
-
"@uniweb/theming": "0.1.
|
|
38
|
+
"@uniweb/core": "0.7.34",
|
|
39
|
+
"@uniweb/theming": "0.1.15"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
42
|
"@vitejs/plugin-react": "^4.5.2",
|
|
43
43
|
"esbuild": "^0.21.0 || ^0.23.0 || ^0.24.0 || ^0.25.0 || ^0.27.0",
|
|
44
44
|
"vite": "^7.3.1",
|
|
45
45
|
"vitest": "^4.1.7",
|
|
46
|
-
"@uniweb/build": "0.15.
|
|
46
|
+
"@uniweb/build": "0.15.13"
|
|
47
47
|
},
|
|
48
48
|
"peerDependencies": {
|
|
49
49
|
"react": "^19.0.0",
|
package/src/setup.js
CHANGED
|
@@ -28,7 +28,7 @@ import {
|
|
|
28
28
|
} from 'react-router-dom'
|
|
29
29
|
|
|
30
30
|
import { ChildBlocks } from './components/PageRenderer.jsx'
|
|
31
|
-
import { wireFoundationCapabilities, hydrateDataStore } from './wire-foundation.js'
|
|
31
|
+
import { wireFoundationCapabilities, hydrateDataStore, ensureThemeCss } from './wire-foundation.js'
|
|
32
32
|
|
|
33
33
|
// Re-export so existing consumers importing hydrateDataStore from
|
|
34
34
|
// setup.js keep working. The implementation moved to wire-foundation.js
|
|
@@ -274,6 +274,18 @@ export function initUniweb({ content, foundation, extensions = [], routingCompon
|
|
|
274
274
|
// here vs. ssr-renderer.js.
|
|
275
275
|
wireFoundationCapabilities(uniweb, foundation)
|
|
276
276
|
|
|
277
|
+
// Site-wide theme CSS, for lanes that arrive without it (a backend-hosted
|
|
278
|
+
// SPA carries the authored theme.yml, not generated CSS). Skipped when a
|
|
279
|
+
// prerendered page already has the style tag in <head>: the build strips
|
|
280
|
+
// `theme.css` from __SITE_CONTENT__ precisely because it is already there,
|
|
281
|
+
// so "no css on the graph" does NOT imply "no css on the page" in this
|
|
282
|
+
// entry. The DOM check belongs here rather than in the L2 helper — it is
|
|
283
|
+
// environment-specific, and ensureThemeCss must stay importable by the
|
|
284
|
+
// hook-free SSR pipeline.
|
|
285
|
+
if (typeof document === 'undefined' || !document.getElementById('uniweb-theme')) {
|
|
286
|
+
ensureThemeCss(uniweb, foundation)
|
|
287
|
+
}
|
|
288
|
+
|
|
277
289
|
uniweb.routingComponents = routingComponents
|
|
278
290
|
uniweb.iconResolver = createIconResolver(content?.icons)
|
|
279
291
|
|
package/src/ssr-renderer.js
CHANGED
|
@@ -18,13 +18,14 @@ import React from 'react'
|
|
|
18
18
|
import { renderToString } from 'react-dom/server'
|
|
19
19
|
import { createUniweb, resolveDefaultLocale } from '@uniweb/core'
|
|
20
20
|
import { sectionDomId } from '@uniweb/core/section-id'
|
|
21
|
-
import { buildSectionOverrides } from '@uniweb/theming'
|
|
21
|
+
import { buildSectionOverrides, FONT_LINKS_MARKER } from '@uniweb/theming'
|
|
22
22
|
import { prepareProps, getComponentMeta } from './prepare-props.js'
|
|
23
23
|
import { default404Html } from './default-404.js'
|
|
24
24
|
import {
|
|
25
25
|
wireFoundationCapabilities,
|
|
26
26
|
sliceContentForLocale,
|
|
27
27
|
hydrateDataStore,
|
|
28
|
+
ensureThemeCss,
|
|
28
29
|
} from './wire-foundation.js'
|
|
29
30
|
import { resolveLayoutTransitions } from './view-transitions.js'
|
|
30
31
|
import { renderAppearanceBootScript } from './appearance.js'
|
|
@@ -479,6 +480,11 @@ export function initPrerender(content, foundation, extensionsOrOptions, maybeOpt
|
|
|
479
480
|
// here vs. setup.js.
|
|
480
481
|
wireFoundationCapabilities(uniweb, foundation)
|
|
481
482
|
|
|
483
|
+
// Site-wide theme CSS. Unconditional here: at this point there is no
|
|
484
|
+
// <head> to inspect, and injectPageContent() emits the result
|
|
485
|
+
// idempotently, so a lane that already baked the style tag is unaffected.
|
|
486
|
+
ensureThemeCss(uniweb, foundation)
|
|
487
|
+
|
|
482
488
|
// Register SSR-safe routing so useRouting()/useActiveRoute() work during prerender.
|
|
483
489
|
// renderPage() calls website.setActivePage() before rendering each page,
|
|
484
490
|
// so activePage.route always reflects the page being rendered.
|
|
@@ -664,6 +670,36 @@ export function injectPageContent(html, renderedContent, page, options = {}) {
|
|
|
664
670
|
}
|
|
665
671
|
}
|
|
666
672
|
|
|
673
|
+
// Site-wide theme CSS. Derived from the website graph
|
|
674
|
+
// (`website.themeData`), so it belongs on THIS side of the seam — every
|
|
675
|
+
// lane builds that graph. It lived in @uniweb/build's injectBuildData
|
|
676
|
+
// until 2026-07-28, which meant sites served by any lane that doesn't run
|
|
677
|
+
// the framework's build rendered with every semantic token unset: no
|
|
678
|
+
// colours, no backgrounds, no failure anywhere. That is the same mistake
|
|
679
|
+
// the appearance script above was moved out of, four lines below the
|
|
680
|
+
// comment warning about it — see the note in build/src/prerender.js.
|
|
681
|
+
// Idempotent, so a shell that already carries the tag is left alone.
|
|
682
|
+
const themeData = page?.website?.themeData
|
|
683
|
+
const themeCss = themeData?.css
|
|
684
|
+
if (themeCss && !result.includes('id="uniweb-theme"')) {
|
|
685
|
+
result = result.replace(
|
|
686
|
+
'</head>',
|
|
687
|
+
` <style id="uniweb-theme">\n${themeCss}\n </style>\n</head>`
|
|
688
|
+
)
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
// The theme's font <link> tags — same seam, same reasoning. Graph-derived,
|
|
692
|
+
// so a lane that never runs @uniweb/build still gets its webfonts instead of
|
|
693
|
+
// falling back to system faces. Deduped on FONT_LINKS_MARKER rather than an
|
|
694
|
+
// id because <link> tags have none; the marker is owned by @uniweb/theming,
|
|
695
|
+
// which generates the block, so this and @uniweb/build read one literal.
|
|
696
|
+
if (themeData?.links && !result.includes(FONT_LINKS_MARKER)) {
|
|
697
|
+
result = result.replace(
|
|
698
|
+
'</head>',
|
|
699
|
+
` ${FONT_LINKS_MARKER}\n${themeData.links}\n</head>`
|
|
700
|
+
)
|
|
701
|
+
}
|
|
702
|
+
|
|
667
703
|
// Inject per-page section override CSS before </head>
|
|
668
704
|
if (options.sectionOverrideCSS) {
|
|
669
705
|
const overrideStyle = `<style id="uniweb-page-overrides">\n${options.sectionOverrideCSS}\n</style>`
|
package/src/wire-foundation.js
CHANGED
|
@@ -46,6 +46,7 @@
|
|
|
46
46
|
|
|
47
47
|
import React from 'react'
|
|
48
48
|
import { deriveCacheKey, resolveDefaultLocale } from '@uniweb/core'
|
|
49
|
+
import { buildTheme } from '@uniweb/theming'
|
|
49
50
|
|
|
50
51
|
/**
|
|
51
52
|
* Renders unhandled `[#id]` cross-reference markers as plain text. Used
|
|
@@ -162,3 +163,72 @@ export function hydrateDataStore(website, fetchedData) {
|
|
|
162
163
|
website.dataStore.set(deriveCacheKey(entry.config), { data: entry.data })
|
|
163
164
|
}
|
|
164
165
|
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Make sure the site's theme CSS exists on the graph, generating it from
|
|
169
|
+
* the authored config when nothing upstream did.
|
|
170
|
+
*
|
|
171
|
+
* **The authored theme config is the source of truth in every lane;
|
|
172
|
+
* generated CSS is a cache of it.** `uniweb build` fills that cache and
|
|
173
|
+
* bakes the result into `<head>`, so this is a no-op on the static lane.
|
|
174
|
+
* A lane that serves a site WITHOUT running the framework's build — a
|
|
175
|
+
* backend-hosted SPA, a cloud shell-mode fallback — carries only the
|
|
176
|
+
* authored `theme.yml` (that is the correct thing for a sync wire to
|
|
177
|
+
* carry: `theme.css` is a build artifact, and with two publishers only
|
|
178
|
+
* one of which computes it, shipping it would make a site's styling
|
|
179
|
+
* depend on who published last). Without this helper those lanes render
|
|
180
|
+
* with every semantic token unset — no colours, no backgrounds.
|
|
181
|
+
*
|
|
182
|
+
* Generating here rather than in a publish step is what keeps the
|
|
183
|
+
* three-ingredient contract true: site + foundation + runtime converge
|
|
184
|
+
* to a *styled* page with no fourth actor. It also stays one
|
|
185
|
+
* implementation — the alternative was re-deriving the OKLCH shade math
|
|
186
|
+
* in another language and keeping the two bit-compatible.
|
|
187
|
+
*
|
|
188
|
+
* L2, not L3: this reads and writes graph state and renders nothing, so
|
|
189
|
+
* it has a single home here and both boot paths call it. **The
|
|
190
|
+
* `@uniweb/theming` import is deliberately static.** An SSR isolate
|
|
191
|
+
* loads a fixed modules map and cannot resolve a chunk graph, so the SSR
|
|
192
|
+
* entry must include the generator statically; a lazy `import()` in the
|
|
193
|
+
* browser entry only would mean two mechanisms for one behaviour,
|
|
194
|
+
* drifting independently. Measured cost of the generator: ~4.9 KB gzip.
|
|
195
|
+
*
|
|
196
|
+
* Foundation-declared vars reach us through
|
|
197
|
+
* `capabilities.vars` — emitted into `dist/entry.js` by
|
|
198
|
+
* `@uniweb/build`'s `generate-entry.js`. Before that existed they lived
|
|
199
|
+
* only in `dist/meta/schema.json` and a theme generated outside the
|
|
200
|
+
* build silently lost every one of them.
|
|
201
|
+
*
|
|
202
|
+
* Callers own the "should I?" question, because it is environment-
|
|
203
|
+
* specific: the browser entry skips this when the document already
|
|
204
|
+
* carries a prerendered `<style id="uniweb-theme">` (regenerating from
|
|
205
|
+
* an already-processed config is wasted work at best), while the SSR
|
|
206
|
+
* entry always runs it and lets `injectPageContent()` emit the result
|
|
207
|
+
* idempotently.
|
|
208
|
+
*
|
|
209
|
+
* @param {import('@uniweb/core').default} uniweb - From createUniweb(...).
|
|
210
|
+
* @param {object} foundation - Loaded foundation module (built shape).
|
|
211
|
+
*/
|
|
212
|
+
export function ensureThemeCss(uniweb, foundation) {
|
|
213
|
+
const website = uniweb?.activeWebsite
|
|
214
|
+
const themeData = website?.themeData
|
|
215
|
+
if (!themeData || themeData.css) return
|
|
216
|
+
|
|
217
|
+
const caps = foundation?.default?.capabilities || {}
|
|
218
|
+
try {
|
|
219
|
+
const { config, css, links } = buildTheme(themeData, {
|
|
220
|
+
foundationVars: caps.vars || {},
|
|
221
|
+
base: website.basePath || '/',
|
|
222
|
+
})
|
|
223
|
+
// Merge rather than replace: `config` is the processed superset (it
|
|
224
|
+
// adds `palettes`, normalized `contexts`, resolved `fonts`), so this
|
|
225
|
+
// also gives a build-less lane the same themeData shape the static
|
|
226
|
+
// lane has — Theme.getPalette() and friends start working too.
|
|
227
|
+
Object.assign(themeData, config, { css, links })
|
|
228
|
+
} catch (err) {
|
|
229
|
+
// This runs on the path taken when something upstream has already
|
|
230
|
+
// gone wrong. A degraded render that is still legibly the site beats
|
|
231
|
+
// one that looks broken, but neither is worth a boot crash.
|
|
232
|
+
console.warn('[uniweb] theme CSS generation failed:', err?.message || err)
|
|
233
|
+
}
|
|
234
|
+
}
|