ladrillosjs 2.0.0-beta.2 → 2.0.0-beta.2.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.
@@ -1 +0,0 @@
1
- {"version":3,"file":"webcomponent-DNeyn3kB.js","sources":["../src/core/css/cssParser.ts","../src/core/html/htmlparser.ts","../src/cache/functionCache.ts","../src/core/html/htmlRenderer.ts","../src/core/js/scriptParser.ts","../src/core/webcomponent.ts"],"sourcesContent":["type StyleTarget = HTMLElement | ShadowRoot;\r\n\r\nexport const loadStyles = (\r\n target: StyleTarget,\r\n cssText: string | undefined,\r\n useShadowDOM: boolean\r\n): void => {\r\n if (!cssText) return;\r\n\r\n const styleEl = document.createElement(\"style\");\r\n styleEl.textContent = cssText;\r\n\r\n if (useShadowDOM) {\r\n target.appendChild(styleEl);\r\n } else {\r\n document.head.appendChild(styleEl);\r\n }\r\n};\r\n","import {\r\n BindingDescriptor,\r\n TwoWayBindingDescriptor,\r\n ConditionalDescriptor,\r\n LoopDescriptor,\r\n} from \"../../types/LadrilloTypes\";\r\nimport { REGEX_PATTERNS } from \"../../utils/regex\";\r\n\r\n/**\r\n * Injects the template HTML into the host element and scans for data bindings.\r\n * Returns a list of all bindings found in text nodes and attributes.\r\n */\r\nexport const loadTemplate = (\r\n host: HTMLElement | ShadowRoot,\r\n template: string\r\n): {\r\n bindings: BindingDescriptor[];\r\n twoWayBindings: TwoWayBindingDescriptor[];\r\n conditionals: ConditionalDescriptor[][];\r\n loops: LoopDescriptor[];\r\n} => {\r\n host.innerHTML = template;\r\n\r\n const bindings = scanBindings(host);\r\n const twoWayBindings = scanTwoWayBindings(host);\r\n const conditionals = scanConditionals(host);\r\n const loops = scanLoops(host);\r\n\r\n return { bindings, twoWayBindings, conditionals, loops };\r\n};\r\n\r\n/**\r\n * Extracts variable names from function arguments.\r\n * e.g., \"formatPrice(price)\" → [\"price\"]\r\n * e.g., \"add(x, y)\" → [\"x\", \"y\"]\r\n * e.g., \"format(user.name)\" → [\"user\"]\r\n */\r\nconst extractFunctionArguments = (functionCall: string): string[] => {\r\n const variables: string[] = [];\r\n\r\n // Extract the part between parentheses\r\n const argsMatch = functionCall.match(/\\((.*)\\)/);\r\n if (!argsMatch) return variables;\r\n\r\n const argsString = argsMatch[1].trim();\r\n if (!argsString) return variables;\r\n\r\n // Split by commas, but respect nested function calls\r\n const args = argsString.split(\",\").map((arg) => arg.trim());\r\n\r\n args.forEach((arg) => {\r\n // Remove string literals (both single and double quotes)\r\n if (/^['\"]/.test(arg)) return;\r\n\r\n // Remove numeric literals\r\n if (/^\\d+/.test(arg)) return;\r\n\r\n // Extract variable name (handle dot notation, just get root)\r\n const identifierMatch = arg.match(/^([a-zA-Z_$][a-zA-Z0-9_$]*)/);\r\n if (identifierMatch) {\r\n variables.push(identifierMatch[1]);\r\n }\r\n });\r\n\r\n return variables;\r\n};\r\n\r\n/**\r\n * Traverses the DOM tree and collects all data binding expressions.\r\n * Looks for {property} placeholders in both text content and element attributes.\r\n */\r\nconst scanBindings = (host: HTMLElement | ShadowRoot): BindingDescriptor[] => {\r\n // TreeWalker efficiently traverses only text nodes\r\n const walker = document.createTreeWalker(host, NodeFilter.SHOW_TEXT, null);\r\n const bindings: BindingDescriptor[] = [];\r\n let node: Text | null;\r\n\r\n // Helper function to check if a node is inside a $for loop element\r\n const isInsideLoopElement = (node: Node): boolean => {\r\n let current = node.parentElement;\r\n while (current) {\r\n if (current.hasAttribute && current.hasAttribute(\"$for\")) {\r\n return true;\r\n }\r\n current = current.parentElement;\r\n }\r\n return false;\r\n };\r\n\r\n // Scan for text nodes with bindings\r\n // e.g. <p>{name}</p> or <span>{user.firstName}</span>\r\n while ((node = walker.nextNode() as Text | null)) {\r\n // Skip bindings inside $for loop elements - they'll be handled by processClonedElement\r\n if (isInsideLoopElement(node)) {\r\n continue;\r\n }\r\n\r\n const matches = [...node.textContent.matchAll(REGEX_PATTERNS.bindings)];\r\n\r\n if (matches.length > 0) {\r\n // Store the original template text before any replacements\r\n const original = node.textContent;\r\n\r\n // Create one binding descriptor per node with all its placeholders\r\n const nodeBindings = matches.map((match) => {\r\n const raw = match[1].trim();\r\n const isFunction = raw.includes(\"(\") && raw.includes(\")\"); // Detect function calls like MyName(\"Peter\")\r\n\r\n // Detect if this is a JavaScript expression (contains operators, method calls, etc.)\r\n // Note: We need to be careful with hyphens - they could be part of property names (data-note)\r\n // or subtraction operators. We check if hyphen is surrounded by word characters.\r\n const hasOperator =\r\n /[+*/%<>=!&|]/.test(raw) || // Math or logical operators (excluding hyphen)\r\n /\\s-\\s/.test(raw); // Hyphen with spaces around it (likely subtraction)\r\n\r\n const isExpression =\r\n hasOperator ||\r\n /\\.(?![\\s}])[a-zA-Z_$][\\w]*\\(/.test(raw) || // Method calls like name.toLowerCase()\r\n /\\bnew\\s+/.test(raw) || // Object instantiation like new Date()\r\n /\\b(typeof|instanceof|void|delete)\\b/.test(raw); // Other JS operators\r\n\r\n // For functions, extract the function name as the path\r\n // For properties, split by dot notation\r\n const path = isFunction\r\n ? [raw.split(\"(\")[0].trim()] // Extract function name before (\r\n : raw.split(\".\").map((p) => p.trim());\r\n\r\n // Extract variables from function arguments\r\n const functionArgs = isFunction ? extractFunctionArguments(raw) : [];\r\n\r\n return { raw, path, isFunction, isExpression, functionArgs };\r\n });\r\n\r\n bindings.push({ node, bindings: nodeBindings, original });\r\n }\r\n } // Scan for attributes with bindings\r\n // e.g. <img src=\"{imageUrl}\"> or <input value=\"{user.email}\">\r\n const elements = host.querySelectorAll(\"*\");\r\n elements.forEach((el) => {\r\n // Skip bindings on $for loop elements - they'll be handled by processClonedElement\r\n if (el.hasAttribute(\"$for\") || isInsideLoopElement(el)) {\r\n return;\r\n }\r\n\r\n for (const attr of el.attributes) {\r\n // Skip conditional and special directive attributes\r\n if (\r\n attr.name === \"$if\" ||\r\n attr.name === \"$else-if\" ||\r\n attr.name === \"$else\" ||\r\n attr.name === \"$bind\"\r\n ) {\r\n continue;\r\n }\r\n\r\n const matches = [...attr.value.matchAll(REGEX_PATTERNS.bindings)];\r\n if (matches.length > 0) {\r\n // Store the original attribute value\r\n const original = attr.value;\r\n\r\n // Create one binding descriptor per attribute with all its placeholders\r\n const attrBindings = matches.map((match) => {\r\n const raw = match[1].trim();\r\n const isFunction = raw.includes(\"(\") && raw.includes(\")\");\r\n\r\n // Detect if this is a JavaScript expression\r\n // Note: We need to be careful with hyphens - they could be part of property names\r\n const hasOperator =\r\n /[+*/%<>=!&|]/.test(raw) || // Math or logical operators (excluding hyphen)\r\n /\\s-\\s/.test(raw); // Hyphen with spaces around it (likely subtraction)\r\n\r\n const isExpression =\r\n hasOperator ||\r\n /\\.(?![\\s}])[a-zA-Z_$][\\w]*\\(/.test(raw) || // Method calls like name.toLowerCase()\r\n /\\bnew\\s+/.test(raw) || // Object instantiation like new Date()\r\n /\\b(typeof|instanceof|void|delete)\\b/.test(raw); // Other JS operators\r\n\r\n const path = isFunction\r\n ? [raw.split(\"(\")[0].trim()]\r\n : raw.split(\".\").map((p) => p.trim());\r\n\r\n // Extract variables from function arguments\r\n const functionArgs = isFunction ? extractFunctionArguments(raw) : [];\r\n\r\n return { raw, path, isFunction, isExpression, functionArgs };\r\n });\r\n\r\n bindings.push({\r\n node: el as unknown as Text,\r\n bindings: attrBindings,\r\n original,\r\n isAttribute: true,\r\n attributeName: attr.name,\r\n });\r\n }\r\n }\r\n });\r\n\r\n return bindings;\r\n};\r\n\r\n/**\r\n * Scans for elements with $bind attribute for two-way data binding.\r\n * e.g. <input $bind=\"inputText\"> or <input $bind=\"person.name\">\r\n * Now also supports contenteditable elements: <div contenteditable $bind=\"text\">\r\n */\r\nconst scanTwoWayBindings = (\r\n host: HTMLElement | ShadowRoot\r\n): TwoWayBindingDescriptor[] => {\r\n const twoWayBindings: TwoWayBindingDescriptor[] = [];\r\n const elements = host.querySelectorAll(\"[\\\\$bind]\");\r\n\r\n elements.forEach((el) => {\r\n const bindValue = el.getAttribute(\"$bind\");\r\n if (!bindValue) return;\r\n\r\n const raw = bindValue.trim();\r\n const path = raw.split(\".\").map((p) => p.trim());\r\n\r\n // Support form inputs (input, textarea, select)\r\n if (\r\n el instanceof HTMLInputElement ||\r\n el instanceof HTMLTextAreaElement ||\r\n el instanceof HTMLSelectElement\r\n ) {\r\n twoWayBindings.push({\r\n element: el,\r\n path,\r\n raw,\r\n isContentEditable: false,\r\n initialValue: el.value || \"\",\r\n });\r\n el.removeAttribute(\"$bind\");\r\n }\r\n // Support contenteditable elements (including those with contenteditable=\"false\" initially)\r\n else if (el instanceof HTMLElement && el.hasAttribute(\"contenteditable\")) {\r\n twoWayBindings.push({\r\n element: el,\r\n path,\r\n raw,\r\n isContentEditable: true,\r\n initialValue: el.textContent?.trim() || \"\",\r\n });\r\n el.removeAttribute(\"$bind\");\r\n }\r\n });\r\n\r\n return twoWayBindings;\r\n};\r\n\r\n/**\r\n * Scans for elements with $if, $else-if, and $else attributes for conditional rendering.\r\n * Groups related conditionals together (if → else-if → else chains).\r\n * e.g. <div $if=\"isVisible\">...</div> or <div $else-if=\"count > 5\">...</div>\r\n */\r\nconst scanConditionals = (\r\n host: HTMLElement | ShadowRoot\r\n): ConditionalDescriptor[][] => {\r\n const allConditionals: ConditionalDescriptor[][] = [];\r\n const processedElements = new Set<Element>();\r\n\r\n // Find all $if elements (start of conditional chains)\r\n const ifElements = host.querySelectorAll(\"[\\\\$if]\");\r\n\r\n ifElements.forEach((element) => {\r\n if (processedElements.has(element)) return;\r\n\r\n const group: ConditionalDescriptor[] = [];\r\n let currentElement: Element | null = element;\r\n\r\n // Process the $if and all following $else-if and $else siblings\r\n while (currentElement) {\r\n const hasIf = currentElement.hasAttribute(\"$if\");\r\n const hasElseIf = currentElement.hasAttribute(\"$else-if\");\r\n const hasElse = currentElement.hasAttribute(\"$else\");\r\n\r\n if (!hasIf && !hasElseIf && !hasElse) break;\r\n\r\n processedElements.add(currentElement);\r\n\r\n let type: \"if\" | \"else-if\" | \"else\";\r\n let condition = \"\";\r\n\r\n if (hasIf) {\r\n type = \"if\";\r\n condition = currentElement.getAttribute(\"$if\") || \"\";\r\n currentElement.removeAttribute(\"$if\");\r\n } else if (hasElseIf) {\r\n type = \"else-if\";\r\n condition = currentElement.getAttribute(\"$else-if\") || \"\";\r\n currentElement.removeAttribute(\"$else-if\");\r\n } else {\r\n type = \"else\";\r\n currentElement.removeAttribute(\"$else\");\r\n }\r\n\r\n // Create a comment placeholder to mark the position\r\n const placeholder = document.createComment(\r\n `conditional:${type}:${condition}`\r\n );\r\n\r\n const parent = currentElement.parentElement || host;\r\n const nextSibling = currentElement.nextSibling;\r\n\r\n // Insert placeholder before the element\r\n parent.insertBefore(placeholder, currentElement);\r\n\r\n const descriptor: ConditionalDescriptor = {\r\n element: currentElement as Element,\r\n condition: condition.trim(),\r\n type,\r\n placeholder,\r\n group: [], // Will be set after the group is complete\r\n originalParent: parent as Element | ShadowRoot,\r\n nextSibling,\r\n };\r\n\r\n group.push(descriptor);\r\n\r\n // Move to the next sibling to check for $else-if or $else\r\n const next: Element | null = currentElement.nextElementSibling;\r\n\r\n // Remove element from DOM initially\r\n currentElement.remove();\r\n\r\n currentElement = next;\r\n\r\n // If next element isn't $else-if or $else, stop the chain\r\n if (\r\n next &&\r\n !next.hasAttribute(\"$else-if\") &&\r\n !next.hasAttribute(\"$else\")\r\n ) {\r\n break;\r\n }\r\n }\r\n\r\n // Set the group reference for all descriptors in this chain\r\n group.forEach((desc) => {\r\n desc.group = group;\r\n });\r\n\r\n allConditionals.push(group);\r\n });\r\n\r\n return allConditionals;\r\n};\r\n\r\n/**\r\n * Extracts variable names from conditional expressions.\r\n * Removes curly braces and extracts identifiers.\r\n * e.g., \"{sending}\" → [\"sending\"], \"{count > 5}\" → [\"count\"]\r\n */\r\nexport const extractConditionalVariables = (\r\n conditionalGroups: ConditionalDescriptor[][]\r\n): Set<string> => {\r\n const variables = new Set<string>();\r\n\r\n conditionalGroups.forEach((group) => {\r\n group.forEach((descriptor) => {\r\n let condition = descriptor.condition;\r\n\r\n // Remove curly braces: {sending} → sending\r\n condition = condition.replace(/\\{([^}]+)\\}/g, \"$1\");\r\n\r\n // Extract variable names (identifiers)\r\n // Match JavaScript identifiers but exclude keywords and literals\r\n const identifierRegex =\r\n /\\b([a-zA-Z_$][a-zA-Z0-9_$]*(?:\\.[a-zA-Z_$][a-zA-Z0-9_$]*)*)\\b/g;\r\n const keywords = new Set([\r\n \"true\",\r\n \"false\",\r\n \"null\",\r\n \"undefined\",\r\n \"typeof\",\r\n \"instanceof\",\r\n \"new\",\r\n \"return\",\r\n \"if\",\r\n \"else\",\r\n \"for\",\r\n \"while\",\r\n \"do\",\r\n \"switch\",\r\n \"case\",\r\n \"break\",\r\n \"continue\",\r\n ]);\r\n\r\n let match;\r\n while ((match = identifierRegex.exec(condition)) !== null) {\r\n const identifier = match[1];\r\n const rootVar = identifier.split(\".\")[0]; // Get root variable name\r\n\r\n // Skip keywords and literals\r\n if (!keywords.has(rootVar)) {\r\n variables.add(rootVar);\r\n }\r\n }\r\n });\r\n });\r\n\r\n return variables;\r\n};\r\n\r\n/**\r\n * Scans for elements with $for attribute for list rendering.\r\n * Supports syntax: \"item in items\" or \"(item, index) in items\"\r\n * e.g. <li $for=\"item in items\">{item}</li>\r\n * e.g. <div $for=\"(user, index) in users\">{index}: {user.name}</div>\r\n */\r\nconst scanLoops = (host: HTMLElement | ShadowRoot): LoopDescriptor[] => {\r\n const loops: LoopDescriptor[] = [];\r\n const loopElements = host.querySelectorAll(\"[\\\\$for]\");\r\n\r\n loopElements.forEach((element) => {\r\n const forExpression = element.getAttribute(\"$for\");\r\n if (!forExpression) return;\r\n\r\n const keyAttribute = element.getAttribute(\"$key\") || undefined;\r\n\r\n // Parse the expression: \"item in items\" or \"(item, index) in items\"\r\n const match = forExpression.match(\r\n /^\\s*(?:\\(([^,]+),\\s*([^)]+)\\)|([^\\s]+))\\s+(?:in|of)\\s+(.+)\\s*$/\r\n );\r\n\r\n if (!match) {\r\n console.error(`Invalid $for expression: \"${forExpression}\"`);\r\n return;\r\n }\r\n\r\n const itemName = (match[1] || match[3]).trim();\r\n const indexName = match[2]?.trim();\r\n const arrayName = match[4].trim();\r\n\r\n // Create a comment placeholder\r\n const placeholder = document.createComment(`loop:${forExpression}`);\r\n\r\n const parent = element.parentElement || host;\r\n parent.insertBefore(placeholder, element);\r\n\r\n // Remove the $for and $key attributes\r\n element.removeAttribute(\"$for\");\r\n if (keyAttribute) element.removeAttribute(\"$key\");\r\n\r\n // Remove the element from DOM (it will be cloned for each iteration)\r\n element.remove();\r\n\r\n const descriptor: LoopDescriptor = {\r\n template: element as Element,\r\n expression: forExpression,\r\n itemName,\r\n indexName,\r\n arrayName,\r\n keyAttribute,\r\n placeholder,\r\n renderedElements: [],\r\n originalParent: parent as Element | ShadowRoot,\r\n };\r\n\r\n loops.push(descriptor);\r\n });\r\n\r\n return loops;\r\n};\r\n\r\n/**\r\n * Extracts variable names from loop expressions.\r\n * e.g., \"item in items\" → [\"items\"], \"(user, index) in users\" → [\"users\"]\r\n */\r\nexport const extractLoopVariables = (loops: LoopDescriptor[]): Set<string> => {\r\n const variables = new Set<string>();\r\n\r\n loops.forEach((loop) => {\r\n // Add the array name as a variable to watch\r\n const rootVar = loop.arrayName.split(\".\")[0];\r\n variables.add(rootVar);\r\n });\r\n\r\n return variables;\r\n};\r\n","/**\r\n * Cache for compiled function expressions used in template bindings.\r\n * Prevents memory leaks by reusing Function objects for identical expressions.\r\n * Example: {MyName(\"Peter\")} compiles once and is reused on every render.\r\n */\r\nconst functionCache = new Map<string, Function>();\r\nconst maxFunctionCacheSize = 100; // Functions are small, can cache more\r\n\r\n/**\r\n * Gets or creates a cached function for evaluating template expressions.\r\n * Uses LRU pattern to limit cache size and prevent unbounded growth.\r\n * @param expression - The JavaScript expression to compile (e.g., 'MyName(\"Peter\")')\r\n * @returns Compiled Function object that can be executed with a component context\r\n */\r\nexport const getCachedFunction = (expression: string): Function => {\r\n const cached = functionCache.get(expression);\r\n\r\n if (cached) {\r\n // LRU: Move to end (most recently used position)\r\n functionCache.delete(expression);\r\n functionCache.set(expression, cached);\r\n return cached;\r\n }\r\n\r\n // Cache miss: compile new function\r\n // Include common globals in the function scope\r\n const compiledFunc = new Function(\r\n \"component\",\r\n `\r\n const { Date, Array, Math, String, Number, Boolean, Object, JSON, RegExp } = globalThis;\r\n with(component) { \r\n return ${expression}; \r\n }\r\n `\r\n );\r\n\r\n // Check cache size and evict least recently used if needed\r\n if (functionCache.size >= maxFunctionCacheSize) {\r\n const firstKey = functionCache.keys().next().value;\r\n if (firstKey) {\r\n functionCache.delete(firstKey);\r\n }\r\n }\r\n\r\n // Add as most recently used\r\n functionCache.set(expression, compiledFunc);\r\n return compiledFunc;\r\n};\r\n\r\n/**\r\n * Clears the function cache. Useful for testing or memory management.\r\n */\r\nexport const clearFunctionCache = (): void => {\r\n functionCache.clear();\r\n};\r\n\r\n/**\r\n * Gets the current function cache size for debugging/monitoring.\r\n */\r\nexport const getFunctionCacheSize = (): number => {\r\n return functionCache.size;\r\n};\r\n","import {\r\n BindingDescriptor,\r\n ConditionalDescriptor,\r\n LoopDescriptor,\r\n} from \"../../types/LadrilloTypes\";\r\nimport { getCachedFunction } from \"../../cache/functionCache\";\r\n\r\n/**\r\n * Safely retrieves a nested value from an object using a path array.\r\n * Example: getValue({ user: { name: 'John' } }, ['user', 'name']) returns 'John'\r\n */\r\nconst getValue = (ctx: unknown, path: string[]): unknown => {\r\n return path.reduce<unknown>((acc: unknown, segment: string) => {\r\n // Stop traversal if we hit null/undefined or non-object\r\n if (acc == null || typeof acc !== \"object\") return undefined;\r\n return (acc as Record<string, unknown>)[segment];\r\n }, ctx);\r\n};\r\n\r\n/**\r\n * Safely sets a nested value in an object using a path array.\r\n * Example: setValue({ user: {} }, ['user', 'name'], 'John') sets user.name to 'John'\r\n * Creates intermediate objects if they don't exist.\r\n */\r\nexport const setValue = (ctx: any, path: string[], value: unknown): void => {\r\n if (path.length === 0) return;\r\n\r\n // Navigate to the parent object\r\n const lastKey = path[path.length - 1];\r\n const parentPath = path.slice(0, -1);\r\n\r\n let current = ctx;\r\n\r\n // Create intermediate objects if needed\r\n for (const segment of parentPath) {\r\n if (current[segment] === undefined || current[segment] === null) {\r\n current[segment] = {};\r\n }\r\n current = current[segment];\r\n }\r\n\r\n // Set the final value\r\n current[lastKey] = value;\r\n};\r\n\r\n/**\r\n * Updates all DOM bindings with values from the current state context.\r\n * Replaces {property.path} placeholders in text nodes and element attributes.\r\n * Always renders from the original template to support reactive updates.\r\n */\r\nexport const renderBindings = (\r\n bindings: BindingDescriptor[],\r\n context: unknown,\r\n component?: any\r\n): void => {\r\n for (const binding of bindings) {\r\n // Start with the original template\r\n let result = binding.original;\r\n\r\n // Replace all placeholders in this node\r\n for (const { raw, path, isFunction, isExpression } of binding.bindings) {\r\n let value: unknown;\r\n\r\n if (isExpression || isFunction) {\r\n // Execute JavaScript expressions like i + 1, name.toLowerCase(), MyName(\"Peter\")\r\n try {\r\n // Use cached function to prevent memory leaks\r\n const evalFunc = getCachedFunction(raw);\r\n // Merge context and component into a single scope object\r\n const scope =\r\n typeof context === \"object\" && context !== null\r\n ? { ...context, ...(component || {}) }\r\n : component || {};\r\n value = evalFunc(scope);\r\n } catch (error) {\r\n console.error(`Error executing expression binding {${raw}}:`, error);\r\n value = undefined;\r\n }\r\n } else {\r\n // Simple property access\r\n value = getValue(context, path);\r\n }\r\n\r\n if (value === undefined) continue;\r\n const replacement = String(value ?? \"\");\r\n\r\n // Replace this specific placeholder\r\n result = result.replace(`{${raw}}`, replacement);\r\n }\r\n\r\n // Apply the final result to the DOM\r\n if (binding.node.nodeType === Node.TEXT_NODE) {\r\n const textNode = binding.node as Text;\r\n const parentElement = textNode.parentElement;\r\n\r\n // Check if this looks like HTML content\r\n const isHTMLContent =\r\n result.trim().startsWith(\"<\") && result.includes(\">\");\r\n\r\n // If parent element exists and content is HTML, render as HTML\r\n if (parentElement && isHTMLContent) {\r\n parentElement.innerHTML = result;\r\n } else {\r\n // Otherwise, use textContent for security\r\n textNode.textContent = result;\r\n }\r\n } else {\r\n // Handle attribute bindings (e.g., <img src=\"{imageUrl}\">)\r\n const element = binding.node as unknown as Element;\r\n if (binding.isAttribute && binding.attributeName) {\r\n element.setAttribute(binding.attributeName, result);\r\n }\r\n }\r\n }\r\n};\r\n\r\n/**\r\n * Evaluates a conditional expression in the context of the component.\r\n * Supports both simple boolean checks and complex expressions.\r\n * e.g. \"isVisible\", \"{isVisible}\", \"count > 5\", \"{count} > 5\"\r\n */\r\nconst evaluateCondition = (\r\n condition: string,\r\n context: unknown,\r\n component?: any\r\n): boolean => {\r\n if (!condition) return true; // $else has no condition\r\n\r\n // Remove curly braces if present: {sending} -> sending\r\n let processedCondition = condition.trim();\r\n\r\n // Replace all {variable} with just variable\r\n processedCondition = processedCondition.replace(/\\{([^}]+)\\}/g, \"$1\");\r\n\r\n try {\r\n // Replace variable references in the condition with their values\r\n // This is a simple approach - for production, consider a proper expression parser\r\n const func = new Function(\r\n \"context\",\r\n \"component\",\r\n `\r\n with (context) {\r\n try {\r\n return Boolean(${processedCondition});\r\n } catch (e) {\r\n return false;\r\n }\r\n }\r\n `\r\n );\r\n\r\n return func(context, component);\r\n } catch (error) {\r\n console.error(`Error evaluating condition \"${condition}\":`, error);\r\n return false;\r\n }\r\n};\r\n\r\n/**\r\n * Processes event handlers on an element and its descendants.\r\n * Converts inline event attributes to proper event listeners with component scope access.\r\n */\r\nconst processElementEventHandlers = (\r\n element: Element,\r\n component: any\r\n): void => {\r\n const eventTypes = [\r\n \"click\",\r\n \"dblclick\",\r\n \"mousedown\",\r\n \"mouseup\",\r\n \"mouseover\",\r\n \"mouseout\",\r\n \"mousemove\",\r\n \"mouseenter\",\r\n \"mouseleave\",\r\n \"keydown\",\r\n \"keyup\",\r\n \"keypress\",\r\n \"focus\",\r\n \"blur\",\r\n \"change\",\r\n \"input\",\r\n \"submit\",\r\n \"reset\",\r\n \"scroll\",\r\n \"resize\",\r\n \"load\",\r\n \"unload\",\r\n \"touchstart\",\r\n \"touchend\",\r\n \"touchmove\",\r\n \"touchcancel\",\r\n \"dragstart\",\r\n \"drag\",\r\n \"dragend\",\r\n \"dragenter\",\r\n \"dragover\",\r\n \"dragleave\",\r\n \"drop\",\r\n ];\r\n\r\n // Process the element itself and all descendants\r\n const elementsToProcess = [element, ...element.querySelectorAll(\"*\")];\r\n\r\n elementsToProcess.forEach((el) => {\r\n eventTypes.forEach((eventType) => {\r\n const attributeName = `on${eventType}`;\r\n const handlerCode = el.getAttribute(attributeName);\r\n\r\n if (handlerCode) {\r\n // Skip if already processed\r\n const key = `__processed_${attributeName}`;\r\n if ((el as any)[key]) return;\r\n\r\n // Remove the attribute\r\n el.removeAttribute(attributeName);\r\n\r\n // Add event listener with component scope\r\n (el as HTMLElement).addEventListener(\r\n eventType,\r\n function (this: HTMLElement, event: Event) {\r\n try {\r\n const func = new Function(\r\n \"event\",\r\n \"component\",\r\n `\r\n with(component) {\r\n ${handlerCode}\r\n }\r\n `\r\n );\r\n func.call(this, event, component);\r\n } catch (error) {\r\n console.error(\r\n `Error executing ${eventType} handler:`,\r\n error,\r\n handlerCode\r\n );\r\n }\r\n }\r\n );\r\n\r\n // Mark as processed\r\n (el as any)[key] = true;\r\n }\r\n });\r\n });\r\n};\r\n\r\n/**\r\n * Updates conditional rendering based on current state.\r\n * Shows/hides elements based on their $if, $else-if, $else conditions.\r\n */\r\nexport const renderConditionals = (\r\n conditionalGroups: ConditionalDescriptor[][],\r\n context: unknown,\r\n component?: any\r\n): void => {\r\n // Process each conditional group (if/else-if/else chain)\r\n for (const group of conditionalGroups) {\r\n let conditionMet = false;\r\n\r\n // Evaluate each condition in the group\r\n for (const descriptor of group) {\r\n const { element, condition, type, placeholder, originalParent } =\r\n descriptor;\r\n\r\n // Check if this condition should be rendered\r\n let shouldRender = false;\r\n\r\n if (type === \"else\") {\r\n // $else renders if no previous condition was met\r\n shouldRender = !conditionMet;\r\n } else if (!conditionMet) {\r\n // $if or $else-if: evaluate condition\r\n shouldRender = evaluateCondition(condition, context, component);\r\n if (shouldRender) conditionMet = true;\r\n }\r\n\r\n // Update DOM based on shouldRender\r\n const isInDOM = element.parentNode !== null;\r\n\r\n if (shouldRender && !isInDOM) {\r\n // Insert element after its placeholder\r\n placeholder.parentNode?.insertBefore(element, placeholder.nextSibling);\r\n\r\n // Process event handlers on newly inserted element\r\n if (component) {\r\n processElementEventHandlers(element, component);\r\n }\r\n } else if (!shouldRender && isInDOM) {\r\n // Remove element from DOM\r\n element.remove();\r\n }\r\n }\r\n }\r\n};\r\n\r\n/**\r\n * Renders loop elements based on array data.\r\n * Creates clones of the template for each item in the array.\r\n */\r\nexport const renderLoops = (\r\n loops: LoopDescriptor[],\r\n context: unknown,\r\n component?: any\r\n): void => {\r\n for (const loop of loops) {\r\n const {\r\n template,\r\n itemName,\r\n indexName,\r\n arrayName,\r\n placeholder,\r\n renderedElements,\r\n } = loop;\r\n\r\n // Get the array data from context\r\n const arrayData = getValue(context, arrayName.split(\".\"));\r\n\r\n // Validate array - only warn if the value exists but is not an array\r\n // (undefined values are expected during initial render before scripts execute)\r\n if (arrayData !== undefined && !Array.isArray(arrayData)) {\r\n console.warn(`$for: \"${arrayName}\" is not an array, got:`, arrayData);\r\n // Clear any existing rendered elements\r\n renderedElements.forEach((el) => el.remove());\r\n renderedElements.length = 0;\r\n return;\r\n }\r\n\r\n // If array doesn't exist yet, don't render anything (wait for state initialization)\r\n if (!arrayData) {\r\n return;\r\n }\r\n\r\n // Remove all currently rendered elements\r\n renderedElements.forEach((el) => el.remove());\r\n renderedElements.length = 0;\r\n\r\n // Render each item\r\n arrayData.forEach((item, index) => {\r\n // Clone the template\r\n const clone = template.cloneNode(true) as Element;\r\n\r\n // Create a scoped context for this iteration\r\n const scopedContext: Record<string, any> = {\r\n ...(context as Record<string, any>),\r\n [itemName]: item,\r\n };\r\n\r\n if (indexName) {\r\n scopedContext[indexName] = index;\r\n }\r\n\r\n // Process bindings in the cloned element\r\n processClonedElement(clone, scopedContext, component);\r\n\r\n // Insert after placeholder (or after the last rendered element)\r\n const insertAfter =\r\n renderedElements.length > 0\r\n ? renderedElements[renderedElements.length - 1]\r\n : placeholder;\r\n\r\n insertAfter.parentNode?.insertBefore(clone, insertAfter.nextSibling);\r\n\r\n // Track rendered element\r\n renderedElements.push(clone);\r\n\r\n // Process event handlers\r\n if (component) {\r\n processElementEventHandlers(clone, component);\r\n }\r\n });\r\n }\r\n};\r\n\r\n/**\r\n * Processes bindings in a cloned element for loop rendering.\r\n * Replaces {variable} placeholders with actual values.\r\n */\r\nconst processClonedElement = (\r\n element: Element,\r\n context: unknown,\r\n component?: any\r\n): void => {\r\n // Process text nodes\r\n const walker = document.createTreeWalker(element, NodeFilter.SHOW_TEXT, null);\r\n let node: Text | null;\r\n\r\n while ((node = walker.nextNode() as Text | null)) {\r\n if (node.textContent && node.textContent.includes(\"{\")) {\r\n let result = node.textContent;\r\n const matches = [...node.textContent.matchAll(/\\{([^}]+)\\}/g)];\r\n\r\n matches.forEach((match) => {\r\n const raw = match[1].trim();\r\n\r\n // Detect if this is a JavaScript expression\r\n const isFunction = raw.includes(\"(\") && raw.includes(\")\");\r\n const hasOperator = /[+*/%<>=!&|]/.test(raw) || /\\s-\\s/.test(raw);\r\n const isExpression =\r\n hasOperator ||\r\n /\\.(?![\\s}])[a-zA-Z_$][\\w]*\\(/.test(raw) || // Method calls\r\n /\\bnew\\s+/.test(raw) || // Object instantiation like new Date()\r\n /\\b(typeof|instanceof|void|delete)\\b/.test(raw); // Other JS operators\r\n\r\n let value: unknown;\r\n\r\n if (isExpression || isFunction) {\r\n // Execute JavaScript expressions\r\n try {\r\n const evalFunc = getCachedFunction(raw);\r\n const scope =\r\n typeof context === \"object\" && context !== null\r\n ? { ...context, ...(component || {}) }\r\n : component || {};\r\n value = evalFunc(scope);\r\n } catch (error) {\r\n console.error(\r\n `Error executing expression in loop {${raw}}:`,\r\n error\r\n );\r\n value = undefined;\r\n }\r\n } else {\r\n // Simple property access\r\n const path = raw.split(\".\").map((p) => p.trim());\r\n value = getValue(context, path);\r\n }\r\n\r\n if (value !== undefined) {\r\n result = result.replace(`{${raw}}`, String(value ?? \"\"));\r\n }\r\n });\r\n\r\n node.textContent = result;\r\n }\r\n }\r\n\r\n // Process attributes (including event handlers with loop variables)\r\n const elementsWithBindings = [element, ...element.querySelectorAll(\"*\")];\r\n elementsWithBindings.forEach((el) => {\r\n Array.from(el.attributes).forEach((attr) => {\r\n if (attr.value.includes(\"{\")) {\r\n let result = attr.value;\r\n const matches = [...attr.value.matchAll(/\\{([^}]+)\\}/g)];\r\n\r\n matches.forEach((match) => {\r\n const raw = match[1].trim();\r\n\r\n // Detect if this is a JavaScript expression\r\n const isFunction = raw.includes(\"(\") && raw.includes(\")\");\r\n const hasOperator = /[+*/%<>=!&|]/.test(raw) || /\\s-\\s/.test(raw);\r\n const isExpression =\r\n hasOperator ||\r\n /\\.(?![\\s}])[a-zA-Z_$][\\w]*\\(/.test(raw) || // Method calls\r\n /\\bnew\\s+/.test(raw) || // Object instantiation like new Date()\r\n /\\b(typeof|instanceof|void|delete)\\b/.test(raw); // Other JS operators\r\n\r\n let value: unknown;\r\n\r\n if (isExpression || isFunction) {\r\n // Execute JavaScript expressions\r\n try {\r\n const evalFunc = getCachedFunction(raw);\r\n const scope =\r\n typeof context === \"object\" && context !== null\r\n ? { ...context, ...(component || {}) }\r\n : component || {};\r\n value = evalFunc(scope);\r\n } catch (error) {\r\n console.error(\r\n `Error executing expression in loop attribute {${raw}}:`,\r\n error\r\n );\r\n value = undefined;\r\n }\r\n } else {\r\n // Simple property access\r\n const path = raw.split(\".\").map((p) => p.trim());\r\n value = getValue(context, path);\r\n }\r\n\r\n if (value !== undefined) {\r\n result = result.replace(`{${raw}}`, String(value ?? \"\"));\r\n }\r\n });\r\n\r\n el.setAttribute(attr.name, result);\r\n }\r\n });\r\n });\r\n};\r\n","import {\r\n ScriptElement,\r\n BindingDescriptor,\r\n ExternalScriptElement,\r\n TwoWayBindingDescriptor,\r\n} from \"../../types/LadrilloTypes\";\r\nimport { eventBus } from \"../eventBus\";\r\n\r\nconst getHostElement = (host: HTMLElement | ShadowRoot): HTMLElement =>\r\n host instanceof ShadowRoot ? (host.host as HTMLElement) : host;\r\n\r\n/**\r\n * Injects $bind variables into the script scope.\r\n * Creates property descriptors that proxy to component.state for reactive access.\r\n */\r\nconst injectBindVariables = (\r\n scriptContent: string,\r\n twoWayBindings: TwoWayBindingDescriptor[]\r\n): {\r\n injectedCode: string;\r\n componentInjections: string;\r\n bindVarNames: Set<string>;\r\n} => {\r\n const bindVarNames = new Set<string>();\r\n\r\n // Extract all $bind variable names (root-level only, e.g., \"person\" from \"person.name\")\r\n twoWayBindings.forEach(({ path }) => {\r\n const rootVar = path[0];\r\n bindVarNames.add(rootVar);\r\n });\r\n\r\n // Create proxy getters/setters for each $bind variable in script scope\r\n const componentInjections: string[] = [];\r\n\r\n bindVarNames.forEach((varName) => {\r\n // Define on component object for event handler access via with(component)\r\n componentInjections.push(`\r\n if (!Object.getOwnPropertyDescriptor(component, '${varName}')) {\r\n Object.defineProperty(component, '${varName}', {\r\n get() { return this.state.${varName}; },\r\n set(val) { this.state.${varName} = val; },\r\n enumerable: true,\r\n configurable: true\r\n });\r\n }\r\n `);\r\n });\r\n\r\n return {\r\n injectedCode: \"\", // No longer needed in script scope\r\n componentInjections: componentInjections.join(\"\\n\"),\r\n bindVarNames,\r\n };\r\n};\r\n\r\n/**\r\n * Extracts variable declarations (const, let, var) from script content\r\n * that match the template bindings or conditionals, and returns code to bind them to state.\r\n * Only binds variables that are actually used in the template or conditionals.\r\n */\r\nconst extractStateBindings = (\r\n scriptContent: string,\r\n bindings: BindingDescriptor[],\r\n conditionalVars: Set<string> = new Set()\r\n): { stateBindings: string[]; boundVarNames: Set<string> } => {\r\n const stateBindings: string[] = [];\r\n\r\n // Create a Set of all binding names used in the template for fast lookup\r\n const bindingNames = new Set<string>();\r\n bindings.forEach((binding) => {\r\n binding.bindings.forEach((b) => {\r\n // Extract the root property name (e.g., \"user.name\" → \"user\", \"count\" → \"count\")\r\n const rootName = b.path[0];\r\n bindingNames.add(rootName);\r\n\r\n // Also add function arguments (e.g., formatPrice(price) → \"price\")\r\n if (b.isFunction && b.functionArgs) {\r\n b.functionArgs.forEach((arg) => {\r\n bindingNames.add(arg);\r\n });\r\n }\r\n });\r\n });\r\n\r\n // Add conditional variables to binding names\r\n conditionalVars.forEach((varName) => {\r\n bindingNames.add(varName);\r\n });\r\n\r\n // Match: const name = value; | let count = 0; | var items = [];\r\n const variableRegex = /(?:const|let|var)\\s+(\\w+)\\s*=\\s*([^;]+);?/g;\r\n\r\n let match;\r\n while ((match = variableRegex.exec(scriptContent)) !== null) {\r\n const varName = match[1];\r\n\r\n // Only auto-bind if this variable is used in a template binding\r\n if (bindingNames.has(varName)) {\r\n stateBindings.push(`component.state.${varName} = ${varName};`);\r\n }\r\n }\r\n\r\n return { stateBindings, boundVarNames: bindingNames };\r\n};\r\n\r\n/**\r\n * Transforms script content to redirect bound variable assignments to state.\r\n * Handles assignments, increments, decrements, compound assignments, and nested property access.\r\n * Examples:\r\n * - \"name = value\" → \"component.state.name = value\"\r\n * - \"count++\" → \"component.state.count++\"\r\n * - \"count += 5\" → \"component.state.count += 5\"\r\n * - \"user.name = value\" → \"component.state.user.name = value\"\r\n * This makes reactivity transparent - users don't need to know about state.\r\n */\r\nconst transformBoundAssignments = (\r\n scriptContent: string,\r\n boundVarNames: Set<string>\r\n): string => {\r\n if (boundVarNames.size === 0) return scriptContent;\r\n\r\n let transformed = scriptContent;\r\n\r\n boundVarNames.forEach((varName) => {\r\n // 1. Transform property access with assignment/operators: user.name = value, user.count++, etc.\r\n // Match: varName.property followed by =, +=, -=, ++, --, etc.\r\n const propertyWriteRegex = new RegExp(\r\n `\\\\b${varName}\\\\.(\\\\w+(?:\\\\.\\\\w+)*)\\\\s*([=+\\\\-*/%&|^]|\\\\+\\\\+|\\\\-\\\\-)`,\r\n \"g\"\r\n );\r\n transformed = transformed.replace(\r\n propertyWriteRegex,\r\n `component.state.${varName}.$1 $2`\r\n );\r\n\r\n // 2. Transform property access in expressions: user.name (reads)\r\n // But NOT if it's part of an already transformed component.state.varName\r\n // And NOT if it's in a variable declaration\r\n const propertyReadRegex = new RegExp(\r\n `(?<!component\\\\.state\\\\.)(?<!const\\\\s${varName}\\\\s*=\\\\s*{[^}]*)\\\\b${varName}\\\\.(\\\\w+(?:\\\\.\\\\w+)*)(?![=+\\\\-*/%&|^]|\\\\+\\\\+|\\\\-\\\\-)`,\r\n \"g\"\r\n );\r\n transformed = transformed.replace(\r\n propertyReadRegex,\r\n `component.state.${varName}.$1`\r\n );\r\n\r\n // 3. Transform increment/decrement on the variable itself: count++ or ++count\r\n const incrementRegex = new RegExp(\r\n `(?<!\\\\.)\\\\b(\\\\+\\\\+|\\\\-\\\\-)${varName}\\\\b|\\\\b${varName}(\\\\+\\\\+|\\\\-\\\\-)`,\r\n \"g\"\r\n );\r\n transformed = transformed.replace(incrementRegex, (match) => {\r\n if (match.startsWith(\"++\") || match.startsWith(\"--\")) {\r\n const op = match.substring(0, 2);\r\n return `${op}component.state.${varName}`;\r\n } else {\r\n const op = match.substring(match.length - 2);\r\n return `component.state.${varName}${op}`;\r\n }\r\n });\r\n\r\n // 4. Transform compound assignments on the variable itself: count += 5\r\n const compoundRegex = new RegExp(\r\n `(?<!\\\\.)\\\\b${varName}\\\\s*(\\\\+=|\\\\-=|\\\\*=|\\\\/=|%=|\\\\*\\\\*=|<<=|>>=|>>>=|&=|\\\\|=|\\\\^=)`,\r\n \"g\"\r\n );\r\n transformed = transformed.replace(\r\n compoundRegex,\r\n `component.state.${varName}$1`\r\n );\r\n\r\n // 5. Transform simple assignments: name = value (but not in declarations)\r\n const assignmentRegex = new RegExp(\r\n `(?<!const\\\\s)(?<!let\\\\s)(?<!var\\\\s)(?<!\\\\.)\\\\b${varName}\\\\s*=\\\\s*([^=])`,\r\n \"g\"\r\n );\r\n transformed = transformed.replace(\r\n assignmentRegex,\r\n `component.state.${varName} = $1`\r\n );\r\n });\r\n\r\n return transformed;\r\n};\r\n\r\n/**\r\n * Processes script content: extracts functions, binds state variables, and transforms assignments.\r\n * This is the core script processing logic that can be reused for both inline and external scripts.\r\n * @param scriptContent - The raw script content to process\r\n * @param bindings - Template bindings to determine which variables should be reactive\r\n * @param twoWayBindings - Two-way bound variables from $bind attributes\r\n * @param host - The host element or shadow root (for querySelector)\r\n * @param componentHost - The component element to execute the script on\r\n * @param conditionalVars - Variables used in conditional expressions ($if, $else-if)\r\n */\r\nconst processScript = (\r\n scriptContent: string,\r\n bindings: BindingDescriptor[],\r\n twoWayBindings: TwoWayBindingDescriptor[],\r\n host: HTMLElement | ShadowRoot,\r\n componentHost: HTMLElement,\r\n conditionalVars: Set<string> = new Set()\r\n): void => {\r\n try {\r\n // Inject $bind variables\r\n const { injectedCode, componentInjections, bindVarNames } =\r\n injectBindVariables(scriptContent, twoWayBindings);\r\n\r\n // Extract function names from the script content\r\n const functionRegex =\r\n /function\\s+(\\w+)|const\\s+(\\w+)\\s*=\\s*(?:\\([^)]*\\)|[\\w\\s]*)\\s*=>/g;\r\n const functionNames: string[] = [];\r\n let match;\r\n\r\n while ((match = functionRegex.exec(scriptContent)) !== null) {\r\n const functionName = match[1] || match[2];\r\n if (functionName) {\r\n functionNames.push(functionName);\r\n }\r\n }\r\n\r\n // Auto-attach detected functions\r\n // Wrap functions to bind them to component and maintain variable access\r\n const attachFunctions = functionNames\r\n .map(\r\n (name) =>\r\n `component.${name} = typeof ${name} !== 'undefined' ? ${name}.bind(component) : undefined;`\r\n )\r\n .join(\"\\n \");\r\n\r\n // Extract and auto-bind variables to state (only those used in template bindings or conditionals)\r\n const { stateBindings, boundVarNames } = extractStateBindings(\r\n scriptContent,\r\n bindings,\r\n conditionalVars\r\n );\r\n\r\n // Merge bindVarNames with boundVarNames for transformation\r\n const allBoundVars = new Set([...boundVarNames, ...bindVarNames]);\r\n\r\n const attachStateBindings = stateBindings.join(\"\\n \");\r\n\r\n // Transform the script to make bound variable assignments reactive\r\n const transformedContent = transformBoundAssignments(\r\n scriptContent,\r\n allBoundVars\r\n );\r\n\r\n // Create a wrapper that captures functions and variables in component scope\r\n const wrappedScript = `\r\n (function() {\r\n // Create component scope with direct access to state\r\n const component = this;\r\n const $state = component.state;\r\n \r\n // Define $bind variables on component object for event handler access\r\n ${componentInjections}\r\n \r\n // Provide framework utilities with $ prefix to avoid naming conflicts\r\n const $setState = (updates) => component.setState(updates);\r\n \r\n // Event bus methods for component communication\r\n const $emit = (eventName, data) => arguments[2].emit(eventName, data);\r\n const $listen = (eventName, callback) => {\r\n const unsubscribe = arguments[2].listen(eventName, callback);\r\n // Store unsubscribe function for cleanup on disconnect\r\n if (!component.__eventUnsubscribers) {\r\n component.__eventUnsubscribers = [];\r\n }\r\n component.__eventUnsubscribers.push(unsubscribe);\r\n return unsubscribe;\r\n };\r\n \r\n // Also attach to component for event handler access\r\n component.$emit = $emit;\r\n component.$listen = $listen;\r\n \r\n // Override querySelector/querySelectorAll to query within the component's host\r\n const host = arguments[1];\r\n const $querySelector = (selector) => host.querySelector(selector);\r\n const $querySelectorAll = (selector) => host.querySelectorAll(selector);\r\n \r\n // Execute script content within component scope so $bind variables are accessible\r\n with(component) {\r\n ${transformedContent}\r\n \r\n // Auto-bind variables to component state (e.g., const name = \"value\" → this.state.name = \"value\")\r\n ${attachStateBindings}\r\n \r\n // Auto-attach all detected functions to component for onclick access\r\n ${attachFunctions}\r\n }\r\n }).call(arguments[0], arguments[0], arguments[1], arguments[2])\r\n `;\r\n\r\n const executor = new Function(wrappedScript);\r\n executor(componentHost, host, eventBus);\r\n } catch (error) {\r\n console.error(\"Script execution failed:\", error);\r\n }\r\n};\r\n\r\n/**\r\n * Processes inline event handlers (onclick, onkeyup, oninput, etc.) to bind them to the component context.\r\n * Removes inline event attributes and converts them to proper event listeners\r\n * that have access to the component scope.\r\n * @param host - The host element or shadow root\r\n * @param componentHost - The component element\r\n */\r\nconst processEventHandlers = (\r\n host: HTMLElement | ShadowRoot,\r\n componentHost: HTMLElement\r\n): void => {\r\n // All standard DOM events that can be handled as attributes\r\n const eventTypes = [\r\n \"click\",\r\n \"dblclick\",\r\n \"mousedown\",\r\n \"mouseup\",\r\n \"mouseover\",\r\n \"mouseout\",\r\n \"mousemove\",\r\n \"mouseenter\",\r\n \"mouseleave\",\r\n \"keydown\",\r\n \"keyup\",\r\n \"keypress\",\r\n \"focus\",\r\n \"blur\",\r\n \"change\",\r\n \"input\",\r\n \"submit\",\r\n \"reset\",\r\n \"scroll\",\r\n \"resize\",\r\n \"load\",\r\n \"unload\",\r\n \"touchstart\",\r\n \"touchend\",\r\n \"touchmove\",\r\n \"touchcancel\",\r\n \"dragstart\",\r\n \"drag\",\r\n \"dragend\",\r\n \"dragenter\",\r\n \"dragover\",\r\n \"dragleave\",\r\n \"drop\",\r\n ];\r\n\r\n // Add a WeakSet to track processed elements\r\n const processedElements = new WeakSet<Element>();\r\n\r\n eventTypes.forEach((eventType) => {\r\n const attributeName = `on${eventType}`;\r\n const elements =\r\n host instanceof ShadowRoot\r\n ? host.querySelectorAll(`[${attributeName}]`)\r\n : componentHost.querySelectorAll(`[${attributeName}]`);\r\n\r\n elements.forEach((element) => {\r\n // Create a unique key for this element + event combination\r\n const key = `${attributeName}`;\r\n if ((element as any)[`__processed_${key}`]) return; // Skip if already processed\r\n\r\n const handlerCode = element.getAttribute(attributeName);\r\n if (handlerCode) {\r\n element.removeAttribute(attributeName);\r\n (element as HTMLElement).addEventListener(\r\n eventType,\r\n function (this: HTMLElement, event: Event) {\r\n const func = new Function(\r\n \"event\",\r\n \"component\",\r\n `\r\n with(component) {\r\n ${handlerCode}\r\n }\r\n `\r\n );\r\n func.call(this, event, componentHost);\r\n }\r\n );\r\n\r\n // Mark as processed for this specific event\r\n (element as any)[`__processed_${key}`] = true;\r\n }\r\n });\r\n });\r\n};\r\n\r\n/**\r\n * Transforms a module script to make variable bindings reactive.\r\n * Detects variables used in template bindings and wraps assignments to update component state.\r\n * @param scriptContent - The module script content\r\n * @param bindings - Template bindings to determine which variables should be reactive\r\n * @param componentId - The component ID for accessing the context\r\n * @returns Transformed script content\r\n */\r\nconst transformModuleScript = (\r\n scriptContent: string,\r\n bindings: BindingDescriptor[],\r\n componentId: string\r\n): string => {\r\n // Extract variable names used in bindings\r\n const bindingVarNames = new Set<string>();\r\n bindings.forEach((binding) => {\r\n binding.bindings.forEach((b) => {\r\n if (!b.isFunction) {\r\n const rootName = b.path[0];\r\n bindingVarNames.add(rootName);\r\n }\r\n });\r\n });\r\n\r\n if (bindingVarNames.size === 0) {\r\n return scriptContent; // No transformations needed\r\n }\r\n\r\n // Add helper code at the beginning to get component context\r\n const helperCode = `\r\n// Auto-generated: Get component context for reactive bindings\r\nconst __getContext = () => window.__ladrilloContexts?.get('${componentId}');\r\nconst __component = __getContext()?.element;\r\n`;\r\n\r\n let transformed = scriptContent;\r\n\r\n // Transform variable declarations to initialize state\r\n bindingVarNames.forEach((varName) => {\r\n // Match: let varName = value; or const varName = value;\r\n const declRegex = new RegExp(\r\n `(let|const|var)\\\\s+${varName}\\\\s*=\\\\s*([^;]+);`,\r\n \"g\"\r\n );\r\n\r\n transformed = transformed.replace(declRegex, (match, keyword, value) => {\r\n return `${keyword} ${varName} = ${value};\\nif (__component?.setState) __component.setState({ ${varName}: ${varName} });`;\r\n });\r\n\r\n // Transform assignments: varName = value\r\n // Make sure we don't match declarations (let/const/var) or object properties (obj.varName)\r\n const assignRegex = new RegExp(\r\n `(?<!let\\\\s|const\\\\s|var\\\\s|\\\\.)\\\\b${varName}\\\\s*=\\\\s*([^;]+);`,\r\n \"g\"\r\n );\r\n\r\n transformed = transformed.replace(assignRegex, (match, value) => {\r\n return `${varName} = ${value};\\nif (__component?.setState) __component.setState({ ${varName}: ${varName} });`;\r\n });\r\n\r\n // Transform increment/decrement operators\r\n const incDecRegex = new RegExp(`\\\\b${varName}(\\\\+\\\\+|\\\\-\\\\-)`, \"g\");\r\n\r\n transformed = transformed.replace(incDecRegex, (match, op) => {\r\n return `${varName}${op};\\nif (__component?.setState) __component.setState({ ${varName}: ${varName} });`;\r\n });\r\n\r\n // Transform compound assignments\r\n const compoundRegex = new RegExp(\r\n `\\\\b${varName}\\\\s*(\\\\+=|\\\\-=|\\\\*=|\\\\/=)\\\\s*([^;]+);`,\r\n \"g\"\r\n );\r\n\r\n transformed = transformed.replace(compoundRegex, (match, op, value) => {\r\n return `${varName} ${op} ${value};\\nif (__component?.setState) __component.setState({ ${varName}: ${varName} });`;\r\n });\r\n });\r\n\r\n return helperCode + transformed;\r\n};\r\n\r\nexport const loadScripts = async (\r\n host: HTMLElement | ShadowRoot,\r\n scripts: ScriptElement[],\r\n bindings: BindingDescriptor[],\r\n twoWayBindings: TwoWayBindingDescriptor[] = [],\r\n conditionalVars: Set<string> = new Set()\r\n) => {\r\n if (!scripts?.length) return;\r\n\r\n const componentHost = getHostElement(host);\r\n\r\n for (const scriptDefinition of scripts) {\r\n if (scriptDefinition.content) {\r\n processScript(\r\n scriptDefinition.content,\r\n bindings,\r\n twoWayBindings,\r\n host,\r\n componentHost,\r\n conditionalVars\r\n );\r\n }\r\n }\r\n\r\n // Process all event handlers to bind them to the component\r\n processEventHandlers(host, componentHost);\r\n};\r\n\r\n/**\r\n * Loads a global external script (e.g., from CDN) and returns a promise that resolves when loaded.\r\n * Prevents duplicate script tags by checking if the script is already loaded.\r\n * @param src - The script URL\r\n * @param type - The script type (e.g., 'module', 'text/javascript')\r\n * @returns Promise that resolves when the script is loaded\r\n */\r\nconst loadGlobalScript = (src: string, type: string | null): Promise<void> => {\r\n return new Promise((resolve, reject) => {\r\n // Check if script is already loaded and ready\r\n const existingScript = document.querySelector(\r\n `script[src=\"${src}\"]`\r\n ) as HTMLScriptElement;\r\n if (existingScript) {\r\n // If script already loaded, check if it's ready\r\n if (existingScript.dataset.loaded === \"true\") {\r\n resolve();\r\n return;\r\n }\r\n\r\n // If it's loading, wait for it\r\n existingScript.addEventListener(\"load\", () => resolve(), { once: true });\r\n existingScript.addEventListener(\r\n \"error\",\r\n () => reject(new Error(`Failed to load external script: ${src}`)),\r\n { once: true }\r\n );\r\n return;\r\n }\r\n\r\n const script = document.createElement(\"script\");\r\n script.src = src;\r\n if (type) {\r\n script.type = type;\r\n }\r\n\r\n script.onload = () => {\r\n script.dataset.loaded = \"true\";\r\n resolve();\r\n };\r\n script.onerror = () =>\r\n reject(new Error(`Failed to load external script: ${src}`));\r\n\r\n document.head.appendChild(script);\r\n });\r\n};\r\n\r\nexport const loadExternalScripts = async (\r\n host: HTMLElement | ShadowRoot,\r\n externalScripts: ExternalScriptElement[],\r\n bindings: BindingDescriptor[],\r\n twoWayBindings: TwoWayBindingDescriptor[] = [],\r\n conditionalVars: Set<string> = new Set(),\r\n componentSourcePath?: string\r\n) => {\r\n const componentHost = getHostElement(host);\r\n\r\n for (const s of externalScripts) {\r\n // Resolve script URL relative to the component's HTML file location\r\n // Convert relative path to absolute URL if needed\r\n let baseURL: string;\r\n if (componentSourcePath) {\r\n // If it's already an absolute URL, use it directly\r\n if (\r\n componentSourcePath.startsWith(\"http://\") ||\r\n componentSourcePath.startsWith(\"https://\")\r\n ) {\r\n baseURL = componentSourcePath;\r\n } else {\r\n // Convert relative path to absolute URL using window.location\r\n // Ensure the base URL ends with the component path including filename\r\n // so that relative paths like '../js/app.js' resolve correctly\r\n const fullComponentURL = new URL(\r\n componentSourcePath,\r\n window.location.href\r\n ).href;\r\n baseURL = fullComponentURL;\r\n }\r\n } else {\r\n baseURL = window.location.href;\r\n }\r\n\r\n const scriptURL = new URL(s.src, baseURL).href;\r\n\r\n if (s.external) {\r\n // Inject script tag to document for external CDN scripts (e.g., highlight.js, three.js)\r\n // These scripts load globally and don't need component-specific processing\r\n await loadGlobalScript(scriptURL, s.type);\r\n } else if (s.type === \"module\") {\r\n // For module scripts, load them normally as ES modules\r\n // The bind attribute is a signal that the user wants reactive bindings,\r\n // but ES modules can't be transformed the same way as regular scripts\r\n // So we store the context and let the module use helper functions\r\n const componentId = componentHost.tagName.toLowerCase();\r\n\r\n if (!(window as any).__ladrilloContexts) {\r\n (window as any).__ladrilloContexts = new Map();\r\n }\r\n\r\n // Store the component context so the module can access it\r\n (window as any).__ladrilloContexts.set(componentId, {\r\n host,\r\n shadowRoot: host instanceof ShadowRoot ? host : null,\r\n element: componentHost,\r\n state: (componentHost as any).state,\r\n setState: (componentHost as any).setState?.bind(componentHost),\r\n });\r\n\r\n // Load the module script normally\r\n const script = document.createElement(\"script\");\r\n script.type = \"module\";\r\n script.src = scriptURL;\r\n script.setAttribute(\"data-component\", componentId);\r\n document.head.appendChild(script);\r\n } else {\r\n // Fetch and process local non-module scripts through reactive processing\r\n await fetch(scriptURL)\r\n .then((response) => {\r\n if (!response.ok) {\r\n throw new Error(`HTTP ${response.status}: ${response.statusText}`);\r\n }\r\n const contentType = response.headers.get(\"content-type\");\r\n if (\r\n contentType &&\r\n !contentType.includes(\"javascript\") &&\r\n !contentType.includes(\"text/plain\")\r\n ) {\r\n throw new Error(`Expected JavaScript but got ${contentType}`);\r\n }\r\n return response.text();\r\n })\r\n .then((scriptContent) => {\r\n // Reuse the same processing logic as inline scripts\r\n processScript(\r\n scriptContent,\r\n bindings,\r\n twoWayBindings,\r\n host,\r\n componentHost,\r\n conditionalVars\r\n );\r\n })\r\n .catch((error) => {\r\n console.error(`Failed to load external script: ${s.src}`, error);\r\n });\r\n }\r\n }\r\n\r\n // Process all event handlers to bind them to the component\r\n processEventHandlers(host, componentHost);\r\n};\r\n","import {\r\n BindingDescriptor,\r\n LadrillosComponent,\r\n TwoWayBindingDescriptor,\r\n ConditionalDescriptor,\r\n LoopDescriptor,\r\n} from \"../types/LadrilloTypes\";\r\nimport { logger } from \"../utils/logger\";\r\nimport { loadStyles } from \"./css/cssParser\";\r\nimport {\r\n loadTemplate,\r\n extractConditionalVariables,\r\n extractLoopVariables,\r\n} from \"./html/htmlparser\";\r\nimport {\r\n renderBindings,\r\n setValue,\r\n renderConditionals,\r\n renderLoops,\r\n} from \"./html/htmlRenderer\";\r\nimport { loadExternalScripts, loadScripts } from \"./js/scriptParser\";\r\n\r\nexport const defineWebComponent = (\r\n component: LadrillosComponent,\r\n useShadowDOM: boolean\r\n) => {\r\n const { tagName, template, scripts, externalScripts, styles, sourcePath } =\r\n component;\r\n\r\n class ComponentElement extends HTMLElement {\r\n state: any;\r\n #bindings: BindingDescriptor[] = [];\r\n #twoWayBindings: TwoWayBindingDescriptor[] = [];\r\n #conditionals: ConditionalDescriptor[][] = [];\r\n #loops: LoopDescriptor[] = [];\r\n #twoWayBindingCleanups: Array<() => void> = [];\r\n #sourcePath: string | undefined = sourcePath;\r\n\r\n /**\r\n * Creates a deep reactive proxy that tracks nested object/array mutations\r\n * @param target - The object or array to make reactive\r\n * @param callback - Function to call when any nested property changes\r\n */\r\n #createDeepProxy(target: any, callback: () => void): any {\r\n // Don't proxy primitives or null\r\n if (target === null || typeof target !== \"object\") {\r\n return target;\r\n }\r\n\r\n // Don't proxy DOM elements or other complex objects\r\n if (target instanceof HTMLElement || target instanceof Node) {\r\n return target;\r\n }\r\n\r\n return new Proxy(target, {\r\n get: (obj, prop) => {\r\n const value = obj[prop];\r\n // Recursively proxy nested objects/arrays\r\n if (value !== null && typeof value === \"object\") {\r\n return this.#createDeepProxy(value, callback);\r\n }\r\n return value;\r\n },\r\n set: (obj, prop, value) => {\r\n const prev = obj[prop];\r\n // Skip if value hasn't changed\r\n if (Object.is(prev, value)) return true;\r\n\r\n obj[prop] = value;\r\n callback(); // Trigger re-render\r\n return true;\r\n },\r\n });\r\n }\r\n\r\n constructor() {\r\n super();\r\n if (useShadowDOM) this.attachShadow({ mode: \"open\" });\r\n\r\n const internalState: any = {};\r\n\r\n // Callback for triggering re-renders\r\n const triggerUpdate = () => {\r\n renderBindings(this.#bindings, this.state, this);\r\n renderConditionals(this.#conditionals, this.state, this);\r\n renderLoops(this.#loops, this.state, this);\r\n this.#updateTwoWayBindings();\r\n };\r\n\r\n // Wrap state in a deep reactive Proxy to detect all nested changes\r\n this.state = new Proxy(internalState, {\r\n get: (target, prop) => {\r\n return target[prop as keyof typeof target];\r\n },\r\n set: (target, prop, value) => {\r\n const prev = target[prop as keyof typeof target];\r\n // Skip update if value hasn't changed (avoids unnecessary re-renders)\r\n if (Object.is(prev, value)) return true;\r\n\r\n // Wrap objects/arrays in deep proxies for nested reactivity\r\n if (value !== null && typeof value === \"object\") {\r\n target[prop as keyof typeof target] = this.#createDeepProxy(\r\n value,\r\n triggerUpdate\r\n );\r\n } else {\r\n target[prop as keyof typeof target] = value;\r\n }\r\n\r\n // Auto-create property descriptor on component for direct access in with() scope\r\n if (!Object.getOwnPropertyDescriptor(this, prop)) {\r\n Object.defineProperty(this, prop, {\r\n get() {\r\n return this.state[prop];\r\n },\r\n set(val) {\r\n this.state[prop] = val;\r\n },\r\n enumerable: true,\r\n configurable: true,\r\n });\r\n }\r\n\r\n // Re-render all bindings with the updated state\r\n triggerUpdate();\r\n return true;\r\n },\r\n });\r\n }\r\n /**\r\n * Updates component state with one or more key-value pairs\r\n * @param updates - Object containing state updates\r\n * @example\r\n * component.setState({ count: 5, name: 'John' })\r\n */\r\n setState(updates: Record<string, any>): void {\r\n Object.assign(this.state, updates);\r\n }\r\n\r\n static #parseAttributeValue(raw: string | null) {\r\n if (raw === null || raw === \"\") return null;\r\n if (raw === \"undefined\") return undefined;\r\n try {\r\n return JSON.parse(raw);\r\n } catch {\r\n return raw;\r\n }\r\n }\r\n\r\n // Invoked when element is added to the DOM\r\n async connectedCallback() {\r\n const host = useShadowDOM ? this.shadowRoot! : this;\r\n\r\n // Parse template and collect all data binding locations\r\n const { bindings, twoWayBindings, conditionals, loops } = loadTemplate(\r\n host,\r\n template\r\n );\r\n this.#bindings = bindings;\r\n this.#twoWayBindings = twoWayBindings;\r\n this.#conditionals = conditionals;\r\n this.#loops = loops;\r\n\r\n // Extract variables used in conditional expressions and loops\r\n const conditionalVars = extractConditionalVariables(conditionals);\r\n const loopVars = extractLoopVariables(loops);\r\n\r\n // Inject component styles\r\n loadStyles(host, styles, useShadowDOM);\r\n\r\n // Sync initial state from HTML attributes (e.g., <my-component name=\"value\">)\r\n this._initializeStateFromAttributes();\r\n\r\n // Setup two-way bindings\r\n this._setupTwoWayBindings();\r\n\r\n // Load external scripts first (e.g., CDN libraries like highlight.js)\r\n // so they're available when inline scripts execute\r\n await loadExternalScripts(\r\n host,\r\n externalScripts,\r\n this.#bindings,\r\n this.#twoWayBindings,\r\n new Set([...conditionalVars, ...loopVars]),\r\n this.#sourcePath\r\n );\r\n\r\n // Execute component scripts (event handlers, methods, etc.)\r\n // Pass conditional variables and loop variables so they get mapped to state\r\n await loadScripts(\r\n host,\r\n scripts,\r\n this.#bindings,\r\n this.#twoWayBindings,\r\n new Set([...conditionalVars, ...loopVars])\r\n );\r\n\r\n // Perform initial render with current state values (after scripts are ready)\r\n renderBindings(this.#bindings, this.state, this);\r\n renderConditionals(this.#conditionals, this.state, this);\r\n renderLoops(this.#loops, this.state, this);\r\n\r\n // Set up MutationObserver to watch for attribute changes\r\n this._setupAttributeObserver();\r\n }\r\n\r\n // Invoked when element is removed from the DOM\r\n disconnectedCallback() {\r\n // Clean up MutationObserver\r\n if ((this as any).__attributeObserver) {\r\n (this as any).__attributeObserver.disconnect();\r\n (this as any).__attributeObserver = null;\r\n }\r\n\r\n // Clean up two-way binding event listeners\r\n this.#twoWayBindingCleanups.forEach((cleanup) => {\r\n try {\r\n cleanup();\r\n } catch (error) {\r\n console.error(\"Error cleaning up two-way binding:\", error);\r\n }\r\n });\r\n this.#twoWayBindingCleanups = [];\r\n\r\n // Clean up EventBus subscriptions\r\n const unsubscribers = (this as any).__eventUnsubscribers;\r\n if (unsubscribers && Array.isArray(unsubscribers)) {\r\n unsubscribers.forEach((unsub: () => void) => {\r\n try {\r\n unsub();\r\n } catch (error) {\r\n console.error(\"Error unsubscribing from event:\", error);\r\n }\r\n });\r\n (this as any).__eventUnsubscribers = [];\r\n }\r\n }\r\n\r\n // Set up observer to watch for attribute changes\r\n _setupAttributeObserver() {\r\n const observer = new MutationObserver((mutations) => {\r\n mutations.forEach((mutation) => {\r\n if (mutation.type === \"attributes\" && mutation.attributeName) {\r\n const newValue = this.getAttribute(mutation.attributeName);\r\n this._handleAttributeChange(mutation.attributeName, newValue);\r\n }\r\n });\r\n });\r\n\r\n observer.observe(this, {\r\n attributes: true,\r\n attributeOldValue: true,\r\n });\r\n\r\n (this as any).__attributeObserver = observer;\r\n }\r\n\r\n // initializes the state from the attributes\r\n _initializeStateFromAttributes() {\r\n this.getAttributeNames().forEach((name) => {\r\n const raw = this.getAttribute(name);\r\n this._handleAttributeChange(name, raw);\r\n });\r\n }\r\n\r\n // Invoked when attributes are changed.\r\n _handleAttributeChange(name: string, raw: string | null) {\r\n if (name) {\r\n // remove \"this.state.\" prefix if it exists\r\n const STATE_PREFIX = \"this.state.\";\r\n if (name.startsWith(STATE_PREFIX)) {\r\n name = name.slice(STATE_PREFIX.length);\r\n }\r\n }\r\n const value = ComponentElement.#parseAttributeValue(raw);\r\n this.state[name] = value;\r\n }\r\n\r\n // Setup two-way data bindings for input elements with $bind\r\n _setupTwoWayBindings() {\r\n this.#twoWayBindings.forEach(\r\n ({ element, path, raw, isContentEditable, initialValue }) => {\r\n // Initialize state property if it doesn't exist, using stored initial content\r\n const currentValue = this._getNestedValue(path);\r\n\r\n if (currentValue === undefined) {\r\n const content = initialValue || \"\";\r\n setValue(this.state, path, content);\r\n }\r\n\r\n if (isContentEditable) {\r\n // Handle contenteditable elements\r\n const contentEditableEl = element as HTMLElement;\r\n\r\n // Initial sync from state to element\r\n contentEditableEl.textContent = this._getNestedValue(path) ?? \"\";\r\n\r\n // Listen for input changes and update state\r\n const handleInput = (e: Event) => {\r\n const target = e.target as HTMLElement;\r\n const newValue = target.textContent || \"\";\r\n\r\n // Update state using setValue to handle nested paths\r\n setValue(this.state, path, newValue);\r\n };\r\n\r\n contentEditableEl.addEventListener(\"input\", handleInput);\r\n\r\n // Store cleanup function\r\n const cleanup = () => {\r\n contentEditableEl.removeEventListener(\"input\", handleInput);\r\n };\r\n this.#twoWayBindingCleanups.push(cleanup);\r\n } else {\r\n // Handle form input elements\r\n const inputEl = element as\r\n | HTMLInputElement\r\n | HTMLTextAreaElement\r\n | HTMLSelectElement;\r\n\r\n // Check if this is a checkbox or radio button\r\n const isCheckbox =\r\n inputEl instanceof HTMLInputElement &&\r\n inputEl.type === \"checkbox\";\r\n const isRadio =\r\n inputEl instanceof HTMLInputElement && inputEl.type === \"radio\";\r\n\r\n // Initial sync from state to element\r\n if (isCheckbox) {\r\n // For checkboxes, use 'checked' property\r\n inputEl.checked = Boolean(this._getNestedValue(path));\r\n } else {\r\n // For other inputs, use 'value' property\r\n inputEl.value = this._getNestedValue(path) ?? \"\";\r\n }\r\n\r\n // Listen for input changes and update state\r\n const handleInput = (e: Event) => {\r\n const target = e.target as\r\n | HTMLInputElement\r\n | HTMLTextAreaElement\r\n | HTMLSelectElement;\r\n\r\n let newValue: any;\r\n\r\n if (\r\n target instanceof HTMLInputElement &&\r\n target.type === \"checkbox\"\r\n ) {\r\n // For checkboxes, get the 'checked' property\r\n newValue = target.checked;\r\n } else if (\r\n target instanceof HTMLInputElement &&\r\n target.type === \"radio\"\r\n ) {\r\n // For radio buttons, get the 'value' property\r\n newValue = target.value;\r\n } else {\r\n // For other inputs, get the 'value' property\r\n newValue = target.value;\r\n }\r\n\r\n // Update state using setValue to handle nested paths\r\n setValue(this.state, path, newValue);\r\n };\r\n\r\n inputEl.addEventListener(\"input\", handleInput);\r\n\r\n // Store cleanup function for 'input' listener\r\n const cleanupInput = () => {\r\n inputEl.removeEventListener(\"input\", handleInput);\r\n };\r\n this.#twoWayBindingCleanups.push(cleanupInput);\r\n\r\n // For select and certain input types, also listen to 'change'\r\n if (\r\n inputEl instanceof HTMLSelectElement ||\r\n (inputEl instanceof HTMLInputElement &&\r\n [\"checkbox\", \"radio\", \"file\"].includes(inputEl.type))\r\n ) {\r\n inputEl.addEventListener(\"change\", handleInput);\r\n\r\n // Store cleanup function for 'change' listener\r\n const cleanupChange = () => {\r\n inputEl.removeEventListener(\"change\", handleInput);\r\n };\r\n this.#twoWayBindingCleanups.push(cleanupChange);\r\n }\r\n }\r\n }\r\n );\r\n }\r\n\r\n // Update two-way bound elements when state changes\r\n #updateTwoWayBindings() {\r\n this.#twoWayBindings.forEach(({ element, path, isContentEditable }) => {\r\n const value = this._getNestedValue(path);\r\n\r\n if (isContentEditable) {\r\n const contentEditableEl = element as HTMLElement;\r\n if (contentEditableEl.textContent !== value) {\r\n contentEditableEl.textContent = value ?? \"\";\r\n }\r\n } else {\r\n const inputEl = element as\r\n | HTMLInputElement\r\n | HTMLTextAreaElement\r\n | HTMLSelectElement;\r\n\r\n // Handle checkboxes differently\r\n if (\r\n inputEl instanceof HTMLInputElement &&\r\n inputEl.type === \"checkbox\"\r\n ) {\r\n const boolValue = Boolean(value);\r\n if (inputEl.checked !== boolValue) {\r\n inputEl.checked = boolValue;\r\n }\r\n } else {\r\n // For other inputs, use value property\r\n if (inputEl.value !== value) {\r\n inputEl.value = value ?? \"\";\r\n }\r\n }\r\n }\r\n });\r\n }\r\n\r\n // Helper to get nested value from state\r\n _getNestedValue(path: string[]): any {\r\n return path.reduce((acc, key) => {\r\n return acc?.[key];\r\n }, this.state);\r\n }\r\n }\r\n\r\n customElements.define(tagName, ComponentElement);\r\n logger.log(`Web component defined: <${tagName}></${tagName}>`);\r\n};\r\n"],"names":["loadStyles","target","cssText","useShadowDOM","styleEl","loadTemplate","host","template","bindings","scanBindings","twoWayBindings","scanTwoWayBindings","conditionals","scanConditionals","loops","scanLoops","extractFunctionArguments","functionCall","variables","argsMatch","argsString","arg","identifierMatch","walker","node","isInsideLoopElement","current","matches","REGEX_PATTERNS","original","nodeBindings","match","raw","isFunction","isExpression","path","p","functionArgs","el","attr","attrBindings","bindValue","_a","allConditionals","processedElements","element","group","currentElement","hasIf","hasElseIf","hasElse","type","condition","placeholder","parent","nextSibling","descriptor","next","desc","extractConditionalVariables","conditionalGroups","identifierRegex","keywords","rootVar","forExpression","keyAttribute","itemName","indexName","arrayName","extractLoopVariables","loop","functionCache","maxFunctionCacheSize","getCachedFunction","expression","cached","compiledFunc","firstKey","getValue","ctx","acc","segment","setValue","value","lastKey","parentPath","renderBindings","context","component","binding","result","evalFunc","scope","__spreadValues","error","replacement","textNode","parentElement","isHTMLContent","evaluateCondition","processedCondition","processElementEventHandlers","eventTypes","eventType","attributeName","handlerCode","key","event","renderConditionals","conditionMet","originalParent","shouldRender","isInDOM","renderLoops","renderedElements","arrayData","item","index","clone","scopedContext","__spreadProps","processClonedElement","insertAfter","getHostElement","injectBindVariables","scriptContent","bindVarNames","componentInjections","varName","extractStateBindings","conditionalVars","stateBindings","bindingNames","b","rootName","variableRegex","transformBoundAssignments","boundVarNames","transformed","propertyWriteRegex","propertyReadRegex","incrementRegex","op","compoundRegex","assignmentRegex","processScript","componentHost","injectedCode","functionRegex","functionNames","functionName","attachFunctions","name","allBoundVars","attachStateBindings","transformedContent","wrappedScript","eventBus","processEventHandlers","loadScripts","_0","_1","_2","_3","__async","scripts","scriptDefinition","loadGlobalScript","src","resolve","reject","existingScript","script","loadExternalScripts","externalScripts","componentSourcePath","s","baseURL","scriptURL","componentId","response","contentType","defineWebComponent","tagName","styles","sourcePath","_ComponentElement","__privateAdd","_ComponentElement_instances","_bindings","_twoWayBindings","_conditionals","_loops","_twoWayBindingCleanups","_sourcePath","internalState","triggerUpdate","__privateGet","__privateMethod","updateTwoWayBindings_fn","prop","prev","createDeepProxy_fn","val","updates","__privateSet","loopVars","cleanup","unsubscribers","unsub","observer","mutations","mutation","newValue","STATE_PREFIX","_ComponentElement_static","parseAttributeValue_fn","isContentEditable","initialValue","content","contentEditableEl","handleInput","e","inputEl","isCheckbox","_b","cleanupInput","cleanupChange","callback","obj","boolValue","ComponentElement","logger"],"mappings":"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"}