Skip to content

Instantly share code, notes, and snippets.

@rmehta
Created December 9, 2016 11:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rmehta/27d528cb6415937114e8b7eb60ef0dc2 to your computer and use it in GitHub Desktop.
Save rmehta/27d528cb6415937114e8b7eb60ef0dc2 to your computer and use it in GitHub Desktop.
A simple microtemplating function in Javascript to parse Jinja style tags, for and if statements
// Simple Jinja Style templates in Javascript
// Adapted from microtemplate.js by John Resig
// http://ejohn.org/blog/javascript-micro-templating/
// usage:
// tepmlate_name = "Testing";
// render_template('{% if template_name %}<h1>{{ template_name }}{% endif %}');
var compiled_templates = {};
function render_template(str, name) {
var key = name || str;
if(str.indexOf("'")!==-1) {
str.replace(/'/g, "\\'");
//console.warn("Warning: Single quotes (') may not work in templates");
}
// replace jinja style tags
str = str.replace(/{{/g, "{%=").replace(/}}/g, "%}");
// {% if not test %} --> {% if (!test) { %}
str = str.replace(/{%\s?if\s?\s?not\s?([^\(][^%{]+)\s?%}/g, "{% if (! $1) { %}")
// {% if test %} --> {% if (test) { %}
str = str.replace(/{%\s?if\s?([^\(][^%{]+)\s?%}/g, "{% if ($1) { %}");
// {% for item in list %}
// --> {% for (var i=0, len=list.length; i<len; i++) { var item = list[i]; %}
function replacer(match, p1, p2, offset, string) {
var i = frappe.utils.get_random(3);
var len = frappe.utils.get_random(3);
return "{% for (var "+i+"=0, "+len+"="+p2+".length; "+i+"<"+len+"; "+i+"++) { var "
+p1+" = "+p2+"["+i+"]; "+p1+"._index = "+i+"; %}";
}
str = str.replace(/{%\s?for\s([a-z]+)\sin\s([a-z._]+)\s?%}/g, replacer);
// {% endfor %} --> {% } %}
str = str.replace(/{%\s?endif\s?%}/g, "{% }; %}");
// {% else %} --> {% } else { %}
str = str.replace(/{%\s?else\s?%}/g, "{% } else { %}");
// {% endif %} --> {% } %}
str = str.replace(/{%\s?endfor\s?%}/g, "{% }; %}");
fn_str = "var _p=[],print=function(){_p.push.apply(_p,arguments)};" +
// Introduce the data as local variables using with(){}
"with(obj){\n_p.push('" +
// Convert the template into pure JavaScript
str
.replace(/[\r\t\n]/g, " ")
.split("{%").join("\t")
.replace(/((^|%})[^\t]*)'/g, "$1\r")
.replace(/\t=(.*?)%}/g, "',$1,'")
.split("\t").join("');\n")
.split("%}").join("\n_p.push('")
.split("\r").join("\\'")
+ "');}return _p.join('');";
try {
compiled_templates[key] = new Function("obj", fn_str);
} catch (e) {
console.log("Error in Template:");
console.log(fn_str);
if(e.lineNumber) {
console.log("Error in Line "+e.lineNumber+", Col "+e.columnNumber+":");
console.log(fn_str.split("\n")[e.lineNumber - 1]);
}
}
return compiled_templates[key];
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment