{"version":3,"sources":["../src/server/escape.ts","../src/server/serverState.ts","../src/server/renderToString.ts"],"names":["ESCAPE_MAP","ESCAPE_REGEX","escapeHtml","str","char","escapeAttribute","isServerRendering","serverStateCollector","hydrationIdCounter","getIsServer","enterServerRender","exitServerRender","states","generateHydrationId","VOID_ELEMENTS","BOOLEAN_ATTRS","ATTR_ALIASES","renderToString","app","options","runWithRequestContext","hydrate","fnode","isFNode","html","renderNodeToString","state","error","renderToStaticMarkup","value","includeHydrationMarkers","child","renderComponentToString","renderElementToString","tag","attrs","renderAttributes","innerHTML","childrenHtml","props","parts","fid","key","attrName","styleStr","v","k","kebabCase","Component","contextId","isProvider","prevContextValue","pushContext","instance","result","runWithComponent","popContext"],"mappings":"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","file":"chunk-QJ4B6ELN.mjs","sourcesContent":["const ESCAPE_MAP: Record<string, string> = {\n  '&': '&amp;',\n  '<': '&lt;',\n  '>': '&gt;',\n  '\"': '&quot;',\n  \"'\": '&#x27;'\n}\n\nconst ESCAPE_REGEX = /[&<>\"']/g\n\nexport function escapeHtml(str: string): string {\n  return String(str).replace(ESCAPE_REGEX, char => ESCAPE_MAP[char])\n}\n\nexport function escapeAttribute(str: string): string {\n  return escapeHtml(str)\n}\n","import type { SerializedState } from './types'\n\nlet isServerRendering = false\nlet serverStateCollector: Map<string, unknown> | null = null\nlet hydrationIdCounter = 0\n\nexport function getIsServer(): boolean {\n  return isServerRendering\n}\n\nexport function enterServerRender(): void {\n  isServerRendering = true\n  serverStateCollector = new Map()\n  hydrationIdCounter = 0\n}\n\nexport function exitServerRender(): SerializedState {\n  isServerRendering = false\n  const states = Object.fromEntries(serverStateCollector || new Map())\n  serverStateCollector = null\n\n  return { states }\n}\n\nexport function collectServerState(key: string, value: unknown): void {\n  if (serverStateCollector) {\n    serverStateCollector.set(key, value)\n  }\n}\n\nexport function generateHydrationId(): string {\n  return `fid-${hydrationIdCounter++}`\n}\n\nexport function resetHydrationIdCounter(): void {\n  hydrationIdCounter = 0\n}\n","import type { FNode, FNodeChild } from '../dom/types'\nimport type { SSROptions, SSRResult } from './types'\nimport { escapeHtml, escapeAttribute } from './escape'\nimport {\n  enterServerRender,\n  exitServerRender,\n  generateHydrationId\n} from './serverState'\nimport { runWithComponent, ComponentInstance } from '../core/hook'\nimport { pushContext, popContext } from '../core/context'\nimport { runWithRequestContext } from '../core/request-context'\n\n// Self-closing HTML tags\nconst VOID_ELEMENTS = new Set([\n  'area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input',\n  'link', 'meta', 'param', 'source', 'track', 'wbr'\n])\n\n// Attributes that should be rendered as boolean\nconst BOOLEAN_ATTRS = new Set([\n  'disabled', 'checked', 'readonly', 'required', 'hidden',\n  'selected', 'autofocus', 'autoplay', 'controls', 'loop', 'muted',\n  'multiple', 'open', 'defer', 'async', 'novalidate'\n])\n\n// Attributes that need special handling\nconst ATTR_ALIASES: Record<string, string> = {\n  className: 'class',\n  htmlFor: 'for'\n}\n\n/**\n * Render component tree to HTML string with hydration markers\n */\nexport function renderToString(\n  app: FNodeChild | (() => FNodeChild),\n  options: SSROptions = {}\n): SSRResult {\n  return runWithRequestContext(() => {\n    const { hydrate = true } = options\n\n    enterServerRender()\n\n    try {\n      // Normalize input - wrap function in FNode if needed\n      let fnode: FNodeChild\n      if (typeof app === 'function' && !isFNode(app)) {\n        fnode = { type: app, props: {}, children: [], key: undefined }\n      } else {\n        fnode = app\n      }\n\n      const html = renderNodeToString(fnode, hydrate)\n      const state = exitServerRender()\n\n      return { html, state }\n    } catch (error) {\n      exitServerRender()\n      throw error\n    }\n  })\n}\n\n/**\n * Render component tree to static HTML (no hydration markers)\n * Use for email templates, static pages, etc.\n */\nexport function renderToStaticMarkup(app: FNodeChild | (() => FNodeChild)): string {\n  const { html } = renderToString(app, { hydrate: false })\n  return html\n}\n\nfunction isFNode(value: unknown): value is FNode {\n  return value !== null && typeof value === 'object' && 'type' in value && 'props' in value\n}\n\nfunction renderNodeToString(fnode: FNodeChild, includeHydrationMarkers: boolean): string {\n  // Null/undefined/boolean -> empty string\n  if (fnode === null || fnode === undefined || typeof fnode === 'boolean') {\n    return ''\n  }\n\n  // String/number -> escaped text\n  if (typeof fnode === 'string' || typeof fnode === 'number') {\n    return escapeHtml(String(fnode))\n  }\n\n  // Array -> concatenate children\n  if (Array.isArray(fnode)) {\n    return fnode.map(child => renderNodeToString(child, includeHydrationMarkers)).join('')\n  }\n\n  // Function (standalone) -> wrap in FNode and render\n  if (typeof fnode === 'function') {\n    const wrappedFnode: FNode = { type: fnode, props: {}, children: [], key: undefined }\n    return renderComponentToString(wrappedFnode, includeHydrationMarkers)\n  }\n\n  // Object (FNode)\n  if (typeof fnode === 'object' && isFNode(fnode)) {\n    // HTML element\n    if (typeof fnode.type === 'string') {\n      return renderElementToString(fnode, includeHydrationMarkers)\n    }\n\n    // Function component\n    if (typeof fnode.type === 'function') {\n      return renderComponentToString(fnode, includeHydrationMarkers)\n    }\n  }\n\n  return ''\n}\n\nfunction renderElementToString(fnode: FNode, includeHydrationMarkers: boolean): string {\n  const tag = fnode.type as string\n  const attrs = renderAttributes(fnode.props, includeHydrationMarkers)\n\n  // Handle dangerouslySetInnerHTML\n  if (fnode.props?.dangerouslySetInnerHTML) {\n    const dih = fnode.props.dangerouslySetInnerHTML as Record<string, unknown>\n    const innerHTML = dih.__html || ''\n    return `<${tag}${attrs}>${innerHTML}</${tag}>`\n  }\n\n  // Void elements (self-closing)\n  if (VOID_ELEMENTS.has(tag)) {\n    return `<${tag}${attrs}>`\n  }\n\n  // Render children\n  const childrenHtml = (fnode.children || [])\n    .map(child => renderNodeToString(child, includeHydrationMarkers))\n    .join('')\n\n  return `<${tag}${attrs}>${childrenHtml}</${tag}>`\n}\n\nfunction renderAttributes(props: Record<string, unknown>, includeHydrationMarkers: boolean): string {\n  if (!props) return ''\n\n  const parts: string[] = []\n\n  // Add hydration ID if needed\n  if (includeHydrationMarkers) {\n    const fid = generateHydrationId()\n    parts.push(`data-fid=\"${fid}\"`)\n  }\n\n  for (const [key, value] of Object.entries(props)) {\n    // Skip event handlers, refs, and internal props\n    if (key.startsWith('on') || key === 'ref' || key === 'key' || key === 'children') continue\n    if (key === 'dangerouslySetInnerHTML') continue\n\n    // Skip undefined/null values\n    if (value === undefined || value === null) continue\n\n    // Handle aliased attributes\n    const attrName = ATTR_ALIASES[key] || key\n\n    // Handle style object\n    if (key === 'style' && typeof value === 'object') {\n      const styleStr = Object.entries(value)\n        .filter(([, v]) => v !== null && v !== undefined)\n        .map(([k, v]) => `${kebabCase(k)}:${v}`)\n        .join(';')\n      if (styleStr) {\n        parts.push(`style=\"${escapeAttribute(styleStr)}\"`)\n      }\n      continue\n    }\n\n    // Handle boolean attributes\n    if (BOOLEAN_ATTRS.has(attrName)) {\n      if (value) parts.push(attrName)\n      continue\n    }\n\n    // Handle false boolean values - skip entirely\n    if (value === false) continue\n\n    // Regular attribute\n    parts.push(`${attrName}=\"${escapeAttribute(String(value))}\"`)\n  }\n\n  return parts.length ? ' ' + parts.join(' ') : ''\n}\n\nfunction renderComponentToString(fnode: FNode, includeHydrationMarkers: boolean): string {\n  const Component = fnode.type as (props: Record<string, unknown>) => FNodeChild\n\n  // Merge props with children\n  const props: Record<string, unknown> = { ...fnode.props }\n  if (fnode.children && fnode.children.length > 0) {\n    props.children = fnode.children.length === 1\n      ? fnode.children[0]\n      : fnode.children\n  }\n\n  // Check if this is a Context Provider\n  // eslint-disable-next-line @typescript-eslint/no-explicit-any -- accessing dynamic ._contextId property set by Context constructor\n  const contextId = (Component as any)._contextId as symbol | undefined\n  const isProvider = contextId !== undefined\n  let prevContextValue: unknown\n\n  if (isProvider) {\n    prevContextValue = pushContext(contextId, props.value)\n  }\n\n  // Create minimal component instance for server (hooks support).\n  // Phase 5C: pre-initialize every ComponentInstance field at construction so\n  // SSR-rendered components share the same V8 hidden class as DOM-rendered\n  // components.\n  const instance: ComponentInstance = {\n    hooks: [],\n    hookIndex: 0,\n    componentName: Component.name || 'Component',\n    hookSignatures: null,\n    prevHookSignatures: null,\n    effects: null,\n    globalKeys: null,\n  }\n\n  try {\n    // Run component with hook context\n    const result = runWithComponent(instance, () => Component(props))\n\n    // Render result\n    return renderNodeToString(result, includeHydrationMarkers)\n  } finally {\n    // Restore context if it was a provider\n    if (isProvider) {\n      popContext(contextId, prevContextValue)\n    }\n  }\n}\n\nfunction kebabCase(str: string): string {\n  return str.replace(/([A-Z])/g, '-$1').toLowerCase()\n}\n"]}