@estjs/server 0.0.16-beta.4 → 0.0.16-beta.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,3 +1,2 @@
1
- 'use strict';var shared=require('@estjs/shared'),template=require('@estjs/template'),internal=require('@estjs/template/internal'),async_hooks=require('async_hooks'),signals=require('@estjs/signals');var Q=Object.defineProperty;var w=Object.getOwnPropertySymbols;var V=Object.prototype.hasOwnProperty,nn=Object.prototype.propertyIsEnumerable;var b=(n,r,t)=>r in n?Q(n,r,{enumerable:true,configurable:true,writable:true,value:t}):n[r]=t,A=(n,r)=>{for(var t in r||(r={}))V.call(r,t)&&b(n,t,r[t]);if(w)for(var t of w(r))nn.call(r,t)&&b(n,t,r[t]);return n};var a=(n,r,t)=>new Promise((e,i)=>{var o=f=>{try{c(t.next(f));}catch(m){i(m);}},s=f=>{try{c(t.throw(f));}catch(m){i(m);}},c=f=>f.done?e(f.value):Promise.resolve(f.value).then(o,s);c((t=t.apply(n,r)).next());});function tn(){return {teleports:Object.create(null)}}var E=new async_hooks.AsyncLocalStorage;function d(){var n;return (n=E.getStore())!=null?n:null}function x(n,r){return E.run(n,r)}function u(n,r=false){return shared.isNil(n)?"":shared.isString(n)?n:shared.isArray(n)?n.map(t=>u(t,r)).join(""):shared.isFunction(n)?u(n(),r):String(n)}function T(n){return n===false||shared.isNil(n)?"":shared.isString(n)?shared.escapeHTML(n):shared.isArray(n)?n.map(r=>T(r)).join(""):shared.isFunction(n)?T(n()):shared.escapeHTML(String(n))}var en=/data-idx="(\d+)"|<!--(\d+)-->/g;function on(n,r){let t=n.indexOf("<");if(t===-1)return n;let e;for(let i=t+1;i<n.length;i++){let o=n[i];if(e){o===e&&(e=void 0);continue}if(o==='"'||o==="'"){e=o;continue}if(o===">"){let s=i;for(let c=i-1;c>t;c--){let f=n[c];if(!(f===" "||f===`
2
- `||f===" "||f==="\r")){f==="/"&&(s=c);break}}return `${n.slice(0,s)} data-hk="${r}"${n.slice(s)}`}}return n}function C(n,r){return on(n,r).replaceAll(en,(t,e,i)=>e!==void 0?`data-idx="${r}-${e}"`:`<!--${r}-${i}-->`)}function K(n,r=internal.getActiveScope()){let t=internal.createScope(r);try{return internal.runWithScope(t,n)}finally{internal.disposeScope(t);}}function un(n,r={},t=null){if(!shared.isFunction(n))return shared.error("Component must be a function"),"";template.resetHydrationKey();let e=x(t,()=>K(()=>n(r),null));return u(e)}function fn(n,r,...t){let e=n.length,i=t.length,o="";for(let s=0;s<e;s++)o+=n[s],s<i&&t[s]&&(o+=u(t[s]));return C(o,r)}function cn(e){return a(this,arguments,function*(n,r={},t=null){if(!shared.isFunction(n))return shared.error("Component must be a function"),"";template.resetHydrationKey();let i=internal.createScope(null);try{return yield x(t,()=>a(null,null,function*(){let o=internal.runWithScope(i,()=>n(r));return shared.isPromise(o)&&(o=yield o),S(o)}))}finally{internal.disposeScope(i);}})}function S(n){return a(this,null,function*(){return shared.isPromise(n)?S(yield n):Array.isArray(n)?(yield Promise.all(n.map(t=>S(t)))).join(""):shared.isFunction(n)?S(n()):u(n)})}function ln(n,r={}){if(!shared.isFunction(n))return shared.error("createSSGComponent: Component is not a function"),"";let t=K(()=>n(r));return u(t)}function mn(n){if(!n)return null;let{class:r,style:t}=n,e=r&&!shared.isString(r),i=!!t;if(!e&&!i)return n;let o=A({},n);return e&&(o.class=shared.normalizeClassName(r)),i&&(o.style=shared.normalizeStyle(t)),o}function D(n,r){if(signals.isSignal(r)||signals.isComputed(r))return D(n,r.value);if(!r&&r!==0)return "";if(n==="style"){let t=shared.normalizeStyle(r);return t?shared.isString(t)?` style="${t}"`:` style="${shared.styleToString(t)}"`:""}if(n==="class"){let t=shared.normalizeClassName(r);return t?` class="${t}"`:""}return n.startsWith("on")?"":r===true?` ${n}`:` ${n}="${shared.escapeHTML(String(r))}"`}function I(n,r){return shared.isNil(r)||r===false?"":r===true?` ${n}`:` ${n}="${shared.escapeHTML(String(r))}"`}function q(n){let r=X(n);return r?` class="${shared.escapeHTML(r)}"`:""}function U(n){if(shared.isNil(n))return "";if(shared.isString(n))return n?` style="${shared.escapeHTML(n)}"`:"";if(shared.isObject(n)){let r=n,t=[];for(let e in r){let i=r[e];if(i!=null&&i!==false){let o=e.startsWith("--")?e:Cn(e);t.push(`${o}:${shared.escapeHTML(String(i))}`);}}return t.length?` style="${t.join(";")}"`:""}return ""}function xn(n){if(!n||!shared.isObject(n))return "";let r="";for(let t in n)t==="children"||t==="ref"||t.startsWith("on")||(t==="class"||t==="className"?r+=q(n[t]):t==="style"?r+=U(n[t]):r+=I(t,n[t]));return r}function X(n){if(shared.isNil(n)||n===false)return "";if(shared.isString(n))return n;if(shared.isArray(n))return n.map(X).filter(Boolean).join(" ");if(shared.isObject(n)){let r=n;return Object.keys(r).filter(t=>!!r[t]).join(" ")}return String(n)}var Tn=/[A-Z]/g;function Cn(n){return n.replaceAll(Tn,r=>`-${r.toLowerCase()}`)}function yn(n){return u(n.children)}var Z="<!--teleport-anchor-->",v="<!--teleport-start-->",J="<!--teleport-end-->";function kn(n){var s;let{target:r,children:t}=n,e=u(t);if((shared.isFunction(n.disabled)?!!n.disabled():!!n.disabled)||!r)return e;let o=d();return !o||!shared.isString(r)?e:(o.teleports[r]=((s=o.teleports[r])!=null?s:"")+v+e+J,Z)}function wn(n){let{children:r,fallback:t}=n;return shared.isNil(r)?u(t):u(r)}function bn(n){var r,t;return shared.isNil(n)?[]:shared.isObject(n)&&"value"in n?(r=n.value)!=null?r:[]:shared.isFunction(n)?(t=n())!=null?t:[]:n}function An(n){let r=bn(n.each);if(r.length===0)return u(n.fallback);let t=n.children;return shared.isFunction(t)?r.map((e,i)=>u(t(e,i))).join(""):""}Object.defineProperty(exports,"escapeHTML",{enumerable:true,get:function(){return shared.escapeHTML}});Object.defineProperty(exports,"getHydrationKey",{enumerable:true,get:function(){return template.getHydrationKey}});Object.defineProperty(exports,"resetHydrationKey",{enumerable:true,get:function(){return template.resetHydrationKey}});exports.For=An;exports.Fragment=yn;exports.Portal=kn;exports.Suspense=wn;exports.TELEPORT_BLOCK_END=J;exports.TELEPORT_BLOCK_START=v;exports.TELEPORT_CALLSITE_ANCHOR=Z;exports.addAttributes=C;exports.convertTextChildToString=T;exports.convertToString=u;exports.createSSGComponent=ln;exports.createSSRContext=tn;exports.getSSRContext=d;exports.normalizeProps=mn;exports.render=fn;exports.renderToString=un;exports.renderToStringAsync=cn;exports.setSSGAttr=D;exports.ssrAttr=I;exports.ssrClass=q;exports.ssrSpread=xn;exports.ssrStyle=U;//# sourceMappingURL=server.cjs.js.map
3
- //# sourceMappingURL=server.cjs.js.map
1
+ 'use strict';var shared=require('@estjs/shared'),template=require('@estjs/template'),internal=require('@estjs/template/internal'),async_hooks=require('async_hooks'),signals=require('@estjs/signals');var V=Object.defineProperty;var w=Object.getOwnPropertySymbols;var nn=Object.prototype.hasOwnProperty,rn=Object.prototype.propertyIsEnumerable;var b=(n,r,t)=>r in n?V(n,r,{enumerable:true,configurable:true,writable:true,value:t}):n[r]=t,A=(n,r)=>{for(var t in r||(r={}))nn.call(r,t)&&b(n,t,r[t]);if(w)for(var t of w(r))rn.call(r,t)&&b(n,t,r[t]);return n};var S=(n,r,t)=>new Promise((e,o)=>{var i=c=>{try{f(t.next(c));}catch(m){o(m);}},s=c=>{try{f(t.throw(c));}catch(m){o(m);}},f=c=>c.done?e(c.value):Promise.resolve(c.value).then(i,s);f((t=t.apply(n,r)).next());});function en(){return {teleports:Object.create(null)}}var E=new async_hooks.AsyncLocalStorage;function d(){var n;return (n=E.getStore())!=null?n:null}function x(n,r){return E.run(n,r)}function u(n,r=false){return shared.isNil(n)?"":shared.isString(n)?n:shared.isArray(n)?n.map(t=>u(t,r)).join(""):shared.isFunction(n)?u(n(),r):String(n)}function T(n){return n===false||shared.isNil(n)?"":shared.isString(n)?shared.escapeHTML(n):shared.isArray(n)?n.map(r=>T(r)).join(""):shared.isFunction(n)?T(n()):shared.escapeHTML(String(n))}var on=/data-idx="(\d+)"|<!--(\d+)-->/g;function sn(n,r){let t=n.indexOf("<");if(t===-1)return n;let e;for(let o=t+1;o<n.length;o++){let i=n[o];if(e){i===e&&(e=void 0);continue}if(i==='"'||i==="'"){e=i;continue}if(i===">"){let s=o;for(let f=o-1;f>t;f--){let c=n[f];if(!(c===" "||c===`
2
+ `||c===" "||c==="\r")){c==="/"&&(s=f);break}}return `${n.slice(0,s)} data-hk="${r}"${n.slice(s)}`}}return n}function C(n,r){return sn(n,r).replaceAll(on,(t,e,o)=>e!==void 0?`data-idx="${r}-${e}"`:`<!--${r}-${o}-->`)}function W(n,r=internal.getActiveScope()){let t=internal.createScope(r);try{return internal.runWithScope(t,n)}finally{internal.disposeScope(t);}}function cn(n,r={},t=null){if(!shared.isFunction(n))return shared.error("Component must be a function"),"";template.resetHydrationKey();let e=x(t,()=>W(()=>n(r),null));return u(e)}function fn(n,r,...t){let e=n.length,o=t.length,i="";for(let s=0;s<e;s++)i+=n[s],s<o&&t[s]&&(i+=u(t[s]));return C(i,r)}function ln(e){return S(this,arguments,function*(n,r={},t=null){if(!shared.isFunction(n))return shared.error("Component must be a function"),"";template.resetHydrationKey();let o=internal.createScope(null),i=internal.getActiveScope();internal.setActiveScope(o);try{return yield x(t,()=>S(null,null,function*(){let s=n(r);return shared.isPromise(s)&&(s=yield s),a(s)}))}finally{internal.setActiveScope(i),internal.disposeScope(o);}})}function a(n){return S(this,null,function*(){return shared.isPromise(n)?a(yield n):Array.isArray(n)?(yield Promise.all(n.map(t=>a(t)))).join(""):shared.isFunction(n)?a(n()):u(n)})}function Sn(n,r={}){if(!shared.isFunction(n))return shared.error("createSSGComponent: Component is not a function"),"";let t=W(()=>n(r));return u(t)}function dn(n){if(!n)return null;let{class:r,style:t}=n,e=r&&!shared.isString(r),o=!!t;if(!e&&!o)return n;let i=A({},n);return e&&(i.class=shared.normalizeClassName(r)),o&&(i.style=shared.normalizeStyle(t)),i}function M(n,r){if(signals.isSignal(r)||signals.isComputed(r))return M(n,r.value);if(!r&&r!==0)return "";if(n==="style"){let t=shared.normalizeStyle(r);return t?shared.isString(t)?` style="${t}"`:` style="${shared.styleToString(t)}"`:""}if(n==="class"){let t=shared.normalizeClassName(r);return t?` class="${t}"`:""}return n.startsWith("on")?"":r===true?` ${n}`:` ${n}="${shared.escapeHTML(String(r))}"`}function I(n,r){return shared.isNil(r)||r===false?"":r===true?` ${n}`:` ${n}="${shared.escapeHTML(String(r))}"`}function q(n){let r=X(n);return r?` class="${shared.escapeHTML(r)}"`:""}function U(n){if(shared.isNil(n))return "";if(shared.isString(n))return n?` style="${shared.escapeHTML(n)}"`:"";if(shared.isObject(n)){let r=n,t=[];for(let e in r){let o=r[e];if(o!=null&&o!==false){let i=e.startsWith("--")?e:Pn(e);t.push(`${i}:${shared.escapeHTML(String(o))}`);}}return t.length?` style="${t.join(";")}"`:""}return ""}function Tn(n){if(!n||!shared.isObject(n))return "";let r="";for(let t in n)t==="children"||t==="ref"||t.startsWith("on")||(t==="class"||t==="className"?r+=q(n[t]):t==="style"?r+=U(n[t]):r+=I(t,n[t]));return r}function X(n){if(shared.isNil(n)||n===false)return "";if(shared.isString(n))return n;if(shared.isArray(n))return n.map(X).filter(Boolean).join(" ");if(shared.isObject(n)){let r=n;return Object.keys(r).filter(t=>!!r[t]).join(" ")}return String(n)}var Cn=/[A-Z]/g;function Pn(n){return n.replaceAll(Cn,r=>`-${r.toLowerCase()}`)}function kn(n){return u(n.children)}var Z="<!--teleport-anchor-->",J="<!--teleport-start-->",Q="<!--teleport-end-->";function wn(n){var s;let{target:r,children:t}=n,e=u(t);if((shared.isFunction(n.disabled)?!!n.disabled():!!n.disabled)||!r)return e;let i=d();return !i||!shared.isString(r)?e:(i.teleports[r]=((s=i.teleports[r])!=null?s:"")+J+e+Q,Z)}function bn(n){let{children:r,fallback:t}=n;return shared.isNil(r)?u(t):u(r)}function An(n){var r,t;return shared.isNil(n)?[]:shared.isObject(n)&&"value"in n?(r=n.value)!=null?r:[]:shared.isFunction(n)?(t=n())!=null?t:[]:n}function En(n){let r=An(n.each);if(r.length===0)return u(n.fallback);let t=n.children;return shared.isFunction(t)?r.map((e,o)=>u(t(e,o))).join(""):""}Object.defineProperty(exports,"escapeHTML",{enumerable:true,get:function(){return shared.escapeHTML}});Object.defineProperty(exports,"getHydrationKey",{enumerable:true,get:function(){return template.getHydrationKey}});Object.defineProperty(exports,"resetHydrationKey",{enumerable:true,get:function(){return template.resetHydrationKey}});exports.For=En;exports.Fragment=kn;exports.Portal=wn;exports.Suspense=bn;exports.TELEPORT_BLOCK_END=Q;exports.TELEPORT_BLOCK_START=J;exports.TELEPORT_CALLSITE_ANCHOR=Z;exports.addAttributes=C;exports.convertTextChildToString=T;exports.convertToString=u;exports.createSSGComponent=Sn;exports.createSSRContext=en;exports.getSSRContext=d;exports.normalizeProps=dn;exports.render=fn;exports.renderToString=cn;exports.renderToStringAsync=ln;exports.setSSGAttr=M;exports.ssrAttr=I;exports.ssrClass=q;exports.ssrSpread=Tn;exports.ssrStyle=U;
@@ -172,15 +172,18 @@ function renderToStringAsync(_0) {
172
172
  }
173
173
  template.resetHydrationKey();
174
174
  const scope = internal.createScope(null);
175
+ const prevScope = internal.getActiveScope();
176
+ internal.setActiveScope(scope);
175
177
  try {
176
178
  return yield runWithSSRContext(context, () => __async(null, null, function* () {
177
- let result = internal.runWithScope(scope, () => component(props));
179
+ let result = component(props);
178
180
  if (shared.isPromise(result)) {
179
181
  result = yield result;
180
182
  }
181
183
  return convertToStringAsync(result);
182
184
  }));
183
185
  } finally {
186
+ internal.setActiveScope(prevScope);
184
187
  internal.disposeScope(scope);
185
188
  }
186
189
  });
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/context.ts","../src/utils.ts","../src/render.ts","../src/attrs.ts","../src/ssr.ts","../src/components.ts"],"names":["AsyncLocalStorage","isNil","isString","isArray","isFunction","escapeHTML","getActiveScope","createScope","runWithScope","disposeScope","error","resetHydrationKey","isPromise","normalizeClassName","normalizeStyle","isSignal","isComputed","styleToString","isObject","warn","render"],"mappings":"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","file":"server.dev.cjs.js","sourcesContent":["// Use bare specifier (not `node:async_hooks`) as a workaround for tsup's\n// dts worker on TS 6.x, which reports TS2591 against the `node:` prefix\n// in some CI environments.\n// eslint-disable-next-line unicorn/prefer-node-protocol\nimport { AsyncLocalStorage } from 'async_hooks';\n\n/**\n * SSR rendering context.\n\n */\nexport interface SSRContext {\n /**\n * Map of teleport target → concatenated HTML string. The caller is\n * responsible for inlining each entry into the final document\n * (e.g. by replacing a placeholder in a shell template).\n */\n teleports: Record<string, string>;\n\n /**\n * Free-form key/value bag for user-defined per-render metadata\n * (e.g. collected `<head>` tags, status codes, response headers).\n */\n [key: string]: unknown;\n}\n\n/**\n * Create an empty SSR context with all collection slots initialised.\n */\nexport function createSSRContext(): SSRContext {\n return {\n teleports: Object.create(null) as Record<string, string>,\n };\n}\n\n/**\n * Async-safe SSR context propagation.\n */\ninterface ContextStore {\n getStore(): SSRContext | null | undefined;\n run<T>(ctx: SSRContext | null, fn: () => T): T;\n}\nconst store: ContextStore = new AsyncLocalStorage<SSRContext | null>();\n\n/**\n * Get the current SSR context, if any. Returns `null` when called outside of\n * a `renderToString` invocation, or when the caller did not pass a context.\n */\nexport function getSSRContext(): SSRContext | null {\n return store.getStore() ?? null;\n}\n\n/**\n * Run `fn` with `ctx` as the active SSR context. The context is preserved\n * across awaits inside `fn` and restored on exit (including when `fn` throws).\n */\nexport function runWithSSRContext<T>(ctx: SSRContext | null, fn: () => T): T {\n return store.run(ctx, fn);\n}\n","import { escapeHTML, isArray, isFunction, isNil, isString } from '@estjs/shared';\n\n/**\n * Convert content to string for SSR output.\n *\n * @param content - The content to convert.\n * @param isSvg - Whether the content is SVG.\n * @returns {string} The content as a string.\n */\nexport function convertToString(content: unknown, isSvg = false): string {\n if (isNil(content)) {\n return '';\n }\n\n if (isString(content)) {\n return content;\n }\n if (isArray(content)) {\n return (content as unknown[]).map((item: unknown) => convertToString(item, isSvg)).join('');\n }\n\n if (isFunction(content)) {\n return convertToString((content as () => unknown)(), isSvg);\n }\n\n return String(content);\n}\n\n/**\n * Convert child-expression content to escaped text for SSR output.\n *\n * JSX expression children have text semantics, so primitives must be escaped\n * before interpolation into the surrounding HTML template.\n */\nexport function convertTextChildToString(content: unknown): string {\n if (content === false || isNil(content)) {\n return '';\n }\n\n if (isString(content)) {\n return escapeHTML(content);\n }\n\n if (isArray(content)) {\n return (content as unknown[]).map((item) => convertTextChildToString(item)).join('');\n }\n\n if (isFunction(content)) {\n return convertTextChildToString((content as () => unknown)());\n }\n\n return escapeHTML(String(content));\n}\n\n/**\n * Combined regex that matches either a `data-idx=\"<digits>\"` attribute or a\n * hydration comment marker (numeric body only) in a single scan. Capture groups:\n * 1. data-idx index value (if attribute matched)\n * 2. numeric comment body (if hydration marker matched)\n *\n * Non-numeric comments (e.g. `<!-- user content -->`) are preserved unchanged.\n */\nconst HYDRATION_REWRITE_REGEX = /data-idx=\"(\\d+)\"|<!--(\\d+)-->/g;\n\n/**\n * Inject the root hydration attribute into the opening tag without corrupting\n * self-closing tags such as `<img />` or `<input/>`.\n */\nfunction injectRootHydrationAttribute(htmlContent: string, hydrationId: string): string {\n const tagStart = htmlContent.indexOf('<');\n if (tagStart === -1) {\n return htmlContent;\n }\n\n let quote: '\"' | \"'\" | undefined;\n for (let i = tagStart + 1; i < htmlContent.length; i++) {\n const char = htmlContent[i];\n\n if (quote) {\n if (char === quote) {\n quote = undefined;\n }\n continue;\n }\n\n if (char === '\"' || char === \"'\") {\n quote = char;\n continue;\n }\n\n if (char === '>') {\n let insertAt = i;\n for (let j = i - 1; j > tagStart; j--) {\n const prev = htmlContent[j];\n if (prev === ' ' || prev === '\\n' || prev === '\\t' || prev === '\\r') {\n continue;\n }\n if (prev === '/') {\n insertAt = j;\n }\n break;\n }\n\n return `${htmlContent.slice(0, insertAt)} data-hk=\"${hydrationId}\"${htmlContent.slice(insertAt)}`;\n }\n }\n\n return htmlContent;\n}\n\n/**\n * Add hydration attributes to HTML content.\n *\n * @param htmlContent - The html content.\n * @param hydrationId - The hydration id.\n * @returns {string} The html content with hydration attributes.\n */\nexport function addAttributes(htmlContent: string, hydrationId: string): string {\n // Single-pass rewrite for both `data-idx` and comment markers — half the\n // string traversals compared to chained `replaceAll` calls.\n return injectRootHydrationAttribute(htmlContent, hydrationId).replaceAll(\n HYDRATION_REWRITE_REGEX,\n (_match, dataIdx, commentBody) =>\n dataIdx !== undefined\n ? `data-idx=\"${hydrationId}-${dataIdx}\"`\n : `<!--${hydrationId}-${commentBody}-->`,\n );\n}\n","import { error, isFunction, isPromise } from '@estjs/shared';\nimport { type ComponentFn, type ComponentProps, resetHydrationKey } from '@estjs/template';\nimport {\n type Scope,\n createScope,\n disposeScope,\n getActiveScope,\n runWithScope,\n} from '@estjs/template/internal';\nimport { type SSRContext, runWithSSRContext } from './context';\nimport { addAttributes, convertToString } from './utils';\n\n/**\n * Runs `fn` inside a freshly created scope whose parent is the currently\n * active scope (if any). The scope is always disposed, even when `fn` throws,\n * so `provide` / `inject` state from one render cannot leak into another.\n */\nfunction runInFreshScope<T>(fn: () => T, parent: Scope | null = getActiveScope()): T {\n const scope = createScope(parent);\n try {\n return runWithScope(scope, fn);\n } finally {\n disposeScope(scope);\n }\n}\n\n/**\n * Render a component to HTML string.\n *\n * Each invocation runs inside its own root scope so that `provide()` calls\n * stay isolated between independent `renderToString` calls.\n *\n * @param component - The component to render.\n * @param props - The props to pass to the component.\n * @param context - Optional {@link SSRContext} that collects out-of-tree\n * render output (currently: `Portal`/`Teleport` content). The same context\n * is visible to nested `createSSGComponent` calls; the caller integrates\n * `context.teleports[selector]` into the final document.\n * @returns {string} The rendered HTML string.\n */\nexport function renderToString<P extends ComponentProps = ComponentProps>(\n component: ComponentFn<P>,\n props: P | ComponentProps = {},\n context: SSRContext | null = null,\n): string {\n if (!isFunction(component)) {\n error('Component must be a function');\n return '';\n }\n\n // Reset the hydration key counter\n resetHydrationKey();\n\n // Render the component within a fresh root scope (parent: null).\n const result = runWithSSRContext(context, () =>\n runInFreshScope(() => component(props as P), null),\n );\n\n if (__DEV__ && isPromise(result)) {\n error('renderToString received a Promise — use renderToStringAsync for async components.');\n }\n\n // Convert the result to string\n return convertToString(result);\n}\n\n/**\n * Render template with components (used by babel plugin in SSG mode).\n *\n * @param templates - The template fragments.\n * @param hydrationKey - The hydration key.\n * @param components - The rendered component strings.\n * @returns {string} The rendered HTML string.\n */\nexport function render(templates: string[], hydrationKey: string, ...components: string[]): string {\n /**\n * JSX source code:\n * <div>\n * <div>\n * <Component1 />\n * <Component2 />\n * </div>\n * <Component3 />\n * </div>\n *\n * Compiles to:\n *\n * let _tmpl = [\n * '<div><div>',\n * '</div>',\n * '</div>',\n * ]\n *\n * function component(props) {\n * return render(_tmpl, getHydrationKey(),\n * createSSGComponent(Component1, {}),\n * createSSGComponent(Component2, {}),\n * createSSGComponent(Component3, {})\n * );\n * }\n */\n\n // Direct string concatenation — avoids array allocation + join overhead\n // for typical 2-4 template fragments.\n const templateLen = templates.length;\n const componentLen = components.length;\n let content = '';\n\n for (let i = 0; i < templateLen; i++) {\n content += templates[i];\n if (i < componentLen && components[i]) {\n content += convertToString(components[i]);\n }\n }\n\n // Add hydration key attribute (data-hk) to the root element\n return addAttributes(content, hydrationKey);\n}\n\n/**\n * Async variant of {@link renderToString}. Awaits component results so that\n * `async` components and promise-returning expressions can participate in SSR.\n *\n * The awaited value is passed through the same {@link convertToString}\n * pipeline as the synchronous path, which itself transparently awaits any\n * nested promises (arrays of promises, promise-returning thunks, etc.).\n */\nexport async function renderToStringAsync<P extends ComponentProps = ComponentProps>(\n component: ComponentFn<P>,\n props: P | ComponentProps = {},\n context: SSRContext | null = null,\n): Promise<string> {\n if (!isFunction(component)) {\n error('Component must be a function');\n return '';\n }\n\n resetHydrationKey();\n\n const scope = createScope(null);\n try {\n // Keep both the SSR context and the reactive scope active for the entire\n // async render lifetime. This ensures that Portal() calls after an `await`\n // inside async components can still access `getSSRContext()`.\n return await runWithSSRContext(context, async () => {\n let result: unknown = runWithScope(scope, () => component(props as P));\n if (isPromise(result)) {\n result = await result;\n }\n return convertToStringAsync(result);\n });\n } finally {\n disposeScope(scope);\n }\n}\n\n/**\n * Promise-aware variant of `convertToString` used by {@link renderToStringAsync}.\n * Recursively unwraps promises and arrays of promises.\n */\nasync function convertToStringAsync(content: unknown): Promise<string> {\n if (isPromise(content)) {\n return convertToStringAsync(await content);\n }\n if (Array.isArray(content)) {\n const parts = await Promise.all(content.map((c) => convertToStringAsync(c)));\n return parts.join('');\n }\n if (isFunction(content)) {\n return convertToStringAsync((content as () => unknown)());\n }\n return convertToString(content);\n}\n\n/**\n * Create a SSG component (renders component to string).\n *\n * The component executes inside a child scope that inherits from the current\n * active scope, so `inject()` calls can resolve values from ancestor\n * `provide()` calls, and `provide()` inside the component is scoped to it.\n *\n * @param component - The component to create.\n * @param props - The props to pass to the component.\n * @returns {string} The rendered component as a string.\n */\nexport function createSSGComponent<P extends ComponentProps = ComponentProps>(\n component: ComponentFn<P>,\n props: P | ComponentProps = {},\n): string {\n if (!isFunction(component)) {\n error('createSSGComponent: Component is not a function');\n return '';\n }\n\n // Inherit the active scope (set by the enclosing renderToString call or by\n // an outer createSSGComponent) so that provide/inject follow the component\n // tree hierarchy.\n const result = runInFreshScope(() => component(props as P));\n\n return convertToString(result);\n}\n","import { isComputed, isSignal } from '@estjs/signals';\nimport {\n escapeHTML,\n isString,\n normalizeClassName,\n normalizeStyle,\n styleToString,\n} from '@estjs/shared';\n\n/**\n * Normalize component properties\n *\n * Special handling for class and style attributes, converting them to normalized format.\n * Returns a new object when normalization is needed, preserving the original.\n *\n * @param props - Original component properties\n * @returns Normalized component properties\n */\nexport function normalizeProps(props: Record<string, any> | null): Record<string, any> | null {\n if (!props) {\n return null;\n }\n\n const { class: className, style } = props;\n const needsClassNorm = className && !isString(className);\n const needsStyleNorm = !!style;\n\n if (!needsClassNorm && !needsStyleNorm) {\n return props;\n }\n\n // Shallow copy to avoid mutating the caller's props\n const result = { ...props };\n\n if (needsClassNorm) {\n result.class = normalizeClassName(className);\n }\n\n if (needsStyleNorm) {\n result.style = normalizeStyle(style);\n }\n\n return result;\n}\n\n/**\n * Generate server-side rendering attribute string\n *\n * Generate HTML-compatible attribute string based on attribute type, handling special cases:\n * - Automatic unwrapping of reactive values\n * - Normalization of special attributes (style/class)\n * - Ignoring event attributes\n * - Special handling for boolean attributes\n *\n * @param attrName - Attribute name\n * @param attrValue - Attribute value\n * @returns Formatted HTML attribute string\n */\nexport function setSSGAttr(attrName: string, attrValue: any): string {\n // Handle reactive values (signals or computed values)\n if (isSignal(attrValue) || isComputed(attrValue)) {\n return setSSGAttr(attrName, attrValue.value);\n }\n\n // Ignore null, undefined, and false value attributes\n if (!attrValue && attrValue !== 0) {\n return '';\n }\n\n // Special attribute handling: style\n if (attrName === 'style') {\n const normalizedStyle = normalizeStyle(attrValue);\n if (!normalizedStyle) {\n return '';\n }\n\n if (isString(normalizedStyle)) {\n return ` style=\"${normalizedStyle}\"`;\n }\n\n return ` style=\"${styleToString(normalizedStyle)}\"`;\n }\n\n // Special attribute handling: class\n if (attrName === 'class') {\n const normalizedClassName = normalizeClassName(attrValue);\n return normalizedClassName ? ` class=\"${normalizedClassName}\"` : '';\n }\n\n // Ignore event handler attributes (client-side behavior)\n if (attrName.startsWith('on')) {\n return '';\n }\n\n // Special handling for boolean attributes\n if (attrValue === true) {\n return ` ${attrName}`;\n }\n\n // Standard attribute handling — escape to prevent attribute injection (XSS)\n return ` ${attrName}=\"${escapeHTML(String(attrValue))}\"`;\n}\n","import { escapeHTML, isArray, isNil, isObject, isString } from '@estjs/shared';\n\n// ---------------------------------------------------------------------------\n// SSR attribute helpers\n// Used by babel-plugin server-mode generated code.\n// ---------------------------------------------------------------------------\n\n/**\n * Render a single attribute as an HTML attribute string.\n *\n * @param name - The name of the attribute.\n * @param value - The value of the attribute.\n * @returns {string} The rendered attribute string (e.g., ` name=\"value\"`).\n */\nexport function ssrAttr(name: string, value: unknown): string {\n if (isNil(value) || value === false) return '';\n if (value === true) return ` ${name}`;\n return ` ${name}=\"${escapeHTML(String(value))}\"`;\n}\n\n/**\n * Render a `class` attribute as an HTML attribute string.\n *\n * @param value - The class value (string, object, or array).\n * @returns {string} The rendered class attribute string.\n */\nexport function ssrClass(value: unknown): string {\n const normalized = normalizeClassSSR(value);\n if (!normalized) return '';\n return ` class=\"${escapeHTML(normalized)}\"`;\n}\n\n/**\n * Render a `style` attribute as an HTML attribute string.\n *\n * @param value - The style value (string or object).\n * @returns {string} The rendered style attribute string.\n */\nexport function ssrStyle(value: unknown): string {\n if (isNil(value)) return '';\n if (isString(value)) return value ? ` style=\"${escapeHTML(value)}\"` : '';\n if (isObject(value)) {\n const obj = value as Record<string, unknown>;\n const parts: string[] = [];\n for (const key in obj) {\n const v = obj[key];\n if (v != null && v !== false) {\n const prop = key.startsWith('--') ? key : camelToKebab(key);\n parts.push(`${prop}:${escapeHTML(String(v))}`);\n }\n }\n if (!parts.length) return '';\n return ` style=\"${parts.join(';')}\"`;\n }\n return '';\n}\n\n/**\n * Render a spread of props as HTML attribute strings.\n * Skips event handlers and special keys.\n *\n * @param props - The props object to spread.\n * @returns {string} The rendered attribute strings.\n */\nexport function ssrSpread(props: Record<string, unknown>): string {\n if (!props || !isObject(props)) return '';\n let out = '';\n for (const key in props) {\n if (key === 'children' || key === 'ref' || key.startsWith('on')) continue;\n if (key === 'class' || key === 'className') {\n out += ssrClass(props[key]);\n } else if (key === 'style') {\n out += ssrStyle(props[key]);\n } else {\n out += ssrAttr(key, props[key]);\n }\n }\n return out;\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Normalizes SSR class input into a string.\n */\nfunction normalizeClassSSR(value: unknown): string {\n if (isNil(value) || value === false) return '';\n if (isString(value)) return value;\n if (isArray(value)) {\n return (value as unknown[]).map(normalizeClassSSR).filter(Boolean).join(' ');\n }\n if (isObject(value)) {\n const obj = value as Record<string, unknown>;\n return Object.keys(obj)\n .filter((k) => Boolean(obj[k]))\n .join(' ');\n }\n return String(value);\n}\n\n/**\n * Matches uppercase characters for camelCase to kebab-case conversion.\n */\nconst UPPER_RE = /[A-Z]/g;\n\n/**\n * Converts a camelCase CSS property into kebab-case.\n */\nfunction camelToKebab(str: string): string {\n return str.replaceAll(UPPER_RE, (m) => `-${m.toLowerCase()}`);\n}\n","import { isFunction, isNil, isObject, isString, warn } from '@estjs/shared';\nimport { convertToString } from './utils';\nimport { getSSRContext } from './context';\n\nexport interface SSRComponentProps {\n children?: unknown;\n [key: string]: unknown;\n}\n\n/**\n * SSR Fragment — returns children converted to a string.\n */\nexport function Fragment(props: SSRComponentProps): string {\n return convertToString(props.children);\n}\n\n// ---------------------------------------------------------------------------\n// Portal (SSR)\n// ---------------------------------------------------------------------------\n\nexport interface SSRPortalProps extends SSRComponentProps {\n /**\n * Teleport target — only CSS selector strings are meaningful on the server.\n * Element references are silently inlined (they have no server-side meaning).\n */\n target?: string;\n /**\n * When truthy, children render inline instead of being teleported.\n * The babel plugin resolves reactive getters before reaching the component,\n * so only a plain boolean is needed on the server.\n */\n disabled?: boolean | (() => boolean);\n}\n\nexport const TELEPORT_CALLSITE_ANCHOR = '<!--teleport-anchor-->';\nexport const TELEPORT_BLOCK_START = '<!--teleport-start-->';\nexport const TELEPORT_BLOCK_END = '<!--teleport-end-->';\n\n/**\n * SSR Portal — collects teleported content into `ctx.teleports[target]`.\n *\n * Emits `<!--teleport-anchor-->` at the call site and wraps children with\n * `<!--teleport-start-->...<!--teleport-end-->` in the target buffer.\n * Disabled / no-target / no-context falls back to inline rendering.\n */\nexport function Portal(props: SSRPortalProps): string {\n const { target, children } = props;\n const rendered = convertToString(children);\n\n // Unwrap disabled getter (for API parity with client)\n const disabled = isFunction(props.disabled)\n ? !!(props.disabled as () => boolean)()\n : !!props.disabled;\n\n if (disabled || !target) return rendered;\n\n const ctx = getSSRContext();\n if (!ctx) return rendered;\n\n // Only string selectors are meaningful for SSR; DOM nodes are inlined.\n if (!isString(target)) {\n if (__DEV__) {\n warn('[Portal] SSR only supports string selector targets; rendering inline.');\n }\n return rendered;\n }\n\n ctx.teleports[target] =\n (ctx.teleports[target] ?? '') + TELEPORT_BLOCK_START + rendered + TELEPORT_BLOCK_END;\n\n return TELEPORT_CALLSITE_ANCHOR;\n}\n\n// ---------------------------------------------------------------------------\n// Suspense (SSR)\n// ---------------------------------------------------------------------------\n\n/**\n * SSR Suspense — renders children when available, otherwise the fallback slot.\n */\nexport function Suspense(props: SSRComponentProps & { fallback?: unknown }): string {\n const { children, fallback } = props;\n return isNil(children) ? convertToString(fallback) : convertToString(children);\n}\n\n// ---------------------------------------------------------------------------\n// For (SSR)\n// ---------------------------------------------------------------------------\n\nexport interface SSRForProps<T> {\n each: T[] | { value: T[] } | (() => T[]);\n children: (item: T, index: number) => unknown;\n key?: (item: T, index: number) => unknown;\n fallback?: unknown;\n}\n\n/** Unwrap signal / getter / plain array for SSR without subscribing. */\nfunction resolveList<T>(input: SSRForProps<T>['each']): T[] {\n if (isNil(input)) return [];\n // Duck-type signal check — avoids importing @estjs/signals on the server.\n if (isObject(input) && 'value' in input) {\n return ((input as { value: T[] }).value ?? []) as T[];\n }\n if (isFunction(input)) {\n return ((input as () => T[])() ?? []) as T[];\n }\n return input as T[];\n}\n\n/**\n * SSR For — maps each item through the render function and joins the output.\n */\nexport function For<T>(props: SSRForProps<T>): string {\n const list = resolveList<T>(props.each);\n\n if (list.length === 0) {\n return convertToString(props.fallback);\n }\n\n const render = props.children;\n if (!isFunction(render)) return '';\n\n return list.map((item, i) => convertToString(render(item, i))).join('');\n}\n"]}
1
+ {"version":3,"sources":["../src/context.ts","../src/utils.ts","../src/render.ts","../src/attrs.ts","../src/ssr.ts","../src/components.ts"],"names":["AsyncLocalStorage","isNil","isString","isArray","isFunction","escapeHTML","getActiveScope","createScope","runWithScope","disposeScope","error","resetHydrationKey","isPromise","setActiveScope","normalizeClassName","normalizeStyle","isSignal","isComputed","styleToString","isObject","warn","render"],"mappings":"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","file":"server.dev.cjs.js","sourcesContent":["// Use bare specifier (not `node:async_hooks`) as a workaround for tsup's\n// dts worker on TS 6.x, which reports TS2591 against the `node:` prefix\n// in some CI environments.\n// eslint-disable-next-line unicorn/prefer-node-protocol\nimport { AsyncLocalStorage } from 'async_hooks';\n\n/**\n * SSR rendering context.\n\n */\nexport interface SSRContext {\n /**\n * Map of teleport target → concatenated HTML string. The caller is\n * responsible for inlining each entry into the final document\n * (e.g. by replacing a placeholder in a shell template).\n */\n teleports: Record<string, string>;\n\n /**\n * Free-form key/value bag for user-defined per-render metadata\n * (e.g. collected `<head>` tags, status codes, response headers).\n */\n [key: string]: unknown;\n}\n\n/**\n * Create an empty SSR context with all collection slots initialised.\n */\nexport function createSSRContext(): SSRContext {\n return {\n teleports: Object.create(null) as Record<string, string>,\n };\n}\n\n/**\n * Async-safe SSR context propagation.\n */\ninterface ContextStore {\n getStore(): SSRContext | null | undefined;\n run<T>(ctx: SSRContext | null, fn: () => T): T;\n}\nconst store: ContextStore = new AsyncLocalStorage<SSRContext | null>();\n\n/**\n * Get the current SSR context, if any. Returns `null` when called outside of\n * a `renderToString` invocation, or when the caller did not pass a context.\n */\nexport function getSSRContext(): SSRContext | null {\n return store.getStore() ?? null;\n}\n\n/**\n * Run `fn` with `ctx` as the active SSR context. The context is preserved\n * across awaits inside `fn` and restored on exit (including when `fn` throws).\n */\nexport function runWithSSRContext<T>(ctx: SSRContext | null, fn: () => T): T {\n return store.run(ctx, fn);\n}\n","import { escapeHTML, isArray, isFunction, isNil, isString } from '@estjs/shared';\n\n/**\n * Convert content to string for SSR output.\n *\n * @param content - The content to convert.\n * @param isSvg - Whether the content is SVG.\n * @returns {string} The content as a string.\n */\nexport function convertToString(content: unknown, isSvg = false): string {\n if (isNil(content)) {\n return '';\n }\n\n if (isString(content)) {\n return content;\n }\n if (isArray(content)) {\n return (content as unknown[]).map((item: unknown) => convertToString(item, isSvg)).join('');\n }\n\n if (isFunction(content)) {\n return convertToString((content as () => unknown)(), isSvg);\n }\n\n return String(content);\n}\n\n/**\n * Convert child-expression content to escaped text for SSR output.\n *\n * JSX expression children have text semantics, so primitives must be escaped\n * before interpolation into the surrounding HTML template.\n */\nexport function convertTextChildToString(content: unknown): string {\n if (content === false || isNil(content)) {\n return '';\n }\n\n if (isString(content)) {\n return escapeHTML(content);\n }\n\n if (isArray(content)) {\n return (content as unknown[]).map((item) => convertTextChildToString(item)).join('');\n }\n\n if (isFunction(content)) {\n return convertTextChildToString((content as () => unknown)());\n }\n\n return escapeHTML(String(content));\n}\n\n/**\n * Combined regex that matches either a `data-idx=\"<digits>\"` attribute or a\n * hydration comment marker (numeric body only) in a single scan. Capture groups:\n * 1. data-idx index value (if attribute matched)\n * 2. numeric comment body (if hydration marker matched)\n *\n * Non-numeric comments (e.g. `<!-- user content -->`) are preserved unchanged.\n */\nconst HYDRATION_REWRITE_REGEX = /data-idx=\"(\\d+)\"|<!--(\\d+)-->/g;\n\n/**\n * Inject the root hydration attribute into the opening tag without corrupting\n * self-closing tags such as `<img />` or `<input/>`.\n */\nfunction injectRootHydrationAttribute(htmlContent: string, hydrationId: string): string {\n const tagStart = htmlContent.indexOf('<');\n if (tagStart === -1) {\n return htmlContent;\n }\n\n let quote: '\"' | \"'\" | undefined;\n for (let i = tagStart + 1; i < htmlContent.length; i++) {\n const char = htmlContent[i];\n\n if (quote) {\n if (char === quote) {\n quote = undefined;\n }\n continue;\n }\n\n if (char === '\"' || char === \"'\") {\n quote = char;\n continue;\n }\n\n if (char === '>') {\n let insertAt = i;\n for (let j = i - 1; j > tagStart; j--) {\n const prev = htmlContent[j];\n if (prev === ' ' || prev === '\\n' || prev === '\\t' || prev === '\\r') {\n continue;\n }\n if (prev === '/') {\n insertAt = j;\n }\n break;\n }\n\n return `${htmlContent.slice(0, insertAt)} data-hk=\"${hydrationId}\"${htmlContent.slice(insertAt)}`;\n }\n }\n\n return htmlContent;\n}\n\n/**\n * Add hydration attributes to HTML content.\n *\n * @param htmlContent - The html content.\n * @param hydrationId - The hydration id.\n * @returns {string} The html content with hydration attributes.\n */\nexport function addAttributes(htmlContent: string, hydrationId: string): string {\n // Single-pass rewrite for both `data-idx` and comment markers — half the\n // string traversals compared to chained `replaceAll` calls.\n return injectRootHydrationAttribute(htmlContent, hydrationId).replaceAll(\n HYDRATION_REWRITE_REGEX,\n (_match, dataIdx, commentBody) =>\n dataIdx !== undefined\n ? `data-idx=\"${hydrationId}-${dataIdx}\"`\n : `<!--${hydrationId}-${commentBody}-->`,\n );\n}\n","import { error, isFunction, isPromise } from '@estjs/shared';\nimport { type ComponentFn, type ComponentProps, resetHydrationKey } from '@estjs/template';\nimport {\n type Scope,\n createScope,\n disposeScope,\n getActiveScope,\n runWithScope,\n setActiveScope,\n} from '@estjs/template/internal';\nimport { type SSRContext, runWithSSRContext } from './context';\nimport { addAttributes, convertToString } from './utils';\n\n/**\n * Runs `fn` inside a freshly created scope whose parent is the currently\n * active scope (if any). The scope is always disposed, even when `fn` throws,\n * so `provide` / `inject` state from one render cannot leak into another.\n */\nfunction runInFreshScope<T>(fn: () => T, parent: Scope | null = getActiveScope()): T {\n const scope = createScope(parent);\n try {\n return runWithScope(scope, fn);\n } finally {\n disposeScope(scope);\n }\n}\n\n/**\n * Render a component to HTML string.\n *\n * Each invocation runs inside its own root scope so that `provide()` calls\n * stay isolated between independent `renderToString` calls.\n *\n * @param component - The component to render.\n * @param props - The props to pass to the component.\n * @param context - Optional {@link SSRContext} that collects out-of-tree\n * render output (currently: `Portal`/`Teleport` content). The same context\n * is visible to nested `createSSGComponent` calls; the caller integrates\n * `context.teleports[selector]` into the final document.\n * @returns {string} The rendered HTML string.\n */\nexport function renderToString<P extends ComponentProps = ComponentProps>(\n component: ComponentFn<P>,\n props: P | ComponentProps = {},\n context: SSRContext | null = null,\n): string {\n if (!isFunction(component)) {\n error('Component must be a function');\n return '';\n }\n\n // Reset the hydration key counter\n resetHydrationKey();\n\n // Render the component within a fresh root scope (parent: null).\n const result = runWithSSRContext(context, () =>\n runInFreshScope(() => component(props as P), null),\n );\n\n if (__DEV__ && isPromise(result)) {\n error('renderToString received a Promise — use renderToStringAsync for async components.');\n }\n\n // Convert the result to string\n return convertToString(result);\n}\n\n/**\n * Render template with components (used by babel plugin in SSG mode).\n *\n * @param templates - The template fragments.\n * @param hydrationKey - The hydration key.\n * @param components - The rendered component strings.\n * @returns {string} The rendered HTML string.\n */\nexport function render(templates: string[], hydrationKey: string, ...components: string[]): string {\n /**\n * JSX source code:\n * <div>\n * <div>\n * <Component1 />\n * <Component2 />\n * </div>\n * <Component3 />\n * </div>\n *\n * Compiles to:\n *\n * let _tmpl = [\n * '<div><div>',\n * '</div>',\n * '</div>',\n * ]\n *\n * function component(props) {\n * return render(_tmpl, getHydrationKey(),\n * createSSGComponent(Component1, {}),\n * createSSGComponent(Component2, {}),\n * createSSGComponent(Component3, {})\n * );\n * }\n */\n\n // Direct string concatenation — avoids array allocation + join overhead\n // for typical 2-4 template fragments.\n const templateLen = templates.length;\n const componentLen = components.length;\n let content = '';\n\n for (let i = 0; i < templateLen; i++) {\n content += templates[i];\n if (i < componentLen && components[i]) {\n content += convertToString(components[i]);\n }\n }\n\n // Add hydration key attribute (data-hk) to the root element\n return addAttributes(content, hydrationKey);\n}\n\n/**\n * Async variant of {@link renderToString}. Awaits component results so that\n * `async` components and promise-returning expressions can participate in SSR.\n *\n * The awaited value is passed through the same {@link convertToString}\n * pipeline as the synchronous path, which itself transparently awaits any\n * nested promises (arrays of promises, promise-returning thunks, etc.).\n */\nexport async function renderToStringAsync<P extends ComponentProps = ComponentProps>(\n component: ComponentFn<P>,\n props: P | ComponentProps = {},\n context: SSRContext | null = null,\n): Promise<string> {\n if (!isFunction(component)) {\n error('Component must be a function');\n return '';\n }\n\n resetHydrationKey();\n\n const scope = createScope(null);\n const prevScope = getActiveScope();\n setActiveScope(scope);\n try {\n // Keep both the SSR context and the reactive scope active for the entire\n // async render lifetime. This ensures that Portal() calls after an `await`\n // inside async components can still access `getSSRContext()`.\n return await runWithSSRContext(context, async () => {\n let result: unknown = component(props as P);\n if (isPromise(result)) {\n result = await result;\n }\n return convertToStringAsync(result);\n });\n } finally {\n setActiveScope(prevScope);\n disposeScope(scope);\n }\n}\n\n/**\n * Promise-aware variant of `convertToString` used by {@link renderToStringAsync}.\n * Recursively unwraps promises and arrays of promises.\n */\nasync function convertToStringAsync(content: unknown): Promise<string> {\n if (isPromise(content)) {\n return convertToStringAsync(await content);\n }\n if (Array.isArray(content)) {\n const parts = await Promise.all(content.map((c) => convertToStringAsync(c)));\n return parts.join('');\n }\n if (isFunction(content)) {\n return convertToStringAsync((content as () => unknown)());\n }\n return convertToString(content);\n}\n\n/**\n * Create a SSG component (renders component to string).\n *\n * The component executes inside a child scope that inherits from the current\n * active scope, so `inject()` calls can resolve values from ancestor\n * `provide()` calls, and `provide()` inside the component is scoped to it.\n *\n * @param component - The component to create.\n * @param props - The props to pass to the component.\n * @returns {string} The rendered component as a string.\n */\nexport function createSSGComponent<P extends ComponentProps = ComponentProps>(\n component: ComponentFn<P>,\n props: P | ComponentProps = {},\n): string {\n if (!isFunction(component)) {\n error('createSSGComponent: Component is not a function');\n return '';\n }\n\n // Inherit the active scope (set by the enclosing renderToString call or by\n // an outer createSSGComponent) so that provide/inject follow the component\n // tree hierarchy.\n const result = runInFreshScope(() => component(props as P));\n\n return convertToString(result);\n}\n","import { isComputed, isSignal } from '@estjs/signals';\nimport {\n escapeHTML,\n isString,\n normalizeClassName,\n normalizeStyle,\n styleToString,\n} from '@estjs/shared';\n\n/**\n * Normalize component properties\n *\n * Special handling for class and style attributes, converting them to normalized format.\n * Returns a new object when normalization is needed, preserving the original.\n *\n * @param props - Original component properties\n * @returns Normalized component properties\n */\nexport function normalizeProps(props: Record<string, any> | null): Record<string, any> | null {\n if (!props) {\n return null;\n }\n\n const { class: className, style } = props;\n const needsClassNorm = className && !isString(className);\n const needsStyleNorm = !!style;\n\n if (!needsClassNorm && !needsStyleNorm) {\n return props;\n }\n\n // Shallow copy to avoid mutating the caller's props\n const result = { ...props };\n\n if (needsClassNorm) {\n result.class = normalizeClassName(className);\n }\n\n if (needsStyleNorm) {\n result.style = normalizeStyle(style);\n }\n\n return result;\n}\n\n/**\n * Generate server-side rendering attribute string\n *\n * Generate HTML-compatible attribute string based on attribute type, handling special cases:\n * - Automatic unwrapping of reactive values\n * - Normalization of special attributes (style/class)\n * - Ignoring event attributes\n * - Special handling for boolean attributes\n *\n * @param attrName - Attribute name\n * @param attrValue - Attribute value\n * @returns Formatted HTML attribute string\n */\nexport function setSSGAttr(attrName: string, attrValue: any): string {\n // Handle reactive values (signals or computed values)\n if (isSignal(attrValue) || isComputed(attrValue)) {\n return setSSGAttr(attrName, attrValue.value);\n }\n\n // Ignore null, undefined, and false value attributes\n if (!attrValue && attrValue !== 0) {\n return '';\n }\n\n // Special attribute handling: style\n if (attrName === 'style') {\n const normalizedStyle = normalizeStyle(attrValue);\n if (!normalizedStyle) {\n return '';\n }\n\n if (isString(normalizedStyle)) {\n return ` style=\"${normalizedStyle}\"`;\n }\n\n return ` style=\"${styleToString(normalizedStyle)}\"`;\n }\n\n // Special attribute handling: class\n if (attrName === 'class') {\n const normalizedClassName = normalizeClassName(attrValue);\n return normalizedClassName ? ` class=\"${normalizedClassName}\"` : '';\n }\n\n // Ignore event handler attributes (client-side behavior)\n if (attrName.startsWith('on')) {\n return '';\n }\n\n // Special handling for boolean attributes\n if (attrValue === true) {\n return ` ${attrName}`;\n }\n\n // Standard attribute handling — escape to prevent attribute injection (XSS)\n return ` ${attrName}=\"${escapeHTML(String(attrValue))}\"`;\n}\n","import { escapeHTML, isArray, isNil, isObject, isString } from '@estjs/shared';\n\n// ---------------------------------------------------------------------------\n// SSR attribute helpers\n// Used by babel-plugin server-mode generated code.\n// ---------------------------------------------------------------------------\n\n/**\n * Render a single attribute as an HTML attribute string.\n *\n * @param name - The name of the attribute.\n * @param value - The value of the attribute.\n * @returns {string} The rendered attribute string (e.g., ` name=\"value\"`).\n */\nexport function ssrAttr(name: string, value: unknown): string {\n if (isNil(value) || value === false) return '';\n if (value === true) return ` ${name}`;\n return ` ${name}=\"${escapeHTML(String(value))}\"`;\n}\n\n/**\n * Render a `class` attribute as an HTML attribute string.\n *\n * @param value - The class value (string, object, or array).\n * @returns {string} The rendered class attribute string.\n */\nexport function ssrClass(value: unknown): string {\n const normalized = normalizeClassSSR(value);\n if (!normalized) return '';\n return ` class=\"${escapeHTML(normalized)}\"`;\n}\n\n/**\n * Render a `style` attribute as an HTML attribute string.\n *\n * @param value - The style value (string or object).\n * @returns {string} The rendered style attribute string.\n */\nexport function ssrStyle(value: unknown): string {\n if (isNil(value)) return '';\n if (isString(value)) return value ? ` style=\"${escapeHTML(value)}\"` : '';\n if (isObject(value)) {\n const obj = value as Record<string, unknown>;\n const parts: string[] = [];\n for (const key in obj) {\n const v = obj[key];\n if (v != null && v !== false) {\n const prop = key.startsWith('--') ? key : camelToKebab(key);\n parts.push(`${prop}:${escapeHTML(String(v))}`);\n }\n }\n if (!parts.length) return '';\n return ` style=\"${parts.join(';')}\"`;\n }\n return '';\n}\n\n/**\n * Render a spread of props as HTML attribute strings.\n * Skips event handlers and special keys.\n *\n * @param props - The props object to spread.\n * @returns {string} The rendered attribute strings.\n */\nexport function ssrSpread(props: Record<string, unknown>): string {\n if (!props || !isObject(props)) return '';\n let out = '';\n for (const key in props) {\n if (key === 'children' || key === 'ref' || key.startsWith('on')) continue;\n if (key === 'class' || key === 'className') {\n out += ssrClass(props[key]);\n } else if (key === 'style') {\n out += ssrStyle(props[key]);\n } else {\n out += ssrAttr(key, props[key]);\n }\n }\n return out;\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Normalizes SSR class input into a string.\n */\nfunction normalizeClassSSR(value: unknown): string {\n if (isNil(value) || value === false) return '';\n if (isString(value)) return value;\n if (isArray(value)) {\n return (value as unknown[]).map(normalizeClassSSR).filter(Boolean).join(' ');\n }\n if (isObject(value)) {\n const obj = value as Record<string, unknown>;\n return Object.keys(obj)\n .filter((k) => Boolean(obj[k]))\n .join(' ');\n }\n return String(value);\n}\n\n/**\n * Matches uppercase characters for camelCase to kebab-case conversion.\n */\nconst UPPER_RE = /[A-Z]/g;\n\n/**\n * Converts a camelCase CSS property into kebab-case.\n */\nfunction camelToKebab(str: string): string {\n return str.replaceAll(UPPER_RE, (m) => `-${m.toLowerCase()}`);\n}\n","import { isFunction, isNil, isObject, isString, warn } from '@estjs/shared';\nimport { convertToString } from './utils';\nimport { getSSRContext } from './context';\n\nexport interface SSRComponentProps {\n children?: unknown;\n [key: string]: unknown;\n}\n\n/**\n * SSR Fragment — returns children converted to a string.\n */\nexport function Fragment(props: SSRComponentProps): string {\n return convertToString(props.children);\n}\n\n// ---------------------------------------------------------------------------\n// Portal (SSR)\n// ---------------------------------------------------------------------------\n\nexport interface SSRPortalProps extends SSRComponentProps {\n /**\n * Teleport target — only CSS selector strings are meaningful on the server.\n * Element references are silently inlined (they have no server-side meaning).\n */\n target?: string;\n /**\n * When truthy, children render inline instead of being teleported.\n * The babel plugin resolves reactive getters before reaching the component,\n * so only a plain boolean is needed on the server.\n */\n disabled?: boolean | (() => boolean);\n}\n\nexport const TELEPORT_CALLSITE_ANCHOR = '<!--teleport-anchor-->';\nexport const TELEPORT_BLOCK_START = '<!--teleport-start-->';\nexport const TELEPORT_BLOCK_END = '<!--teleport-end-->';\n\n/**\n * SSR Portal — collects teleported content into `ctx.teleports[target]`.\n *\n * Emits `<!--teleport-anchor-->` at the call site and wraps children with\n * `<!--teleport-start-->...<!--teleport-end-->` in the target buffer.\n * Disabled / no-target / no-context falls back to inline rendering.\n */\nexport function Portal(props: SSRPortalProps): string {\n const { target, children } = props;\n const rendered = convertToString(children);\n\n // Unwrap disabled getter (for API parity with client)\n const disabled = isFunction(props.disabled)\n ? !!(props.disabled as () => boolean)()\n : !!props.disabled;\n\n if (disabled || !target) return rendered;\n\n const ctx = getSSRContext();\n if (!ctx) return rendered;\n\n // Only string selectors are meaningful for SSR; DOM nodes are inlined.\n if (!isString(target)) {\n if (__DEV__) {\n warn('[Portal] SSR only supports string selector targets; rendering inline.');\n }\n return rendered;\n }\n\n ctx.teleports[target] =\n (ctx.teleports[target] ?? '') + TELEPORT_BLOCK_START + rendered + TELEPORT_BLOCK_END;\n\n return TELEPORT_CALLSITE_ANCHOR;\n}\n\n// ---------------------------------------------------------------------------\n// Suspense (SSR)\n// ---------------------------------------------------------------------------\n\n/**\n * SSR Suspense — renders children when available, otherwise the fallback slot.\n */\nexport function Suspense(props: SSRComponentProps & { fallback?: unknown }): string {\n const { children, fallback } = props;\n return isNil(children) ? convertToString(fallback) : convertToString(children);\n}\n\n// ---------------------------------------------------------------------------\n// For (SSR)\n// ---------------------------------------------------------------------------\n\nexport interface SSRForProps<T> {\n each: T[] | { value: T[] } | (() => T[]);\n children: (item: T, index: number) => unknown;\n key?: (item: T, index: number) => unknown;\n fallback?: unknown;\n}\n\n/** Unwrap signal / getter / plain array for SSR without subscribing. */\nfunction resolveList<T>(input: SSRForProps<T>['each']): T[] {\n if (isNil(input)) return [];\n // Duck-type signal check — avoids importing @estjs/signals on the server.\n if (isObject(input) && 'value' in input) {\n return ((input as { value: T[] }).value ?? []) as T[];\n }\n if (isFunction(input)) {\n return ((input as () => T[])() ?? []) as T[];\n }\n return input as T[];\n}\n\n/**\n * SSR For — maps each item through the render function and joins the output.\n */\nexport function For<T>(props: SSRForProps<T>): string {\n const list = resolveList<T>(props.each);\n\n if (list.length === 0) {\n return convertToString(props.fallback);\n }\n\n const render = props.children;\n if (!isFunction(render)) return '';\n\n return list.map((item, i) => convertToString(render(item, i))).join('');\n}\n"]}
@@ -2,7 +2,7 @@ import { isNil, isString, isArray, isFunction, escapeHTML, error, isPromise, nor
2
2
  export { escapeHTML } from '@estjs/shared';
3
3
  import { resetHydrationKey } from '@estjs/template';
4
4
  export { getHydrationKey, resetHydrationKey } from '@estjs/template';
5
- import { createScope, runWithScope, disposeScope, getActiveScope } from '@estjs/template/internal';
5
+ import { createScope, runWithScope, disposeScope, getActiveScope, setActiveScope } from '@estjs/template/internal';
6
6
  import { AsyncLocalStorage } from 'async_hooks';
7
7
  import { isSignal, isComputed } from '@estjs/signals';
8
8
 
@@ -172,15 +172,18 @@ function renderToStringAsync(_0) {
172
172
  }
173
173
  resetHydrationKey();
174
174
  const scope = createScope(null);
175
+ const prevScope = getActiveScope();
176
+ setActiveScope(scope);
175
177
  try {
176
178
  return yield runWithSSRContext(context, () => __async(null, null, function* () {
177
- let result = runWithScope(scope, () => component(props));
179
+ let result = component(props);
178
180
  if (isPromise(result)) {
179
181
  result = yield result;
180
182
  }
181
183
  return convertToStringAsync(result);
182
184
  }));
183
185
  } finally {
186
+ setActiveScope(prevScope);
184
187
  disposeScope(scope);
185
188
  }
186
189
  });
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/context.ts","../src/utils.ts","../src/render.ts","../src/attrs.ts","../src/ssr.ts","../src/components.ts"],"names":["isFunction","isString","escapeHTML","isNil","isArray","isObject","render"],"mappings":"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","file":"server.dev.esm.js","sourcesContent":["// Use bare specifier (not `node:async_hooks`) as a workaround for tsup's\n// dts worker on TS 6.x, which reports TS2591 against the `node:` prefix\n// in some CI environments.\n// eslint-disable-next-line unicorn/prefer-node-protocol\nimport { AsyncLocalStorage } from 'async_hooks';\n\n/**\n * SSR rendering context.\n\n */\nexport interface SSRContext {\n /**\n * Map of teleport target → concatenated HTML string. The caller is\n * responsible for inlining each entry into the final document\n * (e.g. by replacing a placeholder in a shell template).\n */\n teleports: Record<string, string>;\n\n /**\n * Free-form key/value bag for user-defined per-render metadata\n * (e.g. collected `<head>` tags, status codes, response headers).\n */\n [key: string]: unknown;\n}\n\n/**\n * Create an empty SSR context with all collection slots initialised.\n */\nexport function createSSRContext(): SSRContext {\n return {\n teleports: Object.create(null) as Record<string, string>,\n };\n}\n\n/**\n * Async-safe SSR context propagation.\n */\ninterface ContextStore {\n getStore(): SSRContext | null | undefined;\n run<T>(ctx: SSRContext | null, fn: () => T): T;\n}\nconst store: ContextStore = new AsyncLocalStorage<SSRContext | null>();\n\n/**\n * Get the current SSR context, if any. Returns `null` when called outside of\n * a `renderToString` invocation, or when the caller did not pass a context.\n */\nexport function getSSRContext(): SSRContext | null {\n return store.getStore() ?? null;\n}\n\n/**\n * Run `fn` with `ctx` as the active SSR context. The context is preserved\n * across awaits inside `fn` and restored on exit (including when `fn` throws).\n */\nexport function runWithSSRContext<T>(ctx: SSRContext | null, fn: () => T): T {\n return store.run(ctx, fn);\n}\n","import { escapeHTML, isArray, isFunction, isNil, isString } from '@estjs/shared';\n\n/**\n * Convert content to string for SSR output.\n *\n * @param content - The content to convert.\n * @param isSvg - Whether the content is SVG.\n * @returns {string} The content as a string.\n */\nexport function convertToString(content: unknown, isSvg = false): string {\n if (isNil(content)) {\n return '';\n }\n\n if (isString(content)) {\n return content;\n }\n if (isArray(content)) {\n return (content as unknown[]).map((item: unknown) => convertToString(item, isSvg)).join('');\n }\n\n if (isFunction(content)) {\n return convertToString((content as () => unknown)(), isSvg);\n }\n\n return String(content);\n}\n\n/**\n * Convert child-expression content to escaped text for SSR output.\n *\n * JSX expression children have text semantics, so primitives must be escaped\n * before interpolation into the surrounding HTML template.\n */\nexport function convertTextChildToString(content: unknown): string {\n if (content === false || isNil(content)) {\n return '';\n }\n\n if (isString(content)) {\n return escapeHTML(content);\n }\n\n if (isArray(content)) {\n return (content as unknown[]).map((item) => convertTextChildToString(item)).join('');\n }\n\n if (isFunction(content)) {\n return convertTextChildToString((content as () => unknown)());\n }\n\n return escapeHTML(String(content));\n}\n\n/**\n * Combined regex that matches either a `data-idx=\"<digits>\"` attribute or a\n * hydration comment marker (numeric body only) in a single scan. Capture groups:\n * 1. data-idx index value (if attribute matched)\n * 2. numeric comment body (if hydration marker matched)\n *\n * Non-numeric comments (e.g. `<!-- user content -->`) are preserved unchanged.\n */\nconst HYDRATION_REWRITE_REGEX = /data-idx=\"(\\d+)\"|<!--(\\d+)-->/g;\n\n/**\n * Inject the root hydration attribute into the opening tag without corrupting\n * self-closing tags such as `<img />` or `<input/>`.\n */\nfunction injectRootHydrationAttribute(htmlContent: string, hydrationId: string): string {\n const tagStart = htmlContent.indexOf('<');\n if (tagStart === -1) {\n return htmlContent;\n }\n\n let quote: '\"' | \"'\" | undefined;\n for (let i = tagStart + 1; i < htmlContent.length; i++) {\n const char = htmlContent[i];\n\n if (quote) {\n if (char === quote) {\n quote = undefined;\n }\n continue;\n }\n\n if (char === '\"' || char === \"'\") {\n quote = char;\n continue;\n }\n\n if (char === '>') {\n let insertAt = i;\n for (let j = i - 1; j > tagStart; j--) {\n const prev = htmlContent[j];\n if (prev === ' ' || prev === '\\n' || prev === '\\t' || prev === '\\r') {\n continue;\n }\n if (prev === '/') {\n insertAt = j;\n }\n break;\n }\n\n return `${htmlContent.slice(0, insertAt)} data-hk=\"${hydrationId}\"${htmlContent.slice(insertAt)}`;\n }\n }\n\n return htmlContent;\n}\n\n/**\n * Add hydration attributes to HTML content.\n *\n * @param htmlContent - The html content.\n * @param hydrationId - The hydration id.\n * @returns {string} The html content with hydration attributes.\n */\nexport function addAttributes(htmlContent: string, hydrationId: string): string {\n // Single-pass rewrite for both `data-idx` and comment markers — half the\n // string traversals compared to chained `replaceAll` calls.\n return injectRootHydrationAttribute(htmlContent, hydrationId).replaceAll(\n HYDRATION_REWRITE_REGEX,\n (_match, dataIdx, commentBody) =>\n dataIdx !== undefined\n ? `data-idx=\"${hydrationId}-${dataIdx}\"`\n : `<!--${hydrationId}-${commentBody}-->`,\n );\n}\n","import { error, isFunction, isPromise } from '@estjs/shared';\nimport { type ComponentFn, type ComponentProps, resetHydrationKey } from '@estjs/template';\nimport {\n type Scope,\n createScope,\n disposeScope,\n getActiveScope,\n runWithScope,\n} from '@estjs/template/internal';\nimport { type SSRContext, runWithSSRContext } from './context';\nimport { addAttributes, convertToString } from './utils';\n\n/**\n * Runs `fn` inside a freshly created scope whose parent is the currently\n * active scope (if any). The scope is always disposed, even when `fn` throws,\n * so `provide` / `inject` state from one render cannot leak into another.\n */\nfunction runInFreshScope<T>(fn: () => T, parent: Scope | null = getActiveScope()): T {\n const scope = createScope(parent);\n try {\n return runWithScope(scope, fn);\n } finally {\n disposeScope(scope);\n }\n}\n\n/**\n * Render a component to HTML string.\n *\n * Each invocation runs inside its own root scope so that `provide()` calls\n * stay isolated between independent `renderToString` calls.\n *\n * @param component - The component to render.\n * @param props - The props to pass to the component.\n * @param context - Optional {@link SSRContext} that collects out-of-tree\n * render output (currently: `Portal`/`Teleport` content). The same context\n * is visible to nested `createSSGComponent` calls; the caller integrates\n * `context.teleports[selector]` into the final document.\n * @returns {string} The rendered HTML string.\n */\nexport function renderToString<P extends ComponentProps = ComponentProps>(\n component: ComponentFn<P>,\n props: P | ComponentProps = {},\n context: SSRContext | null = null,\n): string {\n if (!isFunction(component)) {\n error('Component must be a function');\n return '';\n }\n\n // Reset the hydration key counter\n resetHydrationKey();\n\n // Render the component within a fresh root scope (parent: null).\n const result = runWithSSRContext(context, () =>\n runInFreshScope(() => component(props as P), null),\n );\n\n if (__DEV__ && isPromise(result)) {\n error('renderToString received a Promise — use renderToStringAsync for async components.');\n }\n\n // Convert the result to string\n return convertToString(result);\n}\n\n/**\n * Render template with components (used by babel plugin in SSG mode).\n *\n * @param templates - The template fragments.\n * @param hydrationKey - The hydration key.\n * @param components - The rendered component strings.\n * @returns {string} The rendered HTML string.\n */\nexport function render(templates: string[], hydrationKey: string, ...components: string[]): string {\n /**\n * JSX source code:\n * <div>\n * <div>\n * <Component1 />\n * <Component2 />\n * </div>\n * <Component3 />\n * </div>\n *\n * Compiles to:\n *\n * let _tmpl = [\n * '<div><div>',\n * '</div>',\n * '</div>',\n * ]\n *\n * function component(props) {\n * return render(_tmpl, getHydrationKey(),\n * createSSGComponent(Component1, {}),\n * createSSGComponent(Component2, {}),\n * createSSGComponent(Component3, {})\n * );\n * }\n */\n\n // Direct string concatenation — avoids array allocation + join overhead\n // for typical 2-4 template fragments.\n const templateLen = templates.length;\n const componentLen = components.length;\n let content = '';\n\n for (let i = 0; i < templateLen; i++) {\n content += templates[i];\n if (i < componentLen && components[i]) {\n content += convertToString(components[i]);\n }\n }\n\n // Add hydration key attribute (data-hk) to the root element\n return addAttributes(content, hydrationKey);\n}\n\n/**\n * Async variant of {@link renderToString}. Awaits component results so that\n * `async` components and promise-returning expressions can participate in SSR.\n *\n * The awaited value is passed through the same {@link convertToString}\n * pipeline as the synchronous path, which itself transparently awaits any\n * nested promises (arrays of promises, promise-returning thunks, etc.).\n */\nexport async function renderToStringAsync<P extends ComponentProps = ComponentProps>(\n component: ComponentFn<P>,\n props: P | ComponentProps = {},\n context: SSRContext | null = null,\n): Promise<string> {\n if (!isFunction(component)) {\n error('Component must be a function');\n return '';\n }\n\n resetHydrationKey();\n\n const scope = createScope(null);\n try {\n // Keep both the SSR context and the reactive scope active for the entire\n // async render lifetime. This ensures that Portal() calls after an `await`\n // inside async components can still access `getSSRContext()`.\n return await runWithSSRContext(context, async () => {\n let result: unknown = runWithScope(scope, () => component(props as P));\n if (isPromise(result)) {\n result = await result;\n }\n return convertToStringAsync(result);\n });\n } finally {\n disposeScope(scope);\n }\n}\n\n/**\n * Promise-aware variant of `convertToString` used by {@link renderToStringAsync}.\n * Recursively unwraps promises and arrays of promises.\n */\nasync function convertToStringAsync(content: unknown): Promise<string> {\n if (isPromise(content)) {\n return convertToStringAsync(await content);\n }\n if (Array.isArray(content)) {\n const parts = await Promise.all(content.map((c) => convertToStringAsync(c)));\n return parts.join('');\n }\n if (isFunction(content)) {\n return convertToStringAsync((content as () => unknown)());\n }\n return convertToString(content);\n}\n\n/**\n * Create a SSG component (renders component to string).\n *\n * The component executes inside a child scope that inherits from the current\n * active scope, so `inject()` calls can resolve values from ancestor\n * `provide()` calls, and `provide()` inside the component is scoped to it.\n *\n * @param component - The component to create.\n * @param props - The props to pass to the component.\n * @returns {string} The rendered component as a string.\n */\nexport function createSSGComponent<P extends ComponentProps = ComponentProps>(\n component: ComponentFn<P>,\n props: P | ComponentProps = {},\n): string {\n if (!isFunction(component)) {\n error('createSSGComponent: Component is not a function');\n return '';\n }\n\n // Inherit the active scope (set by the enclosing renderToString call or by\n // an outer createSSGComponent) so that provide/inject follow the component\n // tree hierarchy.\n const result = runInFreshScope(() => component(props as P));\n\n return convertToString(result);\n}\n","import { isComputed, isSignal } from '@estjs/signals';\nimport {\n escapeHTML,\n isString,\n normalizeClassName,\n normalizeStyle,\n styleToString,\n} from '@estjs/shared';\n\n/**\n * Normalize component properties\n *\n * Special handling for class and style attributes, converting them to normalized format.\n * Returns a new object when normalization is needed, preserving the original.\n *\n * @param props - Original component properties\n * @returns Normalized component properties\n */\nexport function normalizeProps(props: Record<string, any> | null): Record<string, any> | null {\n if (!props) {\n return null;\n }\n\n const { class: className, style } = props;\n const needsClassNorm = className && !isString(className);\n const needsStyleNorm = !!style;\n\n if (!needsClassNorm && !needsStyleNorm) {\n return props;\n }\n\n // Shallow copy to avoid mutating the caller's props\n const result = { ...props };\n\n if (needsClassNorm) {\n result.class = normalizeClassName(className);\n }\n\n if (needsStyleNorm) {\n result.style = normalizeStyle(style);\n }\n\n return result;\n}\n\n/**\n * Generate server-side rendering attribute string\n *\n * Generate HTML-compatible attribute string based on attribute type, handling special cases:\n * - Automatic unwrapping of reactive values\n * - Normalization of special attributes (style/class)\n * - Ignoring event attributes\n * - Special handling for boolean attributes\n *\n * @param attrName - Attribute name\n * @param attrValue - Attribute value\n * @returns Formatted HTML attribute string\n */\nexport function setSSGAttr(attrName: string, attrValue: any): string {\n // Handle reactive values (signals or computed values)\n if (isSignal(attrValue) || isComputed(attrValue)) {\n return setSSGAttr(attrName, attrValue.value);\n }\n\n // Ignore null, undefined, and false value attributes\n if (!attrValue && attrValue !== 0) {\n return '';\n }\n\n // Special attribute handling: style\n if (attrName === 'style') {\n const normalizedStyle = normalizeStyle(attrValue);\n if (!normalizedStyle) {\n return '';\n }\n\n if (isString(normalizedStyle)) {\n return ` style=\"${normalizedStyle}\"`;\n }\n\n return ` style=\"${styleToString(normalizedStyle)}\"`;\n }\n\n // Special attribute handling: class\n if (attrName === 'class') {\n const normalizedClassName = normalizeClassName(attrValue);\n return normalizedClassName ? ` class=\"${normalizedClassName}\"` : '';\n }\n\n // Ignore event handler attributes (client-side behavior)\n if (attrName.startsWith('on')) {\n return '';\n }\n\n // Special handling for boolean attributes\n if (attrValue === true) {\n return ` ${attrName}`;\n }\n\n // Standard attribute handling — escape to prevent attribute injection (XSS)\n return ` ${attrName}=\"${escapeHTML(String(attrValue))}\"`;\n}\n","import { escapeHTML, isArray, isNil, isObject, isString } from '@estjs/shared';\n\n// ---------------------------------------------------------------------------\n// SSR attribute helpers\n// Used by babel-plugin server-mode generated code.\n// ---------------------------------------------------------------------------\n\n/**\n * Render a single attribute as an HTML attribute string.\n *\n * @param name - The name of the attribute.\n * @param value - The value of the attribute.\n * @returns {string} The rendered attribute string (e.g., ` name=\"value\"`).\n */\nexport function ssrAttr(name: string, value: unknown): string {\n if (isNil(value) || value === false) return '';\n if (value === true) return ` ${name}`;\n return ` ${name}=\"${escapeHTML(String(value))}\"`;\n}\n\n/**\n * Render a `class` attribute as an HTML attribute string.\n *\n * @param value - The class value (string, object, or array).\n * @returns {string} The rendered class attribute string.\n */\nexport function ssrClass(value: unknown): string {\n const normalized = normalizeClassSSR(value);\n if (!normalized) return '';\n return ` class=\"${escapeHTML(normalized)}\"`;\n}\n\n/**\n * Render a `style` attribute as an HTML attribute string.\n *\n * @param value - The style value (string or object).\n * @returns {string} The rendered style attribute string.\n */\nexport function ssrStyle(value: unknown): string {\n if (isNil(value)) return '';\n if (isString(value)) return value ? ` style=\"${escapeHTML(value)}\"` : '';\n if (isObject(value)) {\n const obj = value as Record<string, unknown>;\n const parts: string[] = [];\n for (const key in obj) {\n const v = obj[key];\n if (v != null && v !== false) {\n const prop = key.startsWith('--') ? key : camelToKebab(key);\n parts.push(`${prop}:${escapeHTML(String(v))}`);\n }\n }\n if (!parts.length) return '';\n return ` style=\"${parts.join(';')}\"`;\n }\n return '';\n}\n\n/**\n * Render a spread of props as HTML attribute strings.\n * Skips event handlers and special keys.\n *\n * @param props - The props object to spread.\n * @returns {string} The rendered attribute strings.\n */\nexport function ssrSpread(props: Record<string, unknown>): string {\n if (!props || !isObject(props)) return '';\n let out = '';\n for (const key in props) {\n if (key === 'children' || key === 'ref' || key.startsWith('on')) continue;\n if (key === 'class' || key === 'className') {\n out += ssrClass(props[key]);\n } else if (key === 'style') {\n out += ssrStyle(props[key]);\n } else {\n out += ssrAttr(key, props[key]);\n }\n }\n return out;\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Normalizes SSR class input into a string.\n */\nfunction normalizeClassSSR(value: unknown): string {\n if (isNil(value) || value === false) return '';\n if (isString(value)) return value;\n if (isArray(value)) {\n return (value as unknown[]).map(normalizeClassSSR).filter(Boolean).join(' ');\n }\n if (isObject(value)) {\n const obj = value as Record<string, unknown>;\n return Object.keys(obj)\n .filter((k) => Boolean(obj[k]))\n .join(' ');\n }\n return String(value);\n}\n\n/**\n * Matches uppercase characters for camelCase to kebab-case conversion.\n */\nconst UPPER_RE = /[A-Z]/g;\n\n/**\n * Converts a camelCase CSS property into kebab-case.\n */\nfunction camelToKebab(str: string): string {\n return str.replaceAll(UPPER_RE, (m) => `-${m.toLowerCase()}`);\n}\n","import { isFunction, isNil, isObject, isString, warn } from '@estjs/shared';\nimport { convertToString } from './utils';\nimport { getSSRContext } from './context';\n\nexport interface SSRComponentProps {\n children?: unknown;\n [key: string]: unknown;\n}\n\n/**\n * SSR Fragment — returns children converted to a string.\n */\nexport function Fragment(props: SSRComponentProps): string {\n return convertToString(props.children);\n}\n\n// ---------------------------------------------------------------------------\n// Portal (SSR)\n// ---------------------------------------------------------------------------\n\nexport interface SSRPortalProps extends SSRComponentProps {\n /**\n * Teleport target — only CSS selector strings are meaningful on the server.\n * Element references are silently inlined (they have no server-side meaning).\n */\n target?: string;\n /**\n * When truthy, children render inline instead of being teleported.\n * The babel plugin resolves reactive getters before reaching the component,\n * so only a plain boolean is needed on the server.\n */\n disabled?: boolean | (() => boolean);\n}\n\nexport const TELEPORT_CALLSITE_ANCHOR = '<!--teleport-anchor-->';\nexport const TELEPORT_BLOCK_START = '<!--teleport-start-->';\nexport const TELEPORT_BLOCK_END = '<!--teleport-end-->';\n\n/**\n * SSR Portal — collects teleported content into `ctx.teleports[target]`.\n *\n * Emits `<!--teleport-anchor-->` at the call site and wraps children with\n * `<!--teleport-start-->...<!--teleport-end-->` in the target buffer.\n * Disabled / no-target / no-context falls back to inline rendering.\n */\nexport function Portal(props: SSRPortalProps): string {\n const { target, children } = props;\n const rendered = convertToString(children);\n\n // Unwrap disabled getter (for API parity with client)\n const disabled = isFunction(props.disabled)\n ? !!(props.disabled as () => boolean)()\n : !!props.disabled;\n\n if (disabled || !target) return rendered;\n\n const ctx = getSSRContext();\n if (!ctx) return rendered;\n\n // Only string selectors are meaningful for SSR; DOM nodes are inlined.\n if (!isString(target)) {\n if (__DEV__) {\n warn('[Portal] SSR only supports string selector targets; rendering inline.');\n }\n return rendered;\n }\n\n ctx.teleports[target] =\n (ctx.teleports[target] ?? '') + TELEPORT_BLOCK_START + rendered + TELEPORT_BLOCK_END;\n\n return TELEPORT_CALLSITE_ANCHOR;\n}\n\n// ---------------------------------------------------------------------------\n// Suspense (SSR)\n// ---------------------------------------------------------------------------\n\n/**\n * SSR Suspense — renders children when available, otherwise the fallback slot.\n */\nexport function Suspense(props: SSRComponentProps & { fallback?: unknown }): string {\n const { children, fallback } = props;\n return isNil(children) ? convertToString(fallback) : convertToString(children);\n}\n\n// ---------------------------------------------------------------------------\n// For (SSR)\n// ---------------------------------------------------------------------------\n\nexport interface SSRForProps<T> {\n each: T[] | { value: T[] } | (() => T[]);\n children: (item: T, index: number) => unknown;\n key?: (item: T, index: number) => unknown;\n fallback?: unknown;\n}\n\n/** Unwrap signal / getter / plain array for SSR without subscribing. */\nfunction resolveList<T>(input: SSRForProps<T>['each']): T[] {\n if (isNil(input)) return [];\n // Duck-type signal check — avoids importing @estjs/signals on the server.\n if (isObject(input) && 'value' in input) {\n return ((input as { value: T[] }).value ?? []) as T[];\n }\n if (isFunction(input)) {\n return ((input as () => T[])() ?? []) as T[];\n }\n return input as T[];\n}\n\n/**\n * SSR For — maps each item through the render function and joins the output.\n */\nexport function For<T>(props: SSRForProps<T>): string {\n const list = resolveList<T>(props.each);\n\n if (list.length === 0) {\n return convertToString(props.fallback);\n }\n\n const render = props.children;\n if (!isFunction(render)) return '';\n\n return list.map((item, i) => convertToString(render(item, i))).join('');\n}\n"]}
1
+ {"version":3,"sources":["../src/context.ts","../src/utils.ts","../src/render.ts","../src/attrs.ts","../src/ssr.ts","../src/components.ts"],"names":["isFunction","isString","escapeHTML","isNil","isArray","isObject","render"],"mappings":"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","file":"server.dev.esm.js","sourcesContent":["// Use bare specifier (not `node:async_hooks`) as a workaround for tsup's\n// dts worker on TS 6.x, which reports TS2591 against the `node:` prefix\n// in some CI environments.\n// eslint-disable-next-line unicorn/prefer-node-protocol\nimport { AsyncLocalStorage } from 'async_hooks';\n\n/**\n * SSR rendering context.\n\n */\nexport interface SSRContext {\n /**\n * Map of teleport target → concatenated HTML string. The caller is\n * responsible for inlining each entry into the final document\n * (e.g. by replacing a placeholder in a shell template).\n */\n teleports: Record<string, string>;\n\n /**\n * Free-form key/value bag for user-defined per-render metadata\n * (e.g. collected `<head>` tags, status codes, response headers).\n */\n [key: string]: unknown;\n}\n\n/**\n * Create an empty SSR context with all collection slots initialised.\n */\nexport function createSSRContext(): SSRContext {\n return {\n teleports: Object.create(null) as Record<string, string>,\n };\n}\n\n/**\n * Async-safe SSR context propagation.\n */\ninterface ContextStore {\n getStore(): SSRContext | null | undefined;\n run<T>(ctx: SSRContext | null, fn: () => T): T;\n}\nconst store: ContextStore = new AsyncLocalStorage<SSRContext | null>();\n\n/**\n * Get the current SSR context, if any. Returns `null` when called outside of\n * a `renderToString` invocation, or when the caller did not pass a context.\n */\nexport function getSSRContext(): SSRContext | null {\n return store.getStore() ?? null;\n}\n\n/**\n * Run `fn` with `ctx` as the active SSR context. The context is preserved\n * across awaits inside `fn` and restored on exit (including when `fn` throws).\n */\nexport function runWithSSRContext<T>(ctx: SSRContext | null, fn: () => T): T {\n return store.run(ctx, fn);\n}\n","import { escapeHTML, isArray, isFunction, isNil, isString } from '@estjs/shared';\n\n/**\n * Convert content to string for SSR output.\n *\n * @param content - The content to convert.\n * @param isSvg - Whether the content is SVG.\n * @returns {string} The content as a string.\n */\nexport function convertToString(content: unknown, isSvg = false): string {\n if (isNil(content)) {\n return '';\n }\n\n if (isString(content)) {\n return content;\n }\n if (isArray(content)) {\n return (content as unknown[]).map((item: unknown) => convertToString(item, isSvg)).join('');\n }\n\n if (isFunction(content)) {\n return convertToString((content as () => unknown)(), isSvg);\n }\n\n return String(content);\n}\n\n/**\n * Convert child-expression content to escaped text for SSR output.\n *\n * JSX expression children have text semantics, so primitives must be escaped\n * before interpolation into the surrounding HTML template.\n */\nexport function convertTextChildToString(content: unknown): string {\n if (content === false || isNil(content)) {\n return '';\n }\n\n if (isString(content)) {\n return escapeHTML(content);\n }\n\n if (isArray(content)) {\n return (content as unknown[]).map((item) => convertTextChildToString(item)).join('');\n }\n\n if (isFunction(content)) {\n return convertTextChildToString((content as () => unknown)());\n }\n\n return escapeHTML(String(content));\n}\n\n/**\n * Combined regex that matches either a `data-idx=\"<digits>\"` attribute or a\n * hydration comment marker (numeric body only) in a single scan. Capture groups:\n * 1. data-idx index value (if attribute matched)\n * 2. numeric comment body (if hydration marker matched)\n *\n * Non-numeric comments (e.g. `<!-- user content -->`) are preserved unchanged.\n */\nconst HYDRATION_REWRITE_REGEX = /data-idx=\"(\\d+)\"|<!--(\\d+)-->/g;\n\n/**\n * Inject the root hydration attribute into the opening tag without corrupting\n * self-closing tags such as `<img />` or `<input/>`.\n */\nfunction injectRootHydrationAttribute(htmlContent: string, hydrationId: string): string {\n const tagStart = htmlContent.indexOf('<');\n if (tagStart === -1) {\n return htmlContent;\n }\n\n let quote: '\"' | \"'\" | undefined;\n for (let i = tagStart + 1; i < htmlContent.length; i++) {\n const char = htmlContent[i];\n\n if (quote) {\n if (char === quote) {\n quote = undefined;\n }\n continue;\n }\n\n if (char === '\"' || char === \"'\") {\n quote = char;\n continue;\n }\n\n if (char === '>') {\n let insertAt = i;\n for (let j = i - 1; j > tagStart; j--) {\n const prev = htmlContent[j];\n if (prev === ' ' || prev === '\\n' || prev === '\\t' || prev === '\\r') {\n continue;\n }\n if (prev === '/') {\n insertAt = j;\n }\n break;\n }\n\n return `${htmlContent.slice(0, insertAt)} data-hk=\"${hydrationId}\"${htmlContent.slice(insertAt)}`;\n }\n }\n\n return htmlContent;\n}\n\n/**\n * Add hydration attributes to HTML content.\n *\n * @param htmlContent - The html content.\n * @param hydrationId - The hydration id.\n * @returns {string} The html content with hydration attributes.\n */\nexport function addAttributes(htmlContent: string, hydrationId: string): string {\n // Single-pass rewrite for both `data-idx` and comment markers — half the\n // string traversals compared to chained `replaceAll` calls.\n return injectRootHydrationAttribute(htmlContent, hydrationId).replaceAll(\n HYDRATION_REWRITE_REGEX,\n (_match, dataIdx, commentBody) =>\n dataIdx !== undefined\n ? `data-idx=\"${hydrationId}-${dataIdx}\"`\n : `<!--${hydrationId}-${commentBody}-->`,\n );\n}\n","import { error, isFunction, isPromise } from '@estjs/shared';\nimport { type ComponentFn, type ComponentProps, resetHydrationKey } from '@estjs/template';\nimport {\n type Scope,\n createScope,\n disposeScope,\n getActiveScope,\n runWithScope,\n setActiveScope,\n} from '@estjs/template/internal';\nimport { type SSRContext, runWithSSRContext } from './context';\nimport { addAttributes, convertToString } from './utils';\n\n/**\n * Runs `fn` inside a freshly created scope whose parent is the currently\n * active scope (if any). The scope is always disposed, even when `fn` throws,\n * so `provide` / `inject` state from one render cannot leak into another.\n */\nfunction runInFreshScope<T>(fn: () => T, parent: Scope | null = getActiveScope()): T {\n const scope = createScope(parent);\n try {\n return runWithScope(scope, fn);\n } finally {\n disposeScope(scope);\n }\n}\n\n/**\n * Render a component to HTML string.\n *\n * Each invocation runs inside its own root scope so that `provide()` calls\n * stay isolated between independent `renderToString` calls.\n *\n * @param component - The component to render.\n * @param props - The props to pass to the component.\n * @param context - Optional {@link SSRContext} that collects out-of-tree\n * render output (currently: `Portal`/`Teleport` content). The same context\n * is visible to nested `createSSGComponent` calls; the caller integrates\n * `context.teleports[selector]` into the final document.\n * @returns {string} The rendered HTML string.\n */\nexport function renderToString<P extends ComponentProps = ComponentProps>(\n component: ComponentFn<P>,\n props: P | ComponentProps = {},\n context: SSRContext | null = null,\n): string {\n if (!isFunction(component)) {\n error('Component must be a function');\n return '';\n }\n\n // Reset the hydration key counter\n resetHydrationKey();\n\n // Render the component within a fresh root scope (parent: null).\n const result = runWithSSRContext(context, () =>\n runInFreshScope(() => component(props as P), null),\n );\n\n if (__DEV__ && isPromise(result)) {\n error('renderToString received a Promise — use renderToStringAsync for async components.');\n }\n\n // Convert the result to string\n return convertToString(result);\n}\n\n/**\n * Render template with components (used by babel plugin in SSG mode).\n *\n * @param templates - The template fragments.\n * @param hydrationKey - The hydration key.\n * @param components - The rendered component strings.\n * @returns {string} The rendered HTML string.\n */\nexport function render(templates: string[], hydrationKey: string, ...components: string[]): string {\n /**\n * JSX source code:\n * <div>\n * <div>\n * <Component1 />\n * <Component2 />\n * </div>\n * <Component3 />\n * </div>\n *\n * Compiles to:\n *\n * let _tmpl = [\n * '<div><div>',\n * '</div>',\n * '</div>',\n * ]\n *\n * function component(props) {\n * return render(_tmpl, getHydrationKey(),\n * createSSGComponent(Component1, {}),\n * createSSGComponent(Component2, {}),\n * createSSGComponent(Component3, {})\n * );\n * }\n */\n\n // Direct string concatenation — avoids array allocation + join overhead\n // for typical 2-4 template fragments.\n const templateLen = templates.length;\n const componentLen = components.length;\n let content = '';\n\n for (let i = 0; i < templateLen; i++) {\n content += templates[i];\n if (i < componentLen && components[i]) {\n content += convertToString(components[i]);\n }\n }\n\n // Add hydration key attribute (data-hk) to the root element\n return addAttributes(content, hydrationKey);\n}\n\n/**\n * Async variant of {@link renderToString}. Awaits component results so that\n * `async` components and promise-returning expressions can participate in SSR.\n *\n * The awaited value is passed through the same {@link convertToString}\n * pipeline as the synchronous path, which itself transparently awaits any\n * nested promises (arrays of promises, promise-returning thunks, etc.).\n */\nexport async function renderToStringAsync<P extends ComponentProps = ComponentProps>(\n component: ComponentFn<P>,\n props: P | ComponentProps = {},\n context: SSRContext | null = null,\n): Promise<string> {\n if (!isFunction(component)) {\n error('Component must be a function');\n return '';\n }\n\n resetHydrationKey();\n\n const scope = createScope(null);\n const prevScope = getActiveScope();\n setActiveScope(scope);\n try {\n // Keep both the SSR context and the reactive scope active for the entire\n // async render lifetime. This ensures that Portal() calls after an `await`\n // inside async components can still access `getSSRContext()`.\n return await runWithSSRContext(context, async () => {\n let result: unknown = component(props as P);\n if (isPromise(result)) {\n result = await result;\n }\n return convertToStringAsync(result);\n });\n } finally {\n setActiveScope(prevScope);\n disposeScope(scope);\n }\n}\n\n/**\n * Promise-aware variant of `convertToString` used by {@link renderToStringAsync}.\n * Recursively unwraps promises and arrays of promises.\n */\nasync function convertToStringAsync(content: unknown): Promise<string> {\n if (isPromise(content)) {\n return convertToStringAsync(await content);\n }\n if (Array.isArray(content)) {\n const parts = await Promise.all(content.map((c) => convertToStringAsync(c)));\n return parts.join('');\n }\n if (isFunction(content)) {\n return convertToStringAsync((content as () => unknown)());\n }\n return convertToString(content);\n}\n\n/**\n * Create a SSG component (renders component to string).\n *\n * The component executes inside a child scope that inherits from the current\n * active scope, so `inject()` calls can resolve values from ancestor\n * `provide()` calls, and `provide()` inside the component is scoped to it.\n *\n * @param component - The component to create.\n * @param props - The props to pass to the component.\n * @returns {string} The rendered component as a string.\n */\nexport function createSSGComponent<P extends ComponentProps = ComponentProps>(\n component: ComponentFn<P>,\n props: P | ComponentProps = {},\n): string {\n if (!isFunction(component)) {\n error('createSSGComponent: Component is not a function');\n return '';\n }\n\n // Inherit the active scope (set by the enclosing renderToString call or by\n // an outer createSSGComponent) so that provide/inject follow the component\n // tree hierarchy.\n const result = runInFreshScope(() => component(props as P));\n\n return convertToString(result);\n}\n","import { isComputed, isSignal } from '@estjs/signals';\nimport {\n escapeHTML,\n isString,\n normalizeClassName,\n normalizeStyle,\n styleToString,\n} from '@estjs/shared';\n\n/**\n * Normalize component properties\n *\n * Special handling for class and style attributes, converting them to normalized format.\n * Returns a new object when normalization is needed, preserving the original.\n *\n * @param props - Original component properties\n * @returns Normalized component properties\n */\nexport function normalizeProps(props: Record<string, any> | null): Record<string, any> | null {\n if (!props) {\n return null;\n }\n\n const { class: className, style } = props;\n const needsClassNorm = className && !isString(className);\n const needsStyleNorm = !!style;\n\n if (!needsClassNorm && !needsStyleNorm) {\n return props;\n }\n\n // Shallow copy to avoid mutating the caller's props\n const result = { ...props };\n\n if (needsClassNorm) {\n result.class = normalizeClassName(className);\n }\n\n if (needsStyleNorm) {\n result.style = normalizeStyle(style);\n }\n\n return result;\n}\n\n/**\n * Generate server-side rendering attribute string\n *\n * Generate HTML-compatible attribute string based on attribute type, handling special cases:\n * - Automatic unwrapping of reactive values\n * - Normalization of special attributes (style/class)\n * - Ignoring event attributes\n * - Special handling for boolean attributes\n *\n * @param attrName - Attribute name\n * @param attrValue - Attribute value\n * @returns Formatted HTML attribute string\n */\nexport function setSSGAttr(attrName: string, attrValue: any): string {\n // Handle reactive values (signals or computed values)\n if (isSignal(attrValue) || isComputed(attrValue)) {\n return setSSGAttr(attrName, attrValue.value);\n }\n\n // Ignore null, undefined, and false value attributes\n if (!attrValue && attrValue !== 0) {\n return '';\n }\n\n // Special attribute handling: style\n if (attrName === 'style') {\n const normalizedStyle = normalizeStyle(attrValue);\n if (!normalizedStyle) {\n return '';\n }\n\n if (isString(normalizedStyle)) {\n return ` style=\"${normalizedStyle}\"`;\n }\n\n return ` style=\"${styleToString(normalizedStyle)}\"`;\n }\n\n // Special attribute handling: class\n if (attrName === 'class') {\n const normalizedClassName = normalizeClassName(attrValue);\n return normalizedClassName ? ` class=\"${normalizedClassName}\"` : '';\n }\n\n // Ignore event handler attributes (client-side behavior)\n if (attrName.startsWith('on')) {\n return '';\n }\n\n // Special handling for boolean attributes\n if (attrValue === true) {\n return ` ${attrName}`;\n }\n\n // Standard attribute handling — escape to prevent attribute injection (XSS)\n return ` ${attrName}=\"${escapeHTML(String(attrValue))}\"`;\n}\n","import { escapeHTML, isArray, isNil, isObject, isString } from '@estjs/shared';\n\n// ---------------------------------------------------------------------------\n// SSR attribute helpers\n// Used by babel-plugin server-mode generated code.\n// ---------------------------------------------------------------------------\n\n/**\n * Render a single attribute as an HTML attribute string.\n *\n * @param name - The name of the attribute.\n * @param value - The value of the attribute.\n * @returns {string} The rendered attribute string (e.g., ` name=\"value\"`).\n */\nexport function ssrAttr(name: string, value: unknown): string {\n if (isNil(value) || value === false) return '';\n if (value === true) return ` ${name}`;\n return ` ${name}=\"${escapeHTML(String(value))}\"`;\n}\n\n/**\n * Render a `class` attribute as an HTML attribute string.\n *\n * @param value - The class value (string, object, or array).\n * @returns {string} The rendered class attribute string.\n */\nexport function ssrClass(value: unknown): string {\n const normalized = normalizeClassSSR(value);\n if (!normalized) return '';\n return ` class=\"${escapeHTML(normalized)}\"`;\n}\n\n/**\n * Render a `style` attribute as an HTML attribute string.\n *\n * @param value - The style value (string or object).\n * @returns {string} The rendered style attribute string.\n */\nexport function ssrStyle(value: unknown): string {\n if (isNil(value)) return '';\n if (isString(value)) return value ? ` style=\"${escapeHTML(value)}\"` : '';\n if (isObject(value)) {\n const obj = value as Record<string, unknown>;\n const parts: string[] = [];\n for (const key in obj) {\n const v = obj[key];\n if (v != null && v !== false) {\n const prop = key.startsWith('--') ? key : camelToKebab(key);\n parts.push(`${prop}:${escapeHTML(String(v))}`);\n }\n }\n if (!parts.length) return '';\n return ` style=\"${parts.join(';')}\"`;\n }\n return '';\n}\n\n/**\n * Render a spread of props as HTML attribute strings.\n * Skips event handlers and special keys.\n *\n * @param props - The props object to spread.\n * @returns {string} The rendered attribute strings.\n */\nexport function ssrSpread(props: Record<string, unknown>): string {\n if (!props || !isObject(props)) return '';\n let out = '';\n for (const key in props) {\n if (key === 'children' || key === 'ref' || key.startsWith('on')) continue;\n if (key === 'class' || key === 'className') {\n out += ssrClass(props[key]);\n } else if (key === 'style') {\n out += ssrStyle(props[key]);\n } else {\n out += ssrAttr(key, props[key]);\n }\n }\n return out;\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Normalizes SSR class input into a string.\n */\nfunction normalizeClassSSR(value: unknown): string {\n if (isNil(value) || value === false) return '';\n if (isString(value)) return value;\n if (isArray(value)) {\n return (value as unknown[]).map(normalizeClassSSR).filter(Boolean).join(' ');\n }\n if (isObject(value)) {\n const obj = value as Record<string, unknown>;\n return Object.keys(obj)\n .filter((k) => Boolean(obj[k]))\n .join(' ');\n }\n return String(value);\n}\n\n/**\n * Matches uppercase characters for camelCase to kebab-case conversion.\n */\nconst UPPER_RE = /[A-Z]/g;\n\n/**\n * Converts a camelCase CSS property into kebab-case.\n */\nfunction camelToKebab(str: string): string {\n return str.replaceAll(UPPER_RE, (m) => `-${m.toLowerCase()}`);\n}\n","import { isFunction, isNil, isObject, isString, warn } from '@estjs/shared';\nimport { convertToString } from './utils';\nimport { getSSRContext } from './context';\n\nexport interface SSRComponentProps {\n children?: unknown;\n [key: string]: unknown;\n}\n\n/**\n * SSR Fragment — returns children converted to a string.\n */\nexport function Fragment(props: SSRComponentProps): string {\n return convertToString(props.children);\n}\n\n// ---------------------------------------------------------------------------\n// Portal (SSR)\n// ---------------------------------------------------------------------------\n\nexport interface SSRPortalProps extends SSRComponentProps {\n /**\n * Teleport target — only CSS selector strings are meaningful on the server.\n * Element references are silently inlined (they have no server-side meaning).\n */\n target?: string;\n /**\n * When truthy, children render inline instead of being teleported.\n * The babel plugin resolves reactive getters before reaching the component,\n * so only a plain boolean is needed on the server.\n */\n disabled?: boolean | (() => boolean);\n}\n\nexport const TELEPORT_CALLSITE_ANCHOR = '<!--teleport-anchor-->';\nexport const TELEPORT_BLOCK_START = '<!--teleport-start-->';\nexport const TELEPORT_BLOCK_END = '<!--teleport-end-->';\n\n/**\n * SSR Portal — collects teleported content into `ctx.teleports[target]`.\n *\n * Emits `<!--teleport-anchor-->` at the call site and wraps children with\n * `<!--teleport-start-->...<!--teleport-end-->` in the target buffer.\n * Disabled / no-target / no-context falls back to inline rendering.\n */\nexport function Portal(props: SSRPortalProps): string {\n const { target, children } = props;\n const rendered = convertToString(children);\n\n // Unwrap disabled getter (for API parity with client)\n const disabled = isFunction(props.disabled)\n ? !!(props.disabled as () => boolean)()\n : !!props.disabled;\n\n if (disabled || !target) return rendered;\n\n const ctx = getSSRContext();\n if (!ctx) return rendered;\n\n // Only string selectors are meaningful for SSR; DOM nodes are inlined.\n if (!isString(target)) {\n if (__DEV__) {\n warn('[Portal] SSR only supports string selector targets; rendering inline.');\n }\n return rendered;\n }\n\n ctx.teleports[target] =\n (ctx.teleports[target] ?? '') + TELEPORT_BLOCK_START + rendered + TELEPORT_BLOCK_END;\n\n return TELEPORT_CALLSITE_ANCHOR;\n}\n\n// ---------------------------------------------------------------------------\n// Suspense (SSR)\n// ---------------------------------------------------------------------------\n\n/**\n * SSR Suspense — renders children when available, otherwise the fallback slot.\n */\nexport function Suspense(props: SSRComponentProps & { fallback?: unknown }): string {\n const { children, fallback } = props;\n return isNil(children) ? convertToString(fallback) : convertToString(children);\n}\n\n// ---------------------------------------------------------------------------\n// For (SSR)\n// ---------------------------------------------------------------------------\n\nexport interface SSRForProps<T> {\n each: T[] | { value: T[] } | (() => T[]);\n children: (item: T, index: number) => unknown;\n key?: (item: T, index: number) => unknown;\n fallback?: unknown;\n}\n\n/** Unwrap signal / getter / plain array for SSR without subscribing. */\nfunction resolveList<T>(input: SSRForProps<T>['each']): T[] {\n if (isNil(input)) return [];\n // Duck-type signal check — avoids importing @estjs/signals on the server.\n if (isObject(input) && 'value' in input) {\n return ((input as { value: T[] }).value ?? []) as T[];\n }\n if (isFunction(input)) {\n return ((input as () => T[])() ?? []) as T[];\n }\n return input as T[];\n}\n\n/**\n * SSR For — maps each item through the render function and joins the output.\n */\nexport function For<T>(props: SSRForProps<T>): string {\n const list = resolveList<T>(props.each);\n\n if (list.length === 0) {\n return convertToString(props.fallback);\n }\n\n const render = props.children;\n if (!isFunction(render)) return '';\n\n return list.map((item, i) => convertToString(render(item, i))).join('');\n}\n"]}
@@ -1,3 +1,2 @@
1
- import {isNil,isString,isArray,isFunction,escapeHTML,error,normalizeClassName,normalizeStyle,styleToString,isObject,isPromise}from'@estjs/shared';export{escapeHTML}from'@estjs/shared';import {resetHydrationKey}from'@estjs/template';export{getHydrationKey,resetHydrationKey}from'@estjs/template';import {createScope,runWithScope,disposeScope,getActiveScope}from'@estjs/template/internal';import {AsyncLocalStorage}from'async_hooks';import {isSignal,isComputed}from'@estjs/signals';var V=Object.defineProperty;var b=Object.getOwnPropertySymbols;var nn=Object.prototype.hasOwnProperty,rn=Object.prototype.propertyIsEnumerable;var A=(n,r,t)=>r in n?V(n,r,{enumerable:true,configurable:true,writable:true,value:t}):n[r]=t,E=(n,r)=>{for(var t in r||(r={}))nn.call(r,t)&&A(n,t,r[t]);if(b)for(var t of b(r))rn.call(r,t)&&A(n,t,r[t]);return n};var S=(n,r,t)=>new Promise((e,i)=>{var o=f=>{try{c(t.next(f));}catch(d){i(d);}},s=f=>{try{c(t.throw(f));}catch(d){i(d);}},c=f=>f.done?e(f.value):Promise.resolve(f.value).then(o,s);c((t=t.apply(n,r)).next());});function en(){return {teleports:Object.create(null)}}var _=new AsyncLocalStorage;function x(){var n;return (n=_.getStore())!=null?n:null}function T(n,r){return _.run(n,r)}function u(n,r=false){return isNil(n)?"":isString(n)?n:isArray(n)?n.map(t=>u(t,r)).join(""):isFunction(n)?u(n(),r):String(n)}function C(n){return n===false||isNil(n)?"":isString(n)?escapeHTML(n):isArray(n)?n.map(r=>C(r)).join(""):isFunction(n)?C(n()):escapeHTML(String(n))}var on=/data-idx="(\d+)"|<!--(\d+)-->/g;function sn(n,r){let t=n.indexOf("<");if(t===-1)return n;let e;for(let i=t+1;i<n.length;i++){let o=n[i];if(e){o===e&&(e=void 0);continue}if(o==='"'||o==="'"){e=o;continue}if(o===">"){let s=i;for(let c=i-1;c>t;c--){let f=n[c];if(!(f===" "||f===`
2
- `||f===" "||f==="\r")){f==="/"&&(s=c);break}}return `${n.slice(0,s)} data-hk="${r}"${n.slice(s)}`}}return n}function P(n,r){return sn(n,r).replaceAll(on,(t,e,i)=>e!==void 0?`data-idx="${r}-${e}"`:`<!--${r}-${i}-->`)}function W(n,r=getActiveScope()){let t=createScope(r);try{return runWithScope(t,n)}finally{disposeScope(t);}}function fn(n,r={},t=null){if(!isFunction(n))return error("Component must be a function"),"";resetHydrationKey();let e=T(t,()=>W(()=>n(r),null));return u(e)}function cn(n,r,...t){let e=n.length,i=t.length,o="";for(let s=0;s<e;s++)o+=n[s],s<i&&t[s]&&(o+=u(t[s]));return P(o,r)}function ln(e){return S(this,arguments,function*(n,r={},t=null){if(!isFunction(n))return error("Component must be a function"),"";resetHydrationKey();let i=createScope(null);try{return yield T(t,()=>S(null,null,function*(){let o=runWithScope(i,()=>n(r));return isPromise(o)&&(o=yield o),p(o)}))}finally{disposeScope(i);}})}function p(n){return S(this,null,function*(){return isPromise(n)?p(yield n):Array.isArray(n)?(yield Promise.all(n.map(t=>p(t)))).join(""):isFunction(n)?p(n()):u(n)})}function an(n,r={}){if(!isFunction(n))return error("createSSGComponent: Component is not a function"),"";let t=W(()=>n(r));return u(t)}function dn(n){if(!n)return null;let{class:r,style:t}=n,e=r&&!isString(r),i=!!t;if(!e&&!i)return n;let o=E({},n);return e&&(o.class=normalizeClassName(r)),i&&(o.style=normalizeStyle(t)),o}function M(n,r){if(isSignal(r)||isComputed(r))return M(n,r.value);if(!r&&r!==0)return "";if(n==="style"){let t=normalizeStyle(r);return t?isString(t)?` style="${t}"`:` style="${styleToString(t)}"`:""}if(n==="class"){let t=normalizeClassName(r);return t?` class="${t}"`:""}return n.startsWith("on")?"":r===true?` ${n}`:` ${n}="${escapeHTML(String(r))}"`}function q(n,r){return isNil(r)||r===false?"":r===true?` ${n}`:` ${n}="${escapeHTML(String(r))}"`}function U(n){let r=Y(n);return r?` class="${escapeHTML(r)}"`:""}function X(n){if(isNil(n))return "";if(isString(n))return n?` style="${escapeHTML(n)}"`:"";if(isObject(n)){let r=n,t=[];for(let e in r){let i=r[e];if(i!=null&&i!==false){let o=e.startsWith("--")?e:Pn(e);t.push(`${o}:${escapeHTML(String(i))}`);}}return t.length?` style="${t.join(";")}"`:""}return ""}function Tn(n){if(!n||!isObject(n))return "";let r="";for(let t in n)t==="children"||t==="ref"||t.startsWith("on")||(t==="class"||t==="className"?r+=U(n[t]):t==="style"?r+=X(n[t]):r+=q(t,n[t]));return r}function Y(n){if(isNil(n)||n===false)return "";if(isString(n))return n;if(isArray(n))return n.map(Y).filter(Boolean).join(" ");if(isObject(n)){let r=n;return Object.keys(r).filter(t=>!!r[t]).join(" ")}return String(n)}var Cn=/[A-Z]/g;function Pn(n){return n.replaceAll(Cn,r=>`-${r.toLowerCase()}`)}function kn(n){return u(n.children)}var v="<!--teleport-anchor-->",J="<!--teleport-start-->",Q="<!--teleport-end-->";function wn(n){var s;let{target:r,children:t}=n,e=u(t);if((isFunction(n.disabled)?!!n.disabled():!!n.disabled)||!r)return e;let o=x();return !o||!isString(r)?e:(o.teleports[r]=((s=o.teleports[r])!=null?s:"")+J+e+Q,v)}function bn(n){let{children:r,fallback:t}=n;return isNil(r)?u(t):u(r)}function An(n){var r,t;return isNil(n)?[]:isObject(n)&&"value"in n?(r=n.value)!=null?r:[]:isFunction(n)?(t=n())!=null?t:[]:n}function En(n){let r=An(n.each);if(r.length===0)return u(n.fallback);let t=n.children;return isFunction(t)?r.map((e,i)=>u(t(e,i))).join(""):""}export{En as For,kn as Fragment,wn as Portal,bn as Suspense,Q as TELEPORT_BLOCK_END,J as TELEPORT_BLOCK_START,v as TELEPORT_CALLSITE_ANCHOR,P as addAttributes,C as convertTextChildToString,u as convertToString,an as createSSGComponent,en as createSSRContext,x as getSSRContext,dn as normalizeProps,cn as render,fn as renderToString,ln as renderToStringAsync,M as setSSGAttr,q as ssrAttr,U as ssrClass,Tn as ssrSpread,X as ssrStyle};//# sourceMappingURL=server.esm.js.map
3
- //# sourceMappingURL=server.esm.js.map
1
+ import {isNil,isString,isArray,isFunction,escapeHTML,error,normalizeClassName,normalizeStyle,styleToString,isObject,isPromise}from'@estjs/shared';export{escapeHTML}from'@estjs/shared';import {resetHydrationKey}from'@estjs/template';export{getHydrationKey,resetHydrationKey}from'@estjs/template';import {createScope,runWithScope,disposeScope,getActiveScope,setActiveScope}from'@estjs/template/internal';import {AsyncLocalStorage}from'async_hooks';import {isSignal,isComputed}from'@estjs/signals';var nn=Object.defineProperty;var b=Object.getOwnPropertySymbols;var rn=Object.prototype.hasOwnProperty,tn=Object.prototype.propertyIsEnumerable;var A=(n,r,t)=>r in n?nn(n,r,{enumerable:true,configurable:true,writable:true,value:t}):n[r]=t,E=(n,r)=>{for(var t in r||(r={}))rn.call(r,t)&&A(n,t,r[t]);if(b)for(var t of b(r))tn.call(r,t)&&A(n,t,r[t]);return n};var a=(n,r,t)=>new Promise((e,o)=>{var i=c=>{try{f(t.next(c));}catch(d){o(d);}},s=c=>{try{f(t.throw(c));}catch(d){o(d);}},f=c=>c.done?e(c.value):Promise.resolve(c.value).then(i,s);f((t=t.apply(n,r)).next());});function on(){return {teleports:Object.create(null)}}var _=new AsyncLocalStorage;function x(){var n;return (n=_.getStore())!=null?n:null}function T(n,r){return _.run(n,r)}function u(n,r=false){return isNil(n)?"":isString(n)?n:isArray(n)?n.map(t=>u(t,r)).join(""):isFunction(n)?u(n(),r):String(n)}function C(n){return n===false||isNil(n)?"":isString(n)?escapeHTML(n):isArray(n)?n.map(r=>C(r)).join(""):isFunction(n)?C(n()):escapeHTML(String(n))}var sn=/data-idx="(\d+)"|<!--(\d+)-->/g;function un(n,r){let t=n.indexOf("<");if(t===-1)return n;let e;for(let o=t+1;o<n.length;o++){let i=n[o];if(e){i===e&&(e=void 0);continue}if(i==='"'||i==="'"){e=i;continue}if(i===">"){let s=o;for(let f=o-1;f>t;f--){let c=n[f];if(!(c===" "||c===`
2
+ `||c===" "||c==="\r")){c==="/"&&(s=f);break}}return `${n.slice(0,s)} data-hk="${r}"${n.slice(s)}`}}return n}function P(n,r){return un(n,r).replaceAll(sn,(t,e,o)=>e!==void 0?`data-idx="${r}-${e}"`:`<!--${r}-${o}-->`)}function B(n,r=getActiveScope()){let t=createScope(r);try{return runWithScope(t,n)}finally{disposeScope(t);}}function fn(n,r={},t=null){if(!isFunction(n))return error("Component must be a function"),"";resetHydrationKey();let e=T(t,()=>B(()=>n(r),null));return u(e)}function ln(n,r,...t){let e=n.length,o=t.length,i="";for(let s=0;s<e;s++)i+=n[s],s<o&&t[s]&&(i+=u(t[s]));return P(i,r)}function Sn(e){return a(this,arguments,function*(n,r={},t=null){if(!isFunction(n))return error("Component must be a function"),"";resetHydrationKey();let o=createScope(null),i=getActiveScope();setActiveScope(o);try{return yield T(t,()=>a(null,null,function*(){let s=n(r);return isPromise(s)&&(s=yield s),p(s)}))}finally{setActiveScope(i),disposeScope(o);}})}function p(n){return a(this,null,function*(){return isPromise(n)?p(yield n):Array.isArray(n)?(yield Promise.all(n.map(t=>p(t)))).join(""):isFunction(n)?p(n()):u(n)})}function an(n,r={}){if(!isFunction(n))return error("createSSGComponent: Component is not a function"),"";let t=B(()=>n(r));return u(t)}function xn(n){if(!n)return null;let{class:r,style:t}=n,e=r&&!isString(r),o=!!t;if(!e&&!o)return n;let i=E({},n);return e&&(i.class=normalizeClassName(r)),o&&(i.style=normalizeStyle(t)),i}function v(n,r){if(isSignal(r)||isComputed(r))return v(n,r.value);if(!r&&r!==0)return "";if(n==="style"){let t=normalizeStyle(r);return t?isString(t)?` style="${t}"`:` style="${styleToString(t)}"`:""}if(n==="class"){let t=normalizeClassName(r);return t?` class="${t}"`:""}return n.startsWith("on")?"":r===true?` ${n}`:` ${n}="${escapeHTML(String(r))}"`}function q(n,r){return isNil(r)||r===false?"":r===true?` ${n}`:` ${n}="${escapeHTML(String(r))}"`}function U(n){let r=Y(n);return r?` class="${escapeHTML(r)}"`:""}function X(n){if(isNil(n))return "";if(isString(n))return n?` style="${escapeHTML(n)}"`:"";if(isObject(n)){let r=n,t=[];for(let e in r){let o=r[e];if(o!=null&&o!==false){let i=e.startsWith("--")?e:Rn(e);t.push(`${i}:${escapeHTML(String(o))}`);}}return t.length?` style="${t.join(";")}"`:""}return ""}function Cn(n){if(!n||!isObject(n))return "";let r="";for(let t in n)t==="children"||t==="ref"||t.startsWith("on")||(t==="class"||t==="className"?r+=U(n[t]):t==="style"?r+=X(n[t]):r+=q(t,n[t]));return r}function Y(n){if(isNil(n)||n===false)return "";if(isString(n))return n;if(isArray(n))return n.map(Y).filter(Boolean).join(" ");if(isObject(n)){let r=n;return Object.keys(r).filter(t=>!!r[t]).join(" ")}return String(n)}var Pn=/[A-Z]/g;function Rn(n){return n.replaceAll(Pn,r=>`-${r.toLowerCase()}`)}function wn(n){return u(n.children)}var J="<!--teleport-anchor-->",Q="<!--teleport-start-->",V="<!--teleport-end-->";function bn(n){var s;let{target:r,children:t}=n,e=u(t);if((isFunction(n.disabled)?!!n.disabled():!!n.disabled)||!r)return e;let i=x();return !i||!isString(r)?e:(i.teleports[r]=((s=i.teleports[r])!=null?s:"")+Q+e+V,J)}function An(n){let{children:r,fallback:t}=n;return isNil(r)?u(t):u(r)}function En(n){var r,t;return isNil(n)?[]:isObject(n)&&"value"in n?(r=n.value)!=null?r:[]:isFunction(n)?(t=n())!=null?t:[]:n}function _n(n){let r=En(n.each);if(r.length===0)return u(n.fallback);let t=n.children;return isFunction(t)?r.map((e,o)=>u(t(e,o))).join(""):""}export{_n as For,wn as Fragment,bn as Portal,An as Suspense,V as TELEPORT_BLOCK_END,Q as TELEPORT_BLOCK_START,J as TELEPORT_CALLSITE_ANCHOR,P as addAttributes,C as convertTextChildToString,u as convertToString,an as createSSGComponent,on as createSSRContext,x as getSSRContext,xn as normalizeProps,ln as render,fn as renderToString,Sn as renderToStringAsync,v as setSSGAttr,q as ssrAttr,U as ssrClass,Cn as ssrSpread,X as ssrStyle};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@estjs/server",
3
- "version": "0.0.16-beta.4",
3
+ "version": "0.0.16-beta.5",
4
4
  "description": "Server-side rendering for Essor framework",
