@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.
Files changed (36) hide show
  1. package/README.md +260 -20
  2. package/admin/reldens-admin-client.css +127 -80
  3. package/admin/reldens-admin-client.js +24 -0
  4. package/admin/templates/clear-all-cache-button.html +18 -0
  5. package/lib/admin-manager/contents-builder.js +7 -6
  6. package/lib/admin-manager/router-contents.js +58 -16
  7. package/lib/admin-manager-validator.js +2 -1
  8. package/lib/admin-manager.js +4 -2
  9. package/lib/admin-translations.js +9 -1
  10. package/lib/cache/add-cache-button-subscriber.js +53 -5
  11. package/lib/cache/cache-manager.js +47 -8
  12. package/lib/cache/cache-routes-handler.js +23 -0
  13. package/lib/cms-pages-route-manager.js +16 -4
  14. package/lib/frontend.js +310 -119
  15. package/lib/manager.js +43 -3
  16. package/lib/pagination-handler.js +243 -0
  17. package/lib/search-renderer.js +116 -0
  18. package/lib/search.js +344 -0
  19. package/lib/template-engine/asset-transformer.js +41 -0
  20. package/lib/template-engine/collections-single-transformer.js +70 -0
  21. package/lib/template-engine/collections-transformer-base.js +84 -0
  22. package/lib/template-engine/collections-transformer.js +374 -0
  23. package/lib/template-engine/date-transformer.js +53 -0
  24. package/lib/template-engine/entities-transformer.js +67 -0
  25. package/lib/template-engine/partials-transformer.js +175 -0
  26. package/lib/template-engine/system-variables-provider.js +105 -0
  27. package/lib/template-engine/translate-transformer.js +98 -0
  28. package/lib/template-engine/translation-service.js +104 -0
  29. package/lib/template-engine/url-transformer.js +41 -0
  30. package/lib/template-engine.js +133 -438
  31. package/lib/templates-list.js +1 -0
  32. package/migrations/install.sql +18 -18
  33. package/package.json +4 -4
  34. package/templates/page.html +19 -2
  35. package/templates/partials/entriesListView.html +14 -0
  36. 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
- <div class="block">
161
- <h3>{{row.title}}</h3>
162
- <div class="content">{{row.content}}</div>
163
- </div>
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
- <div class="article">
168
- <h4>{{row.title}}</h4>
169
- <p>{{row.summary}}</p>
170
- <img src="{{row.featured_image}}" alt="{{row.title}}">
171
- </div>
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">{{&currentPage}}</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 functions
456
- - `processEntityFunctions(template)` - Process `<entity>` functions
457
- - `processSingleFieldCollections(template)` - Process single field collections with query options
458
- - `processLoopCollections(template)` - Process loop collections with query options
459
- - `processCustomPartials(template)` - Process `<partial>` tags with attribute parsing
460
- - `fetchEntityForTemplate(tableName, identifier, identifierField)` - Load single entity
461
- - `fetchCollectionForTemplate(tableName, filtersJson, queryOptionsJson)` - Load entity collections with pagination and sorting
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