import type { TemplateChildNode, ElementNode, DirectiveNode, JsxContext } from "../types"; import { escapeJsxText, unwrapExpression } from "./utils"; import { processConditionalChain, processVFor, findDirective } from "./control-flow"; import { processSlot, processSlotRaw, processSlotContent, formatSlotEntries } from "./slots"; import { generateAttributes, formatAttributes } from "./attributes"; import { processDirective } from "./directives"; import { SELF_CLOSING_TAGS, VUE_BUILTINS } from "./utils"; /** * Walk an array of template child nodes and produce JSX string output. * This is the main recursive walker that orchestrates all template modules. */ export function walkChildren(children: TemplateChildNode[], ctx: JsxContext): string { const parts: string[] = []; let i = 0; while (i < children.length) { const child = children[i]; switch (child.type) { case 2: { // TEXT const text = (child as any).content as string; if (text.trim()) { parts.push(escapeJsxText(text)); } else if (!text.includes("\n")) { // Preserve inline whitespace parts.push(" "); } i++; break; } case 5: { // INTERPOLATION const expr = unwrapExpression((child as any).content, ctx); parts.push(`{${expr}}`); i++; break; } case 3: { // COMMENT parts.push(`{/* ${(child as any).content} */}`); i++; break; } case 1: { // ELEMENT const el = child as ElementNode; const result = processElementNode(el, children, i, ctx); parts.push(result.jsx); i += result.consumed; break; } default: i++; break; } } return parts.join(""); } interface ElementResult { jsx: string; consumed: number; } /** * Process an element node, handling directives, slots, and control flow. */ function processElementNode( node: ElementNode, siblings: TemplateChildNode[], index: number, ctx: JsxContext, ): ElementResult { // 1. Check for v-if → process conditional chain across siblings (before slot/v-for) const vIf = findDirective(node, "if"); if (vIf) { const result = processConditionalChain(siblings, index, ctx, renderFullElement); return result; } // 2. Handle elements if (node.tag === "slot") { const jsx = processSlot(node, ctx, renderChildrenForSlot); return { jsx, consumed: 1 }; } // 3. Check for v-for (wraps everything, takes priority) const vFor = findDirective(node, "for"); if (vFor) { const jsx = processVFor(node, ctx, renderFullElement); return { jsx, consumed: 1 }; } // 4. Regular element rendering const jsx = renderFullElement(node, ctx); return { jsx, consumed: 1 }; } /** * Render a full element with all directives, events, and slot content processing. * This is the "enhanced" version of generateElement that integrates all modules. */ function renderFullElement(node: ElementNode, ctx: JsxContext): string { const tag = node.tag; // elements — return raw expression without {}, since caller adds wrapping if (tag === "slot") { return processSlotRaw(node, ctx, renderChildrenForSlot); } //