@reldens/cms 0.19.0 → 0.20.0

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/lib/frontend.js CHANGED
@@ -19,6 +19,7 @@ class Frontend
19
19
  this.appServerFactory = sc.get(props, 'appServerFactory', false);
20
20
  this.dataServer = sc.get(props, 'dataServer', false);
21
21
  this.renderEngine = sc.get(props, 'renderEngine', false);
22
+ this.events = sc.get(props, 'events', false);
22
23
  this.projectRoot = sc.get(props, 'projectRoot', './');
23
24
  this.templatesPath = FileHandler.joinPaths(this.projectRoot, 'templates');
24
25
  this.publicPath = FileHandler.joinPaths(this.projectRoot, 'public');
@@ -79,7 +80,11 @@ class Frontend
79
80
  renderEngine: this.renderEngine,
80
81
  dataServer: this.dataServer,
81
82
  getPartials: this.getPartialsForDomain.bind(this),
82
- entitiesConfig: this.entitiesConfig
83
+ entitiesConfig: this.entitiesConfig,
84
+ events: this.events,
85
+ defaultDomain: this.defaultDomain,
86
+ projectRoot: this.projectRoot,
87
+ publicPath: this.publicPath
83
88
  });
84
89
  this.searchConfig.jsonFieldsParser = this.templateEngine.jsonFieldsParser;
85
90
  await this.loadPartials();
@@ -345,7 +350,8 @@ class Frontend
345
350
  query: req.query
346
351
  }),
347
352
  domain,
348
- req
353
+ req,
354
+ null
349
355
  );
350
356
  if(this.cacheManager && this.cacheManager.isEnabled()){
351
357
  await this.cacheManager.set(domain, cacheKey, content);
@@ -357,28 +363,73 @@ class Frontend
357
363
  }
358
364
  }
359
365
 
366
+ normalizePathForRouteSearch(path)
367
+ {
368
+ if(!path || '/' === path){
369
+ return '/';
370
+ }
371
+ return path.endsWith('/') ? path.slice(0, -1) : path;
372
+ }
373
+
374
+ async handleRouteRedirect(route, res)
375
+ {
376
+ let redirectUrl = sc.get(route, 'redirect_url', null);
377
+ if(!redirectUrl){
378
+ return false;
379
+ }
380
+ let redirectType = sc.get(route, 'redirect_type', '301');
381
+ let statusCode = '301' === redirectType ? 301 : 302;
382
+ return res.redirect(statusCode, redirectUrl);
383
+ }
384
+
360
385
  async handleRequest(req, res)
361
386
  {
362
387
  try {
363
- let path = req.path;
388
+ let originalPath = req.path;
364
389
  let domain = this.getDomainFromRequest(req);
365
390
  if(this.cacheManager && this.cacheManager.isEnabled()){
366
- let cachedContent = await this.cacheManager.get(domain, path);
391
+ let cachedContent = await this.cacheManager.get(domain, originalPath);
367
392
  if(cachedContent){
368
393
  return res.send(cachedContent);
369
394
  }
370
395
  }
371
- let route = await this.findRouteByPath(path, domain);
396
+ let route = await this.findRouteByPath(originalPath, domain);
372
397
  if(route){
373
- return await this.renderRouteWithCache(route, domain, res, path, req);
398
+ let redirectResult = await this.handleRouteRedirect(route, res);
399
+ if(redirectResult){
400
+ return redirectResult;
401
+ }
402
+ let normalizedPath = this.normalizePathForRouteSearch(originalPath);
403
+ let routeFoundWithSlash = originalPath !== normalizedPath && route.path === normalizedPath + '/';
404
+ if(!originalPath.endsWith('/') && routeFoundWithSlash){
405
+ return res.redirect(301, originalPath + '/');
406
+ }
407
+ return await this.renderRouteWithCache(route, domain, res, originalPath, req);
408
+ }
409
+ let normalizedPath = this.normalizePathForRouteSearch(originalPath);
410
+ if(originalPath !== normalizedPath){
411
+ let alternativeRoute = await this.findRouteByPath(normalizedPath + '/', domain);
412
+ if(alternativeRoute){
413
+ let redirectResult = await this.handleRouteRedirect(alternativeRoute, res);
414
+ if(redirectResult){
415
+ return redirectResult;
416
+ }
417
+ if(!originalPath.endsWith('/')){
418
+ return res.redirect(301, originalPath + '/');
419
+ }
420
+ return await this.renderRouteWithCache(alternativeRoute, domain, res, originalPath, req);
421
+ }
374
422
  }
375
- let entityResult = await this.findEntityByPath(path);
423
+ if(!originalPath.endsWith('/') && '/' !== originalPath){
424
+ return res.redirect(301, originalPath + '/');
425
+ }
426
+ let entityResult = await this.findEntityByPath(originalPath);
376
427
  if(entityResult){
377
- return await this.renderEntityWithCache(entityResult, domain, res, path, req);
428
+ return await this.renderEntityWithCache(entityResult, domain, res, originalPath, req);
378
429
  }
379
- let templatePath = this.findTemplateByPath(path, domain);
430
+ let templatePath = this.findTemplateByPath(originalPath, domain);
380
431
  if(templatePath){
381
- return await this.renderTemplateWithCache(templatePath, domain, res, path, req);
432
+ return await this.renderTemplateWithCache(templatePath, domain, res, originalPath, req);
382
433
  }
383
434
  return await this.renderNotFound(domain, res, req);
384
435
  } catch (error) {
@@ -394,8 +445,9 @@ class Frontend
394
445
  Logger.error('Routes entity not found in dataServer.');
395
446
  return false;
396
447
  }
448
+ let normalizedPath = this.normalizePathForRouteSearch(path);
397
449
  let domainFilter = domain || null;
398
- let routeFilters = {path, enabled: 1};
450
+ let routeFilters = {path: normalizedPath, enabled: 1};
399
451
  let routes = await routesEntity.load(routeFilters);
400
452
  let matchingRoute = false;
401
453
  let nullDomain = false;
@@ -411,7 +463,25 @@ class Frontend
411
463
  if(matchingRoute){
412
464
  return matchingRoute;
413
465
  }
414
- return nullDomain;
466
+ if(nullDomain){
467
+ return nullDomain;
468
+ }
469
+ if(normalizedPath !== path){
470
+ let routeFiltersWithSlash = {path: path, enabled: 1};
471
+ let routesWithSlash = await routesEntity.load(routeFiltersWithSlash);
472
+ for(let route of routesWithSlash){
473
+ if(route.domain === domainFilter){
474
+ return route;
475
+ }
476
+ if(!route.domain){
477
+ nullDomain = route;
478
+ }
479
+ }
480
+ if(nullDomain){
481
+ return nullDomain;
482
+ }
483
+ }
484
+ return false;
415
485
  }
416
486
 
417
487
  async isEntityAccessible(entityName)
@@ -509,12 +579,12 @@ class Frontend
509
579
  if(!content){
510
580
  return false;
511
581
  }
512
- return await this.renderWithTemplateContent(content, Object.assign({}, route, content), domain, req);
582
+ return await this.renderWithTemplateContent(content, Object.assign({}, route, content), domain, req, route);
513
583
  }
514
584
 
515
585
  async generateEntityContent(entityResult, domain, req)
516
586
  {
517
- return await this.renderWithTemplateContent(entityResult.entity, entityResult.entity, domain, req);
587
+ return await this.renderWithTemplateContent(entityResult.entity, entityResult.entity, domain, req, null);
518
588
  }
519
589
 
520
590
  async generateTemplateContent(templatePath, domain, req)
@@ -524,7 +594,15 @@ class Frontend
524
594
  Logger.error('Failed to read template: ' + templatePath);
525
595
  return false;
526
596
  }
527
- return await this.templateEngine.render(template, {}, this.getPartialsForDomain(domain), domain, req);
597
+ return await this.templateEngine.render(
598
+ template,
599
+ {},
600
+ this.getPartialsForDomain(domain),
601
+ domain,
602
+ req,
603
+ null,
604
+ null
605
+ );
528
606
  }
529
607
 
530
608
  async renderRoute(route, domain, res, req)
@@ -545,10 +623,10 @@ class Frontend
545
623
 
546
624
  async renderWithTemplate(content, data, domain, res, req)
547
625
  {
548
- return res.send(await this.renderWithTemplateContent(content, data, domain, req));
626
+ return res.send(await this.renderWithTemplateContent(content, data, domain, req, null));
549
627
  }
550
628
 
551
- async renderWithTemplateContent(content, data, domain, req)
629
+ async renderWithTemplateContent(content, data, domain, req, route)
552
630
  {
553
631
  let templateName = sc.get(content, 'template', 'page');
554
632
  if(!templateName){
@@ -558,7 +636,16 @@ class Frontend
558
636
  if(!layoutName){
559
637
  layoutName = 'default';
560
638
  }
561
- let layoutContent = await this.processContentWithLayout(content, data, layoutName, domain, req);
639
+ let currentEntityData = Object.assign({}, content, data);
640
+ let layoutContent = await this.processContentWithLayout(
641
+ content,
642
+ data,
643
+ layoutName,
644
+ domain,
645
+ req,
646
+ route,
647
+ currentEntityData
648
+ );
562
649
  let templatePath = this.findTemplatePath(templateName, domain);
563
650
  if(!templatePath){
564
651
  return layoutContent;
@@ -569,10 +656,19 @@ class Frontend
569
656
  }
570
657
  return await this.templateEngine.render(
571
658
  pageTemplate,
572
- Object.assign({}, this.fetchMetaFields(data), {content: layoutContent, siteHandle: this.resolveDomainToSiteKey(domain)}),
659
+ Object.assign(
660
+ {},
661
+ this.fetchMetaFields(data),
662
+ {
663
+ content: layoutContent,
664
+ siteHandle: this.resolveDomainToSiteKey(domain)
665
+ }
666
+ ),
573
667
  this.getPartialsForDomain(domain),
574
668
  domain,
575
- req
669
+ req,
670
+ route,
671
+ currentEntityData
576
672
  );
577
673
  }
578
674
 
@@ -583,17 +679,25 @@ class Frontend
583
679
  Logger.error('Failed to read template: ' + templatePath);
584
680
  return false;
585
681
  }
586
- return await this.templateEngine.render(template, data, this.getPartialsForDomain(domain), domain, req);
682
+ return await this.templateEngine.render(
683
+ template,
684
+ data,
685
+ this.getPartialsForDomain(domain),
686
+ domain,
687
+ req,
688
+ null,
689
+ null
690
+ );
587
691
  }
588
692
 
589
693
  async renderWithLayout(content, data, layoutName, domain, res, req)
590
694
  {
591
- return res.send(await this.renderWithTemplateContent(content, data, domain, req));
695
+ return res.send(await this.renderWithTemplateContent(content, data, domain, req, null));
592
696
  }
593
697
 
594
- async processContentWithLayout(content, data, layoutName, domain, req)
698
+ async processContentWithLayout(content, data, layoutName, domain, req, route, currentEntityData)
595
699
  {
596
- let processedContent = await this.processContent(content, data, domain, req);
700
+ let processedContent = await this.processContent(content, data, domain, req, route, currentEntityData);
597
701
  let layoutPath = this.findLayoutPath(layoutName, domain);
598
702
  if(!layoutPath){
599
703
  return processedContent;
@@ -607,17 +711,27 @@ class Frontend
607
711
  Object.assign({}, data, {content: processedContent}),
608
712
  this.getPartialsForDomain(domain),
609
713
  domain,
610
- req
714
+ req,
715
+ route,
716
+ currentEntityData
611
717
  );
612
718
  }
613
719
 
614
- async processContent(content, data, domain, req)
720
+ async processContent(content, data, domain, req, route, currentEntityData)
615
721
  {
616
722
  let contentText = sc.get(content, 'content', '');
617
723
  if(!contentText){
618
724
  return '';
619
725
  }
620
- return await this.templateEngine.render(contentText, data, this.getPartialsForDomain(domain), domain, req);
726
+ return await this.templateEngine.render(
727
+ contentText,
728
+ data,
729
+ this.getPartialsForDomain(domain),
730
+ domain,
731
+ req,
732
+ route,
733
+ currentEntityData
734
+ );
621
735
  }
622
736
 
623
737
  async renderNotFound(domain, res, req)
package/lib/manager.js CHANGED
@@ -476,6 +476,7 @@ class Manager
476
476
  this.frontend = new Frontend({
477
477
  app: this.app,
478
478
  dataServer: this.dataServer,
479
+ events: this.events,
479
480
  renderEngine: this.renderEngine,
480
481
  projectRoot: this.projectRoot,
481
482
  appServerFactory: this.appServerFactory,
@@ -0,0 +1,41 @@
1
+ /**
2
+ *
3
+ * Reldens - CMS - AssetTransformer
4
+ *
5
+ */
6
+
7
+ const { sc } = require('@reldens/utils');
8
+
9
+ class AssetTransformer
10
+ {
11
+
12
+ async transform(template, domain, req, systemVariables)
13
+ {
14
+ if(!template){
15
+ return template;
16
+ }
17
+ let currentRequest = sc.get(systemVariables, 'currentRequest', {});
18
+ let assetPattern = /\[asset\(([^)]+)\)\]/g;
19
+ let matches = [...template.matchAll(assetPattern)];
20
+ for(let i = matches.length - 1; i >= 0; i--){
21
+ let match = matches[i];
22
+ let assetPath = match[1].replace(/['"]/g, '');
23
+ let absoluteUrl = this.buildAssetUrl(assetPath, currentRequest);
24
+ template = template.substring(0, match.index) +
25
+ absoluteUrl +
26
+ template.substring(match.index + match[0].length);
27
+ }
28
+ return template;
29
+ }
30
+
31
+ buildAssetUrl(assetPath, currentRequest)
32
+ {
33
+ if(!assetPath || assetPath.startsWith('http')){
34
+ return assetPath;
35
+ }
36
+ return sc.get(currentRequest, 'baseUrl', '')+'/assets'+(assetPath.startsWith('/') ? assetPath : '/'+assetPath);
37
+ }
38
+
39
+ }
40
+
41
+ module.exports.AssetTransformer = AssetTransformer;
@@ -10,12 +10,22 @@ const { sc } = require('@reldens/utils');
10
10
  class CollectionsSingleTransformer extends CollectionsTransformerBase
11
11
  {
12
12
 
13
+ constructor(props)
14
+ {
15
+ super(props);
16
+ this.renderEngine = sc.get(props, 'renderEngine', false);
17
+ this.getPartials = sc.get(props, 'getPartials', false);
18
+ this.findAllPartialTags = sc.get(props, 'findAllPartialTags', false);
19
+ this.loadPartialTemplate = sc.get(props, 'loadPartialTemplate', false);
20
+ this.processAllTemplateFunctions = sc.get(props, 'processAllTemplateFunctions', false);
21
+ }
22
+
13
23
  getSingleFieldCollectionRegex()
14
24
  {
15
25
  return /<collection\s+([^>]+)\/>/g;
16
26
  }
17
27
 
18
- async transform(template, domain)
28
+ async transform(template, domain, req, systemVariables)
19
29
  {
20
30
  let processedTemplate = template;
21
31
  for(let match of template.matchAll(this.getSingleFieldCollectionRegex())){
@@ -30,20 +40,27 @@ class CollectionsSingleTransformer extends CollectionsTransformerBase
30
40
  let fieldName = this.extractAttributeValue(tagContent, 'field');
31
41
  processedTemplate = processedTemplate.replace(
32
42
  match[0],
33
- this.extractFieldValues(
43
+ await this.extractFieldValues(
34
44
  await this.fetchCollectionForTemplate(tableName, filtersJson, queryOptionsJson, relationsString),
35
- fieldName
45
+ fieldName,
46
+ domain,
47
+ req,
48
+ systemVariables
36
49
  )
37
50
  );
38
51
  }
39
52
  return processedTemplate;
40
53
  }
41
54
 
42
- extractFieldValues(collectionData, fieldName)
55
+ async extractFieldValues(collectionData, fieldName, domain, req, systemVariables)
43
56
  {
44
57
  let fieldValues = '';
45
58
  for(let row of collectionData){
46
- fieldValues += sc.get(row, fieldName, '');
59
+ let fieldValue = sc.get(row, fieldName, '');
60
+ if(fieldValue && this.processAllTemplateFunctions){
61
+ fieldValue = await this.processAllTemplateFunctions(fieldValue, domain, req, systemVariables);
62
+ }
63
+ fieldValues += fieldValue;
47
64
  }
48
65
  return fieldValues;
49
66
  }
@@ -18,6 +18,7 @@ class CollectionsTransformer extends CollectionsTransformerBase
18
18
  this.getPartials = sc.get(props, 'getPartials', false);
19
19
  this.findAllPartialTags = sc.get(props, 'findAllPartialTags', false);
20
20
  this.loadPartialTemplate = sc.get(props, 'loadPartialTemplate', false);
21
+ this.processAllTemplateFunctions = sc.get(props, 'processAllTemplateFunctions', false);
21
22
  this.paginationHandler = new PaginationHandler();
22
23
  }
23
24
 
@@ -31,7 +32,7 @@ class CollectionsTransformer extends CollectionsTransformerBase
31
32
  return new RegExp('<\\/collection>');
32
33
  }
33
34
 
34
- async transform(template, domain, req)
35
+ async transform(template, domain, req, systemVariables)
35
36
  {
36
37
  let processedTemplate = template;
37
38
  let matches = [...template.matchAll(this.getLoopCollectionStartRegex())];
@@ -62,7 +63,8 @@ class CollectionsTransformer extends CollectionsTransformerBase
62
63
  prevPages,
63
64
  nextPages,
64
65
  domain,
65
- req
66
+ req,
67
+ systemVariables
66
68
  );
67
69
  if(loopResult){
68
70
  processedTemplate = loopResult;
@@ -76,7 +78,9 @@ class CollectionsTransformer extends CollectionsTransformerBase
76
78
  filtersJson,
77
79
  relationsString,
78
80
  queryOptionsJson,
79
- domain
81
+ domain,
82
+ req,
83
+ systemVariables
80
84
  );
81
85
  if(loopResult){
82
86
  processedTemplate = loopResult;
@@ -92,7 +96,9 @@ class CollectionsTransformer extends CollectionsTransformerBase
92
96
  filtersJson,
93
97
  relationsString,
94
98
  queryOptionsJson,
95
- domain
99
+ domain,
100
+ req,
101
+ systemVariables
96
102
  ){
97
103
  return await this.processCollectionBase(
98
104
  template,
@@ -102,7 +108,9 @@ class CollectionsTransformer extends CollectionsTransformerBase
102
108
  relationsString,
103
109
  queryOptionsJson,
104
110
  domain,
105
- false
111
+ false,
112
+ req,
113
+ systemVariables
106
114
  );
107
115
  }
108
116
 
@@ -118,7 +126,8 @@ class CollectionsTransformer extends CollectionsTransformerBase
118
126
  prevPages,
119
127
  nextPages,
120
128
  domain,
121
- req
129
+ req,
130
+ systemVariables
122
131
  ){
123
132
  if(!req){
124
133
  Logger.warning('No request provided for pagination, falling back to regular collection');
@@ -129,7 +138,9 @@ class CollectionsTransformer extends CollectionsTransformerBase
129
138
  filtersJson,
130
139
  relationsString,
131
140
  queryOptionsJson,
132
- domain
141
+ domain,
142
+ req,
143
+ systemVariables
133
144
  );
134
145
  }
135
146
  return await this.processCollectionBase(
@@ -146,7 +157,9 @@ class CollectionsTransformer extends CollectionsTransformerBase
146
157
  prevPages,
147
158
  nextPages,
148
159
  req
149
- }
160
+ },
161
+ req,
162
+ systemVariables
150
163
  );
151
164
  }
152
165
 
@@ -158,7 +171,9 @@ class CollectionsTransformer extends CollectionsTransformerBase
158
171
  relationsString,
159
172
  queryOptionsJson,
160
173
  domain,
161
- paginationOptions
174
+ paginationOptions,
175
+ req,
176
+ systemVariables
162
177
  ){
163
178
  let startPos = startMatch.index;
164
179
  let startEnd = startPos + startMatch[0].length;
@@ -211,7 +226,7 @@ class CollectionsTransformer extends CollectionsTransformerBase
211
226
  this.jsonFieldsParser.getJsonFieldsForEntity(tableName)
212
227
  );
213
228
  }
214
- let collectionContent = await this.renderCollectionLoop(loopContent, collectionData, domain);
229
+ let collectionContent = await this.renderCollectionLoop(loopContent, collectionData, domain, req, systemVariables);
215
230
  finalContent = this.renderEngine.render(
216
231
  1 < paginationData.totalPages
217
232
  ? this.loadPaginationTemplate(paginationOptions.containerName, domain)
@@ -235,7 +250,7 @@ class CollectionsTransformer extends CollectionsTransformerBase
235
250
  queryOptionsJson,
236
251
  relationsString
237
252
  );
238
- finalContent = await this.renderCollectionLoop(loopContent, collectionData, domain);
253
+ finalContent = await this.renderCollectionLoop(loopContent, collectionData, domain, req, systemVariables);
239
254
  }
