total5 0.0.1-1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/503.html +65 -0
  2. package/CONTRIBUTING.md +55 -0
  3. package/LICENSE +211 -0
  4. package/README.md +32 -0
  5. package/api.js +289 -0
  6. package/bin/total5 +984 -0
  7. package/builders.js +1435 -0
  8. package/bundles.js +457 -0
  9. package/cache.js +58 -0
  10. package/changelog.txt +3 -0
  11. package/cluster.js +320 -0
  12. package/cms.js +625 -0
  13. package/controller.js +1419 -0
  14. package/cron.js +99 -0
  15. package/debug.js +539 -0
  16. package/edit.js +469 -0
  17. package/error.html +49 -0
  18. package/filestorage.js +1088 -0
  19. package/flow-flowstream.js +3152 -0
  20. package/flow.js +209 -0
  21. package/flowstream.js +1991 -0
  22. package/global.js +125 -0
  23. package/helpers/index.js +32 -0
  24. package/htmlparser.js +650 -0
  25. package/http.js +81 -0
  26. package/image.js +773 -0
  27. package/images.js +747 -0
  28. package/index.js +2658 -0
  29. package/jsonschema.js +691 -0
  30. package/ldap.js +792 -0
  31. package/mail.js +936 -0
  32. package/minificators.js +858 -0
  33. package/nosql-builder.js +440 -0
  34. package/nosql-querybuilder.js +316 -0
  35. package/nosql-reader.js +353 -0
  36. package/nosql-stream.js +617 -0
  37. package/nosql.js +763 -0
  38. package/openclient.js +219 -0
  39. package/package.json +32 -0
  40. package/pause.html +67 -0
  41. package/querybuilder.js +1361 -0
  42. package/release.js +167 -0
  43. package/routing.js +905 -0
  44. package/sourcemap.js +160 -0
  45. package/tangular.js +409 -0
  46. package/templates.js +145 -0
  47. package/templates.json +74 -0
  48. package/tms.js +384 -0
  49. package/tmsclient.js +125 -0
  50. package/todo.txt +7 -0
  51. package/tools/beta.sh +6 -0
  52. package/tools/release.sh +6 -0
  53. package/uibuilder.js +206 -0
  54. package/utils.js +6374 -0
  55. package/viewengine.js +880 -0
  56. package/websocket.js +1939 -0
  57. package/workers.js +129 -0
package/sourcemap.js ADDED
@@ -0,0 +1,160 @@
1
+ // Total.js SourceMap generator
2
+ // The MIT License
3
+ // Copyright 2023 (c) Peter Širka <petersirka@gmail.com>
4
+
5
+ var timeout = null;
6
+
7
+ function stringify(schema) {
8
+
9
+ if (typeof(schema) === 'string') {
10
+ if (schema[0] !== '@')
11
+ return schema;
12
+ schema = F.jsonschemas[schema.substring(1)];
13
+ }
14
+
15
+ if (!schema)
16
+ return undefined;
17
+
18
+ var builder = [];
19
+ for (let key in schema.properties) {
20
+ let name = key;
21
+ let meta = schema.properties[key];
22
+ if (schema.required && schema.required.includes(key))
23
+ name = '*' + name;
24
+
25
+ let type = '';
26
+ if (meta.type === 'array')
27
+ type = '[' + meta.items.subtype + (meta.items.maxLength ? ('(' + meta.items.maxLength + ')') : '') + ']';
28
+ else
29
+ type = (meta.subtype || meta.type) + (meta.maxLength ? ('(' + meta.maxLength + ')') : '');
30
+
31
+ builder.push(name + ':' + type);
32
+ }
33
+
34
+ return builder.join(',');
35
+ }
36
+
37
+ exports.create = function() {
38
+
39
+ var actions = [];
40
+ var routes = [];
41
+ var items = [];
42
+
43
+ for (let key in F.actions) {
44
+ let action = F.actions[key];
45
+ let permissions = action.permissions instanceof Array ? action.permissions.join(',') : action.permissions;
46
+ items.push({ action: key, name: action.name, summary: action.summary, params: stringify(action.params), input: stringify(action.input), output: stringify(action.output), query: stringify(action.query), permissions: permissions, owner: action.$owner });
47
+ actions.push({ name: key, params: stringify(action.params), input: stringify(action.input), output: stringify(action.output), query: stringify(action.query), user: action.user, permissions: permissions, public: action.public, publish: action.publish, owner: action.$owner });
48
+ }
49
+
50
+ for (let route of F.routes.routes) {
51
+
52
+ let m = {};
53
+ m.method = route.method;
54
+ m.url = route.url2;
55
+ m.auth = route.auth;
56
+
57
+ if (route.params && route.params.length) {
58
+ m.params = [];
59
+ for (let param of route.params)
60
+ m.params.push(param.name + ':' + param.type);
61
+ m.params = m.params.join(',');
62
+ }
63
+
64
+ if (route.timeout)
65
+ m.timeout = route.timeout;
66
+
67
+ if (route.flags.upload) {
68
+ m.upload = true;
69
+ m.limit = route.size / 1024;
70
+ }
71
+
72
+ if (route.api) {
73
+
74
+ for (let key in route.api) {
75
+
76
+ let tmp = CLONE(m);
77
+ let api = route.api[key];
78
+
79
+ tmp.id = key;
80
+ tmp.method = 'API';
81
+ tmp.auth = api.auth;
82
+ tmp.params = undefined;
83
+
84
+ let name = (api.actions.split(',')[0] || '').replaceAll('(response)', '').trim();
85
+ if (name) {
86
+ let action = F.actions[name];
87
+ if (action) {
88
+ tmp.input = action.input;
89
+
90
+ if (tmp.input && tmp.input[0] === '@')
91
+ tmp.input = stringify(F.jsonschemas[tmp.input.substring(1)]);
92
+
93
+ tmp.query = action.query;
94
+ if (tmp.query && tmp.query[0] === '@')
95
+ tmp.query = stringify(F.jsonschemas[tmp.query.substring(1)]);
96
+
97
+ if (api.params && api.params.length) {
98
+ m.params = [];
99
+ for (let param of api.params)
100
+ m.params.push(param.name + ':' + (param.type || 'string'));
101
+ tmp.params = m.params.join(',');
102
+ }
103
+ } else
104
+ tmp.error = 'Action not found';
105
+ } else
106
+ tmp.error = 'Action not found';
107
+ routes.push(tmp);
108
+ }
109
+
110
+ continue;
111
+ }
112
+
113
+ routes.push(m);
114
+ }
115
+
116
+ for (let route of F.routes.websockets) {
117
+
118
+ let m = {};
119
+
120
+ m.method = 'SOCKET';
121
+ m.url = route.url2;
122
+ m.auth = route.auth;
123
+
124
+ if (route.params && route.params.length) {
125
+ m.params = [];
126
+ for (let param of route.params)
127
+ m.params.push(param.name + ':' + param.type);
128
+ m.params = m.params.join(',');
129
+ }
130
+
131
+ routes.push(m);
132
+ }
133
+
134
+ var output = {};
135
+
136
+ output.routes = routes;
137
+ output.plugins = [];
138
+ output.actions = actions;
139
+
140
+ for (let key in F.plugins) {
141
+ let plugin = F.plugins[key];
142
+ let permissions = [];
143
+ if (plugin.permissions instanceof Array) {
144
+ for (let permission of plugin.permissions)
145
+ permissions.push(permission.id || permission);
146
+ }
147
+ output.plugins.push({ id: key, name: plugin.name, permissions: permissions.join(',') });
148
+ }
149
+
150
+ return output;
151
+ };
152
+
153
+ exports.refresh = function() {
154
+
155
+ if (!F.isloaded || !F.config.$sourcemap || F.id)
156
+ return;
157
+
158
+ timeout && clearTimeout(timeout);
159
+ timeout = setTimeout(() => F.Fs.writeFile(process.mainModule.filename + '.map', JSON.stringify(F.sourcemap(), (key, value) => value == '' || value == null ? undefined : value, '\t'), NOOP), 1000);
160
+ };
package/tangular.js ADDED
@@ -0,0 +1,409 @@
1
+ // Tangular template engine
2
+ // The MIT License
3
+ // Copyright 2017-2023 (c) Peter Širka <petersirka@gmail.com>
4
+
5
+ (function(W) {
6
+
7
+ if (W.Tangular)
8
+ return;
9
+
10
+ var Tangular = {};
11
+ var Thelpers = Tangular.helpers = {};
12
+
13
+ Tangular.version = 'v5.0.5';
14
+ Tangular.cache = {};
15
+
16
+ W.Ta = W.Tangular = Tangular;
17
+ W.Thelpers = Thelpers;
18
+
19
+ var SKIP = { 'null': true, 'undefined': true, 'true': true, 'false': true, 'Object': 1, 'String': 1, 'Number': 1, 'Boolean': 1, 'Date': 1, 'Array': 1, 'window': 1, 'global': 1, 'arguments': 1, 'eval': 1, 'Function': 1, 'function': 1, 'var': 1, 'let': 1, 'const': 1, 'delete': 1 };
20
+ var REG_CMDFIND = /\{\{.*?\}\}/g;
21
+ var REG_CMDCLEAN = /\{\{|\}\}/g;
22
+ var REG_ENCODE = /[<>&"]/g;
23
+ var REG_TRIM = /\n$/g;
24
+
25
+ function parseInlineVariables(line, blacklist) {
26
+
27
+ var tmp = '';
28
+ var variables = [];
29
+ var skip = 0;
30
+
31
+ for (var i = 0; i < line.length; i++) {
32
+
33
+ var c = line.charCodeAt(i);
34
+
35
+ if (!skip) {
36
+
37
+ if ((tmp && c > 47 && c < 58) || (c > 64 && c < 91) || (c > 96 && c < 123) || (c === 95 || c === 36)) {
38
+ tmp += line.charAt(i);
39
+ continue;
40
+ }
41
+
42
+ if (tmp) {
43
+ if (!SKIP[tmp] && variables.indexOf(tmp) === -1 && (!blacklist || blacklist.indexOf(tmp) === -1))
44
+ variables.push(tmp);
45
+ tmp = '';
46
+ }
47
+ }
48
+
49
+ if (c === 46 || c === 124) { // "." or "|"
50
+ skip = c;
51
+ } else if ((skip === 46 || skip === 124) && c === 40) { // ("." or "|") and "("
52
+ skip = 0;
53
+ } else if (c === 96 || c === 34 || c === 39) { // "`" or "'" or "\""
54
+ if (c === skip)
55
+ skip = 0;
56
+ else
57
+ skip = c;
58
+ }
59
+ }
60
+
61
+ if (tmp && !SKIP[tmp] && variables.indexOf(tmp) === -1 && (!blacklist || blacklist.indexOf(tmp) === -1))
62
+ variables.push(tmp);
63
+
64
+ return variables;
65
+ }
66
+
67
+ Tangular.toArray = function(obj) {
68
+ var keys = Object.keys(obj);
69
+ var arr = [];
70
+ for (var i = 0, length = keys.length; i < length; i++)
71
+ arr.push({ key: keys[i], value: obj[keys[i]] });
72
+ return arr;
73
+ };
74
+
75
+ function Template() {
76
+ this.commands;
77
+ this.variables;
78
+ this.builder;
79
+ this.split = '\0';
80
+ }
81
+
82
+ Template.prototype.compile = function(template, tagbeg, tagend) {
83
+
84
+ var self = this;
85
+ var ifcount = 0;
86
+ var loopcount = 0;
87
+ var loops = [];
88
+ var reg_find = REG_CMDFIND;
89
+ var reg_clean = REG_CMDCLEAN;
90
+ var tmp;
91
+
92
+ if (tagbeg && tagend) {
93
+ reg_find = new RegExp(tagbeg + '.*?' + tagend, 'g');
94
+ reg_clean = new RegExp(tagbeg + '|' + tagend, 'g');
95
+ }
96
+
97
+ self.template = template;
98
+
99
+ template = template.replace(/\|\|/g, '\1');
100
+
101
+ self.variables = {};
102
+ self.commands = [];
103
+
104
+ self.builder = template.replace(reg_find, function(text) {
105
+
106
+ var cmd = text.replace(reg_clean, '').trim();
107
+ var variable = null;
108
+ var helpers = null;
109
+ var index;
110
+ var isif = false;
111
+ var isloop = false;
112
+ var iscode = true;
113
+
114
+ if (cmd === 'fi') {
115
+ ifcount--;
116
+ // end of condition
117
+ } else if (cmd === 'end') {
118
+ loopcount--;
119
+ // end of loop
120
+ loops.pop();
121
+ } else if (cmd.substring(0, 3) === 'if ') {
122
+ // condition
123
+ ifcount++;
124
+ variable = parseInlineVariables(cmd.substring(3), loops);
125
+ if (variable.length) {
126
+ for (var i = 0; i < variable.length; i++) {
127
+ var name = variable[i];
128
+ if (self.variables[name])
129
+ self.variables[name]++;
130
+ else
131
+ self.variables[name] = 1;
132
+ }
133
+ } else
134
+ variable = null;
135
+ isif = true;
136
+ iscode = true;
137
+ } else if (cmd.substring(0, 8) === 'foreach ') {
138
+
139
+ loopcount++;
140
+ // loop
141
+
142
+ tmp = cmd.substring(8).split(' ');
143
+ loops.push(tmp[0].trim());
144
+
145
+ index = tmp[2].indexOf('.');
146
+ if (index !== -1)
147
+ tmp[2] = tmp[2].substring(0, index);
148
+
149
+ variable = tmp[2].trim();
150
+
151
+ if (loops.indexOf(variable) === -1) {
152
+ if (self.variables[variable])
153
+ self.variables[variable]++;
154
+ else
155
+ self.variables[variable] = 1;
156
+ variable = [variable];
157
+ }
158
+ else
159
+ variable = null;
160
+
161
+ isloop = true;
162
+ } else if (cmd.substring(0, 8) === 'else if ') {
163
+ // else if
164
+ variable = parseInlineVariables(cmd.substring(8), loops);
165
+ if (variable.length) {
166
+ for (var i = 0; i < variable.length; i++) {
167
+ var name = variable[i];
168
+ if (self.variables[name])
169
+ self.variables[name]++;
170
+ else
171
+ self.variables[name] = 1;
172
+ }
173
+ } else
174
+ variable = null;
175
+ isif = true;
176
+ } else if (cmd !== 'continue' && cmd !== 'break' && cmd !== 'else') {
177
+
178
+ variable = parseInlineVariables(cmd);
179
+
180
+ var ishelper = false;
181
+
182
+ for (var i = 0; i < variable.length; i++) {
183
+ var v = variable[i];
184
+
185
+ if (v + '(' === cmd.substring(0, v.length + 1)) {
186
+ ishelper = true;
187
+ continue;
188
+ }
189
+
190
+ if (self.variables[v])
191
+ self.variables[v]++;
192
+ else
193
+ self.variables[v] = 1;
194
+ }
195
+
196
+ if (!variable.length)
197
+ variable = null;
198
+
199
+ var hindex = cmd.indexOf('|');
200
+ var fnhelper = null;
201
+
202
+ if (ishelper) {
203
+ fnhelper = cmd.substring(0, hindex === -1 ? cmd.length : hindex);
204
+ if (hindex === -1)
205
+ cmd = '';
206
+ else
207
+ cmd = '' + cmd.substring(index);
208
+ } else if (!ishelper && hindex === -1)
209
+ cmd += ' | encode';
210
+
211
+ helpers = cmd.split('|');
212
+ cmd = helpers[0];
213
+ helpers = helpers.slice(1);
214
+
215
+ if (ishelper)
216
+ helpers.unshift(fnhelper);
217
+
218
+ if (helpers.length) {
219
+ for (var i = 0; i < helpers.length; i++) {
220
+ var helper = helpers[i].trim();
221
+ var ishelperfirst = ishelper && !i;
222
+ index = helper.indexOf('(');
223
+ if (index === -1) {
224
+ helper = 'Thelpers.$execute($helpers,model,\'' + helper + '\',' + (ishelperfirst ? '' : '\7)');
225
+ } else
226
+ helper = 'Thelpers.$execute($helpers,model,\'' + helper.substring(0, index) + '\',' + (ishelperfirst ? '' : '\7,') + helper.substring(index + 1);
227
+ helpers[i] = helper;
228
+ }
229
+ } else
230
+ helpers = null;
231
+
232
+ cmd = self.safe(cmd.trim() || 'model');
233
+ iscode = false;
234
+ }
235
+
236
+ self.commands.push({ index: self.commands.length, cmd: cmd, ifcount: ifcount, loopcount: loopcount, variable: variable, helpers: helpers, isloop: isloop, isif: isif, iscode: iscode });
237
+
238
+ return self.split;
239
+
240
+ }).split(self.split);
241
+
242
+ for (var i = 0; i < self.builder.length; i++) {
243
+ var m = self.builder[i];
244
+ self.builder[i] = m ? m.replace(REG_TRIM, '') : m;
245
+ }
246
+
247
+ return self.make();
248
+ };
249
+
250
+ Template.prototype.safe = function(cmd) {
251
+
252
+ var arr = cmd.split('.');
253
+ var output = [];
254
+
255
+ for (var i = 1; i < arr.length; i++) {
256
+ var k = arr.slice(0, i).join('.');
257
+ output.push(k + '==null?\'\':');
258
+ }
259
+ return output.join('') + arr.join('.');
260
+ };
261
+
262
+ Template.prototype.make = function() {
263
+
264
+ var self = this;
265
+ var builder = ['var $output=$text[0];var $tmp;var $index=0;'];
266
+
267
+ for (var i = 0, length = self.commands.length; i < length; i++) {
268
+
269
+ var cmd = self.commands[i];
270
+ var tmp;
271
+
272
+ i && builder.push('$output+=$text[' + i + '];');
273
+
274
+ if (cmd.iscode) {
275
+
276
+ if (cmd.isloop) {
277
+
278
+ var name = '$i' + Math.random().toString(16).substring(3, 6);
279
+ var namea = name + 'a';
280
+ var index = cmd.cmd.lastIndexOf(' in ');
281
+ if (index === -1)
282
+ index = cmd.cmd.lastIndexOf(' of ');
283
+ tmp = cmd.cmd.substring(index + 4).trim();
284
+ tmp = namea + '=' + self.safe(tmp) + ';if(!(' + namea + ' instanceof Array)){if(' + namea + '&&typeof(' + namea + ')===\'object\')' + namea + '=Tangular.toArray(' + namea + ')}if(' + namea + ' instanceof Array&&' + namea + '.length){for(var ' + name + '=0,' + name + 'l=' + namea + '.length;' + name + '<' + name + 'l;' + name + '++){$index=' + name + ';var ' + cmd.cmd.split(' ')[1] + '=' + namea + '[' + name + '];';
285
+ builder.push(tmp);
286
+
287
+ } else if (cmd.isif) {
288
+ if (cmd.cmd.substring(0, 8) === 'else if ')
289
+ builder.push('}' + cmd.cmd.substring(0, 8).trim() + '(' + cmd.cmd.substring(8).trim() + '){');
290
+ else
291
+ builder.push(cmd.cmd.substring(0, 3).trim() + '(' + cmd.cmd.substring(3).trim() + '){');
292
+ } else {
293
+ switch (cmd.cmd) {
294
+ case 'else':
295
+ builder.push('}else{');
296
+ break;
297
+ case 'end':
298
+ builder.push('}}');
299
+ break;
300
+ case 'fi':
301
+ builder.push('}');
302
+ break;
303
+ case 'break':
304
+ builder.push('break;');
305
+ break;
306
+ case 'continue':
307
+ builder.push('continue;');
308
+ break;
309
+ }
310
+ }
311
+
312
+ } else {
313
+ if (cmd.helpers) {
314
+ var str = '';
315
+ for (var j = 0; j < cmd.helpers.length; j++) {
316
+ var helper = cmd.helpers[j];
317
+ if (j === 0)
318
+ str = helper.replace('\7', cmd.cmd.trim()).trim();
319
+ else
320
+ str = helper.replace('\7', str.trim());
321
+ }
322
+ builder.push('$tmp=' + str + ';if($tmp!=null)$output+=$tmp;');
323
+ } else
324
+ builder.push('if(' + cmd.cmd + '!=null)$output+=' + cmd.cmd + ';');
325
+ }
326
+ }
327
+
328
+ builder.push((length ? ('$output+=$text[' + length + '];') : '') + 'return $output.charAt(0) === \'\\n\'?$output.substring(1):$output;');
329
+ delete self.variables.$;
330
+ var variables = Object.keys(self.variables);
331
+ var names = ['$helpers||{}', '$||{}', 'model'];
332
+
333
+ for (var i = 0; i < variables.length; i++)
334
+ names.push('model.' + variables[i]);
335
+
336
+ for (var i = 0; i < self.builder.length; i++)
337
+ self.builder[i] = self.builder[i].replace(/\1/g, '||');
338
+
339
+ var code = 'var tangular=function($helpers,$,model' + (variables.length ? (',' + variables.join(',')) : '') + '){' + builder.join('') + '};return function(model,$,$helpers){try{return tangular(' + names.join(',') + ')}catch(e){console.error(\'Tangular error:\',e + \'\',$template)}}';
340
+ return (new Function('$text', '$template', code.replace(/\1/g, '||')))(self.builder, self.template);
341
+ };
342
+
343
+ Thelpers.$execute = function(helpers, model, name, a, b, c, d, e, f, g, h) {
344
+
345
+ var fn = helpers[name] || Thelpers[name];
346
+
347
+ if (!fn) {
348
+ console && console.warn('Tangular: missing helper', '"' + name + '"');
349
+ return a;
350
+ }
351
+
352
+ return fn.call(model, a, b, c, d, e, f, g, h);
353
+ };
354
+
355
+ Thelpers.encode = function(value, type) {
356
+
357
+ if (type) {
358
+
359
+ if (typeof(type) === 'function')
360
+ return type(value);
361
+
362
+ if (type === 'json')
363
+ return JSON.stringify(value);
364
+
365
+ if (type === 'json2')
366
+ return JSON.stringify(value, null, '\t');
367
+
368
+ if (type === 'url' || type === 'urlencoded')
369
+ return encodeURIComponent(value);
370
+
371
+ if (type === 'querify')
372
+ return QUERIFY(value);
373
+ }
374
+
375
+ return value == null ? '' : (value + '').replace(REG_ENCODE, function(c) {
376
+ switch (c) {
377
+ case '&': return '&amp;';
378
+ case '<': return '&lt;';
379
+ case '>': return '&gt;';
380
+ case '"': return '&quot;';
381
+ }
382
+ return c;
383
+ });
384
+ };
385
+
386
+ Thelpers.raw = function(value) {
387
+ return value;
388
+ };
389
+
390
+ Tangular.render = function(template, model, repository, helpers) {
391
+ var template = new Template().compile(template);
392
+ return template(model == null ? {} : model, repository, helpers);
393
+ };
394
+
395
+ Tangular.compile = function(template, tagbeg, tagend) {
396
+ return new Template().compile(template, tagbeg, tagend);
397
+ };
398
+
399
+ Tangular.register = function(name, fn) {
400
+ Thelpers[name] = fn;
401
+ return Tangular;
402
+ };
403
+
404
+ Thelpers.pluralize = function(r,e,t,a,n){ return r||(r=0),'number'!=typeof r&&(r=parseFloat(r.toString().replace(/\s/g,'').replace(',','.'))),r.pluralize(e,t,a,n)};
405
+ Thelpers.format=function(r,e,t,a){var n=typeof r;if(r==0||r==null)return'';if('number'===n||r instanceof Date)return r.format(e==null?null:e,t,a);'string'!==n&&(r=r.toString()),r=r.trim();for(var i=!1,o=0,f=0,u=0,l=r.length;l>u;u++){var g=r.charCodeAt(u);if(58===g||32===g||84===g){i=!0;break;}if(45===g){if(o++,1===o)continue;i=!0;break;}if(46===g){if(f++,1===f)continue;i=!0;break;}}return i?r.parseDate().format(e||'dd.MM.yyyy'):r.parseFloat().format(e,t,a)};
406
+ Thelpers.empty=Thelpers.def=function(e,n){return e?Thelpers.encode(e):n||'---'};
407
+ Thelpers.currency=function(e,t){switch(typeof e){case'number':return e.currency(t);case'string':return e.parseFloat().currency(t);default:return''}};
408
+
409
+ })(global);
package/templates.js ADDED
@@ -0,0 +1,145 @@
1
+ // Total.js Templates
2
+ // The MIT License
3
+ // Copyright 2023 (c) Peter Širka <petersirka@gmail.com>
4
+
5
+ exports.render = function(body, model, $) {
6
+ return new Promise(function(resolve, reject) {
7
+
8
+ var cache = F.temporary.templates;
9
+ var id = 'Ttemplate' + HASH(body);
10
+ var data = cache[id];
11
+
12
+ if (data) {
13
+ try {
14
+ resolve(data.template({ value: model || data.model }, null, data.helpers));
15
+ } catch (e) {
16
+ if ($ && $.invalid)
17
+ $.invalid(e);
18
+ else
19
+ reject(e);
20
+ }
21
+ return;
22
+ }
23
+
24
+ if (body.indexOf('{{') === -1) {
25
+
26
+ // URL address or filename
27
+ data = cache[id];
28
+
29
+ var start = body.substring(0, 7);
30
+ // http://
31
+ // https:/
32
+
33
+ if (start === 'http://' || start === 'https:/') {
34
+ // download template
35
+ var opt = {};
36
+ opt.url = body;
37
+ opt.method = 'GET';
38
+ opt.$ = function(err, response) {
39
+
40
+ if (err) {
41
+ if ($ && $.invalid)
42
+ $.invalid(err);
43
+ else
44
+ reject(err);
45
+ return;
46
+ }
47
+
48
+ data = parse(response.body);
49
+ cache[id] = data;
50
+
51
+ try {
52
+ resolve(data.template({ value: model || data.model }, null, data.helpers));
53
+ } catch (e) {
54
+ if ($ && $.invalid)
55
+ $.invalid(e);
56
+ else
57
+ reject(e);
58
+ }
59
+ };
60
+ REQUEST(opt);
61
+ return;
62
+ } else {
63
+
64
+ if (body[0] === '~') {
65
+ body = body.substring(1);
66
+ } else {
67
+ body = F.path.templates(body);
68
+ if (body.indexOf('.html') === -1)
69
+ body += '.html';
70
+ }
71
+
72
+ F.Fs.readFile(body, function(err, response) {
73
+
74
+ if (err) {
75
+ if ($ && $.invalid)
76
+ $.invalid(err);
77
+ else
78
+ reject(err);
79
+ return;
80
+ }
81
+
82
+ data = parse(response.toString('utf8'));
83
+
84
+ if (!DEBUG)
85
+ cache[id] = data;
86
+
87
+ try {
88
+ resolve(data.template({ value: model || data.model }, null, data.helpers));
89
+ } catch (e) {
90
+ if ($ && $.invalid)
91
+ $.invalid(e);
92
+ else
93
+ reject(e);
94
+ }
95
+
96
+ });
97
+ return;
98
+ }
99
+ }
100
+
101
+ data = cache[id] = parse(body);
102
+
103
+ try {
104
+ resolve(data.template({ value: model || data.model }, null, data.helpers));
105
+ } catch (e) {
106
+ if ($ && $.invalid)
107
+ $.invalid(e);
108
+ else
109
+ reject(e);
110
+ }
111
+ });
112
+ };
113
+
114
+ function parse(body) {
115
+
116
+ var helpers = {};
117
+ var model = EMPTYOBJECT;
118
+ var strhelpers = '';
119
+ var beg = body.indexOf('<scr' + 'ipt>');
120
+ var end;
121
+
122
+ // helpers
123
+ if (beg !== -1) {
124
+ end = body.indexOf('</scr' + 'ipt>', beg + 8);
125
+ strhelpers = body.substring(beg + 8, end).trim();
126
+ body = body.substring(0, beg) + body.substring(end + 9);
127
+ }
128
+
129
+ // model
130
+ beg = body.indexOf('<scr' + 'ipt type="text/json">');
131
+ if (beg !== -1) {
132
+ end = body.indexOf('</scr' + 'ipt>', beg + 8);
133
+ model = body.substring(beg + 25, end).trim().parseJSON(true);
134
+ body = body.substring(0, beg) + body.substring(end + 9);
135
+ }
136
+
137
+ if (strhelpers)
138
+ new Function('Thelpers', strhelpers)(helpers);
139
+
140
+ var output = {};
141
+ output.helpers = helpers;
142
+ output.template = Tangular.compile(body);
143
+ output.model = model;
144
+ return output;
145
+ }