// JQHTML v2 Runtime - Processes instruction arrays from compiled templates // Minimal implementation focused on MVP functionality /// // Process instruction array into DOM elements export function process_instructions(instructions, component) { const fragment = document.createDocumentFragment(); const stack = []; let current = fragment; for (const instruction of instructions) { // Plain text if (typeof instruction === 'string') { const text = document.createTextNode(instruction); current.appendChild(text); continue; } // Tag instruction: {tag: [name, attrs, selfClosing]} if (instruction.tag) { const [tag_name, attrs, self_closing] = instruction.tag; const element = document.createElement(tag_name); // Set attributes for (const [key, value] of Object.entries(attrs || {})) { element.setAttribute(key, String(value)); } current.appendChild(element); // Push to stack if not self-closing if (!self_closing) { stack.push(current); current = element; } continue; } // Component instruction: {comp: [name, props]} if (instruction.comp) { const [comp_name, props] = instruction.comp; // Create placeholder div for component const placeholder = document.createElement('div'); placeholder.setAttribute('data-component', comp_name); placeholder.setAttribute('data-props', JSON.stringify(props || {})); placeholder.setAttribute('data-state', 'uninitialized'); placeholder.className = 'jqhtml-component'; current.appendChild(placeholder); // TODO: In future, instantiate component here continue; } // Slot instruction: {slot: [name, props, renderFn]} if (instruction.slot) { const [slot_name, props, render_fn] = instruction.slot; // Execute slot render function if provided if (render_fn && typeof render_fn === 'function') { const slot_context = { ...props }; const [slot_output] = render_fn.call(component, slot_context); // Process slot output recursively const slot_dom = process_instructions(slot_output, component); slot_dom.each(function () { current.appendChild(this); }); } continue; } // Closing tag (when we see a string like "") if (typeof instruction === 'string' && instruction.match(/^<\//)) { if (stack.length > 0) { current = stack.pop(); } } } return $(fragment.childNodes); } // HTML escape function required by generated code export function html(str) { if (str == null) return ''; const div = document.createElement('div'); div.textContent = String(str); return div.innerHTML; } // Component template registry const template_registry = new Map(); // Register a compiled template export function register_template(name, render_fn) { template_registry.set(name, render_fn); } // Get a compiled template export function get_template(name) { return template_registry.get(name); } // Create component with template export function create_templated_component(ComponentClass, template_name, args = {}, element) { const template = get_template(template_name); if (!template) { throw new Error(`Template not found: ${template_name}`); } // Create component instance - element first, then args const component = new ComponentClass(element, args); // Override on_render to use template component.on_render = async function () { // Call template render function const [instructions] = template.call(this, ComponentClass, this.data, this.args, {}); // Process instructions into DOM const rendered = process_instructions(instructions, this); // Clear and append this.$.empty().append(rendered); }; return component; } //# sourceMappingURL=runtime.js.map