@symbo.ls/brender 3.14.668 → 3.14.670
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/CHANGELOG.md +21 -0
- package/dist/esm/prefetch.js +1 -1
- package/dist/esm/render.js +29 -29
- package/dist/esm/shell.js +8 -8
- package/package.json +9 -9
- package/prefetch.js +3 -1
- package/render.js +46 -2
- package/shell.js +12 -8
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,26 @@
|
|
|
1
1
|
# @symbo.ls/brender
|
|
2
2
|
|
|
3
|
+
## 3.14.670
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- A page built ahead carries `data-theme` on `<html>` when `globalTheme` is a fixed theme (light, dark or a named scheme), so first paint uses the project theme and not the OS scheme. `auto`/`system`/unset keep the prefers-color-scheme behaviour. (XMA round 7, K)
|
|
8
|
+
|
|
9
|
+
## 3.14.669
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- XMA round 5 ("smbls 3.14.843: what XMA still needs"): container and current CSS props + a dev warning for a dropped CSS prop (S); `_redirects` file rules on Cloudflare (T); `build.prepareDesignSystem: false` covers the pre-render app shell (U); preloads after the charset and `build.modulePreload: "strict"` (K); Dialog re-opens on an `if:` re-mount and hides a closed modal from its first moment (G, R); DropdownDisclosure `open`, `toggle` and `keepOpen` (H); the first render keeps a scrolled reader on an adopted page (P); `addressLang: 'strict'` and languages from a function (I); `fetch.early` chained requests and `afterFirstView` (J, 8); adoption keeps unchanged text, adopts in place, keeps the page's font faces, puts the app's sheets before the server's (F, O, Q, N); the head of a pre-rendered page resolves the page's own metadata (L). Plus the unreleased fixes on main since round 4b.
|
|
14
|
+
- Updated dependencies
|
|
15
|
+
- @symbo.ls/fetch@3.14.669
|
|
16
|
+
- @symbo.ls/utils@3.14.845
|
|
17
|
+
- @symbo.ls/scratch@3.14.792
|
|
18
|
+
- @symbo.ls/css@3.14.782
|
|
19
|
+
- @symbo.ls/element@3.14.809
|
|
20
|
+
- @symbo.ls/default-config@3.14.789
|
|
21
|
+
- @symbo.ls/helmet@3.14.671
|
|
22
|
+
- smbls@3.14.844
|
|
23
|
+
|
|
3
24
|
## 3.14.668
|
|
4
25
|
|
|
5
26
|
### Patch Changes
|
package/dist/esm/prefetch.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
const
|
|
1
|
+
const l=t=>typeof t=="function",S=t=>Array.isArray(t),g=t=>t!==null&&typeof t=="object"&&!Array.isArray(t),_=(t,r)=>{if(t){if(l(t))try{return t({state:r||{},call:()=>{},__ref:{}},r||{})}catch{return}return t}},j=(t,r)=>{if(!t)return null;if(typeof t=="string")return{from:t,method:"select"};const n=l(t)?null:{...t};return!n||(n.method||(n.method="select"),l(n.params)&&(n.params=_(n.params,r)),n.method==="insert"||n.method==="update"||n.method==="upsert"||n.method==="delete")||n.on&&n.on!=="create"?null:n},b=(t,r="")=>{if(!t||typeof t!="object")return[];if(l(t))return[];const n=[],s=t.state||{};if(t.fetch){const e=S(t.fetch)?t.fetch:[t.fetch];for(const c of e){const a=j(c,s);a&&n.push({config:a,stateKey:a.as,path:r,elementState:s})}}for(const e in t)e==="fetch"||e==="state"||e==="props"||e==="attr"||e==="on"||e==="define"||e==="childExtends"||e==="childProps"||e==="childrenAs"||e.charAt(0)>="A"&&e.charAt(0)<="Z"&&g(t[e])&&n.push(...b(t[e],r?`${r}.${e}`:e));return n},M=["rest","local"],w=new WeakMap,A=async t=>{if(!t)return null;if(g(t)&&(l(t.select)||l(t.rpc)))return t;const r=typeof t=="string"?{adapter:t}:t;if(!g(r)||typeof r.adapter!="string")return null;if(w.has(r))return w.get(r);const n=(async()=>{let s;try{s=await import("@symbo.ls/fetch")}catch{return null}if(!(l(s.hasAdapter)?s.hasAdapter(r.adapter):M.includes(r.adapter)))return null;try{return await s.resolveDb(r)}catch(c){return console.warn(`[brender] SSR adapter "${r.adapter}" unavailable: ${c.message}`),null}})();return w.set(r,n),n},k=async(t,r)=>{try{const{method:n,from:s,params:e,transform:c,limit:a,offset:u,order:h,single:f,headers:d,baseUrl:p}=r;let o;if(n==="rpc"){if(!l(t.rpc))return null;o=await t.rpc({from:s,params:e,headers:d,baseUrl:p})}else{if(!l(t.select))return null;o=await t.select({from:s,select:r.select,params:e,limit:a,offset:u,order:h,single:f,headers:d,baseUrl:p})}let i=o?.data??null;if(o?.error)return null;if(i&&c&&l(c))try{i=c(i)}catch{}return i}catch{return null}},P=async(t,r="/",n={})=>{const e=(t.pages||{})[r];if(!e)return new Map;const c=t.config||t.settings||{},a=c.fetch||t.fetch||c.db||t.db;if(!a)return new Map;const u=await A(a);if(!u)return new Map;const h=b(e);if(!h.length)return new Map;const f=new Map,d=await Promise.allSettled(h.map(async({config:p,stateKey:o,path:i})=>{const y=await k(u,p);if(y!==null){const m=f.get(i)||{};o?m[o]=y:g(y)&&Object.assign(m,y),f.set(i,m)}}));return f},x=async t=>{const r=t.config||{},n=r.polyglot||t.polyglot;if(!n?.fetch||typeof n.fetch=="function")return null;const s=r.fetch||t.fetch||r.db||t.db;if(!s)return null;const e=await A(s);if(!e)return null;const c=n.fetch,a=c.rpc||c.from||"get_translations_if_changed",u=(await import("@symbo.ls/utils")).polyglotLanguages(n,!1),h=u.length?u:[n.defaultLang||"en"],f={},d=await Promise.allSettled(h.map(async p=>{try{if(!l(e.rpc))return;const o=await e.rpc({from:a,params:{p_lang:p,p_cached_version:0}});if(o.error||!o.data)return;const i=o.data;i.translations&&(f[p]=i.translations)}catch(o){console.warn("[brender] SSR translation fetch failed:",o.message)}}));return Object.keys(f).length?f:null},D=(t,r)=>{if(!(!r||!r.size))for(const[n,s]of r){let e=t;if(n){const c=n.split(".");for(const a of c){if(!e||typeof e!="object")break;e=e[a]}}e&&typeof e=="object"&&((!e.state||typeof e.state!="object")&&(e.state={}),Object.assign(e.state,s))}};export{A as createSSRAdapter,x as fetchSSRTranslations,D as injectPrefetchedState,P as prefetchPageData};
|
package/dist/esm/render.js
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
import{resolve as u,join as Fe,dirname as _}from"path";import{existsSync as y,unlinkSync as Be,readFileSync as U,realpathSync as Ge}from"fs";import{resolvePackageEntry as Ke}from"./packageEntry.js";import{tmpdir as Ne}from"os";import{randomBytes as He}from"crypto";import{createRequire as re}from"module";import{pathToFileURL as Ue}from"url";import{createEnv as ge}from"./env.js";import{resetKeys as he,assignKeys as ye,mapKeysToElements as be}from"./keys.js";import{extractMetadata as ae,generateHeadHtml as We}from"./metadata.js";import"./hydrate.js";import{composeIntoShell as Je}from"./shell.js";import{fetchSSRTranslations as ze}from"./prefetch.js";import{createEarlySeedScript as Ye}from"@symbo.ls/fetch";import{headerEntries as Xe}from"@symbo.ls/fetch/rest";import{brenderRegistryBlock as Ve,brenderStampMeta as Qe,escapeRegExp as Ze,jsonForScript as et,polyglotFallbackLang as X,polyglotLangStorageKey as tt,polyglotAddressLang as ot,polyglotStartupScript as nt}from"@symbo.ls/utils";let V=null;const st=async()=>{if(V)return V;try{return V=(await import("@symbo.ls/funcql")).funcqlPlugin,V}catch{return null}};import"linkedom";import{createEarlySeedBlock as rt}from"@symbo.ls/fetch";import{reset as at}from"@symbo.ls/css";const Q=(e,t)=>{if(!e||!t)return;if(e[t]!==void 0)return e[t];const o=t.split(".");let n=e;for(const s of o){if(n==null||typeof n!="object")return;n=n[s]}return n},Z=(e,t)=>X(e?.lang,t),Se=(e,t,o,n)=>{if(o?.translations){const r=o.translations[t];if(r){const i=Q(r,e);if(i!==void 0)return i}}if(n?.translations){const r=n.translations[t];if(r){const i=Q(r,e);if(i!==void 0)return i}}const s=X(void 0,o);if(s!==t&&o?.translations){const r=o.translations[s];if(r){const i=Q(r,e);if(i!==void 0)return i}}},it=function(e,t){if(!e)return"";const o=this?.context,n=o?.polyglot,s=this?.state?.root||o?.state?.root,r=Se(e,t||Z(s,n),n,s);if(r!==void 0)return r;const i=fe(le);return n&&i&&i.labelKeys.add(e),e},we=function(){return Z(this?.state?.root,this?.context?.polyglot)},T=(e,t=new WeakMap)=>{if(e===null||typeof e!="object")return e;if(t.has(e))return t.get(e);if(Array.isArray(e)){const n=[];t.set(e,n);for(const s of e)n.push(typeof s=="object"&&s!==null?T(s,t):s);return n}const o={};t.set(e,o);for(const n of Object.keys(e)){const s=e[n];o[n]=typeof s=="object"&&s!==null?T(s,t):s}return o};let $=null;try{import.meta.url&&($=re(import.meta.url))}catch{}const ct=()=>{if(!import.meta.url||!$)return{isMonorepo:!1,monorepoRoot:null,resolvePackage:l=>l};const e=Ge(new URL(".",import.meta.url).pathname),t=u(e,"../..");if(y(u(t,"packages","smbls","src","createDomql.js")))return{isMonorepo:!0,monorepoRoot:t};let n;try{const l=$.resolve("smbls/package.json");n=_(l)}catch{let l=e;for(;l!==_(l);){const g=u(l,"node_modules","smbls");if(y(u(g,"package.json"))){n=g;break}l=_(l)}}let s=$;if(n)try{s=re(u(n,"package.json"))}catch{}let r,i=process.cwd();for(;i!==_(i);){if(y(u(i,"package.json"))){r=i;break}i=_(i)}let d=s;if(r)try{d=re(u(r,"package.json"))}catch{}return{isMonorepo:!1,smblsRoot:n,brenderDir:e,projectRoot:r,_smblsRequire:s,_projectRequire:d}},P=(e,t)=>{const o=e.isMonorepo?[$]:[e._smblsRequire,e._projectRequire,$].filter(Boolean);for(const n of o)try{return n.resolve(t)}catch{}return null},wo=(e,t,...o)=>{if(e.isMonorepo)return u(e.monorepoRoot,"packages",t,...o);const n=P(e,`${t}/package.json`);return n?u(_(n),...o):null},ko=(e,t,...o)=>{if(e.isMonorepo)return u(e.monorepoRoot,"plugins",t,...o);const n=P(e,`@symbo.ls/${t}/package.json`);return n?u(_(n),...o):null},ie=(e,t,...o)=>{if(e.isMonorepo){for(const s of["packages","plugins"]){const r=u(e.monorepoRoot,s,t,...o);if(y(r))return r}return null}const n=P(e,`@symbo.ls/${t}/package.json`);return n?u(_(n),...o):null},ke=(e,t,...o)=>{if(e.isMonorepo)return u(e.monorepoRoot,"packages","domql","packages",t,...o);const n=P(e,`@symbo.ls/${t}/package.json`);return n?u(_(n),...o):null};let ee=null;const Re="smbls/ssr",lt=async()=>{const e=await import("smbls/ssr");if(typeof e?.createDomqlElement!="function")throw new Error("smbls/ssr does not export createDomqlElement");return e},xe=()=>(ee||(ee=ft().catch(e=>{throw ee=null,e})),ee),ft=async()=>{const e=ct();let t;if($&&e.isMonorepo)t=u(e.monorepoRoot,"packages","smbls","src","createDomql.js");else{let f;try{return await lt()}catch(c){f=c}if(!$)throw new Error(`brender: ${Re} is not available in this bundled runtime (${f.message}). Bundle smbls \u2265 the release that adds the smbls/ssr export alongside @symbo.ls/brender.`);const a=e.smblsRoot&&u(e.smblsRoot,"src","createDomql.js");if(a&&y(a))t=a;else throw new Error(`brender: cannot load ${Re} (${f.message}). Server rendering needs smbls installed in this project, at a release that exports smbls/ssr`+(e.smblsRoot?` (found smbls at ${e.smblsRoot}).`:" (no smbls package found)."))}const o=await import("esbuild"),n=Fe(Ne(),`br_createDomql_${He(6).toString("hex")}.mjs`),s=Ke,r=e.isMonorepo?await import(Ue(u(e.monorepoRoot,"scripts","vite-workspace-source.mjs")).href):null,i=r?new Set(r.workspacePackageRoots().map(f=>r.workspacePackageAt(f).name)):null,d=/^(?:smbls(?:\/.*)?|domql|css-in-props(?:\/.*)?|@symbo\.ls\/[^/]+)$/,l={name:"workspace-resolve",setup(f){r&&(f.onResolve({filter:/^[^./]/},a=>{if(d.test(a.path))return;const c=a.path.split("/"),p=a.path.startsWith("@")?c.slice(0,2).join("/"):c[0];if(!i.has(p))return;const m=r.resolveWorkspaceSource(a.path,a.importer||t);return m?{path:m}:{errors:[{text:`"${a.path}" names no source file in the workspace`}]}}),f.onLoad({filter:/[\\/]dist[\\/]/},a=>r.isWorkspaceDist(a.path)?{errors:[{text:`${a.path} is a BUILD of a workspace package \u2014 the render bundles source`}]}:void 0)),f.onResolve({filter:/^smbls/},a=>{const c=a.path.replace(/^smbls\/?/,""),p=e.isMonorepo?u(e.monorepoRoot,"packages","smbls"):e.smblsRoot;if(!p)return;if(!c){const S=s(p);return S?{path:S}:void 0}const m=u(p,c);if(y(m))return{path:m};if(y(m+".js"))return{path:m+".js"};const b=u(m,"index.js");if(y(b))return{path:b}}),f.onResolve({filter:/^domql$/},a=>{if(e.isMonorepo){const c=u(e.monorepoRoot,"packages","domql","src","index.js");if(y(c))return{path:c};const p=u(e.monorepoRoot,"packages","domql","index.js");if(y(p))return{path:p}}else try{const c=_require.resolve("domql/package.json"),p=s(_(c));if(p)return{path:p}}catch{}}),f.onResolve({filter:/^@symbo\.ls\//},a=>{const c=a.path.replace("@symbo.ls/","");if(c==="sync")return{path:"sync-stub",namespace:"brender-stub"};if(e.isMonorepo){for(const m of["packages","plugins"]){const b=u(e.monorepoRoot,m,c,"src","index.js");if(y(b))return{path:b};const S=u(e.monorepoRoot,m,c,"index.js");if(y(S))return{path:S}}const p=u(e.monorepoRoot,"packages","default-config","blank","index.js");if(c==="default-config"&&y(p))return{path:p}}else{const p=ie(e,c,"src","index.js");if(p&&y(p))return{path:p};const m=ie(e,c,"index.js");if(m&&y(m))return{path:m};if(c==="default-config"){const b=ie(e,"default-config","blank","index.js");if(b&&y(b))return{path:b}}}}),f.onResolve({filter:/^@domql\//},a=>{const c=a.path.replace("@symbo.ls/","");if(e.isMonorepo){const p=u(e.monorepoRoot,"packages","domql","packages",c,"src","index.js");if(y(p))return{path:p};const m=u(e.monorepoRoot,"packages","domql","packages",c,"index.js");if(y(m))return{path:m}}else{const p=ke(e,c,"src","index.js");if(p&&y(p))return{path:p};const m=ke(e,c,"index.js");if(m&&y(m))return{path:m}}}),f.onResolve({filter:/^css-in-props/},a=>{let c;if(e.isMonorepo)c=u(e.monorepoRoot,"packages","css-in-props");else{const b=P(e,"css-in-props/package.json");b&&(c=_(b))}if(!c)return;const p=a.path.replace(/^css-in-props\/?/,"");if(p){const b=u(c,p),S=u(b,"index.js");if(y(S))return{path:S};if(y(b+".js"))return{path:b+".js"};if(y(b))return{path:b}}const m=s(c);if(m)return{path:m}}),f.onResolve({filter:/^@emotion\//},a=>{let c;if(e.isMonorepo)c=u(e.monorepoRoot,"node_modules",a.path);else{const p=P(e,`${a.path}/package.json`);if(!p)return;c=_(p)}if(y(c)){const p=u(c,"package.json");if(y(p))try{const m=JSON.parse(U(p,"utf8")),b=m.module||m.main||"dist/emotion-css.esm.js";return{path:u(c,b)}}catch{}return{path:c}}}),f.onResolve({filter:/\.json$/},a=>{if(a.resolveDir){const c=u(a.resolveDir,a.path);if(y(c))return{path:c}}}),f.onLoad({filter:/smbls\/.*options\.js$/},async a=>{if(!a.path.includes("smbls/")||!a.path.endsWith("options.js"))return;let c=U(a.path,"utf8");return c=c.replace(/import\s*\{[^}]*version[^}]*\}\s*from\s*['"][^'"]*package\.json['"][^;\n]*/,"const version = '0.0.0'"),c=c.replace(/import\s*\{[^}]*createRequire[^}]*\}\s*from\s*['"]module['"][^;\n]*/g,"// createRequire removed for brender build"),{contents:c,loader:"js"}}),f.onLoad({filter:/smbls\/.*init\.js$/},async a=>{if(!a.path.includes("smbls/")||!a.path.endsWith("init.js"))return;let c=U(a.path,"utf8");return c=c.replace(/import\s*\{[^}]*createRequire[^}]*\}\s*from\s*['"]module['"][^;\n]*/g,"// createRequire removed for brender build"),{contents:c,loader:"js"}}),f.onLoad({filter:/.*/,namespace:"brender-stub"},()=>({contents:"export const SyncComponent = {}; export const Inspect = {}; export const Notifications = {}; export const syncPlugin = () => ({}); export const notificationsPlugin = () => ({}); export const seedRawDesignSystem = () => {}; export const inspectPlugin = () => ({}); export default {}",loader:"js"})),f.onLoad({filter:/smbls\/src\/router\.js$/},async a=>{let c=U(a.path,"utf8");return c=c.replace(/import\s*\{\s*Link\s*\}\s*from\s*['"]smbls['"]/,"const Link = { tag: 'a', attr: { href: (el) => el.href } }"),{contents:c,loader:"js"}}),f.onLoad({filter:/fetchOnCreate\.js$/},async a=>{if(!a.path.includes("smbls/"))return;let c=U(a.path,"utf8");return c=c.replace(/window\s*&&\s*window\.location\s*\?\s*window\.location\.host\.includes/g,"window && window.location && window.location.host ? window.location.host.includes"),{contents:c,loader:"js"}})}};await o.build({entryPoints:[t],bundle:!0,format:"esm",platform:"node",outfile:n,write:!0,logLevel:"warning",plugins:[l],nodePaths:e.isMonorepo?[u(e.monorepoRoot,"node_modules")]:[...e.smblsRoot?[u(e.smblsRoot,"node_modules")]:[],...e.projectRoot?[u(e.projectRoot,"node_modules")]:[],...e.smblsRoot?[u(e.smblsRoot,"..","..","node_modules")]:[]].filter(f=>y(f)),supported:{"import-attributes":!1},external:["fs","path","os","crypto","url","http","https","stream","util","events","buffer","child_process","worker_threads","net","tls","dns","dgram","zlib","assert","querystring","string_decoder","readline","perf_hooks","async_hooks","v8","vm","cluster","inspector","module","process","tty","color-contrast-checker","linkedom"]});const g=await import(`file://${n}`);if(process.env.BRENDER_DEBUG)console.log("[brender] Bundle saved:",n);else try{Be(n)}catch{}return g},pt={Box:{},Focusable:{},Block:{display:"block"},Inline:{display:"inline"},Flex:{display:"flex"},InlineFlex:{display:"inline-flex"},Grid:{display:"grid"},InlineGrid:{display:"inline-grid"},Link:{tag:"a",attr:{href:e=>e.href,target:e=>e.target,rel:e=>e.rel}},A:{extends:"Link"},RouteLink:{extends:"Link"},Img:{tag:"img",attr:{src:e=>{let t=e.src;return typeof t=="string"&&t.includes("{{")&&(t=e.call("replaceLiteralsWithObjectFields",t,e.state)),t},alt:e=>e.alt,loading:e=>e.loading}},Image:{extends:"Img"},Button:{tag:"button"},FocusableComponent:{tag:"button"},Form:{tag:"form"},Input:{tag:"input"},TextArea:{tag:"textarea"},Textarea:{tag:"textarea"},Select:{tag:"select"},Label:{tag:"label"},Iframe:{tag:"iframe"},Video:{tag:"video"},Audio:{tag:"audio"},Canvas:{tag:"canvas"},Span:{tag:"span"},P:{tag:"p"},H1:{tag:"h1"},H2:{tag:"h2"},H3:{tag:"h3"},H4:{tag:"h4"},H5:{tag:"h5"},H6:{tag:"h6"},Svg:{tag:"svg",attr:{xmlns:"http://www.w3.org/2000/svg","xmlns:xlink":"http://www.w3.org/1999/xlink"}},Text:{tag:"span"}},ut=(e,t)=>{const o={};return je(e,(n,s)=>{if(!s.__brKey)return;const r=t(n);o[r===""?"__root":r]=s.__brKey}),o},je=(e,t)=>{const o=n=>{const s=n&&n.__ref;if(s&&(t(n,s),s.__children))for(const r of s.__children)o(n[r])};o(e)},dt=new Set(["app","config","pages","components","state","snippets","designSystem","dependencies","functions","methods","files","sharedLibraries"]);let F=0;const _e=Symbol.for("brender.fetchTracked"),ce=()=>F,mt=256*1024,gt=1024*1024,ht=new Set(["accept-language","accept"]),Ee={renders:0,record:null},yt=50,le={renders:0,record:null},ve=(e,t)=>{e.renders++,e.renders===1?e.record=t():e.record&&(e.record.tainted=!0);const o=e.record;return{record:o,close:()=>{e.renders--,e.record===o&&(e.record=null)}}},fe=e=>e.record&&!e.record.tainted?e.record:null,bt=e=>{try{const t=new URL(e);return t.origin+t.pathname}catch{return String(e).split("?")[0]}},pe=(e,t,o)=>{!e||e.tainted||e.failures.length>=yt||e.failures.push({url:bt(t),reason:o})},Te=e=>e&&typeof e=="object"&&typeof e.url=="string"?e.url:String(e),St=e=>{const[t,o]=e,n=t&&typeof t=="object"&&typeof t.url=="string",s=Te(t),r=String(o&&o.method||n&&t.method||"GET").toUpperCase(),i={},d=l=>{if(!l)return;const g=!Array.isArray(l)&&typeof l.entries!="function";for(const[f,a]of Xe(l))g&&a==null||(i[String(f).toLowerCase()]=String(a))};return n&&d(t.headers),o&&d(o.headers),{url:s,method:r,headers:i}},wt=(e,t,o,n)=>{if(!o||!o.ok||typeof o.clone!="function")return;const s=o.headers&&o.headers.get&&o.headers.get("content-type")||"";if(!/json|^text\//i.test(s))return;let r;try{r=o.clone()}catch{return}n(r.text().then(i=>{e.tainted||i.length>mt||e.bytes+i.length>gt||(e.bytes+=i.length,e.entries.push({url:t.url,lang:t.headers["accept-language"]||"",status:o.status,type:s,body:i}))},()=>{}))},kt=()=>{const e=globalThis.fetch;if(typeof e!="function"||e[_e])return;const t=function(...o){F++;let n=!1;const s=()=>{n||(n=!0,F--)},r=a=>{F++,a.then(()=>{F--},()=>{F--})},i=fe(Ee),d=fe(le);let l=null;if(i)try{l=St(o),(l.method!=="GET"||!/^https?:/i.test(l.url)||Object.keys(l.headers).some(a=>!ht.has(a)))&&(l=null)}catch{l=null}const g=()=>Te(o[0]);let f;try{f=e.apply(this,o)}catch(a){throw pe(d,g(),a&&a.message||"failed"),s(),a}return f&&typeof f.then=="function"?f.then(a=>{l&&wt(i,l,a,r),d&&a&&a.ok===!1&&pe(d,g(),"HTTP "+a.status),s()},a=>{pe(d,g(),a&&a.message||"network error"),s()}):s(),f};t[_e]=!0,globalThis.fetch=t},Ro=({brRegistry:e,fetchSeed:t,hydrateFlag:o=!0}={})=>{if(!e||!Object.keys(e).length)return"";const n=et(e);return o?`<script>window.__BR_REGISTRY__=${n};window.__BRENDER_HYDRATE__=true<\/script>`+(t&&t.length?`
|
|
2
|
-
`+
|
|
1
|
+
import{resolve as p,join as Ne,dirname as T}from"path";import{existsSync as h,unlinkSync as He,readFileSync as J,realpathSync as Ue}from"fs";import{resolvePackageEntry as We}from"./packageEntry.js";import{tmpdir as Je}from"os";import{randomBytes as ze}from"crypto";import{createRequire as ie}from"module";import{pathToFileURL as Ye}from"url";import{createEnv as ye}from"./env.js";import{resetKeys as be,assignKeys as Se,mapKeysToElements as we}from"./keys.js";import{extractMetadata as ae,generateHeadHtml as Xe}from"./metadata.js";import"./hydrate.js";import{composeIntoShell as Ve}from"./shell.js";import{fetchSSRTranslations as Qe}from"./prefetch.js";import{createEarlySeedScript as Ze}from"@symbo.ls/fetch";import{headerEntries as et}from"@symbo.ls/fetch/rest";import{brenderRegistryBlock as tt,brenderStampMeta as ot,escapeRegExp as nt,jsonForScript as st,polyglotFallbackLang as Q,polyglotLangStorageKey as rt,polyglotAddressLang as ct,polyglotStartupScript as it}from"@symbo.ls/utils";let Z=null;const at=async()=>{if(Z)return Z;try{return Z=(await import("@symbo.ls/funcql")).funcqlPlugin,Z}catch{return null}};import"linkedom";import{createEarlySeedBlock as lt}from"@symbo.ls/fetch";import{reset as ft}from"@symbo.ls/css";const ee=(e,t)=>{if(!e||!t)return;if(e[t]!==void 0)return e[t];const o=t.split(".");let n=e;for(const s of o){if(n==null||typeof n!="object")return;n=n[s]}return n},te=(e,t)=>Q(e?.lang,t),Re=(e,t,o,n)=>{if(o?.translations){const r=o.translations[t];if(r){const i=ee(r,e);if(i!==void 0)return i}}if(n?.translations){const r=n.translations[t];if(r){const i=ee(r,e);if(i!==void 0)return i}}const s=Q(void 0,o);if(s!==t&&o?.translations){const r=o.translations[s];if(r){const i=ee(r,e);if(i!==void 0)return i}}},ut=function(e,t){if(!e)return"";const o=this?.context,n=o?.polyglot,s=this?.state?.root||o?.state?.root,r=Re(e,t||te(s,n),n,s);if(r!==void 0)return r;const i=pe(ue);return n&&i&&i.labelKeys.add(e),e},ke=function(){return te(this?.state?.root,this?.context?.polyglot)},$=(e,t=new WeakMap)=>{if(e===null||typeof e!="object")return e;if(t.has(e))return t.get(e);if(Array.isArray(e)){const n=[];t.set(e,n);for(const s of e)n.push(typeof s=="object"&&s!==null?$(s,t):s);return n}const o={};t.set(e,o);for(const n of Object.keys(e)){const s=e[n];o[n]=typeof s=="object"&&s!==null?$(s,t):s}return o};let q=null;try{import.meta.url&&(q=ie(import.meta.url))}catch{}const pt=()=>{if(!import.meta.url||!q)return{isMonorepo:!1,monorepoRoot:null,resolvePackage:l=>l};const e=Ue(new URL(".",import.meta.url).pathname),t=p(e,"../..");if(h(p(t,"packages","smbls","src","createDomql.js")))return{isMonorepo:!0,monorepoRoot:t};let n;try{const l=q.resolve("smbls/package.json");n=T(l)}catch{let l=e;for(;l!==T(l);){const g=p(l,"node_modules","smbls");if(h(p(g,"package.json"))){n=g;break}l=T(l)}}let s=q;if(n)try{s=ie(p(n,"package.json"))}catch{}let r,i=process.cwd();for(;i!==T(i);){if(h(p(i,"package.json"))){r=i;break}i=T(i)}let m=s;if(r)try{m=ie(p(r,"package.json"))}catch{}return{isMonorepo:!1,smblsRoot:n,brenderDir:e,projectRoot:r,_smblsRequire:s,_projectRequire:m}},P=(e,t)=>{const o=e.isMonorepo?[q]:[e._smblsRequire,e._projectRequire,q].filter(Boolean);for(const n of o)try{return n.resolve(t)}catch{}return null},Eo=(e,t,...o)=>{if(e.isMonorepo)return p(e.monorepoRoot,"packages",t,...o);const n=P(e,`${t}/package.json`);return n?p(T(n),...o):null},To=(e,t,...o)=>{if(e.isMonorepo)return p(e.monorepoRoot,"plugins",t,...o);const n=P(e,`@symbo.ls/${t}/package.json`);return n?p(T(n),...o):null},le=(e,t,...o)=>{if(e.isMonorepo){for(const s of["packages","plugins"]){const r=p(e.monorepoRoot,s,t,...o);if(h(r))return r}return null}const n=P(e,`@symbo.ls/${t}/package.json`);return n?p(T(n),...o):null},xe=(e,t,...o)=>{if(e.isMonorepo)return p(e.monorepoRoot,"packages","domql","packages",t,...o);const n=P(e,`@symbo.ls/${t}/package.json`);return n?p(T(n),...o):null};let oe=null;const je="smbls/ssr",mt=async()=>{const e=await import("smbls/ssr");if(typeof e?.createDomqlElement!="function")throw new Error("smbls/ssr does not export createDomqlElement");return e},_e=()=>(oe||(oe=dt().catch(e=>{throw oe=null,e})),oe),dt=async()=>{const e=pt();let t;if(q&&e.isMonorepo)t=p(e.monorepoRoot,"packages","smbls","src","createDomql.js");else{let f;try{return await mt()}catch(a){f=a}if(!q)throw new Error(`brender: ${je} is not available in this bundled runtime (${f.message}). Bundle smbls \u2265 the release that adds the smbls/ssr export alongside @symbo.ls/brender.`);const c=e.smblsRoot&&p(e.smblsRoot,"src","createDomql.js");if(c&&h(c))t=c;else throw new Error(`brender: cannot load ${je} (${f.message}). Server rendering needs smbls installed in this project, at a release that exports smbls/ssr`+(e.smblsRoot?` (found smbls at ${e.smblsRoot}).`:" (no smbls package found)."))}const o=await import("esbuild"),n=Ne(Je(),`br_createDomql_${ze(6).toString("hex")}.mjs`),s=We,r=e.isMonorepo?await import(Ye(p(e.monorepoRoot,"scripts","vite-workspace-source.mjs")).href):null,i=r?new Set(r.workspacePackageRoots().map(f=>r.workspacePackageAt(f).name)):null,m=/^(?:smbls(?:\/.*)?|domql|css-in-props(?:\/.*)?|@symbo\.ls\/[^/]+)$/,l={name:"workspace-resolve",setup(f){r&&(f.onResolve({filter:/^[^./]/},c=>{if(m.test(c.path))return;const a=c.path.split("/"),u=c.path.startsWith("@")?a.slice(0,2).join("/"):a[0];if(!i.has(u))return;const d=r.resolveWorkspaceSource(c.path,c.importer||t);return d?{path:d}:{errors:[{text:`"${c.path}" names no source file in the workspace`}]}}),f.onLoad({filter:/[\\/]dist[\\/]/},c=>r.isWorkspaceDist(c.path)?{errors:[{text:`${c.path} is a BUILD of a workspace package \u2014 the render bundles source`}]}:void 0)),f.onResolve({filter:/^smbls/},c=>{const a=c.path.replace(/^smbls\/?/,""),u=e.isMonorepo?p(e.monorepoRoot,"packages","smbls"):e.smblsRoot;if(!u)return;if(!a){const b=s(u);return b?{path:b}:void 0}const d=p(u,a);if(h(d))return{path:d};if(h(d+".js"))return{path:d+".js"};const y=p(d,"index.js");if(h(y))return{path:y}}),f.onResolve({filter:/^domql$/},c=>{if(e.isMonorepo){const a=p(e.monorepoRoot,"packages","domql","src","index.js");if(h(a))return{path:a};const u=p(e.monorepoRoot,"packages","domql","index.js");if(h(u))return{path:u}}else try{const a=_require.resolve("domql/package.json"),u=s(T(a));if(u)return{path:u}}catch{}}),f.onResolve({filter:/^@symbo\.ls\//},c=>{const a=c.path.replace("@symbo.ls/","");if(a==="sync")return{path:"sync-stub",namespace:"brender-stub"};if(e.isMonorepo){for(const d of["packages","plugins"]){const y=p(e.monorepoRoot,d,a,"src","index.js");if(h(y))return{path:y};const b=p(e.monorepoRoot,d,a,"index.js");if(h(b))return{path:b}}const u=p(e.monorepoRoot,"packages","default-config","blank","index.js");if(a==="default-config"&&h(u))return{path:u}}else{const u=le(e,a,"src","index.js");if(u&&h(u))return{path:u};const d=le(e,a,"index.js");if(d&&h(d))return{path:d};if(a==="default-config"){const y=le(e,"default-config","blank","index.js");if(y&&h(y))return{path:y}}}}),f.onResolve({filter:/^@domql\//},c=>{const a=c.path.replace("@symbo.ls/","");if(e.isMonorepo){const u=p(e.monorepoRoot,"packages","domql","packages",a,"src","index.js");if(h(u))return{path:u};const d=p(e.monorepoRoot,"packages","domql","packages",a,"index.js");if(h(d))return{path:d}}else{const u=xe(e,a,"src","index.js");if(u&&h(u))return{path:u};const d=xe(e,a,"index.js");if(d&&h(d))return{path:d}}}),f.onResolve({filter:/^css-in-props/},c=>{let a;if(e.isMonorepo)a=p(e.monorepoRoot,"packages","css-in-props");else{const y=P(e,"css-in-props/package.json");y&&(a=T(y))}if(!a)return;const u=c.path.replace(/^css-in-props\/?/,"");if(u){const y=p(a,u),b=p(y,"index.js");if(h(b))return{path:b};if(h(y+".js"))return{path:y+".js"};if(h(y))return{path:y}}const d=s(a);if(d)return{path:d}}),f.onResolve({filter:/^@emotion\//},c=>{let a;if(e.isMonorepo)a=p(e.monorepoRoot,"node_modules",c.path);else{const u=P(e,`${c.path}/package.json`);if(!u)return;a=T(u)}if(h(a)){const u=p(a,"package.json");if(h(u))try{const d=JSON.parse(J(u,"utf8")),y=d.module||d.main||"dist/emotion-css.esm.js";return{path:p(a,y)}}catch{}return{path:a}}}),f.onResolve({filter:/\.json$/},c=>{if(c.resolveDir){const a=p(c.resolveDir,c.path);if(h(a))return{path:a}}}),f.onLoad({filter:/smbls\/.*options\.js$/},async c=>{if(!c.path.includes("smbls/")||!c.path.endsWith("options.js"))return;let a=J(c.path,"utf8");return a=a.replace(/import\s*\{[^}]*version[^}]*\}\s*from\s*['"][^'"]*package\.json['"][^;\n]*/,"const version = '0.0.0'"),a=a.replace(/import\s*\{[^}]*createRequire[^}]*\}\s*from\s*['"]module['"][^;\n]*/g,"// createRequire removed for brender build"),{contents:a,loader:"js"}}),f.onLoad({filter:/smbls\/.*init\.js$/},async c=>{if(!c.path.includes("smbls/")||!c.path.endsWith("init.js"))return;let a=J(c.path,"utf8");return a=a.replace(/import\s*\{[^}]*createRequire[^}]*\}\s*from\s*['"]module['"][^;\n]*/g,"// createRequire removed for brender build"),{contents:a,loader:"js"}}),f.onLoad({filter:/.*/,namespace:"brender-stub"},()=>({contents:"export const SyncComponent = {}; export const Inspect = {}; export const Notifications = {}; export const syncPlugin = () => ({}); export const notificationsPlugin = () => ({}); export const seedRawDesignSystem = () => {}; export const inspectPlugin = () => ({}); export default {}",loader:"js"})),f.onLoad({filter:/smbls\/src\/router\.js$/},async c=>{let a=J(c.path,"utf8");return a=a.replace(/import\s*\{\s*Link\s*\}\s*from\s*['"]smbls['"]/,"const Link = { tag: 'a', attr: { href: (el) => el.href } }"),{contents:a,loader:"js"}}),f.onLoad({filter:/fetchOnCreate\.js$/},async c=>{if(!c.path.includes("smbls/"))return;let a=J(c.path,"utf8");return a=a.replace(/window\s*&&\s*window\.location\s*\?\s*window\.location\.host\.includes/g,"window && window.location && window.location.host ? window.location.host.includes"),{contents:a,loader:"js"}})}};await o.build({entryPoints:[t],bundle:!0,format:"esm",platform:"node",outfile:n,write:!0,logLevel:"warning",plugins:[l],nodePaths:e.isMonorepo?[p(e.monorepoRoot,"node_modules")]:[...e.smblsRoot?[p(e.smblsRoot,"node_modules")]:[],...e.projectRoot?[p(e.projectRoot,"node_modules")]:[],...e.smblsRoot?[p(e.smblsRoot,"..","..","node_modules")]:[]].filter(f=>h(f)),supported:{"import-attributes":!1},external:["fs","path","os","crypto","url","http","https","stream","util","events","buffer","child_process","worker_threads","net","tls","dns","dgram","zlib","assert","querystring","string_decoder","readline","perf_hooks","async_hooks","v8","vm","cluster","inspector","module","process","tty","color-contrast-checker","linkedom"]});const g=await import(`file://${n}`);if(process.env.BRENDER_DEBUG)console.log("[brender] Bundle saved:",n);else try{He(n)}catch{}return g},gt={Box:{},Focusable:{},Block:{display:"block"},Inline:{display:"inline"},Flex:{display:"flex"},InlineFlex:{display:"inline-flex"},Grid:{display:"grid"},InlineGrid:{display:"inline-grid"},Link:{tag:"a",attr:{href:e=>e.href,target:e=>e.target,rel:e=>e.rel}},A:{extends:"Link"},RouteLink:{extends:"Link"},Img:{tag:"img",attr:{src:e=>{let t=e.src;return typeof t=="string"&&t.includes("{{")&&(t=e.call("replaceLiteralsWithObjectFields",t,e.state)),t},alt:e=>e.alt,loading:e=>e.loading}},Image:{extends:"Img"},Button:{tag:"button"},FocusableComponent:{tag:"button"},Form:{tag:"form"},Input:{tag:"input"},TextArea:{tag:"textarea"},Textarea:{tag:"textarea"},Select:{tag:"select"},Label:{tag:"label"},Iframe:{tag:"iframe"},Video:{tag:"video"},Audio:{tag:"audio"},Canvas:{tag:"canvas"},Span:{tag:"span"},P:{tag:"p"},H1:{tag:"h1"},H2:{tag:"h2"},H3:{tag:"h3"},H4:{tag:"h4"},H5:{tag:"h5"},H6:{tag:"h6"},Svg:{tag:"svg",attr:{xmlns:"http://www.w3.org/2000/svg","xmlns:xlink":"http://www.w3.org/1999/xlink"}},Text:{tag:"span"}},ht=(e,t)=>{const o={};return Ee(e,(n,s)=>{if(!s.__brKey)return;const r=t(n);o[r===""?"__root":r]=s.__brKey}),o},Ee=(e,t)=>{const o=n=>{const s=n&&n.__ref;if(s&&(t(n,s),s.__children))for(const r of s.__children)o(n[r])};o(e)},yt=new Set(["app","config","pages","components","state","snippets","designSystem","dependencies","functions","methods","files","sharedLibraries"]);let F=0;const Te=Symbol.for("brender.fetchTracked"),fe=()=>F,bt=256*1024,St=1024*1024,wt=new Set(["accept-language","accept"]),ve={renders:0,record:null},Rt=50,ue={renders:0,record:null},Le=(e,t)=>{e.renders++,e.renders===1?e.record=t():e.record&&(e.record.tainted=!0);const o=e.record;return{record:o,close:()=>{e.renders--,e.record===o&&(e.record=null)}}},pe=e=>e.record&&!e.record.tainted?e.record:null,kt=e=>{try{const t=new URL(e);return t.origin+t.pathname}catch{return String(e).split("?")[0]}},me=(e,t,o)=>{!e||e.tainted||e.failures.length>=Rt||e.failures.push({url:kt(t),reason:o})},De=e=>e&&typeof e=="object"&&typeof e.url=="string"?e.url:String(e),xt=e=>{const[t,o]=e,n=t&&typeof t=="object"&&typeof t.url=="string",s=De(t),r=String(o&&o.method||n&&t.method||"GET").toUpperCase(),i={},m=l=>{if(!l)return;const g=!Array.isArray(l)&&typeof l.entries!="function";for(const[f,c]of et(l))g&&c==null||(i[String(f).toLowerCase()]=String(c))};return n&&m(t.headers),o&&m(o.headers),{url:s,method:r,headers:i}},jt=(e,t,o,n)=>{if(!o||!o.ok||typeof o.clone!="function")return;const s=o.headers&&o.headers.get&&o.headers.get("content-type")||"";if(!/json|^text\//i.test(s))return;let r;try{r=o.clone()}catch{return}n(r.text().then(i=>{e.tainted||i.length>bt||e.bytes+i.length>St||(e.bytes+=i.length,e.entries.push({url:t.url,lang:t.headers["accept-language"]||"",status:o.status,type:s,body:i}))},()=>{}))},_t=()=>{const e=globalThis.fetch;if(typeof e!="function"||e[Te])return;const t=function(...o){F++;let n=!1;const s=()=>{n||(n=!0,F--)},r=c=>{F++,c.then(()=>{F--},()=>{F--})},i=pe(ve),m=pe(ue);let l=null;if(i)try{l=xt(o),(l.method!=="GET"||!/^https?:/i.test(l.url)||Object.keys(l.headers).some(c=>!wt.has(c)))&&(l=null)}catch{l=null}const g=()=>De(o[0]);let f;try{f=e.apply(this,o)}catch(c){throw me(m,g(),c&&c.message||"failed"),s(),c}return f&&typeof f.then=="function"?f.then(c=>{l&&jt(i,l,c,r),m&&c&&c.ok===!1&&me(m,g(),"HTTP "+c.status),s()},c=>{me(m,g(),c&&c.message||"network error"),s()}):s(),f};t[Te]=!0,globalThis.fetch=t},vo=({brRegistry:e,fetchSeed:t,hydrateFlag:o=!0}={})=>{if(!e||!Object.keys(e).length)return"";const n=st(e);return o?`<script>window.__BR_REGISTRY__=${n};window.__BRENDER_HYDRATE__=true<\/script>`+(t&&t.length?`
|
|
2
|
+
`+Ze(t):""):`<script>window.__BR_REGISTRY__=${n}<\/script>`},Et=3e4,Tt=2147483647;let $e=Promise.resolve();const Ae=()=>{},vt=e=>{const t=$e.then(e);return $e=t.then(Ae,Ae),t},Lt=e=>{if(e===void 0)return Et;if(e===0||e===!1||e===1/0)return 0;if(typeof e!="number"||!(e>0))throw new TypeError(`brender: options.timeout is a number of milliseconds, or 0 / false for no limit \u2014 not ${JSON.stringify(e)}`);return Math.min(e,Tt)},Dt=(e,t)=>{const o=e.route||"/",n=e.pathname||o,s=n===o?o:`${n} (route ${o})`,r=new Error(`brender: the render of ${s} did not finish within ${t} ms and was abandoned, so the renders after it can run (options.timeout)`);return r.code="BRENDER_RENDER_TIMEOUT",r.route=o,r.pathname=n,r.timeout=t,r},$t=e=>{e.closed=!0;for(const t of e.undo.splice(0))t()},At=e=>{let t=!1;return()=>{t||(t=!0,e())}},qe=(e,t={})=>{let o;try{o=Lt(t.timeout)}catch(n){return Promise.reject(n)}return vt(()=>qt(e,t,o))},qt=async(e,t,o)=>{await _e();const n={closed:!1,undo:[]},s=Ct(e,t,n);if(!o)return s;let r;const i=new Promise((m,l)=>{r=setTimeout(()=>{$t(n),l(Dt(t,o))},o)});try{return await Promise.race([s,i])}finally{clearTimeout(r)}},Ct=async(e,t,o)=>{const{route:n="/",pathname:s,state:r,context:i,prefetch:m=!1}=t,l=s||n;_t();const g=Le(ue,()=>({failures:[],labelKeys:new Set,tainted:!1}));try{return await Mt(e,{route:n,locationPath:l,stateOverrides:r,contextOverrides:i,prefetch:m},g.record,o)}finally{g.close()}},Mt=async(e,{route:t,locationPath:o,stateOverrides:n,contextOverrides:s,prefetch:r},i,m)=>{const l=()=>{if(m.closed)throw new Error("brender: this render was abandoned at its timeout")};let g;if(r){try{g=await Qe(e)}catch(d){m.closed||console.warn("[brender] SSR translation fetch failed:",d.message)}l()}const{window:f,document:c}=ye(),a=c.body;f.location.pathname=o;const u=[ne("document",c),ne("location",f.location),ne("localStorage",f.localStorage),ne("sessionStorage",f.sessionStorage)].map(At);m.undo.push(...u);try{const{createDomqlElement:d}=await _e();l();const y=$(e.app||{}),b={...e.config||{}};e.polyglot&&!b.polyglot&&(b.polyglot=e.polyglot),e.fetch&&!b.fetch&&(b.fetch=e.fetch),e.router&&!b.router&&(b.router=e.router);for(const w of Kt)e[w]!=null&&b[w]==null&&(b[w]=e[w]);const R=b.polyglot?{...b.polyglot}:void 0,z=ct(o,R);z&&f.localStorage.setItem(rt(R),z),g&&R&&(R.translations={...R.translations||{},...g});const _=$(e.state||{});(g||R)&&(_.root||(_.root={}),R&&(_.root.lang=Q(_.root.lang,R)),g&&(_.root.translations={..._.root.translations||{},...g})),ft();const S={};for(const w in e){if(yt.has(w))continue;const x=e[w];S[w]=x&&typeof x=="object"?$(x):x}const v={...S,state:_,...n?{state:{..._,...n}}:{},dependencies:$(e.dependencies||{}),components:$(e.components||{}),snippets:$(e.snippets||{}),pages:$(e.pages||{}),functions:{...e.functions||{},polyglot:ut,getActiveLang:ke,getLang:ke},methods:e.methods||{},designSystem:$(e.designSystem||{}),files:e.files||{},sharedLibraries:e.sharedLibraries||[],...b,...R?{polyglot:R}:{},document:c,window:f,parent:{node:a},initOptions:{},domqlOptions:{sourcemap:!1},firstRender:!1,sync:!1,inspect:!1,notifications:!1,isolateDesignSystem:!0,isolateFetchCache:!0,captureDesignSystem:!0,...s||{}},B=await at();l(),B&&(v.plugins=v.plugins||[],v.plugins.some(w=>w.name==="funcql")||v.plugins.push(B)),be();const K=Le(ve,()=>({entries:[],bytes:0,tainted:!1})),C=K.record;let j;try{j=await d(y,v),l();const w=Date.now(),x=r?2e3:50,W=ce=>new Promise(Ge=>setTimeout(Ge,ce));for(await W(Math.min(50,x));r&&!m.closed&&fe()>0&&Date.now()-w<x;)await W(10),fe()===0&&await W(Math.max(0,Math.min(50,x-(Date.now()-w))));if(l(),r&&await It(j,R)){l();const ce=Date.now();for(await W(Math.min(50,x));!m.closed&&fe()>0&&Date.now()-ce<x;)await W(10);l()}}finally{K.close()}const Y=C&&!C.tainted&&!(b.fetch&&b.fetch.seed===!1)?C.entries.slice():[];Se(a);const X=we(j),{elementPath:V}=await import("@symbo.ls/element");l();const M=ht(j,V),G=j?.context?.routerOptions?.contentElementKey||"content",A=j&&j[G],I=A&&typeof A=="object"&&A.__ref?A:void 0,O=ae(e,t,j,j?.state,I),L=[],N=c.head||c.querySelector("head");if(N)for(const w of N.querySelectorAll("style")){if(w.sheet&&w.sheet.cssRules)for(const x of w.sheet.cssRules)x.cssText&&L.push(x);if(!L.length){const x=w.textContent||"";x&&L.push({cssText:x})}}const he=L.map(w=>w.cssText),{globalCSS:k,classRules:E}=Jt(L);let D=Ie(a.innerHTML);const H=j?.state?.root,U=te(H,R),re=Ot(g,H);re&&(D=Me(D,Ce(re,U,R)));const Ke=i&&!i.tainted?{failedRequests:i.failures.slice(),rawLabelKeys:Bt(i.labelKeys,D,U,R,H)}:null;return{html:D,metadata:O,registry:X,brRegistry:M,element:j,emotionCSS:he,globalCSS:k,classRules:E,fetchSeed:Y,document:c,window:f,ssrTranslations:re||void 0,activeLang:U,diagnostics:Ke,preparedDesignSystem:v.preparedDesignSystem||null}}finally{for(const d of u)d()}},ne=(e,t)=>{const o=Object.getOwnPropertyDescriptor(globalThis,e);return o&&!o.configurable?!o.writable&&!o.set?()=>{}:(globalThis[e]=t,()=>{}):(Object.defineProperty(globalThis,e,{value:t,writable:!0,configurable:!0,enumerable:!0}),()=>{o?Object.defineProperty(globalThis,e,o):delete globalThis[e]})},It=async(e,t)=>{if(!t||!t.fetch||!e||typeof e.call!="function")return!1;const o=e.state&&e.state.root;if(!o)return!1;const n=te(o,t),s=o.translations&&o.translations[n];if(s&&typeof s=="object"&&Object.keys(s).length||t.translations&&t.translations[n])return!1;try{await e.call("loadTranslations",n,{inFlight:!0})}catch{}return!0},de=/\{\{\s*([^|{}]+?)\s*\|\s*polyglot\s*\}\}/g,ge=e=>e&&typeof e.parse=="function"?e.parse():e,Ot=(e,t)=>{const o=ge(t?.translations),n={};for(const s of[e,o])if(!(!s||typeof s!="object"))for(const r in s){const i=ge(s[r]);i&&typeof i=="object"&&(n[r]={...n[r]||{},...i})}return Object.keys(n).length?n:null},Ce=(e,t,o)=>e[t]||e[Q(void 0,o)]||Object.values(e)[0]||{},Me=(e,t)=>e.replace(de,(o,n)=>ee(t,n.trim())??o),Pt=/<script\b[^>]*\btype\s*=\s*["']?application\/json["']?[^>]*>[\s\S]*?<\/script\s*>/gi,Ft=(e,t)=>new RegExp(`(?:^|[^\\w.-])${nt(t)}(?![\\w-]|\\.\\w)`).test(e),Bt=(e,t,o,n,s)=>{const r=new Set,i=t.replace(Pt,"");for(const m of e)/\s/.test(m)||Re(m,o,n,s)===void 0&&Ft(i,m)&&r.add(m);for(const m of i.matchAll(de))r.add(m[1].trim());return[...r]},Lo=async(e,t={})=>{const{context:o={}}=t,{window:n,document:s}=ye(),r=s.body,{create:i}=await import("@symbo.ls/element"),m=await import("@symbo.ls/utils"),l={...gt,...o.components||{}},g={...m,...o.utils||{},...o.functions||{}};be();let f;try{f=i(e,{node:r},"root",{context:{document:s,window:n,...o,components:l,utils:g}})}catch{}Se(r);const c=f?we(f):{};return{html:Ie(r.innerHTML),registry:c,element:f}},Ie=e=>e.replace(/(<svg\b[^>]*>)([\s\S]*?)(<\/svg>)/gi,(t,o,n,s)=>{if(n.includes("<")){const r=n.replace(/</g,"<").replace(/>/g,">").replace(/&/g,"&").replace(/"/g,'"').replace(/'/g,"'");return o+r+s}return t}),Kt=["globalTheme","themeStorageKey","themeRoot","useReset","useVariable","useFontImport","useIconSprite","useSvgSprite","useDocumentTheme","useDefaultConfig","useDefaultIcons","useThemeSuffixedVars","verbose","semanticIcons"],Gt=new Set(["auto","system"]),Oe=e=>{if(!e||typeof e!="object")return null;const t=e.config&&typeof e.config=="object"?e.config:{};if((t.themeRoot!=null?t.themeRoot:e.themeRoot)!=null)return null;const n=t.globalTheme!=null?t.globalTheme:e.globalTheme;if(typeof n!="string")return null;const s=n.trim();return!s||Gt.has(s)?null:s},Nt=e=>String(e).replace(/&/g,"&").replace(/"/g,""").replace(/</g,"<"),Ht=/\.[A-Za-z_\\-]/,Ut=e=>{if(typeof e!="string"||!e)return!1;const t=e.replace(/"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*'/g,'""').replace(/\[[^\]]*\]/g,"[]");return!Ht.test(t)},Wt=/^\s*(:root|\[data-theme|\[data-skin)/,Pe=e=>{const t=e&&e.cssText;if(typeof t!="string")return null;if(/^@(-webkit-)?keyframes\b/.test(t))return"keyframes";if(t.startsWith("@font-face"))return null;if(typeof e.selectorText=="string")return Ut(e.selectorText)?Wt.test(e.selectorText)?"root":"reset":null;const o=e.cssRules&&Array.from(e.cssRules);if(o&&o.length&&/^@(media|supports|container)\b/.test(t)){const n=new Set(o.map(Pe));return n.has(null)||n.size!==1?n.has(null)?null:"reset":[...n][0]}return null},Jt=e=>{const t={root:[],reset:[],keyframes:[]},o=[];for(const n of e||[]){const s=Pe(n);s?t[s].push(n.cssText):n&&n.cssText&&o.push(n.cssText)}return{globalCSS:{rootRule:t.root.join(`
|
|
3
3
|
`),resetRules:t.reset.join(`
|
|
4
4
|
`),keyframeRules:t.keyframes.join(`
|
|
5
|
-
`),fontFaceCSS:""},classRules:o}};let
|
|
6
|
-
`),
|
|
5
|
+
`),fontFaceCSS:""},classRules:o}};let se=new Set;const Do=()=>{se=new Set},$o=()=>Array.from(se).join(`
|
|
6
|
+
`),Ao=(e,t)=>e.replace(/<style data-emotion="smbls">[\s\S]*?<\/style>/,t?`<style data-emotion="smbls">
|
|
7
7
|
${t}
|
|
8
|
-
</style>`:""),
|
|
9
|
-
`),classRules:i.classRules.slice(),globalCSS:l,resetCss:l.resetRules,fontLinks:
|
|
10
|
-
`),
|
|
11
|
-
${
|
|
12
|
-
${
|
|
13
|
-
${
|
|
14
|
-
</style>`,
|
|
15
|
-
${
|
|
16
|
-
</style>`:"",
|
|
17
|
-
`:"",
|
|
18
|
-
`:"";G=`${
|
|
8
|
+
</style>`:""),qo=async(e,t={})=>{const{route:o="/",pathname:n,prefetch:s=!0,timeout:r}=t,i=await qe(e,{route:o,pathname:n,prefetch:s,timeout:r});if(!i)return null;const m=e.designSystem||{},l=i.globalCSS;let g=null;try{const c=zt(i.element);Object.keys(c).length&&(g=c)}catch{}const f=i.activeLang;return{html:i.html,css:i.classRules.join(`
|
|
9
|
+
`),classRules:i.classRules.slice(),globalCSS:l,resetCss:l.resetRules,fontLinks:Be(m),metadata:i.metadata||ae(e,o),brKeyCount:i.registry?Object.keys(i.registry).length:0,brRegistry:i.brRegistry||{},fetchSeed:i.fetchSeed||[],ssrTranslations:i.ssrTranslations,prefetchedState:g,activeLang:f,theme:Oe(e),diagnostics:i.diagnostics,preparedDesignSystem:i.preparedDesignSystem||null}},zt=e=>{const t={};return Ee(e,o=>{const n=o.fetch;if(!(!n||typeof n!="object"||!o.state))for(const s of Array.isArray(n)?n:[n]){const r=s&&typeof s=="object"&&typeof s.as=="string"?s.as:null;if(!r)continue;const i=r.startsWith("~/"),m=i?r.slice(2):r,l=i?o.state.root:o.state,g=ge(l&&l[m]);m&&g!=null&&typeof g!="function"&&(t[m]=g)}}),t},Co=async(e,t="/",o={})=>{const{lang:n,themeColor:s,isr:r,hydrate:i=!0,prefetch:m=!0,shell:l,adoptDom:g=!1,pathname:f,eagerImages:c=Fe,preloadScripts:a=!0,nonce:u,timeout:d,stamp:y,time:b}=o,R=eo(u),z=n||e.state?.lang||e.app?.metadata?.lang||"en",_=Oe(e),S=await qe(e,{route:t,pathname:f,prefetch:m,timeout:d});if(!S)return null;const v={...S.metadata};if(s&&(v["theme-color"]=s),typeof l=="string"&&!e.name){const k="\0brender-undeclared-title\0";if(ae({...e,name:k},t,S.element,S.element?.state).title===k)for(const D of["title","og:title","twitter:title"])v[D]===S.metadata.title&&delete v[D]}const B=Xe(v);for(const k of S.classRules)k&&se.add(k);const K=Array.from(se).join(`
|
|
10
|
+
`),C=S.globalCSS,j=`<style data-brender>
|
|
11
|
+
${C.rootRule||""}
|
|
12
|
+
${C.resetRules||""}
|
|
13
|
+
${C.keyframeRules||""}
|
|
14
|
+
</style>`,Y=K?`<style data-emotion="smbls">
|
|
15
|
+
${K}
|
|
16
|
+
</style>`:"",X=Be(e.designSystem||{}),V=Object.keys(S.registry).length,M=Qt({brRegistry:S.brRegistry,fetchSeed:S.fetchSeed,adoptDom:g,stamp:y,time:b});let G="";if(r&&r.clientScript){const k=Number.isInteger(o.depth)?o.depth:t==="/"?0:t.replace(/^\/|\/$/g,"").split("/").length,E=k>0?"../".repeat(k):"./";if(i){const D=it({polyglot:e.polyglot||e.config?.polyglot,translations:S.ssrTranslations,lang:S.activeLang,pathname:f||t,attrs:R}),H=D?D+`
|
|
17
|
+
`:"",U=M.blocks?M.blocks+`
|
|
18
|
+
`:"";G=`${H}${U}<script type="module" src="${E}${r.clientScript}"${R}><\/script>`}else G=`<script type="module"${R}>
|
|
19
19
|
{
|
|
20
20
|
const brEls = document.querySelectorAll('body > :not(script):not(style)')
|
|
21
21
|
const observer = new MutationObserver((mutations) => {
|
|
@@ -32,23 +32,23 @@ ${B}
|
|
|
32
32
|
observer.observe(document.body, { childList: true })
|
|
33
33
|
}
|
|
34
34
|
<\/script>
|
|
35
|
-
<script type="module" src="${
|
|
36
|
-
${
|
|
37
|
-
`),body:
|
|
38
|
-
<html lang="${
|
|
35
|
+
<script type="module" src="${E}${r.clientScript}"${R}><\/script>`}const A={...e.config||{}};e.polyglot&&!A.polyglot&&(A.polyglot=e.polyglot);const I=A.polyglot;let O=B;if(I){const k={...I.translations||{}};for(const E in S.ssrTranslations||{})k[E]={...k[E]||{},...S.ssrTranslations[E]};O=Me(B,Ce(k,S.activeLang,I))}const L=S.diagnostics;if(L)for(const k of O.matchAll(de)){const E=k[1].trim();L.rawLabelKeys.includes(E)||L.rawLabelKeys.push(E)}const N=Vt(S.html,c);return typeof l=="string"?{html:Ve(l,{headTags:`${O}
|
|
36
|
+
${M.meta}`,headEnd:[X,j,Y].filter(Boolean).join(`
|
|
37
|
+
`),body:N,depth:Number.isInteger(o.depth)?o.depth:0,bootScripts:M.blocks,lang:n||(I?S.activeLang:void 0),theme:_,preloadScripts:a}),route:t,brKeyCount:V,shell:!0,diagnostics:L,preparedDesignSystem:S.preparedDesignSystem||null}:{html:`<!DOCTYPE html>
|
|
38
|
+
<html lang="${z}"${_?` data-theme="${Nt(_)}"`:""}>
|
|
39
39
|
<head>
|
|
40
|
-
${
|
|
41
|
-
${
|
|
42
|
-
${
|
|
40
|
+
${O}${r&&r.clientScript&&i?`
|
|
41
|
+
${M.meta}`:""}
|
|
42
|
+
${X}
|
|
43
43
|
|
|
44
|
-
${
|
|
45
|
-
${
|
|
44
|
+
${j}
|
|
45
|
+
${Y}
|
|
46
46
|
</head>
|
|
47
47
|
<body>
|
|
48
|
-
${
|
|
48
|
+
${N}
|
|
49
49
|
${G}
|
|
50
50
|
</body>
|
|
51
|
-
</html>`,route:t,brKeyCount:
|
|
52
|
-
`):""},
|
|
53
|
-
`+
|
|
54
|
-
`)}},
|
|
51
|
+
</html>`,route:t,brKeyCount:V,diagnostics:L,preparedDesignSystem:S.preparedDesignSystem||null}},Fe=2,Yt=/<img\b(?:[^>"']|"[^"]*"|'[^']*')*>/gi,Xt=/\sloading\s*=/i,Vt=(e,t=Fe)=>{if(t===!1||t==null||typeof e!="string")return e;const o=Math.max(0,Number(t)||0);let n=0;return e.replace(Yt,s=>n++<o||Xt.test(s)?s:s.replace(/^<img\b/i,'<img loading="lazy"'))},Be=e=>{if(!e)return"";const t=e.font_family||e.fontFamily||{},o=new Set;for(const s of Object.values(t)){if(typeof s!="string")continue;const r=s.match(/'([^']+)'/);r&&o.add(r[1])}return o.size?['<link rel="preconnect" href="https://fonts.googleapis.com">','<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>',`<link href="https://fonts.googleapis.com/css2?${[...o].map(s=>`family=${s.replace(/\s+/g,"+")}:wght@300;400;500;600;700`).join("&")}&display=swap" rel="stylesheet">`].join(`
|
|
52
|
+
`):""},Qt=({brRegistry:e,fetchSeed:t,adoptDom:o=!1,stamp:n,time:s}={})=>{const r=o&&e&&Object.keys(e).length?tt(e):"",i=lt(t);return{meta:`<meta name="brender" content="${r?"hydrate":"replace"}">
|
|
53
|
+
`+ot(Zt(n,s)),blocks:[r,i].filter(Boolean).join(`
|
|
54
|
+
`)}},Zt=(e,t)=>{const o=typeof t=="number"&&isFinite(t)?Math.round(t):Date.now();return{stamp:e!=null&&e!==""?String(e):new Date(o).toISOString(),time:o}},eo=e=>{if(e==null||e==="")return"";const t=String(e);if(!/^[A-Za-z0-9+/=_-]+$/.test(t))throw new Error("brender: a nonce is base64 or base64url text");return` nonce="${t}"`};export{Fe as EAGER_IMAGES_DEFAULT,je as SMBLS_SSR_SPECIFIER,vo as adoptionScripts,Zt as buildStamp,Oe as fixedThemeOf,$o as getAccumulatedEmotionCSS,Vt as markLazyImages,Qt as prerenderParts,qe as render,Lo as renderElement,Co as renderPage,qo as renderRoute,Ao as replaceEmotionCSS,Do as resetGlobalCSSCache,Jt as splitCapturedCSS};
|
package/dist/esm/shell.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import{insertAfterImportMap as
|
|
2
|
-
`)},
|
|
3
|
-
${
|
|
4
|
-
${
|
|
5
|
-
${
|
|
6
|
-
`:"",g=
|
|
1
|
+
import{insertAfterImportMap as _}from"@symbo.ls/utils";const j=/<head(\s[^>]*)?>/i,q=/<body(\s[^>]*)?>/i,u=(e,t)=>{const s=new RegExp(`\\s${t}\\s*=\\s*("([^"]*)"|'([^']*)'|([^\\s>]+))`,"i").exec(e);return s?s[2]??s[3]??s[4]??"":null},v=e=>{const t=e.slice(0,12).toLowerCase();if(t.startsWith("<title"))return"title";if(t.startsWith("<meta")){if(u(e,"charset")!==null)return"charset";for(const s of["name","property","http-equiv","itemprop"]){const r=u(e,s);if(r!==null)return`${s}:${r.toLowerCase()}`}return null}if(t.startsWith("<link")){const s=(u(e,"rel")||"").toLowerCase();return s==="canonical"?"link:canonical":s==="icon"||s==="shortcut icon"?`link:${s}:${u(e,"href")||""}`:s==="alternate"&&u(e,"hreflang")!==null?`link:alternate:${(u(e,"hreflang")||"").toLowerCase()}`:null}return null},E=/<title[^>]*>[\s\S]*?<\/title\s*>|<meta\b[^>]*>|<link\b[^>]*>/gi,W=/<(script|style|noscript|template|textarea)\b[\s\S]*?<\/\1\s*>/gi,x=e=>[...e.matchAll(W)].map(t=>[t.index,t.index+t[0].length,t[0]]),I=(e,t,s=r=>r)=>{let r="",i=0;for(const[o,l,a]of x(e))r+=t(e.slice(i,o))+s(a),i=l;return r+t(e.slice(i))},h=(e,t,s=0)=>{const r=x(e),i=new RegExp(t.source,t.flags.includes("g")?t.flags:t.flags+"g");i.lastIndex=s;let o;for(;o=i.exec(e);){const l=o.index,a=r.find(([f,n])=>l>f&&l<n);if(!a)return o;i.lastIndex=a[1]}return null},B=e=>!!e&&!/^(?:[a-z][a-z0-9+.-]*:|\/|#|\?)/i.test(e),L=(e,t)=>e.replace(/(\s(?:src|href)\s*=\s*)(?:(["'])([^"']*)\2|([^\s"'>]+))/gi,(s,r,i,o,l)=>{const a=i?o:l;if(!B(a))return s;const f=i||"";return`${r}${f}${t}${a.replace(/^\.\//,"")}${f}`}),D=(e,t)=>{if(!t)return e;const s="../".repeat(t);return I(e,r=>r.replace(/<link\b[^>]*>/gi,i=>L(i,s)),r=>/^<script\b/i.test(r)?r.replace(/^<script\b[^>]*>/i,i=>L(i,s)):r)},H=new Set(["","module","text/javascript","application/javascript"]),m=(e,t)=>new RegExp(`\\s${t}(?:\\s*=|\\s|>|/)`,"i").test(e),T=e=>{const t=[],s=new Set;for(const[,,r]of x(e)){if(!/^<script\b/i.test(r))continue;const i=r.slice(0,r.indexOf(">")+1),o=u(i,"src");if(!o||s.has(o))continue;const l=(u(i,"type")||"").trim().toLowerCase();if(!H.has(l)||m(i,"async")||m(i,"nomodule"))continue;s.add(o);const a=["crossorigin","integrity","referrerpolicy"].map(n=>{const d=u(i,n);return d===null?m(i,n)?` ${n}`:"":` ${n}="${d.replace(/"/g,""")}"`}).join(""),f=o.replace(/"/g,""");t.push(l==="module"?`<link rel="modulepreload" href="${f}" fetchpriority="high"${a}>`:`<link rel="preload" as="script" href="${f}" fetchpriority="high"${a}>`)}return t.join(`
|
|
2
|
+
`)},P=(e,t,s)=>{const r=h(e,/<html(\s[^>]*)?>/i);if(!r)return e;const i=r[0],o=String(s).replace(/&/g,"&").replace(/"/g,"""),l=u(i,t)!==null?i.replace(new RegExp(`(\\s${t}\\s*=\\s*)(?:"[^"]*"|'[^']*'|[^\\s>]+)`,"i"),`$1"${o}"`):i.replace(/^<html/i,`<html ${t}="${o}"`);return e.slice(0,r.index)+l+e.slice(r.index+i.length)},K=(e,{headTags:t="",headEnd:s="",body:r="",depth:i=0,bootScripts:o="",lang:l,theme:a,preloadScripts:f=!1}={})=>{if(typeof e!="string"||!e.trim())throw new Error("brender: the shell document is empty");let n=D(e,i);l&&(n=P(n,"lang",l)),a&&(n=P(n,"data-theme",a));const d=f?T(n):"";if(d){const c=_(n,d);c!==null?n=c:s=s?`${d}
|
|
3
|
+
${s}`:d}const w=new Set;for(const c of t.matchAll(E)){const p=v(c[0]);p&&w.add(p)}const y=c=>I(c,p=>p.replace(E,S=>w.has(v(S))?"":S)),O=t?`
|
|
4
|
+
${t}`:"",b=s?`
|
|
5
|
+
${s}
|
|
6
|
+
`:"",g=h(n,j),k=g&&h(n,/<\/head\s*>/i,g.index);if(g&&k){const c=g.index+g[0].length,p=k.index;n=n.slice(0,c)+O+y(n.slice(c,p))+b+n.slice(p)}else{n=y(n);const c=h(n,/<html(\s[^>]*)?>/i)||h(n,/<!doctype[^>]*>/i),p=c?c.index+c[0].length:0;n=n.slice(0,p)+O+b+n.slice(p)}const A=`
|
|
7
7
|
${r}
|
|
8
|
-
${
|
|
9
|
-
`:""}`,$=
|
|
8
|
+
${o?o+`
|
|
9
|
+
`:""}`,$=h(n,q);if($){const c=$.index+$[0].length;return n.slice(0,c)+A+n.slice(c)}const C=h(n,/<\/(?:body|html)\s*>/i),R=C?C.index:n.length;return n.slice(0,R)+A+n.slice(R)};export{K as composeIntoShell,v as headTagKey,T as scriptPreloads};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@symbo.ls/brender",
|
|
3
|
-
"version": "3.14.
|
|
3
|
+
"version": "3.14.670",
|
|
4
4
|
"license": "CC-BY-NC-4.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"module": "./dist/esm/index.js",
|
|
@@ -46,18 +46,18 @@
|
|
|
46
46
|
"prepublishOnly": "npm run build"
|
|
47
47
|
},
|
|
48
48
|
"dependencies": {
|
|
49
|
-
"@symbo.ls/css": "^3.14.
|
|
50
|
-
"@symbo.ls/default-config": "^3.14.
|
|
51
|
-
"@symbo.ls/element": "^3.14.
|
|
52
|
-
"@symbo.ls/fetch": "^3.14.
|
|
53
|
-
"@symbo.ls/helmet": "^3.14.
|
|
54
|
-
"@symbo.ls/scratch": "^3.14.
|
|
55
|
-
"@symbo.ls/utils": "^3.14.
|
|
49
|
+
"@symbo.ls/css": "^3.14.782",
|
|
50
|
+
"@symbo.ls/default-config": "^3.14.789",
|
|
51
|
+
"@symbo.ls/element": "^3.14.809",
|
|
52
|
+
"@symbo.ls/fetch": "^3.14.669",
|
|
53
|
+
"@symbo.ls/helmet": "^3.14.671",
|
|
54
|
+
"@symbo.ls/scratch": "^3.14.792",
|
|
55
|
+
"@symbo.ls/utils": "^3.14.845",
|
|
56
56
|
"esbuild": "^0.28.1",
|
|
57
57
|
"linkedom": "^0.16.8"
|
|
58
58
|
},
|
|
59
59
|
"peerDependencies": {
|
|
60
|
-
"smbls": "^3.14.
|
|
60
|
+
"smbls": "^3.14.844"
|
|
61
61
|
},
|
|
62
62
|
"optionalDependencies": {
|
|
63
63
|
"@symbo.ls/funcql": "^3.14.0"
|
package/prefetch.js
CHANGED
|
@@ -269,7 +269,9 @@ export const fetchSSRTranslations = async (data) => {
|
|
|
269
269
|
|
|
270
270
|
const fetchConfig = polyglot.fetch
|
|
271
271
|
const rpcName = fetchConfig.rpc || fetchConfig.from || 'get_translations_if_changed'
|
|
272
|
-
|
|
272
|
+
// `languages` may be a function (utils polyglotLanguages); none: the default
|
|
273
|
+
const listed = (await import('@symbo.ls/utils')).polyglotLanguages(polyglot, false)
|
|
274
|
+
const languages = listed.length ? listed : [polyglot.defaultLang || 'en']
|
|
273
275
|
|
|
274
276
|
const translations = {}
|
|
275
277
|
|
package/render.js
CHANGED
|
@@ -1351,7 +1351,13 @@ const renderWithDiagnostics = async (data, { route, locationPath, stateOverrides
|
|
|
1351
1351
|
// Extract metadata for the rendered route
|
|
1352
1352
|
// Pass the rendered element and its state so function-valued metadata
|
|
1353
1353
|
// (e.g. detail page titles from fetched data) can be resolved
|
|
1354
|
-
|
|
1354
|
+
// The routed page's own metadata resolves against the page element and its
|
|
1355
|
+
// state, where its fetched data lands — as the client's helmet resolves it
|
|
1356
|
+
// (XMA round 5, item L: the head carried the app's defaults).
|
|
1357
|
+
const contentKey = element?.context?.routerOptions?.contentElementKey || 'content'
|
|
1358
|
+
const routed = element && element[contentKey]
|
|
1359
|
+
const pageElement = routed && typeof routed === 'object' && routed.__ref ? routed : undefined
|
|
1360
|
+
const metadata = extractMetadata(data, route, element, element?.state, pageElement)
|
|
1355
1361
|
|
|
1356
1362
|
// Extract CSS from style tags in virtual head (atomic CSS engine writes here)
|
|
1357
1363
|
const capturedRules = []
|
|
@@ -1595,6 +1601,37 @@ const SCRATCH_CONFIG_FLAGS = [
|
|
|
1595
1601
|
'useThemeSuffixedVars', 'verbose', 'semanticIcons',
|
|
1596
1602
|
]
|
|
1597
1603
|
|
|
1604
|
+
// The theme a built page's `<html data-theme>` carries — the project's
|
|
1605
|
+
// `globalTheme` when it is a FIXED theme ('light', 'dark' or any named
|
|
1606
|
+
// scheme), else null. The global CSS keys every scheme on `[data-theme=…]`
|
|
1607
|
+
// and falls back to `@media (prefers-color-scheme) { :root:not([data-theme]) }`,
|
|
1608
|
+
// so a page with no attribute painted the OS scheme until the client's boot
|
|
1609
|
+
// (smbls resolveAndApplyTheme, scratch applyThemeRoot) stamped the project's
|
|
1610
|
+
// one: on a `globalTheme: 'light'` project, a visitor in OS dark mode saw the
|
|
1611
|
+
// dark tokens from first paint to boot (xma.info: white ink on the white
|
|
1612
|
+
// header, 237–771 ms). The client writes the same value at boot, so the
|
|
1613
|
+
// attribute is never removed or changed on adoption.
|
|
1614
|
+
//
|
|
1615
|
+
// 'auto' (and 'system', unset) keeps the OS fallback: the client resolves it
|
|
1616
|
+
// from prefers-color-scheme, or from a choice stored under `themeStorageKey`
|
|
1617
|
+
// — which smbls consults ONLY for 'auto', so a fixed theme has no stored
|
|
1618
|
+
// choice that could differ. A config with its own `themeRoot` stamps that
|
|
1619
|
+
// node, not `<html>`, so it gets none.
|
|
1620
|
+
const UNFORCED_THEMES = new Set(['auto', 'system'])
|
|
1621
|
+
export const fixedThemeOf = (data) => {
|
|
1622
|
+
if (!data || typeof data !== 'object') return null
|
|
1623
|
+
const config = data.config && typeof data.config === 'object' ? data.config : {}
|
|
1624
|
+
const themeRoot = config.themeRoot != null ? config.themeRoot : data.themeRoot
|
|
1625
|
+
if (themeRoot != null) return null
|
|
1626
|
+
const theme = config.globalTheme != null ? config.globalTheme : data.globalTheme
|
|
1627
|
+
if (typeof theme !== 'string') return null
|
|
1628
|
+
const value = theme.trim()
|
|
1629
|
+
if (!value || UNFORCED_THEMES.has(value)) return null
|
|
1630
|
+
return value
|
|
1631
|
+
}
|
|
1632
|
+
|
|
1633
|
+
const escapeAttr = (value) => String(value).replace(/&/g, '&').replace(/"/g, '"').replace(/</g, '<')
|
|
1634
|
+
|
|
1598
1635
|
// ── Global CSS: the render's own capture, split ────────────────────────────
|
|
1599
1636
|
// The rules smbls init injects into the virtual <head> during render() ARE
|
|
1600
1637
|
// the page's global CSS — the :root variables, scheme and skin blocks, the
|
|
@@ -1755,6 +1792,9 @@ export const renderRoute = async (data, options = {}) => {
|
|
|
1755
1792
|
ssrTranslations: result.ssrTranslations,
|
|
1756
1793
|
prefetchedState,
|
|
1757
1794
|
activeLang,
|
|
1795
|
+
// the `<html data-theme>` a page of this render carries (fixedThemeOf);
|
|
1796
|
+
// null when the project follows the OS
|
|
1797
|
+
theme: fixedThemeOf(data),
|
|
1758
1798
|
// failed requests and raw label keys (see `DIAG`); null when an
|
|
1759
1799
|
// overlapping render made them unknowable
|
|
1760
1800
|
diagnostics: result.diagnostics,
|
|
@@ -1837,6 +1877,9 @@ export const renderPage = async (data, route = '/', options = {}) => {
|
|
|
1837
1877
|
|
|
1838
1878
|
// Detect lang from project config, app metadata, or default
|
|
1839
1879
|
const htmlLang = lang || data.state?.lang || data.app?.metadata?.lang || 'en'
|
|
1880
|
+
// The project's fixed theme on <html>, so the first paint uses its tokens
|
|
1881
|
+
// and not the OS scheme's (see fixedThemeOf).
|
|
1882
|
+
const htmlTheme = fixedThemeOf(data)
|
|
1840
1883
|
|
|
1841
1884
|
// Use the full smbls pipeline for rendering. `pathname` is the address the
|
|
1842
1885
|
// page is rendered at — the router matches it, location and every
|
|
@@ -1997,6 +2040,7 @@ export const renderPage = async (data, route = '/', options = {}) => {
|
|
|
1997
2040
|
// boot — a page rendered for /en/… kept the shell's `lang="ka"`.
|
|
1998
2041
|
// Only when the project has languages (or the caller names one).
|
|
1999
2042
|
lang: lang || (polyglotCfg ? result.activeLang : undefined),
|
|
2043
|
+
theme: htmlTheme,
|
|
2000
2044
|
preloadScripts
|
|
2001
2045
|
})
|
|
2002
2046
|
return { html, route, brKeyCount, shell: true, diagnostics, preparedDesignSystem: result.preparedDesignSystem || null }
|
|
@@ -2005,7 +2049,7 @@ export const renderPage = async (data, route = '/', options = {}) => {
|
|
|
2005
2049
|
// (The empty line after the font links held a @font-face <style> that
|
|
2006
2050
|
// splitCapturedCSS never fills — @font-face stays in the class stream.)
|
|
2007
2051
|
const html = `<!DOCTYPE html>
|
|
2008
|
-
<html lang="${htmlLang}">
|
|
2052
|
+
<html lang="${htmlLang}"${htmlTheme ? ` data-theme="${escapeAttr(htmlTheme)}"` : ''}>
|
|
2009
2053
|
<head>
|
|
2010
2054
|
${resolvedHeadTags}${isr && isr.clientScript && hydrate ? `\n${prerender.meta}` : ''}
|
|
2011
2055
|
${fontLinks}
|
package/shell.js
CHANGED
|
@@ -168,15 +168,16 @@ export const scriptPreloads = (html) => {
|
|
|
168
168
|
return links.join('\n')
|
|
169
169
|
}
|
|
170
170
|
|
|
171
|
-
// `<html
|
|
172
|
-
|
|
171
|
+
// One attribute on `<html>` set to `value` — replaced when the shell already
|
|
172
|
+
// carries it, added otherwise.
|
|
173
|
+
const setHtmlAttr = (html, name, value) => {
|
|
173
174
|
const htmlOpen = findOutside(html, /<html(\s[^>]*)?>/i)
|
|
174
175
|
if (!htmlOpen) return html
|
|
175
176
|
const tag = htmlOpen[0]
|
|
176
|
-
const
|
|
177
|
-
const next = attr(tag,
|
|
178
|
-
? tag.replace(
|
|
179
|
-
: tag.replace(/^<html/i, `<html
|
|
177
|
+
const escaped = String(value).replace(/&/g, '&').replace(/"/g, '"')
|
|
178
|
+
const next = attr(tag, name) !== null
|
|
179
|
+
? tag.replace(new RegExp(`(\\s${name}\\s*=\\s*)(?:"[^"]*"|'[^']*'|[^\\s>]+)`, 'i'), `$1"${escaped}"`)
|
|
180
|
+
: tag.replace(/^<html/i, `<html ${name}="${escaped}"`)
|
|
180
181
|
return html.slice(0, htmlOpen.index) + next + html.slice(htmlOpen.index + tag.length)
|
|
181
182
|
}
|
|
182
183
|
|
|
@@ -191,16 +192,19 @@ const setHtmlLang = (html, lang) => {
|
|
|
191
192
|
* markup (the hydration registry and the fetch seed — renderPage
|
|
192
193
|
* prerenderParts)
|
|
193
194
|
* @param {string} [parts.lang] - the page's language, written to `<html lang>`
|
|
195
|
+
* @param {string} [parts.theme] - the project's fixed theme, written to
|
|
196
|
+
* `<html data-theme>` (see render.js fixedThemeOf); none for 'auto'
|
|
194
197
|
* @param {boolean} [parts.preloadScripts=false] - preload the shell's own
|
|
195
198
|
* scripts with high priority (see scriptPreloads)
|
|
196
199
|
* @returns {string}
|
|
197
200
|
*/
|
|
198
|
-
export const composeIntoShell = (shell, { headTags = '', headEnd = '', body = '', depth = 0, bootScripts = '', lang, preloadScripts = false } = {}) => {
|
|
201
|
+
export const composeIntoShell = (shell, { headTags = '', headEnd = '', body = '', depth = 0, bootScripts = '', lang, theme, preloadScripts = false } = {}) => {
|
|
199
202
|
if (typeof shell !== 'string' || !shell.trim()) {
|
|
200
203
|
throw new Error('brender: the shell document is empty')
|
|
201
204
|
}
|
|
202
205
|
let html = rebaseAssets(shell, depth)
|
|
203
|
-
if (lang) html =
|
|
206
|
+
if (lang) html = setHtmlAttr(html, 'lang', lang)
|
|
207
|
+
if (theme) html = setHtmlAttr(html, 'data-theme', theme)
|
|
204
208
|
// The app's preloads go right after the shell's import map when it has one
|
|
205
209
|
// (parcel's page does): a modulepreload before it gets the map rejected,
|
|
206
210
|
// and the app's lazy bundles resolve through it. Else first in what the
|