Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

fix some bugs in IE version < 9, rewrite some usgae

  • Loading branch information...
commit 4e98836f354a146a003264f96e95cfbde8161e31 1 parent f80ea7c
@microwork microwork authored
Showing with 106 additions and 79 deletions.
  1. +89 −79 template.js
  2. +17 −0 test.html
View
168 template.js
@@ -1,87 +1,97 @@
-// simple template engine
-(function(){
-var r_if = /^if\s+(.+)$/,
- r_elif = /^elif\s+(.+)$/,
- r_each = /^each\s+(.+)\s+as\s+(\w+)(?:\s*,\s*(\w+))?$/,
- r_var = /^(\w+)\s*=\s*(.+)$/,
- r_trim = /^[\s\xA0]+|[\s\xA0]+$/,
- r_d = /\\/g, r_q = /'/g, r_m = /[\r\t\n\b\f]/g;
-function q(str){
- return "'"+str.replace(r_d, "\\\\").replace(r_q, "\\'").replace(r_m, ' ')+"'";
+(function() {
+var R_TRIM = /\S/.test("\xA0") ? (/^[\s\xA0]+|[\s\xA0]+$/g) : /^\s+|\s+$/g,
+ R_D = /\\/g,
+ R_Q = /'/g,
+ R_M = /[\r\t\n\b\f]/g,
+
+ R_IF = /^if\s+(.+)$/,
+ R_ELSEIF = /^else\s+if\s+(.+)$/,
+ R_EACH = /^foreach\s+(.+)\s+as\s+(\w+)(?:\s*,\s*(\w+))?$/,
+ R_VAR = /^(\w+)\s*=\s*(.+)$/,
+
+ openTag = '{%',
+ closeTag = '%}',
+
+ nativeTrim = String.prototype.trim,
+ toString = Object.prototype.toString,
+
+ trim = nativeTrim ? function(text) {
+ return text == null ? '' : nativeTrim.call(text);
+ } : function(text) {
+ return text == null ? '' : text.toString().replace(R_TRIM, '');
+ };
+function quote(value) {
+ return "'" + value.replace(R_D, "\\\\").replace(R_Q, "\\'").replace(R_M, ' ') + "'";
}
-function trim(str){
- return str.trim ? str.trim() : str.replace(r_trim, '');
+function expr(token) {
+ return '(function() { try { return ' + token + '; } catch(e) { return \'\'; } })()';
}
-function expr(str){
- return '(function(){try{return('+str+')}catch(e){return""}})()';
+function compile(template) {
+ var output = ['var __O = [];'], part;
+ template = template.split(openTag);
+ while ((part = template.shift())) {
+ var parts = part.split(closeTag),
+ token = parts[0],
+ plain = parts[1];
+ if (token && plain) {
+ token = trim(token);
+ switch (true) {
+ case R_IF.test(token):
+ output.push('if (' + expr(RegExp.$1) + ') {');
+ break;
+ case R_ELSEIF.test(token):
+ output.push('} else if (' + expr(RegExp.$1) + ') {');
+ break;
+ case token == 'else':
+ output.push('} else {');
+ break;
+ case token == 'endif':
+ output.push('}');
+ break;
+ case R_EACH.test(token):
+ output.push('this.foreach(' + expr(RegExp.$1) + ', function(' + RegExp.$3 || 'index' + ',' + RegExp.$2 + ') {');
+ break;
+ case token == 'endforeach':
+ output.push('});');
+ break;
+ case R_VAR.test(token):
+ output.push('var ' + RegExp.$1 + ' = ' + expr(RegExp.$2) + ';');
+ break;
+ default:
+ output.push('__O.push(' + expr(token) + ');');
+ break;
+ }
+ output.push('__O.push(' + quote(plain) + ');');
+ } else {
+ output.push('__O.push(' + quote(token) + ');');
+ }
+ }
+ output.push("return __O.join('');");
+ return output.join('');
}
-function compile(template){
- var chunk = template.split(/{%(.*?)%}/gm);
- var body = ['var _O=[];'];
- for (var i=0,l=chunk.length,token;i<l;i++) {
- token = chunk[i];
- if (i%2) {
- token = trim(token);
- switch(true){
- // {%fi%}
- case token == 'fi': body.push('}'); break;
- // {%hcae%}
- case token == 'hcae': body.push('});'); break;
- // {%else%}
- case token == 'else': body.push('}else{'); break;
- // {%if expr%}
- case r_if.test(token):
- body.push("if("+expr(RegExp.$1)+"){");
- break;
- // {%elif expr%}
- case r_elif.test(token):
- body.push("}else if("+expr(RegExp.$1)+"){");
- break;
- // {%each expr as value,key%}
- case r_each.test(token):
- body.push("this.each("+expr(RegExp.$1)+",function("+(RegExp.$3 || "_P") + "," + RegExp.$2 + "){");
- break;
- // {%var=expr%}
- case r_var.test(token):
- body.push("var "+RegExp.$1+"="+expr(RegExp.$2)+";");
- break;
- // {%expr%}
- default:
- body.push("_O.push("+expr(token)+");");
- break;
- }
- } else {
- body.push("_O.push("+q(token)+");");
- }
- }
- body.push('return _O.join("");');
- return body.join('');
-}
-var Template = function(template){
- this.template = compile(template);
+var Template = function(template) {
+ this.template = compile(template);
};
-Template.each = function(object, callback) {
- if (!object) return;
- var key, i = 0,
- length = object.length;
-
- if (length === undefined || Object.prototype.toString.call(object) == '[object Function]') {
- for (key in object) {
- callback.call(object[key], key, object[key]);
- }
- } else {
- for (; i < length;) {
- callback.call(object[i], i, object[i++]);
- }
- }
+Template.foreach = function(object, callback) {
+ if (! object) return;
+ var key, index = 0, length = object.length;
+ if (length === undefined || toString.call(object) == '[object Function]') {
+ for (key in object) {
+ callback.call(object[key], key, object[key]);
+ }
+ } else {
+ for (; index < length;) {
+ callback.call(object[index], index, object[index++]);
+ }
+ }
};
-Template.prototype.render = function(data){
- var body = [
- 'with(_I){',
- this.template,
- '}'
- ].join('');
- return (new Function('_I', body)).call(Template, data);
+Template.prototype.render = function(data) {
+ var body = [
+ 'with(__I) {',
+ this.template,
+ '}'
+ ].join('');
+ return (new Function('__I', body)).call(Template, data);
};
window.Template = Template;
})();
View
17 test.html
@@ -11,5 +11,22 @@
var t = new Template(tpl);
console.info(t.render({somevar:'other'}));
</script>
+
+<script type="text/template" id="template">
+<div>
+ {%if age > 18%}
+ <span>hello, {%decodeURIComponent(name)%}</span>
+ {%else%}
+ <span class="error">sorry, your age {%parseInt(age) || 0%} is too lower to see that.</span>
+ {%endif%}
+</div>
+</script>
+<script>
+var template = new Template(document.getElementById('template').innerHTML);
+console.info(template.render({
+ age: null,
+ name: 'Bob'
+}));
+</script>
</body>
</html>
Please sign in to comment.
Something went wrong with that request. Please try again.