Skip to content

Instantly share code, notes, and snippets.

@tomhodgins
Created April 1, 2020 00:46
Show Gist options
  • Save tomhodgins/a535016fd5cd10520672175946a1566f to your computer and use it in GitHub Desktop.
Save tomhodgins/a535016fd5cd10520672175946a1566f to your computer and use it in GitHub Desktop.
function html(strings, ...things) {
function stringify(object = '') {
if (Array.isArray(object)) {
return object.map(stringify).join('')
}
if (object instanceof DocumentFragment) {
return Array.from(object.childNodes)
.map(node => node.outerHTML || node.nodeValue)
.join('')
}
if (object instanceof Element) {
return object.outerHTML
}
return object
}
return document.implementation
.createHTMLDocument()
.createRange()
.createContextualFragment(
strings.reduce((markup, string, index) =>
markup + stringify(things[index - 1]) + string
)
)
}
function DOMProcessor(object = new DocumentFragment, transforms = {}) {
if (
object.nodeName === '#text'
&& transforms['#text']
) {
return transforms['#text'](object)
}
if (object instanceof Element) {
Object.keys(transforms)
.filter(key => object.matches(key))
.forEach(transform => {
object.replaceWith(transforms[transform](object))
})
}
if (object instanceof NodeList) {
[...object].forEach(child =>
child.replaceWith(DOMProcessor(child, transforms))
)
}
if (object.childNodes) {
object.childNodes.forEach(child =>
child.replaceWith(DOMProcessor(child, transforms))
)
}
return object
}
// NOW…for the demo!!
const headline = 'Hello'
const subheadline = 'Subheadline'
document.body.append(
DOMProcessor(
html`
<test-1>
<flex-container>
<hero-section></hero-section>
<side-bar></side-bar>
</flex-container>
</test-1>
`,
{
'hero-section': node => {
node.append(
html`
<h1>${headline}</h1>
<h2>${subheadline}</h2>
`
)
return node
},
'side-bar': node => {
node.append(
html`
Hello!
`
)
return node
},
}
)
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment