@reldens/cms 0.18.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/README.md +260 -20
- package/admin/reldens-admin-client.css +127 -80
- package/admin/reldens-admin-client.js +24 -0
- package/admin/templates/clear-all-cache-button.html +18 -0
- package/lib/admin-manager/contents-builder.js +7 -6
- package/lib/admin-manager/router-contents.js +58 -16
- package/lib/admin-manager-validator.js +2 -1
- package/lib/admin-manager.js +4 -2
- package/lib/admin-translations.js +9 -1
- package/lib/cache/add-cache-button-subscriber.js +53 -5
- package/lib/cache/cache-manager.js +47 -8
- package/lib/cache/cache-routes-handler.js +23 -0
- package/lib/cms-pages-route-manager.js +16 -4
- package/lib/frontend.js +310 -119
- package/lib/manager.js +43 -3
- package/lib/pagination-handler.js +243 -0
- package/lib/search-renderer.js +116 -0
- package/lib/search.js +344 -0
- package/lib/template-engine/asset-transformer.js +41 -0
- package/lib/template-engine/collections-single-transformer.js +70 -0
- package/lib/template-engine/collections-transformer-base.js +84 -0
- package/lib/template-engine/collections-transformer.js +374 -0
- package/lib/template-engine/date-transformer.js +53 -0
- package/lib/template-engine/entities-transformer.js +67 -0
- package/lib/template-engine/partials-transformer.js +175 -0
- package/lib/template-engine/system-variables-provider.js +105 -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 +133 -438
- package/lib/templates-list.js +1 -0
- package/migrations/install.sql +18 -18
- package/package.json +4 -4
- package/templates/page.html +19 -2
- package/templates/partials/entriesListView.html +14 -0
- package/templates/partials/pagedCollection.html +33 -0
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
# Reldens CMS
|
|
4
4
|
|
|
5
|
-
A powerful, flexible Content Management System built with Node.js, featuring an admin panel, multi-domain frontend support, enhanced templating with reusable content blocks, and automated installation.
|
|
5
|
+
A powerful, flexible Content Management System built with Node.js, featuring an admin panel, multi-domain frontend support, enhanced templating with reusable content blocks, system variables, internationalization, and automated installation.
|
|
6
6
|
|
|
7
7
|
## Features
|
|
8
8
|
|
|
@@ -24,6 +24,10 @@ A powerful, flexible Content Management System built with Node.js, featuring an
|
|
|
24
24
|
- **Entity access control** for public/private content
|
|
25
25
|
- **Static asset serving** with Express integration as default
|
|
26
26
|
- **Template engine** with Mustache integration as default
|
|
27
|
+
- **System variables** for request, route, and domain context
|
|
28
|
+
- **Enhanced context passing** with currentEntity data in child blocks
|
|
29
|
+
- **Template functions** for URLs, assets, dates, and translations
|
|
30
|
+
- **Event-driven rendering** with hooks for customization
|
|
27
31
|
- **Custom 404 handling**
|
|
28
32
|
|
|
29
33
|
### - Admin Panel
|
|
@@ -50,6 +54,7 @@ A powerful, flexible Content Management System built with Node.js, featuring an
|
|
|
50
54
|
- **Event-driven system** with hooks for customization
|
|
51
55
|
- **Extensible authentication** (database users or custom callbacks)
|
|
52
56
|
- **File security** with path validation and dangerous key filtering
|
|
57
|
+
- **Internationalization support** with translation files
|
|
53
58
|
|
|
54
59
|
## Installation
|
|
55
60
|
|
|
@@ -128,6 +133,74 @@ const cms = new Manager({
|
|
|
128
133
|
|
|
129
134
|
## Enhanced Templating System
|
|
130
135
|
|
|
136
|
+
### System Variables
|
|
137
|
+
Every template has access to system variables providing context about the current request:
|
|
138
|
+
|
|
139
|
+
```html
|
|
140
|
+
<!-- Current request information -->
|
|
141
|
+
{{currentRequest.baseUrl}} <!-- https://example.com -->
|
|
142
|
+
{{currentRequest.protocol}} <!-- https -->
|
|
143
|
+
{{currentRequest.host}} <!-- example.com -->
|
|
144
|
+
{{currentRequest.path}} <!-- /articles/123 -->
|
|
145
|
+
{{currentRequest.method}} <!-- GET -->
|
|
146
|
+
{{currentRequest.userAgent}} <!-- Browser information -->
|
|
147
|
+
{{currentRequest.isSecure}} <!-- true/false -->
|
|
148
|
+
|
|
149
|
+
<!-- Current route data (if matched) -->
|
|
150
|
+
{{currentRoute.id}} <!-- Route ID -->
|
|
151
|
+
{{currentRoute.path}} <!-- Route path pattern -->
|
|
152
|
+
{{currentRoute.title}} <!-- Route title -->
|
|
153
|
+
{{currentRoute.template}} <!-- Route template -->
|
|
154
|
+
{{currentRoute.layout}} <!-- Route layout -->
|
|
155
|
+
|
|
156
|
+
<!-- Current domain information -->
|
|
157
|
+
{{currentDomain.current}} <!-- Current domain -->
|
|
158
|
+
{{currentDomain.default}} <!-- Default domain -->
|
|
159
|
+
{{currentDomain.resolved}} <!-- Resolved domain -->
|
|
160
|
+
|
|
161
|
+
<!-- System information -->
|
|
162
|
+
{{systemInfo.environment}} <!-- development/production -->
|
|
163
|
+
{{systemInfo.nodeVersion}} <!-- Node.js version -->
|
|
164
|
+
{{systemInfo.timestamp}} <!-- Current timestamp -->
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
### Template Functions
|
|
168
|
+
Templates support dynamic functions for common operations:
|
|
169
|
+
|
|
170
|
+
```html
|
|
171
|
+
<!-- URL generation with current domain -->
|
|
172
|
+
[url(/articles)] <!-- https://example.com/articles -->
|
|
173
|
+
[url(/contact#form)] <!-- https://example.com/contact#form -->
|
|
174
|
+
|
|
175
|
+
<!-- Asset URLs with domain -->
|
|
176
|
+
[asset(/css/styles.css)] <!-- https://example.com/css/styles.css -->
|
|
177
|
+
[asset(/images/logo.png)] <!-- https://example.com/images/logo.png -->
|
|
178
|
+
|
|
179
|
+
<!-- Date formatting -->
|
|
180
|
+
[date()] <!-- Current date with default format -->
|
|
181
|
+
[date(now, Y-m-d)] <!-- 2024-01-15 -->
|
|
182
|
+
[date(2024-01-01, d/m/Y)] <!-- 01/01/2024 -->
|
|
183
|
+
|
|
184
|
+
<!-- Internationalization -->
|
|
185
|
+
[translate(welcome.message)] <!-- Translated text -->
|
|
186
|
+
[t(hello.world, Hello World!)] <!-- With fallback -->
|
|
187
|
+
[t(greeting, Hi {name}!, {name: John})] <!-- With interpolation -->
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
### Enhanced Context Passing
|
|
191
|
+
Child content blocks and partials receive context from parent pages:
|
|
192
|
+
|
|
193
|
+
```html
|
|
194
|
+
<!-- In a CMS page or layout -->
|
|
195
|
+
<entity name="cmsBlocks" field="name" value="article-sidebar"/>
|
|
196
|
+
|
|
197
|
+
<!-- Inside the article-sidebar block, you can access: -->
|
|
198
|
+
{{currentEntity.title}} <!-- Parent page title -->
|
|
199
|
+
{{currentEntity.id}} <!-- Parent page ID -->
|
|
200
|
+
{{currentEntity.template}} <!-- Parent page template -->
|
|
201
|
+
<!-- Any other parent page properties -->
|
|
202
|
+
```
|
|
203
|
+
|
|
131
204
|
### Template Functions
|
|
132
205
|
Templates support dynamic content blocks, entity rendering, and collections with advanced query options:
|
|
133
206
|
|
|
@@ -157,18 +230,18 @@ Templates support dynamic content blocks, entity rendering, and collections with
|
|
|
157
230
|
```html
|
|
158
231
|
<!-- Loop through records with full template rendering -->
|
|
159
232
|
<collection name="cmsBlocks" filters="{status: 'active'}">
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
233
|
+
<div class="block">
|
|
234
|
+
<h3>{{row.title}}</h3>
|
|
235
|
+
<div class="content">{{row.content}}</div>
|
|
236
|
+
</div>
|
|
164
237
|
</collection>
|
|
165
238
|
|
|
166
239
|
<collection name="articles" filters="{category: 'technology'}">
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
240
|
+
<div class="article">
|
|
241
|
+
<h4>{{row.title}}</h4>
|
|
242
|
+
<p>{{row.summary}}</p>
|
|
243
|
+
<img src="{{row.featured_image}}" alt="{{row.title}}">
|
|
244
|
+
</div>
|
|
172
245
|
</collection>
|
|
173
246
|
|
|
174
247
|
<!-- With pagination and sorting -->
|
|
@@ -178,8 +251,91 @@ Templates support dynamic content blocks, entity rendering, and collections with
|
|
|
178
251
|
<p>{{row.summary}}</p>
|
|
179
252
|
</div>
|
|
180
253
|
</collection>
|
|
254
|
+
|
|
255
|
+
<!-- Paginated collections with navigation -->
|
|
256
|
+
<collection name="articles"
|
|
257
|
+
filters="{featured: true}"
|
|
258
|
+
data="{limit: 10, sortBy: 'created_at', sortDirection: 'desc'}"
|
|
259
|
+
pagination="articles-1"
|
|
260
|
+
container="pagedCollection"
|
|
261
|
+
prevPages="2"
|
|
262
|
+
nextPages="2">
|
|
263
|
+
<div class="article-card">
|
|
264
|
+
<h4>{{row.title}}</h4>
|
|
265
|
+
<p>{{row.summary}}</p>
|
|
266
|
+
<span class="date">{{row.created_at}}</span>
|
|
267
|
+
</div>
|
|
268
|
+
</collection>
|
|
269
|
+
|
|
270
|
+
<!-- Multiple paginated collections on the same page -->
|
|
271
|
+
<collection name="news"
|
|
272
|
+
filters="{category: 'technology'}"
|
|
273
|
+
data="{limit: 5, sortBy: 'published_at'}"
|
|
274
|
+
pagination="news-tech"
|
|
275
|
+
container="customPager">
|
|
276
|
+
<article>{{row.title}}</article>
|
|
277
|
+
</collection>
|
|
278
|
+
|
|
279
|
+
<collection name="events"
|
|
280
|
+
filters="{upcoming: true}"
|
|
281
|
+
data="{limit: 8}"
|
|
282
|
+
pagination="events-upcoming"
|
|
283
|
+
prevPages="3"
|
|
284
|
+
nextPages="1">
|
|
285
|
+
<div class="event">{{row.title}} - {{row.date}}</div>
|
|
286
|
+
</collection>
|
|
181
287
|
```
|
|
182
288
|
|
|
289
|
+
**Pagination Attributes:**
|
|
290
|
+
- `pagination="collection-id"` - Enables pagination with unique identifier
|
|
291
|
+
- `container="templateName"` - Custom pagination template (defaults to "pagedCollection")
|
|
292
|
+
- `prevPages="2"` - Number of previous page links to show (default: 2)
|
|
293
|
+
- `nextPages="2"` - Number of next page links to show (default: 2)
|
|
294
|
+
|
|
295
|
+
**Pagination URL Parameters:**
|
|
296
|
+
Pagination state is managed via URL query parameters:
|
|
297
|
+
```
|
|
298
|
+
/articles?articles-1-key={"page":2,"limit":10,"sortBy":"created_at","sortDirection":"desc"}
|
|
299
|
+
/news?news-tech-key={"page":3,"limit":5,"category":"technology"}
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
**Custom Pagination Template:**
|
|
303
|
+
Create `templates/partials/pagedCollection.html`:
|
|
304
|
+
```html
|
|
305
|
+
<div class="row paginated-contents">
|
|
306
|
+
<div class="collection-content col-lg-12 mt-2 mb-2">
|
|
307
|
+
{{&collectionContentForCurrentPage}}
|
|
308
|
+
</div>
|
|
309
|
+
<div class="pagination col-lg-12 mt-2 mb-2">
|
|
310
|
+
<ul class="pagination-list">
|
|
311
|
+
{{#prevPageUrl}}
|
|
312
|
+
<li><a href="{{prevPageUrl}}" class="page-link">{{&prevPageLabel}}</a></li>
|
|
313
|
+
{{/prevPageUrl}}
|
|
314
|
+
{{#prevPages}}
|
|
315
|
+
<li><a href="{{pageUrl}}" class="page-link">{{&pageLabel}}</a></li>
|
|
316
|
+
{{/prevPages}}
|
|
317
|
+
<li class="current">{{¤tPage}}</li>
|
|
318
|
+
{{#nextPages}}
|
|
319
|
+
<li><a href="{{pageUrl}}" class="page-link">{{&pageLabel}}</a></li>
|
|
320
|
+
{{/nextPages}}
|
|
321
|
+
{{#nextPageUrl}}
|
|
322
|
+
<li><a href="{{nextPageUrl}}" class="page-link">{{&nextPageLabel}}</a></li>
|
|
323
|
+
{{/nextPageUrl}}
|
|
324
|
+
</ul>
|
|
325
|
+
</div>
|
|
326
|
+
</div>
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
**Available Pagination Template Variables:**
|
|
330
|
+
- `{{&collectionContentForCurrentPage}}` - Rendered collection items for current page
|
|
331
|
+
- `{{currentPage}}` - Current page number
|
|
332
|
+
- `{{totalPages}}` - Total number of pages
|
|
333
|
+
- `{{totalRecords}}` - Total number of records
|
|
334
|
+
- `{{prevPageUrl}}` / `{{nextPageUrl}}` - Previous/next page URLs
|
|
335
|
+
- `{{&prevPageLabel}}` / `{{&nextPageLabel}}` - Previous/next link labels ("Previous"/"Next")
|
|
336
|
+
- `{{#prevPages}}` / `{{#nextPages}}` - Arrays of page objects with `pageUrl` and `pageLabel`
|
|
337
|
+
- `{{hasNextPage}}` / `{{hasPrevPage}}` - Boolean flags for navigation availability
|
|
338
|
+
|
|
183
339
|
**Custom Partials with Variables:**
|
|
184
340
|
|
|
185
341
|
*New HTML-style partial tags:*
|
|
@@ -282,6 +438,55 @@ Collections support advanced query parameters for pagination and sorting:
|
|
|
282
438
|
</collection>
|
|
283
439
|
```
|
|
284
440
|
|
|
441
|
+
## Internationalization
|
|
442
|
+
|
|
443
|
+
### Translation Files
|
|
444
|
+
Create translation files in the `translations` directory:
|
|
445
|
+
|
|
446
|
+
**translations/en.json:**
|
|
447
|
+
```json
|
|
448
|
+
{
|
|
449
|
+
"navigation": {
|
|
450
|
+
"home": "Home",
|
|
451
|
+
"about": "About Us",
|
|
452
|
+
"contact": "Contact"
|
|
453
|
+
},
|
|
454
|
+
"messages": {
|
|
455
|
+
"welcome": "Welcome to our site!",
|
|
456
|
+
"greeting": "Hello {name}!"
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
```
|
|
460
|
+
|
|
461
|
+
**translations/es.json:**
|
|
462
|
+
```json
|
|
463
|
+
{
|
|
464
|
+
"navigation": {
|
|
465
|
+
"home": "Inicio",
|
|
466
|
+
"about": "Acerca de",
|
|
467
|
+
"contact": "Contacto"
|
|
468
|
+
},
|
|
469
|
+
"messages": {
|
|
470
|
+
"welcome": "¡Bienvenido a nuestro sitio!",
|
|
471
|
+
"greeting": "¡Hola {name}!"
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
```
|
|
475
|
+
|
|
476
|
+
### Using Translations in Templates
|
|
477
|
+
```html
|
|
478
|
+
<!-- Simple translation -->
|
|
479
|
+
[translate(navigation.home)]
|
|
480
|
+
|
|
481
|
+
<!-- With fallback -->
|
|
482
|
+
[t(navigation.home, Home)]
|
|
483
|
+
|
|
484
|
+
<!-- With interpolation -->
|
|
485
|
+
[t(messages.greeting, Hello!, {name: John})]
|
|
486
|
+
|
|
487
|
+
<!-- Locale detection from request headers or ?locale=es parameter -->
|
|
488
|
+
```
|
|
489
|
+
|
|
285
490
|
### Layout System
|
|
286
491
|
The CMS uses a two-tier layout system:
|
|
287
492
|
|
|
@@ -292,11 +497,11 @@ The CMS uses a two-tier layout system:
|
|
|
292
497
|
<head>
|
|
293
498
|
<title>{{title}}</title>
|
|
294
499
|
<meta name="description" content="{{description}}"/>
|
|
295
|
-
<link href="/css/styles.css" rel="stylesheet"/>
|
|
500
|
+
<link href="[asset(/css/styles.css)]" rel="stylesheet"/>
|
|
296
501
|
</head>
|
|
297
502
|
<body class="{{siteHandle}}">
|
|
298
503
|
{{&content}}
|
|
299
|
-
<script src="/js/scripts.js"></script>
|
|
504
|
+
<script src="[asset(/js/scripts.js)]"></script>
|
|
300
505
|
</body>
|
|
301
506
|
</html>
|
|
302
507
|
```
|
|
@@ -332,7 +537,7 @@ Create reusable content blocks in the `cms_blocks` table via the admin panel:
|
|
|
332
537
|
INSERT INTO cms_blocks (name, title, content) VALUES
|
|
333
538
|
('contact-info', 'Contact Information', '<p>Email: info@example.com</p>'),
|
|
334
539
|
('article-sidebar', 'Article Categories',
|
|
335
|
-
'<div class="categories"><h3>Categories</h3><ul><li><a href="/articles/technology">Technology</a></li></ul></div>');
|
|
540
|
+
'<div class="categories"><h3>Categories</h3><ul><li><a href="[url(/articles/technology)]">Technology</a></li></ul></div>');
|
|
336
541
|
```
|
|
337
542
|
|
|
338
543
|
### Entity Access Control
|
|
@@ -369,12 +574,41 @@ templates/
|
|
|
369
574
|
├── partials/
|
|
370
575
|
│ ├── header.html (default)
|
|
371
576
|
│ └── footer.html (default)
|
|
577
|
+
├── translations/
|
|
578
|
+
│ ├── en.json
|
|
579
|
+
│ ├── es.json
|
|
580
|
+
│ └── fr.json
|
|
372
581
|
├── page.html (base HTML wrapper)
|
|
373
582
|
└── 404.html
|
|
374
583
|
```
|
|
375
584
|
|
|
376
585
|
## Advanced Usage
|
|
377
586
|
|
|
587
|
+
### Event System
|
|
588
|
+
The CMS provides hooks for customization through event listeners:
|
|
589
|
+
|
|
590
|
+
```javascript
|
|
591
|
+
// Listen for template variable events
|
|
592
|
+
cms.events.on('reldens.afterVariablesCreated', (eventData) => {
|
|
593
|
+
// Add custom variables
|
|
594
|
+
eventData.variables.customData = {
|
|
595
|
+
timestamp: Date.now(),
|
|
596
|
+
version: '1.0.0'
|
|
597
|
+
};
|
|
598
|
+
});
|
|
599
|
+
|
|
600
|
+
// Listen for content processing events
|
|
601
|
+
cms.events.on('reldens.beforeContentProcess', (eventData) => {
|
|
602
|
+
// Modify content before processing
|
|
603
|
+
eventData.content = eventData.content.replace(/\[custom\]/g, 'Custom Value');
|
|
604
|
+
});
|
|
605
|
+
|
|
606
|
+
cms.events.on('reldens.afterContentProcess', (eventData) => {
|
|
607
|
+
// Modify processed content
|
|
608
|
+
eventData.processedContent += '\n<!-- Processed at ' + new Date() + ' -->';
|
|
609
|
+
});
|
|
610
|
+
```
|
|
611
|
+
|
|
378
612
|
### Custom Authentication
|
|
379
613
|
```javascript
|
|
380
614
|
const customAuth = async (email, password, roleId) => {
|
|
@@ -452,13 +686,15 @@ The installer provides checkboxes for:
|
|
|
452
686
|
- `findEntityByPath(path)` - Entity-based URL handling
|
|
453
687
|
|
|
454
688
|
### TemplateEngine Class
|
|
455
|
-
- `render(template, data, partials)` - Main template rendering with enhanced
|
|
456
|
-
- `
|
|
457
|
-
- `
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
- `
|
|
461
|
-
- `
|
|
689
|
+
- `render(template, data, partials, domain, req, route, currentEntityData)` - Main template rendering with enhanced context
|
|
690
|
+
- `processAllTemplateFunctions(template, domain, req, systemVariables)` - Process all template functions
|
|
691
|
+
- `buildEnhancedRenderData(data, systemVariables, currentEntityData)` - Build template context with system variables
|
|
692
|
+
|
|
693
|
+
### SystemVariablesProvider Class
|
|
694
|
+
- `buildSystemVariables(req, route, domain)` - Create system variables for templates
|
|
695
|
+
- `buildCurrentRequestData(req, domain)` - Build request context
|
|
696
|
+
- `buildCurrentRouteData(route)` - Build route context
|
|
697
|
+
- `buildCurrentDomainData(domain)` - Build domain context
|
|
462
698
|
|
|
463
699
|
### AdminManager Class
|
|
464
700
|
- `setupAdmin()` - Initialize admin panel
|
|
@@ -483,6 +719,10 @@ project/
|
|
|
483
719
|
│ ├── partials/ # Shared template partials
|
|
484
720
|
│ ├── page.html # Base HTML wrapper
|
|
485
721
|
│ └── 404.html # Error page
|
|
722
|
+
├── translations/
|
|
723
|
+
│ ├── en.json # English translations
|
|
724
|
+
│ ├── es.json # Spanish translations
|
|
725
|
+
│ └── fr.json # French translations
|
|
486
726
|
├── public/
|
|
487
727
|
│ ├── css/ # Stylesheets
|
|
488
728
|
│ ├── js/ # Client scripts
|