total5 0.0.1 → 0.0.2

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.
package/viewengine.js ADDED
@@ -0,0 +1,891 @@
1
+ // Total.js ViewEngine
2
+ // The MIT License
3
+ // Copyright 2014-2023 (c) Peter Širka <petersirka@gmail.com>
4
+
5
+ const REG_NOCOMPRESS = /@\{nocompress\s\w+}/gi;
6
+ const REG_TAGREMOVE = /[^>](\r)\n\s{1,}$/;
7
+ const REG_HELPERS = /helpers\.[a-z0-9A-Z_$]+\(.*?\)+/g;
8
+ const REG_CHECKCSS = /\.css(\s|\+)?/;
9
+ const VIEW_IF = { 'if ': 1, 'if(': 1 };
10
+
11
+ exports.cache = [];
12
+ exports.compile = function(name, content, debug = true) {
13
+
14
+ if (F.$events.$view) {
15
+ let meta = { name: name, body: content, debug: debug };
16
+ F.emit('$view', meta);
17
+ content = meta.body;
18
+ }
19
+
20
+ content = F.TMinificators.htmlremovecomments(content).ROOT();
21
+
22
+ var nocompressHTML = false;
23
+ var nocompressJS = false;
24
+ var nocompressCSS = false;
25
+
26
+ content = content.replace(REG_NOCOMPRESS, function(text) {
27
+
28
+ var index = text.lastIndexOf(' ');
29
+ if (index === -1)
30
+ return '';
31
+
32
+ switch (text.substring(index, text.length - 1).trim()) {
33
+ case 'all':
34
+ nocompressHTML = true;
35
+ nocompressJS = true;
36
+ nocompressCSS = true;
37
+ break;
38
+ case 'html':
39
+ nocompressHTML = true;
40
+ break;
41
+ case 'js':
42
+ case 'script':
43
+ case 'javascript':
44
+ nocompressJS = true;
45
+ break;
46
+ case 'css':
47
+ case 'style':
48
+ nocompressCSS = true;
49
+ break;
50
+ }
51
+
52
+ return '';
53
+
54
+ }).trim();
55
+
56
+ if (!nocompressJS)
57
+ content = F.TMinificators.htmljs(content);
58
+
59
+ if (!nocompressCSS)
60
+ content = F.TMinificators.htmlcss(content);
61
+
62
+ if (!nocompressHTML)
63
+ content = minify(content);
64
+
65
+ var DELIMITER = '\'';
66
+ var SPACE = ' ';
67
+ var builder = 'var $EMPTY=\'\';var $length=0;var $source=null;var $tmp=index;var $output=$EMPTY';
68
+ var command = findcommand(content, 0);
69
+ var isFirst = false;
70
+ var txtindex = -1;
71
+ var index = 0;
72
+ var isCookie = false;
73
+
74
+ function escaper(value) {
75
+
76
+ var is = REG_TAGREMOVE.test(value);
77
+
78
+ if (!isFirst) {
79
+ isFirst = true;
80
+ value = value.replace(/^\s+/, '');
81
+ }
82
+
83
+ if (!value)
84
+ return '$EMPTY';
85
+
86
+ if (!nocompressHTML && is)
87
+ value += ' ';
88
+
89
+ txtindex = exports.cache.indexOf(value);
90
+
91
+ if (txtindex === -1) {
92
+ txtindex = exports.cache.length;
93
+ exports.cache.push(value);
94
+ }
95
+
96
+ return 'F.TViewEngine.cache[' + txtindex + ']';
97
+ }
98
+
99
+ if (!command)
100
+ builder += '+' + escaper(content);
101
+
102
+ index = 0;
103
+
104
+ var old = null;
105
+ var newCommand = '';
106
+ var tmp = '';
107
+ var counter = 0;
108
+ var functions = [];
109
+ var functionNames = [];
110
+ var isFN = false;
111
+ var isSECTION = false;
112
+ var isCOMPILATION = false;
113
+ var builderTMP = '';
114
+ var sectionName = '';
115
+ var components = {};
116
+ var text;
117
+
118
+ while (command) {
119
+
120
+ if (!isCookie && command.command.indexOf('cookie') !== -1)
121
+ isCookie = true;
122
+
123
+ if (old) {
124
+ text = content.substring(old.end + 1, command.beg);
125
+ if (text) {
126
+ if (parseplus(builder))
127
+ builder += '+';
128
+ builder += escaper(text);
129
+ }
130
+ } else {
131
+ text = content.substring(0, command.beg);
132
+ if (text) {
133
+ if (parseplus(builder))
134
+ builder += '+';
135
+ builder += escaper(text);
136
+ }
137
+ }
138
+
139
+ var cmd = content.substring(command.beg + 2, command.end).trim();
140
+
141
+ var cmd8 = cmd.substring(0, 8);
142
+ var cmd7 = cmd.substring(0, 7);
143
+
144
+ if (cmd === 'continue' || cmd === 'break') {
145
+ builder += ';' + cmd + ';';
146
+ old = command;
147
+ command = findcommand(content, command.end);
148
+ continue;
149
+ }
150
+
151
+ // cmd = cmd.replace
152
+ command.command = command.command.replace(REG_HELPERS, function(text) {
153
+ var index = text.indexOf('(');
154
+ return index === - 1 ? text : text.substring(0, index) + '.call(self' + (text.endsWith('()') ? ')' : ',' + text.substring(index + 1));
155
+ });
156
+
157
+ if (cmd[0] === '\'' || cmd[0] === '"') {
158
+ if (cmd[1] === '%') {
159
+ var t = F.config[cmd.substring(2, cmd.length - 1)];
160
+ if (t != null)
161
+ builder += '+' + DELIMITER + (t + '').safehtml().replace(/'/g, "\\'") + DELIMITER;
162
+ }
163
+ // else
164
+ // builder += '+' + DELIMITER + (new Function('self', 'return self.import(' + cmd[0] + '!' + cmd.substring(1) + ')'))(controller) + DELIMITER;
165
+ } else if (cmd7 === 'compile' && cmd.lastIndexOf(')') === -1) {
166
+
167
+ builderTMP = builder + '+(DEF.onViewCompile.call(self,\'' + (cmd8[7] === ' ' ? cmd.substring(8).trim() : '') + '\',';
168
+ builder = '';
169
+ sectionName = cmd.substring(8);
170
+ isCOMPILATION = true;
171
+ isFN = true;
172
+
173
+ } else if (cmd8 === 'section ' && cmd.lastIndexOf(')') === -1) {
174
+ builderTMP = builder;
175
+ builder = '+(function(){var $output=$EMPTY';
176
+ sectionName = cmd.substring(8);
177
+ isSECTION = true;
178
+ isFN = true;
179
+ } else if (cmd7 === 'helper ') {
180
+
181
+ builderTMP = builder;
182
+ builder = 'function ' + cmd.substring(7).trim() + '{var $output=$EMPTY';
183
+ isFN = true;
184
+ functionNames.push(cmd.substring(7, cmd.indexOf('(', 7)).trim());
185
+
186
+ } else if (cmd8 === 'foreach ') {
187
+
188
+ counter++;
189
+
190
+ if (cmd.indexOf('foreach var ') !== -1)
191
+ cmd = cmd.replace(' var ', SPACE);
192
+
193
+ newCommand = (cmd.substring(8, cmd.indexOf(SPACE, 8)) || '').trim();
194
+ index = cmd.trim().indexOf(SPACE, newCommand.length + 10);
195
+
196
+ if (index === -1)
197
+ index = cmd.indexOf('[', newCommand.length + 10);
198
+
199
+ builder += '+(function(){var $source=' + cmd.substring(index).trim() + ';if(!($source instanceof Array))$source=self.ota($source);if(!$source.length)return $EMPTY;var $length=$source.length;var $output=$EMPTY;var index=0;for(var $i=0;$i<$length;$i++){index=$i;var ' + newCommand + '=$source[$i];$output+=$EMPTY';
200
+ } else if (cmd === 'end') {
201
+
202
+ if (isFN && counter <= 0) {
203
+ counter = 0;
204
+
205
+ if (isCOMPILATION) {
206
+ builder = builderTMP + 'unescape($EMPTY' + builder + '),model) || $EMPTY)';
207
+ builderTMP = '';
208
+ } else if (isSECTION) {
209
+ builder = builderTMP + builder + ';repository[\'section_' + sectionName + '\']=repository[\'section_' + sectionName + '\']?repository[\'section_' + sectionName + '\']+$output:$output;return $EMPTY})()';
210
+ builderTMP = '';
211
+ } else {
212
+ builder += ';return $output;}';
213
+ functions.push(builder);
214
+ builder = builderTMP;
215
+ builderTMP = '';
216
+ }
217
+
218
+ isSECTION = false;
219
+ isCOMPILATION = false;
220
+ isFN = false;
221
+
222
+ } else {
223
+ counter--;
224
+ builder += '}return $output})()';
225
+ newCommand = '';
226
+ }
227
+
228
+ } else if (VIEW_IF[cmd.substring(0, 3)]) {
229
+ builder += ';if (' + (cmd.substring(2, 3) === '(' ? '(' : '') + cmd.substring(3) + '){$output+=$EMPTY';
230
+ } else if (cmd7 === 'else if') {
231
+ builder += '} else if (' + cmd.substring(7) + ') {$output+=$EMPTY';
232
+ } else if (cmd === 'else') {
233
+ builder += '} else {$output+=$EMPTY';
234
+ } else if (cmd === 'endif' || cmd === 'fi') {
235
+ builder += '}$output+=$EMPTY';
236
+ } else {
237
+ tmp = prepare(command.command, newCommand, functionNames);
238
+ if (tmp) {
239
+ if (parseplus(builder))
240
+ builder += '+';
241
+ if (tmp.substring(1, 4) !== '@{-' && tmp.substring(0, 11) !== 'self.view')
242
+ builder += trycatch(tmp, command.command, command.line, debug);
243
+ else
244
+ builder += tmp;
245
+ }
246
+ }
247
+
248
+ old = command;
249
+ command = findcommand(content, command.end);
250
+ }
251
+
252
+ if (old) {
253
+ text = content.substring(old.end + 1);
254
+ if (text)
255
+ builder += '+' + escaper(text);
256
+ }
257
+
258
+ if (!debug)
259
+ builder = builder.replace(/(\+\$EMPTY\+)/g, '+').replace(/(\$output=\$EMPTY\+)/g, '$output=').replace(/(\$output\+=\$EMPTY\+)/g, '$output+=').replace(/(\}\$output\+=\$EMPTY)/g, '}').replace(/(\{\$output\+=\$EMPTY;)/g, '{').replace(/(\+\$EMPTY\+)/g, '+').replace(/(>'\+'<)/g, '><').replace(/'\+'/g, '');
260
+
261
+ var fn = ('(function(self){var model=self.model;var config=F.config;var ctrl=self.controller;var query=ctrl?.query || EMPTYOBJECT,repository=self.repository,controller=self.controller,files=ctrl?.files || EMPTYARRAY,user=ctrl?.user,session=ctrl?.session,body=ctrl?.body,language=ctrl?.language || \'\'' + (isCookie ? ',cookie=name=>ctrl?ctrl.cookie(name):\'\'' : '') + ';' + (nocompressHTML ? 'if(ctrl)ctrl.response.minify=false;' : '') + builder + ';return $output;})');
262
+ try {
263
+ fn = eval(fn);
264
+ } catch (e) {
265
+ throw new Error(name + ': ' + (e.message + ''));
266
+ }
267
+
268
+ return fn;
269
+ }
270
+
271
+ function trycatch(value, command, line) {
272
+ return DEBUG ? ('(function(){try{return ' + value + '}catch(e){throw new Error(unescape(\'' + escape(command) + '\') + \' - Line: ' + line + ' - \' + e.message.toString());}return $EMPTY})()') : value;
273
+ }
274
+
275
+ function parseplus(builder) {
276
+ var c = builder[builder.length - 1];
277
+ return c !== '!' && c !== '?' && c !== '+' && c !== '.' && c !== ':';
278
+ }
279
+
280
+ function prepare(command, dcommand, functions) {
281
+
282
+ var a = command.indexOf('.');
283
+ var b = command.indexOf('(');
284
+ var c = command.indexOf('[');
285
+
286
+ var max = [];
287
+ var tmp = 0;
288
+
289
+ if (a !== -1)
290
+ max.push(a);
291
+
292
+ if (b !== -1)
293
+ max.push(b);
294
+
295
+ if (c !== -1)
296
+ max.push(c);
297
+
298
+ var index = Math.min.apply(this, max);
299
+
300
+ if (index === -1)
301
+ index = command.length;
302
+
303
+ var name = command.substring(0, index);
304
+ if (name === dcommand)
305
+ return 'self.safehtml(' + command + ', 1)';
306
+
307
+ if (name[0] === '!' && name.substring(1) === dcommand)
308
+ return 'self.safehtml(' + command.substring(1) + ')';
309
+
310
+ switch (name) {
311
+
312
+ case 'foreach':
313
+ case 'end':
314
+ return '';
315
+
316
+ case 'section':
317
+ tmp = command.indexOf('(');
318
+ return tmp === -1 ? '' : '(repository[\'section_' + command.substring(tmp + 1, command.length - 1).replace(/'|"/g, '') + '\'] || \'\')';
319
+
320
+ case 'console':
321
+ case 'print':
322
+ return '(' + command + '?$EMPTY:$EMPTY)';
323
+
324
+ case '!cookie':
325
+ return 'self.safehtml(' + command + ')';
326
+
327
+ case 'csrf':
328
+ return 'self.csrf()';
329
+
330
+ case 'root':
331
+ var r = F.config.$root;
332
+ return '\'' + (r ? r.substring(0, r.length - 1) : r) + '\'';
333
+
334
+ case 'CONF':
335
+ case 'config':
336
+ case 'controller':
337
+ case 'FUNC':
338
+ case 'MAIN':
339
+ case 'model':
340
+ case 'MODS':
341
+ case 'query':
342
+ case 'REPO':
343
+ case 'repository':
344
+ case 'session':
345
+ case 'user':
346
+ return isassign(command) ? ('self.set(' + command + ')') : ('self.safehtml(' + command + ', 1)');
347
+
348
+ case 'body':
349
+ return isassign(command) ? ('self.set(' + command + ')') : command.lastIndexOf('.') === -1 ? 'self.output' : ('self.safehtml(' + command + ', 1)');
350
+
351
+ case 'break':
352
+ case 'continue':
353
+ case 'files':
354
+ case 'helpers':
355
+ case 'language':
356
+ case 'mobile':
357
+ case 'robot':
358
+ return command;
359
+
360
+ case 'cookie':
361
+ case 'functions':
362
+ return 'self.safehtml(' + command + ', 1)';
363
+
364
+ case '!body':
365
+ case '!CONF':
366
+ case '!controller':
367
+ case '!FUNC':
368
+ case '!function':
369
+ case '!model':
370
+ case '!MODS':
371
+ case '!query':
372
+ case '!repository':
373
+ case '!session':
374
+ case '!user':
375
+ return 'self.safehtml(' + command.substring(1) + ')';
376
+
377
+ case 'host':
378
+ case 'hostname':
379
+ return 'self.hostname';
380
+
381
+ case 'href':
382
+ return command.indexOf('(') === -1 ? 'self.href()' : 'self.' + command;
383
+
384
+ case 'url':
385
+ return 'self.' + command;
386
+
387
+ case 'title':
388
+ case 'description':
389
+ case 'keywords':
390
+ case 'author':
391
+ return command.indexOf('(') === -1 ? '((repository[\'' + command + '\'] || \'\') + \'\').safehtml()' : 'self.' + command;
392
+
393
+ case 'title2':
394
+ return 'self.' + command;
395
+
396
+ case '!title':
397
+ case '!description':
398
+ case '!keywords':
399
+ case '!author':
400
+ return '(repository[\'' + command.substring(1) + '\'] || \'\')';
401
+
402
+ case 'place':
403
+ return command.indexOf('(') === -1 ? '(repository[\'' + command + '\'] || \'\')' : 'self.' + command;
404
+
405
+ case 'import':
406
+ return 'self.' + command + (command.indexOf('(') === -1 ? '()' : '');
407
+
408
+ case 'index':
409
+ return '(' + command + ')';
410
+
411
+ case 'json':
412
+ case 'json2':
413
+ case 'helper':
414
+ case 'view':
415
+ case 'layout':
416
+ case 'download':
417
+ case 'selected':
418
+ case 'disabled':
419
+ case 'checked':
420
+ case 'options':
421
+ case 'readonly':
422
+ return 'self.' + command;
423
+
424
+ case 'now':
425
+ return '(new Date()' + command.substring(3) + ')';
426
+
427
+ default:
428
+ return F.def.helpers[name] ? ('F.def.helpers.' + insertcall(command)) : ('self.safehtml(' + (functions.indexOf(name) === -1 ? command[0] === '!' ? command.substring(1) + ')' : command + ', 1)' : command + ')'));
429
+ }
430
+ }
431
+
432
+ function insertcall(command) {
433
+
434
+ var beg = command.indexOf('(');
435
+ if (beg === -1)
436
+ return command;
437
+
438
+ var length = command.length;
439
+ var count = 0;
440
+
441
+ for (var i = beg + 1; i < length; i++) {
442
+
443
+ var c = command[i];
444
+
445
+ if (c !== '(' && c !== ')')
446
+ continue;
447
+
448
+ if (c === '(') {
449
+ count++;
450
+ continue;
451
+ }
452
+
453
+ if (count > 0) {
454
+ count--;
455
+ continue;
456
+ }
457
+
458
+ var arg = command.substring(beg + 1);
459
+ return command.substring(0, beg) + '.call(self' + (arg.length > 1 ? ',' + arg : ')');
460
+ }
461
+
462
+ return command;
463
+ }
464
+
465
+ function isassign(value) {
466
+
467
+ var length = value.length;
468
+ var skip = 0;
469
+
470
+ for (var i = 0; i < length; i++) {
471
+
472
+ var c = value[i];
473
+
474
+ if (c === '[') {
475
+ skip++;
476
+ continue;
477
+ }
478
+
479
+ if (c === ']') {
480
+ skip--;
481
+ continue;
482
+ }
483
+
484
+ var next = value[i + 1] || '';
485
+
486
+ if (c === '+' && (next === '+' || next === '=')) {
487
+ if (!skip)
488
+ return true;
489
+ }
490
+
491
+ if (c === '-' && (next === '-' || next === '=')) {
492
+ if (!skip)
493
+ return true;
494
+ }
495
+
496
+ if (c === '*' && (next === '*' || next === '=')) {
497
+ if (!skip)
498
+ return true;
499
+ }
500
+
501
+ if (c === '=') {
502
+ if (!skip)
503
+ return true;
504
+ }
505
+ }
506
+ return false;
507
+ }
508
+
509
+ function findcommand(content, index, entire) {
510
+
511
+ index = content.indexOf('@{', index);
512
+
513
+ if (index === -1)
514
+ return null;
515
+
516
+ var length = content.length;
517
+ var count = 0;
518
+
519
+ for (var i = index + 2; i < length; i++) {
520
+ var c = content[i];
521
+
522
+ if (c === '{') {
523
+ count++;
524
+ continue;
525
+ }
526
+
527
+ if (c !== '}')
528
+ continue;
529
+ else if (count > 0) {
530
+ count--;
531
+ continue;
532
+ }
533
+
534
+ var command = content.substring(index + 2, i).trim();
535
+
536
+ // @{{ SKIP }}
537
+ if (command[0] === '{')
538
+ return findcommand(content, index + 1);
539
+
540
+ var obj = { beg: index, end: i, line: inlinecounter(content.substr(0, index)), command: command };
541
+
542
+ if (entire)
543
+ obj.phrase = content.substring(index, i + 1);
544
+
545
+ return obj;
546
+ }
547
+
548
+ return null;
549
+ }
550
+
551
+ function inlinecounter(value) {
552
+ var count = value.match(/\n/g);
553
+ return count ? count.length : 0;
554
+ }
555
+
556
+ function minify(html) {
557
+
558
+ var cache = [];
559
+ var beg = 0;
560
+ var end;
561
+
562
+ while (true) {
563
+ beg = html.indexOf('@{compile ', beg - 1);
564
+ if (beg === -1)
565
+ break;
566
+ end = html.indexOf('@{end}', beg + 6);
567
+ if (end === -1)
568
+ break;
569
+ cache.push(html.substring(beg, end + 6));
570
+ html = html.substring(0, beg) + '#@' + (cache.length - 1) + '#' + html.substring(end + 6);
571
+ }
572
+
573
+ while (true) {
574
+ beg = html.indexOf('@{', beg);
575
+ if (beg === -1)
576
+ break;
577
+ end = html.indexOf('}', beg + 2);
578
+ if (end === -1)
579
+ break;
580
+ cache.push(html.substring(beg, end + 1));
581
+ html = html.substring(0, beg) + '#@' + (cache.length - 1) + '#' + html.substring(end + 1);
582
+ }
583
+
584
+ html = F.TMinificators.html(html);
585
+ return html.replace(/#@\d+#/g, text => cache[+text.substring(2, text.length - 1)]);
586
+ }
587
+
588
+ function View(controller) {
589
+ var self = this;
590
+ self.controller = controller;
591
+ self.language = controller?.language || '';
592
+ self.repository = { layout: 'layout' };
593
+ self.islayout = false;
594
+ }
595
+
596
+ View.prototype.ota = function(obj) {
597
+ if (obj == null)
598
+ return EMPTYARRAY;
599
+ var output = [];
600
+ for (var key in obj)
601
+ output.push({ key: key, value: obj[key]});
602
+ return output;
603
+ };
604
+
605
+ View.prototype.layout = function(value) {
606
+ this.repository.layout = value;
607
+ return '';
608
+ };
609
+
610
+ View.prototype.json = function(obj, id, beautify, replacer) {
611
+
612
+ if (typeof(id) === 'boolean') {
613
+ replacer = beautify;
614
+ beautify = id;
615
+ id = null;
616
+ }
617
+
618
+ if (typeof(beautify) === 'function') {
619
+ replacer = beautify;
620
+ beautify = false;
621
+ }
622
+
623
+ var value = beautify ? JSON.stringify(obj, replacer == true ? F.TUtils.json2replacer : replacer, 4) : JSON.stringify(obj, replacer == true ? F.TUtils.json2replacer : replacer);
624
+ return id ? ('<script type="application/json" id="' + id + '">' + value + '</script>') : value;
625
+ };
626
+
627
+ View.prototype.view = function(name, model) {
628
+ return this.render(name, model, true);
629
+ };
630
+
631
+ View.prototype.safehtml = function(value, escape) {
632
+ value = value != null ? (value + '') : '';
633
+ return escape && value ? value.safehtml() : value;
634
+ };
635
+
636
+ View.prototype.title = function(value) {
637
+ this.repository.title = value;
638
+ return '';
639
+ };
640
+
641
+ View.prototype.title2 = function(value) {
642
+ var current = this.repository.title;
643
+ if (value)
644
+ this.repository.title = (current || '') + value.safehtml();
645
+ return '';
646
+ };
647
+
648
+ View.prototype.description = function(value) {
649
+ this.repository.description = value;
650
+ return '';
651
+ };
652
+
653
+ View.prototype.keywords = function(value) {
654
+ this.repository.keywords = value instanceof Array ? value.join(', ') : value;
655
+ return '';
656
+ };
657
+
658
+ function querystring_encode(value, def, key) {
659
+
660
+ if (value instanceof Array) {
661
+ var tmp = '';
662
+ for (var i = 1; i < value.length; i++)
663
+ tmp += (tmp ? '&' : '') + key + '=' + querystring_encode(value[i], def);
664
+ return querystring_encode(value[0], def) + (tmp ? tmp : '');
665
+ }
666
+
667
+ return value != null ? value instanceof Date ? encodeURIComponent(value.format()) : typeof(value) === 'string' ? encodeURIComponent(value) : (value + '') : def || '';
668
+ }
669
+
670
+ // @{href({ key1: 1, key2: 2 })}
671
+ // @{href('key', 'value')}
672
+ View.prototype.href = function(key, value) {
673
+
674
+ var self = this;
675
+
676
+ if (!arguments.length) {
677
+ let val = F.TUtils.toURLEncode(self.query);
678
+ return val ? '?' + val : '';
679
+ }
680
+
681
+ var type = typeof(key);
682
+ var obj;
683
+
684
+ if (type === 'string') {
685
+
686
+ var cachekey = 'href_' + key;
687
+ var str = self.repository[cachekey] || '';
688
+
689
+ if (!str) {
690
+
691
+ obj = F.TUtils.copy(self.query);
692
+
693
+ for (var i = 2; i < arguments.length; i++)
694
+ obj[arguments[i]] = undefined;
695
+
696
+ obj[key] = '\0';
697
+
698
+ for (var m in obj) {
699
+ var val = obj[m];
700
+ if (val !== undefined) {
701
+ if (val instanceof Array) {
702
+ for (var j = 0; j < val.length; j++)
703
+ str += (str ? '&' : '') + m + '=' + (key === m ? '\0' : querystring_encode(val[j]));
704
+ } else
705
+ str += (str ? '&' : '') + m + '=' + (key === m ? '\0' : querystring_encode(val));
706
+ }
707
+ }
708
+ self.repository[cachekey] = str;
709
+ }
710
+
711
+ str = str.replace('\0', querystring_encode(value, self.query[key], key));
712
+
713
+ for (var i = 2; i < arguments.length; i++) {
714
+ var beg = str.indexOf(arguments[i] + '=');
715
+ if (beg === -1)
716
+ continue;
717
+ var end = str.indexOf('&', beg);
718
+ str = str.substring(0, beg) + str.substring(end === -1 ? str.length : end + 1);
719
+ }
720
+
721
+ return str ? '?' + str : '';
722
+ }
723
+
724
+ if (value) {
725
+ obj = F.TUtils.copy(self.query);
726
+ F.TUtils.extend(obj, value);
727
+ }
728
+
729
+ if (value != null)
730
+ obj[key] = value;
731
+
732
+ obj = F.TUtils.toURLEncode(obj);
733
+
734
+ if (value === undefined && type === 'string')
735
+ obj += (obj ? '&' : '') + key;
736
+
737
+ return self.url + (obj ? '?' + obj : '');
738
+ };
739
+
740
+ function makehtmlmeta(self) {
741
+
742
+ var builder = '';
743
+ var repo = self.repository;
744
+
745
+ var title = '';
746
+
747
+ if (repo.title)
748
+ title = repo.title.safehtml();
749
+
750
+ if (title) {
751
+ if (!F.config.$customtitles && self?.controller?.url !== '/')
752
+ title += ' - ' + F.config.name;
753
+ } else if (!title)
754
+ title = F.config.name;
755
+
756
+ builder += '<title>' + title + '</title>';
757
+
758
+ if (repo.description)
759
+ builder += '<meta name="description" content="' + repo.description.safehtml() + '" />';
760
+
761
+ if (repo.keywords)
762
+ builder += '<meta name="description" content="' + repo.keywords.safehtml() + '" />';
763
+
764
+ if (repo.image) {
765
+ let tmp = repo.image.substring(0, 6);
766
+ let src = tmp === 'http:/' || tmp === 'https:' || tmp.substring(0, 2) === '//' ? repo.image : ((self?.controller.host || '') + repo.image);
767
+ builder += '<meta property="og:image" content="' + src + '" /><meta name="twitter:image" content="' + src + '" />';
768
+ }
769
+
770
+ return builder;
771
+ }
772
+
773
+ View.prototype.import = function() {
774
+
775
+ var builder = '';
776
+ var self = this;
777
+
778
+ for (var m of arguments) {
779
+
780
+ switch (m) {
781
+ case 'meta':
782
+ builder += makehtmlmeta(self);
783
+ break;
784
+ case 'head':
785
+ builder += '';
786
+ break;
787
+ case 'favicon.ico':
788
+ case 'favicon.png':
789
+ case 'favicon.gif':
790
+ let ext = m.substring(m.length - 3);
791
+ if (ext === 'ico')
792
+ ext = 'x-icon';
793
+ builder += '<link rel="icon" href="/' + m + '" type="image/' + ext + '" />';
794
+ break;
795
+ default:
796
+
797
+ // merging
798
+ let key = 'meta_' + m;
799
+ let tmp = F.temporary.views[key];
800
+ if (tmp != null) {
801
+ builder += tmp;
802
+ continue;
803
+ }
804
+
805
+ if (m.indexOf('+') === -1) {
806
+ let absolute = m[0] === '/';
807
+ let key = absolute ? m : ('/' + m);
808
+ if (REG_CHECKCSS.test(m)) {
809
+ tmp = '<link rel="stylesheet" href="' + (absolute ? m : ('/' + (F.routes.virtual[key] ? '' : 'css/') + m)) + '" />';
810
+ } else {
811
+ tmp = '<scri' + 'pt src="' + (absolute ? m : ('/' + (F.routes.virtual[key] ? '' : 'js/') + m)) + '"></scr' + 'ipt>';
812
+ }
813
+ } else {
814
+ let iscss = REG_CHECKCSS.test(m);
815
+ let path = '/' + F.TUtils.random_string(10).toLowerCase() + '-min.' + (iscss ? 'css' : 'js');
816
+ F.merge(path, m);
817
+ if (iscss)
818
+ tmp = '<link rel="stylesheet" href="' + path + '" />';
819
+ else
820
+ tmp = '<scri' + 'pt src="' + path + '"></scr' + 'ipt>';
821
+ }
822
+
823
+ F.temporary.views[key] = tmp;
824
+ builder += tmp;
825
+ break;
826
+ }
827
+ }
828
+
829
+ return builder;
830
+ };
831
+
832
+ View.prototype.section = function(name, value, replace) {
833
+
834
+ var key = 'section_' + name;
835
+ var self = this;
836
+
837
+ if (value == null)
838
+ return self.repository[key];
839
+
840
+ if (replace) {
841
+ self.repository[key] = value;
842
+ return self;
843
+ }
844
+
845
+ if (self.repository[key])
846
+ self.repository[key] += value;
847
+ else
848
+ self.repository[key] = value;
849
+
850
+ return self;
851
+ };
852
+
853
+ View.prototype.url = function(hostname = false) {
854
+ var self = this;
855
+ return hostname ? (self.controller ? self.controller.hostname(self.controller.url) : '') : (self.controller ? self.controller.url : '');
856
+ };
857
+
858
+ View.prototype.set = function() {
859
+ return '';
860
+ };
861
+
862
+ View.prototype.render = function(name, model, ispartial = false) {
863
+
864
+ var self = this;
865
+ var key = name + '_' + self.language;
866
+ var fn = F.temporary.views[key];
867
+ var content;
868
+
869
+ self.model = model;
870
+
871
+ if (!fn) {
872
+ let path = name[0] === '#' ? F.path.plugins(name.substring(1) + '.html') : F.path.directory('views', name + '.html');
873
+ content = F.translate(self.language, F.Fs.readFileSync(path, 'utf8'));
874
+ fn = exports.compile(name, content, DEBUG);
875
+ if (!DEBUG)
876
+ F.temporary.views[key] = fn;
877
+ }
878
+
879
+ content = fn(self);
880
+
881
+ if (!ispartial && !self.islayout && self.repository.layout) {
882
+ // render layout
883
+ self.output = content;
884
+ self.islayout = true;
885
+ content = self.render(self.repository.layout);
886
+ }
887
+
888
+ return content;
889
+ };
890
+
891
+ exports.View = View;