Skip to content

Instantly share code, notes, and snippets.

@dgraham
Last active February 2, 2018 10:17
Show Gist options
  • Save dgraham/1e2921f25051a0180d35 to your computer and use it in GitHub Desktop.
Save dgraham/1e2921f25051a0180d35 to your computer and use it in GitHub Desktop.
Minimum Viable Mustache
// $ traceur --experimental --out template-es6.js template.js
function escape(text) {
let el = document.createElement('p')
el.textContent = text
return el.innerHTML
}
function node(html) {
let parser = new DOMParser()
let doc = parser.parseFromString(html, 'text/html')
return doc.body.firstChild
}
function resolve(obj, prop) {
if (typeof obj !== 'undefined') {
return obj[prop]
}
}
function replace(match, key) {
let properties = key.trim().split('.')
let value = properties.reduce(resolve, this) || ''
return escape(value)
}
function nodes(sel, root = document) {
return Array.from(root.querySelectorAll(sel))
}
function blueprint(name) {
let template = nodes('template').find(
el => el.getAttribute('data-name') === name)
return template.innerHTML
}
function template(name) {
let stache = /{{(.+?)}}/g
let template = blueprint(name)
return function evaluate(context) {
return node(template.replace(stache, replace.bind(context)))
}
}
function install(global = 'Templates') {
let registry = {}
let templates = nodes('template[data-name]')
let names = [for (el of templates) el.getAttribute('data-name')]
for (let name of names) registry[name] = template(name)
window[global] = registry
}
export {template, install}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="https://google.github.io/traceur-compiler/bin/traceur.js"></script>
<script src="https://google.github.io/traceur-compiler/src/bootstrap.js"></script>
<script src="template-es6.js"></script>
<style>
body {
text-align: center;
}
.avatar-container {
display: inline-block;
font-family: 'Helvetica Neue', sans-serif;
margin: 40px 20px;
text-align: center;
}
.avatar {
border-radius: 50%;
border: 1px solid #f8f8f8;
}
.avatar-link {
text-decoration: none;
}
.name {
color: #252525;
font-weight: 300;
line-height: 1;
}
</style>
</head>
<body>
<template data-name="avatar">
<div class="avatar-container" data-id="{{ id }}" data-user="{{ user.login }}">
<a class="avatar-link" href="{{ user.url }}" title="{{ user.login }}" target="_blank">
<div class="avatar-frame">
<img class="avatar photo" alt="{{ user.login }}" src="{{ user.avatar }}" height="230" width="230">
</div>
<h1 class="name">{{ user.name }}</h1>
</a>
</div>
</template>
<script>
traceur.options.experimental = true
</script>
<script type="module">
import {template, install} from 'template'
window.addEventListener('DOMContentLoaded', event => {
install()
let context = {
id: 42,
user: {
name: 'Hubot',
login: 'hubot',
url: 'https://github.com/hubot',
avatar: 'https://github.com/hubot.png?size=460'
}
}
// Create a single template method.
let avatar = template('avatar')
let node = avatar(context)
document.body.appendChild(node)
// Use global template method.
node = Templates['avatar'](context)
document.body.appendChild(node)
})
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment