@reldens/cms 0.19.0 → 0.21.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/README.md +399 -17
- package/admin/reldens-admin-client.css +156 -99
- package/admin/reldens-admin-client.js +108 -133
- package/admin/templates/clear-all-cache-button.html +7 -7
- package/admin/templates/edit.html +7 -0
- package/admin/templates/layout.html +15 -9
- package/admin/templates/list-content.html +4 -2
- package/admin/templates/list.html +24 -8
- package/admin/templates/view.html +21 -0
- package/lib/admin-manager/admin-filters-manager.js +177 -0
- package/lib/admin-manager/contents-builder.js +1 -0
- package/lib/admin-manager/default-translations.js +38 -0
- package/lib/admin-manager/router-contents.js +50 -45
- package/lib/admin-manager/router.js +19 -0
- package/lib/frontend/content-renderer.js +178 -0
- package/lib/frontend/entity-access-manager.js +63 -0
- package/lib/frontend/request-processor.js +128 -0
- package/lib/frontend/response-manager.js +54 -0
- package/lib/frontend/template-cache.js +102 -0
- package/lib/frontend/template-resolver.js +111 -0
- package/lib/frontend.js +111 -538
- package/lib/manager.js +26 -12
- package/lib/search-renderer.js +15 -7
- package/lib/search-request-handler.js +67 -0
- package/lib/search.js +13 -1
- package/lib/template-engine/asset-transformer.js +41 -0
- package/lib/template-engine/collections-single-transformer.js +28 -5
- package/lib/template-engine/collections-transformer.js +66 -32
- package/lib/template-engine/date-transformer.js +53 -0
- package/lib/template-engine/entities-transformer.js +5 -2
- package/lib/template-engine/partials-transformer.js +8 -5
- package/lib/template-engine/system-variables-provider.js +108 -0
- package/lib/template-engine/translate-transformer.js +98 -0
- package/lib/template-engine/translation-service.js +104 -0
- package/lib/template-engine/url-transformer.js +41 -0
- package/lib/template-engine.js +99 -12
- package/lib/template-reloader.js +307 -0
- package/package.json +4 -4
- package/templates/{browserconfig.xml → assets/favicons/default/browserconfig.xml} +1 -1
- package/templates/assets/favicons/default/favicon.ico +0 -0
- package/templates/{site.webmanifest → assets/favicons/default/site.webmanifest} +3 -3
- package/templates/js/functions.js +144 -0
- package/templates/js/scripts.js +5 -0
- package/templates/page.html +11 -5
- package/templates/partials/pagedCollection.html +1 -1
- package/lib/admin-translations.js +0 -56
- package/templates/favicon.ico +0 -0
- /package/templates/assets/favicons/{android-icon-144x144.png → default/android-icon-144x144.png} +0 -0
- /package/templates/assets/favicons/{android-icon-192x192.png → default/android-icon-192x192.png} +0 -0
- /package/templates/assets/favicons/{android-icon-512x512.png → default/android-icon-512x512.png} +0 -0
- /package/templates/assets/favicons/{apple-touch-icon.png → default/apple-touch-icon.png} +0 -0
- /package/templates/assets/favicons/{favicon-16x16.png → default/favicon-16x16.png} +0 -0
- /package/templates/assets/favicons/{favicon-32x32.png → default/favicon-32x32.png} +0 -0
- /package/templates/assets/favicons/{mstile-150x150.png → default/mstile-150x150.png} +0 -0
- /package/templates/assets/favicons/{safari-pinned-tab.svg → default/safari-pinned-tab.svg} +0 -0
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
*
|
|
3
|
+
* Reldens - CMS - Frontend - ResponseManager
|
|
4
|
+
*
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const { sc } = require('@reldens/utils');
|
|
8
|
+
|
|
9
|
+
class ResponseManager
|
|
10
|
+
{
|
|
11
|
+
|
|
12
|
+
constructor(props)
|
|
13
|
+
{
|
|
14
|
+
this.cacheManager = sc.get(props, 'cacheManager', false);
|
|
15
|
+
this.contentRenderer = sc.get(props, 'contentRenderer', false);
|
|
16
|
+
this.templateResolver = sc.get(props, 'templateResolver', false);
|
|
17
|
+
this.requestProcessor = sc.get(props, 'requestProcessor', false);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
async renderWithCacheHandler(contentGenerator, errorHandler, responseHandler, domain, res, path, req)
|
|
21
|
+
{
|
|
22
|
+
let renderedContent = await contentGenerator();
|
|
23
|
+
if(!renderedContent){
|
|
24
|
+
return await errorHandler();
|
|
25
|
+
}
|
|
26
|
+
if(this.cacheManager && this.cacheManager.isEnabled()){
|
|
27
|
+
let cacheKey = this.requestProcessor.buildCacheKey(path, req);
|
|
28
|
+
await this.cacheManager.set(domain, cacheKey, renderedContent);
|
|
29
|
+
}
|
|
30
|
+
return await responseHandler(renderedContent);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
async renderNotFound(domain, res, req)
|
|
34
|
+
{
|
|
35
|
+
let notFoundPath = this.templateResolver.findTemplatePath('404', domain);
|
|
36
|
+
if(notFoundPath){
|
|
37
|
+
let content = await this.contentRenderer.generateTemplateContent(notFoundPath, domain, req, {});
|
|
38
|
+
if(content){
|
|
39
|
+
res.status(404);
|
|
40
|
+
return res.send(await this.contentRenderer.renderWithTemplateContent(
|
|
41
|
+
{content},
|
|
42
|
+
{meta_title: 'Page not found'},
|
|
43
|
+
domain,
|
|
44
|
+
req,
|
|
45
|
+
null
|
|
46
|
+
));
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return res.status(404).send('Page not found');
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
module.exports.ResponseManager = ResponseManager;
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
*
|
|
3
|
+
* Reldens - CMS - Frontend - TemplateCache
|
|
4
|
+
*
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const { FileHandler } = require('@reldens/server-utils');
|
|
8
|
+
const { Logger, sc } = require('@reldens/utils');
|
|
9
|
+
|
|
10
|
+
class TemplateCache
|
|
11
|
+
{
|
|
12
|
+
|
|
13
|
+
constructor(props)
|
|
14
|
+
{
|
|
15
|
+
this.templatesPath = sc.get(props, 'templatesPath', '');
|
|
16
|
+
this.templateExtensions = sc.get(props, 'templateExtensions', ['.html', '.mustache', '.template']);
|
|
17
|
+
this.defaultDomain = sc.get(props, 'defaultDomain', 'default');
|
|
18
|
+
this.partialsCache = {};
|
|
19
|
+
this.domainPartialsCache = new Map();
|
|
20
|
+
this.domainTemplatesMap = new Map();
|
|
21
|
+
this.templateResolver = sc.get(props, 'templateResolver', false);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
async loadPartials()
|
|
25
|
+
{
|
|
26
|
+
let partialsPath = FileHandler.joinPaths(this.templatesPath, 'partials');
|
|
27
|
+
FileHandler.createFolder(partialsPath);
|
|
28
|
+
let partialFiles = FileHandler.getFilesInFolder(partialsPath, this.templateExtensions);
|
|
29
|
+
for(let file of partialFiles){
|
|
30
|
+
let partialName = this.templateResolver.extractTemplateName(file);
|
|
31
|
+
if(!partialName){
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
let partialPath = FileHandler.joinPaths(partialsPath, file);
|
|
35
|
+
let partialContent = FileHandler.readFile(partialPath);
|
|
36
|
+
if(!partialContent){
|
|
37
|
+
Logger.error('Failed to read partial: '+partialPath);
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
this.partialsCache[partialName] = partialContent;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
async loadDomainPartials(domain, domainPath)
|
|
45
|
+
{
|
|
46
|
+
let domainPartialsPath = FileHandler.joinPaths(domainPath, 'partials');
|
|
47
|
+
if(!FileHandler.exists(domainPartialsPath)){
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
let domainPartials = {};
|
|
51
|
+
let partialFiles = FileHandler.getFilesInFolder(domainPartialsPath, this.templateExtensions);
|
|
52
|
+
for(let file of partialFiles){
|
|
53
|
+
let partialName = this.templateResolver.extractTemplateName(file);
|
|
54
|
+
if(!partialName){
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
let partialPath = FileHandler.joinPaths(domainPartialsPath, file);
|
|
58
|
+
let partialContent = FileHandler.readFile(partialPath);
|
|
59
|
+
if(!partialContent){
|
|
60
|
+
Logger.error('Failed to read domain partial: '+partialPath);
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
domainPartials[partialName] = partialContent;
|
|
64
|
+
}
|
|
65
|
+
this.domainPartialsCache.set(domain, domainPartials);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
async setupDomainTemplates()
|
|
69
|
+
{
|
|
70
|
+
let domainsPath = FileHandler.joinPaths(this.templatesPath, 'domains');
|
|
71
|
+
if(!FileHandler.exists(domainsPath)){
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
let domainFolders = FileHandler.fetchSubFoldersList(domainsPath);
|
|
75
|
+
for(let domain of domainFolders){
|
|
76
|
+
let domainPath = FileHandler.joinPaths(domainsPath, domain);
|
|
77
|
+
this.domainTemplatesMap.set(domain, domainPath);
|
|
78
|
+
await this.loadDomainPartials(domain, domainPath);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
getPartialsForDomain(domain)
|
|
83
|
+
{
|
|
84
|
+
let resolvedDomain = this.templateResolver.resolveDomainToFolder(domain);
|
|
85
|
+
let domainPartials = this.domainPartialsCache.get(resolvedDomain);
|
|
86
|
+
if(!domainPartials && this.defaultDomain && resolvedDomain !== this.defaultDomain){
|
|
87
|
+
domainPartials = this.domainPartialsCache.get(this.defaultDomain);
|
|
88
|
+
}
|
|
89
|
+
if(!domainPartials){
|
|
90
|
+
return this.partialsCache;
|
|
91
|
+
}
|
|
92
|
+
return Object.assign({}, this.partialsCache, domainPartials);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
getDomainTemplatesMap()
|
|
96
|
+
{
|
|
97
|
+
return this.domainTemplatesMap;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
module.exports.TemplateCache = TemplateCache;
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
*
|
|
3
|
+
* Reldens - CMS - Frontend - TemplateResolver
|
|
4
|
+
*
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const { FileHandler } = require('@reldens/server-utils');
|
|
8
|
+
const { sc } = require('@reldens/utils');
|
|
9
|
+
|
|
10
|
+
class TemplateResolver
|
|
11
|
+
{
|
|
12
|
+
|
|
13
|
+
constructor(props)
|
|
14
|
+
{
|
|
15
|
+
this.templatesPath = sc.get(props, 'templatesPath', '');
|
|
16
|
+
this.templateExtensions = sc.get(props, 'templateExtensions', ['.html', '.mustache', '.template']);
|
|
17
|
+
this.defaultDomain = sc.get(props, 'defaultDomain', 'default');
|
|
18
|
+
this.domainMapping = sc.get(props, 'domainMapping', {});
|
|
19
|
+
this.siteKeyMapping = sc.get(props, 'siteKeyMapping', {});
|
|
20
|
+
this.domainTemplatesMap = sc.get(props, 'domainTemplatesMap', new Map());
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
extractTemplateName(filename)
|
|
24
|
+
{
|
|
25
|
+
for(let extension of this.templateExtensions){
|
|
26
|
+
if(filename.endsWith(extension)){
|
|
27
|
+
return filename.replace(extension, '');
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
resolveDomainToFolder(domain)
|
|
34
|
+
{
|
|
35
|
+
if(!domain){
|
|
36
|
+
domain = this.defaultDomain;
|
|
37
|
+
}
|
|
38
|
+
return sc.get(this.domainMapping, domain, domain);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
resolveDomainToSiteKey(domain)
|
|
42
|
+
{
|
|
43
|
+
return sc.get(this.siteKeyMapping, this.resolveDomainToFolder(domain), 'default');
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
findTemplatePath(templateName, domain)
|
|
47
|
+
{
|
|
48
|
+
let resolvedDomain = this.resolveDomainToFolder(domain);
|
|
49
|
+
if(resolvedDomain){
|
|
50
|
+
let domainPath = this.domainTemplatesMap.get(resolvedDomain);
|
|
51
|
+
if(domainPath){
|
|
52
|
+
let domainTemplatePath = this.findTemplateInPath(templateName, domainPath);
|
|
53
|
+
if(domainTemplatePath){
|
|
54
|
+
return domainTemplatePath;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
if(this.defaultDomain && resolvedDomain !== this.defaultDomain){
|
|
58
|
+
let defaultDomainPath = this.domainTemplatesMap.get(this.defaultDomain);
|
|
59
|
+
if(defaultDomainPath){
|
|
60
|
+
let defaultTemplatePath = this.findTemplateInPath(templateName, defaultDomainPath);
|
|
61
|
+
if(defaultTemplatePath){
|
|
62
|
+
return defaultTemplatePath;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return this.findTemplateInPath(templateName, this.templatesPath);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
findTemplateInPath(templateName, basePath)
|
|
71
|
+
{
|
|
72
|
+
for(let extension of this.templateExtensions){
|
|
73
|
+
let templatePath = FileHandler.joinPaths(basePath, templateName + extension);
|
|
74
|
+
if(FileHandler.exists(templatePath)){
|
|
75
|
+
return templatePath;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return false;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
findLayoutPath(layoutName, domain)
|
|
82
|
+
{
|
|
83
|
+
let resolvedDomain = this.resolveDomainToFolder(domain);
|
|
84
|
+
if(resolvedDomain){
|
|
85
|
+
let domainPath = this.domainTemplatesMap.get(resolvedDomain);
|
|
86
|
+
if(domainPath){
|
|
87
|
+
let domainLayoutPath = this.findTemplateInPath('layouts/' + layoutName, domainPath);
|
|
88
|
+
if(domainLayoutPath){
|
|
89
|
+
return domainLayoutPath;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
return this.findTemplateInPath('layouts/' + layoutName, this.templatesPath);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
findTemplateByPath(path, domain)
|
|
97
|
+
{
|
|
98
|
+
if('/' === path){
|
|
99
|
+
path = '/index';
|
|
100
|
+
}
|
|
101
|
+
let templatePath = path.endsWith('/') ? path.slice(0, -1) : path;
|
|
102
|
+
templatePath = templatePath.startsWith('/') ? templatePath.substring(1) : templatePath;
|
|
103
|
+
if('page' === templatePath){
|
|
104
|
+
return false;
|
|
105
|
+
}
|
|
106
|
+
return this.findTemplatePath(templatePath, domain);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
module.exports.TemplateResolver = TemplateResolver;
|