Skip to content

Instantly share code, notes, and snippets.

@jinjor
Last active August 29, 2015 14:07
Show Gist options
  • Save jinjor/5dd47b5b82ea3acd3104 to your computer and use it in GitHub Desktop.
Save jinjor/5dd47b5b82ea3acd3104 to your computer and use it in GitHub Desktop.
荒削りテンプレート
<template id="target">
<div>
<span foo="{{ bar }}">{{foo}}</span>
<template repeat="{{ bar , i in list }}">
<div><span>{{i}}: </span><span>{{foo}}</span><span>{{bar}}</span></div>
</template>
<div><a>{{bar}} dayo{{foo}}</a></div>
</div>
</template>
<script>
var template = {};
template.splitBracketOnce = function(text) {
var index1 = text.indexOf('{{');
if (index1 < 0) {
return [text];
}
var left = text.substring(0, index1);
var rest = text.substring(index1 + 2);
var index2 = rest.indexOf('}}');
if (index2 < 0) {
return [left, rest];
}
var center = rest.substring(0, index2).trim();
var right = rest.substring(index2 + 2);
return [left, center, right];
};
template.parse = function(text) {
var parts = [];
while (true) {
var splitted = template.splitBracketOnce(text);
splitted[0] && parts.push(splitted[0]);
if (splitted.length >= 2) {
if (splitted.length === 3) {
var inner = splitted[1];
parts.push({
value: inner
});
text = splitted[2];
} else {
parts.push(splitted[1]);
break;
}
} else {
break;
}
}
return parts;
};
template.traverse = function(nodes, variables) {
var len_i = nodes.length;
for (var i = 0; i < len_i; i++) {
var node = nodes[i];
if (node.tagName === 'TEMPLATE') {
var rep = node.getAttribute('repeat')
if (rep) {
var parsed = template.parseRepeat(rep);
var render = template.compile(node);
node.forLoop = {
one: parsed[0],
index: parsed[1],
list: parsed[2],
render: render
};
}
} else {
if (node.attributes) {
var len_j = node.attributes.length;
for (var j = 0; j < len_j; j++) {
var attribute = node.attributes[j];
var parts = template.parse(attribute.value);
if (parts.length > 1 || typeof parts[0] === 'object') {
node.attrParts = node.attrParts || {};
node.attrParts[attribute.name] = parts;
}
}
}
if (node.nodeValue) {
var text = node.nodeValue;
var parts = template.parse(text);
if (parts.length > 1 || typeof parts[0] === 'object') {
node.parts = parts;
}
}
}
if (node.attrParts || node.parts || node.forLoop) {
variables.push(node);
}
if (node.tagName !== 'TEMPLATE') {
template.traverse(node.childNodes, variables);
}
}
};
template.parseRepeat = function(text) {
var splitted = template.splitBracketOnce(text);
var inner = splitted[1];
if (!inner) {
throw new Error();
}
var innerSplitted = inner.split(' in ');
var _one = innerSplitted[0].trim();
var _oneSplitted = _one.split(',');
var one = _oneSplitted[0].trim();
var index = _oneSplitted[1].trim();
var list = innerSplitted[1].trim();
return [one, index, list];
};
template.traverseAndRender = function(variables, object) {
var len_i = variables.length;
for (var i = 0; i < len_i; i++) {
var node = variables[i];
if (node.forLoop) {
var newObject = Object.create(object);
var list = object[node.forLoop.list];
var len_j = list.length;
for(var j = 0; j < len_j; j++){
newObject[node.forLoop.one] = list[j];
newObject[node.forLoop.index] = j;
var childNode = node.forLoop.render(newObject);
node.parentNode.insertBefore(childNode, node);
}
continue;
}
if (node.attrParts) {
var names = Object.keys(node.attrParts);
var len_j = names.length;
for (var j = 0; j < len_j; j++) {
var name = names[j];
var parts = node.attrParts[name];
var text = template.makeText(parts, object);
node.setAttribute(name, text);
}
}
if (node.parts) {
var text = template.makeText(node.parts, object);
node.nodeValue = text;
}
}
};
template.makeText = function(parts, object) {
var text = ''
var len_j = parts.length;
for (var j = 0; j < len_j; j++) {
var part = parts[j];
if (typeof part === 'object') {
text += object[part.value];
} else {
text += part;
}
}
return text;
};
template.compile = function(templateElement) {
var variables = [];
template.traverse(templateElement.content.childNodes, variables);
return function(object) {
template.traverseAndRender(variables, object);
var clone = document.importNode(templateElement.content, true);
return clone;
};
};
window.onload = function() {
var render = template.compile(document.getElementById('target'));
var node = render({
foo: 'FOO',
bar: 'BAR',
list: ['a', 'b', '<b>c</b>']
});
document.body.appendChild(node);
};
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment