@uniweb/runtime 1.2.4 → 1.2.5
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/ssr.js +1 -18
- package/dist/ssr.js.map +1 -1
- package/package.json +4 -6
- package/src/components/PageRenderer.jsx +1 -2
- package/src/hooks/useHeadMeta.js +1 -17
- package/src/ssr-renderer.js +6 -11
- package/src/head-meta.js +0 -38
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@uniweb/runtime",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.5",
|
|
4
4
|
"description": "Minimal runtime for loading Uniweb foundations",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -36,16 +36,15 @@
|
|
|
36
36
|
"node": ">=22.12"
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"@uniweb/core": "~1.4.
|
|
40
|
-
"@uniweb/theming": "~1.2.1"
|
|
41
|
-
"@uniweb/projections": "~1.2.2"
|
|
39
|
+
"@uniweb/core": "~1.4.9",
|
|
40
|
+
"@uniweb/theming": "~1.2.1"
|
|
42
41
|
},
|
|
43
42
|
"devDependencies": {
|
|
44
43
|
"@vitejs/plugin-react": "^4.5.2",
|
|
45
44
|
"esbuild": "^0.21.0 || ^0.23.0 || ^0.24.0 || ^0.25.0 || ^0.27.0 || ^0.28.0",
|
|
46
45
|
"vite": "^7.3.1",
|
|
47
46
|
"vitest": "^4.1.7",
|
|
48
|
-
"@uniweb/build": "1.10.
|
|
47
|
+
"@uniweb/build": "1.10.6"
|
|
49
48
|
},
|
|
50
49
|
"peerDependencies": {
|
|
51
50
|
"react": "^19.0.0",
|
|
@@ -55,7 +54,6 @@
|
|
|
55
54
|
"uniweb": {
|
|
56
55
|
"bundledDeps": [
|
|
57
56
|
"@uniweb/core",
|
|
58
|
-
"@uniweb/projections",
|
|
59
57
|
"@uniweb/theming"
|
|
60
58
|
]
|
|
61
59
|
},
|
|
@@ -11,7 +11,6 @@ import { useLocation, useNavigate } from 'react-router-dom'
|
|
|
11
11
|
import BlockRenderer from './BlockRenderer.jsx'
|
|
12
12
|
import Layout from './Layout.jsx'
|
|
13
13
|
import { useHeadMeta } from '../hooks/useHeadMeta.js'
|
|
14
|
-
import { pageHeadMeta } from '../head-meta.js'
|
|
15
14
|
import { useSectionViews } from '../hooks/useSectionViews.js'
|
|
16
15
|
import { buildSectionOverrides } from '@uniweb/theming'
|
|
17
16
|
import { carryQuery } from '@uniweb/core/resolve-route'
|
|
@@ -183,7 +182,7 @@ export default function PageRenderer() {
|
|
|
183
182
|
}
|
|
184
183
|
|
|
185
184
|
// Head metadata — compute for all cases (redirect pages get a fallback)
|
|
186
|
-
const headMeta =
|
|
185
|
+
const headMeta = page?.getHeadMeta?.() || {
|
|
187
186
|
title: isNotFound ? 'Page Not Found' : (page?.title || 'Website'),
|
|
188
187
|
description: page?.description || ''
|
|
189
188
|
}
|
package/src/hooks/useHeadMeta.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* Updates meta tags when page changes in SPA navigation.
|
|
6
6
|
*
|
|
7
7
|
* ⭐ The browser twin of `injectPageContent`'s head tags, from the same source
|
|
8
|
-
* (`
|
|
8
|
+
* (`Page#getHeadMeta`), so a crawler that runs the page's script reads what one that
|
|
9
9
|
* does not read. These tags are the framework's: each is set when the page has a value
|
|
10
10
|
* and removed when it has none — as it must be, or a tag of the page before survives a
|
|
11
11
|
* navigation. ⛔ Until 2026-10-25 this removed the canonical of every page that did not
|
|
@@ -116,20 +116,6 @@ function setAlternates(alternates) {
|
|
|
116
116
|
}
|
|
117
117
|
}
|
|
118
118
|
|
|
119
|
-
/**
|
|
120
|
-
* The link to the page's markdown, replacing whatever the document carried
|
|
121
|
-
* @param {string|null} href
|
|
122
|
-
*/
|
|
123
|
-
function setMarkdownLink(href) {
|
|
124
|
-
for (const link of document.querySelectorAll('link[rel="alternate"][type="text/markdown"]')) link.remove()
|
|
125
|
-
if (!href) return
|
|
126
|
-
const link = document.createElement('link')
|
|
127
|
-
link.setAttribute('rel', 'alternate')
|
|
128
|
-
link.setAttribute('type', 'text/markdown')
|
|
129
|
-
link.setAttribute('href', href)
|
|
130
|
-
document.head.appendChild(link)
|
|
131
|
-
}
|
|
132
|
-
|
|
133
119
|
/**
|
|
134
120
|
* useHeadMeta hook
|
|
135
121
|
*
|
|
@@ -203,7 +189,6 @@ export function useHeadMeta(meta, options = {}) {
|
|
|
203
189
|
}
|
|
204
190
|
|
|
205
191
|
setAlternates(meta.alternates)
|
|
206
|
-
setMarkdownLink(meta.markdown || null)
|
|
207
192
|
|
|
208
193
|
// Cleanup function - reset to defaults on unmount
|
|
209
194
|
return () => {
|
|
@@ -224,7 +209,6 @@ export function useHeadMeta(meta, options = {}) {
|
|
|
224
209
|
meta?.og?.siteName,
|
|
225
210
|
meta?.twitter?.site,
|
|
226
211
|
JSON.stringify(meta?.alternates || []),
|
|
227
|
-
meta?.markdown,
|
|
228
212
|
siteName
|
|
229
213
|
])
|
|
230
214
|
}
|
package/src/ssr-renderer.js
CHANGED
|
@@ -37,7 +37,6 @@ import { layoutStickiness, sectionStickyProps, sectionScrollMargin, zoneProps }
|
|
|
37
37
|
import { DefaultLayout } from './default-layout.js'
|
|
38
38
|
import { renderAppearanceBootScript } from './appearance.js'
|
|
39
39
|
import { documentTitle } from './document-title.js'
|
|
40
|
-
import { pageHeadMeta } from './head-meta.js'
|
|
41
40
|
import { escapeHtml } from '@uniweb/core/page-shell'
|
|
42
41
|
|
|
43
42
|
// Re-export L2 helpers so the public `@uniweb/runtime/ssr` surface
|
|
@@ -585,8 +584,7 @@ export { escapeHtml }
|
|
|
585
584
|
* Common operations shared by both build and cloud:
|
|
586
585
|
* - Replace #root div with rendered HTML
|
|
587
586
|
* - Update page title
|
|
588
|
-
* - Write the page's head tags — description, canonical, hreflang, Open Graph
|
|
589
|
-
* markdown (`writeHeadMeta`)
|
|
587
|
+
* - Write the page's head tags — description, canonical, hreflang, Open Graph (`writeHeadMeta`)
|
|
590
588
|
* - Inject section override CSS
|
|
591
589
|
* - Inject the pre-paint appearance script
|
|
592
590
|
*
|
|
@@ -678,10 +676,9 @@ export function injectPageContent(html, renderedContent, page, options = {}) {
|
|
|
678
676
|
)
|
|
679
677
|
}
|
|
680
678
|
|
|
681
|
-
// ⭐ THE PAGE'S HEAD TAGS — description, canonical, hreflang, Open Graph, Twitter
|
|
682
|
-
//
|
|
683
|
-
//
|
|
684
|
-
// read the page's own.
|
|
679
|
+
// ⭐ THE PAGE'S HEAD TAGS — description, canonical, hreflang, Open Graph, Twitter — from the
|
|
680
|
+
// page's own head metadata (`Page#getHeadMeta`, which the browser writes the same tags from in
|
|
681
|
+
// `useHeadMeta`), so crawlers and social unfurlers, which run no script, read the page's own.
|
|
685
682
|
// ⛔ Until 2026-10-25 these were APPENDED, after the static build had written the HOME page's
|
|
686
683
|
// into the one shell every page is rendered into: each page named the home page its canonical
|
|
687
684
|
// and carried two og:title and two og:url, the home page's first.
|
|
@@ -701,8 +698,8 @@ export function injectPageContent(html, renderedContent, page, options = {}) {
|
|
|
701
698
|
* @returns {string}
|
|
702
699
|
*/
|
|
703
700
|
function writeHeadMeta(html, page) {
|
|
704
|
-
// A Page states its own (`
|
|
705
|
-
const meta = typeof page?.getHeadMeta === 'function' ?
|
|
701
|
+
// A Page states its own (`getHeadMeta`); plain page data, which callers may hand in, its fields.
|
|
702
|
+
const meta = typeof page?.getHeadMeta === 'function' ? page.getHeadMeta() : { description: page?.description || null }
|
|
706
703
|
const end = html.indexOf('</head>')
|
|
707
704
|
if (!meta || end === -1) return html
|
|
708
705
|
const og = meta.og || {}
|
|
@@ -736,8 +733,6 @@ function writeHeadMeta(html, page) {
|
|
|
736
733
|
for (const { hreflang, url } of meta.alternates || []) {
|
|
737
734
|
written.push(`<link rel="alternate" hreflang="${escapeHtml(hreflang)}" href="${escapeHtml(url)}">`)
|
|
738
735
|
}
|
|
739
|
-
head = head.replace(/<link\b(?=[^>]*\brel=["']alternate["'])(?=[^>]*\btype=["']text\/markdown["'])[^>]*>\s*/gi, '')
|
|
740
|
-
if (meta.markdown) written.push(`<link rel="alternate" type="text/markdown" href="${escapeHtml(meta.markdown)}">`)
|
|
741
736
|
return `${head}${written.join('\n')}\n${html.slice(end)}`
|
|
742
737
|
}
|
|
743
738
|
|
package/src/head-meta.js
DELETED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* A page's head metadata, as both of its writers state it: the prerender (`injectPageContent`)
|
|
3
|
-
* and the browser (`useHeadMeta`).
|
|
4
|
-
*
|
|
5
|
-
* ⭐ `Page#getHeadMeta`'s, plus the address of the page's markdown (`markdown`), which the head
|
|
6
|
-
* links with `<link rel="alternate" type="text/markdown">` so an agent that lands on the HTML finds
|
|
7
|
-
* the document. The address is the one the site index gives the page, for the pages a markdown
|
|
8
|
-
* file is written for (`pageMarkdownUrls`, `@uniweb/projections`). It is added here rather than
|
|
9
|
-
* in core because core cannot depend on the package whose rules decide it.
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
import { pageMarkdownUrls } from '@uniweb/projections/markdown-urls'
|
|
13
|
-
|
|
14
|
-
// A site's markdown addresses, worked out once for its content. `rebuild({ content })` gives the
|
|
15
|
-
// Website a new `pages` array, so that array is the key and a rebuilt site is worked out again.
|
|
16
|
-
const urlsOfPages = new WeakMap()
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* @param {Object} page - a Page
|
|
20
|
-
* @returns {Object} `page.getHeadMeta()`, and `markdown`: the URL of the page's markdown, or null —
|
|
21
|
-
* for a page the index leaves out and the not-found page, and for a record's page made on
|
|
22
|
-
* request (`uniweb dev`, a host), which is not among the content's pages. A static build's
|
|
23
|
-
* record pages are: its prerender writes them into the content each page boots with.
|
|
24
|
-
*/
|
|
25
|
-
export function pageHeadMeta(page) {
|
|
26
|
-
return { ...page.getHeadMeta(), markdown: markdownUrlOf(page) }
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
function markdownUrlOf(page) {
|
|
30
|
-
const website = page?.website
|
|
31
|
-
if (!website) return null
|
|
32
|
-
let urls = urlsOfPages.get(website.pages)
|
|
33
|
-
if (!urls) {
|
|
34
|
-
urls = pageMarkdownUrls({ pages: website.getContentPages(), config: website.config })
|
|
35
|
-
urlsOfPages.set(website.pages, urls)
|
|
36
|
-
}
|
|
37
|
-
return urls.get(page.route) ?? null
|
|
38
|
-
}
|