@webtypen/webframez-react 0.0.25 → 0.0.27
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/README.md +20 -1
- package/dist/client.cjs +1 -1
- package/dist/client.js +1 -1
- package/dist/http.cjs +68 -7
- package/dist/http.js +68 -7
- package/dist/index.cjs +68 -7
- package/dist/index.js +68 -7
- package/dist/router.cjs +68 -7
- package/dist/router.js +68 -7
- package/dist/types.d.ts +7 -6
- package/dist/webframez-core.cjs +68 -7
- package/dist/webframez-core.js +68 -7
- package/package.json +7 -7
package/README.md
CHANGED
|
@@ -14,7 +14,7 @@ React Server Components (RSC) extension for `@webtypen/webframez-core`.
|
|
|
14
14
|
|
|
15
15
|
- Node.js `>= 20`
|
|
16
16
|
- `@webtypen/webframez-core`
|
|
17
|
-
- React
|
|
17
|
+
- React 19.x with matching `react-dom` and `react-server-dom-webpack`
|
|
18
18
|
|
|
19
19
|
## Installation
|
|
20
20
|
|
|
@@ -130,6 +130,25 @@ Route.renderReact("/app", {
|
|
|
130
130
|
- Additional route options forwarded to `webframez-core`.
|
|
131
131
|
- Typical use case: middleware.
|
|
132
132
|
|
|
133
|
+
## `Head()` Assets
|
|
134
|
+
|
|
135
|
+
Inside a page, layout, or error `Head()` method you can set `assetsBaseUrl`.
|
|
136
|
+
That base URL is applied to `favicon` and `links[].href`, which is useful for CSS
|
|
137
|
+
files and other head assets served from a CDN or shared asset host.
|
|
138
|
+
|
|
139
|
+
```ts
|
|
140
|
+
export function Head() {
|
|
141
|
+
return {
|
|
142
|
+
title: "Dashboard",
|
|
143
|
+
assetsBaseUrl: "https://cdn.example.com/app",
|
|
144
|
+
favicon: "/favicon.ico",
|
|
145
|
+
links: [{ rel: "stylesheet", href: "/styles/dashboard.css" }],
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
Absolute URLs like `https://...` or `//...` stay unchanged.
|
|
151
|
+
|
|
133
152
|
## Recommended Project Structure
|
|
134
153
|
|
|
135
154
|
```txt
|
package/dist/client.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var
|
|
1
|
+
var H=Object.create;var f=Object.defineProperty;var N=Object.getOwnPropertyDescriptor;var z=Object.getOwnPropertyNames;var B=Object.getPrototypeOf,M=Object.prototype.hasOwnProperty;var W=(e,n)=>{for(var t in n)f(e,t,{get:n[t],enumerable:!0})},v=(e,n,t,o)=>{if(n&&typeof n=="object"||typeof n=="function")for(let r of z(n))!M.call(e,r)&&r!==t&&f(e,r,{get:()=>n[r],enumerable:!(o=N(n,r))||o.enumerable});return e};var D=(e,n,t)=>(t=e!=null?H(B(e)):{},v(n||!e||!e.__esModule?f(t,"default",{value:e,enumerable:!0}):t,e)),F=e=>v(f({},"__esModule",{value:!0}),e);var oe={};W(oe,{mountWebframezClient:()=>ne,useCookie:()=>X,useRouter:()=>K});module.exports=F(oe);var i=D(require("react"),1),L=require("react-dom/client"),u=require("react-server-dom-webpack/client");var G=/^(?:[a-zA-Z][a-zA-Z\d+\-.]*:|\/\/|#)/;function g(e){let n=e?.trim();if(n)return n==="/"?"/":n.replace(/\/+$/,"")}function x(e,n){let t=e.trim(),o=g(n);return!t||!o||G.test(t)||o!=="/"&&(t===o||t.startsWith(`${o}/`))?t:o==="/"?t.startsWith("/")?t:`/${t}`:t.startsWith("/")?`${o}${t}`:`${o}/${t}`}function E(e,n){if(!e)return;let t=g(e.assetsBaseUrl)??g(n),o={...e,...t?{assetsBaseUrl:t}:{}};return o.favicon&&(o.favicon=x(o.favicon,t)),o.links&&(o.links=o.links.map(r=>({...r,href:x(r.href,t)}))),o}var s=require("react/jsx-runtime"),Y={push:()=>{},replace:()=>{},refresh:()=>{}},p=typeof i.default.createContext=="function"?i.default.createContext(null):null,U="__WEBFRAMEZ_ROUTER__",Z="[data-webframez-head='true']";function q(){return typeof window>"u"?null:window[U]??null}function j(e){typeof window>"u"||(window[U]=e)}function S(){let e={},n=typeof document>"u"?"":document.cookie;if(!n||n.trim()==="")return e;for(let t of n.split(";")){let o=t.trim();if(!o)continue;let r=o.indexOf("="),d=r>=0?o.slice(0,r).trim():o,c=r>=0?o.slice(r+1):"";d&&(e[d]=decodeURIComponent(c))}return e}function k(e,n,t={}){let o=[`${e}=${encodeURIComponent(n)}`];return t.path&&o.push(`Path=${t.path}`),t.domain&&o.push(`Domain=${t.domain}`),typeof t.maxAge=="number"&&o.push(`Max-Age=${Math.floor(t.maxAge)}`),t.expires&&o.push(`Expires=${t.expires.toUTCString()}`),t.sameSite&&o.push(`SameSite=${t.sameSite}`),t.secure&&o.push("Secure"),o.join("; ")}function X(){return i.default.useMemo(()=>({all:()=>S(),get:e=>S()[e],set:(e,n,t)=>{typeof document>"u"||(document.cookie=k(e,n,t))},remove:(e,n)=>{typeof document>"u"||(document.cookie=k(e,"",{...n??{},maxAge:0}))}}),[])}function K(){let e=p?i.default.useContext(p):null;if(!e){let n=q();if(n)return n;if(typeof window>"u")return Y;throw new Error("useRouter must be used inside mountWebframezClient()")}return e}function V({active:e}){return(0,s.jsx)("div",{style:{position:"fixed",top:0,left:0,width:"100%",height:3,zIndex:9999,transformOrigin:"left",transform:e?"scaleX(1)":"scaleX(0)",transition:"transform 180ms ease",background:"linear-gradient(90deg, #0ea5e9, #22c55e)"}})}function I(e){let n=document.createElement("meta");n.setAttribute("data-webframez-head","true");let t=Object.entries(e).filter(([,o])=>!!o);for(let[o,r]of t)n.setAttribute(o,String(r));document.head.appendChild(n)}function b(e){let n=document.createElement("link");n.setAttribute("data-webframez-head","true");let t=Object.entries(e).filter(([,o])=>!!o);for(let[o,r]of t)n.setAttribute(o,String(r));document.head.appendChild(n)}function P(e){if(typeof document>"u")return;let n=E(e)??e;document.title=n.title||"Webframez React";for(let t of document.head.querySelectorAll(Z))t.remove();n.description&&I({name:"description",content:n.description}),n.favicon&&b({rel:"icon",href:n.favicon});for(let t of n.meta??[])I(t);for(let t of n.links??[])b(t)}function J(e){let n=new TextEncoder;return new ReadableStream({start(t){t.enqueue(n.encode(e)),t.close()}})}function Q(){if(typeof window>"u")return null;let e=window.__RSC_INITIAL_PAYLOAD;return typeof e!="string"||e===""?null:(delete window.__RSC_INITIAL_PAYLOAD,(0,u.createFromReadableStream)(J(e)))}function ee(e){return Q()??(0,u.createFromFetch)(fetch(`${e}?path=${encodeURIComponent(window.location.pathname)}&search=${encodeURIComponent(window.location.search)}`,{headers:{Accept:"text/x-component"}}))}function te(e,n){return function(){let o=i.default.use(e),[r,d]=(0,i.useState)(o.model),[c,h]=(0,i.useState)(o.head),[O,w]=(0,i.useState)(!1),[T,$]=(0,i.useState)(!1);async function l(a,A="push"){w(!0);try{let m=await(0,u.createFromFetch)(fetch(`${n}?path=${encodeURIComponent(a.pathname)}&search=${encodeURIComponent(a.search)}`,{headers:{Accept:"text/x-component"}}));P(m.head),h(m.head),d(m.model);let _=`${a.pathname}${a.search}`;A==="replace"?history.replaceState(null,"",_):A==="push"&&history.pushState(null,"",_)}catch(y){console.error("[webframez-react] Failed to render route",y),d((0,s.jsx)("p",{children:"Failed to load route."}))}finally{w(!1)}}(0,i.useEffect)(()=>{P(c)},[c]),(0,i.useEffect)(()=>{$(!0);let a=()=>{l(new URL(window.location.href),"none")};return window.addEventListener("popstate",a),()=>{window.removeEventListener("popstate",a)}},[]);let R=i.default.useMemo(()=>({push:a=>{l(new URL(a,window.location.origin),"push")},replace:a=>{l(new URL(a,window.location.origin),"replace")},refresh:()=>{l(new URL(window.location.href),"none")}}),[]);j(R);let C=(0,s.jsxs)(s.Fragment,{children:[T?(0,s.jsx)(V,{active:O}):null,r??(0,s.jsx)("p",{style:{padding:24},children:"Loading..."})]});return p?(0,s.jsx)(p.Provider,{value:R,children:C}):C}}function ne(e={}){let n=e.rootId??"root",t=document.getElementById(n);if(!t)throw new Error(`Missing #${n} element`);let o=typeof window<"u"&&window.__RSC_ENDPOINT,r=e.rscEndpoint??o??"/rsc",d=ee(r),c=te(d,r);return(0,L.hydrateRoot)(t,(0,s.jsx)(c,{}))}
|
package/dist/client.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import
|
|
1
|
+
import c,{useEffect as x,useState as l}from"react";import{hydrateRoot as H}from"react-dom/client";import{createFromFetch as P,createFromReadableStream as N}from"react-server-dom-webpack/client";var $=/^(?:[a-zA-Z][a-zA-Z\d+\-.]*:|\/\/|#)/;function m(t){let n=t?.trim();if(n)return n==="/"?"/":n.replace(/\/+$/,"")}function _(t,n){let e=t.trim(),o=m(n);return!e||!o||$.test(e)||o!=="/"&&(e===o||e.startsWith(`${o}/`))?e:o==="/"?e.startsWith("/")?e:`/${e}`:e.startsWith("/")?`${o}${e}`:`${o}/${e}`}function v(t,n){if(!t)return;let e=m(t.assetsBaseUrl)??m(n),o={...t,...e?{assetsBaseUrl:e}:{}};return o.favicon&&(o.favicon=_(o.favicon,e)),o.links&&(o.links=o.links.map(r=>({...r,href:_(r.href,e)}))),o}import{Fragment as q,jsx as d,jsxs as j}from"react/jsx-runtime";var z={push:()=>{},replace:()=>{},refresh:()=>{}},f=typeof c.createContext=="function"?c.createContext(null):null,L="__WEBFRAMEZ_ROUTER__",B="[data-webframez-head='true']";function M(){return typeof window>"u"?null:window[L]??null}function W(t){typeof window>"u"||(window[L]=t)}function E(){let t={},n=typeof document>"u"?"":document.cookie;if(!n||n.trim()==="")return t;for(let e of n.split(";")){let o=e.trim();if(!o)continue;let r=o.indexOf("="),a=r>=0?o.slice(0,r).trim():o,s=r>=0?o.slice(r+1):"";a&&(t[a]=decodeURIComponent(s))}return t}function S(t,n,e={}){let o=[`${t}=${encodeURIComponent(n)}`];return e.path&&o.push(`Path=${e.path}`),e.domain&&o.push(`Domain=${e.domain}`),typeof e.maxAge=="number"&&o.push(`Max-Age=${Math.floor(e.maxAge)}`),e.expires&&o.push(`Expires=${e.expires.toUTCString()}`),e.sameSite&&o.push(`SameSite=${e.sameSite}`),e.secure&&o.push("Secure"),o.join("; ")}function ee(){return c.useMemo(()=>({all:()=>E(),get:t=>E()[t],set:(t,n,e)=>{typeof document>"u"||(document.cookie=S(t,n,e))},remove:(t,n)=>{typeof document>"u"||(document.cookie=S(t,"",{...n??{},maxAge:0}))}}),[])}function te(){let t=f?c.useContext(f):null;if(!t){let n=M();if(n)return n;if(typeof window>"u")return z;throw new Error("useRouter must be used inside mountWebframezClient()")}return t}function D({active:t}){return d("div",{style:{position:"fixed",top:0,left:0,width:"100%",height:3,zIndex:9999,transformOrigin:"left",transform:t?"scaleX(1)":"scaleX(0)",transition:"transform 180ms ease",background:"linear-gradient(90deg, #0ea5e9, #22c55e)"}})}function k(t){let n=document.createElement("meta");n.setAttribute("data-webframez-head","true");let e=Object.entries(t).filter(([,o])=>!!o);for(let[o,r]of e)n.setAttribute(o,String(r));document.head.appendChild(n)}function I(t){let n=document.createElement("link");n.setAttribute("data-webframez-head","true");let e=Object.entries(t).filter(([,o])=>!!o);for(let[o,r]of e)n.setAttribute(o,String(r));document.head.appendChild(n)}function b(t){if(typeof document>"u")return;let n=v(t)??t;document.title=n.title||"Webframez React";for(let e of document.head.querySelectorAll(B))e.remove();n.description&&k({name:"description",content:n.description}),n.favicon&&I({rel:"icon",href:n.favicon});for(let e of n.meta??[])k(e);for(let e of n.links??[])I(e)}function F(t){let n=new TextEncoder;return new ReadableStream({start(e){e.enqueue(n.encode(t)),e.close()}})}function G(){if(typeof window>"u")return null;let t=window.__RSC_INITIAL_PAYLOAD;return typeof t!="string"||t===""?null:(delete window.__RSC_INITIAL_PAYLOAD,N(F(t)))}function Y(t){return G()??P(fetch(`${t}?path=${encodeURIComponent(window.location.pathname)}&search=${encodeURIComponent(window.location.search)}`,{headers:{Accept:"text/x-component"}}))}function Z(t,n){return function(){let o=c.use(t),[r,a]=l(o.model),[s,g]=l(o.head),[U,h]=l(!1),[O,T]=l(!1);async function u(i,C="push"){h(!0);try{let p=await P(fetch(`${n}?path=${encodeURIComponent(i.pathname)}&search=${encodeURIComponent(i.search)}`,{headers:{Accept:"text/x-component"}}));b(p.head),g(p.head),a(p.model);let y=`${i.pathname}${i.search}`;C==="replace"?history.replaceState(null,"",y):C==="push"&&history.pushState(null,"",y)}catch(A){console.error("[webframez-react] Failed to render route",A),a(d("p",{children:"Failed to load route."}))}finally{h(!1)}}x(()=>{b(s)},[s]),x(()=>{T(!0);let i=()=>{u(new URL(window.location.href),"none")};return window.addEventListener("popstate",i),()=>{window.removeEventListener("popstate",i)}},[]);let w=c.useMemo(()=>({push:i=>{u(new URL(i,window.location.origin),"push")},replace:i=>{u(new URL(i,window.location.origin),"replace")},refresh:()=>{u(new URL(window.location.href),"none")}}),[]);W(w);let R=j(q,{children:[O?d(D,{active:U}):null,r??d("p",{style:{padding:24},children:"Loading..."})]});return f?d(f.Provider,{value:w,children:R}):R}}function ne(t={}){let n=t.rootId??"root",e=document.getElementById(n);if(!e)throw new Error(`Missing #${n} element`);let o=typeof window<"u"&&window.__RSC_ENDPOINT,r=t.rscEndpoint??o??"/rsc",a=Y(r),s=Z(a,r);return H(e,d(s,{}))}export{ne as mountWebframezClient,ee as useCookie,te as useRouter};
|
package/dist/http.cjs
CHANGED
|
@@ -150,6 +150,62 @@ var import_node_fs = __toESM(require("node:fs"), 1);
|
|
|
150
150
|
var import_node_module2 = __toESM(require("node:module"), 1);
|
|
151
151
|
var import_node_path2 = __toESM(require("node:path"), 1);
|
|
152
152
|
|
|
153
|
+
// src/head.ts
|
|
154
|
+
var ABSOLUTE_ASSET_URL_PATTERN = /^(?:[a-zA-Z][a-zA-Z\d+\-.]*:|\/\/|#)/;
|
|
155
|
+
function normalizeAssetsBaseUrl(value) {
|
|
156
|
+
const trimmed = value?.trim();
|
|
157
|
+
if (!trimmed) {
|
|
158
|
+
return void 0;
|
|
159
|
+
}
|
|
160
|
+
if (trimmed === "/") {
|
|
161
|
+
return "/";
|
|
162
|
+
}
|
|
163
|
+
return trimmed.replace(/\/+$/, "");
|
|
164
|
+
}
|
|
165
|
+
function resolveHeadAssetUrl(assetUrl, assetsBaseUrl) {
|
|
166
|
+
const normalizedAssetUrl = assetUrl.trim();
|
|
167
|
+
const normalizedAssetsBaseUrl = normalizeAssetsBaseUrl(assetsBaseUrl);
|
|
168
|
+
if (!normalizedAssetUrl || !normalizedAssetsBaseUrl) {
|
|
169
|
+
return normalizedAssetUrl;
|
|
170
|
+
}
|
|
171
|
+
if (ABSOLUTE_ASSET_URL_PATTERN.test(normalizedAssetUrl)) {
|
|
172
|
+
return normalizedAssetUrl;
|
|
173
|
+
}
|
|
174
|
+
if (normalizedAssetsBaseUrl !== "/" && (normalizedAssetUrl === normalizedAssetsBaseUrl || normalizedAssetUrl.startsWith(`${normalizedAssetsBaseUrl}/`))) {
|
|
175
|
+
return normalizedAssetUrl;
|
|
176
|
+
}
|
|
177
|
+
if (normalizedAssetsBaseUrl === "/") {
|
|
178
|
+
return normalizedAssetUrl.startsWith("/") ? normalizedAssetUrl : `/${normalizedAssetUrl}`;
|
|
179
|
+
}
|
|
180
|
+
if (normalizedAssetUrl.startsWith("/")) {
|
|
181
|
+
return `${normalizedAssetsBaseUrl}${normalizedAssetUrl}`;
|
|
182
|
+
}
|
|
183
|
+
return `${normalizedAssetsBaseUrl}/${normalizedAssetUrl}`;
|
|
184
|
+
}
|
|
185
|
+
function normalizeHeadConfig(head, inheritedAssetsBaseUrl) {
|
|
186
|
+
if (!head) {
|
|
187
|
+
return void 0;
|
|
188
|
+
}
|
|
189
|
+
const effectiveAssetsBaseUrl = normalizeAssetsBaseUrl(head.assetsBaseUrl) ?? normalizeAssetsBaseUrl(inheritedAssetsBaseUrl);
|
|
190
|
+
const normalizedHead = {
|
|
191
|
+
...head,
|
|
192
|
+
...effectiveAssetsBaseUrl ? { assetsBaseUrl: effectiveAssetsBaseUrl } : {}
|
|
193
|
+
};
|
|
194
|
+
if (normalizedHead.favicon) {
|
|
195
|
+
normalizedHead.favicon = resolveHeadAssetUrl(
|
|
196
|
+
normalizedHead.favicon,
|
|
197
|
+
effectiveAssetsBaseUrl
|
|
198
|
+
);
|
|
199
|
+
}
|
|
200
|
+
if (normalizedHead.links) {
|
|
201
|
+
normalizedHead.links = normalizedHead.links.map((link) => ({
|
|
202
|
+
...link,
|
|
203
|
+
href: resolveHeadAssetUrl(link.href, effectiveAssetsBaseUrl)
|
|
204
|
+
}));
|
|
205
|
+
}
|
|
206
|
+
return normalizedHead;
|
|
207
|
+
}
|
|
208
|
+
|
|
153
209
|
// src/router-runtime.tsx
|
|
154
210
|
var import_react = __toESM(require("react"), 1);
|
|
155
211
|
var ROUTE_CHILDREN_TAG = "webframez-route-children";
|
|
@@ -365,7 +421,8 @@ function mergeHead(...configs) {
|
|
|
365
421
|
meta: [],
|
|
366
422
|
links: []
|
|
367
423
|
};
|
|
368
|
-
for (const
|
|
424
|
+
for (const candidate of configs) {
|
|
425
|
+
const config = normalizeHeadConfig(candidate, merged.assetsBaseUrl);
|
|
369
426
|
if (!config) {
|
|
370
427
|
continue;
|
|
371
428
|
}
|
|
@@ -375,6 +432,9 @@ function mergeHead(...configs) {
|
|
|
375
432
|
if (config.description) {
|
|
376
433
|
merged.description = config.description;
|
|
377
434
|
}
|
|
435
|
+
if (config.assetsBaseUrl) {
|
|
436
|
+
merged.assetsBaseUrl = config.assetsBaseUrl;
|
|
437
|
+
}
|
|
378
438
|
if (config.favicon) {
|
|
379
439
|
merged.favicon = config.favicon;
|
|
380
440
|
}
|
|
@@ -388,22 +448,23 @@ function mergeHead(...configs) {
|
|
|
388
448
|
return merged;
|
|
389
449
|
}
|
|
390
450
|
function renderHeadToString(head) {
|
|
451
|
+
const normalizedHead = normalizeHeadConfig(head) ?? head;
|
|
391
452
|
const tags = [];
|
|
392
|
-
if (
|
|
453
|
+
if (normalizedHead.description) {
|
|
393
454
|
tags.push(
|
|
394
|
-
`<meta ${createManagedAttributes()} name="description" content="${escapeHtml(
|
|
455
|
+
`<meta ${createManagedAttributes()} name="description" content="${escapeHtml(normalizedHead.description)}" />`
|
|
395
456
|
);
|
|
396
457
|
}
|
|
397
|
-
if (
|
|
458
|
+
if (normalizedHead.favicon) {
|
|
398
459
|
tags.push(
|
|
399
|
-
`<link ${createManagedAttributes()} rel="icon" href="${escapeHtml(
|
|
460
|
+
`<link ${createManagedAttributes()} rel="icon" href="${escapeHtml(normalizedHead.favicon)}" />`
|
|
400
461
|
);
|
|
401
462
|
}
|
|
402
|
-
for (const meta of
|
|
463
|
+
for (const meta of normalizedHead.meta ?? []) {
|
|
403
464
|
const attrs = Object.entries(meta).filter(([, value]) => Boolean(value)).map(([key, value]) => `${key}="${escapeHtml(String(value))}"`).join(" ");
|
|
404
465
|
tags.push(`<meta ${createManagedAttributes()} ${attrs} />`);
|
|
405
466
|
}
|
|
406
|
-
for (const link of
|
|
467
|
+
for (const link of normalizedHead.links ?? []) {
|
|
407
468
|
const attrs = Object.entries(link).filter(([, value]) => Boolean(value)).map(([key, value]) => `${key}="${escapeHtml(String(value))}"`).join(" ");
|
|
408
469
|
tags.push(`<link ${createManagedAttributes()} ${attrs} />`);
|
|
409
470
|
}
|
package/dist/http.js
CHANGED
|
@@ -125,6 +125,62 @@ import fs from "node:fs";
|
|
|
125
125
|
import Module from "node:module";
|
|
126
126
|
import path2 from "node:path";
|
|
127
127
|
|
|
128
|
+
// src/head.ts
|
|
129
|
+
var ABSOLUTE_ASSET_URL_PATTERN = /^(?:[a-zA-Z][a-zA-Z\d+\-.]*:|\/\/|#)/;
|
|
130
|
+
function normalizeAssetsBaseUrl(value) {
|
|
131
|
+
const trimmed = value?.trim();
|
|
132
|
+
if (!trimmed) {
|
|
133
|
+
return void 0;
|
|
134
|
+
}
|
|
135
|
+
if (trimmed === "/") {
|
|
136
|
+
return "/";
|
|
137
|
+
}
|
|
138
|
+
return trimmed.replace(/\/+$/, "");
|
|
139
|
+
}
|
|
140
|
+
function resolveHeadAssetUrl(assetUrl, assetsBaseUrl) {
|
|
141
|
+
const normalizedAssetUrl = assetUrl.trim();
|
|
142
|
+
const normalizedAssetsBaseUrl = normalizeAssetsBaseUrl(assetsBaseUrl);
|
|
143
|
+
if (!normalizedAssetUrl || !normalizedAssetsBaseUrl) {
|
|
144
|
+
return normalizedAssetUrl;
|
|
145
|
+
}
|
|
146
|
+
if (ABSOLUTE_ASSET_URL_PATTERN.test(normalizedAssetUrl)) {
|
|
147
|
+
return normalizedAssetUrl;
|
|
148
|
+
}
|
|
149
|
+
if (normalizedAssetsBaseUrl !== "/" && (normalizedAssetUrl === normalizedAssetsBaseUrl || normalizedAssetUrl.startsWith(`${normalizedAssetsBaseUrl}/`))) {
|
|
150
|
+
return normalizedAssetUrl;
|
|
151
|
+
}
|
|
152
|
+
if (normalizedAssetsBaseUrl === "/") {
|
|
153
|
+
return normalizedAssetUrl.startsWith("/") ? normalizedAssetUrl : `/${normalizedAssetUrl}`;
|
|
154
|
+
}
|
|
155
|
+
if (normalizedAssetUrl.startsWith("/")) {
|
|
156
|
+
return `${normalizedAssetsBaseUrl}${normalizedAssetUrl}`;
|
|
157
|
+
}
|
|
158
|
+
return `${normalizedAssetsBaseUrl}/${normalizedAssetUrl}`;
|
|
159
|
+
}
|
|
160
|
+
function normalizeHeadConfig(head, inheritedAssetsBaseUrl) {
|
|
161
|
+
if (!head) {
|
|
162
|
+
return void 0;
|
|
163
|
+
}
|
|
164
|
+
const effectiveAssetsBaseUrl = normalizeAssetsBaseUrl(head.assetsBaseUrl) ?? normalizeAssetsBaseUrl(inheritedAssetsBaseUrl);
|
|
165
|
+
const normalizedHead = {
|
|
166
|
+
...head,
|
|
167
|
+
...effectiveAssetsBaseUrl ? { assetsBaseUrl: effectiveAssetsBaseUrl } : {}
|
|
168
|
+
};
|
|
169
|
+
if (normalizedHead.favicon) {
|
|
170
|
+
normalizedHead.favicon = resolveHeadAssetUrl(
|
|
171
|
+
normalizedHead.favicon,
|
|
172
|
+
effectiveAssetsBaseUrl
|
|
173
|
+
);
|
|
174
|
+
}
|
|
175
|
+
if (normalizedHead.links) {
|
|
176
|
+
normalizedHead.links = normalizedHead.links.map((link) => ({
|
|
177
|
+
...link,
|
|
178
|
+
href: resolveHeadAssetUrl(link.href, effectiveAssetsBaseUrl)
|
|
179
|
+
}));
|
|
180
|
+
}
|
|
181
|
+
return normalizedHead;
|
|
182
|
+
}
|
|
183
|
+
|
|
128
184
|
// src/router-runtime.tsx
|
|
129
185
|
import React from "react";
|
|
130
186
|
var ROUTE_CHILDREN_TAG = "webframez-route-children";
|
|
@@ -340,7 +396,8 @@ function mergeHead(...configs) {
|
|
|
340
396
|
meta: [],
|
|
341
397
|
links: []
|
|
342
398
|
};
|
|
343
|
-
for (const
|
|
399
|
+
for (const candidate of configs) {
|
|
400
|
+
const config = normalizeHeadConfig(candidate, merged.assetsBaseUrl);
|
|
344
401
|
if (!config) {
|
|
345
402
|
continue;
|
|
346
403
|
}
|
|
@@ -350,6 +407,9 @@ function mergeHead(...configs) {
|
|
|
350
407
|
if (config.description) {
|
|
351
408
|
merged.description = config.description;
|
|
352
409
|
}
|
|
410
|
+
if (config.assetsBaseUrl) {
|
|
411
|
+
merged.assetsBaseUrl = config.assetsBaseUrl;
|
|
412
|
+
}
|
|
353
413
|
if (config.favicon) {
|
|
354
414
|
merged.favicon = config.favicon;
|
|
355
415
|
}
|
|
@@ -363,22 +423,23 @@ function mergeHead(...configs) {
|
|
|
363
423
|
return merged;
|
|
364
424
|
}
|
|
365
425
|
function renderHeadToString(head) {
|
|
426
|
+
const normalizedHead = normalizeHeadConfig(head) ?? head;
|
|
366
427
|
const tags = [];
|
|
367
|
-
if (
|
|
428
|
+
if (normalizedHead.description) {
|
|
368
429
|
tags.push(
|
|
369
|
-
`<meta ${createManagedAttributes()} name="description" content="${escapeHtml(
|
|
430
|
+
`<meta ${createManagedAttributes()} name="description" content="${escapeHtml(normalizedHead.description)}" />`
|
|
370
431
|
);
|
|
371
432
|
}
|
|
372
|
-
if (
|
|
433
|
+
if (normalizedHead.favicon) {
|
|
373
434
|
tags.push(
|
|
374
|
-
`<link ${createManagedAttributes()} rel="icon" href="${escapeHtml(
|
|
435
|
+
`<link ${createManagedAttributes()} rel="icon" href="${escapeHtml(normalizedHead.favicon)}" />`
|
|
375
436
|
);
|
|
376
437
|
}
|
|
377
|
-
for (const meta of
|
|
438
|
+
for (const meta of normalizedHead.meta ?? []) {
|
|
378
439
|
const attrs = Object.entries(meta).filter(([, value]) => Boolean(value)).map(([key, value]) => `${key}="${escapeHtml(String(value))}"`).join(" ");
|
|
379
440
|
tags.push(`<meta ${createManagedAttributes()} ${attrs} />`);
|
|
380
441
|
}
|
|
381
|
-
for (const link of
|
|
442
|
+
for (const link of normalizedHead.links ?? []) {
|
|
382
443
|
const attrs = Object.entries(link).filter(([, value]) => Boolean(value)).map(([key, value]) => `${key}="${escapeHtml(String(value))}"`).join(" ");
|
|
383
444
|
tags.push(`<link ${createManagedAttributes()} ${attrs} />`);
|
|
384
445
|
}
|
package/dist/index.cjs
CHANGED
|
@@ -183,6 +183,62 @@ var import_node_fs = __toESM(require("node:fs"), 1);
|
|
|
183
183
|
var import_node_module2 = __toESM(require("node:module"), 1);
|
|
184
184
|
var import_node_path2 = __toESM(require("node:path"), 1);
|
|
185
185
|
|
|
186
|
+
// src/head.ts
|
|
187
|
+
var ABSOLUTE_ASSET_URL_PATTERN = /^(?:[a-zA-Z][a-zA-Z\d+\-.]*:|\/\/|#)/;
|
|
188
|
+
function normalizeAssetsBaseUrl(value) {
|
|
189
|
+
const trimmed = value?.trim();
|
|
190
|
+
if (!trimmed) {
|
|
191
|
+
return void 0;
|
|
192
|
+
}
|
|
193
|
+
if (trimmed === "/") {
|
|
194
|
+
return "/";
|
|
195
|
+
}
|
|
196
|
+
return trimmed.replace(/\/+$/, "");
|
|
197
|
+
}
|
|
198
|
+
function resolveHeadAssetUrl(assetUrl, assetsBaseUrl) {
|
|
199
|
+
const normalizedAssetUrl = assetUrl.trim();
|
|
200
|
+
const normalizedAssetsBaseUrl = normalizeAssetsBaseUrl(assetsBaseUrl);
|
|
201
|
+
if (!normalizedAssetUrl || !normalizedAssetsBaseUrl) {
|
|
202
|
+
return normalizedAssetUrl;
|
|
203
|
+
}
|
|
204
|
+
if (ABSOLUTE_ASSET_URL_PATTERN.test(normalizedAssetUrl)) {
|
|
205
|
+
return normalizedAssetUrl;
|
|
206
|
+
}
|
|
207
|
+
if (normalizedAssetsBaseUrl !== "/" && (normalizedAssetUrl === normalizedAssetsBaseUrl || normalizedAssetUrl.startsWith(`${normalizedAssetsBaseUrl}/`))) {
|
|
208
|
+
return normalizedAssetUrl;
|
|
209
|
+
}
|
|
210
|
+
if (normalizedAssetsBaseUrl === "/") {
|
|
211
|
+
return normalizedAssetUrl.startsWith("/") ? normalizedAssetUrl : `/${normalizedAssetUrl}`;
|
|
212
|
+
}
|
|
213
|
+
if (normalizedAssetUrl.startsWith("/")) {
|
|
214
|
+
return `${normalizedAssetsBaseUrl}${normalizedAssetUrl}`;
|
|
215
|
+
}
|
|
216
|
+
return `${normalizedAssetsBaseUrl}/${normalizedAssetUrl}`;
|
|
217
|
+
}
|
|
218
|
+
function normalizeHeadConfig(head, inheritedAssetsBaseUrl) {
|
|
219
|
+
if (!head) {
|
|
220
|
+
return void 0;
|
|
221
|
+
}
|
|
222
|
+
const effectiveAssetsBaseUrl = normalizeAssetsBaseUrl(head.assetsBaseUrl) ?? normalizeAssetsBaseUrl(inheritedAssetsBaseUrl);
|
|
223
|
+
const normalizedHead = {
|
|
224
|
+
...head,
|
|
225
|
+
...effectiveAssetsBaseUrl ? { assetsBaseUrl: effectiveAssetsBaseUrl } : {}
|
|
226
|
+
};
|
|
227
|
+
if (normalizedHead.favicon) {
|
|
228
|
+
normalizedHead.favicon = resolveHeadAssetUrl(
|
|
229
|
+
normalizedHead.favicon,
|
|
230
|
+
effectiveAssetsBaseUrl
|
|
231
|
+
);
|
|
232
|
+
}
|
|
233
|
+
if (normalizedHead.links) {
|
|
234
|
+
normalizedHead.links = normalizedHead.links.map((link) => ({
|
|
235
|
+
...link,
|
|
236
|
+
href: resolveHeadAssetUrl(link.href, effectiveAssetsBaseUrl)
|
|
237
|
+
}));
|
|
238
|
+
}
|
|
239
|
+
return normalizedHead;
|
|
240
|
+
}
|
|
241
|
+
|
|
186
242
|
// src/router-runtime.tsx
|
|
187
243
|
var import_react = __toESM(require("react"), 1);
|
|
188
244
|
var ROUTE_CHILDREN_TAG = "webframez-route-children";
|
|
@@ -398,7 +454,8 @@ function mergeHead(...configs) {
|
|
|
398
454
|
meta: [],
|
|
399
455
|
links: []
|
|
400
456
|
};
|
|
401
|
-
for (const
|
|
457
|
+
for (const candidate of configs) {
|
|
458
|
+
const config = normalizeHeadConfig(candidate, merged.assetsBaseUrl);
|
|
402
459
|
if (!config) {
|
|
403
460
|
continue;
|
|
404
461
|
}
|
|
@@ -408,6 +465,9 @@ function mergeHead(...configs) {
|
|
|
408
465
|
if (config.description) {
|
|
409
466
|
merged.description = config.description;
|
|
410
467
|
}
|
|
468
|
+
if (config.assetsBaseUrl) {
|
|
469
|
+
merged.assetsBaseUrl = config.assetsBaseUrl;
|
|
470
|
+
}
|
|
411
471
|
if (config.favicon) {
|
|
412
472
|
merged.favicon = config.favicon;
|
|
413
473
|
}
|
|
@@ -421,22 +481,23 @@ function mergeHead(...configs) {
|
|
|
421
481
|
return merged;
|
|
422
482
|
}
|
|
423
483
|
function renderHeadToString(head) {
|
|
484
|
+
const normalizedHead = normalizeHeadConfig(head) ?? head;
|
|
424
485
|
const tags = [];
|
|
425
|
-
if (
|
|
486
|
+
if (normalizedHead.description) {
|
|
426
487
|
tags.push(
|
|
427
|
-
`<meta ${createManagedAttributes()} name="description" content="${escapeHtml(
|
|
488
|
+
`<meta ${createManagedAttributes()} name="description" content="${escapeHtml(normalizedHead.description)}" />`
|
|
428
489
|
);
|
|
429
490
|
}
|
|
430
|
-
if (
|
|
491
|
+
if (normalizedHead.favicon) {
|
|
431
492
|
tags.push(
|
|
432
|
-
`<link ${createManagedAttributes()} rel="icon" href="${escapeHtml(
|
|
493
|
+
`<link ${createManagedAttributes()} rel="icon" href="${escapeHtml(normalizedHead.favicon)}" />`
|
|
433
494
|
);
|
|
434
495
|
}
|
|
435
|
-
for (const meta of
|
|
496
|
+
for (const meta of normalizedHead.meta ?? []) {
|
|
436
497
|
const attrs = Object.entries(meta).filter(([, value]) => Boolean(value)).map(([key, value]) => `${key}="${escapeHtml(String(value))}"`).join(" ");
|
|
437
498
|
tags.push(`<meta ${createManagedAttributes()} ${attrs} />`);
|
|
438
499
|
}
|
|
439
|
-
for (const link of
|
|
500
|
+
for (const link of normalizedHead.links ?? []) {
|
|
440
501
|
const attrs = Object.entries(link).filter(([, value]) => Boolean(value)).map(([key, value]) => `${key}="${escapeHtml(String(value))}"`).join(" ");
|
|
441
502
|
tags.push(`<link ${createManagedAttributes()} ${attrs} />`);
|
|
442
503
|
}
|
package/dist/index.js
CHANGED
|
@@ -147,6 +147,62 @@ import fs from "node:fs";
|
|
|
147
147
|
import Module from "node:module";
|
|
148
148
|
import path2 from "node:path";
|
|
149
149
|
|
|
150
|
+
// src/head.ts
|
|
151
|
+
var ABSOLUTE_ASSET_URL_PATTERN = /^(?:[a-zA-Z][a-zA-Z\d+\-.]*:|\/\/|#)/;
|
|
152
|
+
function normalizeAssetsBaseUrl(value) {
|
|
153
|
+
const trimmed = value?.trim();
|
|
154
|
+
if (!trimmed) {
|
|
155
|
+
return void 0;
|
|
156
|
+
}
|
|
157
|
+
if (trimmed === "/") {
|
|
158
|
+
return "/";
|
|
159
|
+
}
|
|
160
|
+
return trimmed.replace(/\/+$/, "");
|
|
161
|
+
}
|
|
162
|
+
function resolveHeadAssetUrl(assetUrl, assetsBaseUrl) {
|
|
163
|
+
const normalizedAssetUrl = assetUrl.trim();
|
|
164
|
+
const normalizedAssetsBaseUrl = normalizeAssetsBaseUrl(assetsBaseUrl);
|
|
165
|
+
if (!normalizedAssetUrl || !normalizedAssetsBaseUrl) {
|
|
166
|
+
return normalizedAssetUrl;
|
|
167
|
+
}
|
|
168
|
+
if (ABSOLUTE_ASSET_URL_PATTERN.test(normalizedAssetUrl)) {
|
|
169
|
+
return normalizedAssetUrl;
|
|
170
|
+
}
|
|
171
|
+
if (normalizedAssetsBaseUrl !== "/" && (normalizedAssetUrl === normalizedAssetsBaseUrl || normalizedAssetUrl.startsWith(`${normalizedAssetsBaseUrl}/`))) {
|
|
172
|
+
return normalizedAssetUrl;
|
|
173
|
+
}
|
|
174
|
+
if (normalizedAssetsBaseUrl === "/") {
|
|
175
|
+
return normalizedAssetUrl.startsWith("/") ? normalizedAssetUrl : `/${normalizedAssetUrl}`;
|
|
176
|
+
}
|
|
177
|
+
if (normalizedAssetUrl.startsWith("/")) {
|
|
178
|
+
return `${normalizedAssetsBaseUrl}${normalizedAssetUrl}`;
|
|
179
|
+
}
|
|
180
|
+
return `${normalizedAssetsBaseUrl}/${normalizedAssetUrl}`;
|
|
181
|
+
}
|
|
182
|
+
function normalizeHeadConfig(head, inheritedAssetsBaseUrl) {
|
|
183
|
+
if (!head) {
|
|
184
|
+
return void 0;
|
|
185
|
+
}
|
|
186
|
+
const effectiveAssetsBaseUrl = normalizeAssetsBaseUrl(head.assetsBaseUrl) ?? normalizeAssetsBaseUrl(inheritedAssetsBaseUrl);
|
|
187
|
+
const normalizedHead = {
|
|
188
|
+
...head,
|
|
189
|
+
...effectiveAssetsBaseUrl ? { assetsBaseUrl: effectiveAssetsBaseUrl } : {}
|
|
190
|
+
};
|
|
191
|
+
if (normalizedHead.favicon) {
|
|
192
|
+
normalizedHead.favicon = resolveHeadAssetUrl(
|
|
193
|
+
normalizedHead.favicon,
|
|
194
|
+
effectiveAssetsBaseUrl
|
|
195
|
+
);
|
|
196
|
+
}
|
|
197
|
+
if (normalizedHead.links) {
|
|
198
|
+
normalizedHead.links = normalizedHead.links.map((link) => ({
|
|
199
|
+
...link,
|
|
200
|
+
href: resolveHeadAssetUrl(link.href, effectiveAssetsBaseUrl)
|
|
201
|
+
}));
|
|
202
|
+
}
|
|
203
|
+
return normalizedHead;
|
|
204
|
+
}
|
|
205
|
+
|
|
150
206
|
// src/router-runtime.tsx
|
|
151
207
|
import React from "react";
|
|
152
208
|
var ROUTE_CHILDREN_TAG = "webframez-route-children";
|
|
@@ -362,7 +418,8 @@ function mergeHead(...configs) {
|
|
|
362
418
|
meta: [],
|
|
363
419
|
links: []
|
|
364
420
|
};
|
|
365
|
-
for (const
|
|
421
|
+
for (const candidate of configs) {
|
|
422
|
+
const config = normalizeHeadConfig(candidate, merged.assetsBaseUrl);
|
|
366
423
|
if (!config) {
|
|
367
424
|
continue;
|
|
368
425
|
}
|
|
@@ -372,6 +429,9 @@ function mergeHead(...configs) {
|
|
|
372
429
|
if (config.description) {
|
|
373
430
|
merged.description = config.description;
|
|
374
431
|
}
|
|
432
|
+
if (config.assetsBaseUrl) {
|
|
433
|
+
merged.assetsBaseUrl = config.assetsBaseUrl;
|
|
434
|
+
}
|
|
375
435
|
if (config.favicon) {
|
|
376
436
|
merged.favicon = config.favicon;
|
|
377
437
|
}
|
|
@@ -385,22 +445,23 @@ function mergeHead(...configs) {
|
|
|
385
445
|
return merged;
|
|
386
446
|
}
|
|
387
447
|
function renderHeadToString(head) {
|
|
448
|
+
const normalizedHead = normalizeHeadConfig(head) ?? head;
|
|
388
449
|
const tags = [];
|
|
389
|
-
if (
|
|
450
|
+
if (normalizedHead.description) {
|
|
390
451
|
tags.push(
|
|
391
|
-
`<meta ${createManagedAttributes()} name="description" content="${escapeHtml(
|
|
452
|
+
`<meta ${createManagedAttributes()} name="description" content="${escapeHtml(normalizedHead.description)}" />`
|
|
392
453
|
);
|
|
393
454
|
}
|
|
394
|
-
if (
|
|
455
|
+
if (normalizedHead.favicon) {
|
|
395
456
|
tags.push(
|
|
396
|
-
`<link ${createManagedAttributes()} rel="icon" href="${escapeHtml(
|
|
457
|
+
`<link ${createManagedAttributes()} rel="icon" href="${escapeHtml(normalizedHead.favicon)}" />`
|
|
397
458
|
);
|
|
398
459
|
}
|
|
399
|
-
for (const meta of
|
|
460
|
+
for (const meta of normalizedHead.meta ?? []) {
|
|
400
461
|
const attrs = Object.entries(meta).filter(([, value]) => Boolean(value)).map(([key, value]) => `${key}="${escapeHtml(String(value))}"`).join(" ");
|
|
401
462
|
tags.push(`<meta ${createManagedAttributes()} ${attrs} />`);
|
|
402
463
|
}
|
|
403
|
-
for (const link of
|
|
464
|
+
for (const link of normalizedHead.links ?? []) {
|
|
404
465
|
const attrs = Object.entries(link).filter(([, value]) => Boolean(value)).map(([key, value]) => `${key}="${escapeHtml(String(value))}"`).join(" ");
|
|
405
466
|
tags.push(`<link ${createManagedAttributes()} ${attrs} />`);
|
|
406
467
|
}
|
package/dist/router.cjs
CHANGED
|
@@ -41,6 +41,62 @@ var import_node_fs = __toESM(require("node:fs"), 1);
|
|
|
41
41
|
var import_node_module = __toESM(require("node:module"), 1);
|
|
42
42
|
var import_node_path = __toESM(require("node:path"), 1);
|
|
43
43
|
|
|
44
|
+
// src/head.ts
|
|
45
|
+
var ABSOLUTE_ASSET_URL_PATTERN = /^(?:[a-zA-Z][a-zA-Z\d+\-.]*:|\/\/|#)/;
|
|
46
|
+
function normalizeAssetsBaseUrl(value) {
|
|
47
|
+
const trimmed = value?.trim();
|
|
48
|
+
if (!trimmed) {
|
|
49
|
+
return void 0;
|
|
50
|
+
}
|
|
51
|
+
if (trimmed === "/") {
|
|
52
|
+
return "/";
|
|
53
|
+
}
|
|
54
|
+
return trimmed.replace(/\/+$/, "");
|
|
55
|
+
}
|
|
56
|
+
function resolveHeadAssetUrl(assetUrl, assetsBaseUrl) {
|
|
57
|
+
const normalizedAssetUrl = assetUrl.trim();
|
|
58
|
+
const normalizedAssetsBaseUrl = normalizeAssetsBaseUrl(assetsBaseUrl);
|
|
59
|
+
if (!normalizedAssetUrl || !normalizedAssetsBaseUrl) {
|
|
60
|
+
return normalizedAssetUrl;
|
|
61
|
+
}
|
|
62
|
+
if (ABSOLUTE_ASSET_URL_PATTERN.test(normalizedAssetUrl)) {
|
|
63
|
+
return normalizedAssetUrl;
|
|
64
|
+
}
|
|
65
|
+
if (normalizedAssetsBaseUrl !== "/" && (normalizedAssetUrl === normalizedAssetsBaseUrl || normalizedAssetUrl.startsWith(`${normalizedAssetsBaseUrl}/`))) {
|
|
66
|
+
return normalizedAssetUrl;
|
|
67
|
+
}
|
|
68
|
+
if (normalizedAssetsBaseUrl === "/") {
|
|
69
|
+
return normalizedAssetUrl.startsWith("/") ? normalizedAssetUrl : `/${normalizedAssetUrl}`;
|
|
70
|
+
}
|
|
71
|
+
if (normalizedAssetUrl.startsWith("/")) {
|
|
72
|
+
return `${normalizedAssetsBaseUrl}${normalizedAssetUrl}`;
|
|
73
|
+
}
|
|
74
|
+
return `${normalizedAssetsBaseUrl}/${normalizedAssetUrl}`;
|
|
75
|
+
}
|
|
76
|
+
function normalizeHeadConfig(head, inheritedAssetsBaseUrl) {
|
|
77
|
+
if (!head) {
|
|
78
|
+
return void 0;
|
|
79
|
+
}
|
|
80
|
+
const effectiveAssetsBaseUrl = normalizeAssetsBaseUrl(head.assetsBaseUrl) ?? normalizeAssetsBaseUrl(inheritedAssetsBaseUrl);
|
|
81
|
+
const normalizedHead = {
|
|
82
|
+
...head,
|
|
83
|
+
...effectiveAssetsBaseUrl ? { assetsBaseUrl: effectiveAssetsBaseUrl } : {}
|
|
84
|
+
};
|
|
85
|
+
if (normalizedHead.favicon) {
|
|
86
|
+
normalizedHead.favicon = resolveHeadAssetUrl(
|
|
87
|
+
normalizedHead.favicon,
|
|
88
|
+
effectiveAssetsBaseUrl
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
if (normalizedHead.links) {
|
|
92
|
+
normalizedHead.links = normalizedHead.links.map((link) => ({
|
|
93
|
+
...link,
|
|
94
|
+
href: resolveHeadAssetUrl(link.href, effectiveAssetsBaseUrl)
|
|
95
|
+
}));
|
|
96
|
+
}
|
|
97
|
+
return normalizedHead;
|
|
98
|
+
}
|
|
99
|
+
|
|
44
100
|
// src/router-runtime.tsx
|
|
45
101
|
var import_react = __toESM(require("react"), 1);
|
|
46
102
|
var ROUTE_CHILDREN_TAG = "webframez-route-children";
|
|
@@ -256,7 +312,8 @@ function mergeHead(...configs) {
|
|
|
256
312
|
meta: [],
|
|
257
313
|
links: []
|
|
258
314
|
};
|
|
259
|
-
for (const
|
|
315
|
+
for (const candidate of configs) {
|
|
316
|
+
const config = normalizeHeadConfig(candidate, merged.assetsBaseUrl);
|
|
260
317
|
if (!config) {
|
|
261
318
|
continue;
|
|
262
319
|
}
|
|
@@ -266,6 +323,9 @@ function mergeHead(...configs) {
|
|
|
266
323
|
if (config.description) {
|
|
267
324
|
merged.description = config.description;
|
|
268
325
|
}
|
|
326
|
+
if (config.assetsBaseUrl) {
|
|
327
|
+
merged.assetsBaseUrl = config.assetsBaseUrl;
|
|
328
|
+
}
|
|
269
329
|
if (config.favicon) {
|
|
270
330
|
merged.favicon = config.favicon;
|
|
271
331
|
}
|
|
@@ -279,22 +339,23 @@ function mergeHead(...configs) {
|
|
|
279
339
|
return merged;
|
|
280
340
|
}
|
|
281
341
|
function renderHeadToString(head) {
|
|
342
|
+
const normalizedHead = normalizeHeadConfig(head) ?? head;
|
|
282
343
|
const tags = [];
|
|
283
|
-
if (
|
|
344
|
+
if (normalizedHead.description) {
|
|
284
345
|
tags.push(
|
|
285
|
-
`<meta ${createManagedAttributes()} name="description" content="${escapeHtml(
|
|
346
|
+
`<meta ${createManagedAttributes()} name="description" content="${escapeHtml(normalizedHead.description)}" />`
|
|
286
347
|
);
|
|
287
348
|
}
|
|
288
|
-
if (
|
|
349
|
+
if (normalizedHead.favicon) {
|
|
289
350
|
tags.push(
|
|
290
|
-
`<link ${createManagedAttributes()} rel="icon" href="${escapeHtml(
|
|
351
|
+
`<link ${createManagedAttributes()} rel="icon" href="${escapeHtml(normalizedHead.favicon)}" />`
|
|
291
352
|
);
|
|
292
353
|
}
|
|
293
|
-
for (const meta of
|
|
354
|
+
for (const meta of normalizedHead.meta ?? []) {
|
|
294
355
|
const attrs = Object.entries(meta).filter(([, value]) => Boolean(value)).map(([key, value]) => `${key}="${escapeHtml(String(value))}"`).join(" ");
|
|
295
356
|
tags.push(`<meta ${createManagedAttributes()} ${attrs} />`);
|
|
296
357
|
}
|
|
297
|
-
for (const link of
|
|
358
|
+
for (const link of normalizedHead.links ?? []) {
|
|
298
359
|
const attrs = Object.entries(link).filter(([, value]) => Boolean(value)).map(([key, value]) => `${key}="${escapeHtml(String(value))}"`).join(" ");
|
|
299
360
|
tags.push(`<link ${createManagedAttributes()} ${attrs} />`);
|
|
300
361
|
}
|
package/dist/router.js
CHANGED
|
@@ -11,6 +11,62 @@ import fs from "node:fs";
|
|
|
11
11
|
import Module from "node:module";
|
|
12
12
|
import path from "node:path";
|
|
13
13
|
|
|
14
|
+
// src/head.ts
|
|
15
|
+
var ABSOLUTE_ASSET_URL_PATTERN = /^(?:[a-zA-Z][a-zA-Z\d+\-.]*:|\/\/|#)/;
|
|
16
|
+
function normalizeAssetsBaseUrl(value) {
|
|
17
|
+
const trimmed = value?.trim();
|
|
18
|
+
if (!trimmed) {
|
|
19
|
+
return void 0;
|
|
20
|
+
}
|
|
21
|
+
if (trimmed === "/") {
|
|
22
|
+
return "/";
|
|
23
|
+
}
|
|
24
|
+
return trimmed.replace(/\/+$/, "");
|
|
25
|
+
}
|
|
26
|
+
function resolveHeadAssetUrl(assetUrl, assetsBaseUrl) {
|
|
27
|
+
const normalizedAssetUrl = assetUrl.trim();
|
|
28
|
+
const normalizedAssetsBaseUrl = normalizeAssetsBaseUrl(assetsBaseUrl);
|
|
29
|
+
if (!normalizedAssetUrl || !normalizedAssetsBaseUrl) {
|
|
30
|
+
return normalizedAssetUrl;
|
|
31
|
+
}
|
|
32
|
+
if (ABSOLUTE_ASSET_URL_PATTERN.test(normalizedAssetUrl)) {
|
|
33
|
+
return normalizedAssetUrl;
|
|
34
|
+
}
|
|
35
|
+
if (normalizedAssetsBaseUrl !== "/" && (normalizedAssetUrl === normalizedAssetsBaseUrl || normalizedAssetUrl.startsWith(`${normalizedAssetsBaseUrl}/`))) {
|
|
36
|
+
return normalizedAssetUrl;
|
|
37
|
+
}
|
|
38
|
+
if (normalizedAssetsBaseUrl === "/") {
|
|
39
|
+
return normalizedAssetUrl.startsWith("/") ? normalizedAssetUrl : `/${normalizedAssetUrl}`;
|
|
40
|
+
}
|
|
41
|
+
if (normalizedAssetUrl.startsWith("/")) {
|
|
42
|
+
return `${normalizedAssetsBaseUrl}${normalizedAssetUrl}`;
|
|
43
|
+
}
|
|
44
|
+
return `${normalizedAssetsBaseUrl}/${normalizedAssetUrl}`;
|
|
45
|
+
}
|
|
46
|
+
function normalizeHeadConfig(head, inheritedAssetsBaseUrl) {
|
|
47
|
+
if (!head) {
|
|
48
|
+
return void 0;
|
|
49
|
+
}
|
|
50
|
+
const effectiveAssetsBaseUrl = normalizeAssetsBaseUrl(head.assetsBaseUrl) ?? normalizeAssetsBaseUrl(inheritedAssetsBaseUrl);
|
|
51
|
+
const normalizedHead = {
|
|
52
|
+
...head,
|
|
53
|
+
...effectiveAssetsBaseUrl ? { assetsBaseUrl: effectiveAssetsBaseUrl } : {}
|
|
54
|
+
};
|
|
55
|
+
if (normalizedHead.favicon) {
|
|
56
|
+
normalizedHead.favicon = resolveHeadAssetUrl(
|
|
57
|
+
normalizedHead.favicon,
|
|
58
|
+
effectiveAssetsBaseUrl
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
if (normalizedHead.links) {
|
|
62
|
+
normalizedHead.links = normalizedHead.links.map((link) => ({
|
|
63
|
+
...link,
|
|
64
|
+
href: resolveHeadAssetUrl(link.href, effectiveAssetsBaseUrl)
|
|
65
|
+
}));
|
|
66
|
+
}
|
|
67
|
+
return normalizedHead;
|
|
68
|
+
}
|
|
69
|
+
|
|
14
70
|
// src/router-runtime.tsx
|
|
15
71
|
import React from "react";
|
|
16
72
|
var ROUTE_CHILDREN_TAG = "webframez-route-children";
|
|
@@ -226,7 +282,8 @@ function mergeHead(...configs) {
|
|
|
226
282
|
meta: [],
|
|
227
283
|
links: []
|
|
228
284
|
};
|
|
229
|
-
for (const
|
|
285
|
+
for (const candidate of configs) {
|
|
286
|
+
const config = normalizeHeadConfig(candidate, merged.assetsBaseUrl);
|
|
230
287
|
if (!config) {
|
|
231
288
|
continue;
|
|
232
289
|
}
|
|
@@ -236,6 +293,9 @@ function mergeHead(...configs) {
|
|
|
236
293
|
if (config.description) {
|
|
237
294
|
merged.description = config.description;
|
|
238
295
|
}
|
|
296
|
+
if (config.assetsBaseUrl) {
|
|
297
|
+
merged.assetsBaseUrl = config.assetsBaseUrl;
|
|
298
|
+
}
|
|
239
299
|
if (config.favicon) {
|
|
240
300
|
merged.favicon = config.favicon;
|
|
241
301
|
}
|
|
@@ -249,22 +309,23 @@ function mergeHead(...configs) {
|
|
|
249
309
|
return merged;
|
|
250
310
|
}
|
|
251
311
|
function renderHeadToString(head) {
|
|
312
|
+
const normalizedHead = normalizeHeadConfig(head) ?? head;
|
|
252
313
|
const tags = [];
|
|
253
|
-
if (
|
|
314
|
+
if (normalizedHead.description) {
|
|
254
315
|
tags.push(
|
|
255
|
-
`<meta ${createManagedAttributes()} name="description" content="${escapeHtml(
|
|
316
|
+
`<meta ${createManagedAttributes()} name="description" content="${escapeHtml(normalizedHead.description)}" />`
|
|
256
317
|
);
|
|
257
318
|
}
|
|
258
|
-
if (
|
|
319
|
+
if (normalizedHead.favicon) {
|
|
259
320
|
tags.push(
|
|
260
|
-
`<link ${createManagedAttributes()} rel="icon" href="${escapeHtml(
|
|
321
|
+
`<link ${createManagedAttributes()} rel="icon" href="${escapeHtml(normalizedHead.favicon)}" />`
|
|
261
322
|
);
|
|
262
323
|
}
|
|
263
|
-
for (const meta of
|
|
324
|
+
for (const meta of normalizedHead.meta ?? []) {
|
|
264
325
|
const attrs = Object.entries(meta).filter(([, value]) => Boolean(value)).map(([key, value]) => `${key}="${escapeHtml(String(value))}"`).join(" ");
|
|
265
326
|
tags.push(`<meta ${createManagedAttributes()} ${attrs} />`);
|
|
266
327
|
}
|
|
267
|
-
for (const link of
|
|
328
|
+
for (const link of normalizedHead.links ?? []) {
|
|
268
329
|
const attrs = Object.entries(link).filter(([, value]) => Boolean(value)).map(([key, value]) => `${key}="${escapeHtml(String(value))}"`).join(" ");
|
|
269
330
|
tags.push(`<link ${createManagedAttributes()} ${attrs} />`);
|
|
270
331
|
}
|
package/dist/types.d.ts
CHANGED
|
@@ -9,7 +9,7 @@ export type AbortRouteOptions = {
|
|
|
9
9
|
payload?: unknown;
|
|
10
10
|
};
|
|
11
11
|
|
|
12
|
-
export type RouteContext<TData =
|
|
12
|
+
export type RouteContext<TData = any> = {
|
|
13
13
|
pathname: string;
|
|
14
14
|
params: RouteParams;
|
|
15
15
|
searchParams: RouteSearchParams;
|
|
@@ -22,11 +22,11 @@ export type InferPageData<TDataResolver> =
|
|
|
22
22
|
TDataResolver extends (...args: any[]) => any
|
|
23
23
|
? Awaited<ReturnType<TDataResolver>>
|
|
24
24
|
: TDataResolver;
|
|
25
|
-
export type PageProps<TData =
|
|
25
|
+
export type PageProps<TData = any> = RouteContext<InferPageData<TData>>;
|
|
26
26
|
export type PagePropsFromData<TDataResolver extends (...args: any[]) => any> =
|
|
27
27
|
PageProps<InferPageData<TDataResolver>>;
|
|
28
28
|
|
|
29
|
-
export type ErrorPageProps<TData =
|
|
29
|
+
export type ErrorPageProps<TData = any> = RouteContext<TData> & {
|
|
30
30
|
statusCode: number;
|
|
31
31
|
message: string;
|
|
32
32
|
payload?: unknown;
|
|
@@ -51,6 +51,7 @@ export type HeadLinkTag = {
|
|
|
51
51
|
export type HeadConfig = {
|
|
52
52
|
title?: string;
|
|
53
53
|
description?: string;
|
|
54
|
+
assetsBaseUrl?: string;
|
|
54
55
|
favicon?: string;
|
|
55
56
|
meta?: HeadMetaTag[];
|
|
56
57
|
links?: HeadLinkTag[];
|
|
@@ -65,18 +66,18 @@ export type HeadResolver<TContext = RouteContext> = (
|
|
|
65
66
|
context: TContext
|
|
66
67
|
) => HeadConfig | Promise<HeadConfig>;
|
|
67
68
|
|
|
68
|
-
export type PageDataResolver<TData =
|
|
69
|
+
export type PageDataResolver<TData = any> = (
|
|
69
70
|
context: RouteContext
|
|
70
71
|
) => TData | Promise<TData>;
|
|
71
72
|
|
|
72
73
|
export type RouteMiddlewareResult = Record<string, unknown> | undefined | void;
|
|
73
|
-
export type RouteMiddlewareResolver<TData =
|
|
74
|
+
export type RouteMiddlewareResolver<TData = any> = (
|
|
74
75
|
context: RouteContext<TData>
|
|
75
76
|
) => RouteMiddlewareResult | Promise<RouteMiddlewareResult>;
|
|
76
77
|
export type RouteMiddlewareRegistry = Record<string, RouteMiddlewareResolver<any>>;
|
|
77
78
|
export type RouteMiddlewareConfig = string | string[];
|
|
78
79
|
|
|
79
|
-
export type PageModule<TData =
|
|
80
|
+
export type PageModule<TData = any> = {
|
|
80
81
|
default: (props: PageProps<TData>) => ReactNode | Promise<ReactNode>;
|
|
81
82
|
Head?: HeadResolver<PageProps<TData>>;
|
|
82
83
|
Data?: PageDataResolver<TData>;
|
package/dist/webframez-core.cjs
CHANGED
|
@@ -153,6 +153,62 @@ var import_node_fs = __toESM(require("node:fs"), 1);
|
|
|
153
153
|
var import_node_module2 = __toESM(require("node:module"), 1);
|
|
154
154
|
var import_node_path2 = __toESM(require("node:path"), 1);
|
|
155
155
|
|
|
156
|
+
// src/head.ts
|
|
157
|
+
var ABSOLUTE_ASSET_URL_PATTERN = /^(?:[a-zA-Z][a-zA-Z\d+\-.]*:|\/\/|#)/;
|
|
158
|
+
function normalizeAssetsBaseUrl(value) {
|
|
159
|
+
const trimmed = value?.trim();
|
|
160
|
+
if (!trimmed) {
|
|
161
|
+
return void 0;
|
|
162
|
+
}
|
|
163
|
+
if (trimmed === "/") {
|
|
164
|
+
return "/";
|
|
165
|
+
}
|
|
166
|
+
return trimmed.replace(/\/+$/, "");
|
|
167
|
+
}
|
|
168
|
+
function resolveHeadAssetUrl(assetUrl, assetsBaseUrl) {
|
|
169
|
+
const normalizedAssetUrl = assetUrl.trim();
|
|
170
|
+
const normalizedAssetsBaseUrl = normalizeAssetsBaseUrl(assetsBaseUrl);
|
|
171
|
+
if (!normalizedAssetUrl || !normalizedAssetsBaseUrl) {
|
|
172
|
+
return normalizedAssetUrl;
|
|
173
|
+
}
|
|
174
|
+
if (ABSOLUTE_ASSET_URL_PATTERN.test(normalizedAssetUrl)) {
|
|
175
|
+
return normalizedAssetUrl;
|
|
176
|
+
}
|
|
177
|
+
if (normalizedAssetsBaseUrl !== "/" && (normalizedAssetUrl === normalizedAssetsBaseUrl || normalizedAssetUrl.startsWith(`${normalizedAssetsBaseUrl}/`))) {
|
|
178
|
+
return normalizedAssetUrl;
|
|
179
|
+
}
|
|
180
|
+
if (normalizedAssetsBaseUrl === "/") {
|
|
181
|
+
return normalizedAssetUrl.startsWith("/") ? normalizedAssetUrl : `/${normalizedAssetUrl}`;
|
|
182
|
+
}
|
|
183
|
+
if (normalizedAssetUrl.startsWith("/")) {
|
|
184
|
+
return `${normalizedAssetsBaseUrl}${normalizedAssetUrl}`;
|
|
185
|
+
}
|
|
186
|
+
return `${normalizedAssetsBaseUrl}/${normalizedAssetUrl}`;
|
|
187
|
+
}
|
|
188
|
+
function normalizeHeadConfig(head, inheritedAssetsBaseUrl) {
|
|
189
|
+
if (!head) {
|
|
190
|
+
return void 0;
|
|
191
|
+
}
|
|
192
|
+
const effectiveAssetsBaseUrl = normalizeAssetsBaseUrl(head.assetsBaseUrl) ?? normalizeAssetsBaseUrl(inheritedAssetsBaseUrl);
|
|
193
|
+
const normalizedHead = {
|
|
194
|
+
...head,
|
|
195
|
+
...effectiveAssetsBaseUrl ? { assetsBaseUrl: effectiveAssetsBaseUrl } : {}
|
|
196
|
+
};
|
|
197
|
+
if (normalizedHead.favicon) {
|
|
198
|
+
normalizedHead.favicon = resolveHeadAssetUrl(
|
|
199
|
+
normalizedHead.favicon,
|
|
200
|
+
effectiveAssetsBaseUrl
|
|
201
|
+
);
|
|
202
|
+
}
|
|
203
|
+
if (normalizedHead.links) {
|
|
204
|
+
normalizedHead.links = normalizedHead.links.map((link) => ({
|
|
205
|
+
...link,
|
|
206
|
+
href: resolveHeadAssetUrl(link.href, effectiveAssetsBaseUrl)
|
|
207
|
+
}));
|
|
208
|
+
}
|
|
209
|
+
return normalizedHead;
|
|
210
|
+
}
|
|
211
|
+
|
|
156
212
|
// src/router-runtime.tsx
|
|
157
213
|
var import_react = __toESM(require("react"), 1);
|
|
158
214
|
var ROUTE_CHILDREN_TAG = "webframez-route-children";
|
|
@@ -368,7 +424,8 @@ function mergeHead(...configs) {
|
|
|
368
424
|
meta: [],
|
|
369
425
|
links: []
|
|
370
426
|
};
|
|
371
|
-
for (const
|
|
427
|
+
for (const candidate of configs) {
|
|
428
|
+
const config = normalizeHeadConfig(candidate, merged.assetsBaseUrl);
|
|
372
429
|
if (!config) {
|
|
373
430
|
continue;
|
|
374
431
|
}
|
|
@@ -378,6 +435,9 @@ function mergeHead(...configs) {
|
|
|
378
435
|
if (config.description) {
|
|
379
436
|
merged.description = config.description;
|
|
380
437
|
}
|
|
438
|
+
if (config.assetsBaseUrl) {
|
|
439
|
+
merged.assetsBaseUrl = config.assetsBaseUrl;
|
|
440
|
+
}
|
|
381
441
|
if (config.favicon) {
|
|
382
442
|
merged.favicon = config.favicon;
|
|
383
443
|
}
|
|
@@ -391,22 +451,23 @@ function mergeHead(...configs) {
|
|
|
391
451
|
return merged;
|
|
392
452
|
}
|
|
393
453
|
function renderHeadToString(head) {
|
|
454
|
+
const normalizedHead = normalizeHeadConfig(head) ?? head;
|
|
394
455
|
const tags = [];
|
|
395
|
-
if (
|
|
456
|
+
if (normalizedHead.description) {
|
|
396
457
|
tags.push(
|
|
397
|
-
`<meta ${createManagedAttributes()} name="description" content="${escapeHtml(
|
|
458
|
+
`<meta ${createManagedAttributes()} name="description" content="${escapeHtml(normalizedHead.description)}" />`
|
|
398
459
|
);
|
|
399
460
|
}
|
|
400
|
-
if (
|
|
461
|
+
if (normalizedHead.favicon) {
|
|
401
462
|
tags.push(
|
|
402
|
-
`<link ${createManagedAttributes()} rel="icon" href="${escapeHtml(
|
|
463
|
+
`<link ${createManagedAttributes()} rel="icon" href="${escapeHtml(normalizedHead.favicon)}" />`
|
|
403
464
|
);
|
|
404
465
|
}
|
|
405
|
-
for (const meta of
|
|
466
|
+
for (const meta of normalizedHead.meta ?? []) {
|
|
406
467
|
const attrs = Object.entries(meta).filter(([, value]) => Boolean(value)).map(([key, value]) => `${key}="${escapeHtml(String(value))}"`).join(" ");
|
|
407
468
|
tags.push(`<meta ${createManagedAttributes()} ${attrs} />`);
|
|
408
469
|
}
|
|
409
|
-
for (const link of
|
|
470
|
+
for (const link of normalizedHead.links ?? []) {
|
|
410
471
|
const attrs = Object.entries(link).filter(([, value]) => Boolean(value)).map(([key, value]) => `${key}="${escapeHtml(String(value))}"`).join(" ");
|
|
411
472
|
tags.push(`<link ${createManagedAttributes()} ${attrs} />`);
|
|
412
473
|
}
|
package/dist/webframez-core.js
CHANGED
|
@@ -125,6 +125,62 @@ import fs from "node:fs";
|
|
|
125
125
|
import Module from "node:module";
|
|
126
126
|
import path2 from "node:path";
|
|
127
127
|
|
|
128
|
+
// src/head.ts
|
|
129
|
+
var ABSOLUTE_ASSET_URL_PATTERN = /^(?:[a-zA-Z][a-zA-Z\d+\-.]*:|\/\/|#)/;
|
|
130
|
+
function normalizeAssetsBaseUrl(value) {
|
|
131
|
+
const trimmed = value?.trim();
|
|
132
|
+
if (!trimmed) {
|
|
133
|
+
return void 0;
|
|
134
|
+
}
|
|
135
|
+
if (trimmed === "/") {
|
|
136
|
+
return "/";
|
|
137
|
+
}
|
|
138
|
+
return trimmed.replace(/\/+$/, "");
|
|
139
|
+
}
|
|
140
|
+
function resolveHeadAssetUrl(assetUrl, assetsBaseUrl) {
|
|
141
|
+
const normalizedAssetUrl = assetUrl.trim();
|
|
142
|
+
const normalizedAssetsBaseUrl = normalizeAssetsBaseUrl(assetsBaseUrl);
|
|
143
|
+
if (!normalizedAssetUrl || !normalizedAssetsBaseUrl) {
|
|
144
|
+
return normalizedAssetUrl;
|
|
145
|
+
}
|
|
146
|
+
if (ABSOLUTE_ASSET_URL_PATTERN.test(normalizedAssetUrl)) {
|
|
147
|
+
return normalizedAssetUrl;
|
|
148
|
+
}
|
|
149
|
+
if (normalizedAssetsBaseUrl !== "/" && (normalizedAssetUrl === normalizedAssetsBaseUrl || normalizedAssetUrl.startsWith(`${normalizedAssetsBaseUrl}/`))) {
|
|
150
|
+
return normalizedAssetUrl;
|
|
151
|
+
}
|
|
152
|
+
if (normalizedAssetsBaseUrl === "/") {
|
|
153
|
+
return normalizedAssetUrl.startsWith("/") ? normalizedAssetUrl : `/${normalizedAssetUrl}`;
|
|
154
|
+
}
|
|
155
|
+
if (normalizedAssetUrl.startsWith("/")) {
|
|
156
|
+
return `${normalizedAssetsBaseUrl}${normalizedAssetUrl}`;
|
|
157
|
+
}
|
|
158
|
+
return `${normalizedAssetsBaseUrl}/${normalizedAssetUrl}`;
|
|
159
|
+
}
|
|
160
|
+
function normalizeHeadConfig(head, inheritedAssetsBaseUrl) {
|
|
161
|
+
if (!head) {
|
|
162
|
+
return void 0;
|
|
163
|
+
}
|
|
164
|
+
const effectiveAssetsBaseUrl = normalizeAssetsBaseUrl(head.assetsBaseUrl) ?? normalizeAssetsBaseUrl(inheritedAssetsBaseUrl);
|
|
165
|
+
const normalizedHead = {
|
|
166
|
+
...head,
|
|
167
|
+
...effectiveAssetsBaseUrl ? { assetsBaseUrl: effectiveAssetsBaseUrl } : {}
|
|
168
|
+
};
|
|
169
|
+
if (normalizedHead.favicon) {
|
|
170
|
+
normalizedHead.favicon = resolveHeadAssetUrl(
|
|
171
|
+
normalizedHead.favicon,
|
|
172
|
+
effectiveAssetsBaseUrl
|
|
173
|
+
);
|
|
174
|
+
}
|
|
175
|
+
if (normalizedHead.links) {
|
|
176
|
+
normalizedHead.links = normalizedHead.links.map((link) => ({
|
|
177
|
+
...link,
|
|
178
|
+
href: resolveHeadAssetUrl(link.href, effectiveAssetsBaseUrl)
|
|
179
|
+
}));
|
|
180
|
+
}
|
|
181
|
+
return normalizedHead;
|
|
182
|
+
}
|
|
183
|
+
|
|
128
184
|
// src/router-runtime.tsx
|
|
129
185
|
import React from "react";
|
|
130
186
|
var ROUTE_CHILDREN_TAG = "webframez-route-children";
|
|
@@ -340,7 +396,8 @@ function mergeHead(...configs) {
|
|
|
340
396
|
meta: [],
|
|
341
397
|
links: []
|
|
342
398
|
};
|
|
343
|
-
for (const
|
|
399
|
+
for (const candidate of configs) {
|
|
400
|
+
const config = normalizeHeadConfig(candidate, merged.assetsBaseUrl);
|
|
344
401
|
if (!config) {
|
|
345
402
|
continue;
|
|
346
403
|
}
|
|
@@ -350,6 +407,9 @@ function mergeHead(...configs) {
|
|
|
350
407
|
if (config.description) {
|
|
351
408
|
merged.description = config.description;
|
|
352
409
|
}
|
|
410
|
+
if (config.assetsBaseUrl) {
|
|
411
|
+
merged.assetsBaseUrl = config.assetsBaseUrl;
|
|
412
|
+
}
|
|
353
413
|
if (config.favicon) {
|
|
354
414
|
merged.favicon = config.favicon;
|
|
355
415
|
}
|
|
@@ -363,22 +423,23 @@ function mergeHead(...configs) {
|
|
|
363
423
|
return merged;
|
|
364
424
|
}
|
|
365
425
|
function renderHeadToString(head) {
|
|
426
|
+
const normalizedHead = normalizeHeadConfig(head) ?? head;
|
|
366
427
|
const tags = [];
|
|
367
|
-
if (
|
|
428
|
+
if (normalizedHead.description) {
|
|
368
429
|
tags.push(
|
|
369
|
-
`<meta ${createManagedAttributes()} name="description" content="${escapeHtml(
|
|
430
|
+
`<meta ${createManagedAttributes()} name="description" content="${escapeHtml(normalizedHead.description)}" />`
|
|
370
431
|
);
|
|
371
432
|
}
|
|
372
|
-
if (
|
|
433
|
+
if (normalizedHead.favicon) {
|
|
373
434
|
tags.push(
|
|
374
|
-
`<link ${createManagedAttributes()} rel="icon" href="${escapeHtml(
|
|
435
|
+
`<link ${createManagedAttributes()} rel="icon" href="${escapeHtml(normalizedHead.favicon)}" />`
|
|
375
436
|
);
|
|
376
437
|
}
|
|
377
|
-
for (const meta of
|
|
438
|
+
for (const meta of normalizedHead.meta ?? []) {
|
|
378
439
|
const attrs = Object.entries(meta).filter(([, value]) => Boolean(value)).map(([key, value]) => `${key}="${escapeHtml(String(value))}"`).join(" ");
|
|
379
440
|
tags.push(`<meta ${createManagedAttributes()} ${attrs} />`);
|
|
380
441
|
}
|
|
381
|
-
for (const link of
|
|
442
|
+
for (const link of normalizedHead.links ?? []) {
|
|
382
443
|
const attrs = Object.entries(link).filter(([, value]) => Boolean(value)).map(([key, value]) => `${key}="${escapeHtml(String(value))}"`).join(" ");
|
|
383
444
|
tags.push(`<link ${createManagedAttributes()} ${attrs} />`);
|
|
384
445
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@webtypen/webframez-react",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.27",
|
|
4
4
|
"description": "TypeScript React RSC addition for @webtypen/webframez-core",
|
|
5
5
|
"homepage": "https://webtypen.de/",
|
|
6
6
|
"author": {
|
|
@@ -78,9 +78,9 @@
|
|
|
78
78
|
},
|
|
79
79
|
"peerDependencies": {
|
|
80
80
|
"@webtypen/webframez-core": "^0.3.30",
|
|
81
|
-
"react": "
|
|
82
|
-
"react-dom": "
|
|
83
|
-
"react-server-dom-webpack": "
|
|
81
|
+
"react": "^19.0.0",
|
|
82
|
+
"react-dom": "^19.0.0",
|
|
83
|
+
"react-server-dom-webpack": "^19.0.0"
|
|
84
84
|
},
|
|
85
85
|
"peerDependenciesMeta": {
|
|
86
86
|
"@webtypen/webframez-core": {
|
|
@@ -89,8 +89,8 @@
|
|
|
89
89
|
},
|
|
90
90
|
"devDependencies": {
|
|
91
91
|
"esbuild": "^0.20.2",
|
|
92
|
-
"react": "
|
|
93
|
-
"react-dom": "
|
|
94
|
-
"react-server-dom-webpack": "
|
|
92
|
+
"react": "19.1.1",
|
|
93
|
+
"react-dom": "19.1.1",
|
|
94
|
+
"react-server-dom-webpack": "19.1.1"
|
|
95
95
|
}
|
|
96
96
|
}
|