Created
December 9, 2016 11:29
-
-
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
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
// 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