Fix bin/publish: use correct .env path for rspade_system Fix bin/publish script: prevent grep exit code 1 from terminating script 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
106 lines
4.2 KiB
JavaScript
Executable File
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
|