Last active
February 2, 2018 10:17
-
-
Save dgraham/1e2921f25051a0180d35 to your computer and use it in GitHub Desktop.
Minimum Viable Mustache
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
// $ 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} |
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
<!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