Skip to content

Instantly share code, notes, and snippets.

@xulapp
Created October 27, 2010 17:14
Show Gist options
  • Save xulapp/649489 to your computer and use it in GitHub Desktop.
Save xulapp/649489 to your computer and use it in GitHub Desktop.
JS テンプレートエンジン
(function() {
var quote = (function() {
var specialCharReg = /[\n\r'\\]/g;
var specialCharMap = {'\n': '\\n', '\r': '\\r', '\'': '\\\'', '\\': '\\\\'};
var specialCharRegCb = function(c) { return specialCharMap[c]; };
return function(str) {
return '\'' + str.replace(specialCharReg, specialCharRegCb) + '\'';
};
})();
var pipeCheckReg = /\|[\s\w]+$/;
var pipeParseReg = /(.+?)\|\s*(\w+)(?=[|\s\w]*$)/;
var tmplReg = /(?:^|%>)([\s\S]*?)(?:<%(?:=([\s\S]+?(?=%>)))?|$)/g;
var tmplRegCb = function($0, $1, $2) {
var out = '';
if ($1)
out += ';__jstmpl__buffer.push(' + quote($1) + ');';
if ($2) {
while (pipeCheckReg.test($2))
$2 = $2.replace(pipeParseReg, '$2(($1))');
out += ';__jstmpl__buffer.push((' + $2 + '));';
}
return out;
};
function Template(text) {
this.compiled = Function('__jstmpl__context',
'with(__jstmpl__context){with(__jstmpl__kwargs){(function(){' +
text.replace(tmplReg, tmplRegCb) +
'})();}}'
);
}
Template.prototype.render = function(dict) {
var ctx = new Template.Context(dict);
this.compiled(ctx);
return ctx.__jstmpl__buffer.join('');
};
Template.Context = function Context(dict) {
this.__jstmpl__buffer = [];
this.__jstmpl__kwargs = dict || {};
}
this.Template = Template;
Template.Context.prototype.print = function() {
this.__jstmpl__buffer.push(Array.prototype.join.call(arguments, ' '));
};
Template.Context.prototype.url = encodeURIComponent;
Template.Context.prototype.html = (function() {
var specialCharReg = /["&'<>]/g;
var specialCharMap = {'"': '&quot;', '&': '&amp;', '\'': '&#039;', '<': '&lt;', '>': '&gt;'};
var specialCharRegCb = function(c) { return specialCharMap[c]; };
return function(str) {
return ('' + str).replace(specialCharReg, specialCharRegCb);
};
})();
Template.Context.prototype.trim = String.trim || (String.prototype.trim
? function(str) { return ('' + str).trim(); }
: (function() {
var trimmingReg = /^\s+|\s+$/g;
return function(str) { return ('' + str).replace(trimmingReg, ''); }
})()
);
})();
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<title>jstmpl Benchmark</title>
<script src="jstmpl.js"></script>
</head>
<body>
<h1>jstmpl Benchmark</h1>
<form>
<p><label for="source">Source:</label></p>
<p><textarea id="source" cols="80" rows="10"><div>
<h2><%= title %></h2>
<ul>
<% for (var i in items) { %>
<li><%= items[i] || '(none)' %></li>
<% } %>
</ul>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
<p><%= paragraph %></p>
<%if (test) { %>
<p>Test!</p>
<% } %>
</div></textarea></p>
<p>
<label for="loop">Loop:</label>
<input type="text" id="loop" size="10" value="1000" /> times (&lt;= 10000 recommended)
</p>
<p>
<input type="button" value="Bench with Each-Time Compile" onclick="benchCompileEachTime();" />
<input type="button" value="Bench with Precompile" onclick="benchPrecompile();" />
</p>
</form>
<h2>Result</h2>
<textarea id="result" cols="80" rows="5"></textarea><br>
<textarea id="result_compiled" cols="80" rows="5"></textarea><br>
<textarea id="result_html" cols="80" rows="5"></textarea>
<script>
var dict = {
title: "This is test",
items: [
"Apple",
"Banana",
null,
"Grape",
"Orange"
],
paragraph: "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.",
test: true
};
function benchCompileEachTime() {
var source = document.getElementById("source").value;
var loop = parseInt(document.getElementById("loop").value);
var template;
var beginTime = (new Date()).getTime();
for (var i = 0; i < loop; i++) {
template = new Template(source);
template.render(dict);
}
var endTime = (new Date()).getTime();
printResult(endTime - beginTime, loop);
}
function benchPrecompile() {
var source = document.getElementById("source").value;
var loop = parseInt(document.getElementById("loop").value);
var template = new Template(source);
var beginTime = (new Date()).getTime();
for (var i = 0; i < loop; i++) {
template.render(dict);
}
var endTime = (new Date()).getTime();
printResult(endTime - beginTime, loop);
}
function printResult(elapsed, loop) {
var average = elapsed / loop;
var persec = (1000 / average).toString().replace(/(\.\d{2})\d+/, "$1");
document.getElementById("result").value =
"looped: " + loop + " times\n" +
"elapsed: " + elapsed + " ms (" + (elapsed/1000) + " sec)\n" +
"average: " + average + " ms/time\n" +
"persec: " + persec + " times/sec\n";
var template = new Template(document.getElementById("source").value);
document.getElementById("result_compiled").value = template.compiled;
document.getElementById("result_html").value = template.render(dict);
}
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment