dreamlandjs/html.js
CoolElectronics 991b9ca535
bump semver
2024-02-12 16:59:16 -05:00

65 lines
1.8 KiB
JavaScript

Object.assign(window, { html });
export function html(strings, ...values) {
let flattened = "";
let markers = {};
for (const i in strings) {
let string = strings[i];
let value = values[i];
flattened += string;
if (i < values.length) {
let dupe = Object.values(markers).findIndex(v => v == value);
if (dupe !== -1) {
flattened += Object.keys(markers)[dupe];
} else {
let marker = "m" + Array(16).fill(0).map(() => Math.floor(Math.random() * 16).toString(16)).join("");
markers[marker] = value;
flattened += marker;
}
}
}
let dom = new DOMParser().parseFromString(flattened, "text/html");
if (dom.body.children.length !== 1)
throw "html builder needs exactly one child";
function wraph(elm) {
let nodename = elm.nodeName.toLowerCase();
if (nodename === "#text")
return elm.textContent;
if (nodename in markers)
nodename = markers[nodename];
let children = [...elm.childNodes].map(wraph);
for (let i = 0; i < children.length; i++) {
let text = children[i];
if (typeof text !== "string") continue;
for (const [marker, value] of Object.entries(markers)) {
if (!text) break;
if (!text.includes(marker)) continue;
let before;
[before, text] = text.split(marker);
children = [
...children.slice(0, i),
before,
value,
text,
...children.slice(i + 1)
];
i += 2;
}
}
let attributes = {};
for (const attr of [...elm.attributes]) {
let val = attr.nodeValue;
if (val in markers)
val = markers[val];
attributes[attr.name] = val;
}
return h(nodename, attributes, children);
}
return wraph(dom.body.children[0]);
}