class Reactive { constructor(obj) { this.contents = obj; this.objs = [obj] this.listeners = {}; this.makeReactive(obj); } makeReactive(obj) { Object.keys(obj).forEach(prop => this.makePropReactive(obj, prop)); } makePropReactive(obj, key) { let value = obj[key]; // Gotta be careful with this here const that = this; Object.defineProperty(obj, key, { get() { return value; }, set(newValue) { value = newValue; that.notify(key) } }) } listen(prop, handler) { if (!this.listeners[prop]) this.listeners[prop] = []; this.listeners[prop].push(handler); } notify(prop) { this.listeners[prop].forEach(listener => listener(this.contents[prop])); } } const compileToString = (template) => { const ast = parse(template); let fnStr = `\`\``; ast.map(t => { // checking to see if it is an interpolation if (t.startsWith("{") && t.endsWith("}")) { // append it to fnStr const uuid = t.split(/{|}/).filter(Boolean)[0].trim().split("").map(c => c.charCodeAt(0).toString(16).padStart(2, "0")).join(""); fnStr = fnStr.substring(0, fnStr.length - 2) + ` data-token-${uuid}>\``; fnStr += `+appState.contents.${t.split(/{|}/).filter(Boolean)[0].trim()}`; } else { // append the string to the fnStr fnStr += `+\`${t}\``; } }); return fnStr; } var parse = (template) => { let result = /{(.*?)}/g.exec(template); const arr = []; let firstPos; while (result) { firstPos = result.index; if (firstPos !== 0) { arr.push(template.substring(0, firstPos)); template = template.slice(firstPos); } arr.push(result[0]); template = template.slice(result[0].length); result = /{(.*?)}/g.exec(template); } if (template) arr.push(template); return arr; } const compile = (template) => { return new Function("data", "return " + compileToString(template)) } const virtualDomBody = `

{count}


{count}

` const appState = new Reactive({ count: 0, }); // run code to compile the templated virtualDomBody into a play body const templatedVirtualDom = eval(compileToString(virtualDomBody)) // equivalent to mounted() on svelte or vue window.addEventListener('load', () => { const documentBody = document.getElementById('app') documentBody.innerHTML = templatedVirtualDom Object.keys(appState.contents).forEach((e) => { const querySelector = "data-token-" + e.split("").map(c => c.charCodeAt(0).toString(16).padStart(2, "0")).join("") const listeningElements = document.querySelectorAll(`[${querySelector}]`) listeningElements.forEach((elm) => { appState.listen(e, (change) => elm.textContent = change); }) }) let elms = documentBody.querySelectorAll('*[d-click]') elms.forEach((e) => { const clickFunction = new Function(e.getAttribute("d-click")) e.addEventListener('click', () => { clickFunction() }) }) })