Files
rspade_system/node_modules/@jqhtml/parser/dist/runtime.js
root 2899ae826b Update jqhtml packages to latest versions
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-23 07:45:41 +00:00

106 lines
4.2 KiB
JavaScript
Executable File

// JQHTML v2 Runtime - Processes instruction arrays from compiled templates
// Minimal implementation focused on MVP functionality
/// <reference path="./types.d.ts" />
// 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 "</div>")
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