@researchdatabox/sails-ng-common 0.2.1 → 5.0.0-RC1
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/dist/src/config/base-field-component.model.d.ts +26 -0
- package/dist/src/config/base-field-component.model.js +29 -0
- package/dist/src/config/base-field-component.outline.d.ts +108 -0
- package/dist/src/config/base-field-component.outline.js +3 -0
- package/dist/src/config/component/accordion.model.d.ts +103 -0
- package/dist/src/config/component/accordion.model.js +127 -0
- package/dist/src/config/component/accordion.outline.d.ts +162 -0
- package/dist/src/config/component/accordion.outline.js +13 -0
- package/dist/src/config/component/action-row-layout.model.d.ts +28 -0
- package/dist/src/config/component/action-row-layout.model.js +35 -0
- package/dist/src/config/component/action-row-layout.outline.d.ts +36 -0
- package/dist/src/config/component/action-row-layout.outline.js +6 -0
- package/dist/src/config/component/cancel-button.model.d.ts +48 -0
- package/dist/src/config/component/cancel-button.model.js +58 -0
- package/dist/src/config/component/cancel-button.outline.d.ts +85 -0
- package/dist/src/config/component/cancel-button.outline.js +6 -0
- package/dist/src/config/component/checkbox-input.model.d.ts +67 -0
- package/dist/src/config/component/checkbox-input.model.js +79 -0
- package/dist/src/config/component/checkbox-input.outline.d.ts +93 -0
- package/dist/src/config/component/checkbox-input.outline.js +8 -0
- package/dist/src/config/component/checkbox-tree.model.d.ts +68 -0
- package/dist/src/config/component/checkbox-tree.model.js +80 -0
- package/dist/src/config/component/checkbox-tree.outline.d.ts +105 -0
- package/dist/src/config/component/checkbox-tree.outline.js +8 -0
- package/dist/src/config/component/content.model.d.ts +46 -0
- package/dist/src/config/component/content.model.js +56 -0
- package/dist/src/config/component/content.outline.d.ts +74 -0
- package/dist/src/config/component/content.outline.js +6 -0
- package/dist/src/config/component/data-location.model.d.ts +83 -0
- package/dist/src/config/component/data-location.model.js +95 -0
- package/dist/src/config/component/data-location.outline.d.ts +124 -0
- package/dist/src/config/component/data-location.outline.js +6 -0
- package/dist/src/config/component/date-input.model.d.ts +67 -0
- package/dist/src/config/component/date-input.model.js +80 -0
- package/dist/src/config/component/date-input.outline.d.ts +88 -0
- package/dist/src/config/component/date-input.outline.js +8 -0
- package/dist/src/config/component/default-layout.model.d.ts +22 -0
- package/dist/src/config/component/default-layout.model.js +30 -0
- package/dist/src/config/component/default-layout.outline.d.ts +29 -0
- package/dist/src/config/component/default-layout.outline.js +5 -0
- package/dist/src/config/component/delete-button.model.d.ts +46 -0
- package/dist/src/config/component/delete-button.model.js +48 -0
- package/dist/src/config/component/delete-button.outline.d.ts +89 -0
- package/dist/src/config/component/delete-button.outline.js +5 -0
- package/dist/src/config/component/dropdown-input.model.d.ts +65 -0
- package/dist/src/config/component/dropdown-input.model.js +78 -0
- package/dist/src/config/component/dropdown-input.outline.d.ts +92 -0
- package/dist/src/config/component/dropdown-input.outline.js +8 -0
- package/dist/src/config/component/file-upload.model.d.ts +67 -0
- package/dist/src/config/component/file-upload.model.js +81 -0
- package/dist/src/config/component/file-upload.outline.d.ts +99 -0
- package/dist/src/config/component/file-upload.outline.js +8 -0
- package/dist/src/config/component/group.model.d.ts +61 -0
- package/dist/src/config/component/group.model.js +75 -0
- package/dist/src/config/component/group.outline.d.ts +83 -0
- package/dist/src/config/component/group.outline.js +8 -0
- package/dist/src/config/component/inline-layout.model.d.ts +22 -0
- package/dist/src/config/component/inline-layout.model.js +29 -0
- package/dist/src/config/component/inline-layout.outline.d.ts +29 -0
- package/dist/src/config/component/inline-layout.outline.js +5 -0
- package/dist/src/config/component/integration-status.model.d.ts +49 -0
- package/dist/src/config/component/integration-status.model.js +65 -0
- package/dist/src/config/component/integration-status.outline.d.ts +61 -0
- package/dist/src/config/component/integration-status.outline.js +5 -0
- package/dist/src/config/component/map.model.d.ts +69 -0
- package/dist/src/config/component/map.model.js +86 -0
- package/dist/src/config/component/map.outline.d.ts +110 -0
- package/dist/src/config/component/map.outline.js +8 -0
- package/dist/src/config/component/pdf-list.model.d.ts +68 -0
- package/dist/src/config/component/pdf-list.model.js +71 -0
- package/dist/src/config/component/pdf-list.outline.d.ts +97 -0
- package/dist/src/config/component/pdf-list.outline.js +6 -0
- package/dist/src/config/component/publish-data-location-refresh.model.d.ts +39 -0
- package/dist/src/config/component/publish-data-location-refresh.model.js +52 -0
- package/dist/src/config/component/publish-data-location-refresh.outline.d.ts +58 -0
- package/dist/src/config/component/publish-data-location-refresh.outline.js +5 -0
- package/dist/src/config/component/publish-data-location-selector.model.d.ts +78 -0
- package/dist/src/config/component/publish-data-location-selector.model.js +104 -0
- package/dist/src/config/component/publish-data-location-selector.outline.d.ts +110 -0
- package/dist/src/config/component/publish-data-location-selector.outline.js +6 -0
- package/dist/src/config/component/question-tree.helper.d.ts +58 -0
- package/dist/src/config/component/question-tree.helper.js +291 -0
- package/dist/src/config/component/question-tree.model.d.ts +64 -0
- package/dist/src/config/component/question-tree.model.js +80 -0
- package/dist/src/config/component/question-tree.outline.d.ts +314 -0
- package/dist/src/config/component/question-tree.outline.js +9 -0
- package/dist/src/config/component/radio-input.model.d.ts +65 -0
- package/dist/src/config/component/radio-input.model.js +77 -0
- package/dist/src/config/component/radio-input.outline.d.ts +91 -0
- package/dist/src/config/component/radio-input.outline.js +8 -0
- package/dist/src/config/component/record-metadata-retriever.model.d.ts +41 -0
- package/dist/src/config/component/record-metadata-retriever.model.js +57 -0
- package/dist/src/config/component/record-metadata-retriever.outline.d.ts +53 -0
- package/dist/src/config/component/record-metadata-retriever.outline.js +5 -0
- package/dist/src/config/component/record-selector.model.d.ts +61 -0
- package/dist/src/config/component/record-selector.model.js +61 -0
- package/dist/src/config/component/record-selector.outline.d.ts +91 -0
- package/dist/src/config/component/record-selector.outline.js +6 -0
- package/dist/src/config/component/repeatable.model.d.ts +91 -0
- package/dist/src/config/component/repeatable.model.js +112 -0
- package/dist/src/config/component/repeatable.outline.d.ts +115 -0
- package/dist/src/config/component/repeatable.outline.js +10 -0
- package/dist/src/config/component/reusable.model.d.ts +42 -0
- package/dist/src/config/component/reusable.model.js +57 -0
- package/dist/src/config/component/reusable.outline.d.ts +55 -0
- package/dist/src/config/component/reusable.outline.js +6 -0
- package/dist/src/config/component/rich-text-editor.model.d.ts +65 -0
- package/dist/src/config/component/rich-text-editor.model.js +79 -0
- package/dist/src/config/component/rich-text-editor.outline.d.ts +92 -0
- package/dist/src/config/component/rich-text-editor.outline.js +8 -0
- package/dist/src/config/component/save-button.model.d.ts +49 -0
- package/dist/src/config/component/save-button.model.js +59 -0
- package/dist/src/config/component/save-button.outline.d.ts +90 -0
- package/dist/src/config/component/save-button.outline.js +6 -0
- package/dist/src/config/component/save-status.model.d.ts +42 -0
- package/dist/src/config/component/save-status.model.js +60 -0
- package/dist/src/config/component/save-status.outline.d.ts +58 -0
- package/dist/src/config/component/save-status.outline.js +6 -0
- package/dist/src/config/component/simple-input.model.d.ts +62 -0
- package/dist/src/config/component/simple-input.model.js +75 -0
- package/dist/src/config/component/simple-input.outline.d.ts +86 -0
- package/dist/src/config/component/simple-input.outline.js +9 -0
- package/dist/src/config/component/suggested-validation-summary.model.d.ts +45 -0
- package/dist/src/config/component/suggested-validation-summary.model.js +61 -0
- package/dist/src/config/component/suggested-validation-summary.outline.d.ts +57 -0
- package/dist/src/config/component/suggested-validation-summary.outline.js +5 -0
- package/dist/src/config/component/tab-content.model.d.ts +63 -0
- package/dist/src/config/component/tab-content.model.js +77 -0
- package/dist/src/config/component/tab-content.outline.d.ts +98 -0
- package/dist/src/config/component/tab-content.outline.js +8 -0
- package/dist/src/config/component/tab-nav-button.model.d.ts +45 -0
- package/dist/src/config/component/tab-nav-button.model.js +55 -0
- package/dist/src/config/component/tab-nav-button.outline.d.ts +70 -0
- package/dist/src/config/component/tab-nav-button.outline.js +6 -0
- package/dist/src/config/component/tab.model.d.ts +71 -0
- package/dist/src/config/component/tab.model.js +84 -0
- package/dist/src/config/component/tab.outline.d.ts +112 -0
- package/dist/src/config/component/tab.outline.js +9 -0
- package/dist/src/config/component/text-area.model.d.ts +63 -0
- package/dist/src/config/component/text-area.model.js +76 -0
- package/dist/src/config/component/text-area.outline.d.ts +87 -0
- package/dist/src/config/component/text-area.outline.js +8 -0
- package/dist/src/config/component/typeahead-input.model.d.ts +83 -0
- package/dist/src/config/component/typeahead-input.model.js +97 -0
- package/dist/src/config/component/typeahead-input.outline.d.ts +199 -0
- package/dist/src/config/component/typeahead-input.outline.js +10 -0
- package/dist/src/config/component/validation-summary.model.d.ts +42 -0
- package/dist/src/config/component/validation-summary.model.js +60 -0
- package/dist/src/config/component/validation-summary.outline.d.ts +63 -0
- package/dist/src/config/component/validation-summary.outline.js +6 -0
- package/dist/src/config/dictionary.model.d.ts +648 -0
- package/dist/src/config/dictionary.model.js +181 -0
- package/dist/src/config/dictionary.outline.d.ts +96 -0
- package/dist/src/config/dictionary.outline.js +3 -0
- package/dist/src/config/field-component.model.d.ts +7 -0
- package/dist/src/config/field-component.model.js +11 -0
- package/dist/src/config/field-component.outline.d.ts +20 -0
- package/dist/src/config/field-component.outline.js +3 -0
- package/dist/src/config/field-layout.model.d.ts +19 -0
- package/dist/src/config/field-layout.model.js +23 -0
- package/dist/src/config/field-layout.outline.d.ts +42 -0
- package/dist/src/config/field-layout.outline.js +3 -0
- package/dist/src/config/field-model.model.d.ts +21 -0
- package/dist/src/config/field-model.model.js +24 -0
- package/dist/src/config/field-model.outline.d.ts +63 -0
- package/dist/src/config/field-model.outline.js +3 -0
- package/dist/src/config/field.model.d.ts +12 -0
- package/dist/src/config/field.model.js +12 -0
- package/dist/src/config/field.outline.d.ts +19 -0
- package/dist/src/config/field.outline.js +3 -0
- package/dist/src/config/form-behaviour.outline.d.ts +128 -0
- package/dist/src/config/form-behaviour.outline.js +40 -0
- package/dist/src/config/form-component.model.d.ts +38 -0
- package/dist/src/config/form-component.model.js +36 -0
- package/dist/src/config/form-component.outline.d.ts +305 -0
- package/dist/src/config/form-component.outline.js +27 -0
- package/dist/src/config/form-config.model.d.ts +33 -0
- package/dist/src/config/form-config.model.js +36 -0
- package/dist/src/config/form-config.outline.d.ts +111 -0
- package/dist/src/config/form-config.outline.js +3 -0
- package/dist/src/config/form-override.model.d.ts +146 -0
- package/dist/src/config/form-override.model.js +1523 -0
- package/dist/src/config/form-override.outline.d.ts +15 -0
- package/dist/src/config/form-override.outline.js +3 -0
- package/dist/src/config/form-prehydrate.outline.d.ts +17 -0
- package/dist/src/config/form-prehydrate.outline.js +5 -0
- package/dist/src/config/form-types.model.d.ts +6 -0
- package/dist/src/config/form-types.model.js +23 -0
- package/dist/src/config/form-types.outline.d.ts +48 -0
- package/dist/src/config/form-types.outline.js +137 -0
- package/dist/src/config/helpers.d.ts +31 -0
- package/dist/src/config/helpers.js +122 -0
- package/dist/src/config/names/naming-helpers.d.ts +112 -0
- package/dist/src/config/names/naming-helpers.js +188 -0
- package/dist/src/config/names/query-helpers.d.ts +43 -0
- package/dist/src/config/names/query-helpers.js +59 -0
- package/dist/src/config/shared.outline.d.ts +54 -0
- package/dist/src/config/shared.outline.js +41 -0
- package/dist/src/config/visitor/base.model.d.ts +143 -0
- package/dist/src/config/visitor/base.model.js +336 -0
- package/dist/src/config/visitor/base.outline.d.ts +146 -0
- package/dist/src/config/visitor/base.outline.js +3 -0
- package/dist/src/config/visitor/common.model.d.ts +119 -0
- package/dist/src/config/visitor/common.model.js +422 -0
- package/dist/src/date-format-helpers.d.ts +1 -0
- package/dist/src/date-format-helpers.js +21 -0
- package/dist/src/handlebars-helpers.d.ts +258 -0
- package/dist/src/handlebars-helpers.js +715 -0
- package/dist/src/html-helpers.d.ts +15 -0
- package/dist/src/html-helpers.js +42 -0
- package/dist/src/index.d.ts +118 -3
- package/dist/src/index.js +127 -2
- package/dist/src/jsonata-helpers.d.ts +40 -0
- package/dist/src/jsonata-helpers.js +118 -0
- package/dist/src/logger.interface.d.ts +14 -0
- package/dist/src/logger.interface.js +3 -0
- package/dist/src/record.model.d.ts +23 -0
- package/dist/src/record.model.js +19 -1
- package/dist/src/report.model.d.ts +46 -0
- package/dist/src/status.model.d.ts +22 -0
- package/dist/src/status.model.js +28 -0
- package/dist/src/template.outline.d.ts +82 -0
- package/dist/src/template.outline.js +14 -0
- package/dist/src/translation-helpers.d.ts +26 -0
- package/dist/src/translation-helpers.js +71 -0
- package/dist/src/validation/form.model.d.ts +306 -24
- package/dist/src/validation/form.model.js +29 -1
- package/dist/src/validation/helpers.d.ts +15 -7
- package/dist/src/validation/helpers.js +49 -13
- package/dist/src/validation/validators-support.d.ts +39 -2
- package/dist/src/validation/validators-support.js +162 -12
- package/dist/src/validation/validators.d.ts +28 -0
- package/dist/src/validation/validators.js +531 -0
- package/package.json +51 -34
- package/LICENSE +0 -674
- package/dist/src/validation/index.d.ts +0 -3
- package/dist/src/validation/index.js +0 -20
|
@@ -0,0 +1,715 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Copyright (c) 2025 Queensland Cyber Infrastructure Foundation (http://www.qcif.edu.au/)
|
|
3
|
+
//
|
|
4
|
+
// GNU GENERAL PUBLIC LICENSE
|
|
5
|
+
// Version 2, June 1991
|
|
6
|
+
//
|
|
7
|
+
// This program is free software; you can redistribute it and/or modify
|
|
8
|
+
// it under the terms of the GNU General Public License as published by
|
|
9
|
+
// the Free Software Foundation; either version 2 of the License, or
|
|
10
|
+
// (at your option) any later version.
|
|
11
|
+
//
|
|
12
|
+
// This program is distributed in the hope that it will be useful,
|
|
13
|
+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
14
|
+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
15
|
+
// GNU General Public License for more details.
|
|
16
|
+
//
|
|
17
|
+
// You should have received a copy of the GNU General Public License along
|
|
18
|
+
// with this program; if not, write to the Free Software Foundation, Inc.,
|
|
19
|
+
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
20
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
21
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
22
|
+
};
|
|
23
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
24
|
+
exports.handlebarsHelperDefinitions = void 0;
|
|
25
|
+
exports.handlebarsInstance = handlebarsInstance;
|
|
26
|
+
exports.handlebarsPrecompile = handlebarsPrecompile;
|
|
27
|
+
exports.handlebarsCompile = handlebarsCompile;
|
|
28
|
+
exports.handlebarsTemplate = handlebarsTemplate;
|
|
29
|
+
const luxon_1 = require("luxon");
|
|
30
|
+
const handlebars_1 = __importDefault(require("handlebars"));
|
|
31
|
+
const lodash_1 = require("lodash");
|
|
32
|
+
const date_format_helpers_1 = require("./date-format-helpers");
|
|
33
|
+
const html_helpers_1 = require("./html-helpers");
|
|
34
|
+
const naming_helpers_1 = require("./config/names/naming-helpers");
|
|
35
|
+
function isHandlebarsOptionsArg(value) {
|
|
36
|
+
return (typeof value === 'object' &&
|
|
37
|
+
value !== null &&
|
|
38
|
+
(Object.prototype.hasOwnProperty.call(value, 'hash') ||
|
|
39
|
+
Object.prototype.hasOwnProperty.call(value, 'data') ||
|
|
40
|
+
Object.prototype.hasOwnProperty.call(value, 'fn') ||
|
|
41
|
+
Object.prototype.hasOwnProperty.call(value, 'inverse')));
|
|
42
|
+
}
|
|
43
|
+
// TODO: this is because the DateInputComponent needs Luxon style formatters. We have a moment shim on the server side but not on the client.
|
|
44
|
+
function resolveDateFormatArg(formatOrOptions) {
|
|
45
|
+
if (typeof formatOrOptions === 'string') {
|
|
46
|
+
return (0, date_format_helpers_1.mapMomentToLuxonFormat)(formatOrOptions);
|
|
47
|
+
}
|
|
48
|
+
if (isHandlebarsOptionsArg(formatOrOptions)) {
|
|
49
|
+
return undefined;
|
|
50
|
+
}
|
|
51
|
+
return undefined;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Marked is an ESM module so cannot be imported synchronously in a CommonJS context.
|
|
55
|
+
* We use dynamic import to load it when needed, and cache the parser function for future use. If the module cannot be loaded, the markdownToHtml helper will simply return the input string unmodified.
|
|
56
|
+
*/
|
|
57
|
+
let cachedMarkedParser;
|
|
58
|
+
void import('marked')
|
|
59
|
+
.then(markedModule => {
|
|
60
|
+
const parseFn = markedModule?.marked?.parse ?? markedModule?.parse;
|
|
61
|
+
if (typeof parseFn === 'function') {
|
|
62
|
+
cachedMarkedParser = (value) => {
|
|
63
|
+
const result = parseFn(value);
|
|
64
|
+
return typeof result === 'string' ? result : value;
|
|
65
|
+
};
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
cachedMarkedParser = null;
|
|
69
|
+
})
|
|
70
|
+
.catch(() => {
|
|
71
|
+
cachedMarkedParser = null;
|
|
72
|
+
});
|
|
73
|
+
function resolveMarkedParser() {
|
|
74
|
+
return cachedMarkedParser ?? null;
|
|
75
|
+
}
|
|
76
|
+
function isPrimitiveMetadataValue(value) {
|
|
77
|
+
return (value === null ||
|
|
78
|
+
value === undefined ||
|
|
79
|
+
typeof value === 'string' ||
|
|
80
|
+
typeof value === 'number' ||
|
|
81
|
+
typeof value === 'boolean');
|
|
82
|
+
}
|
|
83
|
+
function isFlatObject(value) {
|
|
84
|
+
if (!(0, lodash_1.isPlainObject)(value)) {
|
|
85
|
+
return false;
|
|
86
|
+
}
|
|
87
|
+
return Object.values(value).every(entry => isPrimitiveMetadataValue(entry));
|
|
88
|
+
}
|
|
89
|
+
function renderMetadataPrimitive(value) {
|
|
90
|
+
if ((0, lodash_1.isUndefined)(value) || (0, lodash_1.isNull)(value) || value === '') {
|
|
91
|
+
return '<em class="text-muted">—</em>';
|
|
92
|
+
}
|
|
93
|
+
return (0, html_helpers_1.escapeHtmlText)(value);
|
|
94
|
+
}
|
|
95
|
+
function renderMetadataObjectEntries(value) {
|
|
96
|
+
const entries = Object.entries(value);
|
|
97
|
+
if (entries.length === 0) {
|
|
98
|
+
return '<em class="text-muted">—</em>';
|
|
99
|
+
}
|
|
100
|
+
const rows = entries
|
|
101
|
+
.map(([key, entryValue]) => {
|
|
102
|
+
return `<div class="rb-view-metadata__nested-row"><div class="rb-view-metadata__nested-key">${(0, html_helpers_1.escapeHtmlText)(key)}</div><div class="rb-view-metadata__nested-value">${renderMetadataValue(entryValue)}</div></div>`;
|
|
103
|
+
})
|
|
104
|
+
.join('');
|
|
105
|
+
return `<div class="rb-view-metadata__nested">${rows}</div>`;
|
|
106
|
+
}
|
|
107
|
+
function renderMetadataTable(value) {
|
|
108
|
+
if (value.length === 0) {
|
|
109
|
+
return '<em class="text-muted">—</em>';
|
|
110
|
+
}
|
|
111
|
+
const columnsSet = new Set();
|
|
112
|
+
for (const row of value) {
|
|
113
|
+
for (const key of Object.keys(row)) {
|
|
114
|
+
columnsSet.add(key);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
const columns = Array.from(columnsSet);
|
|
118
|
+
if (columns.length === 0) {
|
|
119
|
+
return '<em class="text-muted">—</em>';
|
|
120
|
+
}
|
|
121
|
+
const headerHtml = columns.map(key => `<th>${(0, html_helpers_1.escapeHtmlText)(key)}</th>`).join('');
|
|
122
|
+
const rowHtml = value
|
|
123
|
+
.map(row => {
|
|
124
|
+
const cells = columns.map(key => `<td>${renderMetadataPrimitive(row[key])}</td>`).join('');
|
|
125
|
+
return `<tr>${cells}</tr>`;
|
|
126
|
+
})
|
|
127
|
+
.join('');
|
|
128
|
+
return `<div class="rb-view-metadata__table-wrapper"><table class="table table-striped table-sm rb-view-metadata__table"><thead><tr>${headerHtml}</tr></thead><tbody>${rowHtml}</tbody></table></div>`;
|
|
129
|
+
}
|
|
130
|
+
function renderMetadataArray(value) {
|
|
131
|
+
if (value.length === 0) {
|
|
132
|
+
return '<em class="text-muted">—</em>';
|
|
133
|
+
}
|
|
134
|
+
if (value.every(entry => typeof entry === 'string')) {
|
|
135
|
+
const items = value.map(entry => `<li>${(0, html_helpers_1.escapeHtmlText)(entry)}</li>`).join('');
|
|
136
|
+
return `<ul class="rb-view-metadata__list">${items}</ul>`;
|
|
137
|
+
}
|
|
138
|
+
if (value.every(entry => isFlatObject(entry))) {
|
|
139
|
+
return renderMetadataTable(value);
|
|
140
|
+
}
|
|
141
|
+
const items = value.map(entry => `<li>${renderMetadataValue(entry)}</li>`).join('');
|
|
142
|
+
return `<ul class="rb-view-metadata__list">${items}</ul>`;
|
|
143
|
+
}
|
|
144
|
+
function renderMetadataValue(value) {
|
|
145
|
+
if ((0, lodash_1.isArray)(value)) {
|
|
146
|
+
return renderMetadataArray(value);
|
|
147
|
+
}
|
|
148
|
+
if ((0, lodash_1.isPlainObject)(value)) {
|
|
149
|
+
return renderMetadataObjectEntries(value);
|
|
150
|
+
}
|
|
151
|
+
return renderMetadataPrimitive(value);
|
|
152
|
+
}
|
|
153
|
+
function trimSlashes(value) {
|
|
154
|
+
const text = String(value ?? '');
|
|
155
|
+
let start = 0;
|
|
156
|
+
let end = text.length;
|
|
157
|
+
while (start < end && text[start] === '/')
|
|
158
|
+
start++;
|
|
159
|
+
while (end > start && text[end - 1] === '/')
|
|
160
|
+
end--;
|
|
161
|
+
return text.slice(start, end);
|
|
162
|
+
}
|
|
163
|
+
function isSafeDownloadUrl(value) {
|
|
164
|
+
return /^https?:\/\//i.test(value) || value.startsWith('/');
|
|
165
|
+
}
|
|
166
|
+
function resolveAttachmentLocation(location, branding, portal) {
|
|
167
|
+
if (!location) {
|
|
168
|
+
return '';
|
|
169
|
+
}
|
|
170
|
+
if (/^https?:\/\//i.test(location)) {
|
|
171
|
+
return location;
|
|
172
|
+
}
|
|
173
|
+
const recordRelativeMatch = location.match(/^([^/]+)\/attach\/([^/?#]+)$/);
|
|
174
|
+
if (recordRelativeMatch) {
|
|
175
|
+
const prefix = [trimSlashes(branding), trimSlashes(portal)].filter(Boolean).join('/');
|
|
176
|
+
const path = `record/${encodeURIComponent(recordRelativeMatch[1])}/attach/${encodeURIComponent(recordRelativeMatch[2])}`;
|
|
177
|
+
return `/${[prefix, path].filter(Boolean).join('/')}`;
|
|
178
|
+
}
|
|
179
|
+
if (!isSafeDownloadUrl(location)) {
|
|
180
|
+
return '';
|
|
181
|
+
}
|
|
182
|
+
if (location.startsWith('/record/')) {
|
|
183
|
+
const prefix = [trimSlashes(branding), trimSlashes(portal)].filter(Boolean).join('/');
|
|
184
|
+
return prefix ? `/${prefix}${location}` : location;
|
|
185
|
+
}
|
|
186
|
+
return location;
|
|
187
|
+
}
|
|
188
|
+
function buildAttachmentDownloadUrl(attachment, oid, branding, portal) {
|
|
189
|
+
if (!(0, lodash_1.isPlainObject)(attachment)) {
|
|
190
|
+
return '';
|
|
191
|
+
}
|
|
192
|
+
const item = attachment;
|
|
193
|
+
const url = String(item.url ?? '').trim();
|
|
194
|
+
if (url && isSafeDownloadUrl(url)) {
|
|
195
|
+
return url;
|
|
196
|
+
}
|
|
197
|
+
const uploadUrl = String(item.uploadUrl ?? '').trim();
|
|
198
|
+
if (uploadUrl) {
|
|
199
|
+
try {
|
|
200
|
+
const parsedUploadUrl = new URL(uploadUrl);
|
|
201
|
+
const uploadPath = resolveAttachmentLocation(parsedUploadUrl.pathname, branding, portal);
|
|
202
|
+
if (uploadPath) {
|
|
203
|
+
return uploadPath;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
catch {
|
|
207
|
+
const uploadPath = resolveAttachmentLocation(uploadUrl, branding, portal);
|
|
208
|
+
if (uploadPath) {
|
|
209
|
+
return uploadPath;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
const location = resolveAttachmentLocation(String(item.location ?? '').trim(), branding, portal);
|
|
214
|
+
if (location) {
|
|
215
|
+
return location;
|
|
216
|
+
}
|
|
217
|
+
const fileId = String(item.fileId ?? '').trim();
|
|
218
|
+
const recordOid = String(oid ?? '').trim();
|
|
219
|
+
if (!fileId || !recordOid) {
|
|
220
|
+
return '';
|
|
221
|
+
}
|
|
222
|
+
const prefix = [trimSlashes(branding), trimSlashes(portal)].filter(Boolean).join('/');
|
|
223
|
+
const path = `record/${encodeURIComponent(recordOid)}/attach/${encodeURIComponent(fileId)}`;
|
|
224
|
+
return `/${[prefix, path].filter(Boolean).join('/')}`;
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* Shared Handlebars helper definitions for use in both server and client contexts.
|
|
228
|
+
* These helpers provide CSP-safe alternatives to lodash template expressions.
|
|
229
|
+
*
|
|
230
|
+
* Usage:
|
|
231
|
+
* - Server: Import and register with Handlebars.registerHelper()
|
|
232
|
+
* - Client: Import and register with Handlebars runtime
|
|
233
|
+
*/
|
|
234
|
+
/**
|
|
235
|
+
* Preset mapping for locale-aware date formatting.
|
|
236
|
+
* Maps preset names to Luxon's built-in format options.
|
|
237
|
+
*/
|
|
238
|
+
const dateLocalePresetMap = {
|
|
239
|
+
DATE_SHORT: luxon_1.DateTime.DATE_SHORT,
|
|
240
|
+
DATE_MED: luxon_1.DateTime.DATE_MED,
|
|
241
|
+
DATE_MED_WITH_WEEKDAY: luxon_1.DateTime.DATE_MED_WITH_WEEKDAY,
|
|
242
|
+
DATE_FULL: luxon_1.DateTime.DATE_FULL,
|
|
243
|
+
DATE_HUGE: luxon_1.DateTime.DATE_HUGE,
|
|
244
|
+
TIME_SIMPLE: luxon_1.DateTime.TIME_SIMPLE,
|
|
245
|
+
TIME_WITH_SECONDS: luxon_1.DateTime.TIME_WITH_SECONDS,
|
|
246
|
+
TIME_WITH_SHORT_OFFSET: luxon_1.DateTime.TIME_WITH_SHORT_OFFSET,
|
|
247
|
+
TIME_WITH_LONG_OFFSET: luxon_1.DateTime.TIME_WITH_LONG_OFFSET,
|
|
248
|
+
TIME_24_SIMPLE: luxon_1.DateTime.TIME_24_SIMPLE,
|
|
249
|
+
TIME_24_WITH_SECONDS: luxon_1.DateTime.TIME_24_WITH_SECONDS,
|
|
250
|
+
TIME_24_WITH_SHORT_OFFSET: luxon_1.DateTime.TIME_24_WITH_SHORT_OFFSET,
|
|
251
|
+
TIME_24_WITH_LONG_OFFSET: luxon_1.DateTime.TIME_24_WITH_LONG_OFFSET,
|
|
252
|
+
DATETIME_SHORT: luxon_1.DateTime.DATETIME_SHORT,
|
|
253
|
+
DATETIME_MED: luxon_1.DateTime.DATETIME_MED,
|
|
254
|
+
DATETIME_FULL: luxon_1.DateTime.DATETIME_FULL,
|
|
255
|
+
DATETIME_HUGE: luxon_1.DateTime.DATETIME_HUGE,
|
|
256
|
+
DATETIME_SHORT_WITH_SECONDS: luxon_1.DateTime.DATETIME_SHORT_WITH_SECONDS,
|
|
257
|
+
DATETIME_MED_WITH_SECONDS: luxon_1.DateTime.DATETIME_MED_WITH_SECONDS,
|
|
258
|
+
DATETIME_FULL_WITH_SECONDS: luxon_1.DateTime.DATETIME_FULL_WITH_SECONDS,
|
|
259
|
+
DATETIME_HUGE_WITH_SECONDS: luxon_1.DateTime.DATETIME_HUGE_WITH_SECONDS,
|
|
260
|
+
};
|
|
261
|
+
/**
|
|
262
|
+
* Helper function definitions that can be registered with Handlebars.
|
|
263
|
+
* Each function is a pure, deterministic helper that does not execute arbitrary code.
|
|
264
|
+
*/
|
|
265
|
+
exports.handlebarsHelperDefinitions = {
|
|
266
|
+
/**
|
|
267
|
+
* Format a date value using a custom format string.
|
|
268
|
+
* Supports ISO date strings and JavaScript Date instances.
|
|
269
|
+
* Replaces lodash template usage like: ${ DateTime.fromISO(data.date).toFormat('dd/MM/yyyy hh:mm a') }
|
|
270
|
+
*
|
|
271
|
+
* @example {{formatDate lastSaveDate "dd/MM/yyyy hh:mm a"}}
|
|
272
|
+
*/
|
|
273
|
+
formatDate: function (dateValue, formatOrOptions) {
|
|
274
|
+
if (!dateValue) {
|
|
275
|
+
return '';
|
|
276
|
+
}
|
|
277
|
+
try {
|
|
278
|
+
const dt = dateValue instanceof Date ? luxon_1.DateTime.fromJSDate(dateValue) : luxon_1.DateTime.fromISO(dateValue);
|
|
279
|
+
if (!dt.isValid) {
|
|
280
|
+
return String(dateValue);
|
|
281
|
+
}
|
|
282
|
+
const format = resolveDateFormatArg(formatOrOptions);
|
|
283
|
+
return dt.toFormat(format || 'dd/MM/yyyy hh:mm a');
|
|
284
|
+
}
|
|
285
|
+
catch {
|
|
286
|
+
return String(dateValue);
|
|
287
|
+
}
|
|
288
|
+
},
|
|
289
|
+
/**
|
|
290
|
+
* Format a date value using locale-aware presets.
|
|
291
|
+
* Supports ISO date strings and JavaScript Date instances.
|
|
292
|
+
*
|
|
293
|
+
* @example {{formatDateLocale lastSaveDate "DATETIME_MED"}}
|
|
294
|
+
*/
|
|
295
|
+
formatDateLocale: function (dateValue, presetNameOrOptions, localeOrOptions) {
|
|
296
|
+
if (!dateValue) {
|
|
297
|
+
return '';
|
|
298
|
+
}
|
|
299
|
+
try {
|
|
300
|
+
let dt = dateValue instanceof Date ? luxon_1.DateTime.fromJSDate(dateValue) : luxon_1.DateTime.fromISO(dateValue);
|
|
301
|
+
if (!dt.isValid) {
|
|
302
|
+
return String(dateValue);
|
|
303
|
+
}
|
|
304
|
+
const presetName = typeof presetNameOrOptions === 'string' ? presetNameOrOptions : undefined;
|
|
305
|
+
const locale = typeof localeOrOptions === 'string' ? localeOrOptions : undefined;
|
|
306
|
+
// Set locale - use provided locale or browser's language
|
|
307
|
+
if (locale) {
|
|
308
|
+
dt = dt.setLocale(locale);
|
|
309
|
+
}
|
|
310
|
+
else if (typeof navigator !== 'undefined' && navigator.language) {
|
|
311
|
+
dt = dt.setLocale(navigator.language);
|
|
312
|
+
}
|
|
313
|
+
const preset = dateLocalePresetMap[presetName || 'DATETIME_MED'];
|
|
314
|
+
return dt.toLocaleString(preset);
|
|
315
|
+
}
|
|
316
|
+
catch {
|
|
317
|
+
return String(dateValue);
|
|
318
|
+
}
|
|
319
|
+
},
|
|
320
|
+
/**
|
|
321
|
+
* Parse a date string (pass-through for chaining).
|
|
322
|
+
*
|
|
323
|
+
* @example {{parseDateString dateString}}
|
|
324
|
+
*/
|
|
325
|
+
parseDateString: function (dateString) {
|
|
326
|
+
return dateString || '';
|
|
327
|
+
},
|
|
328
|
+
/**
|
|
329
|
+
* Get a nested property from an object using dot notation.
|
|
330
|
+
* Replaces lodash template usage like: ${ _.get(data, 'metadata.contributor_ci', '') }
|
|
331
|
+
*
|
|
332
|
+
* @example {{get this "metadata.contributor_ci.text_full_name"}}
|
|
333
|
+
*/
|
|
334
|
+
get: function (obj, path, defaultValue) {
|
|
335
|
+
return (0, lodash_1.get)(obj, path, defaultValue ?? '');
|
|
336
|
+
},
|
|
337
|
+
/**
|
|
338
|
+
* Check if a value is empty (null, undefined, empty string, empty array, empty object).
|
|
339
|
+
*
|
|
340
|
+
* @example {{#if (isEmpty value)}}empty{{/if}}
|
|
341
|
+
*/
|
|
342
|
+
isEmpty: function (value) {
|
|
343
|
+
return (0, lodash_1.isEmpty)(value);
|
|
344
|
+
},
|
|
345
|
+
/**
|
|
346
|
+
* Check if a value is undefined.
|
|
347
|
+
*
|
|
348
|
+
* @example {{#if (isUndefined value)}}undefined{{/if}}
|
|
349
|
+
*/
|
|
350
|
+
isUndefined: function (value) {
|
|
351
|
+
return (0, lodash_1.isUndefined)(value);
|
|
352
|
+
},
|
|
353
|
+
/**
|
|
354
|
+
* Check if a value is null.
|
|
355
|
+
*
|
|
356
|
+
* @example {{#if (isNull value)}}null{{/if}}
|
|
357
|
+
*/
|
|
358
|
+
isNull: function (value) {
|
|
359
|
+
return (0, lodash_1.isNull)(value);
|
|
360
|
+
},
|
|
361
|
+
/**
|
|
362
|
+
* Check if a value is defined (not undefined and not null).
|
|
363
|
+
*
|
|
364
|
+
* @example {{#if (isDefined value)}}defined{{/if}}
|
|
365
|
+
*/
|
|
366
|
+
isDefined: function (value) {
|
|
367
|
+
return !(0, lodash_1.isUndefined)(value) && !(0, lodash_1.isNull)(value);
|
|
368
|
+
},
|
|
369
|
+
/**
|
|
370
|
+
* Check if a value is an array.
|
|
371
|
+
*
|
|
372
|
+
* @example {{#if (isArray value)}}is array{{/if}}
|
|
373
|
+
*/
|
|
374
|
+
isArray: function (value) {
|
|
375
|
+
return (0, lodash_1.isArray)(value);
|
|
376
|
+
},
|
|
377
|
+
/**
|
|
378
|
+
* Check if a value is a plain object.
|
|
379
|
+
*
|
|
380
|
+
* @example {{#if (isObject value)}}is object{{/if}}
|
|
381
|
+
*/
|
|
382
|
+
isObject: function (value) {
|
|
383
|
+
return (0, lodash_1.isPlainObject)(value);
|
|
384
|
+
},
|
|
385
|
+
/**
|
|
386
|
+
* Strict equality comparison.
|
|
387
|
+
*
|
|
388
|
+
* @example {{#if (eq status "active")}}active{{/if}}
|
|
389
|
+
*/
|
|
390
|
+
eq: function (a, b) {
|
|
391
|
+
return a === b;
|
|
392
|
+
},
|
|
393
|
+
/**
|
|
394
|
+
* Not equal comparison.
|
|
395
|
+
*
|
|
396
|
+
* @example {{#if (ne status "inactive")}}not inactive{{/if}}
|
|
397
|
+
*/
|
|
398
|
+
ne: function (a, b) {
|
|
399
|
+
return a !== b;
|
|
400
|
+
},
|
|
401
|
+
/**
|
|
402
|
+
* Logical AND - returns true if all arguments are truthy.
|
|
403
|
+
* Note: The last argument is the Handlebars options hash, which is removed.
|
|
404
|
+
*
|
|
405
|
+
* @example {{#if (and condition1 condition2)}}both true{{/if}}
|
|
406
|
+
*/
|
|
407
|
+
and: function (...args) {
|
|
408
|
+
// Remove the Handlebars options hash (last argument)
|
|
409
|
+
args.pop();
|
|
410
|
+
return args.every(Boolean);
|
|
411
|
+
},
|
|
412
|
+
/**
|
|
413
|
+
* Logical OR - returns true if any argument is truthy.
|
|
414
|
+
* Note: The last argument is the Handlebars options hash, which is removed.
|
|
415
|
+
*
|
|
416
|
+
* @example {{#if (or condition1 condition2)}}at least one true{{/if}}
|
|
417
|
+
*/
|
|
418
|
+
or: function (...args) {
|
|
419
|
+
// Remove the Handlebars options hash (last argument)
|
|
420
|
+
args.pop();
|
|
421
|
+
return args.some(Boolean);
|
|
422
|
+
},
|
|
423
|
+
/**
|
|
424
|
+
* Logical NOT - returns true if value is falsy.
|
|
425
|
+
*
|
|
426
|
+
* @example {{#if (not condition)}}condition is false{{/if}}
|
|
427
|
+
*/
|
|
428
|
+
not: function (value) {
|
|
429
|
+
return !value;
|
|
430
|
+
},
|
|
431
|
+
/**
|
|
432
|
+
* Greater than comparison.
|
|
433
|
+
*
|
|
434
|
+
* @example {{#if (gt count 0)}}has items{{/if}}
|
|
435
|
+
*/
|
|
436
|
+
gt: function (a, b) {
|
|
437
|
+
return Number(a) > Number(b);
|
|
438
|
+
},
|
|
439
|
+
/**
|
|
440
|
+
* Greater than or equal comparison.
|
|
441
|
+
*
|
|
442
|
+
* @example {{#if (gte count 1)}}at least one{{/if}}
|
|
443
|
+
*/
|
|
444
|
+
gte: function (a, b) {
|
|
445
|
+
return Number(a) >= Number(b);
|
|
446
|
+
},
|
|
447
|
+
/**
|
|
448
|
+
* Less than comparison.
|
|
449
|
+
*
|
|
450
|
+
* @example {{#if (lt count 10)}}less than ten{{/if}}
|
|
451
|
+
*/
|
|
452
|
+
lt: function (a, b) {
|
|
453
|
+
return Number(a) < Number(b);
|
|
454
|
+
},
|
|
455
|
+
/**
|
|
456
|
+
* Less than or equal comparison.
|
|
457
|
+
*
|
|
458
|
+
* @example {{#if (lte count 10)}}ten or less{{/if}}
|
|
459
|
+
*/
|
|
460
|
+
lte: function (a, b) {
|
|
461
|
+
return Number(a) <= Number(b);
|
|
462
|
+
},
|
|
463
|
+
/**
|
|
464
|
+
* Trim leading/trailing whitespace from a string value.
|
|
465
|
+
*
|
|
466
|
+
* @example {{trim title}}
|
|
467
|
+
*/
|
|
468
|
+
trim: function (value) {
|
|
469
|
+
return String(value ?? '').trim();
|
|
470
|
+
},
|
|
471
|
+
/**
|
|
472
|
+
* Convert a value to lowercase text.
|
|
473
|
+
*
|
|
474
|
+
* @example {{toLower value}}
|
|
475
|
+
*/
|
|
476
|
+
toLower: function (value) {
|
|
477
|
+
return String(value ?? '').toLowerCase();
|
|
478
|
+
},
|
|
479
|
+
/**
|
|
480
|
+
* Convert a value to uppercase text.
|
|
481
|
+
*
|
|
482
|
+
* @example {{toUpper value}}
|
|
483
|
+
*/
|
|
484
|
+
toUpper: function (value) {
|
|
485
|
+
return String(value ?? '').toUpperCase();
|
|
486
|
+
},
|
|
487
|
+
/**
|
|
488
|
+
* Translation helper - looks up translation from context.translationService.
|
|
489
|
+
* The translation service must be provided in the template context.
|
|
490
|
+
*
|
|
491
|
+
* @example {{t "label.title"}}
|
|
492
|
+
*/
|
|
493
|
+
t: function (key) {
|
|
494
|
+
const translationService = this?.translationService;
|
|
495
|
+
if (translationService && typeof translationService.t === 'function') {
|
|
496
|
+
return translationService.t(key);
|
|
497
|
+
}
|
|
498
|
+
return key;
|
|
499
|
+
},
|
|
500
|
+
/**
|
|
501
|
+
* Join array elements with a separator.
|
|
502
|
+
*
|
|
503
|
+
* @example {{join items ", "}}
|
|
504
|
+
*/
|
|
505
|
+
join: function (arr, separator) {
|
|
506
|
+
if (!(0, lodash_1.isArray)(arr)) {
|
|
507
|
+
return '';
|
|
508
|
+
}
|
|
509
|
+
return arr.join(separator ?? ', ');
|
|
510
|
+
},
|
|
511
|
+
/**
|
|
512
|
+
* Extract a property from each item in an array using dot notation.
|
|
513
|
+
* Replaces lodash usage like: _.map(creators, c => c.email).
|
|
514
|
+
* Returns an empty array for non-array input. Combine with {{join}} to
|
|
515
|
+
* build a delimited string, e.g. {{join (pluck creators "email") ","}}.
|
|
516
|
+
*
|
|
517
|
+
* @example {{join (pluck record.metadata.creators "email") ","}}
|
|
518
|
+
*/
|
|
519
|
+
pluck: function (arr, path) {
|
|
520
|
+
if (!(0, lodash_1.isArray)(arr)) {
|
|
521
|
+
return [];
|
|
522
|
+
}
|
|
523
|
+
return arr.map((item) => (0, lodash_1.get)(item, path, ''));
|
|
524
|
+
},
|
|
525
|
+
/**
|
|
526
|
+
* Return part of a string using slice semantics.
|
|
527
|
+
*
|
|
528
|
+
* @example {{substring notation 0 6}}
|
|
529
|
+
*/
|
|
530
|
+
substring: function (value, start, end) {
|
|
531
|
+
const text = String(value ?? '');
|
|
532
|
+
const from = Number(start);
|
|
533
|
+
const to = end === undefined || end === null ? undefined : Number(end);
|
|
534
|
+
// Use slice semantics so negative offsets work (e.g. -1 for last char, -6 for trailing code).
|
|
535
|
+
// String.prototype.substring() clamps negatives to 0 and cannot express this.
|
|
536
|
+
return text.slice(Number.isNaN(from) ? 0 : from, Number.isNaN(to) ? undefined : to);
|
|
537
|
+
},
|
|
538
|
+
/**
|
|
539
|
+
* Split a string into parts, or return one part if index is provided.
|
|
540
|
+
* Supports negative index values, where -1 is the last part.
|
|
541
|
+
*
|
|
542
|
+
* @example {{split notation "/" -1}}
|
|
543
|
+
*/
|
|
544
|
+
split: function (value, separator, index) {
|
|
545
|
+
const text = String(value ?? '');
|
|
546
|
+
const parts = text.split(String(separator ?? ''));
|
|
547
|
+
if (index === undefined || index === null) {
|
|
548
|
+
return parts;
|
|
549
|
+
}
|
|
550
|
+
const parsedIndex = Number(index);
|
|
551
|
+
if (Number.isNaN(parsedIndex)) {
|
|
552
|
+
return '';
|
|
553
|
+
}
|
|
554
|
+
const normalizedIndex = parsedIndex < 0 ? parts.length + parsedIndex : parsedIndex;
|
|
555
|
+
if (normalizedIndex < 0 || normalizedIndex >= parts.length) {
|
|
556
|
+
return '';
|
|
557
|
+
}
|
|
558
|
+
return parts[normalizedIndex];
|
|
559
|
+
},
|
|
560
|
+
/**
|
|
561
|
+
* Encode user-controlled URL path values while preserving path separators.
|
|
562
|
+
* Trailing slashes are trimmed so prefixed paths can be safely concatenated.
|
|
563
|
+
*
|
|
564
|
+
* @example {{urlEncode oid}}
|
|
565
|
+
*/
|
|
566
|
+
urlEncode: function (value) {
|
|
567
|
+
const rawText = String(value ?? '');
|
|
568
|
+
if (!rawText) {
|
|
569
|
+
return '';
|
|
570
|
+
}
|
|
571
|
+
let endIndex = rawText.length;
|
|
572
|
+
while (endIndex > 0 && rawText[endIndex - 1] === '/') {
|
|
573
|
+
endIndex--;
|
|
574
|
+
}
|
|
575
|
+
const text = rawText.slice(0, endIndex);
|
|
576
|
+
if (!text) {
|
|
577
|
+
return '';
|
|
578
|
+
}
|
|
579
|
+
return text
|
|
580
|
+
.split('/')
|
|
581
|
+
.map((segment) => encodeURIComponent(segment))
|
|
582
|
+
.join('/');
|
|
583
|
+
},
|
|
584
|
+
/**
|
|
585
|
+
* Concatenate strings.
|
|
586
|
+
* Note: The last argument is the Handlebars options hash, which is removed.
|
|
587
|
+
*
|
|
588
|
+
* @example {{concat prefix value suffix}}
|
|
589
|
+
*/
|
|
590
|
+
concat: function (...args) {
|
|
591
|
+
// Remove the Handlebars options hash (last argument)
|
|
592
|
+
args.pop();
|
|
593
|
+
return args.map(String).join('');
|
|
594
|
+
},
|
|
595
|
+
/**
|
|
596
|
+
* Default value if the primary value is empty/falsy.
|
|
597
|
+
*
|
|
598
|
+
* @example {{default title "Untitled"}}
|
|
599
|
+
*/
|
|
600
|
+
default: function (value, defaultValue) {
|
|
601
|
+
return value || defaultValue;
|
|
602
|
+
},
|
|
603
|
+
/**
|
|
604
|
+
* Convert markdown to HTML when output format is markdown, otherwise pass HTML through.
|
|
605
|
+
* Note: This helper does not sanitize HTML output, we are currently only using it on the client side with Angular's DomSanitizer to ensure safe usage.
|
|
606
|
+
* Do not use this helper with untrusted content in a server-side context without proper sanitization (see DOMSanitizerService as a way to sanitize the HTML on the server side).
|
|
607
|
+
*
|
|
608
|
+
* @example {{{markdownToHtml content outputFormat}}}
|
|
609
|
+
*/
|
|
610
|
+
markdownToHtml: function (value, outputFormat) {
|
|
611
|
+
const input = String(value ?? '');
|
|
612
|
+
if (!input) {
|
|
613
|
+
return '';
|
|
614
|
+
}
|
|
615
|
+
if (outputFormat === 'markdown') {
|
|
616
|
+
const parser = resolveMarkedParser();
|
|
617
|
+
if (parser) {
|
|
618
|
+
return parser(input);
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
return input;
|
|
622
|
+
},
|
|
623
|
+
/**
|
|
624
|
+
* Render plain text as escaped HTML while preserving line breaks.
|
|
625
|
+
*
|
|
626
|
+
* @example {{{plaintextToHtml content}}}
|
|
627
|
+
*/
|
|
628
|
+
plaintextToHtml: function (value) {
|
|
629
|
+
return (0, html_helpers_1.escapeHtmlText)(value).replace(/\r\n|\r|\n/g, '<br>');
|
|
630
|
+
},
|
|
631
|
+
/**
|
|
632
|
+
* JSON stringify a value (useful for debugging).
|
|
633
|
+
*
|
|
634
|
+
* @example {{json data}}
|
|
635
|
+
*/
|
|
636
|
+
json: function (value) {
|
|
637
|
+
try {
|
|
638
|
+
return JSON.stringify(value);
|
|
639
|
+
}
|
|
640
|
+
catch {
|
|
641
|
+
return String(value);
|
|
642
|
+
}
|
|
643
|
+
},
|
|
644
|
+
/**
|
|
645
|
+
* Render metadata values into nested HTML suitable for generated view-only display.
|
|
646
|
+
*
|
|
647
|
+
* @example {{{renderMetadataValue metadata.someField}}}
|
|
648
|
+
*/
|
|
649
|
+
renderMetadataValue: function (value) {
|
|
650
|
+
return renderMetadataValue(value);
|
|
651
|
+
},
|
|
652
|
+
/**
|
|
653
|
+
* Build a view-mode download URL for a file upload attachment value.
|
|
654
|
+
*
|
|
655
|
+
* @example {{attachmentDownloadUrl this oid branding portal}}
|
|
656
|
+
*/
|
|
657
|
+
attachmentDownloadUrl: function (attachment, oid, branding, portal) {
|
|
658
|
+
return buildAttachmentDownloadUrl(attachment, oid, branding, portal);
|
|
659
|
+
},
|
|
660
|
+
};
|
|
661
|
+
/**
|
|
662
|
+
* A class to encapsulate the Handlebars registerHelper calls
|
|
663
|
+
* and ensure they happen exactly once.
|
|
664
|
+
*/
|
|
665
|
+
class HandlebarsRegisterHelper {
|
|
666
|
+
static #isSetupDone = false;
|
|
667
|
+
constructor() {
|
|
668
|
+
if (HandlebarsRegisterHelper.#isSetupDone) {
|
|
669
|
+
return;
|
|
670
|
+
}
|
|
671
|
+
for (const [name, fn] of Object.entries(exports.handlebarsHelperDefinitions)) {
|
|
672
|
+
handlebars_1.default.registerHelper(name, fn);
|
|
673
|
+
}
|
|
674
|
+
HandlebarsRegisterHelper.#isSetupDone = true;
|
|
675
|
+
}
|
|
676
|
+
get instance() {
|
|
677
|
+
return handlebars_1.default;
|
|
678
|
+
}
|
|
679
|
+
}
|
|
680
|
+
/**
|
|
681
|
+
* Register Handlebars helpers for use in dashboard and report templates.
|
|
682
|
+
* Uses shared helpers from sails-ng-common for consistency between server and client.
|
|
683
|
+
*/
|
|
684
|
+
function handlebarsInstance() {
|
|
685
|
+
return new HandlebarsRegisterHelper().instance;
|
|
686
|
+
}
|
|
687
|
+
/**
|
|
688
|
+
* Pre-compile a handlebars template.
|
|
689
|
+
* @param input The template to compile.
|
|
690
|
+
* @param options The compile options.
|
|
691
|
+
*/
|
|
692
|
+
function handlebarsPrecompile(input, options) {
|
|
693
|
+
const instance = handlebarsInstance();
|
|
694
|
+
const value = (0, naming_helpers_1.normaliseVisual)(input);
|
|
695
|
+
return instance.precompile(value, options);
|
|
696
|
+
}
|
|
697
|
+
/**
|
|
698
|
+
* Get a compiled handlebars template.
|
|
699
|
+
* @param input The template to compile.
|
|
700
|
+
* @param options The compile options.
|
|
701
|
+
*/
|
|
702
|
+
function handlebarsCompile(input, options) {
|
|
703
|
+
const instance = handlebarsInstance();
|
|
704
|
+
const value = (0, naming_helpers_1.normaliseVisual)(input);
|
|
705
|
+
return instance.compile(value, options);
|
|
706
|
+
}
|
|
707
|
+
/**
|
|
708
|
+
* Render a pre-compiled handlebars template.
|
|
709
|
+
* @param precompilation The pre-compiled template.
|
|
710
|
+
*/
|
|
711
|
+
function handlebarsTemplate(precompilation) {
|
|
712
|
+
const instance = handlebarsInstance();
|
|
713
|
+
return instance.template(precompilation);
|
|
714
|
+
}
|
|
715
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaGFuZGxlYmFycy1oZWxwZXJzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2hhbmRsZWJhcnMtaGVscGVycy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUEsMEZBQTBGO0FBQzFGLEVBQUU7QUFDRiw2QkFBNkI7QUFDN0IsMEJBQTBCO0FBQzFCLEVBQUU7QUFDRix1RUFBdUU7QUFDdkUsdUVBQXVFO0FBQ3ZFLG9FQUFvRTtBQUNwRSxzQ0FBc0M7QUFDdEMsRUFBRTtBQUNGLGtFQUFrRTtBQUNsRSxpRUFBaUU7QUFDakUsZ0VBQWdFO0FBQ2hFLCtDQUErQztBQUMvQyxFQUFFO0FBQ0YsMEVBQTBFO0FBQzFFLDBFQUEwRTtBQUMxRSw4REFBOEQ7Ozs7OztBQWl2QjlELGdEQUVDO0FBT0Qsb0RBSUM7QUFPRCw4Q0FJQztBQU1ELGdEQUdDO0FBaHhCRCxpQ0FBaUM7QUFDakMsNERBQW9DO0FBQ3BDLG1DQU9nQjtBQUNoQiwrREFBK0Q7QUFDL0QsaURBQWdEO0FBQ2hELGtFQUE4RDtBQUU5RCxTQUFTLHNCQUFzQixDQUFDLEtBQWM7SUFDNUMsT0FBTyxDQUNMLE9BQU8sS0FBSyxLQUFLLFFBQVE7UUFDekIsS0FBSyxLQUFLLElBQUk7UUFDZCxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQyxLQUFLLEVBQUUsTUFBTSxDQUFDO1lBQ2xELE1BQU0sQ0FBQyxTQUFTLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQyxLQUFLLEVBQUUsTUFBTSxDQUFDO1lBQ25ELE1BQU0sQ0FBQyxTQUFTLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQyxLQUFLLEVBQUUsSUFBSSxDQUFDO1lBQ2pELE1BQU0sQ0FBQyxTQUFTLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQyxLQUFLLEVBQUUsU0FBUyxDQUFDLENBQUMsQ0FDMUQsQ0FBQztBQUNKLENBQUM7QUFFRCw2SUFBNkk7QUFDN0ksU0FBUyxvQkFBb0IsQ0FBQyxlQUFr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QUFVLEVBQUUsQ0FBVTtRQUNsQyxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDakIsQ0FBQztJQUVEOzs7O09BSUc7SUFDSCxFQUFFLEVBQUUsVUFBVSxDQUFVLEVBQUUsQ0FBVTtRQUNsQyxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDakIsQ0FBQztJQUVEOzs7OztPQUtHO0lBQ0gsR0FBRyxFQUFFLFVBQVUsR0FBRyxJQUFlO1FBQy9CLHFEQUFxRDtRQUNyRCxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUM7UUFDWCxPQUFPLElBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDN0IsQ0FBQztJQUVEOzs7OztPQUtHO0lBQ0gsRUFBRSxFQUFFLFVBQVUsR0FBRyxJQUFlO1FBQzlCLHFEQUFxRDtRQUNyRCxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUM7UUFDWCxPQUFPLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDNUIsQ0FBQztJQUVEOzs7O09BSUc7SUFDSCxHQUFHLEVBQUUsVUFBVSxLQUFjO1FBQzNCLE9BQU8sQ0FBQyxLQUFLLENBQUM7SUFDaEIsQ0FBQztJQUVEOzs7O09BSUc7SUFDSCxFQUFFLEVBQUUsVUFBVSxDQUFVLEVBQUUsQ0FBVTtRQUNsQyxPQUFPLE1BQU0sQ0FBQyxDQUFDLENBQUMsR0FBRyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDL0IsQ0FBQztJQUVEOzs7O09BSUc7SUFDSCxHQUFHLEVBQUUsVUFBVSxDQUFVLEVBQUUsQ0FBVTtRQUNuQyxPQUFPLE1BQU0sQ0FBQyxDQUFDLENBQUMsSUFBSSxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDaEMsQ0FBQztJQUVEOzs7O09BSUc7SUFDSCxFQUFFLEVBQUUsVUFBVSxDQUFVLEVBQUUsQ0FBVTtRQUNsQyxPQUFPLE1BQU0sQ0FBQyxDQUFDLENBQUMsR0FBRyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDL0IsQ0FBQztJQUVEOzs7O09BSUc7SUFDSCxHQUFHLEVBQUUsVUFB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
|