Last active
January 25, 2023 08:43
-
-
Save groverburger/24e267a8f0641f8ff19262d1161fbc3d to your computer and use it in GitHub Desktop.
Simple and fast immediate mode HTML gui rendering
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
let renderStack | |
let cache | |
function htmlify (what) { | |
if (!Array.isArray(what)) { | |
return what | |
} | |
const tagDef = typeof what[0] === 'string' ? what[0] : what[0].tag | |
const [tag, ...modifiers] = tagDef.split(' ') | |
const parser = document.createElement('div') | |
parser.innerHTML = `<${tag} ${modifiers.join(' ')}></${tag}>` | |
const parent = parser.firstElementChild | |
if (typeof what[0] !== 'string') { | |
for (const [key, value] of Object.entries(what[0])) { | |
if (key === 'tag') { continue } | |
parent[key] = value | |
} | |
} | |
what.slice(1).map(htmlify).forEach(element => { | |
if (element instanceof HTMLElement) { | |
parent.appendChild(element) | |
} else if (element !== undefined && element !== null) { | |
parent.append(element) | |
} | |
}) | |
return parent | |
} | |
export function createComponent (func) { | |
return (...args) => { | |
if (!cache[renderStack]) { | |
cache[renderStack] = { | |
prevArgs: '', | |
element: null | |
} | |
} | |
const myCache = cache[renderStack] | |
renderStack.push(1) | |
const newArgs = JSON.stringify(args) | |
if (newArgs !== myCache.prevArgs || !myCache.element) { | |
myCache.prevArgs = newArgs | |
myCache.element = htmlify(func(...args)) | |
} | |
renderStack.pop() | |
renderStack[renderStack.length - 1] += 1 | |
return myCache.element | |
} | |
} | |
export class Renderer { | |
renderStack = [] | |
cache = {} | |
render (element, component, ...args) { | |
this.renderStack = [0] | |
renderStack = this.renderStack | |
cache = this.cache | |
const result = component(...args) | |
if (!result) { | |
element.innerHTML = '' | |
} else if (result.outerHTML !== element.innerHTML) { | |
element.innerHTML = '' | |
element.appendChild(result) | |
} | |
return result | |
} | |
clear () { | |
this.renderStack = [] | |
this.cache = {} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment