muu

DEPRECATED lightweight JS framework
git clone https://git.ce9e.org/muu.git

commit
b9ede1986fab336dc43c2a93fdeec5a896f7ea68
parent
37db3ac93095dea97f496ba0f0fa94bc03440395
Author
Tobias Bengfort <tobias.bengfort@gmx.net>
Date
2015-08-28 17:05
refactor template

Diffstat

M src/muu-template.js 209 ++++++++++++++++++++++++++++++++++++-------------------------

1 files changed, 125 insertions, 84 deletions


diff --git a/src/muu-template.js b/src/muu-template.js

@@ -68,26 +68,40 @@ define('muu-template', ['muu-js-helpers', 'muu-dom-helpers'], function(_, $) {
   68    68     var openTag = '{{';
   69    69     var closeTag = '}}';
   70    70 
   -1    71     /**
   -1    72      * @param {string} key
   -1    73      * @param {Object} data
   -1    74      * @return {*}
   -1    75      * @nosideeffects
   -1    76      */
   71    77     var getValue = function(key, data) {
   72    78         return key === 'this' ? data : data[key];
   73    79     };
   74    80 
   75    -1     var parseVariableTemplate = function(template) {
   76    -1         var content = template.slice(2, -2);
   77    -1 
   78    -1         if (template.indexOf(':') === -1) {
   79    -1             return function(data) {
   80    -1                 return $.escapeHtml(getValue(content, data) || '');
   -1    81     /**
   -1    82      * @param {string} tag
   -1    83      * @param {string} afterTag
   -1    84      * @param {string} loopName
   -1    85      * @return {{render: function(*): string, afterBlock: string}}
   -1    86      * @nosideeffects
   -1    87      */
   -1    88     var parseVariable = function(tag, afterTag, loopName) {
   -1    89         var next = parseTemplate(afterTag, loopName);
   -1    90         var render;
   -1    91 
   -1    92         if (tag.indexOf(':') === -1) {
   -1    93             render = function(data) {
   -1    94                 return $.escapeHtml(getValue(tag, data) || '');
   81    95             };
   82    96         } else {
   83    -1             var pairs = content.split(',').map(function(pair) {
   -1    97             var pairs = _.map(tag.split(','), function(pair) {
   84    98                 var v = pair.split(':');
   85    99                 var key = v[0].trim();
   86   100                 var value = v.slice(1).join(':').trim();
   87   101                 return [key, value];
   88   102             });
   89   103 
   90    -1             return function(data) {
   -1   104             render = function(data) {
   91   105                 var results = [];
   92   106 
   93   107                 for (var i = 0; i < pairs.length; i++) {
@@ -102,67 +116,98 @@ define('muu-template', ['muu-js-helpers', 'muu-dom-helpers'], function(_, $) {
  102   116                 return $.escapeHtml(results.join(' '));
  103   117             };
  104   118         }
  105    -1     };
  106   119 
  107    -1     var parseLoopTemplate = function(tag, afterTag, inverted) {
  108    -1         var tagName = tag.slice(3, -2);
  109    -1 
  110    -1         var v = parseTemplate(afterTag, tagName);
  111    -1         var inner = v[0];
  112    -1         var afterLoop = v[1];
   -1   120         return {
   -1   121             render: function(data) {
   -1   122                 return render(data) + next.render(data, loopName);
   -1   123             },
   -1   124             afterBlock: next.afterBlock
   -1   125         };
   -1   126     };
  113   127 
  114    -1         var render = function(data) {
  115    -1             if (inverted) {
  116    -1                 if (getValue(tagName, data)) {
  117    -1                     return '';
  118    -1                 } else {
  119    -1                     return inner(data);
  120    -1                 }
  121    -1             } else {
  122    -1                 if (_.isArray(getValue(tagName, data))) {
  123    -1                     var result = '';
  124    -1                     for (var i = 0; i < getValue(tagName, data).length; i++) {
  125    -1                         result += inner(getValue(tagName, data)[i]);
   -1   128     /**
   -1   129      * @param {string} tag
   -1   130      * @param {string} afterTag
   -1   131      * @param {string} loopName
   -1   132      * @param {boolean} [inverted]
   -1   133      * @return {{render: function(*): string, afterBlock: string}}
   -1   134      * @nosideeffects
   -1   135      */
   -1   136     var parseLoop = function(tag, afterTag, loopName, inverted) {
   -1   137         var inner = parseTemplate(afterTag, tag);
   -1   138         var next = parseTemplate(inner.afterBlock, loopName);
   -1   139 
   -1   140         return {
   -1   141             render: function(data) {
   -1   142                 var value = getValue(tag, data);
   -1   143                 var result = '';
   -1   144 
   -1   145                 if (inverted) {
   -1   146                     if (!value) {
   -1   147                         result += inner.render(data);
  126   148                     }
  127    -1                     return result;
  128    -1                 } else if (getValue(tagName, data)) {
  129    -1                     return inner(data);
  130   149                 } else {
  131    -1                     return '';
   -1   150                     if (_.isArray(value)) {
   -1   151                         for (var i = 0; i < value.length; i++) {
   -1   152                             result += inner.render(value[i]);
   -1   153                         }
   -1   154                     } else if (value) {
   -1   155                         result += inner.render(data);
   -1   156                     }
  132   157                 }
  133    -1             }
  134    -1         };
  135   158 
  136    -1         return [render, afterLoop];
   -1   159                 return result + next.render(data);
   -1   160             },
   -1   161             afterBlock: next.afterBlock
   -1   162         };
  137   163     };
  138   164 
  139    -1     var concat = function(a) {
  140    -1         var last = a.pop();
  141    -1 
  142    -1         if (_.isArray(last)) {
  143    -1             a.push(last[0]);
  144    -1             return [concat(a), last[1]];
  145    -1         } else {
  146    -1             a.push(last);
  147    -1 
  148    -1             return function(data) {
  149    -1                 return a.map(function(item) {
  150    -1                     if (_.isString(item)) {
  151    -1                         return item;
  152    -1                     } else if (_.isFunction(item)) {
  153    -1                         return item(data);
  154    -1                     }
  155    -1                 }).join('');
   -1   165     /**
   -1   166      * @param {string} tag
   -1   167      * @param {string} afterTag
   -1   168      * @param {string} loopName
   -1   169      * @return {{render: function(*): string, afterBlock: string}}
   -1   170      * @nosideeffects
   -1   171      */
   -1   172     var parseClose = function(tag, afterTag, loopName) {
   -1   173         if (tag === loopName) {
   -1   174             return {
   -1   175                 render: function(data) {
   -1   176                     return '';
   -1   177                 },
   -1   178                 afterBlock: afterTag
  156   179             };
   -1   180         } else {
   -1   181             throw new Error('unexpected closing loop: ' + tag);
  157   182         }
  158   183     };
  159   184 
   -1   185     /**
   -1   186      * @param {string} tag
   -1   187      * @param {string} afterTag
   -1   188      * @param {string} loopName
   -1   189      * @return {{render: function(*): string, afterBlock: string}}
   -1   190      * @nosideeffects
   -1   191      */
   -1   192     var parseComment = function(tag, afterTag, loopName) {
   -1   193         return parseTemplate(afterTag, loopName);
   -1   194     };
   -1   195 
   -1   196     /**
   -1   197      * @param {string} template
   -1   198      * @param {string} loopName
   -1   199      * @return {{render: function(*): string, afterBlock: string}}
   -1   200      * @nosideeffects
   -1   201      */
  160   202     var parseTemplate = function(template, loopName) {
  161   203         var openIndex = template.indexOf(openTag);
  162   204         if (openIndex === -1) {
  163   205             if (loopName === undefined) {
  164    -1                 return function() {
  165    -1                     return template;
   -1   206                 return {
   -1   207                     render: function(data) {
   -1   208                         return template;
   -1   209                     },
   -1   210                     afterBlock: ''
  166   211                 };
  167   212             } else {
  168   213                 throw new Error('unclosed loop: ' + loopName);
@@ -171,44 +216,40 @@ define('muu-template', ['muu-js-helpers', 'muu-dom-helpers'], function(_, $) {
  171   216             var beforeTag = template.slice(0, openIndex);
  172   217             var tmp = template.slice(openIndex);
  173   218 
  174    -1             var closeIndex = tmp.indexOf(closeTag) + 2;
  175    -1             if (closeIndex === 1) {
   -1   219             var closeIndex = tmp.indexOf(closeTag);
   -1   220             if (closeIndex === -1) {
  176   221                 throw new Error('unclosed tag: ' + tmp);
  177   222             }
  178    -1             var tag = tmp.slice(0, closeIndex);
  179    -1             var afterTag = tmp.slice(closeIndex);
  180    -1 
  181    -1             if (tag.lastIndexOf('{{#', 0) === 0) {
  182    -1                 var v = parseLoopTemplate(tag, afterTag);
  183    -1                 var loop = v[0];
  184    -1                 var after = parseTemplate(v[1], loopName);
  185    -1                 return concat([beforeTag, loop, after]);
  186    -1             } else if (tag.lastIndexOf('{{^', 0) === 0) {
  187    -1                 var v = parseLoopTemplate(tag, afterTag, true);
  188    -1                 var loop = v[0];
  189    -1                 var after = parseTemplate(v[1], loopName);
  190    -1                 return concat([beforeTag, loop, after]);
  191    -1             } else if (tag.lastIndexOf('{{!', 0) === 0) {
  192    -1                 var after = parseTemplate(afterTag, loopName);
  193    -1                 return concat([beforeTag, after]);
  194    -1             } else if (tag.lastIndexOf('{{/', 0) === 0) {
  195    -1                 if (tag.slice(3, -2) === loopName) {
  196    -1                     var render = function() {
  197    -1                         return beforeTag;
  198    -1                     };
  199    -1                     return [render, afterTag];
  200    -1                 } else {
  201    -1                     throw new Error('unexpected closing loop: ' + tag);
  202    -1                 }
   -1   223             var tag = tmp.slice(openTag.length, closeIndex);
   -1   224             var afterTag = tmp.slice(closeIndex + closeTag.length);
   -1   225 
   -1   226             var next;
   -1   227             if (tag.lastIndexOf('#', 0) === 0) {
   -1   228                 next = parseLoop(tag.substr(1), afterTag, loopName);
   -1   229             } else if (tag.lastIndexOf('^', 0) === 0) {
   -1   230                 next = parseLoop(tag.substr(1), afterTag, loopName, true);
   -1   231             } else if (tag.lastIndexOf('!', 0) === 0) {
   -1   232                 next = parseComment(tag.substr(1), afterTag, loopName);
   -1   233             } else if (tag.lastIndexOf('/', 0) === 0) {
   -1   234                 next = parseClose(tag.substr(1), afterTag, loopName);
  203   235             } else {
  204    -1                 var render = parseVariableTemplate(tag);
  205    -1                 var after = parseTemplate(afterTag, loopName);
  206    -1                 return concat([beforeTag, render, after]);
   -1   236                 next = parseVariable(tag, afterTag, loopName);
  207   237             }
   -1   238 
   -1   239             return {
   -1   240                 render: function(data) {
   -1   241                     return beforeTag + next.render(data);
   -1   242                 },
   -1   243                 afterBlock: next.afterBlock
   -1   244             };
  208   245         }
  209   246     };
  210   247 
  211   248     return function(template, data) {
  212    -1         return parseTemplate(template)(data);
   -1   249         var parsed = parseTemplate(template);
   -1   250         if (parsed.afterBlock) {
   -1   251             throw new Error('non-empty afterBlock');
   -1   252         }
   -1   253         return parsed.render(data);
  213   254     };
  214   255 });