240
255
  return template.substring(0, startPos) + finalContent + template.substring(endPos + endMatch[0].length);
241
256
  }
@@ -281,14 +296,14 @@ class CollectionsTransformer extends CollectionsTransformerBase
281
296
  return '{{&collectionContentForCurrentPage}}';
282
297
  }
283
298
 
284
- async renderCollectionLoop(loopContent, collectionData, domain)
299
+ async renderCollectionLoop(loopContent, collectionData, domain, req, systemVariables)
285
300
  {
286
301
  if(!collectionData || 0 === collectionData.length){
287
302
  return this.renderNoResultsMessage(domain);
288
303
  }
289
304
  let renderedContent = '';
290
305
  for(let row of collectionData){
291
- renderedContent += await this.processPartialsInLoop(loopContent, row, domain);
306
+ renderedContent += await this.processPartialsInLoop(loopContent, row, domain, req, systemVariables);
292
307
  }
293
308
  return renderedContent;
294
309
  }
@@ -310,7 +325,7 @@ class CollectionsTransformer extends CollectionsTransformerBase
310
325
  return '';
311
326
  }
312
327
 
313
- async processPartialsInLoop(content, rowData, domain)
328
+ async processPartialsInLoop(content, rowData, domain, req, systemVariables)
314
329
  {
315
330
  let processedContent = content;
316
331
  let partialTags = this.findAllPartialTags(content);
@@ -322,6 +337,9 @@ class CollectionsTransformer extends CollectionsTransformerBase
322
337
  processedContent = processedContent.substring(0, tag.start)+''+processedContent.substring(tag.end);
323
338
  continue;
324
339
  }
340
+ if(this.processAllTemplateFunctions){
341
+ partialContent = await this.processAllTemplateFunctions(partialContent, domain, req, systemVariables);
342
+ }
325
343
  if(sc.hasOwn(tag.attributes, 'row')){
326
344
  processedContent = processedContent.substring(0, tag.start)
327
345
  +this.renderEngine.render(partialContent, {row: rowData}, this.getPartials(domain))
@@ -335,6 +353,9 @@ class CollectionsTransformer extends CollectionsTransformerBase
335
353
  this.renderEngine.render(wrapperTemplate, renderData, partials) +
336
354
  processedContent.substring(tag.end);
337
355
  }
356
+ if(this.processAllTemplateFunctions){
357
+ processedContent = await this.processAllTemplateFunctions(processedContent, domain, req, systemVariables);
358
+ }
338
359
  return this.renderEngine.render(processedContent, {row: rowData}, this.getPartials(domain));
