@jasonshimmy/custom-elements-runtime 3.6.0 → 3.7.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -9
- package/dist/custom-elements-runtime.cjs.js +2 -2
- package/dist/custom-elements-runtime.cjs.js.map +1 -1
- package/dist/custom-elements-runtime.es.js +25 -4
- package/dist/custom-elements-runtime.es.js.map +1 -1
- package/dist/custom-elements-runtime.jit-css.cjs.js +1 -1
- package/dist/custom-elements-runtime.jit-css.es.js +2 -2
- package/dist/custom-elements-runtime.router.cjs.js +1 -1
- package/dist/custom-elements-runtime.router.es.js +3 -3
- package/dist/custom-elements-runtime.ssr-middleware.cjs.js +1 -1
- package/dist/custom-elements-runtime.ssr-middleware.es.js +1 -1
- package/dist/custom-elements-runtime.ssr.cjs.js +1 -1
- package/dist/custom-elements-runtime.ssr.es.js +2 -2
- package/dist/custom-elements-runtime.vite-plugin.cjs.js +1 -1
- package/dist/custom-elements-runtime.vite-plugin.es.js +1 -1
- package/dist/{helpers-kOWgceUQ.js → helpers-BiGdX-3A.js} +22 -14
- package/dist/helpers-BiGdX-3A.js.map +1 -0
- package/dist/helpers-hGU9czPG.cjs +5 -0
- package/dist/helpers-hGU9czPG.cjs.map +1 -0
- package/dist/{hooks-BY_35J9Y.cjs → hooks-CACte2Ir.cjs} +2 -2
- package/dist/{hooks-BY_35J9Y.cjs.map → hooks-CACte2Ir.cjs.map} +1 -1
- package/dist/{hooks-Dj1xwqpK.js → hooks-yP009oF9.js} +2 -2
- package/dist/{hooks-Dj1xwqpK.js.map → hooks-yP009oF9.js.map} +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/runtime/component/async-component.d.ts +48 -0
- package/dist/runtime/reactive.d.ts +3 -1
- package/dist/runtime/render.d.ts +7 -0
- package/dist/{ssr-Bg9jYXYv.js → ssr-COmrqY64.js} +3 -3
- package/dist/{ssr-Bg9jYXYv.js.map → ssr-COmrqY64.js.map} +1 -1
- package/dist/{ssr-CucZ-Iwz.cjs → ssr-CUT0FqUz.cjs} +2 -2
- package/dist/{ssr-CucZ-Iwz.cjs.map → ssr-CUT0FqUz.cjs.map} +1 -1
- package/dist/{tag-utils-ZOoyzCm9.cjs → tag-utils-CMy95A4Z.cjs} +2 -2
- package/dist/{tag-utils-ZOoyzCm9.cjs.map → tag-utils-CMy95A4Z.cjs.map} +1 -1
- package/dist/{tag-utils-Dg0vRKq9.js → tag-utils-DVutXfzj.js} +2 -2
- package/dist/{tag-utils-Dg0vRKq9.js.map → tag-utils-DVutXfzj.js.map} +1 -1
- package/dist/{template-compiler-BJRZoRzZ.js → template-compiler-BkR0G45f.js} +63 -52
- package/dist/{template-compiler-BJRZoRzZ.js.map → template-compiler-BkR0G45f.js.map} +1 -1
- package/dist/{template-compiler-C0SkzB_f.cjs → template-compiler-EdgxOr6e.cjs} +6 -6
- package/dist/{template-compiler-C0SkzB_f.cjs.map → template-compiler-EdgxOr6e.cjs.map} +1 -1
- package/package.json +1 -1
- package/dist/helpers-7zLtbh_q.cjs +0 -5
- package/dist/helpers-7zLtbh_q.cjs.map +0 -1
- package/dist/helpers-kOWgceUQ.js.map +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const e=require(`./logger-Dkht1dCX.cjs`),t=require(`./namespace-helpers-yYIb7INq.cjs`),n=require(`./helpers-
|
|
1
|
+
const e=require(`./logger-Dkht1dCX.cjs`),t=require(`./namespace-helpers-yYIb7INq.cjs`),n=require(`./helpers-hGU9czPG.cjs`),r=require(`./css-utils-CFeP8SK1.cjs`),i=require(`./hooks-CACte2Ir.cjs`),a=require(`./style-A8l3aQ52.cjs`);var o=new Set([`area`,`base`,`br`,`col`,`embed`,`hr`,`img`,`input`,`link`,`meta`,`param`,`source`,`track`,`wbr`]);function s(e,r,i){let a=i.injectSvgNamespace??!0,o=i.injectKnownNamespaces??a,s={...e};return a&&r===`svg`&&!(`xmlns`in s)?s.xmlns=t.t:o&&r in t.n&&!(`xmlns`in s)&&(s.xmlns=t.n[r]),Object.entries(s).map(([e,t])=>` ${e}="${n.r(String(t))}"`).join(``)}function c(e){return Object.entries(e).map(([e,t])=>` ${e}="${n.r(String(t))}"`).join(``)}function l(e,t){if(typeof e==`string`)return n.r(e);if(e.tag===`#text`)return typeof e.children==`string`?n.r(e.children):``;if(e.tag===`#anchor`)return(Array.isArray(e.children)?e.children.filter(e=>e!=null):[]).map(e=>l(e,t)).join(``);if(e.tag===`#raw`)return typeof e.children==`string`?e.children:``;let r=s(e.props?.attrs?{...e.props.attrs}:{},e.tag,t??{});if(o.has(e.tag))return`<${e.tag}${r}>`;let i=Array.isArray(e.children)?e.children.filter(e=>e!=null).map(e=>l(e,t)).join(``):typeof e.children==`string`?n.r(e.children):e.children?l(e.children,t):``;return`<${e.tag}${r}>${i}</${e.tag}>`}var u=`<script>(function(){if(HTMLTemplateElement.prototype.hasOwnProperty('shadowRootMode'))return;document.querySelectorAll('template[shadowrootmode]').forEach(function(t){var m=t.getAttribute('shadowrootmode');var s=t.parentElement.attachShadow({mode:m});s.appendChild(t.content);t.remove();});})()<\/script>`;function d(e){return e.includes(`-`)&&t.o.has(e)}function f(e,t){let n=[r.a];e.trim()&&n.push(e);let i=a.l(t);i.trim()&&n.push(i);let o=r.d(n.join(`
|
|
2
2
|
`));return o?`<style>${o}</style>`:``}var p=null,m=0;function h(e){p=e,m=0}function g(){p=null}function _(e,t){if(!t.dsd)return l(e,t);if(typeof e==`string`)return n.r(e);let r=e.tag;if(r===`#text`||r===`#anchor`||r===`#raw`)return l(e,t);if(d(r))return v(e,t);let i=s(e.props?.attrs?{...e.props.attrs}:{},r,t);return o.has(r)?`<${r}${i}>`:`<${r}${i}>${y(e.children,t)}</${r}>`}function v(n,r){let a=n.tag,o=t.o.get(a),s=n.props?.attrs??{},l=c(s);if(!o)return`<${a}${l}><template shadowrootmode="open"></template>${y(n.children,r)}</${a}>`;let u=o.hydrate,d=u&&u!==`load`?` data-cer-hydrate="${u}"`:``,{shadowVNode:h,useStyleCSS:g,asyncPromise:v}=i.S(o,s,a,r.router);if(v&&p===null&&e.r(`[SSR] Component "${a}" has an async render function. In standard SSR the shadow DOM will be empty. Use renderToStream() for incremental async component streaming.`),v&&p!==null){let e=`cer-stream-${m++}`,t=y(n.children,r);return p.push({id:e,tag:a,attrsString:l,hydrateAttr:d,useStyleCSS:g,lightDOM:t,opts:r,promise:v,router:r.router}),`<${a} id="${e}"${l}${d}><template shadowrootmode="open"></template>${t}</${a}>`}let b=``;h!=null&&(b=Array.isArray(h)?h.map(e=>_(e,r)).join(``):_(h,r));let x=f(g,b),S=y(n.children,r);return`<${a}${l}${d}><template shadowrootmode="open">${x}${b}</template>${S}</${a}>`}function y(e,t){return e?typeof e==`string`?n.r(e):Array.isArray(e)?e.filter(e=>e!=null).map(e=>_(e,t)).join(``):_(e,t):``}function b(e,t){let n={dsd:!0,...t},r=_(e,n);return n.dsdPolyfill===!1?r:r.includes(`</body>`)?r.replace(`</body>`,`${u}</body>`):r+u}function x(e,t){let{jit:n,dsd:r,dsdPolyfill:o,...s}=t??{};n&&a.i(n),i.b();let c,d;try{c=r?b(e,{...s,dsd:!0,dsdPolyfill:!1}):l(e,s)}finally{d=i.x()}let f=a.l(c),p=d.join(`
|
|
3
3
|
`),m=[];f&&m.push(`<style id="cer-ssr-jit">${f}</style>`),p.trim()&&m.push(`<style id="cer-ssr-global">${p}</style>`);let h=c;if(m.length){let e=m.join(``);h=c.includes(`</head>`)?c.replace(`</head>`,`${e}</head>`):`${e}${c}`}return r&&o!==!1&&(h=h.includes(`</body>`)?h.replace(`</body>`,`${u}</body>`):h+u),{html:c,css:f,globalStyles:p,htmlWithStyles:h}}function S(e,t){return x(e,{...t,dsd:!0})}function C(e,t){let n=t?.asyncTimeout??3e4;return new ReadableStream({async start(r){let i=[];h(i);try{let{htmlWithStyles:n}=x(e,t);r.enqueue(n)}catch(e){r.error(e);return}finally{g()}for(let e of i)try{let t=new Promise((e,t)=>setTimeout(()=>t(Error(`[cer] async component timed out after ${n}ms`)),n)),i=await Promise.race([e.promise,t]),a=Array.isArray(i)?i.map(t=>_(t,e.opts)).join(``):_(i,e.opts),o=`${f(e.useStyleCSS,a)}${a}`;r.enqueue(`<script>(function(){var e=document.getElementById(${JSON.stringify(e.id)});if(!e)return;var s=e.shadowRoot;if(!s&&e.attachShadow)try{s=e.attachShadow({mode:'open'});}catch(_){};if(s)s.innerHTML=${JSON.stringify(o)};e.removeAttribute('id');})();<\/script>`)}catch{}r.close()}})}function w(e,t){return C(e,{...t,dsd:!0})}Object.defineProperty(exports,`a`,{enumerable:!0,get:function(){return u}}),Object.defineProperty(exports,`i`,{enumerable:!0,get:function(){return S}}),Object.defineProperty(exports,`n`,{enumerable:!0,get:function(){return w}}),Object.defineProperty(exports,`o`,{enumerable:!0,get:function(){return b}}),Object.defineProperty(exports,`r`,{enumerable:!0,get:function(){return x}}),Object.defineProperty(exports,`s`,{enumerable:!0,get:function(){return l}}),Object.defineProperty(exports,`t`,{enumerable:!0,get:function(){return C}});
|
|
4
|
-
//# sourceMappingURL=ssr-
|
|
4
|
+
//# sourceMappingURL=ssr-CUT0FqUz.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ssr-CucZ-Iwz.cjs","names":[],"sources":["../src/lib/runtime/ssr-utils.ts","../src/lib/runtime/vdom-ssr.ts","../src/lib/runtime/vdom-ssr-dsd.ts","../src/lib/ssr.ts"],"sourcesContent":["/**\n * Shared utilities for SSR renderers.\n * Imported by vdom-ssr.ts and vdom-ssr-dsd.ts to avoid duplication.\n */\nimport { escapeHTML } from './helpers';\nimport { TAG_NAMESPACE_MAP, SVG_NS } from './namespace-helpers';\n\nexport type RenderOptions = {\n /** Backwards-compatible: whether to inject the SVG namespace on <svg> nodes (default true) */\n injectSvgNamespace?: boolean;\n /** Inject known well-known namespaces for tags like <math> when missing (default follows injectSvgNamespace) */\n injectKnownNamespaces?: boolean;\n};\n\nexport const VOID_ELEMENTS = new Set([\n 'area',\n 'base',\n 'br',\n 'col',\n 'embed',\n 'hr',\n 'img',\n 'input',\n 'link',\n 'meta',\n 'param',\n 'source',\n 'track',\n 'wbr',\n]);\n\nexport function buildAttrs(\n attrs: Record<string, unknown>,\n tag: string,\n opts: RenderOptions,\n): string {\n const inject = opts.injectSvgNamespace ?? true;\n const injectKnown = opts.injectKnownNamespaces ?? inject;\n const merged = { ...attrs };\n\n if (inject && tag === 'svg' && !('xmlns' in merged)) {\n merged['xmlns'] = SVG_NS;\n } else if (injectKnown && tag in TAG_NAMESPACE_MAP && !('xmlns' in merged)) {\n merged['xmlns'] = TAG_NAMESPACE_MAP[tag];\n }\n\n return Object.entries(merged)\n .map(([k, v]) => ` ${k}=\"${escapeHTML(String(v))}\"`)\n .join('');\n}\n\nexport function buildRawAttrs(attrs: Record<string, unknown>): string {\n return Object.entries(attrs)\n .map(([k, v]) => ` ${k}=\"${escapeHTML(String(v))}\"`)\n .join('');\n}\n","import type { VNode } from './types';\nimport { escapeHTML } from './helpers';\nimport { VOID_ELEMENTS, buildAttrs, type RenderOptions } from './ssr-utils';\n\n/**\n * Render a VNode to a string (SSR).\n * Kept intentionally minimal: only serializes attributes under `props.attrs`\n * to avoid leaking runtime-only values (functions, reactive state, directives).\n * @param vnode The virtual node to render.\n * @returns The rendered HTML string.\n */\nexport type { RenderOptions } from './ssr-utils';\n\nexport function renderToString(vnode: VNode, opts?: RenderOptions): string {\n if (typeof vnode === 'string') return escapeHTML(vnode) as string;\n\n if (vnode.tag === '#text') {\n return typeof vnode.children === 'string'\n ? (escapeHTML(vnode.children) as string)\n : '';\n }\n\n if (vnode.tag === '#anchor') {\n // Preserve meaningful falsy children (0, false, '') while filtering out\n // only null and undefined. Anchor blocks are normalized by the compiler\n // to exclude null/undefined; SSR should follow the same rule to avoid\n // hydration mismatches where falsy values are significant.\n const children = Array.isArray(vnode.children)\n ? vnode.children.filter((c) => c !== null && c !== undefined)\n : [];\n return children.map((c) => renderToString(c, opts)).join('');\n }\n\n if (vnode.tag === '#raw') {\n return typeof vnode.children === 'string' ? vnode.children : '';\n }\n\n // Collect attributes from props.attrs. For SSR we mirror vnode.attrs\n // but ensure SVG nodes behave like client-side: if this is an <svg>\n // and no xmlns was provided, inject the standard SVG namespace so\n // server markup matches client-created DOM namespace.\n const attrsObj: Record<string, unknown> = vnode.props?.attrs\n ? { ...vnode.props.attrs }\n : {};\n\n const attrsString = buildAttrs(attrsObj, vnode.tag, opts ?? {});\n\n // Handle void elements (self-closing tags)\n if (VOID_ELEMENTS.has(vnode.tag)) {\n return `<${vnode.tag}${attrsString}>`;\n }\n\n const children = Array.isArray(vnode.children)\n ? vnode.children\n .filter((c) => c !== null && c !== undefined)\n .map((c) => renderToString(c, opts))\n .join('')\n : typeof vnode.children === 'string'\n ? escapeHTML(vnode.children)\n : vnode.children\n ? renderToString(vnode.children, opts)\n : '';\n\n return `<${vnode.tag}${attrsString}>${children}</${vnode.tag}>`;\n}\n","/**\n * Declarative Shadow DOM (DSD) SSR renderer.\n *\n * When `dsd: true` is passed to the render options, registered custom elements\n * are serialised as:\n *\n * ```html\n * <my-element attr=\"val\">\n * <template shadowrootmode=\"open\">\n * <style>\n * /* baseReset + useStyle() output + JIT utility CSS *\\/\n * </style>\n * <!-- shadow DOM from component render function -->\n * </template>\n * <!-- light DOM / slotted children from vnode.children -->\n * </my-element>\n * ```\n *\n * The browser parses the `<template shadowrootmode=\"open\">` block and attaches\n * a real shadow root before any JavaScript executes. All CSS layers are present\n * at first paint — eliminating both FOUC and layout shift.\n *\n * Non-custom-element VNodes are rendered identically to renderToString() but\n * with DSD recursion active for any custom elements nested inside them.\n */\n\nimport type { VNode } from './types';\nimport { renderToString } from './vdom-ssr';\nimport { VOID_ELEMENTS, buildAttrs, buildRawAttrs, type RenderOptions } from './ssr-utils';\nimport { registry } from './component/registry';\nimport { runComponentSSRRender } from './ssr-context';\nimport { jitCSS } from './style';\nimport { baseReset, minifyCSS } from './css-utils';\nimport { escapeHTML } from './helpers';\nimport { devWarn } from './logger';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport type DSDRenderOptions = RenderOptions & {\n /**\n * Emit Declarative Shadow DOM output for registered custom elements.\n * Shadow content is serialised inside `<template shadowrootmode=\"open\">`,\n * with a complete CSS layer stack (`baseReset` + `useStyle` + JIT CSS)\n * injected as a `<style>` block so styles are available at first paint.\n * @default false\n */\n dsd?: boolean;\n /**\n * Append the DSD polyfill `<script>` for browsers without native support\n * (Firefox < 123). Only meaningful when `dsd` is true.\n * @default true\n */\n dsdPolyfill?: boolean;\n /**\n * Router instance to thread through each component's SSR context.\n *\n * When provided, `router-view` reads the current route from this instance\n * instead of the module-level `activeRouterProxy` singleton, making\n * concurrent SSR renders safe — each request carries its own router with\n * its own URL state.\n *\n * In browser mode this option is ignored; components always use\n * `activeRouterProxy` there.\n */\n router?: unknown;\n};\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\n/**\n * @internal\n * Minified DSD polyfill for browsers without native Declarative Shadow DOM.\n * Processes all `<template shadowrootmode>` elements synchronously.\n */\nexport const DSD_POLYFILL_SCRIPT =\n '<script>(function(){' +\n \"if(HTMLTemplateElement.prototype.hasOwnProperty('shadowRootMode'))return;\" +\n \"document.querySelectorAll('template[shadowrootmode]').forEach(function(t){\" +\n \"var m=t.getAttribute('shadowrootmode');\" +\n 'var s=t.parentElement.attachShadow({mode:m});' +\n 's.appendChild(t.content);t.remove();' +\n '});})()' +\n '</script>';\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction isRegisteredCustomElement(tag: string): boolean {\n return tag.includes('-') && registry.has(tag);\n}\n\n/**\n * Build the combined `<style>` block for a shadow root.\n *\n * Layer order (matches the runtime adoptedStyleSheets order):\n * 1. baseReset — global reset + CSS custom properties\n * 2. useStyle() output — component-defined rules (:host, ::slotted, etc.)\n * 3. JIT CSS — utility classes extracted from the shadow HTML\n */\nexport function buildShadowStyleBlock(\n useStyleCSS: string,\n shadowHTML: string,\n): string {\n const parts: string[] = [baseReset];\n\n if (useStyleCSS.trim()) {\n parts.push(useStyleCSS);\n }\n\n const jit = jitCSS(shadowHTML);\n if (jit.trim()) {\n parts.push(jit);\n }\n\n const combined = minifyCSS(parts.join('\\n'));\n return combined ? `<style>${combined}</style>` : '';\n}\n\n// ---------------------------------------------------------------------------\n// Streaming async component collector\n// ---------------------------------------------------------------------------\n\nexport interface AsyncStreamEntry {\n id: string;\n tag: string;\n attrsString: string;\n hydrateAttr: string;\n useStyleCSS: string;\n lightDOM: string;\n opts: DSDRenderOptions;\n promise: Promise<VNode | VNode[]>;\n /** Router threaded from the originating render pass — propagated to async re-renders. */\n router?: unknown;\n}\n\nlet _streamingCollector: AsyncStreamEntry[] | null = null;\nlet _streamingCounter = 0;\n\n/** @internal Called by renderToStream() before the sync render pass. */\nexport function beginStreamingCollection(collector: AsyncStreamEntry[]): void {\n _streamingCollector = collector;\n _streamingCounter = 0;\n}\n\n/** @internal Called by renderToStream() after the sync render pass. */\nexport function endStreamingCollection(): void {\n _streamingCollector = null;\n}\n\n// ---------------------------------------------------------------------------\n// Core renderer\n// ---------------------------------------------------------------------------\n\n/**\n * Render a VNode tree to an HTML string with Declarative Shadow DOM output\n * for all registered custom elements encountered in the tree.\n */\nexport function renderToDSD(vnode: VNode, opts: DSDRenderOptions): string {\n if (!opts.dsd) {\n return renderToString(vnode, opts);\n }\n\n // Primitive string nodes\n if (typeof vnode === 'string') {\n return escapeHTML(vnode) as string;\n }\n\n const tag = (vnode as VNode).tag;\n\n // Special virtual node types — delegate entirely to the base renderer\n if (tag === '#text' || tag === '#anchor' || tag === '#raw') {\n return renderToString(vnode, opts);\n }\n\n // Custom element — emit DSD wrapper\n if (isRegisteredCustomElement(tag)) {\n return renderCustomElementDSD(vnode, opts);\n }\n\n // Regular element — recurse with DSD mode on\n const attrsObj: Record<string, unknown> = vnode.props?.attrs\n ? { ...vnode.props.attrs }\n : {};\n\n const attrsString = buildAttrs(attrsObj, tag, opts);\n\n if (VOID_ELEMENTS.has(tag)) {\n return `<${tag}${attrsString}>`;\n }\n\n const children = renderChildrenDSD(vnode.children, opts);\n return `<${tag}${attrsString}>${children}</${tag}>`;\n}\n\nfunction renderCustomElementDSD(vnode: VNode, opts: DSDRenderOptions): string {\n const tag = vnode.tag;\n const config = registry.get(tag);\n\n // Build the plain attribute string (no namespace injection for custom elements)\n const rawAttrs = vnode.props?.attrs ?? {};\n const attrsString = buildRawAttrs(rawAttrs);\n\n // Move the null check BEFORE reading config.* properties for clarity.\n if (!config) {\n // Component not in registry on server (e.g. dynamic import not yet run).\n // Emit a shell with an empty DSD template so the client hydrates normally.\n const lightDOM = renderChildrenDSD(vnode.children, opts);\n return `<${tag}${attrsString}><template shadowrootmode=\"open\"></template>${lightDOM}</${tag}>`;\n }\n\n // Emit data-cer-hydrate when a non-default strategy is configured.\n // 'load' is the default and doesn't need to be serialised.\n const hydrateStrategy = config.hydrate;\n const hydrateAttr =\n hydrateStrategy && hydrateStrategy !== 'load'\n ? ` data-cer-hydrate=\"${hydrateStrategy}\"`\n : '';\n\n // Run the component's render function in a minimal SSR context to get the\n // shadow DOM VNode tree and capture any useStyle() output.\n const { shadowVNode, useStyleCSS, asyncPromise } = runComponentSSRRender(config, rawAttrs, tag, opts.router);\n\n // When streaming and this component has an async render, emit a placeholder\n // and register the promise for later resolution.\n if (asyncPromise && _streamingCollector === null) {\n devWarn(\n `[SSR] Component \"${tag}\" has an async render function. ` +\n `In standard SSR the shadow DOM will be empty. ` +\n `Use renderToStream() for incremental async component streaming.`,\n );\n }\n if (asyncPromise && _streamingCollector !== null) {\n const id = `cer-stream-${_streamingCounter++}`;\n const lightDOM = renderChildrenDSD(vnode.children, opts);\n _streamingCollector.push({\n id,\n tag,\n attrsString,\n hydrateAttr,\n useStyleCSS,\n lightDOM,\n opts,\n promise: asyncPromise,\n router: opts.router,\n });\n return (\n `<${tag} id=\"${id}\"${attrsString}${hydrateAttr}>` +\n `<template shadowrootmode=\"open\"></template>` +\n `${lightDOM}` +\n `</${tag}>`\n );\n }\n\n // Render the shadow DOM VNode tree to HTML (DSD-recursive for nested elements)\n let shadowHTML = '';\n if (shadowVNode !== null && shadowVNode !== undefined) {\n if (Array.isArray(shadowVNode)) {\n shadowHTML = (shadowVNode as VNode[])\n .map((n) => renderToDSD(n, opts))\n .join('');\n } else {\n shadowHTML = renderToDSD(shadowVNode as VNode, opts);\n }\n }\n\n const styleBlock = buildShadowStyleBlock(useStyleCSS, shadowHTML);\n\n // Light DOM children become slotted content — rendered outside the template\n const lightDOM = renderChildrenDSD(vnode.children, opts);\n\n return (\n `<${tag}${attrsString}${hydrateAttr}>` +\n `<template shadowrootmode=\"open\">${styleBlock}${shadowHTML}</template>` +\n `${lightDOM}` +\n `</${tag}>`\n );\n}\n\nfunction renderChildrenDSD(\n children: VNode['children'],\n opts: DSDRenderOptions,\n): string {\n if (!children) return '';\n if (typeof children === 'string') return escapeHTML(children) as string;\n if (Array.isArray(children)) {\n return children\n .filter((c) => c !== null && c !== undefined)\n .map((c) => renderToDSD(c as VNode, opts))\n .join('');\n }\n return renderToDSD(children as VNode, opts);\n}\n\n// ---------------------------------------------------------------------------\n// Public entry points\n// ---------------------------------------------------------------------------\n\n/**\n * Render a VNode tree to a DSD HTML string and optionally append the\n * DSD polyfill script for older browsers.\n */\nexport function renderToStringDSD(\n vnode: VNode,\n opts?: DSDRenderOptions,\n): string {\n const effectiveOpts: DSDRenderOptions = { dsd: true, ...opts };\n const html = renderToDSD(vnode, effectiveOpts);\n\n if (effectiveOpts.dsdPolyfill !== false) {\n // Inject polyfill before </body> if present, otherwise append\n if (html.includes('</body>')) {\n return html.replace('</body>', `${DSD_POLYFILL_SCRIPT}</body>`);\n }\n return html + DSD_POLYFILL_SCRIPT;\n }\n\n return html;\n}\n","/**\n * SSR entry point — import from `@jasonshimmy/custom-elements-runtime/ssr`.\n *\n * Provides four rendering modes:\n *\n * 1. **renderToString** — baseline HTML serialisation (no shadow DOM content).\n * Backwards-compatible with the original API.\n *\n * 2. **renderToStringWithJITCSS** — HTML + pre-generated JIT CSS injected into\n * `<head>` to prevent FOUC. Supports `dsd: true` for DSD output.\n *\n * 3. **renderToStringWithJITCSSDSD** — convenience alias for DSD mode.\n * Full Declarative Shadow DOM output with per-shadow-root CSS layer stack\n * (baseReset + useStyle() + JIT CSS). Enables true hydration, zero FOUC.\n *\n * 4. **renderToStream** — ReadableStream variant for streaming SSR.\n *\n * 5. **renderToStreamWithJITCSSDSD** — convenience alias for streaming DSD mode.\n * Equivalent to `renderToStream(vnode, { dsd: true, ...options })`.\n * Recommended for new server-rendered applications that want true incremental\n * streaming with Declarative Shadow DOM and zero FOUC.\n *\n * Entity map utilities are also exported for full HTML5 named-entity support.\n *\n * @example DSD usage (recommended)\n * ```ts\n * import { renderToStringWithJITCSSDSD } from '@jasonshimmy/custom-elements-runtime/ssr';\n *\n * const { htmlWithStyles } = renderToStringWithJITCSSDSD(appVNode, {\n * jit: { extendedColors: true },\n * });\n * res.send(`<!DOCTYPE html><html><head>${head}</head><body>${htmlWithStyles}</body></html>`);\n * ```\n */\n\n// ---------------------------------------------------------------------------\n// Re-exports — backwards-compatible\n// ---------------------------------------------------------------------------\n\nexport { renderToString } from './runtime/vdom-ssr';\nexport type { VNode } from './runtime/types';\nexport type { RenderOptions } from './runtime/vdom-ssr';\n\nexport {\n registerEntityMap,\n loadEntityMap,\n clearRegisteredEntityMap,\n} from './runtime/helpers';\n\nexport {\n renderToStringDSD,\n DSD_POLYFILL_SCRIPT,\n} from './runtime/vdom-ssr-dsd';\nexport type { DSDRenderOptions } from './runtime/vdom-ssr-dsd';\n\n// ---------------------------------------------------------------------------\n// Internal imports\n// ---------------------------------------------------------------------------\n\nimport { renderToString as _render } from './runtime/vdom-ssr';\nimport {\n renderToStringDSD as _renderToStringDSD,\n renderToDSD,\n buildShadowStyleBlock,\n beginStreamingCollection,\n endStreamingCollection,\n DSD_POLYFILL_SCRIPT,\n type AsyncStreamEntry,\n} from './runtime/vdom-ssr-dsd';\nimport { jitCSS, enableJITCSS, type JITCSSOptions } from './runtime/style';\nimport type { VNode } from './runtime/types';\nimport type { RenderOptions } from './runtime/vdom-ssr';\nimport type { DSDRenderOptions } from './runtime/vdom-ssr-dsd';\nimport {\n beginSSRGlobalStyleCollection,\n endSSRGlobalStyleCollection,\n} from './runtime/ssr-context';\n\n// ---------------------------------------------------------------------------\n// Result type\n// ---------------------------------------------------------------------------\n\n/**\n * Result of `renderToStringWithJITCSS()` and `renderToStringWithJITCSSDSD()`.\n */\nexport interface SSRJITResult {\n /** The rendered HTML string (styles not yet injected). */\n html: string;\n /**\n * Global JIT CSS extracted from the rendered HTML.\n * For DSD renders, each shadow root embeds its own scoped styles; this field\n * holds any residual light-DOM utility CSS.\n */\n css: string;\n /**\n * CSS captured from `useGlobalStyle()` calls during this render pass\n * (e.g. `@font-face`, `:root` custom properties).\n * Inject in a `<style id=\"cer-ssr-global\">` in `<head>`.\n */\n globalStyles: string;\n /**\n * Convenience: `html` with both `<style>` tags injected before `</head>`.\n * If no `</head>` is found, the styles are prepended.\n */\n htmlWithStyles: string;\n}\n\n// ---------------------------------------------------------------------------\n// renderToStringWithJITCSS — primary API, supports both modes\n// ---------------------------------------------------------------------------\n\n/**\n * Server-side render a VNode tree and simultaneously pre-generate JIT CSS.\n *\n * Pass `dsd: true` to enable Declarative Shadow DOM output with full per-shadow-\n * root CSS layer extraction (recommended for new apps).\n *\n * @example Standard (no DSD)\n * ```ts\n * const { htmlWithStyles } = renderToStringWithJITCSS(appVNode);\n * ```\n *\n * @example With DSD\n * ```ts\n * const { htmlWithStyles } = renderToStringWithJITCSS(appVNode, {\n * dsd: true,\n * jit: { extendedColors: true },\n * });\n * ```\n */\nexport function renderToStringWithJITCSS(\n vnode: VNode,\n options?: RenderOptions & DSDRenderOptions & { jit?: JITCSSOptions },\n): SSRJITResult {\n const { jit, dsd, dsdPolyfill, ...renderOptions } = options ?? {};\n\n if (jit) enableJITCSS(jit);\n\n beginSSRGlobalStyleCollection();\n\n let html!: string;\n let globalStylesCaptured!: string[];\n try {\n if (dsd) {\n // renderToStringDSD handles DSD wrapping but skips the polyfill so we can\n // place it correctly relative to other injected style tags below.\n html = _renderToStringDSD(vnode, {\n ...renderOptions,\n dsd: true,\n dsdPolyfill: false,\n });\n } else {\n html = _render(vnode, renderOptions);\n }\n } finally {\n // Always end collection — even when the render throws — so the collector\n // is never left non-null, which would cause subsequent non-SSR\n // useGlobalStyle() calls to silently skip DOM injection.\n globalStylesCaptured = endSSRGlobalStyleCollection();\n }\n\n const css = jitCSS(html);\n const globalStyles = globalStylesCaptured.join('\\n');\n\n const styleTags: string[] = [];\n if (css) styleTags.push(`<style id=\"cer-ssr-jit\">${css}</style>`);\n if (globalStyles.trim())\n styleTags.push(`<style id=\"cer-ssr-global\">${globalStyles}</style>`);\n\n let htmlWithStyles = html;\n if (styleTags.length) {\n const injection = styleTags.join('');\n htmlWithStyles = html.includes('</head>')\n ? html.replace('</head>', `${injection}</head>`)\n : `${injection}${html}`;\n }\n\n // Append DSD polyfill script inside </body> when in DSD mode\n if (dsd && dsdPolyfill !== false) {\n htmlWithStyles = htmlWithStyles.includes('</body>')\n ? htmlWithStyles.replace('</body>', `${DSD_POLYFILL_SCRIPT}</body>`)\n : htmlWithStyles + DSD_POLYFILL_SCRIPT;\n }\n\n return { html, css, globalStyles, htmlWithStyles };\n}\n\n// ---------------------------------------------------------------------------\n// renderToStringWithJITCSSDSD — convenience alias\n// ---------------------------------------------------------------------------\n\n/**\n * Convenience alias: `renderToStringWithJITCSS(vnode, { dsd: true, ...options })`.\n *\n * Renders with Declarative Shadow DOM output, full per-shadow-root CSS layer\n * extraction, and the DSD browser polyfill. This is the recommended function\n * for all new server-rendered applications.\n *\n * @example\n * ```ts\n * import { renderToStringWithJITCSSDSD } from '@jasonshimmy/custom-elements-runtime/ssr';\n *\n * const { htmlWithStyles } = renderToStringWithJITCSSDSD(appVNode, {\n * jit: { extendedColors: true },\n * });\n * ```\n */\nexport function renderToStringWithJITCSSDSD(\n vnode: VNode,\n options?: Omit<\n RenderOptions & DSDRenderOptions & { jit?: JITCSSOptions },\n 'dsd'\n >,\n): SSRJITResult {\n return renderToStringWithJITCSS(vnode, { ...options, dsd: true });\n}\n\n// ---------------------------------------------------------------------------\n// renderToStream — streaming SSR\n// ---------------------------------------------------------------------------\n\n/**\n * Render a VNode tree to a `ReadableStream<string>`.\n *\n * Supports true incremental streaming: synchronous components are flushed as\n * the first chunk, then each async component's resolved output is streamed as\n * an inline swap `<script>` that fills the placeholder's shadow root.\n *\n * @example Node.js\n * ```ts\n * import { renderToStream } from '@jasonshimmy/custom-elements-runtime/ssr';\n *\n * app.get('/', (req, res) => {\n * const stream = renderToStream(appVNode, { dsd: true });\n * const reader = stream.getReader();\n * const pump = () =>\n * reader.read().then(({ value, done }) => {\n * if (done) { res.end(); return; }\n * res.write(value);\n * pump();\n * });\n * pump();\n * });\n * ```\n */\nexport function renderToStream(\n vnode: VNode,\n options?: RenderOptions & DSDRenderOptions & { jit?: JITCSSOptions; asyncTimeout?: number },\n): ReadableStream<string> {\n const timeoutMs = options?.asyncTimeout ?? 30_000;\n\n return new ReadableStream<string>({\n async start(controller) {\n const asyncEntries: AsyncStreamEntry[] = [];\n beginStreamingCollection(asyncEntries);\n\n try {\n const { htmlWithStyles } = renderToStringWithJITCSS(vnode, options);\n controller.enqueue(htmlWithStyles);\n } catch (err) {\n controller.error(err);\n return;\n } finally {\n endStreamingCollection();\n }\n\n // Resolve async components and stream swap scripts as they settle.\n // Each resolved component replaces its placeholder via an inline script.\n // A per-entry timeout prevents hung async components from blocking the stream.\n for (const entry of asyncEntries) {\n try {\n const timeout = new Promise<never>((_, reject) =>\n setTimeout(() => reject(new Error(`[cer] async component timed out after ${timeoutMs}ms`)), timeoutMs),\n );\n const resolvedVNodes = await Promise.race([entry.promise, timeout]);\n const shadowHTML = Array.isArray(resolvedVNodes)\n ? (resolvedVNodes as VNode[]).map((n) => renderToDSD(n, entry.opts)).join('')\n : renderToDSD(resolvedVNodes as VNode, entry.opts);\n const styleBlock = buildShadowStyleBlock(entry.useStyleCSS, shadowHTML);\n const shadowContent = `${styleBlock}${shadowHTML}`;\n controller.enqueue(\n `<script>(function(){` +\n `var e=document.getElementById(${JSON.stringify(entry.id)});` +\n `if(!e)return;` +\n // The placeholder already has an empty shadow root attached (native DSD or polyfill).\n // If for some reason it doesn't, attach one now.\n `var s=e.shadowRoot;` +\n `if(!s&&e.attachShadow)try{s=e.attachShadow({mode:'open'});}catch(_){};` +\n `if(s)s.innerHTML=${JSON.stringify(shadowContent)};` +\n `e.removeAttribute('id');` +\n `})();</script>`,\n );\n } catch {\n // Async render failed — leave placeholder for client hydration.\n }\n }\n\n controller.close();\n },\n });\n}\n\n// ---------------------------------------------------------------------------\n// renderToStreamWithJITCSSDSD — convenience alias\n// ---------------------------------------------------------------------------\n\n/**\n * Convenience alias: `renderToStream(vnode, { dsd: true, ...options })`.\n *\n * Renders with Declarative Shadow DOM output and full JIT CSS extraction,\n * streaming the synchronous render as the first chunk and each resolved async\n * component as a subsequent inline-script swap. This is the recommended\n * function for all new server-rendered applications.\n *\n * @example\n * ```ts\n * import { renderToStreamWithJITCSSDSD } from '@jasonshimmy/custom-elements-runtime/ssr';\n *\n * app.get('/', (req, res) => {\n * const stream = renderToStreamWithJITCSSDSD(appVNode, { router });\n * const reader = stream.getReader();\n * const pump = () =>\n * reader.read().then(({ value, done }) => {\n * if (done) { res.end(); return; }\n * res.write(value);\n * pump();\n * });\n * pump();\n * });\n * ```\n */\nexport function renderToStreamWithJITCSSDSD(\n vnode: VNode,\n options?: Omit<\n RenderOptions & DSDRenderOptions & { jit?: JITCSSOptions; asyncTimeout?: number },\n 'dsd'\n >,\n): ReadableStream<string> {\n return renderToStream(vnode, { ...options, dsd: true });\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ssr-CUT0FqUz.cjs","names":[],"sources":["../src/lib/runtime/ssr-utils.ts","../src/lib/runtime/vdom-ssr.ts","../src/lib/runtime/vdom-ssr-dsd.ts","../src/lib/ssr.ts"],"sourcesContent":["/**\n * Shared utilities for SSR renderers.\n * Imported by vdom-ssr.ts and vdom-ssr-dsd.ts to avoid duplication.\n */\nimport { escapeHTML } from './helpers';\nimport { TAG_NAMESPACE_MAP, SVG_NS } from './namespace-helpers';\n\nexport type RenderOptions = {\n /** Backwards-compatible: whether to inject the SVG namespace on <svg> nodes (default true) */\n injectSvgNamespace?: boolean;\n /** Inject known well-known namespaces for tags like <math> when missing (default follows injectSvgNamespace) */\n injectKnownNamespaces?: boolean;\n};\n\nexport const VOID_ELEMENTS = new Set([\n 'area',\n 'base',\n 'br',\n 'col',\n 'embed',\n 'hr',\n 'img',\n 'input',\n 'link',\n 'meta',\n 'param',\n 'source',\n 'track',\n 'wbr',\n]);\n\nexport function buildAttrs(\n attrs: Record<string, unknown>,\n tag: string,\n opts: RenderOptions,\n): string {\n const inject = opts.injectSvgNamespace ?? true;\n const injectKnown = opts.injectKnownNamespaces ?? inject;\n const merged = { ...attrs };\n\n if (inject && tag === 'svg' && !('xmlns' in merged)) {\n merged['xmlns'] = SVG_NS;\n } else if (injectKnown && tag in TAG_NAMESPACE_MAP && !('xmlns' in merged)) {\n merged['xmlns'] = TAG_NAMESPACE_MAP[tag];\n }\n\n return Object.entries(merged)\n .map(([k, v]) => ` ${k}=\"${escapeHTML(String(v))}\"`)\n .join('');\n}\n\nexport function buildRawAttrs(attrs: Record<string, unknown>): string {\n return Object.entries(attrs)\n .map(([k, v]) => ` ${k}=\"${escapeHTML(String(v))}\"`)\n .join('');\n}\n","import type { VNode } from './types';\nimport { escapeHTML } from './helpers';\nimport { VOID_ELEMENTS, buildAttrs, type RenderOptions } from './ssr-utils';\n\n/**\n * Render a VNode to a string (SSR).\n * Kept intentionally minimal: only serializes attributes under `props.attrs`\n * to avoid leaking runtime-only values (functions, reactive state, directives).\n * @param vnode The virtual node to render.\n * @returns The rendered HTML string.\n */\nexport type { RenderOptions } from './ssr-utils';\n\nexport function renderToString(vnode: VNode, opts?: RenderOptions): string {\n if (typeof vnode === 'string') return escapeHTML(vnode) as string;\n\n if (vnode.tag === '#text') {\n return typeof vnode.children === 'string'\n ? (escapeHTML(vnode.children) as string)\n : '';\n }\n\n if (vnode.tag === '#anchor') {\n // Preserve meaningful falsy children (0, false, '') while filtering out\n // only null and undefined. Anchor blocks are normalized by the compiler\n // to exclude null/undefined; SSR should follow the same rule to avoid\n // hydration mismatches where falsy values are significant.\n const children = Array.isArray(vnode.children)\n ? vnode.children.filter((c) => c !== null && c !== undefined)\n : [];\n return children.map((c) => renderToString(c, opts)).join('');\n }\n\n if (vnode.tag === '#raw') {\n return typeof vnode.children === 'string' ? vnode.children : '';\n }\n\n // Collect attributes from props.attrs. For SSR we mirror vnode.attrs\n // but ensure SVG nodes behave like client-side: if this is an <svg>\n // and no xmlns was provided, inject the standard SVG namespace so\n // server markup matches client-created DOM namespace.\n const attrsObj: Record<string, unknown> = vnode.props?.attrs\n ? { ...vnode.props.attrs }\n : {};\n\n const attrsString = buildAttrs(attrsObj, vnode.tag, opts ?? {});\n\n // Handle void elements (self-closing tags)\n if (VOID_ELEMENTS.has(vnode.tag)) {\n return `<${vnode.tag}${attrsString}>`;\n }\n\n const children = Array.isArray(vnode.children)\n ? vnode.children\n .filter((c) => c !== null && c !== undefined)\n .map((c) => renderToString(c, opts))\n .join('')\n : typeof vnode.children === 'string'\n ? escapeHTML(vnode.children)\n : vnode.children\n ? renderToString(vnode.children, opts)\n : '';\n\n return `<${vnode.tag}${attrsString}>${children}</${vnode.tag}>`;\n}\n","/**\n * Declarative Shadow DOM (DSD) SSR renderer.\n *\n * When `dsd: true` is passed to the render options, registered custom elements\n * are serialised as:\n *\n * ```html\n * <my-element attr=\"val\">\n * <template shadowrootmode=\"open\">\n * <style>\n * /* baseReset + useStyle() output + JIT utility CSS *\\/\n * </style>\n * <!-- shadow DOM from component render function -->\n * </template>\n * <!-- light DOM / slotted children from vnode.children -->\n * </my-element>\n * ```\n *\n * The browser parses the `<template shadowrootmode=\"open\">` block and attaches\n * a real shadow root before any JavaScript executes. All CSS layers are present\n * at first paint — eliminating both FOUC and layout shift.\n *\n * Non-custom-element VNodes are rendered identically to renderToString() but\n * with DSD recursion active for any custom elements nested inside them.\n */\n\nimport type { VNode } from './types';\nimport { renderToString } from './vdom-ssr';\nimport { VOID_ELEMENTS, buildAttrs, buildRawAttrs, type RenderOptions } from './ssr-utils';\nimport { registry } from './component/registry';\nimport { runComponentSSRRender } from './ssr-context';\nimport { jitCSS } from './style';\nimport { baseReset, minifyCSS } from './css-utils';\nimport { escapeHTML } from './helpers';\nimport { devWarn } from './logger';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport type DSDRenderOptions = RenderOptions & {\n /**\n * Emit Declarative Shadow DOM output for registered custom elements.\n * Shadow content is serialised inside `<template shadowrootmode=\"open\">`,\n * with a complete CSS layer stack (`baseReset` + `useStyle` + JIT CSS)\n * injected as a `<style>` block so styles are available at first paint.\n * @default false\n */\n dsd?: boolean;\n /**\n * Append the DSD polyfill `<script>` for browsers without native support\n * (Firefox < 123). Only meaningful when `dsd` is true.\n * @default true\n */\n dsdPolyfill?: boolean;\n /**\n * Router instance to thread through each component's SSR context.\n *\n * When provided, `router-view` reads the current route from this instance\n * instead of the module-level `activeRouterProxy` singleton, making\n * concurrent SSR renders safe — each request carries its own router with\n * its own URL state.\n *\n * In browser mode this option is ignored; components always use\n * `activeRouterProxy` there.\n */\n router?: unknown;\n};\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\n/**\n * @internal\n * Minified DSD polyfill for browsers without native Declarative Shadow DOM.\n * Processes all `<template shadowrootmode>` elements synchronously.\n */\nexport const DSD_POLYFILL_SCRIPT =\n '<script>(function(){' +\n \"if(HTMLTemplateElement.prototype.hasOwnProperty('shadowRootMode'))return;\" +\n \"document.querySelectorAll('template[shadowrootmode]').forEach(function(t){\" +\n \"var m=t.getAttribute('shadowrootmode');\" +\n 'var s=t.parentElement.attachShadow({mode:m});' +\n 's.appendChild(t.content);t.remove();' +\n '});})()' +\n '</script>';\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction isRegisteredCustomElement(tag: string): boolean {\n return tag.includes('-') && registry.has(tag);\n}\n\n/**\n * Build the combined `<style>` block for a shadow root.\n *\n * Layer order (matches the runtime adoptedStyleSheets order):\n * 1. baseReset — global reset + CSS custom properties\n * 2. useStyle() output — component-defined rules (:host, ::slotted, etc.)\n * 3. JIT CSS — utility classes extracted from the shadow HTML\n */\nexport function buildShadowStyleBlock(\n useStyleCSS: string,\n shadowHTML: string,\n): string {\n const parts: string[] = [baseReset];\n\n if (useStyleCSS.trim()) {\n parts.push(useStyleCSS);\n }\n\n const jit = jitCSS(shadowHTML);\n if (jit.trim()) {\n parts.push(jit);\n }\n\n const combined = minifyCSS(parts.join('\\n'));\n return combined ? `<style>${combined}</style>` : '';\n}\n\n// ---------------------------------------------------------------------------\n// Streaming async component collector\n// ---------------------------------------------------------------------------\n\nexport interface AsyncStreamEntry {\n id: string;\n tag: string;\n attrsString: string;\n hydrateAttr: string;\n useStyleCSS: string;\n lightDOM: string;\n opts: DSDRenderOptions;\n promise: Promise<VNode | VNode[]>;\n /** Router threaded from the originating render pass — propagated to async re-renders. */\n router?: unknown;\n}\n\nlet _streamingCollector: AsyncStreamEntry[] | null = null;\nlet _streamingCounter = 0;\n\n/** @internal Called by renderToStream() before the sync render pass. */\nexport function beginStreamingCollection(collector: AsyncStreamEntry[]): void {\n _streamingCollector = collector;\n _streamingCounter = 0;\n}\n\n/** @internal Called by renderToStream() after the sync render pass. */\nexport function endStreamingCollection(): void {\n _streamingCollector = null;\n}\n\n// ---------------------------------------------------------------------------\n// Core renderer\n// ---------------------------------------------------------------------------\n\n/**\n * Render a VNode tree to an HTML string with Declarative Shadow DOM output\n * for all registered custom elements encountered in the tree.\n */\nexport function renderToDSD(vnode: VNode, opts: DSDRenderOptions): string {\n if (!opts.dsd) {\n return renderToString(vnode, opts);\n }\n\n // Primitive string nodes\n if (typeof vnode === 'string') {\n return escapeHTML(vnode) as string;\n }\n\n const tag = (vnode as VNode).tag;\n\n // Special virtual node types — delegate entirely to the base renderer\n if (tag === '#text' || tag === '#anchor' || tag === '#raw') {\n return renderToString(vnode, opts);\n }\n\n // Custom element — emit DSD wrapper\n if (isRegisteredCustomElement(tag)) {\n return renderCustomElementDSD(vnode, opts);\n }\n\n // Regular element — recurse with DSD mode on\n const attrsObj: Record<string, unknown> = vnode.props?.attrs\n ? { ...vnode.props.attrs }\n : {};\n\n const attrsString = buildAttrs(attrsObj, tag, opts);\n\n if (VOID_ELEMENTS.has(tag)) {\n return `<${tag}${attrsString}>`;\n }\n\n const children = renderChildrenDSD(vnode.children, opts);\n return `<${tag}${attrsString}>${children}</${tag}>`;\n}\n\nfunction renderCustomElementDSD(vnode: VNode, opts: DSDRenderOptions): string {\n const tag = vnode.tag;\n const config = registry.get(tag);\n\n // Build the plain attribute string (no namespace injection for custom elements)\n const rawAttrs = vnode.props?.attrs ?? {};\n const attrsString = buildRawAttrs(rawAttrs);\n\n // Move the null check BEFORE reading config.* properties for clarity.\n if (!config) {\n // Component not in registry on server (e.g. dynamic import not yet run).\n // Emit a shell with an empty DSD template so the client hydrates normally.\n const lightDOM = renderChildrenDSD(vnode.children, opts);\n return `<${tag}${attrsString}><template shadowrootmode=\"open\"></template>${lightDOM}</${tag}>`;\n }\n\n // Emit data-cer-hydrate when a non-default strategy is configured.\n // 'load' is the default and doesn't need to be serialised.\n const hydrateStrategy = config.hydrate;\n const hydrateAttr =\n hydrateStrategy && hydrateStrategy !== 'load'\n ? ` data-cer-hydrate=\"${hydrateStrategy}\"`\n : '';\n\n // Run the component's render function in a minimal SSR context to get the\n // shadow DOM VNode tree and capture any useStyle() output.\n const { shadowVNode, useStyleCSS, asyncPromise } = runComponentSSRRender(config, rawAttrs, tag, opts.router);\n\n // When streaming and this component has an async render, emit a placeholder\n // and register the promise for later resolution.\n if (asyncPromise && _streamingCollector === null) {\n devWarn(\n `[SSR] Component \"${tag}\" has an async render function. ` +\n `In standard SSR the shadow DOM will be empty. ` +\n `Use renderToStream() for incremental async component streaming.`,\n );\n }\n if (asyncPromise && _streamingCollector !== null) {\n const id = `cer-stream-${_streamingCounter++}`;\n const lightDOM = renderChildrenDSD(vnode.children, opts);\n _streamingCollector.push({\n id,\n tag,\n attrsString,\n hydrateAttr,\n useStyleCSS,\n lightDOM,\n opts,\n promise: asyncPromise,\n router: opts.router,\n });\n return (\n `<${tag} id=\"${id}\"${attrsString}${hydrateAttr}>` +\n `<template shadowrootmode=\"open\"></template>` +\n `${lightDOM}` +\n `</${tag}>`\n );\n }\n\n // Render the shadow DOM VNode tree to HTML (DSD-recursive for nested elements)\n let shadowHTML = '';\n if (shadowVNode !== null && shadowVNode !== undefined) {\n if (Array.isArray(shadowVNode)) {\n shadowHTML = (shadowVNode as VNode[])\n .map((n) => renderToDSD(n, opts))\n .join('');\n } else {\n shadowHTML = renderToDSD(shadowVNode as VNode, opts);\n }\n }\n\n const styleBlock = buildShadowStyleBlock(useStyleCSS, shadowHTML);\n\n // Light DOM children become slotted content — rendered outside the template\n const lightDOM = renderChildrenDSD(vnode.children, opts);\n\n return (\n `<${tag}${attrsString}${hydrateAttr}>` +\n `<template shadowrootmode=\"open\">${styleBlock}${shadowHTML}</template>` +\n `${lightDOM}` +\n `</${tag}>`\n );\n}\n\nfunction renderChildrenDSD(\n children: VNode['children'],\n opts: DSDRenderOptions,\n): string {\n if (!children) return '';\n if (typeof children === 'string') return escapeHTML(children) as string;\n if (Array.isArray(children)) {\n return children\n .filter((c) => c !== null && c !== undefined)\n .map((c) => renderToDSD(c as VNode, opts))\n .join('');\n }\n return renderToDSD(children as VNode, opts);\n}\n\n// ---------------------------------------------------------------------------\n// Public entry points\n// ---------------------------------------------------------------------------\n\n/**\n * Render a VNode tree to a DSD HTML string and optionally append the\n * DSD polyfill script for older browsers.\n */\nexport function renderToStringDSD(\n vnode: VNode,\n opts?: DSDRenderOptions,\n): string {\n const effectiveOpts: DSDRenderOptions = { dsd: true, ...opts };\n const html = renderToDSD(vnode, effectiveOpts);\n\n if (effectiveOpts.dsdPolyfill !== false) {\n // Inject polyfill before </body> if present, otherwise append\n if (html.includes('</body>')) {\n return html.replace('</body>', `${DSD_POLYFILL_SCRIPT}</body>`);\n }\n return html + DSD_POLYFILL_SCRIPT;\n }\n\n return html;\n}\n","/**\n * SSR entry point — import from `@jasonshimmy/custom-elements-runtime/ssr`.\n *\n * Provides four rendering modes:\n *\n * 1. **renderToString** — baseline HTML serialisation (no shadow DOM content).\n * Backwards-compatible with the original API.\n *\n * 2. **renderToStringWithJITCSS** — HTML + pre-generated JIT CSS injected into\n * `<head>` to prevent FOUC. Supports `dsd: true` for DSD output.\n *\n * 3. **renderToStringWithJITCSSDSD** — convenience alias for DSD mode.\n * Full Declarative Shadow DOM output with per-shadow-root CSS layer stack\n * (baseReset + useStyle() + JIT CSS). Enables true hydration, zero FOUC.\n *\n * 4. **renderToStream** — ReadableStream variant for streaming SSR.\n *\n * 5. **renderToStreamWithJITCSSDSD** — convenience alias for streaming DSD mode.\n * Equivalent to `renderToStream(vnode, { dsd: true, ...options })`.\n * Recommended for new server-rendered applications that want true incremental\n * streaming with Declarative Shadow DOM and zero FOUC.\n *\n * Entity map utilities are also exported for full HTML5 named-entity support.\n *\n * @example DSD usage (recommended)\n * ```ts\n * import { renderToStringWithJITCSSDSD } from '@jasonshimmy/custom-elements-runtime/ssr';\n *\n * const { htmlWithStyles } = renderToStringWithJITCSSDSD(appVNode, {\n * jit: { extendedColors: true },\n * });\n * res.send(`<!DOCTYPE html><html><head>${head}</head><body>${htmlWithStyles}</body></html>`);\n * ```\n */\n\n// ---------------------------------------------------------------------------\n// Re-exports — backwards-compatible\n// ---------------------------------------------------------------------------\n\nexport { renderToString } from './runtime/vdom-ssr';\nexport type { VNode } from './runtime/types';\nexport type { RenderOptions } from './runtime/vdom-ssr';\n\nexport {\n registerEntityMap,\n loadEntityMap,\n clearRegisteredEntityMap,\n} from './runtime/helpers';\n\nexport {\n renderToStringDSD,\n DSD_POLYFILL_SCRIPT,\n} from './runtime/vdom-ssr-dsd';\nexport type { DSDRenderOptions } from './runtime/vdom-ssr-dsd';\n\n// ---------------------------------------------------------------------------\n// Internal imports\n// ---------------------------------------------------------------------------\n\nimport { renderToString as _render } from './runtime/vdom-ssr';\nimport {\n renderToStringDSD as _renderToStringDSD,\n renderToDSD,\n buildShadowStyleBlock,\n beginStreamingCollection,\n endStreamingCollection,\n DSD_POLYFILL_SCRIPT,\n type AsyncStreamEntry,\n} from './runtime/vdom-ssr-dsd';\nimport { jitCSS, enableJITCSS, type JITCSSOptions } from './runtime/style';\nimport type { VNode } from './runtime/types';\nimport type { RenderOptions } from './runtime/vdom-ssr';\nimport type { DSDRenderOptions } from './runtime/vdom-ssr-dsd';\nimport {\n beginSSRGlobalStyleCollection,\n endSSRGlobalStyleCollection,\n} from './runtime/ssr-context';\n\n// ---------------------------------------------------------------------------\n// Result type\n// ---------------------------------------------------------------------------\n\n/**\n * Result of `renderToStringWithJITCSS()` and `renderToStringWithJITCSSDSD()`.\n */\nexport interface SSRJITResult {\n /** The rendered HTML string (styles not yet injected). */\n html: string;\n /**\n * Global JIT CSS extracted from the rendered HTML.\n * For DSD renders, each shadow root embeds its own scoped styles; this field\n * holds any residual light-DOM utility CSS.\n */\n css: string;\n /**\n * CSS captured from `useGlobalStyle()` calls during this render pass\n * (e.g. `@font-face`, `:root` custom properties).\n * Inject in a `<style id=\"cer-ssr-global\">` in `<head>`.\n */\n globalStyles: string;\n /**\n * Convenience: `html` with both `<style>` tags injected before `</head>`.\n * If no `</head>` is found, the styles are prepended.\n */\n htmlWithStyles: string;\n}\n\n// ---------------------------------------------------------------------------\n// renderToStringWithJITCSS — primary API, supports both modes\n// ---------------------------------------------------------------------------\n\n/**\n * Server-side render a VNode tree and simultaneously pre-generate JIT CSS.\n *\n * Pass `dsd: true` to enable Declarative Shadow DOM output with full per-shadow-\n * root CSS layer extraction (recommended for new apps).\n *\n * @example Standard (no DSD)\n * ```ts\n * const { htmlWithStyles } = renderToStringWithJITCSS(appVNode);\n * ```\n *\n * @example With DSD\n * ```ts\n * const { htmlWithStyles } = renderToStringWithJITCSS(appVNode, {\n * dsd: true,\n * jit: { extendedColors: true },\n * });\n * ```\n */\nexport function renderToStringWithJITCSS(\n vnode: VNode,\n options?: RenderOptions & DSDRenderOptions & { jit?: JITCSSOptions },\n): SSRJITResult {\n const { jit, dsd, dsdPolyfill, ...renderOptions } = options ?? {};\n\n if (jit) enableJITCSS(jit);\n\n beginSSRGlobalStyleCollection();\n\n let html!: string;\n let globalStylesCaptured!: string[];\n try {\n if (dsd) {\n // renderToStringDSD handles DSD wrapping but skips the polyfill so we can\n // place it correctly relative to other injected style tags below.\n html = _renderToStringDSD(vnode, {\n ...renderOptions,\n dsd: true,\n dsdPolyfill: false,\n });\n } else {\n html = _render(vnode, renderOptions);\n }\n } finally {\n // Always end collection — even when the render throws — so the collector\n // is never left non-null, which would cause subsequent non-SSR\n // useGlobalStyle() calls to silently skip DOM injection.\n globalStylesCaptured = endSSRGlobalStyleCollection();\n }\n\n const css = jitCSS(html);\n const globalStyles = globalStylesCaptured.join('\\n');\n\n const styleTags: string[] = [];\n if (css) styleTags.push(`<style id=\"cer-ssr-jit\">${css}</style>`);\n if (globalStyles.trim())\n styleTags.push(`<style id=\"cer-ssr-global\">${globalStyles}</style>`);\n\n let htmlWithStyles = html;\n if (styleTags.length) {\n const injection = styleTags.join('');\n htmlWithStyles = html.includes('</head>')\n ? html.replace('</head>', `${injection}</head>`)\n : `${injection}${html}`;\n }\n\n // Append DSD polyfill script inside </body> when in DSD mode\n if (dsd && dsdPolyfill !== false) {\n htmlWithStyles = htmlWithStyles.includes('</body>')\n ? htmlWithStyles.replace('</body>', `${DSD_POLYFILL_SCRIPT}</body>`)\n : htmlWithStyles + DSD_POLYFILL_SCRIPT;\n }\n\n return { html, css, globalStyles, htmlWithStyles };\n}\n\n// ---------------------------------------------------------------------------\n// renderToStringWithJITCSSDSD — convenience alias\n// ---------------------------------------------------------------------------\n\n/**\n * Convenience alias: `renderToStringWithJITCSS(vnode, { dsd: true, ...options })`.\n *\n * Renders with Declarative Shadow DOM output, full per-shadow-root CSS layer\n * extraction, and the DSD browser polyfill. This is the recommended function\n * for all new server-rendered applications.\n *\n * @example\n * ```ts\n * import { renderToStringWithJITCSSDSD } from '@jasonshimmy/custom-elements-runtime/ssr';\n *\n * const { htmlWithStyles } = renderToStringWithJITCSSDSD(appVNode, {\n * jit: { extendedColors: true },\n * });\n * ```\n */\nexport function renderToStringWithJITCSSDSD(\n vnode: VNode,\n options?: Omit<\n RenderOptions & DSDRenderOptions & { jit?: JITCSSOptions },\n 'dsd'\n >,\n): SSRJITResult {\n return renderToStringWithJITCSS(vnode, { ...options, dsd: true });\n}\n\n// ---------------------------------------------------------------------------\n// renderToStream — streaming SSR\n// ---------------------------------------------------------------------------\n\n/**\n * Render a VNode tree to a `ReadableStream<string>`.\n *\n * Supports true incremental streaming: synchronous components are flushed as\n * the first chunk, then each async component's resolved output is streamed as\n * an inline swap `<script>` that fills the placeholder's shadow root.\n *\n * @example Node.js\n * ```ts\n * import { renderToStream } from '@jasonshimmy/custom-elements-runtime/ssr';\n *\n * app.get('/', (req, res) => {\n * const stream = renderToStream(appVNode, { dsd: true });\n * const reader = stream.getReader();\n * const pump = () =>\n * reader.read().then(({ value, done }) => {\n * if (done) { res.end(); return; }\n * res.write(value);\n * pump();\n * });\n * pump();\n * });\n * ```\n */\nexport function renderToStream(\n vnode: VNode,\n options?: RenderOptions & DSDRenderOptions & { jit?: JITCSSOptions; asyncTimeout?: number },\n): ReadableStream<string> {\n const timeoutMs = options?.asyncTimeout ?? 30_000;\n\n return new ReadableStream<string>({\n async start(controller) {\n const asyncEntries: AsyncStreamEntry[] = [];\n beginStreamingCollection(asyncEntries);\n\n try {\n const { htmlWithStyles } = renderToStringWithJITCSS(vnode, options);\n controller.enqueue(htmlWithStyles);\n } catch (err) {\n controller.error(err);\n return;\n } finally {\n endStreamingCollection();\n }\n\n // Resolve async components and stream swap scripts as they settle.\n // Each resolved component replaces its placeholder via an inline script.\n // A per-entry timeout prevents hung async components from blocking the stream.\n for (const entry of asyncEntries) {\n try {\n const timeout = new Promise<never>((_, reject) =>\n setTimeout(() => reject(new Error(`[cer] async component timed out after ${timeoutMs}ms`)), timeoutMs),\n );\n const resolvedVNodes = await Promise.race([entry.promise, timeout]);\n const shadowHTML = Array.isArray(resolvedVNodes)\n ? (resolvedVNodes as VNode[]).map((n) => renderToDSD(n, entry.opts)).join('')\n : renderToDSD(resolvedVNodes as VNode, entry.opts);\n const styleBlock = buildShadowStyleBlock(entry.useStyleCSS, shadowHTML);\n const shadowContent = `${styleBlock}${shadowHTML}`;\n controller.enqueue(\n `<script>(function(){` +\n `var e=document.getElementById(${JSON.stringify(entry.id)});` +\n `if(!e)return;` +\n // The placeholder already has an empty shadow root attached (native DSD or polyfill).\n // If for some reason it doesn't, attach one now.\n `var s=e.shadowRoot;` +\n `if(!s&&e.attachShadow)try{s=e.attachShadow({mode:'open'});}catch(_){};` +\n `if(s)s.innerHTML=${JSON.stringify(shadowContent)};` +\n `e.removeAttribute('id');` +\n `})();</script>`,\n );\n } catch {\n // Async render failed — leave placeholder for client hydration.\n }\n }\n\n controller.close();\n },\n });\n}\n\n// ---------------------------------------------------------------------------\n// renderToStreamWithJITCSSDSD — convenience alias\n// ---------------------------------------------------------------------------\n\n/**\n * Convenience alias: `renderToStream(vnode, { dsd: true, ...options })`.\n *\n * Renders with Declarative Shadow DOM output and full JIT CSS extraction,\n * streaming the synchronous render as the first chunk and each resolved async\n * component as a subsequent inline-script swap. This is the recommended\n * function for all new server-rendered applications.\n *\n * @example\n * ```ts\n * import { renderToStreamWithJITCSSDSD } from '@jasonshimmy/custom-elements-runtime/ssr';\n *\n * app.get('/', (req, res) => {\n * const stream = renderToStreamWithJITCSSDSD(appVNode, { router });\n * const reader = stream.getReader();\n * const pump = () =>\n * reader.read().then(({ value, done }) => {\n * if (done) { res.end(); return; }\n * res.write(value);\n * pump();\n * });\n * pump();\n * });\n * ```\n */\nexport function renderToStreamWithJITCSSDSD(\n vnode: VNode,\n options?: Omit<\n RenderOptions & DSDRenderOptions & { jit?: JITCSSOptions; asyncTimeout?: number },\n 'dsd'\n >,\n): ReadableStream<string> {\n return renderToStream(vnode, { ...options, dsd: true });\n}\n"],"mappings":"qOAcA,IAAa,EAAgB,IAAI,IAAI,CACnC,OACA,OACA,KACA,MACA,QACA,KACA,MACA,QACA,OACA,OACA,QACA,SACA,QACA,MACD,CAAC,CAEF,SAAgB,EACd,EACA,EACA,EACQ,CACR,IAAM,EAAS,EAAK,oBAAsB,GACpC,EAAc,EAAK,uBAAyB,EAC5C,EAAS,CAAE,GAAG,EAAO,CAQ3B,OANI,GAAU,IAAQ,OAAS,EAAE,UAAW,GAC1C,EAAO,MAAW,EAAA,EACT,GAAe,KAAO,EAAA,GAAqB,EAAE,UAAW,KACjE,EAAO,MAAW,EAAA,EAAkB,IAG/B,OAAO,QAAQ,EAAO,CAC1B,KAAK,CAAC,EAAG,KAAO,IAAI,EAAE,IAAI,EAAA,EAAW,OAAO,EAAE,CAAC,CAAC,GAAG,CACnD,KAAK,GAAG,CAGb,SAAgB,EAAc,EAAwC,CACpE,OAAO,OAAO,QAAQ,EAAM,CACzB,KAAK,CAAC,EAAG,KAAO,IAAI,EAAE,IAAI,EAAA,EAAW,OAAO,EAAE,CAAC,CAAC,GAAG,CACnD,KAAK,GAAG,CCzCb,SAAgB,EAAe,EAAc,EAA8B,CACzE,GAAI,OAAO,GAAU,SAAU,OAAO,EAAA,EAAW,EAAM,CAEvD,GAAI,EAAM,MAAQ,QAChB,OAAO,OAAO,EAAM,UAAa,SAC5B,EAAA,EAAW,EAAM,SAAS,CAC3B,GAGN,GAAI,EAAM,MAAQ,UAQhB,OAHiB,MAAM,QAAQ,EAAM,SAAS,CAC1C,EAAM,SAAS,OAAQ,GAAM,GAAM,KAAwB,CAC3D,EAAE,EACU,IAAK,GAAM,EAAe,EAAG,EAAK,CAAC,CAAC,KAAK,GAAG,CAG9D,GAAI,EAAM,MAAQ,OAChB,OAAO,OAAO,EAAM,UAAa,SAAW,EAAM,SAAW,GAW/D,IAAM,EAAc,EAJsB,EAAM,OAAO,MACnD,CAAE,GAAG,EAAM,MAAM,MAAO,CACxB,EAAE,CAEmC,EAAM,IAAK,GAAQ,EAAE,CAAC,CAG/D,GAAI,EAAc,IAAI,EAAM,IAAI,CAC9B,MAAO,IAAI,EAAM,MAAM,EAAY,GAGrC,IAAM,EAAW,MAAM,QAAQ,EAAM,SAAS,CAC1C,EAAM,SACH,OAAQ,GAAM,GAAM,KAAwB,CAC5C,IAAK,GAAM,EAAe,EAAG,EAAK,CAAC,CACnC,KAAK,GAAG,CACX,OAAO,EAAM,UAAa,SACxB,EAAA,EAAW,EAAM,SAAS,CAC1B,EAAM,SACJ,EAAe,EAAM,SAAU,EAAK,CACpC,GAER,MAAO,IAAI,EAAM,MAAM,EAAY,GAAG,EAAS,IAAI,EAAM,IAAI,GCe/D,IAAa,EACX,mTAaF,SAAS,EAA0B,EAAsB,CACvD,OAAO,EAAI,SAAS,IAAI,EAAI,EAAA,EAAS,IAAI,EAAI,CAW/C,SAAgB,EACd,EACA,EACQ,CACR,IAAM,EAAkB,CAAC,EAAA,EAAU,CAE/B,EAAY,MAAM,EACpB,EAAM,KAAK,EAAY,CAGzB,IAAM,EAAM,EAAA,EAAO,EAAW,CAC1B,EAAI,MAAM,EACZ,EAAM,KAAK,EAAI,CAGjB,IAAM,EAAW,EAAA,EAAU,EAAM,KAAK;EAAK,CAAC,CAC5C,OAAO,EAAW,UAAU,EAAS,UAAY,GAoBnD,IAAI,EAAiD,KACjD,EAAoB,EAGxB,SAAgB,EAAyB,EAAqC,CAC5E,EAAsB,EACtB,EAAoB,EAItB,SAAgB,GAA+B,CAC7C,EAAsB,KAWxB,SAAgB,EAAY,EAAc,EAAgC,CACxE,GAAI,CAAC,EAAK,IACR,OAAO,EAAe,EAAO,EAAK,CAIpC,GAAI,OAAO,GAAU,SACnB,OAAO,EAAA,EAAW,EAAM,CAG1B,IAAM,EAAO,EAAgB,IAG7B,GAAI,IAAQ,SAAW,IAAQ,WAAa,IAAQ,OAClD,OAAO,EAAe,EAAO,EAAK,CAIpC,GAAI,EAA0B,EAAI,CAChC,OAAO,EAAuB,EAAO,EAAK,CAQ5C,IAAM,EAAc,EAJsB,EAAM,OAAO,MACnD,CAAE,GAAG,EAAM,MAAM,MAAO,CACxB,EAAE,CAEmC,EAAK,EAAK,CAOnD,OALI,EAAc,IAAI,EAAI,CACjB,IAAI,IAAM,EAAY,GAIxB,IAAI,IAAM,EAAY,GADZ,EAAkB,EAAM,SAAU,EAAK,CACf,IAAI,EAAI,GAGnD,SAAS,EAAuB,EAAc,EAAgC,CAC5E,IAAM,EAAM,EAAM,IACZ,EAAS,EAAA,EAAS,IAAI,EAAI,CAG1B,EAAW,EAAM,OAAO,OAAS,EAAE,CACnC,EAAc,EAAc,EAAS,CAG3C,GAAI,CAAC,EAIH,MAAO,IAAI,IAAM,EAAY,8CADZ,EAAkB,EAAM,SAAU,EAAK,CAC4B,IAAI,EAAI,GAK9F,IAAM,EAAkB,EAAO,QACzB,EACJ,GAAmB,IAAoB,OACnC,sBAAsB,EAAgB,GACtC,GAIA,CAAE,cAAa,cAAa,gBAAiB,EAAA,EAAsB,EAAQ,EAAU,EAAK,EAAK,OAAO,CAW5G,GAPI,GAAgB,IAAwB,MAC1C,EAAA,EACE,oBAAoB,EAAI,+IAGzB,CAEC,GAAgB,IAAwB,KAAM,CAChD,IAAM,EAAK,cAAc,MACnB,EAAW,EAAkB,EAAM,SAAU,EAAK,CAYxD,OAXA,EAAoB,KAAK,CACvB,KACA,MACA,cACA,cACA,cACA,WACA,OACA,QAAS,EACT,OAAQ,EAAK,OACd,CAAC,CAEA,IAAI,EAAI,OAAO,EAAG,GAAG,IAAc,EAAY,8CAE5C,EAAA,IACE,EAAI,GAKb,IAAI,EAAa,GACb,GAAgB,OAClB,AAKE,EALE,MAAM,QAAQ,EAAY,CACd,EACX,IAAK,GAAM,EAAY,EAAG,EAAK,CAAC,CAChC,KAAK,GAAG,CAEE,EAAY,EAAsB,EAAK,EAIxD,IAAM,EAAa,EAAsB,EAAa,EAAW,CAG3D,EAAW,EAAkB,EAAM,SAAU,EAAK,CAExD,MACE,IAAI,IAAM,IAAc,EAAY,mCACD,IAAa,EAAW,aACxD,EAAA,IACE,EAAI,GAIb,SAAS,EACP,EACA,EACQ,CASR,OARK,EACD,OAAO,GAAa,SAAiB,EAAA,EAAW,EAAS,CACzD,MAAM,QAAQ,EAAS,CAClB,EACJ,OAAQ,GAAM,GAAM,KAAwB,CAC5C,IAAK,GAAM,EAAY,EAAY,EAAK,CAAC,CACzC,KAAK,GAAG,CAEN,EAAY,EAAmB,EAAK,CARrB,GAmBxB,SAAgB,EACd,EACA,EACQ,CACR,IAAM,EAAkC,CAAE,IAAK,GAAM,GAAG,EAAM,CACxD,EAAO,EAAY,EAAO,EAAc,CAU9C,OARI,EAAc,cAAgB,GAQ3B,EAND,EAAK,SAAS,UAAU,CACnB,EAAK,QAAQ,UAAW,GAAG,EAAoB,SAAS,CAE1D,EAAO,EC5LlB,SAAgB,EACd,EACA,EACc,CACd,GAAM,CAAE,MAAK,MAAK,cAAa,GAAG,GAAkB,GAAW,EAAE,CAE7D,GAAK,EAAA,EAAa,EAAI,CAE1B,EAAA,GAA+B,CAE/B,IAAI,EACA,EACJ,GAAI,CACF,AASE,EATE,EAGK,EAAmB,EAAO,CAC/B,GAAG,EACH,IAAK,GACL,YAAa,GACd,CAAC,CAEK,EAAQ,EAAO,EAAc,QAE9B,CAIR,EAAuB,EAAA,GAA6B,CAGtD,IAAM,EAAM,EAAA,EAAO,EAAK,CAClB,EAAe,EAAqB,KAAK;EAAK,CAE9C,EAAsB,EAAE,CAC1B,GAAK,EAAU,KAAK,2BAA2B,EAAI,UAAU,CAC7D,EAAa,MAAM,EACrB,EAAU,KAAK,8BAA8B,EAAa,UAAU,CAEtE,IAAI,EAAiB,EACrB,GAAI,EAAU,OAAQ,CACpB,IAAM,EAAY,EAAU,KAAK,GAAG,CACpC,EAAiB,EAAK,SAAS,UAAU,CACrC,EAAK,QAAQ,UAAW,GAAG,EAAU,SAAS,CAC9C,GAAG,IAAY,IAUrB,OANI,GAAO,IAAgB,KACzB,EAAiB,EAAe,SAAS,UAAU,CAC/C,EAAe,QAAQ,UAAW,GAAG,EAAoB,SAAS,CAClE,EAAiB,GAGhB,CAAE,OAAM,MAAK,eAAc,iBAAgB,CAuBpD,SAAgB,EACd,EACA,EAIc,CACd,OAAO,EAAyB,EAAO,CAAE,GAAG,EAAS,IAAK,GAAM,CAAC,CA+BnE,SAAgB,EACd,EACA,EACwB,CACxB,IAAM,EAAY,GAAS,cAAgB,IAE3C,OAAO,IAAI,eAAuB,CAChC,MAAM,MAAM,EAAY,CACtB,IAAM,EAAmC,EAAE,CAC3C,EAAyB,EAAa,CAEtC,GAAI,CACF,GAAM,CAAE,kBAAmB,EAAyB,EAAO,EAAQ,CACnE,EAAW,QAAQ,EAAe,OAC3B,EAAK,CACZ,EAAW,MAAM,EAAI,CACrB,cACQ,CACR,GAAwB,CAM1B,IAAK,IAAM,KAAS,EAClB,GAAI,CACF,IAAM,EAAU,IAAI,SAAgB,EAAG,IACrC,eAAiB,EAAW,MAAM,yCAAyC,EAAU,IAAI,CAAC,CAAE,EAAU,CACvG,CACK,EAAiB,MAAM,QAAQ,KAAK,CAAC,EAAM,QAAS,EAAQ,CAAC,CAC7D,EAAa,MAAM,QAAQ,EAAe,CAC3C,EAA2B,IAAK,GAAM,EAAY,EAAG,EAAM,KAAK,CAAC,CAAC,KAAK,GAAG,CAC3E,EAAY,EAAyB,EAAM,KAAK,CAE9C,EAAgB,GADH,EAAsB,EAAM,YAAa,EAAW,GACjC,IACtC,EAAW,QACT,qDACmC,KAAK,UAAU,EAAM,GAAG,CAAC,2HAMtC,KAAK,UAAU,EAAc,CAAC,0CAGrD,MACK,EAKV,EAAW,OAAO,EAErB,CAAC,CAgCJ,SAAgB,EACd,EACA,EAIwB,CACxB,OAAO,EAAe,EAAO,CAAE,GAAG,EAAS,IAAK,GAAM,CAAC"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const e=require(`./helpers-
|
|
2
|
-
//# sourceMappingURL=tag-utils-
|
|
1
|
+
const e=require(`./helpers-hGU9czPG.cjs`);function t(t){let n=e.p(t);return n.includes(`-`)?n:`cer-${n}`}Object.defineProperty(exports,`t`,{enumerable:!0,get:function(){return t}});
|
|
2
|
+
//# sourceMappingURL=tag-utils-CMy95A4Z.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tag-utils-
|
|
1
|
+
{"version":3,"file":"tag-utils-CMy95A4Z.cjs","names":[],"sources":["../src/lib/runtime/tag-utils.ts"],"sourcesContent":["import { toKebab } from './helpers';\n\n/**\n * Resolves a component() tag argument to the actual registered tag name.\n * Single source of truth used by both factory.ts (runtime) and\n * vite-plugin.ts (build time) so the two can never drift apart.\n *\n * Rules:\n * camelCase → kebab-case (myButton → my-button)\n * no hyphen → cer- prefix (app → cer-app)\n * has hyphen → unchanged (ks-badge → ks-badge)\n */\nexport function resolveTagName(name: string): string {\n const kebab = toKebab(name);\n return kebab.includes('-') ? kebab : `cer-${kebab}`;\n}\n"],"mappings":"0CAYA,SAAgB,EAAe,EAAsB,CACnD,IAAM,EAAQ,EAAA,EAAQ,EAAK,CAC3B,OAAO,EAAM,SAAS,IAAI,CAAG,EAAQ,OAAO"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { p as e } from "./helpers-
|
|
1
|
+
import { p as e } from "./helpers-BiGdX-3A.js";
|
|
2
2
|
//#region src/lib/runtime/tag-utils.ts
|
|
3
3
|
function t(t) {
|
|
4
4
|
let n = e(t);
|
|
@@ -7,4 +7,4 @@ function t(t) {
|
|
|
7
7
|
//#endregion
|
|
8
8
|
export { t };
|
|
9
9
|
|
|
10
|
-
//# sourceMappingURL=tag-utils-
|
|
10
|
+
//# sourceMappingURL=tag-utils-DVutXfzj.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tag-utils-
|
|
1
|
+
{"version":3,"file":"tag-utils-DVutXfzj.js","names":[],"sources":["../src/lib/runtime/tag-utils.ts"],"sourcesContent":["import { toKebab } from './helpers';\n\n/**\n * Resolves a component() tag argument to the actual registered tag name.\n * Single source of truth used by both factory.ts (runtime) and\n * vite-plugin.ts (build time) so the two can never drift apart.\n *\n * Rules:\n * camelCase → kebab-case (myButton → my-button)\n * no hyphen → cer- prefix (app → cer-app)\n * has hyphen → unchanged (ks-badge → ks-badge)\n */\nexport function resolveTagName(name: string): string {\n const kebab = toKebab(name);\n return kebab.includes('-') ? kebab : `cer-${kebab}`;\n}\n"],"mappings":";;AAYA,SAAgB,EAAe,GAAsB;CACnD,IAAM,IAAQ,EAAQ,EAAK;AAC3B,QAAO,EAAM,SAAS,IAAI,GAAG,IAAQ,OAAO"}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { r as e, t } from "./logger-DIJ0UH3R.js";
|
|
2
2
|
import { a as n, i as r, n as i, o as a, r as o } from "./namespace-helpers-CIUkG8Mn.js";
|
|
3
|
-
import { C as s, O as c, S as l, T as u, _ as d, a as f, d as p, f as m, i as h, l as g, n as _, o as v, p as y, u as b, v as x, w as S } from "./helpers-
|
|
3
|
+
import { C as s, O as c, S as l, T as u, _ as d, a as f, d as p, f as m, i as h, l as g, n as _, o as v, p as y, u as b, v as x, w as S } from "./helpers-BiGdX-3A.js";
|
|
4
4
|
import { a as C, d as w, f as T, i as E, n as ee, r as D, u as O } from "./css-utils-Bn-dO44e.js";
|
|
5
5
|
import { resetWhenCounter as te } from "./custom-elements-runtime.directives.es.js";
|
|
6
6
|
import { getTransitionStyleSheet as ne } from "./custom-elements-runtime.transitions.es.js";
|
|
7
|
-
import { t as re } from "./tag-utils-
|
|
8
|
-
import { c as ie, t as k } from "./hooks-
|
|
7
|
+
import { t as re } from "./tag-utils-DVutXfzj.js";
|
|
8
|
+
import { c as ie, t as k } from "./hooks-yP009oF9.js";
|
|
9
9
|
//#region src/lib/runtime/watchers.ts
|
|
10
10
|
function ae(e, n, r) {
|
|
11
11
|
if (r) for (let [i, a] of Object.entries(r)) {
|
|
@@ -2002,15 +2002,26 @@ function Ve(e, t, n, r) {
|
|
|
2002
2002
|
}
|
|
2003
2003
|
//#endregion
|
|
2004
2004
|
//#region src/lib/runtime/render.ts
|
|
2005
|
-
var Y = [], He = /* @__PURE__ */ new WeakMap(), X = /* @__PURE__ */ new WeakMap();
|
|
2006
|
-
function
|
|
2005
|
+
var Y = [], He = /* @__PURE__ */ new WeakMap(), X = /* @__PURE__ */ new WeakMap(), Ue = /* @__PURE__ */ new Map();
|
|
2006
|
+
function We(e) {
|
|
2007
|
+
if (typeof CSSStyleSheet > "u" || !("replaceSync" in CSSStyleSheet.prototype)) return null;
|
|
2008
|
+
let t = Ue.get(e);
|
|
2009
|
+
if (t) return t;
|
|
2010
|
+
try {
|
|
2011
|
+
let t = new CSSStyleSheet();
|
|
2012
|
+
return t.replaceSync(e), Ue.set(e, t), t;
|
|
2013
|
+
} catch {
|
|
2014
|
+
return null;
|
|
2015
|
+
}
|
|
2016
|
+
}
|
|
2017
|
+
function Ge(e, t) {
|
|
2007
2018
|
X.has(e) || X.set(e, /* @__PURE__ */ new Set()), X.get(e).add(t);
|
|
2008
2019
|
}
|
|
2009
|
-
function
|
|
2020
|
+
function Ke(e, t) {
|
|
2010
2021
|
let n = X.get(e);
|
|
2011
2022
|
n && (n.delete(t), n.size === 0 && X.delete(e));
|
|
2012
2023
|
}
|
|
2013
|
-
function
|
|
2024
|
+
function qe(e, n, r, i, a, o, s, c) {
|
|
2014
2025
|
if (e) {
|
|
2015
2026
|
Y.push(r);
|
|
2016
2027
|
try {
|
|
@@ -2019,7 +2030,7 @@ function Ge(e, n, r, i, a, o, s, c) {
|
|
|
2019
2030
|
o(!0);
|
|
2020
2031
|
let n = e.host.isConnected, u = e, d = u._asyncRenderToken = (u._asyncRenderToken ?? 0) + 1;
|
|
2021
2032
|
l.then((t) => {
|
|
2022
|
-
n && !e.host.isConnected || u._asyncRenderToken === d && (o(!1), s(null),
|
|
2033
|
+
n && !e.host.isConnected || u._asyncRenderToken === d && (o(!1), s(null), Je(e, t, r, i, a), c(e.innerHTML));
|
|
2023
2034
|
}).catch((r) => {
|
|
2024
2035
|
if (n && !e.host.isConnected || u._asyncRenderToken !== d) return;
|
|
2025
2036
|
o(!1);
|
|
@@ -2028,7 +2039,7 @@ function Ge(e, n, r, i, a, o, s, c) {
|
|
|
2028
2039
|
});
|
|
2029
2040
|
return;
|
|
2030
2041
|
}
|
|
2031
|
-
|
|
2042
|
+
Je(e, l, r, i, a), c(e.innerHTML);
|
|
2032
2043
|
} catch (n) {
|
|
2033
2044
|
let r = n instanceof Error ? n : Error(String(n));
|
|
2034
2045
|
t(`[${e.host.tagName.toLowerCase()}] Render error:`, r), s(r);
|
|
@@ -2037,10 +2048,10 @@ function Ge(e, n, r, i, a, o, s, c) {
|
|
|
2037
2048
|
}
|
|
2038
2049
|
}
|
|
2039
2050
|
}
|
|
2040
|
-
function
|
|
2051
|
+
function Je(e, t, n, r, i) {
|
|
2041
2052
|
e && (Ve(e, Array.isArray(t) ? t : [t], n, r), i(e.innerHTML));
|
|
2042
2053
|
}
|
|
2043
|
-
function
|
|
2054
|
+
function Ye(n, r, i, a, o, s, c) {
|
|
2044
2055
|
s !== null && clearTimeout(s);
|
|
2045
2056
|
let l = Date.now() - r < 16, { isVitest: d, isCypress: f, isTest: p } = u(), m = (d || p) && !f;
|
|
2046
2057
|
if (l) {
|
|
@@ -2068,7 +2079,7 @@ function qe(n, r, i, a, o, s, c) {
|
|
|
2068
2079
|
};
|
|
2069
2080
|
h > 0 ? c(setTimeout(g, h)) : p ? g() : (c({}), queueMicrotask(g));
|
|
2070
2081
|
}
|
|
2071
|
-
function
|
|
2082
|
+
function Xe(e, t) {
|
|
2072
2083
|
let n = t;
|
|
2073
2084
|
try {
|
|
2074
2085
|
let t = X.get(e);
|
|
@@ -2086,22 +2097,22 @@ function Je(e, t) {
|
|
|
2086
2097
|
} catch {}
|
|
2087
2098
|
return n;
|
|
2088
2099
|
}
|
|
2089
|
-
function
|
|
2100
|
+
function Ze(e) {
|
|
2090
2101
|
return "adoptedStyleSheets" in e && typeof CSSStyleSheet < "u" && "replaceSync" in CSSStyleSheet.prototype;
|
|
2091
2102
|
}
|
|
2092
|
-
function
|
|
2103
|
+
function Qe(e, t) {
|
|
2093
2104
|
let n = e.querySelector("style[data-cer-runtime]");
|
|
2094
2105
|
n || (n = document.createElement("style"), r(n, "data-cer-runtime", "true"), e.appendChild(n));
|
|
2095
2106
|
try {
|
|
2096
2107
|
n.textContent = t;
|
|
2097
2108
|
} catch {}
|
|
2098
2109
|
}
|
|
2099
|
-
function
|
|
2110
|
+
function $e(e, t, n, r, i) {
|
|
2100
2111
|
if (!e) return;
|
|
2101
|
-
let a =
|
|
2112
|
+
let a = Xe(e, n);
|
|
2102
2113
|
if (He.get(e) === a) return;
|
|
2103
2114
|
He.set(e, a);
|
|
2104
|
-
let o = D(e) ? E(a) : "", s = ee(), c = t._computedStyle, l =
|
|
2115
|
+
let o = D(e) ? E(a) : "", s = ee(), c = t._computedStyle, l = Ze(e), u = ne(), d = "";
|
|
2105
2116
|
if (!l) try {
|
|
2106
2117
|
u?.cssRules && (d = Array.from(u.cssRules).map((e) => e.cssText).join("\n"));
|
|
2107
2118
|
} catch {
|
|
@@ -2110,7 +2121,7 @@ function Ze(e, t, n, r, i) {
|
|
|
2110
2121
|
if (!o?.trim() && !c && !s) {
|
|
2111
2122
|
if (i(null), l) e.adoptedStyleSheets = [O(), u];
|
|
2112
2123
|
else {
|
|
2113
|
-
|
|
2124
|
+
Qe(e, w(`${w(C)}\n${d}`));
|
|
2114
2125
|
try {
|
|
2115
2126
|
e.adoptedStyleSheets = [O(), u];
|
|
2116
2127
|
} catch {}
|
|
@@ -2119,16 +2130,16 @@ function Ze(e, t, n, r, i) {
|
|
|
2119
2130
|
}
|
|
2120
2131
|
let f = "";
|
|
2121
2132
|
if (c && (f += c + "\n"), o && (f += o + "\n"), f = T(f), f = w(f), l) {
|
|
2122
|
-
let t =
|
|
2123
|
-
t ||= new CSSStyleSheet();
|
|
2133
|
+
let t = !o?.trim() && !!c, n;
|
|
2134
|
+
t ? (n = We(f), n ||= new CSSStyleSheet()) : (n = r, n ||= new CSSStyleSheet());
|
|
2124
2135
|
try {
|
|
2125
|
-
t.replaceSync(f);
|
|
2126
|
-
let
|
|
2127
|
-
s &&
|
|
2136
|
+
t || n.replaceSync(f);
|
|
2137
|
+
let r = [O(), u];
|
|
2138
|
+
s && r.push(s), r.push(n), e.adoptedStyleSheets = r, i(t ? null : n);
|
|
2128
2139
|
return;
|
|
2129
2140
|
} catch {}
|
|
2130
2141
|
}
|
|
2131
|
-
|
|
2142
|
+
Qe(e, w(`${w(C)}\n${d}\n${f}`));
|
|
2132
2143
|
try {
|
|
2133
2144
|
let t = [O(), u];
|
|
2134
2145
|
if (s && t.push(s), typeof CSSStyleSheet < "u") try {
|
|
@@ -2146,7 +2157,7 @@ function Ze(e, t, n, r, i) {
|
|
|
2146
2157
|
}
|
|
2147
2158
|
//#endregion
|
|
2148
2159
|
//#region src/lib/runtime/component/element-class.ts
|
|
2149
|
-
function
|
|
2160
|
+
function et(n, r) {
|
|
2150
2161
|
if (!r.render) throw Error("Component must have a render function");
|
|
2151
2162
|
return typeof window > "u" ? class {
|
|
2152
2163
|
constructor() {}
|
|
@@ -2232,7 +2243,7 @@ function Qe(n, r) {
|
|
|
2232
2243
|
connectedCallback() {
|
|
2233
2244
|
this._runLogicWithinErrorBoundary(r, () => {
|
|
2234
2245
|
let e = this.getRootNode();
|
|
2235
|
-
e && e !== document && "host" in e &&
|
|
2246
|
+
e && e !== document && "host" in e && Ge(e, this);
|
|
2236
2247
|
let t = this.getAttribute("data-cer-hydrate");
|
|
2237
2248
|
if (t !== "none") {
|
|
2238
2249
|
if (t === "idle") {
|
|
@@ -2265,7 +2276,7 @@ function Qe(n, r) {
|
|
|
2265
2276
|
disconnectedCallback() {
|
|
2266
2277
|
this._runLogicWithinErrorBoundary(r, () => {
|
|
2267
2278
|
let e = this.getRootNode();
|
|
2268
|
-
e && e !== document && "host" in e &&
|
|
2279
|
+
e && e !== document && "host" in e && Ke(e, this), de(r, this.context, this._listeners, () => {
|
|
2269
2280
|
this._listeners = [];
|
|
2270
2281
|
}, () => {
|
|
2271
2282
|
this._watchers.clear();
|
|
@@ -2288,7 +2299,7 @@ function Qe(n, r) {
|
|
|
2288
2299
|
}
|
|
2289
2300
|
_render(e) {
|
|
2290
2301
|
this._runLogicWithinErrorBoundary(e, () => {
|
|
2291
|
-
|
|
2302
|
+
qe(this.shadowRoot, e, this.context, this._refs, (e) => {
|
|
2292
2303
|
this._lastHtmlStringForJitCSS = e, typeof this.onHtmlStringUpdate == "function" && this?.onHtmlStringUpdate?.(e);
|
|
2293
2304
|
}, (e) => {
|
|
2294
2305
|
this._templateLoading = e, this?.onLoadingStateChange?.(e);
|
|
@@ -2303,7 +2314,7 @@ function Qe(n, r) {
|
|
|
2303
2314
|
_requestRender() {
|
|
2304
2315
|
this._runLogicWithinErrorBoundary(this._cfg, () => {
|
|
2305
2316
|
c(() => {
|
|
2306
|
-
|
|
2317
|
+
Ye(() => this._render(this._cfg), this._lastRenderTime, this._renderCount, (e) => {
|
|
2307
2318
|
this._lastRenderTime = e;
|
|
2308
2319
|
}, (e) => {
|
|
2309
2320
|
this._renderCount = e;
|
|
@@ -2315,7 +2326,7 @@ function Qe(n, r) {
|
|
|
2315
2326
|
}
|
|
2316
2327
|
_applyStyle(e, t) {
|
|
2317
2328
|
this._runLogicWithinErrorBoundary(e, () => {
|
|
2318
|
-
|
|
2329
|
+
$e(this.shadowRoot, this.context, t, this._styleSheet, (e) => {
|
|
2319
2330
|
this._styleSheet = e;
|
|
2320
2331
|
});
|
|
2321
2332
|
});
|
|
@@ -2435,14 +2446,14 @@ function Qe(n, r) {
|
|
|
2435
2446
|
}
|
|
2436
2447
|
//#endregion
|
|
2437
2448
|
//#region src/lib/runtime/component/factory.ts
|
|
2438
|
-
function
|
|
2449
|
+
function tt(e, n, r, i) {
|
|
2439
2450
|
for (let a of r) try {
|
|
2440
2451
|
a(...i);
|
|
2441
2452
|
} catch (r) {
|
|
2442
2453
|
t(`[${e}] Error in ${n} lifecycle hook:`, r);
|
|
2443
2454
|
}
|
|
2444
2455
|
}
|
|
2445
|
-
function
|
|
2456
|
+
function nt(r, i, o) {
|
|
2446
2457
|
n();
|
|
2447
2458
|
let c = re(r), u = {}, d = {
|
|
2448
2459
|
props: {},
|
|
@@ -2531,19 +2542,19 @@ function et(r, i, o) {
|
|
|
2531
2542
|
if (e.onConnected) {
|
|
2532
2543
|
let t = e.onConnected;
|
|
2533
2544
|
u.onConnected = (e) => {
|
|
2534
|
-
|
|
2545
|
+
tt(c, "useOnConnected", t, [e]);
|
|
2535
2546
|
};
|
|
2536
2547
|
}
|
|
2537
2548
|
if (e.onDisconnected) {
|
|
2538
2549
|
let t = e.onDisconnected;
|
|
2539
2550
|
u.onDisconnected = (e) => {
|
|
2540
|
-
|
|
2551
|
+
tt(c, "useOnDisconnected", t, [e]);
|
|
2541
2552
|
};
|
|
2542
2553
|
}
|
|
2543
2554
|
if (e.onAttributeChanged) {
|
|
2544
2555
|
let t = e.onAttributeChanged;
|
|
2545
2556
|
u.onAttributeChanged = (e, n, r, i) => {
|
|
2546
|
-
|
|
2557
|
+
tt(c, "useOnAttributeChanged", t, [
|
|
2547
2558
|
e,
|
|
2548
2559
|
n,
|
|
2549
2560
|
r,
|
|
@@ -2554,7 +2565,7 @@ function et(r, i, o) {
|
|
|
2554
2565
|
if (e.onError) {
|
|
2555
2566
|
let t = e.onError;
|
|
2556
2567
|
u.onError = (e) => {
|
|
2557
|
-
|
|
2568
|
+
tt(c, "useOnError", t, [e]);
|
|
2558
2569
|
};
|
|
2559
2570
|
}
|
|
2560
2571
|
if (e.props && !Object.keys(d.props ?? {}).length) {
|
|
@@ -2606,7 +2617,7 @@ function et(r, i, o) {
|
|
|
2606
2617
|
} catch (t) {
|
|
2607
2618
|
e(`[${c}] Failed to register component. Check your component definition for errors.`, t);
|
|
2608
2619
|
}
|
|
2609
|
-
typeof customElements < "u" && !customElements.get(c) && customElements.define(c,
|
|
2620
|
+
typeof customElements < "u" && !customElements.get(c) && customElements.define(c, et(c, d));
|
|
2610
2621
|
}
|
|
2611
2622
|
}
|
|
2612
2623
|
//#endregion
|
|
@@ -2625,7 +2636,7 @@ function Q(e) {
|
|
|
2625
2636
|
function $(e) {
|
|
2626
2637
|
return typeof e == "object" && !!e && "tag" in e && !Q(e);
|
|
2627
2638
|
}
|
|
2628
|
-
function
|
|
2639
|
+
function rt(e, t) {
|
|
2629
2640
|
return e.key == null ? {
|
|
2630
2641
|
...e,
|
|
2631
2642
|
key: t
|
|
@@ -2633,14 +2644,14 @@ function tt(e, t) {
|
|
|
2633
2644
|
}
|
|
2634
2645
|
//#endregion
|
|
2635
2646
|
//#region src/lib/runtime/template-compiler/props-parser.ts
|
|
2636
|
-
function
|
|
2647
|
+
function it(t, n) {
|
|
2637
2648
|
if (t == null) {
|
|
2638
2649
|
e(`⚠️ Event handler for '@${n}' is ${t}. This will prevent the event from working. Use a function reference instead: @${n}="\${functionName}"`);
|
|
2639
2650
|
return;
|
|
2640
2651
|
}
|
|
2641
2652
|
typeof t != "function" && e(`🚨 Potential infinite loop detected! Event handler for '@${n}' appears to be the result of a function call (${typeof t}) instead of a function reference. Change @${n}="\${functionName()}" to @${n}="\${functionName}" to pass the function reference instead of calling it immediately.`), t === void 0 && typeof t != "function" && e(`💡 Tip: If your event handler function returns undefined, make sure you're passing the function reference, not calling it. Use @${n}="\${fn}" not @${n}="\${fn()}"`);
|
|
2642
2653
|
}
|
|
2643
|
-
function
|
|
2654
|
+
function at(e, t = [], n = {}) {
|
|
2644
2655
|
let r = {}, i = {}, a = {}, o = [], s = /([:@#]?)([a-zA-Z0-9-:.]+)(?:\s*=\s*("([^"\\]*(\\.[^"\\]*)*)"|'([^'\\]*(\\.[^'\\]*)*)'|([^\s>]+)))?/g, c;
|
|
2645
2656
|
for (; c = s.exec(e);) {
|
|
2646
2657
|
let e = c[1], s = c[2], l = "";
|
|
@@ -2685,7 +2696,7 @@ function rt(e, t = [], n = {}) {
|
|
|
2685
2696
|
}
|
|
2686
2697
|
} else if (e === "@") {
|
|
2687
2698
|
let [e, ...t] = s.split("."), i = t;
|
|
2688
|
-
|
|
2699
|
+
it(m, e);
|
|
2689
2700
|
let a = typeof m == "function" ? m : typeof n[m] == "function" ? n[m] : void 0;
|
|
2690
2701
|
if (a) {
|
|
2691
2702
|
let t = (n) => {
|
|
@@ -2704,7 +2715,7 @@ function rt(e, t = [], n = {}) {
|
|
|
2704
2715
|
}
|
|
2705
2716
|
//#endregion
|
|
2706
2717
|
//#region src/lib/runtime/template-compiler/impl.ts
|
|
2707
|
-
function
|
|
2718
|
+
function ot(e) {
|
|
2708
2719
|
if (!$(e) || Q(e)) return e;
|
|
2709
2720
|
let t = e.props?.directives;
|
|
2710
2721
|
if (t && t.when) {
|
|
@@ -2716,14 +2727,14 @@ function it(e) {
|
|
|
2716
2727
|
...e,
|
|
2717
2728
|
props: a
|
|
2718
2729
|
};
|
|
2719
|
-
return Array.isArray(o.children) && (o.children = o.children.map((e) => typeof e == "object" && e ?
|
|
2730
|
+
return Array.isArray(o.children) && (o.children = o.children.map((e) => typeof e == "object" && e ? ot(e) : e)), {
|
|
2720
2731
|
tag: "#anchor",
|
|
2721
2732
|
key: e.key == null ? `when-${e.tag}` : `when-${e.key}`,
|
|
2722
2733
|
children: r ? [o] : []
|
|
2723
2734
|
};
|
|
2724
2735
|
}
|
|
2725
2736
|
if (Array.isArray(e.children)) {
|
|
2726
|
-
let t = e.children.map((e) => typeof e == "object" && e ?
|
|
2737
|
+
let t = e.children.map((e) => typeof e == "object" && e ? ot(e) : e);
|
|
2727
2738
|
return {
|
|
2728
2739
|
...e,
|
|
2729
2740
|
children: t
|
|
@@ -2731,7 +2742,7 @@ function it(e) {
|
|
|
2731
2742
|
}
|
|
2732
2743
|
return e;
|
|
2733
2744
|
}
|
|
2734
|
-
function
|
|
2745
|
+
function st(e, t, n) {
|
|
2735
2746
|
let r = Y.length > 0 ? Y[Y.length - 1] : void 0, i = n ?? r, a = !n && t.length === 0, o = a ? e.join("<!--TEMPLATE_DELIM-->") : null;
|
|
2736
2747
|
if (a && o) {
|
|
2737
2748
|
let e = me.get(o);
|
|
@@ -2786,7 +2797,7 @@ function at(e, t, n) {
|
|
|
2786
2797
|
return;
|
|
2787
2798
|
}
|
|
2788
2799
|
if ($(e)) {
|
|
2789
|
-
n.push(
|
|
2800
|
+
n.push(rt(e, void 0));
|
|
2790
2801
|
return;
|
|
2791
2802
|
}
|
|
2792
2803
|
if (Array.isArray(e)) {
|
|
@@ -2826,7 +2837,7 @@ function at(e, t, n) {
|
|
|
2826
2837
|
]);
|
|
2827
2838
|
for (; S = u.exec(l);) if (!(S[0].startsWith("<!--") && S[0].endsWith("-->"))) {
|
|
2828
2839
|
if (S[1]) {
|
|
2829
|
-
let e = S[1], n = S[0][1] === "/", r = S[0][S[0].length - 2] === "/" || ie.has(e), { props: a, attrs: o, directives: s, bound: c } =
|
|
2840
|
+
let e = S[1], n = S[0][1] === "/", r = S[0][S[0].length - 2] === "/" || ie.has(e), { props: a, attrs: o, directives: s, bound: c } = at(S[2] || "", t, i ?? {}), l = {
|
|
2830
2841
|
props: {},
|
|
2831
2842
|
attrs: {}
|
|
2832
2843
|
};
|
|
@@ -3021,7 +3032,7 @@ function at(e, t, n) {
|
|
|
3021
3032
|
}
|
|
3022
3033
|
}
|
|
3023
3034
|
}
|
|
3024
|
-
let k = D.filter((e) => $(e) && e.tag === "#text" ? typeof e.children == "string" && e.children.trim() !== "" : !0).map((e) =>
|
|
3035
|
+
let k = D.filter((e) => $(e) && e.tag === "#text" ? typeof e.children == "string" && e.children.trim() !== "" : !0).map((e) => ot(e));
|
|
3025
3036
|
if (k.length === 1) {
|
|
3026
3037
|
let e = k[0];
|
|
3027
3038
|
return a && o && me.set(o, e), e;
|
|
@@ -3033,12 +3044,12 @@ function at(e, t, n) {
|
|
|
3033
3044
|
}
|
|
3034
3045
|
//#endregion
|
|
3035
3046
|
//#region src/lib/runtime/template-compiler.ts
|
|
3036
|
-
function
|
|
3047
|
+
function ct(e, ...t) {
|
|
3037
3048
|
if (S()) return [];
|
|
3038
3049
|
let n = t[t.length - 1];
|
|
3039
|
-
return
|
|
3050
|
+
return st(e, t, typeof n == "object" && n && !Array.isArray(n) ? n : void 0);
|
|
3040
3051
|
}
|
|
3041
3052
|
//#endregion
|
|
3042
|
-
export {
|
|
3053
|
+
export { nt as n, Ve as r, ct as t };
|
|
3043
3054
|
|
|
3044
|
-
//# sourceMappingURL=template-compiler-
|
|
3055
|
+
//# sourceMappingURL=template-compiler-BkR0G45f.js.map
|