lightview
Version:
A reactive UI library with features of Bau, Juris, and HTMX plus safe LLM UI generation
83 lines (77 loc) • 3.15 kB
HTML
<html>
<script>
const oDOM = (odom, options, script = document.currentScript) => {
const type = typeof odom;
if (type === 'string') {
odom = JSON.parse(odom);
}
const dom = odomToDOM(odom, { ...(options || {}), wasString: type === 'string' });
if (options) {
let { target = script, location = 'outerHTML' } = options;
location = location.toLowerCase();
if (location === 'outerhtml') target.replaceWith(dom);
else if (location === 'innerhtml') { target.replaceChildren(dom) }
else if (location === 'beforebegin') { target.insertAdjacentElement('beforebegin', dom) }
else if (location === 'afterbegin') { target.insertAdjacentElement('afterbegin', dom) }
else if (location === 'beforeend') { target.insertAdjacentElement('beforeend', dom) }
else if (location === 'afterend') { target.insertAdjacentElement('afterend', dom) }
}
return dom;
}
function odomToDOM(onode, { wasString, unsafe }) {
if (typeof onode !== 'object' || onode === null) {
return document.createTextNode(onode);
}
const tag = Object.keys(onode)[0];
const el = document.createElement(tag);
const content = onode[tag];
if (typeof content === 'object' && content !== null && !Array.isArray(content)) {
for (const key in content) {
const value = content[key];
if (key === 'children') {
el.append(...value.map(odomToDOM));
} else if (key === 'class') {
el.className = value;
} else if (typeof value === 'object' && !Array.isArray(value)) {
// Nested shorthand tag
const child = {};
child[key] = content[key];
el.append(odomToDOM(child));
} else if (Array.isArray(content[key])) {
// Property with array value (e.g., children shorthand)
el.append(...content[key].map(odomToDOM));
} else if (key.startsWith('on')) {
if (typeof value === "string"(!wasString || unsafe)) {
try {
value = new Function("event", value);
} catch (e) {
}
}
el[key] = value;
} else {
el.setAttribute(key, value);
}
}
} else {
if (Array.isArray(content)) {
el.append(...content.map(odomToDOM));
} else {
el.append(odomToDOM(content));
}
}
return el;
}
</script>
<body>
<script>
oDOM({
div: {
onclick: () => alert('Hello World'),
children: [
"Hello World"
]
}
}, {})
</script>
</body>
</html>