5
5
  "type": "module",
6
6
  "keywords": [
@@ -35,11 +35,11 @@
35
35
  "sideEffects": false,
36
36
  "dependencies": {
37
37
  "@types/node": "^25.6.0",
38
- "@estjs/shared": "0.0.16-beta.4",
39
- "@estjs/template": "0.0.16-beta.4"
38
+ "@estjs/shared": "0.0.16-beta.5",
39
+ "@estjs/template": "0.0.16-beta.5"
40
40
  },
41
41
  "scripts": {
42
- "build": "tsup && cross-env NODE_ENV=production tsup --clean=false --treeshake --sourcemap=false",
42
+ "build": "tsup && cross-env NODE_ENV=production tsup --clean=false",
43
43
  "dev": "tsup --watch"
44
44
  }
45
45
  }
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/context.ts","../src/utils.ts","../src/render.ts","../src/attrs.ts","../src/ssr.ts","../src/components.ts"],"names":["createSSRContext","store","AsyncLocalStorage","getSSRContext","_a","runWithSSRContext","ctx","fn","convertToString","content","isSvg","isNil","isString","isArray","item","isFunction","convertTextChildToString","escapeHTML","HYDRATION_REWRITE_REGEX","injectRootHydrationAttribute","htmlContent","hydrationId","tagStart","quote","char","insertAt","j","prev","addAttributes","_match","dataIdx","commentBody","runInFreshScope","parent","getActiveScope","scope","createScope","runWithScope","disposeScope","renderToString","component","props","context","error","resetHydrationKey","result","render","templates","hydrationKey","components","templateLen","componentLen","i","renderToStringAsync","_0","__async","isPromise","convertToStringAsync","c","createSSGComponent","normalizeProps","className","style","needsClassNorm","needsStyleNorm","__spreadValues","normalizeClassName","normalizeStyle","setSSGAttr","attrName","attrValue","isSignal","isComputed","normalizedStyle","styleToString","normalizedClassName","ssrAttr","name","value","ssrClass","normalized","normalizeClassSSR","ssrStyle","isObject","obj","parts","key","v","prop","camelToKebab","ssrSpread","out","k","UPPER_RE","str","m","Fragment","TELEPORT_CALLSITE_ANCHOR","TELEPORT_BLOCK_START","TELEPORT_BLOCK_END","Portal","target","children","rendered","Suspense","fallback","resolveList","input","_b","For","list"],"mappings":"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","file":"server.cjs.js","sourcesContent":["// Use bare specifier (not `node:async_hooks`) as a workaround for tsup's\n// dts worker on TS 6.x, which reports TS2591 against the `node:` prefix\n// in some CI environments.\n// eslint-disable-next-line unicorn/prefer-node-protocol\nimport { AsyncLocalStorage } from 'async_hooks';\n\n/**\n * SSR rendering context.\n\n */\nexport interface SSRContext {\n /**\n * Map of teleport target → concatenated HTML string. The caller is\n * responsible for inlining each entry into the final document\n * (e.g. by replacing a placeholder in a shell template).\n */\n teleports: Record<string, string>;\n\n /**\n * Free-form key/value bag for user-defined per-render metadata\n * (e.g. collected `<head>` tags, status codes, response headers).\n */\n [key: string]: unknown;\n}\n\n/**\n * Create an empty SSR context with all collection slots initialised.\n */\nexport function createSSRContext(): SSRContext {\n return {\n teleports: Object.create(null) as Record<string, string>,\n };\n}\n\n/**\n * Async-safe SSR context propagation.\n */\ninterface ContextStore {\n getStore(): SSRContext | null | undefined;\n run<T>(ctx: SSRContext | null, fn: () => T): T;\n}\nconst store: ContextStore = new AsyncLocalStorage<SSRContext | null>();\n\n/**\n * Get the current SSR context, if any. Returns `null` when called outside of\n * a `renderToString` invocation, or when the caller did not pass a context.\n */\nexport function getSSRContext(): SSRContext | null {\n return store.getStore() ?? null;\n}\n\n/**\n * Run `fn` with `ctx` as the active SSR context. The context is preserved\n * across awaits inside `fn` and restored on exit (including when `fn` throws).\n */\nexport function runWithSSRContext<T>(ctx: SSRContext | null, fn: () => T): T {\n return store.run(ctx, fn);\n}\n","import { escapeHTML, isArray, isFunction, isNil, isString } from '@estjs/shared';\n\n/**\n * Convert content to string for SSR output.\n *\n * @param content - The content to convert.\n * @param isSvg - Whether the content is SVG.\n * @returns {string} The content as a string.\n */\nexport function convertToString(content: unknown, isSvg = false): string {\n if (isNil(content)) {\n return '';\n }\n\n if (isString(content)) {\n return content;\n }\n if (isArray(content)) {\n return (content as unknown[]).map((item: unknown) => convertToString(item, isSvg)).join('');\n }\n\n if (isFunction(content)) {\n return convertToString((content as () => unknown)(), isSvg);\n }\n\n return String(content);\n}\n\n/**\n * Convert child-expression content to escaped text for SSR output.\n *\n * JSX expression children have text semantics, so primitives must be escaped\n * before interpolation into the surrounding HTML template.\n */\nexport function convertTextChildToString(content: unknown): string {\n if (content === false || isNil(content)) {\n return '';\n }\n\n if (isString(content)) {\n return escapeHTML(content);\n }\n\n if (isArray(content)) {\n return (content as unknown[]).map((item) => convertTextChildToString(item)).join('');\n }\n\n if (isFunction(content)) {\n return convertTextChildToString((content as () => unknown)());\n }\n\n return escapeHTML(String(content));\n}\n\n/**\n * Combined regex that matches either a `data-idx=\"<digits>\"` attribute or a\n * hydration comment marker (numeric body only) in a single scan. Capture groups:\n * 1. data-idx index value (if attribute matched)\n * 2. numeric comment body (if hydration marker matched)\n *\n * Non-numeric comments (e.g. `<!-- user content -->`) are preserved unchanged.\n */\nconst HYDRATION_REWRITE_REGEX = /data-idx=\"(\\d+)\"|<!--(\\d+)-->/g;\n\n/**\n * Inject the root hydration attribute into the opening tag without corrupting\n * self-closing tags such as `<img />` or `<input/>`.\n */\nfunction injectRootHydrationAttribute(htmlContent: string, hydrationId: string): string {\n const tagStart = htmlContent.indexOf('<');\n if (tagStart === -1) {\n return htmlContent;\n }\n\n let quote: '\"' | \"'\" | undefined;\n for (let i = tagStart + 1; i < htmlContent.length; i++) {\n const char = htmlContent[i];\n\n if (quote) {\n if (char === quote) {\n quote = undefined;\n }\n continue;\n }\n\n if (char === '\"' || char === \"'\") {\n quote = char;\n continue;\n }\n\n if (char === '>') {\n let insertAt = i;\n for (let j = i - 1; j > tagStart; j--) {\n const prev = htmlContent[j];\n if (prev === ' ' || prev === '\\n' || prev === '\\t' || prev === '\\r') {\n continue;\n }\n if (prev === '/') {\n insertAt = j;\n }\n break;\n }\n\n return `${htmlContent.slice(0, insertAt)} data-hk=\"${hydrationId}\"${htmlContent.slice(insertAt)}`;\n }\n }\n\n return htmlContent;\n}\n\n/**\n * Add hydration attributes to HTML content.\n *\n * @param htmlContent - The html content.\n * @param hydrationId - The hydration id.\n * @returns {string} The html content with hydration attributes.\n */\nexport function addAttributes(htmlContent: string, hydrationId: string): string {\n // Single-pass rewrite for both `data-idx` and comment markers — half the\n // string traversals compared to chained `replaceAll` calls.\n return injectRootHydrationAttribute(htmlContent, hydrationId).replaceAll(\n HYDRATION_REWRITE_REGEX,\n (_match, dataIdx, commentBody) =>\n dataIdx !== undefined\n ? `data-idx=\"${hydrationId}-${dataIdx}\"`\n : `<!--${hydrationId}-${commentBody}-->`,\n );\n}\n","import { error, isFunction, isPromise } from '@estjs/shared';\nimport { type ComponentFn, type ComponentProps, resetHydrationKey } from '@estjs/template';\nimport {\n type Scope,\n createScope,\n disposeScope,\n getActiveScope,\n runWithScope,\n} from '@estjs/template/internal';\nimport { type SSRContext, runWithSSRContext } from './context';\nimport { addAttributes, convertToString } from './utils';\n\n/**\n * Runs `fn` inside a freshly created scope whose parent is the currently\n * active scope (if any). The scope is always disposed, even when `fn` throws,\n * so `provide` / `inject` state from one render cannot leak into another.\n */\nfunction runInFreshScope<T>(fn: () => T, parent: Scope | null = getActiveScope()): T {\n const scope = createScope(parent);\n try {\n return runWithScope(scope, fn);\n } finally {\n disposeScope(scope);\n }\n}\n\n/**\n * Render a component to HTML string.\n *\n * Each invocation runs inside its own root scope so that `provide()` calls\n * stay isolated between independent `renderToString` calls.\n *\n * @param component - The component to render.\n * @param props - The props to pass to the component.\n * @param context - Optional {@link SSRContext} that collects out-of-tree\n * render output (currently: `Portal`/`Teleport` content). The same context\n * is visible to nested `createSSGComponent` calls; the caller integrates\n * `context.teleports[selector]` into the final document.\n * @returns {string} The rendered HTML string.\n */\nexport function renderToString<P extends ComponentProps = ComponentProps>(\n component: ComponentFn<P>,\n props: P | ComponentProps = {},\n context: SSRContext | null = null,\n): string {\n if (!isFunction(component)) {\n error('Component must be a function');\n return '';\n }\n\n // Reset the hydration key counter\n resetHydrationKey();\n\n // Render the component within a fresh root scope (parent: null).\n const result = runWithSSRContext(context, () =>\n runInFreshScope(() => component(props as P), null),\n );\n\n if (__DEV__ && isPromise(result)) {\n error('renderToString received a Promise — use renderToStringAsync for async components.');\n }\n\n // Convert the result to string\n return convertToString(result);\n}\n\n/**\n * Render template with components (used by babel plugin in SSG mode).\n *\n * @param templates - The template fragments.\n * @param hydrationKey - The hydration key.\n * @param components - The rendered component strings.\n * @returns {string} The rendered HTML string.\n */\nexport function render(templates: string[], hydrationKey: string, ...components: string[]): string {\n /**\n * JSX source code:\n * <div>\n * <div>\n * <Component1 />\n * <Component2 />\n * </div>\n * <Component3 />\n * </div>\n *\n * Compiles to:\n *\n * let _tmpl = [\n * '<div><div>',\n * '</div>',\n * '</div>',\n * ]\n *\n * function component(props) {\n * return render(_tmpl, getHydrationKey(),\n * createSSGComponent(Component1, {}),\n * createSSGComponent(Component2, {}),\n * createSSGComponent(Component3, {})\n * );\n * }\n */\n\n // Direct string concatenation — avoids array allocation + join overhead\n // for typical 2-4 template fragments.\n const templateLen = templates.length;\n const componentLen = components.length;\n let content = '';\n\n for (let i = 0; i < templateLen; i++) {\n content += templates[i];\n if (i < componentLen && components[i]) {\n content += convertToString(components[i]);\n }\n }\n\n // Add hydration key attribute (data-hk) to the root element\n return addAttributes(content, hydrationKey);\n}\n\n/**\n * Async variant of {@link renderToString}. Awaits component results so that\n * `async` components and promise-returning expressions can participate in SSR.\n *\n * The awaited value is passed through the same {@link convertToString}\n * pipeline as the synchronous path, which itself transparently awaits any\n * nested promises (arrays of promises, promise-returning thunks, etc.).\n */\nexport async function renderToStringAsync<P extends ComponentProps = ComponentProps>(\n component: ComponentFn<P>,\n props: P | ComponentProps = {},\n context: SSRContext | null = null,\n): Promise<string> {\n if (!isFunction(component)) {\n error('Component must be a function');\n return '';\n }\n\n resetHydrationKey();\n\n const scope = createScope(null);\n try {\n // Keep both the SSR context and the reactive scope active for the entire\n // async render lifetime. This ensures that Portal() calls after an `await`\n // inside async components can still access `getSSRContext()`.\n return await runWithSSRContext(context, async () => {\n let result: unknown = runWithScope(scope, () => component(props as P));\n if (isPromise(result)) {\n result = await result;\n }\n return convertToStringAsync(result);\n });\n } finally {\n disposeScope(scope);\n }\n}\n\n/**\n * Promise-aware variant of `convertToString` used by {@link renderToStringAsync}.\n * Recursively unwraps promises and arrays of promises.\n */\nasync function convertToStringAsync(content: unknown): Promise<string> {\n if (isPromise(content)) {\n return convertToStringAsync(await content);\n }\n if (Array.isArray(content)) {\n const parts = await Promise.all(content.map((c) => convertToStringAsync(c)));\n return parts.join('');\n }\n if (isFunction(content)) {\n return convertToStringAsync((content as () => unknown)());\n }\n return convertToString(content);\n}\n\n/**\n * Create a SSG component (renders component to string).\n *\n * The component executes inside a child scope that inherits from the current\n * active scope, so `inject()` calls can resolve values from ancestor\n * `provide()` calls, and `provide()` inside the component is scoped to it.\n *\n * @param component - The component to create.\n * @param props - The props to pass to the component.\n * @returns {string} The rendered component as a string.\n */\nexport function createSSGComponent<P extends ComponentProps = ComponentProps>(\n component: ComponentFn<P>,\n props: P | ComponentProps = {},\n): string {\n if (!isFunction(component)) {\n error('createSSGComponent: Component is not a function');\n return '';\n }\n\n // Inherit the active scope (set by the enclosing renderToString call or by\n // an outer createSSGComponent) so that provide/inject follow the component\n // tree hierarchy.\n const result = runInFreshScope(() => component(props as P));\n\n return convertToString(result);\n}\n","import { isComputed, isSignal } from '@estjs/signals';\nimport {\n escapeHTML,\n isString,\n normalizeClassName,\n normalizeStyle,\n styleToString,\n} from '@estjs/shared';\n\n/**\n * Normalize component properties\n *\n * Special handling for class and style attributes, converting them to normalized format.\n * Returns a new object when normalization is needed, preserving the original.\n *\n * @param props - Original component properties\n * @returns Normalized component properties\n */\nexport function normalizeProps(props: Record<string, any> | null): Record<string, any> | null {\n if (!props) {\n return null;\n }\n\n const { class: className, style } = props;\n const needsClassNorm = className && !isString(className);\n const needsStyleNorm = !!style;\n\n if (!needsClassNorm && !needsStyleNorm) {\n return props;\n }\n\n // Shallow copy to avoid mutating the caller's props\n const result = { ...props };\n\n if (needsClassNorm) {\n result.class = normalizeClassName(className);\n }\n\n if (needsStyleNorm) {\n result.style = normalizeStyle(style);\n }\n\n return result;\n}\n\n/**\n * Generate server-side rendering attribute string\n *\n * Generate HTML-compatible attribute string based on attribute type, handling special cases:\n * - Automatic unwrapping of reactive values\n * - Normalization of special attributes (style/class)\n * - Ignoring event attributes\n * - Special handling for boolean attributes\n *\n * @param attrName - Attribute name\n * @param attrValue - Attribute value\n * @returns Formatted HTML attribute string\n */\nexport function setSSGAttr(attrName: string, attrValue: any): string {\n // Handle reactive values (signals or computed values)\n if (isSignal(attrValue) || isComputed(attrValue)) {\n return setSSGAttr(attrName, attrValue.value);\n }\n\n // Ignore null, undefined, and false value attributes\n if (!attrValue && attrValue !== 0) {\n return '';\n }\n\n // Special attribute handling: style\n if (attrName === 'style') {\n const normalizedStyle = normalizeStyle(attrValue);\n if (!normalizedStyle) {\n return '';\n }\n\n if (isString(normalizedStyle)) {\n return ` style=\"${normalizedStyle}\"`;\n }\n\n return ` style=\"${styleToString(normalizedStyle)}\"`;\n }\n\n // Special attribute handling: class\n if (attrName === 'class') {\n const normalizedClassName = normalizeClassName(attrValue);\n return normalizedClassName ? ` class=\"${normalizedClassName}\"` : '';\n }\n\n // Ignore event handler attributes (client-side behavior)\n if (attrName.startsWith('on')) {\n return '';\n }\n\n // Special handling for boolean attributes\n if (attrValue === true) {\n return ` ${attrName}`;\n }\n\n // Standard attribute handling — escape to prevent attribute injection (XSS)\n return ` ${attrName}=\"${escapeHTML(String(attrValue))}\"`;\n}\n","import { escapeHTML, isArray, isNil, isObject, isString } from '@estjs/shared';\n\n// ---------------------------------------------------------------------------\n// SSR attribute helpers\n// Used by babel-plugin server-mode generated code.\n// ---------------------------------------------------------------------------\n\n/**\n * Render a single attribute as an HTML attribute string.\n *\n * @param name - The name of the attribute.\n * @param value - The value of the attribute.\n * @returns {string} The rendered attribute string (e.g., ` name=\"value\"`).\n */\nexport function ssrAttr(name: string, value: unknown): string {\n if (isNil(value) || value === false) return '';\n if (value === true) return ` ${name}`;\n return ` ${name}=\"${escapeHTML(String(value))}\"`;\n}\n\n/**\n * Render a `class` attribute as an HTML attribute string.\n *\n * @param value - The class value (string, object, or array).\n * @returns {string} The rendered class attribute string.\n */\nexport function ssrClass(value: unknown): string {\n const normalized = normalizeClassSSR(value);\n if (!normalized) return '';\n return ` class=\"${escapeHTML(normalized)}\"`;\n}\n\n/**\n * Render a `style` attribute as an HTML attribute string.\n *\n * @param value - The style value (string or object).\n * @returns {string} The rendered style attribute string.\n */\nexport function ssrStyle(value: unknown): string {\n if (isNil(value)) return '';\n if (isString(value)) return value ? ` style=\"${escapeHTML(value)}\"` : '';\n if (isObject(value)) {\n const obj = value as Record<string, unknown>;\n const parts: string[] = [];\n for (const key in obj) {\n const v = obj[key];\n if (v != null && v !== false) {\n const prop = key.startsWith('--') ? key : camelToKebab(key);\n parts.push(`${prop}:${escapeHTML(String(v))}`);\n }\n }\n if (!parts.length) return '';\n return ` style=\"${parts.join(';')}\"`;\n }\n return '';\n}\n\n/**\n * Render a spread of props as HTML attribute strings.\n * Skips event handlers and special keys.\n *\n * @param props - The props object to spread.\n * @returns {string} The rendered attribute strings.\n */\nexport function ssrSpread(props: Record<string, unknown>): string {\n if (!props || !isObject(props)) return '';\n let out = '';\n for (const key in props) {\n if (key === 'children' || key === 'ref' || key.startsWith('on')) continue;\n if (key === 'class' || key === 'className') {\n out += ssrClass(props[key]);\n } else if (key === 'style') {\n out += ssrStyle(props[key]);\n } else {\n out += ssrAttr(key, props[key]);\n }\n }\n return out;\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Normalizes SSR class input into a string.\n */\nfunction normalizeClassSSR(value: unknown): string {\n if (isNil(value) || value === false) return '';\n if (isString(value)) return value;\n if (isArray(value)) {\n return (value as unknown[]).map(normalizeClassSSR).filter(Boolean).join(' ');\n }\n if (isObject(value)) {\n const obj = value as Record<string, unknown>;\n return Object.keys(obj)\n .filter((k) => Boolean(obj[k]))\n .join(' ');\n }\n return String(value);\n}\n\n/**\n * Matches uppercase characters for camelCase to kebab-case conversion.\n */\nconst UPPER_RE = /[A-Z]/g;\n\n/**\n * Converts a camelCase CSS property into kebab-case.\n */\nfunction camelToKebab(str: string): string {\n return str.replaceAll(UPPER_RE, (m) => `-${m.toLowerCase()}`);\n}\n","import { isFunction, isNil, isObject, isString, warn } from '@estjs/shared';\nimport { convertToString } from './utils';\nimport { getSSRContext } from './context';\n\nexport interface SSRComponentProps {\n children?: unknown;\n [key: string]: unknown;\n}\n\n/**\n * SSR Fragment — returns children converted to a string.\n */\nexport function Fragment(props: SSRComponentProps): string {\n return convertToString(props.children);\n}\n\n// ---------------------------------------------------------------------------\n// Portal (SSR)\n// ---------------------------------------------------------------------------\n\nexport interface SSRPortalProps extends SSRComponentProps {\n /**\n * Teleport target — only CSS selector strings are meaningful on the server.\n * Element references are silently inlined (they have no server-side meaning).\n */\n target?: string;\n /**\n * When truthy, children render inline instead of being teleported.\n * The babel plugin resolves reactive getters before reaching the component,\n * so only a plain boolean is needed on the server.\n */\n disabled?: boolean | (() => boolean);\n}\n\nexport const TELEPORT_CALLSITE_ANCHOR = '<!--teleport-anchor-->';\nexport const TELEPORT_BLOCK_START = '<!--teleport-start-->';\nexport const TELEPORT_BLOCK_END = '<!--teleport-end-->';\n\n/**\n * SSR Portal — collects teleported content into `ctx.teleports[target]`.\n *\n * Emits `<!--teleport-anchor-->` at the call site and wraps children with\n * `<!--teleport-start-->...<!--teleport-end-->` in the target buffer.\n * Disabled / no-target / no-context falls back to inline rendering.\n */\nexport function Portal(props: SSRPortalProps): string {\n const { target, children } = props;\n const rendered = convertToString(children);\n\n // Unwrap disabled getter (for API parity with client)\n const disabled = isFunction(props.disabled)\n ? !!(props.disabled as () => boolean)()\n : !!props.disabled;\n\n if (disabled || !target) return rendered;\n\n const ctx = getSSRContext();\n if (!ctx) return rendered;\n\n // Only string selectors are meaningful for SSR; DOM nodes are inlined.\n if (!isString(target)) {\n if (__DEV__) {\n warn('[Portal] SSR only supports string selector targets; rendering inline.');\n }\n return rendered;\n }\n\n ctx.teleports[target] =\n (ctx.teleports[target] ?? '') + TELEPORT_BLOCK_START + rendered + TELEPORT_BLOCK_END;\n\n return TELEPORT_CALLSITE_ANCHOR;\n}\n\n// ---------------------------------------------------------------------------\n// Suspense (SSR)\n// ---------------------------------------------------------------------------\n\n/**\n * SSR Suspense — renders children when available, otherwise the fallback slot.\n */\nexport function Suspense(props: SSRComponentProps & { fallback?: unknown }): string {\n const { children, fallback } = props;\n return isNil(children) ? convertToString(fallback) : convertToString(children);\n}\n\n// ---------------------------------------------------------------------------\n// For (SSR)\n// ---------------------------------------------------------------------------\n\nexport interface SSRForProps<T> {\n each: T[] | { value: T[] } | (() => T[]);\n children: (item: T, index: number) => unknown;\n key?: (item: T, index: number) => unknown;\n fallback?: unknown;\n}\n\n/** Unwrap signal / getter / plain array for SSR without subscribing. */\nfunction resolveList<T>(input: SSRForProps<T>['each']): T[] {\n if (isNil(input)) return [];\n // Duck-type signal check — avoids importing @estjs/signals on the server.\n if (isObject(input) && 'value' in input) {\n return ((input as { value: T[] }).value ?? []) as T[];\n }\n if (isFunction(input)) {\n return ((input as () => T[])() ?? []) as T[];\n }\n return input as T[];\n}\n\n/**\n * SSR For — maps each item through the render function and joins the output.\n */\nexport function For<T>(props: SSRForProps<T>): string {\n const list = resolveList<T>(props.each);\n\n if (list.length === 0) {\n return convertToString(props.fallback);\n }\n\n const render = props.children;\n if (!isFunction(render)) return '';\n\n return list.map((item, i) => convertToString(render(item, i))).join('');\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/context.ts","../src/utils.ts","../src/render.ts","../src/attrs.ts","../src/ssr.ts","../src/components.ts"],"names":["createSSRContext","store","AsyncLocalStorage","getSSRContext","_a","runWithSSRContext","ctx","fn","convertToString","content","isSvg","isNil","isString","isArray","item","isFunction","convertTextChildToString","escapeHTML","HYDRATION_REWRITE_REGEX","injectRootHydrationAttribute","htmlContent","hydrationId","tagStart","quote","char","insertAt","j","prev","addAttributes","_match","dataIdx","commentBody","runInFreshScope","parent","getActiveScope","scope","createScope","runWithScope","disposeScope","renderToString","component","props","context","error","resetHydrationKey","result","render","templates","hydrationKey","components","templateLen","componentLen","i","renderToStringAsync","_0","__async","isPromise","convertToStringAsync","c","createSSGComponent","normalizeProps","className","style","needsClassNorm","needsStyleNorm","__spreadValues","normalizeClassName","normalizeStyle","setSSGAttr","attrName","attrValue","isSignal","isComputed","normalizedStyle","styleToString","normalizedClassName","ssrAttr","name","value","ssrClass","normalized","normalizeClassSSR","ssrStyle","isObject","obj","parts","key","v","prop","camelToKebab","ssrSpread","out","k","UPPER_RE","str","m","Fragment","TELEPORT_CALLSITE_ANCHOR","TELEPORT_BLOCK_START","TELEPORT_BLOCK_END","Portal","target","children","rendered","Suspense","fallback","resolveList","input","_b","For","list"],"mappings":"qhCA4BO,SAASA,EAAAA,EAA+B,CAC7C,OAAO,CACL,SAAA,CAAW,MAAA,CAAO,MAAA,CAAO,IAAI,CAC/B,CACF,CASA,IAAMC,CAAAA,CAAsB,IAAIC,iBAAAA,CAMzB,SAASC,CAAAA,EAAmC,CA/CnD,IAAAC,CAAAA,CAgDE,OAAA,CAAOA,CAAAA,CAAAH,CAAAA,CAAM,QAAA,EAAS,GAAf,IAAA,CAAAG,CAAAA,CAAoB,IAC7B,CAMO,SAASC,CAAAA,CAAqBC,CAAAA,CAAwBC,CAAAA,CAAgB,CAC3E,OAAON,CAAAA,CAAM,GAAA,CAAIK,CAAAA,CAAKC,CAAE,CAC1B,CChDO,SAASC,CAAAA,CAAgBC,CAAAA,CAAkBC,CAAAA,CAAQ,KAAA,CAAe,CACvE,OAAIC,KAAAA,CAAMF,CAAO,CAAA,CACR,GAGLG,QAAAA,CAASH,CAAO,CAAA,CACXA,CAAAA,CAELI,OAAAA,CAAQJ,CAAO,CAAA,CACTA,CAAAA,CAAsB,GAAA,CAAKK,CAAAA,EAAkBN,CAAAA,CAAgBM,CAAAA,CAAMJ,CAAK,CAAC,CAAA,CAAE,IAAA,CAAK,EAAE,CAAA,CAGxFK,UAAAA,CAAWN,CAAO,CAAA,CACbD,CAAAA,CAAiBC,CAAAA,EAA0B,CAAGC,CAAK,CAAA,CAGrD,MAAA,CAAOD,CAAO,CACvB,CAQO,SAASO,CAAAA,CAAyBP,CAAAA,CAA0B,CACjE,OAAIA,CAAAA,GAAY,KAAA,EAASE,KAAAA,CAAMF,CAAO,CAAA,CAC7B,EAAA,CAGLG,QAAAA,CAASH,CAAO,CAAA,CACXQ,UAAAA,CAAWR,CAAO,CAAA,CAGvBI,OAAAA,CAAQJ,CAAO,CAAA,CACTA,CAAAA,CAAsB,GAAA,CAAKK,CAAAA,EAASE,CAAAA,CAAyBF,CAAI,CAAC,CAAA,CAAE,IAAA,CAAK,EAAE,CAAA,CAGjFC,WAAWN,CAAO,CAAA,CACbO,CAAAA,CAA0BP,CAAAA,EAA2B,CAAA,CAGvDQ,UAAAA,CAAW,MAAA,CAAOR,CAAO,CAAC,CACnC,CAUA,IAAMS,EAAAA,CAA0B,gCAAA,CAMhC,SAASC,EAAAA,CAA6BC,CAAAA,CAAqBC,CAAAA,CAA6B,CACtF,IAAMC,CAAAA,CAAWF,CAAAA,CAAY,OAAA,CAAQ,GAAG,CAAA,CACxC,GAAIE,CAAAA,GAAa,EAAA,CACf,OAAOF,EAGT,IAAIG,CAAAA,CACJ,IAAA,IAAS,CAAA,CAAID,CAAAA,CAAW,CAAA,CAAG,CAAA,CAAIF,CAAAA,CAAY,MAAA,CAAQ,CAAA,EAAA,CAAK,CACtD,IAAMI,CAAAA,CAAOJ,CAAAA,CAAY,CAAC,CAAA,CAE1B,GAAIG,CAAAA,CAAO,CACLC,CAAAA,GAASD,CAAAA,GACXA,CAAAA,CAAQ,MAAA,CAAA,CAEV,QACF,CAEA,GAAIC,CAAAA,GAAS,GAAA,EAAOA,CAAAA,GAAS,GAAA,CAAK,CAChCD,CAAAA,CAAQC,CAAAA,CACR,QACF,CAEA,GAAIA,CAAAA,GAAS,GAAA,CAAK,CAChB,IAAIC,CAAAA,CAAW,CAAA,CACf,IAAA,IAASC,CAAAA,CAAI,CAAA,CAAI,CAAA,CAAGA,CAAAA,CAAIJ,CAAAA,CAAUI,CAAAA,EAAAA,CAAK,CACrC,IAAMC,CAAAA,CAAOP,CAAAA,CAAYM,CAAC,CAAA,CAC1B,GAAI,EAAAC,CAAAA,GAAS,GAAA,EAAOA,CAAAA,GAAS;AAAA,CAAA,EAAQA,CAAAA,GAAS,GAAA,EAAQA,CAAAA,GAAS,IAAA,CAAA,CAG/D,CAAIA,IAAS,GAAA,GACXF,CAAAA,CAAWC,CAAAA,CAAAA,CAEb,KAAA,CACF,CAEA,OAAO,GAAGN,CAAAA,CAAY,KAAA,CAAM,CAAA,CAAGK,CAAQ,CAAC,CAAA,UAAA,EAAaJ,CAAW,CAAA,CAAA,EAAID,CAAAA,CAAY,KAAA,CAAMK,CAAQ,CAAC,CAAA,CACjG,CACF,CAEA,OAAOL,CACT,CASO,SAASQ,CAAAA,CAAcR,CAAAA,CAAqBC,CAAAA,CAA6B,CAG9E,OAAOF,EAAAA,CAA6BC,CAAAA,CAAaC,CAAW,CAAA,CAAE,UAAA,CAC5DH,GACA,CAACW,CAAAA,CAAQC,CAAAA,CAASC,CAAAA,GAChBD,CAAAA,GAAY,MAAA,CACR,CAAA,UAAA,EAAaT,CAAW,CAAA,CAAA,EAAIS,CAAO,CAAA,CAAA,CAAA,CACnC,CAAA,IAAA,EAAOT,CAAW,CAAA,CAAA,EAAIU,CAAW,CAAA,GAAA,CACzC,CACF,CC9GA,SAASC,CAAAA,CAAmBzB,CAAAA,CAAa0B,CAAAA,CAAuBC,cAAAA,EAAe,CAAM,CACnF,IAAMC,CAAAA,CAAQC,WAAAA,CAAYH,CAAM,EAChC,GAAI,CACF,OAAOI,YAAAA,CAAaF,CAAAA,CAAO5B,CAAE,CAC/B,CAAA,OAAE,CACA+B,YAAAA,CAAaH,CAAK,EACpB,CACF,CAgBO,SAASI,EAAAA,CACdC,CAAAA,CACAC,CAAAA,CAA4B,EAAC,CAC7BC,CAAAA,CAA6B,IAAA,CACrB,CACR,GAAI,CAAC3B,UAAAA,CAAWyB,CAAS,CAAA,CACvB,OAAAG,MAAM,8BAA8B,CAAA,CAC7B,EAAA,CAITC,iBAAAA,EAAkB,CAGlB,IAAMC,CAAAA,CAASxC,CAAAA,CAAkBqC,CAAAA,CAAS,IACxCV,CAAAA,CAAgB,IAAMQ,CAAAA,CAAUC,CAAU,EAAG,IAAI,CACnD,CAAA,CAOA,OAAOjC,CAAAA,CAAgBqC,CAAM,CAC/B,CAUO,SAASC,EAAAA,CAAOC,CAAAA,CAAqBC,CAAAA,CAAAA,GAAyBC,CAAAA,CAA8B,CA8BjG,IAAMC,CAAAA,CAAcH,CAAAA,CAAU,MAAA,CACxBI,CAAAA,CAAeF,CAAAA,CAAW,MAAA,CAC5BxC,CAAAA,CAAU,EAAA,CAEd,IAAA,IAAS2C,CAAAA,CAAI,CAAA,CAAGA,CAAAA,CAAIF,CAAAA,CAAaE,IAC/B3C,CAAAA,EAAWsC,CAAAA,CAAUK,CAAC,CAAA,CAClBA,CAAAA,CAAID,CAAAA,EAAgBF,CAAAA,CAAWG,CAAC,CAAA,GAClC3C,CAAAA,EAAWD,CAAAA,CAAgByC,CAAAA,CAAWG,CAAC,CAAC,GAK5C,OAAOxB,CAAAA,CAAcnB,CAAAA,CAASuC,CAAY,CAC5C,CAUA,SAAsBK,EAAAA,CACpBC,CAAAA,CAGiB,CAAA,OAAAC,CAAAA,CAAA,IAAA,CAAA,SAAA,CAAA,UAHjBf,CAAAA,CACAC,CAAAA,CAA4B,EAAC,CAC7BC,CAAAA,CAA6B,IAAA,CACZ,CACjB,GAAI,CAAC3B,UAAAA,CAAWyB,CAAS,CAAA,CACvB,OAAAG,KAAAA,CAAM,8BAA8B,CAAA,CAC7B,EAAA,CAGTC,mBAAkB,CAElB,IAAMT,CAAAA,CAAQC,WAAAA,CAAY,IAAI,CAAA,CAC9B,GAAI,CAIF,OAAO,MAAM/B,CAAAA,CAAkBqC,CAAAA,CAAS,IAAYa,CAAAA,CAAA,sBAClD,IAAIV,CAAAA,CAAkBR,YAAAA,CAAaF,CAAAA,CAAO,IAAMK,CAAAA,CAAUC,CAAU,CAAC,CAAA,CACrE,OAAIe,SAAAA,CAAUX,CAAM,CAAA,GAClBA,CAAAA,CAAS,MAAMA,CAAAA,CAAAA,CAEVY,CAAAA,CAAqBZ,CAAM,CACpC,CAAA,CAAC,CACH,CAAA,OAAE,CACAP,YAAAA,CAAaH,CAAK,EACpB,CACF,CAAA,CAAA,CAMA,SAAesB,EAAqBhD,CAAAA,CAAmC,CAAA,OAAA8C,CAAAA,CAAA,IAAA,CAAA,IAAA,CAAA,WAAA,CACrE,OAAIC,SAAAA,CAAU/C,CAAO,CAAA,CACZgD,CAAAA,CAAqB,MAAMhD,CAAO,CAAA,CAEvC,KAAA,CAAM,QAAQA,CAAO,CAAA,CAAA,CACT,MAAM,OAAA,CAAQ,GAAA,CAAIA,CAAAA,CAAQ,GAAA,CAAKiD,CAAAA,EAAMD,CAAAA,CAAqBC,CAAC,CAAC,CAAC,CAAA,EAC9D,IAAA,CAAK,EAAE,CAAA,CAElB3C,UAAAA,CAAWN,CAAO,CAAA,CACbgD,CAAAA,CAAsBhD,CAAAA,EAA2B,CAAA,CAEnDD,CAAAA,CAAgBC,CAAO,CAChC,CAAA,CAAA,CAaO,SAASkD,EAAAA,CACdnB,EACAC,CAAAA,CAA4B,EAAC,CACrB,CACR,GAAI,CAAC1B,UAAAA,CAAWyB,CAAS,CAAA,CACvB,OAAAG,KAAAA,CAAM,iDAAiD,CAAA,CAChD,EAAA,CAMT,IAAME,CAAAA,CAASb,CAAAA,CAAgB,IAAMQ,CAAAA,CAAUC,CAAU,CAAC,CAAA,CAE1D,OAAOjC,CAAAA,CAAgBqC,CAAM,CAC/B,CCtLO,SAASe,EAAAA,CAAenB,CAAAA,CAA+D,CAC5F,GAAI,CAACA,CAAAA,CACH,OAAO,IAAA,CAGT,GAAM,CAAE,KAAA,CAAOoB,CAAAA,CAAW,KAAA,CAAAC,CAAM,CAAA,CAAIrB,CAAAA,CAC9BsB,CAAAA,CAAiBF,CAAAA,EAAa,CAACjD,QAAAA,CAASiD,CAAS,CAAA,CACjDG,CAAAA,CAAiB,CAAC,CAACF,CAAAA,CAEzB,GAAI,CAACC,CAAAA,EAAkB,CAACC,CAAAA,CACtB,OAAOvB,CAAAA,CAIT,IAAMI,CAAAA,CAASoB,CAAAA,CAAA,EAAA,CAAKxB,CAAAA,CAAAA,CAEpB,OAAIsB,CAAAA,GACFlB,CAAAA,CAAO,KAAA,CAAQqB,kBAAAA,CAAmBL,CAAS,CAAA,CAAA,CAGzCG,CAAAA,GACFnB,CAAAA,CAAO,KAAA,CAAQsB,cAAAA,CAAeL,CAAK,CAAA,CAAA,CAG9BjB,CACT,CAeO,SAASuB,CAAAA,CAAWC,CAAAA,CAAkBC,CAAAA,CAAwB,CAEnE,GAAIC,QAAAA,CAASD,CAAS,CAAA,EAAKE,UAAAA,CAAWF,CAAS,CAAA,CAC7C,OAAOF,CAAAA,CAAWC,CAAAA,CAAUC,EAAU,KAAK,CAAA,CAI7C,GAAI,CAACA,CAAAA,EAAaA,CAAAA,GAAc,CAAA,CAC9B,OAAO,EAAA,CAIT,GAAID,CAAAA,GAAa,OAAA,CAAS,CACxB,IAAMI,EAAkBN,cAAAA,CAAeG,CAAS,CAAA,CAChD,OAAKG,CAAAA,CAID7D,QAAAA,CAAS6D,CAAe,CAAA,CACnB,CAAA,QAAA,EAAWA,CAAe,CAAA,CAAA,CAAA,CAG5B,CAAA,QAAA,EAAWC,aAAAA,CAAcD,CAAe,CAAC,CAAA,CAAA,CAAA,CAPvC,EAQX,CAGA,GAAIJ,CAAAA,GAAa,OAAA,CAAS,CACxB,IAAMM,CAAAA,CAAsBT,kBAAAA,CAAmBI,CAAS,CAAA,CACxD,OAAOK,CAAAA,CAAsB,WAAWA,CAAmB,CAAA,CAAA,CAAA,CAAM,EACnE,CAGA,OAAIN,CAAAA,CAAS,UAAA,CAAW,IAAI,CAAA,CACnB,EAAA,CAILC,CAAAA,GAAc,IAAA,CACT,CAAA,CAAA,EAAID,CAAQ,GAId,CAAA,CAAA,EAAIA,CAAQ,CAAA,EAAA,EAAKpD,UAAAA,CAAW,MAAA,CAAOqD,CAAS,CAAC,CAAC,CAAA,CAAA,CACvD,CCvFO,SAASM,CAAAA,CAAQC,CAAAA,CAAcC,CAAAA,CAAwB,CAC5D,OAAInE,MAAMmE,CAAK,CAAA,EAAKA,CAAAA,GAAU,KAAA,CAAc,EAAA,CACxCA,CAAAA,GAAU,IAAA,CAAa,CAAA,CAAA,EAAID,CAAI,CAAA,CAAA,CAC5B,CAAA,CAAA,EAAIA,CAAI,CAAA,EAAA,EAAK5D,UAAAA,CAAW,OAAO6D,CAAK,CAAC,CAAC,CAAA,CAAA,CAC/C,CAQO,SAASC,CAAAA,CAASD,CAAAA,CAAwB,CAC/C,IAAME,CAAAA,CAAaC,CAAAA,CAAkBH,CAAK,CAAA,CAC1C,OAAKE,CAAAA,CACE,CAAA,QAAA,EAAW/D,UAAAA,CAAW+D,CAAU,CAAC,CAAA,CAAA,CAAA,CADhB,EAE1B,CAQO,SAASE,CAAAA,CAASJ,CAAAA,CAAwB,CAC/C,GAAInE,KAAAA,CAAMmE,CAAK,CAAA,CAAG,OAAO,EAAA,CACzB,GAAIlE,QAAAA,CAASkE,CAAK,CAAA,CAAG,OAAOA,CAAAA,CAAQ,CAAA,QAAA,EAAW7D,UAAAA,CAAW6D,CAAK,CAAC,CAAA,CAAA,CAAA,CAAM,GACtE,GAAIK,QAAAA,CAASL,CAAK,CAAA,CAAG,CACnB,IAAMM,CAAAA,CAAMN,CAAAA,CACNO,CAAAA,CAAkB,EAAC,CACzB,IAAA,IAAWC,CAAAA,IAAOF,CAAAA,CAAK,CACrB,IAAMG,CAAAA,CAAIH,CAAAA,CAAIE,CAAG,CAAA,CACjB,GAAIC,CAAAA,EAAK,IAAA,EAAQA,CAAAA,GAAM,KAAA,CAAO,CAC5B,IAAMC,CAAAA,CAAOF,CAAAA,CAAI,WAAW,IAAI,CAAA,CAAIA,CAAAA,CAAMG,EAAAA,CAAaH,CAAG,CAAA,CAC1DD,CAAAA,CAAM,IAAA,CAAK,CAAA,EAAGG,CAAI,CAAA,CAAA,EAAIvE,UAAAA,CAAW,MAAA,CAAOsE,CAAC,CAAC,CAAC,CAAA,CAAE,EAC/C,CACF,CACA,OAAKF,EAAM,MAAA,CACJ,CAAA,QAAA,EAAWA,CAAAA,CAAM,IAAA,CAAK,GAAG,CAAC,IADP,EAE5B,CACA,OAAO,EACT,CASO,SAASK,EAAAA,CAAUjD,CAAAA,CAAwC,CAChE,GAAI,CAACA,CAAAA,EAAS,CAAC0C,QAAAA,CAAS1C,CAAK,CAAA,CAAG,OAAO,EAAA,CACvC,IAAIkD,CAAAA,CAAM,EAAA,CACV,IAAA,IAAWL,CAAAA,IAAO7C,CAAAA,CACZ6C,CAAAA,GAAQ,UAAA,EAAcA,CAAAA,GAAQ,KAAA,EAASA,CAAAA,CAAI,WAAW,IAAI,CAAA,GAC1DA,CAAAA,GAAQ,OAAA,EAAWA,CAAAA,GAAQ,WAAA,CAC7BK,CAAAA,EAAOZ,CAAAA,CAAStC,CAAAA,CAAM6C,CAAG,CAAC,CAAA,CACjBA,CAAAA,GAAQ,OAAA,CACjBK,GAAOT,CAAAA,CAASzC,CAAAA,CAAM6C,CAAG,CAAC,CAAA,CAE1BK,CAAAA,EAAOf,CAAAA,CAAQU,CAAAA,CAAK7C,CAAAA,CAAM6C,CAAG,CAAC,CAAA,CAAA,CAGlC,OAAOK,CACT,CASA,SAASV,CAAAA,CAAkBH,CAAAA,CAAwB,CACjD,GAAInE,KAAAA,CAAMmE,CAAK,CAAA,EAAKA,CAAAA,GAAU,KAAA,CAAO,OAAO,EAAA,CAC5C,GAAIlE,QAAAA,CAASkE,CAAK,CAAA,CAAG,OAAOA,CAAAA,CAC5B,GAAIjE,OAAAA,CAAQiE,CAAK,CAAA,CACf,OAAQA,CAAAA,CAAoB,GAAA,CAAIG,CAAiB,CAAA,CAAE,MAAA,CAAO,OAAO,EAAE,IAAA,CAAK,GAAG,CAAA,CAE7E,GAAIE,QAAAA,CAASL,CAAK,CAAA,CAAG,CACnB,IAAMM,CAAAA,CAAMN,CAAAA,CACZ,OAAO,MAAA,CAAO,IAAA,CAAKM,CAAG,CAAA,CACnB,MAAA,CAAQQ,CAAAA,EAAM,CAAA,CAAQR,CAAAA,CAAIQ,CAAC,CAAE,CAAA,CAC7B,IAAA,CAAK,GAAG,CACb,CACA,OAAO,OAAOd,CAAK,CACrB,CAKA,IAAMe,EAAAA,CAAW,QAAA,CAKjB,SAASJ,EAAAA,CAAaK,CAAAA,CAAqB,CACzC,OAAOA,CAAAA,CAAI,UAAA,CAAWD,EAAAA,CAAWE,GAAM,CAAA,CAAA,EAAIA,CAAAA,CAAE,WAAA,EAAa,CAAA,CAAE,CAC9D,CCpGO,SAASC,EAAAA,CAASvD,CAAAA,CAAkC,CACzD,OAAOjC,CAAAA,CAAgBiC,CAAAA,CAAM,QAAQ,CACvC,CAoBO,IAAMwD,CAAAA,CAA2B,yBAC3BC,CAAAA,CAAuB,uBAAA,CACvBC,CAAAA,CAAqB,sBAS3B,SAASC,EAAAA,CAAO3D,CAAAA,CAA+B,CA7CtD,IAAArC,CAAAA,CA8CE,GAAM,CAAE,MAAA,CAAAiG,CAAAA,CAAQ,SAAAC,CAAS,CAAA,CAAI7D,CAAAA,CACvB8D,CAAAA,CAAW/F,CAAAA,CAAgB8F,CAAQ,CAAA,CAOzC,GAAA,CAJiBvF,UAAAA,CAAW0B,CAAAA,CAAM,QAAQ,CAAA,CACtC,CAAC,CAAEA,EAAM,QAAA,EAA2B,CACpC,CAAC,CAACA,CAAAA,CAAM,QAAA,GAEI,CAAC4D,CAAAA,CAAQ,OAAOE,CAAAA,CAEhC,IAAMjG,CAAAA,CAAMH,CAAAA,EAAc,CAI1B,OAHI,CAACG,CAAAA,EAGD,CAACM,QAAAA,CAASyF,CAAM,CAAA,CAIXE,CAAAA,EAGTjG,CAAAA,CAAI,SAAA,CAAU+F,CAAM,CAAA,CAAA,CAAA,CACjBjG,CAAAA,CAAAE,CAAAA,CAAI,SAAA,CAAU+F,CAAM,CAAA,GAApB,IAAA,CAAAjG,CAAAA,CAAyB,EAAA,EAAM8F,CAAAA,CAAuBK,CAAAA,CAAWJ,CAAAA,CAE7DF,CAAAA,CACT,CASO,SAASO,EAAAA,CAAS/D,CAAAA,CAA2D,CAClF,GAAM,CAAE,QAAA,CAAA6D,CAAAA,CAAU,QAAA,CAAAG,CAAS,CAAA,CAAIhE,CAAAA,CAC/B,OAAO9B,KAAAA,CAAM2F,CAAQ,CAAA,CAAI9F,CAAAA,CAAgBiG,CAAQ,CAAA,CAAIjG,CAAAA,CAAgB8F,CAAQ,CAC/E,CAcA,SAASI,EAAAA,CAAeC,CAAAA,CAAoC,CAjG5D,IAAAvG,CAAAA,CAAAwG,CAAAA,CAkGE,OAAIjG,KAAAA,CAAMgG,CAAK,CAAA,CAAU,GAErBxB,QAAAA,CAASwB,CAAK,CAAA,EAAK,OAAA,GAAWA,CAAAA,CAAAA,CACvBvG,CAAAA,CAAAuG,CAAAA,CAAyB,KAAA,GAAzB,IAAA,CAAAvG,CAAAA,CAAkC,EAAC,CAE1CW,UAAAA,CAAW4F,CAAK,GACTC,CAAAA,CAAAD,CAAAA,EAAoB,GAApB,IAAA,CAAAC,CAAAA,CAAyB,EAAC,CAE9BD,CACT,CAKO,SAASE,EAAAA,CAAOpE,CAAAA,CAA+B,CACpD,IAAMqE,EAAOJ,EAAAA,CAAejE,CAAAA,CAAM,IAAI,CAAA,CAEtC,GAAIqE,CAAAA,CAAK,MAAA,GAAW,CAAA,CAClB,OAAOtG,CAAAA,CAAgBiC,CAAAA,CAAM,QAAQ,CAAA,CAGvC,IAAMK,EAASL,CAAAA,CAAM,QAAA,CACrB,OAAK1B,UAAAA,CAAW+B,CAAM,CAAA,CAEfgE,CAAAA,CAAK,GAAA,CAAI,CAAChG,CAAAA,CAAM,CAAA,GAAMN,CAAAA,CAAgBsC,CAAAA,CAAOhC,CAAAA,CAAM,CAAC,CAAC,CAAC,CAAA,CAAE,IAAA,CAAK,EAAE,CAAA,CAFtC,EAGlC","file":"server.esm.js","sourcesContent":["// Use bare specifier (not `node:async_hooks`) as a workaround for tsup's\n// dts worker on TS 6.x, which reports TS2591 against the `node:` prefix\n// in some CI environments.\n// eslint-disable-next-line unicorn/prefer-node-protocol\nimport { AsyncLocalStorage } from 'async_hooks';\n\n/**\n * SSR rendering context.\n\n */\nexport interface SSRContext {\n /**\n * Map of teleport target → concatenated HTML string. The caller is\n * responsible for inlining each entry into the final document\n * (e.g. by replacing a placeholder in a shell template).\n */\n teleports: Record<string, string>;\n\n /**\n * Free-form key/value bag for user-defined per-render metadata\n * (e.g. collected `<head>` tags, status codes, response headers).\n */\n [key: string]: unknown;\n}\n\n/**\n * Create an empty SSR context with all collection slots initialised.\n */\nexport function createSSRContext(): SSRContext {\n return {\n teleports: Object.create(null) as Record<string, string>,\n };\n}\n\n/**\n * Async-safe SSR context propagation.\n */\ninterface ContextStore {\n getStore(): SSRContext | null | undefined;\n run<T>(ctx: SSRContext | null, fn: () => T): T;\n}\nconst store: ContextStore = new AsyncLocalStorage<SSRContext | null>();\n\n/**\n * Get the current SSR context, if any. Returns `null` when called outside of\n * a `renderToString` invocation, or when the caller did not pass a context.\n */\nexport function getSSRContext(): SSRContext | null {\n return store.getStore() ?? null;\n}\n\n/**\n * Run `fn` with `ctx` as the active SSR context. The context is preserved\n * across awaits inside `fn` and restored on exit (including when `fn` throws).\n */\nexport function runWithSSRContext<T>(ctx: SSRContext | null, fn: () => T): T {\n return store.run(ctx, fn);\n}\n","import { escapeHTML, isArray, isFunction, isNil, isString } from '@estjs/shared';\n\n/**\n * Convert content to string for SSR output.\n *\n * @param content - The content to convert.\n * @param isSvg - Whether the content is SVG.\n * @returns {string} The content as a string.\n */\nexport function convertToString(content: unknown, isSvg = false): string {\n if (isNil(content)) {\n return '';\n }\n\n if (isString(content)) {\n return content;\n }\n if (isArray(content)) {\n return (content as unknown[]).map((item: unknown) => convertToString(item, isSvg)).join('');\n }\n\n if (isFunction(content)) {\n return convertToString((content as () => unknown)(), isSvg);\n }\n\n return String(content);\n}\n\n/**\n * Convert child-expression content to escaped text for SSR output.\n *\n * JSX expression children have text semantics, so primitives must be escaped\n * before interpolation into the surrounding HTML template.\n */\nexport function convertTextChildToString(content: unknown): string {\n if (content === false || isNil(content)) {\n return '';\n }\n\n if (isString(content)) {\n return escapeHTML(content);\n }\n\n if (isArray(content)) {\n return (content as unknown[]).map((item) => convertTextChildToString(item)).join('');\n }\n\n if (isFunction(content)) {\n return convertTextChildToString((content as () => unknown)());\n }\n\n return escapeHTML(String(content));\n}\n\n/**\n * Combined regex that matches either a `data-idx=\"<digits>\"` attribute or a\n * hydration comment marker (numeric body only) in a single scan. Capture groups:\n * 1. data-idx index value (if attribute matched)\n * 2. numeric comment body (if hydration marker matched)\n *\n * Non-numeric comments (e.g. `<!-- user content -->`) are preserved unchanged.\n */\nconst HYDRATION_REWRITE_REGEX = /data-idx=\"(\\d+)\"|<!--(\\d+)-->/g;\n\n/**\n * Inject the root hydration attribute into the opening tag without corrupting\n * self-closing tags such as `<img />` or `<input/>`.\n */\nfunction injectRootHydrationAttribute(htmlContent: string, hydrationId: string): string {\n const tagStart = htmlContent.indexOf('<');\n if (tagStart === -1) {\n return htmlContent;\n }\n\n let quote: '\"' | \"'\" | undefined;\n for (let i = tagStart + 1; i < htmlContent.length; i++) {\n const char = htmlContent[i];\n\n if (quote) {\n if (char === quote) {\n quote = undefined;\n }\n continue;\n }\n\n if (char === '\"' || char === \"'\") {\n quote = char;\n continue;\n }\n\n if (char === '>') {\n let insertAt = i;\n for (let j = i - 1; j > tagStart; j--) {\n const prev = htmlContent[j];\n if (prev === ' ' || prev === '\\n' || prev === '\\t' || prev === '\\r') {\n continue;\n }\n if (prev === '/') {\n insertAt = j;\n }\n break;\n }\n\n return `${htmlContent.slice(0, insertAt)} data-hk=\"${hydrationId}\"${htmlContent.slice(insertAt)}`;\n }\n }\n\n return htmlContent;\n}\n\n/**\n * Add hydration attributes to HTML content.\n *\n * @param htmlContent - The html content.\n * @param hydrationId - The hydration id.\n * @returns {string} The html content with hydration attributes.\n */\nexport function addAttributes(htmlContent: string, hydrationId: string): string {\n // Single-pass rewrite for both `data-idx` and comment markers — half the\n // string traversals compared to chained `replaceAll` calls.\n return injectRootHydrationAttribute(htmlContent, hydrationId).replaceAll(\n HYDRATION_REWRITE_REGEX,\n (_match, dataIdx, commentBody) =>\n dataIdx !== undefined\n ? `data-idx=\"${hydrationId}-${dataIdx}\"`\n : `<!--${hydrationId}-${commentBody}-->`,\n );\n}\n","import { error, isFunction, isPromise } from '@estjs/shared';\nimport { type ComponentFn, type ComponentProps, resetHydrationKey } from '@estjs/template';\nimport {\n type Scope,\n createScope,\n disposeScope,\n getActiveScope,\n runWithScope,\n} from '@estjs/template/internal';\nimport { type SSRContext, runWithSSRContext } from './context';\nimport { addAttributes, convertToString } from './utils';\n\n/**\n * Runs `fn` inside a freshly created scope whose parent is the currently\n * active scope (if any). The scope is always disposed, even when `fn` throws,\n * so `provide` / `inject` state from one render cannot leak into another.\n */\nfunction runInFreshScope<T>(fn: () => T, parent: Scope | null = getActiveScope()): T {\n const scope = createScope(parent);\n try {\n return runWithScope(scope, fn);\n } finally {\n disposeScope(scope);\n }\n}\n\n/**\n * Render a component to HTML string.\n *\n * Each invocation runs inside its own root scope so that `provide()` calls\n * stay isolated between independent `renderToString` calls.\n *\n * @param component - The component to render.\n * @param props - The props to pass to the component.\n * @param context - Optional {@link SSRContext} that collects out-of-tree\n * render output (currently: `Portal`/`Teleport` content). The same context\n * is visible to nested `createSSGComponent` calls; the caller integrates\n * `context.teleports[selector]` into the final document.\n * @returns {string} The rendered HTML string.\n */\nexport function renderToString<P extends ComponentProps = ComponentProps>(\n component: ComponentFn<P>,\n props: P | ComponentProps = {},\n context: SSRContext | null = null,\n): string {\n if (!isFunction(component)) {\n error('Component must be a function');\n return '';\n }\n\n // Reset the hydration key counter\n resetHydrationKey();\n\n // Render the component within a fresh root scope (parent: null).\n const result = runWithSSRContext(context, () =>\n runInFreshScope(() => component(props as P), null),\n );\n\n if (__DEV__ && isPromise(result)) {\n error('renderToString received a Promise — use renderToStringAsync for async components.');\n }\n\n // Convert the result to string\n return convertToString(result);\n}\n\n/**\n * Render template with components (used by babel plugin in SSG mode).\n *\n * @param templates - The template fragments.\n * @param hydrationKey - The hydration key.\n * @param components - The rendered component strings.\n * @returns {string} The rendered HTML string.\n */\nexport function render(templates: string[], hydrationKey: string, ...components: string[]): string {\n /**\n * JSX source code:\n * <div>\n * <div>\n * <Component1 />\n * <Component2 />\n * </div>\n * <Component3 />\n * </div>\n *\n * Compiles to:\n *\n * let _tmpl = [\n * '<div><div>',\n * '</div>',\n * '</div>',\n * ]\n *\n * function component(props) {\n * return render(_tmpl, getHydrationKey(),\n * createSSGComponent(Component1, {}),\n * createSSGComponent(Component2, {}),\n * createSSGComponent(Component3, {})\n * );\n * }\n */\n\n // Direct string concatenation — avoids array allocation + join overhead\n // for typical 2-4 template fragments.\n const templateLen = templates.length;\n const componentLen = components.length;\n let content = '';\n\n for (let i = 0; i < templateLen; i++) {\n content += templates[i];\n if (i < componentLen && components[i]) {\n content += convertToString(components[i]);\n }\n }\n\n // Add hydration key attribute (data-hk) to the root element\n return addAttributes(content, hydrationKey);\n}\n\n/**\n * Async variant of {@link renderToString}. Awaits component results so that\n * `async` components and promise-returning expressions can participate in SSR.\n *\n * The awaited value is passed through the same {@link convertToString}\n * pipeline as the synchronous path, which itself transparently awaits any\n * nested promises (arrays of promises, promise-returning thunks, etc.).\n */\nexport async function renderToStringAsync<P extends ComponentProps = ComponentProps>(\n component: ComponentFn<P>,\n props: P | ComponentProps = {},\n context: SSRContext | null = null,\n): Promise<string> {\n if (!isFunction(component)) {\n error('Component must be a function');\n return '';\n }\n\n resetHydrationKey();\n\n const scope = createScope(null);\n try {\n // Keep both the SSR context and the reactive scope active for the entire\n // async render lifetime. This ensures that Portal() calls after an `await`\n // inside async components can still access `getSSRContext()`.\n return await runWithSSRContext(context, async () => {\n let result: unknown = runWithScope(scope, () => component(props as P));\n if (isPromise(result)) {\n result = await result;\n }\n return convertToStringAsync(result);\n });\n } finally {\n disposeScope(scope);\n }\n}\n\n/**\n * Promise-aware variant of `convertToString` used by {@link renderToStringAsync}.\n * Recursively unwraps promises and arrays of promises.\n */\nasync function convertToStringAsync(content: unknown): Promise<string> {\n if (isPromise(content)) {\n return convertToStringAsync(await content);\n }\n if (Array.isArray(content)) {\n const parts = await Promise.all(content.map((c) => convertToStringAsync(c)));\n return parts.join('');\n }\n if (isFunction(content)) {\n return convertToStringAsync((content as () => unknown)());\n }\n return convertToString(content);\n}\n\n/**\n * Create a SSG component (renders component to string).\n *\n * The component executes inside a child scope that inherits from the current\n * active scope, so `inject()` calls can resolve values from ancestor\n * `provide()` calls, and `provide()` inside the component is scoped to it.\n *\n * @param component - The component to create.\n * @param props - The props to pass to the component.\n * @returns {string} The rendered component as a string.\n */\nexport function createSSGComponent<P extends ComponentProps = ComponentProps>(\n component: ComponentFn<P>,\n props: P | ComponentProps = {},\n): string {\n if (!isFunction(component)) {\n error('createSSGComponent: Component is not a function');\n return '';\n }\n\n // Inherit the active scope (set by the enclosing renderToString call or by\n // an outer createSSGComponent) so that provide/inject follow the component\n // tree hierarchy.\n const result = runInFreshScope(() => component(props as P));\n\n return convertToString(result);\n}\n","import { isComputed, isSignal } from '@estjs/signals';\nimport {\n escapeHTML,\n isString,\n normalizeClassName,\n normalizeStyle,\n styleToString,\n} from '@estjs/shared';\n\n/**\n * Normalize component properties\n *\n * Special handling for class and style attributes, converting them to normalized format.\n * Returns a new object when normalization is needed, preserving the original.\n *\n * @param props - Original component properties\n * @returns Normalized component properties\n */\nexport function normalizeProps(props: Record<string, any> | null): Record<string, any> | null {\n if (!props) {\n return null;\n }\n\n const { class: className, style } = props;\n const needsClassNorm = className && !isString(className);\n const needsStyleNorm = !!style;\n\n if (!needsClassNorm && !needsStyleNorm) {\n return props;\n }\n\n // Shallow copy to avoid mutating the caller's props\n const result = { ...props };\n\n if (needsClassNorm) {\n result.class = normalizeClassName(className);\n }\n\n if (needsStyleNorm) {\n result.style = normalizeStyle(style);\n }\n\n return result;\n}\n\n/**\n * Generate server-side rendering attribute string\n *\n * Generate HTML-compatible attribute string based on attribute type, handling special cases:\n * - Automatic unwrapping of reactive values\n * - Normalization of special attributes (style/class)\n * - Ignoring event attributes\n * - Special handling for boolean attributes\n *\n * @param attrName - Attribute name\n * @param attrValue - Attribute value\n * @returns Formatted HTML attribute string\n */\nexport function setSSGAttr(attrName: string, attrValue: any): string {\n // Handle reactive values (signals or computed values)\n if (isSignal(attrValue) || isComputed(attrValue)) {\n return setSSGAttr(attrName, attrValue.value);\n }\n\n // Ignore null, undefined, and false value attributes\n if (!attrValue && attrValue !== 0) {\n return '';\n }\n\n // Special attribute handling: style\n if (attrName === 'style') {\n const normalizedStyle = normalizeStyle(attrValue);\n if (!normalizedStyle) {\n return '';\n }\n\n if (isString(normalizedStyle)) {\n return ` style=\"${normalizedStyle}\"`;\n }\n\n return ` style=\"${styleToString(normalizedStyle)}\"`;\n }\n\n // Special attribute handling: class\n if (attrName === 'class') {\n const normalizedClassName = normalizeClassName(attrValue);\n return normalizedClassName ? ` class=\"${normalizedClassName}\"` : '';\n }\n\n // Ignore event handler attributes (client-side behavior)\n if (attrName.startsWith('on')) {\n return '';\n }\n\n // Special handling for boolean attributes\n if (attrValue === true) {\n return ` ${attrName}`;\n }\n\n // Standard attribute handling — escape to prevent attribute injection (XSS)\n return ` ${attrName}=\"${escapeHTML(String(attrValue))}\"`;\n}\n","import { escapeHTML, isArray, isNil, isObject, isString } from '@estjs/shared';\n\n// ---------------------------------------------------------------------------\n// SSR attribute helpers\n// Used by babel-plugin server-mode generated code.\n// ---------------------------------------------------------------------------\n\n/**\n * Render a single attribute as an HTML attribute string.\n *\n * @param name - The name of the attribute.\n * @param value - The value of the attribute.\n * @returns {string} The rendered attribute string (e.g., ` name=\"value\"`).\n */\nexport function ssrAttr(name: string, value: unknown): string {\n if (isNil(value) || value === false) return '';\n if (value === true) return ` ${name}`;\n return ` ${name}=\"${escapeHTML(String(value))}\"`;\n}\n\n/**\n * Render a `class` attribute as an HTML attribute string.\n *\n * @param value - The class value (string, object, or array).\n * @returns {string} The rendered class attribute string.\n */\nexport function ssrClass(value: unknown): string {\n const normalized = normalizeClassSSR(value);\n if (!normalized) return '';\n return ` class=\"${escapeHTML(normalized)}\"`;\n}\n\n/**\n * Render a `style` attribute as an HTML attribute string.\n *\n * @param value - The style value (string or object).\n * @returns {string} The rendered style attribute string.\n */\nexport function ssrStyle(value: unknown): string {\n if (isNil(value)) return '';\n if (isString(value)) return value ? ` style=\"${escapeHTML(value)}\"` : '';\n if (isObject(value)) {\n const obj = value as Record<string, unknown>;\n const parts: string[] = [];\n for (const key in obj) {\n const v = obj[key];\n if (v != null && v !== false) {\n const prop = key.startsWith('--') ? key : camelToKebab(key);\n parts.push(`${prop}:${escapeHTML(String(v))}`);\n }\n }\n if (!parts.length) return '';\n return ` style=\"${parts.join(';')}\"`;\n }\n return '';\n}\n\n/**\n * Render a spread of props as HTML attribute strings.\n * Skips event handlers and special keys.\n *\n * @param props - The props object to spread.\n * @returns {string} The rendered attribute strings.\n */\nexport function ssrSpread(props: Record<string, unknown>): string {\n if (!props || !isObject(props)) return '';\n let out = '';\n for (const key in props) {\n if (key === 'children' || key === 'ref' || key.startsWith('on')) continue;\n if (key === 'class' || key === 'className') {\n out += ssrClass(props[key]);\n } else if (key === 'style') {\n out += ssrStyle(props[key]);\n } else {\n out += ssrAttr(key, props[key]);\n }\n }\n return out;\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Normalizes SSR class input into a string.\n */\nfunction normalizeClassSSR(value: unknown): string {\n if (isNil(value) || value === false) return '';\n if (isString(value)) return value;\n if (isArray(value)) {\n return (value as unknown[]).map(normalizeClassSSR).filter(Boolean).join(' ');\n }\n if (isObject(value)) {\n const obj = value as Record<string, unknown>;\n return Object.keys(obj)\n .filter((k) => Boolean(obj[k]))\n .join(' ');\n }\n return String(value);\n}\n\n/**\n * Matches uppercase characters for camelCase to kebab-case conversion.\n */\nconst UPPER_RE = /[A-Z]/g;\n\n/**\n * Converts a camelCase CSS property into kebab-case.\n */\nfunction camelToKebab(str: string): string {\n return str.replaceAll(UPPER_RE, (m) => `-${m.toLowerCase()}`);\n}\n","import { isFunction, isNil, isObject, isString, warn } from '@estjs/shared';\nimport { convertToString } from './utils';\nimport { getSSRContext } from './context';\n\nexport interface SSRComponentProps {\n children?: unknown;\n [key: string]: unknown;\n}\n\n/**\n * SSR Fragment — returns children converted to a string.\n */\nexport function Fragment(props: SSRComponentProps): string {\n return convertToString(props.children);\n}\n\n// ---------------------------------------------------------------------------\n// Portal (SSR)\n// ---------------------------------------------------------------------------\n\nexport interface SSRPortalProps extends SSRComponentProps {\n /**\n * Teleport target — only CSS selector strings are meaningful on the server.\n * Element references are silently inlined (they have no server-side meaning).\n */\n target?: string;\n /**\n * When truthy, children render inline instead of being teleported.\n * The babel plugin resolves reactive getters before reaching the component,\n * so only a plain boolean is needed on the server.\n */\n disabled?: boolean | (() => boolean);\n}\n\nexport const TELEPORT_CALLSITE_ANCHOR = '<!--teleport-anchor-->';\nexport const TELEPORT_BLOCK_START = '<!--teleport-start-->';\nexport const TELEPORT_BLOCK_END = '<!--teleport-end-->';\n\n/**\n * SSR Portal — collects teleported content into `ctx.teleports[target]`.\n *\n * Emits `<!--teleport-anchor-->` at the call site and wraps children with\n * `<!--teleport-start-->...<!--teleport-end-->` in the target buffer.\n * Disabled / no-target / no-context falls back to inline rendering.\n */\nexport function Portal(props: SSRPortalProps): string {\n const { target, children } = props;\n const rendered = convertToString(children);\n\n // Unwrap disabled getter (for API parity with client)\n const disabled = isFunction(props.disabled)\n ? !!(props.disabled as () => boolean)()\n : !!props.disabled;\n\n if (disabled || !target) return rendered;\n\n const ctx = getSSRContext();\n if (!ctx) return rendered;\n\n // Only string selectors are meaningful for SSR; DOM nodes are inlined.\n if (!isString(target)) {\n if (__DEV__) {\n warn('[Portal] SSR only supports string selector targets; rendering inline.');\n }\n return rendered;\n }\n\n ctx.teleports[target] =\n (ctx.teleports[target] ?? '') + TELEPORT_BLOCK_START + rendered + TELEPORT_BLOCK_END;\n\n return TELEPORT_CALLSITE_ANCHOR;\n}\n\n// ---------------------------------------------------------------------------\n// Suspense (SSR)\n// ---------------------------------------------------------------------------\n\n/**\n * SSR Suspense — renders children when available, otherwise the fallback slot.\n */\nexport function Suspense(props: SSRComponentProps & { fallback?: unknown }): string {\n const { children, fallback } = props;\n return isNil(children) ? convertToString(fallback) : convertToString(children);\n}\n\n// ---------------------------------------------------------------------------\n// For (SSR)\n// ---------------------------------------------------------------------------\n\nexport interface SSRForProps<T> {\n each: T[] | { value: T[] } | (() => T[]);\n children: (item: T, index: number) => unknown;\n key?: (item: T, index: number) => unknown;\n fallback?: unknown;\n}\n\n/** Unwrap signal / getter / plain array for SSR without subscribing. */\nfunction resolveList<T>(input: SSRForProps<T>['each']): T[] {\n if (isNil(input)) return [];\n // Duck-type signal check — avoids importing @estjs/signals on the server.\n if (isObject(input) && 'value' in input) {\n return ((input as { value: T[] }).value ?? []) as T[];\n }\n if (isFunction(input)) {\n return ((input as () => T[])() ?? []) as T[];\n }\n return input as T[];\n}\n\n/**\n * SSR For — maps each item through the render function and joins the output.\n */\nexport function For<T>(props: SSRForProps<T>): string {\n const list = resolveList<T>(props.each);\n\n if (list.length === 0) {\n return convertToString(props.fallback);\n }\n\n const render = props.children;\n if (!isFunction(render)) return '';\n\n return list.map((item, i) => convertToString(render(item, i))).join('');\n}\n"]}