339
360
  }
340
361
 
@@ -0,0 +1,53 @@
1
+ /**
2
+ *
3
+ * Reldens - CMS - DateTransformer
4
+ *
5
+ */
6
+
7
+ const { sc } = require('@reldens/utils');
8
+
9
+ class DateTransformer
10
+ {
11
+
12
+ constructor(props)
13
+ {
14
+ this.defaultFormat = sc.get(props, 'defaultFormat', 'Y-m-d H:i:s');
15
+ }
16
+
17
+ async transform(template, domain, req, systemVariables)
18
+ {
19
+ if(!template){
20
+ return template;
21
+ }
22
+ let datePattern = /\[date\(([^)]*)\)\]/g;
23
+ let matches = [...template.matchAll(datePattern)];
24
+ for(let i = matches.length - 1; i >= 0; i--){
25
+ let match = matches[i];
26
+ let args = match[1] ? match[1].split(',').map(arg => arg.trim().replace(/['"]/g, '')) : [];
27
+ let dateValue = args[0] || '';
28
+ let formatValue = args[1] || this.defaultFormat;
29
+ let formattedDate = this.formatDate(dateValue, formatValue);
30
+ template = template.substring(0, match.index) +
31
+ formattedDate +
32
+ template.substring(match.index + match[0].length);
33
+ }
34
+ return template;
35
+ }
36
+
37
+ formatDate(dateValue, format)
38
+ {
39
+ let date;
40
+ if(!dateValue || '' === dateValue || 'now' === dateValue.toLowerCase()){
41
+ date = new Date();
42
+ } else {
43
+ date = new Date(dateValue);
44
+ if(isNaN(date.getTime())){
45
+ date = new Date();
46
+ }
47
+ }
48
+ return sc.formatDate(date, format);
49
+ }
50
+
51
+ }
52
+
53
+ module.exports.DateTransformer = DateTransformer;
@@ -21,7 +21,7 @@ class EntitiesTransformer
21
21
  return /<entity\s+name="([^"]+)"(?:\s+field="([^"]+)"\s+value="([^"]+)"|\s+id="([^"]+)")?\s*\/?>/g;
22
22
  }
23
23
 
24
- async transform(template, domain)
24
+ async transform(template, domain, req, systemVariables)
25
25
  {
26
26
  let processedTemplate = template;
27
27
  for(let match of template.matchAll(this.getEntityRegex())){
@@ -36,7 +36,9 @@ class EntitiesTransformer
36
36
  match[0],
37
37
  await this.processAllTemplateFunctions(
38
38
  sc.get(await this.fetchEntityForTemplate(tableName, value, field), 'content', ''),
39
- domain
39
+ domain,
40
+ req,
41
+ systemVariables
40
42
  )
41
43
  );
42
44
  }
@@ -13,9 +13,10 @@ class PartialsTransformer
13
13
  {
14
14
  this.renderEngine = sc.get(props, 'renderEngine', false);
15
15
  this.getPartials = sc.get(props, 'getPartials', false);
16
+ this.processAllTemplateFunctions = sc.get(props, 'processAllTemplateFunctions', false);
16
17
  }
17
18
 
18
- async transform(template, domain)
19
+ async transform(template, domain, req, systemVariables)
19
20
  {
20
21
  let processedTemplate = template;
21
22
  let partialTags = this.findAllPartialTags(template);
@@ -27,6 +28,9 @@ class PartialsTransformer
27
28
  processedTemplate = processedTemplate.substring(0, tag.start)+''+processedTemplate.substring(tag.end);
28
29
  continue;
29
30
  }
31
+ if(this.processAllTemplateFunctions){
32
+ partialContent = await this.processAllTemplateFunctions(partialContent, domain, req, systemVariables);
33
+ }
30
34
  let wrapperTemplate = '{{#vars}}{{> ' + tag.name + '}}{{/vars}}';
31
35
  let renderData = { vars: tag.attributes };
32
36
  let partials = {[tag.name]: partialContent};