Mercurial > pub > ImplabJs
annotate core/src/js/text/template-compile.js @ 30:2dfba21cd879
sync
| author | cin | 
|---|---|
| date | Wed, 27 Jun 2018 02:46:14 +0300 | 
| parents | acdcdf1a8d21 | 
| children | 
| rev | line source | 
|---|---|
| 0 | 1 define( | 
| 24 
f750c89976d3
Added trace tools, implab/log/trace!<channel-name>, <channel-name> is optional
 cin parents: 
21diff
changeset | 2 ["dojo/request", "./format", "../log/trace!"], | 
| 
f750c89976d3
Added trace tools, implab/log/trace!<channel-name>, <channel-name> is optional
 cin parents: 
21diff
changeset | 3 function (request, format, trace) { | 
| 21 | 4 | 
| 5 // разбивает строку шаблона на токены, возвращает контекст для | |
| 6 // дальнейшей обработки в visitTemplate | |
| 7 var parseTemplate = function (str) { | |
| 26 | 8 var tokens = str.split(/(<%=|\[%=|<%|\[%|%\]|%>)/); | 
| 21 | 9 var pos = -1; | 
| 10 var data = [], | |
| 11 code = []; | |
| 0 | 12 | 
| 21 | 13 return { | 
| 14 next: function () { | |
| 15 pos++; | |
| 16 return pos < tokens.length; | |
| 17 }, | |
| 18 token: function () { | |
| 19 return tokens[pos]; | |
| 20 }, | |
| 21 pushData: function () { | |
| 22 var i = data.length; | |
| 23 data.push.apply(data, arguments); | |
| 24 return i; | |
| 25 }, | |
| 26 pushCode : function() { | |
| 27 var i = code.length; | |
| 28 code.push.apply(code, arguments); | |
| 29 return i; | |
| 30 }, | |
| 31 compile: function () { | |
| 32 var text = "var $p = [];\n" + | |
| 33 "var print = function(){\n" + | |
| 34 " $p.push(format.apply(null,arguments));\n" + | |
| 35 "};\n" + | |
| 36 // Introduce the data as local variables using with(){} | |
| 37 "with(obj){\n" + | |
| 38 code.join("\n") + | |
| 39 "}\n" + | |
| 40 "return $p.join('');"; | |
| 41 | |
| 42 try { | |
| 43 var compiled = new Function("obj, format, $data", text); | |
| 44 /** | |
| 45 * Функция форматирования по шаблону | |
| 46 * | |
| 47 * @type{Function} | |
| 48 * @param{Object} obj объект с параметрами для подстановки | |
| 49 */ | |
| 50 return function (obj) { | |
| 51 return compiled(obj || {}, format, data); | |
| 52 }; | |
| 53 } catch (e) { | |
| 24 
f750c89976d3
Added trace tools, implab/log/trace!<channel-name>, <channel-name> is optional
 cin parents: 
21diff
changeset | 54 trace.error([e]); | 
| 
f750c89976d3
Added trace tools, implab/log/trace!<channel-name>, <channel-name> is optional
 cin parents: 
21diff
changeset | 55 trace.log([text, data]); | 
| 
f750c89976d3
Added trace tools, implab/log/trace!<channel-name>, <channel-name> is optional
 cin parents: 
21diff
changeset | 56 throw e; | 
| 21 | 57 } | 
| 0 | 58 } | 
| 59 } | |
| 60 }; | |
| 61 | |
| 21 | 62 function visitTemplate(context) { | 
| 63 while (context.next()) { | |
| 64 switch (context.token()) { | |
| 65 case "<%": | |
| 26 | 66 case "[%": | 
| 21 | 67 visitCode(context); | 
| 68 break; | |
| 69 case "<%=": | |
| 26 | 70 case "[%=": | 
| 21 | 71 visitInline(context); | 
| 72 break; | |
| 73 default: | |
| 74 visitTextFragment(context); | |
| 75 break; | |
| 76 } | |
| 77 } | |
| 78 } | |
| 79 | |
| 80 function visitInline(context) { | |
| 81 var code = ["$p.push("]; | |
| 82 while (context.next()) { | |
| 26 | 83 if (context.token() == "%>" || context.token() == "%]") | 
| 21 | 84 break; | 
| 85 code.push(context.token()); | |
| 86 } | |
| 87 code.push(");"); | |
| 88 context.pushCode(code.join('')); | |
| 89 } | |
| 90 | |
| 91 function visitCode(context) { | |
| 92 var code = []; | |
| 93 while (context.next()) { | |
| 26 | 94 if (context.token() == "%>" || context.token() == "%]") | 
| 21 | 95 break; | 
| 96 code.push(context.token()); | |
| 97 } | |
| 98 context.pushCode(code.join('')); | |
| 99 } | |
| 100 | |
| 101 function visitTextFragment(context) { | |
| 102 var i = context.pushData(context.token()); | |
| 103 context.pushCode("$p.push($data["+i+"]);"); | |
| 104 } | |
| 105 | |
| 106 var compile = function (str) { | |
| 107 if (!str) | |
| 108 return function() { return "";}; | |
| 109 | |
| 110 var ctx = parseTemplate(str); | |
| 111 visitTemplate(ctx); | |
| 112 return ctx.compile(); | |
| 113 }; | |
| 114 | |
| 0 | 115 var cache = {}; | 
| 116 | |
| 21 | 117 compile.load = function (id, require, callback) { | 
| 0 | 118 var url = require.toUrl(id); | 
| 119 if (url in cache) { | |
| 120 callback(cache[url]); | |
| 121 } else { | |
| 21 | 122 request(url).then(compile).then(function (tc) { | 
| 0 | 123 callback(cache[url] = tc); | 
| 21 | 124 }, function (err) { | 
| 125 require.signal("error", [{ | |
| 126 error: err, | |
| 127 src: 'implab/text/template-compile' | |
| 128 }]); | |
| 0 | 129 }); | 
| 130 } | |
| 131 }; | |
| 132 | |
| 133 return compile; | |
| 134 }); | 
