0
|
1 define(
|
21
|
2 ["dojo/request", "./format"],
|
|
3 function (request, format) {
|
|
4
|
|
5 // разбивает строку шаблона на токены, возвращает контекст для
|
|
6 // дальнейшей обработки в visitTemplate
|
|
7 var parseTemplate = function (str) {
|
|
8 var tokens = str.split(/(<%=|<%|%>)/);
|
|
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) {
|
|
54 if (console && console.error) {
|
|
55 console.error(text);
|
|
56 console.log(data);
|
|
57 }
|
|
58 }
|
0
|
59 }
|
|
60 }
|
|
61 };
|
|
62
|
21
|
63 function visitTemplate(context) {
|
|
64 while (context.next()) {
|
|
65 switch (context.token()) {
|
|
66 case "<%":
|
|
67 visitCode(context);
|
|
68 break;
|
|
69 case "<%=":
|
|
70 visitInline(context);
|
|
71 break;
|
|
72 default:
|
|
73 visitTextFragment(context);
|
|
74 break;
|
|
75 }
|
|
76 }
|
|
77 }
|
|
78
|
|
79 function visitInline(context) {
|
|
80 var code = ["$p.push("];
|
|
81 while (context.next()) {
|
|
82 if (context.token() == "%>")
|
|
83 break;
|
|
84 code.push(context.token());
|
|
85 }
|
|
86 code.push(");");
|
|
87 context.pushCode(code.join(''));
|
|
88 }
|
|
89
|
|
90 function visitCode(context) {
|
|
91 var code = [];
|
|
92 while (context.next()) {
|
|
93 if (context.token() == "%>")
|
|
94 break;
|
|
95 code.push(context.token());
|
|
96 }
|
|
97 context.pushCode(code.join(''));
|
|
98 }
|
|
99
|
|
100 function visitTextFragment(context) {
|
|
101 var i = context.pushData(context.token());
|
|
102 context.pushCode("$p.push($data["+i+"]);");
|
|
103 }
|
|
104
|
|
105 var compile = function (str) {
|
|
106 if (!str)
|
|
107 return function() { return "";};
|
|
108
|
|
109 var ctx = parseTemplate(str);
|
|
110 visitTemplate(ctx);
|
|
111 return ctx.compile();
|
|
112 };
|
|
113
|
0
|
114 var cache = {};
|
|
115
|
21
|
116 compile.load = function (id, require, callback) {
|
0
|
117 var url = require.toUrl(id);
|
|
118 if (url in cache) {
|
|
119 callback(cache[url]);
|
|
120 } else {
|
21
|
121 request(url).then(compile).then(function (tc) {
|
0
|
122 callback(cache[url] = tc);
|
21
|
123 }, function (err) {
|
|
124 require.signal("error", [{
|
|
125 error: err,
|
|
126 src: 'implab/text/template-compile'
|
|
127 }]);
|
0
|
128 });
|
|
129 }
|
|
130 };
|
|
131
|
|
132 return compile;
|
|
133 }); |