Skip to content

Instantly share code, notes, and snippets.

@imranismail
Last active June 18, 2018 12:25
Show Gist options
  • Save imranismail/84549a8a2e4130a16ac2974089a316e2 to your computer and use it in GitHub Desktop.
Save imranismail/84549a8a2e4130a16ac2974089a316e2 to your computer and use it in GitHub Desktop.
const Tree = union('Tree', {
Leaf(value) {
return { value }
},
Node(value, ...children) {
return { value, children }
}
})
const HTML = union('HTML', {
tag(name, props) { return { name, props } }
text(text) { return { content: text } }
}).derive(
toHTMLElement
)
const toHTMLElement = (variant, union) => {
switch (variant.tag) {
case 'Tag':
variant.prototype.toElement = function() {
const element = document.createElement(this.name)
for (prop in this.props) {
element.setAttribute(prop, this.props[prop])
}
return element
}
break;
case 'Text':
variant.prototype.toElement = function() {
return document.createTextNode(this.content)
}
break;
default:
throw new Error(`Invalid tag ${pattern.tag}`)
}
}
const Greeter = ({ name }) =>
Tree.Node(HTML.Tag('p'),
Tree.Leaf(HTML.Text('Hello, ')),
Tree.Leaf(HTML.Text(name))
)
const HelloWorld = () =>
Tree.Leaf(HTML.Tag('div'), Greeter({name: 'imran'}))
const render = tree, mount => {
const element = tree.matchWith({
Leaf: leaf => leaf.value.toHTMLElement(),
Node: node => {
const element = node.value.toHTMLElement();
node.children.forEach(node => element.appendChild(render(node)))
return element;
}
})
while (mount.firstChild) {
mount.removeChild(mount.firstChild);
}
mount.appendChild(element)
}
render(HelloWorld(), document.getElementById('#root'))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment