@syncfusion/ej2-form-renderer 34.2.2
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 +60 -0
- package/common.d.ts +4 -0
- package/common.js +4 -0
- package/dist/ej2-form-renderer.umd.min.js +11 -0
- package/dist/ej2-form-renderer.umd.min.js.map +1 -0
- package/dist/es6/ej2-form-renderer.es2015.js +6787 -0
- package/dist/es6/ej2-form-renderer.es2015.js.map +1 -0
- package/dist/es6/ej2-form-renderer.es5.js +7055 -0
- package/dist/es6/ej2-form-renderer.es5.js.map +1 -0
- package/dist/global/ej2-form-renderer.min.js +11 -0
- package/dist/global/ej2-form-renderer.min.js.map +1 -0
- package/dist/global/index.d.ts +14 -0
- package/form-renderer.d.ts +4 -0
- package/form-renderer.js +4 -0
- package/index.d.ts +4 -0
- package/index.js +4 -0
- package/license +10 -0
- package/package.json +41 -0
- package/src/common/checkbox-group.d.ts +55 -0
- package/src/common/checkbox-group.js +241 -0
- package/src/common/conditional-rule-engine.d.ts +241 -0
- package/src/common/conditional-rule-engine.js +505 -0
- package/src/common/custom-validation-engine.d.ts +57 -0
- package/src/common/custom-validation-engine.js +152 -0
- package/src/common/datagrid-component.d.ts +156 -0
- package/src/common/datagrid-component.js +410 -0
- package/src/common/expressions/dependency-tracker.d.ts +29 -0
- package/src/common/expressions/dependency-tracker.js +137 -0
- package/src/common/expressions/expression-engine.d.ts +94 -0
- package/src/common/expressions/expression-engine.js +514 -0
- package/src/common/expressions/expression-parser.d.ts +40 -0
- package/src/common/expressions/expression-parser.js +270 -0
- package/src/common/expressions/grid-expressions.d.ts +24 -0
- package/src/common/expressions/grid-expressions.js +92 -0
- package/src/common/expressions/index.d.ts +4 -0
- package/src/common/expressions/index.js +4 -0
- package/src/common/index.d.ts +10 -0
- package/src/common/index.js +10 -0
- package/src/common/json-converter.d.ts +945 -0
- package/src/common/json-converter.js +1110 -0
- package/src/common/minmax-rule-engine.d.ts +105 -0
- package/src/common/minmax-rule-engine.js +380 -0
- package/src/common/option-fetcher.d.ts +30 -0
- package/src/common/option-fetcher.js +139 -0
- package/src/common/parser.d.ts +98 -0
- package/src/common/parser.js +788 -0
- package/src/common/static-html-renderer.d.ts +45 -0
- package/src/common/static-html-renderer.js +77 -0
- package/src/common/utils.d.ts +116 -0
- package/src/common/utils.js +484 -0
- package/src/form-renderer/form-renderer-model.d.ts +65 -0
- package/src/form-renderer/form-renderer.d.ts +425 -0
- package/src/form-renderer/form-renderer.js +2277 -0
- package/src/form-renderer/index.d.ts +6 -0
- package/src/form-renderer/index.js +5 -0
- package/src/form-renderer/render-form-field.d.ts +31 -0
- package/src/form-renderer/render-form-field.js +816 -0
- package/src/form-renderer/types/form-schema.d.ts +452 -0
- package/src/form-renderer/types/form-schema.js +32 -0
- package/src/global.js +1 -0
- package/src/index.d.ts +4 -0
- package/src/index.js +4 -0
- package/styles/bds-lite.css +599 -0
- package/styles/bds-lite.scss +2 -0
- package/styles/bds.css +599 -0
- package/styles/bds.scss +2 -0
- package/styles/bootstrap-dark-lite.css +608 -0
- package/styles/bootstrap-dark-lite.scss +2 -0
- package/styles/bootstrap-dark.css +608 -0
- package/styles/bootstrap-dark.scss +2 -0
- package/styles/bootstrap-lite.css +595 -0
- package/styles/bootstrap-lite.scss +2 -0
- package/styles/bootstrap.css +595 -0
- package/styles/bootstrap.scss +2 -0
- package/styles/bootstrap4-lite.css +595 -0
- package/styles/bootstrap4-lite.scss +2 -0
- package/styles/bootstrap4.css +595 -0
- package/styles/bootstrap4.scss +2 -0
- package/styles/bootstrap5-dark-lite.css +595 -0
- package/styles/bootstrap5-dark-lite.scss +2 -0
- package/styles/bootstrap5-dark.css +595 -0
- package/styles/bootstrap5-dark.scss +2 -0
- package/styles/bootstrap5-lite.css +595 -0
- package/styles/bootstrap5-lite.scss +2 -0
- package/styles/bootstrap5.3-lite.css +679 -0
- package/styles/bootstrap5.3-lite.scss +2 -0
- package/styles/bootstrap5.3.css +679 -0
- package/styles/bootstrap5.3.scss +2 -0
- package/styles/bootstrap5.css +595 -0
- package/styles/bootstrap5.scss +2 -0
- package/styles/fabric-dark-lite.css +608 -0
- package/styles/fabric-dark-lite.scss +2 -0
- package/styles/fabric-dark.css +608 -0
- package/styles/fabric-dark.scss +2 -0
- package/styles/fabric-lite.css +595 -0
- package/styles/fabric-lite.scss +2 -0
- package/styles/fabric.css +595 -0
- package/styles/fabric.scss +2 -0
- package/styles/fluent-dark-lite.css +595 -0
- package/styles/fluent-dark-lite.scss +2 -0
- package/styles/fluent-dark.css +595 -0
- package/styles/fluent-dark.scss +2 -0
- package/styles/fluent-lite.css +595 -0
- package/styles/fluent-lite.scss +2 -0
- package/styles/fluent.css +595 -0
- package/styles/fluent.scss +2 -0
- package/styles/fluent2-lite.css +681 -0
- package/styles/fluent2-lite.scss +2 -0
- package/styles/fluent2.css +681 -0
- package/styles/fluent2.scss +2 -0
- package/styles/form-renderer/_all.scss +2 -0
- package/styles/form-renderer/_bds-definition.scss +8 -0
- package/styles/form-renderer/_bootstrap-dark-definition.scss +8 -0
- package/styles/form-renderer/_bootstrap-definition.scss +8 -0
- package/styles/form-renderer/_bootstrap4-definition.scss +8 -0
- package/styles/form-renderer/_bootstrap5-dark-definition.scss +8 -0
- package/styles/form-renderer/_bootstrap5-definition.scss +8 -0
- package/styles/form-renderer/_bootstrap5.3-definition.scss +8 -0
- package/styles/form-renderer/_fabric-dark-definition.scss +8 -0
- package/styles/form-renderer/_fabric-definition.scss +8 -0
- package/styles/form-renderer/_fluent-dark-definition.scss +8 -0
- package/styles/form-renderer/_fluent-definition.scss +8 -0
- package/styles/form-renderer/_fluent2-definition.scss +8 -0
- package/styles/form-renderer/_highcontrast-definition.scss +8 -0
- package/styles/form-renderer/_highcontrast-light-definition.scss +8 -0
- package/styles/form-renderer/_layout.scss +480 -0
- package/styles/form-renderer/_material-dark-definition.scss +8 -0
- package/styles/form-renderer/_material-definition.scss +8 -0
- package/styles/form-renderer/_material3-dark-definition.scss +8 -0
- package/styles/form-renderer/_material3-definition.scss +8 -0
- package/styles/form-renderer/_mixin.scss +26 -0
- package/styles/form-renderer/_tailwind-dark-definition.scss +8 -0
- package/styles/form-renderer/_tailwind-definition.scss +8 -0
- package/styles/form-renderer/_tailwind3-definition.scss +8 -0
- package/styles/form-renderer/_theme.scss +69 -0
- package/styles/form-renderer/_variables.scss +2 -0
- package/styles/form-renderer/bds.css +599 -0
- package/styles/form-renderer/bds.scss +2 -0
- package/styles/form-renderer/bootstrap-dark.css +608 -0
- package/styles/form-renderer/bootstrap-dark.scss +2 -0
- package/styles/form-renderer/bootstrap.css +595 -0
- package/styles/form-renderer/bootstrap.scss +2 -0
- package/styles/form-renderer/bootstrap4.css +595 -0
- package/styles/form-renderer/bootstrap4.scss +2 -0
- package/styles/form-renderer/bootstrap5-dark.css +595 -0
- package/styles/form-renderer/bootstrap5-dark.scss +2 -0
- package/styles/form-renderer/bootstrap5.3.css +679 -0
- package/styles/form-renderer/bootstrap5.3.scss +2 -0
- package/styles/form-renderer/bootstrap5.css +595 -0
- package/styles/form-renderer/bootstrap5.scss +2 -0
- package/styles/form-renderer/fabric-dark.css +608 -0
- package/styles/form-renderer/fabric-dark.scss +2 -0
- package/styles/form-renderer/fabric.css +595 -0
- package/styles/form-renderer/fabric.scss +2 -0
- package/styles/form-renderer/fluent-dark.css +595 -0
- package/styles/form-renderer/fluent-dark.scss +2 -0
- package/styles/form-renderer/fluent.css +595 -0
- package/styles/form-renderer/fluent.scss +2 -0
- package/styles/form-renderer/fluent2.css +681 -0
- package/styles/form-renderer/fluent2.scss +2 -0
- package/styles/form-renderer/highcontrast-light.css +595 -0
- package/styles/form-renderer/highcontrast-light.scss +2 -0
- package/styles/form-renderer/highcontrast.css +608 -0
- package/styles/form-renderer/highcontrast.scss +2 -0
- package/styles/form-renderer/material-dark.css +608 -0
- package/styles/form-renderer/material-dark.scss +2 -0
- package/styles/form-renderer/material.css +595 -0
- package/styles/form-renderer/material.scss +2 -0
- package/styles/form-renderer/material3-dark.css +677 -0
- package/styles/form-renderer/material3-dark.scss +2 -0
- package/styles/form-renderer/material3.css +679 -0
- package/styles/form-renderer/material3.scss +2 -0
- package/styles/form-renderer/tailwind-dark.css +595 -0
- package/styles/form-renderer/tailwind-dark.scss +2 -0
- package/styles/form-renderer/tailwind.css +595 -0
- package/styles/form-renderer/tailwind.scss +2 -0
- package/styles/form-renderer/tailwind3.css +669 -0
- package/styles/form-renderer/tailwind3.scss +2 -0
- package/styles/highcontrast-light-lite.css +595 -0
- package/styles/highcontrast-light-lite.scss +2 -0
- package/styles/highcontrast-light.css +595 -0
- package/styles/highcontrast-light.scss +2 -0
- package/styles/highcontrast-lite.css +608 -0
- package/styles/highcontrast-lite.scss +2 -0
- package/styles/highcontrast.css +608 -0
- package/styles/highcontrast.scss +2 -0
- package/styles/material-dark-lite.css +608 -0
- package/styles/material-dark-lite.scss +2 -0
- package/styles/material-dark.css +608 -0
- package/styles/material-dark.scss +2 -0
- package/styles/material-lite.css +595 -0
- package/styles/material-lite.scss +2 -0
- package/styles/material.css +595 -0
- package/styles/material.scss +2 -0
- package/styles/material3-dark-lite.css +677 -0
- package/styles/material3-dark-lite.scss +2 -0
- package/styles/material3-dark.css +677 -0
- package/styles/material3-dark.scss +2 -0
- package/styles/material3-lite.css +679 -0
- package/styles/material3-lite.scss +2 -0
- package/styles/material3.css +679 -0
- package/styles/material3.scss +2 -0
- package/styles/tailwind-dark-lite.css +595 -0
- package/styles/tailwind-dark-lite.scss +2 -0
- package/styles/tailwind-dark.css +595 -0
- package/styles/tailwind-dark.scss +2 -0
- package/styles/tailwind-lite.css +595 -0
- package/styles/tailwind-lite.scss +2 -0
- package/styles/tailwind.css +595 -0
- package/styles/tailwind.scss +2 -0
- package/styles/tailwind3-lite.css +669 -0
- package/styles/tailwind3-lite.scss +2 -0
- package/styles/tailwind3.css +669 -0
- package/styles/tailwind3.scss +2 -0
|
@@ -0,0 +1,788 @@
|
|
|
1
|
+
var __assign = (this && this.__assign) || function () {
|
|
2
|
+
__assign = Object.assign || function(t) {
|
|
3
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
4
|
+
s = arguments[i];
|
|
5
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
6
|
+
t[p] = s[p];
|
|
7
|
+
}
|
|
8
|
+
return t;
|
|
9
|
+
};
|
|
10
|
+
return __assign.apply(this, arguments);
|
|
11
|
+
};
|
|
12
|
+
import { sanitizeId, VALIDATION_REGEX } from './utils';
|
|
13
|
+
/**
|
|
14
|
+
* @private
|
|
15
|
+
*/
|
|
16
|
+
var DEFAULT_CONFIG = {
|
|
17
|
+
strict: false,
|
|
18
|
+
maxInputSize: 5 * 1024 * 1024,
|
|
19
|
+
defaultTextType: 'textbox',
|
|
20
|
+
inferTypeFromValue: true,
|
|
21
|
+
generateIds: true,
|
|
22
|
+
includeMetadata: true,
|
|
23
|
+
customTypeMap: {},
|
|
24
|
+
validateUnknownFields: false
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* @private
|
|
28
|
+
*/
|
|
29
|
+
var UniversalJsonParser = /** @class */ (function () {
|
|
30
|
+
function UniversalJsonParser(customConfig) {
|
|
31
|
+
this.config = __assign({}, DEFAULT_CONFIG, customConfig);
|
|
32
|
+
}
|
|
33
|
+
UniversalJsonParser.prototype.parse = function (input) {
|
|
34
|
+
var errors = [];
|
|
35
|
+
var warnings = [];
|
|
36
|
+
// Handle string input
|
|
37
|
+
if (typeof input === 'string') {
|
|
38
|
+
if (input.length > this.config.maxInputSize) {
|
|
39
|
+
return this.formatError(errors, warnings, "Input exceeds maximum size of " + this.config.maxInputSize + " bytes");
|
|
40
|
+
}
|
|
41
|
+
var jsonValidation = validateJSON(input);
|
|
42
|
+
if (!jsonValidation.valid) {
|
|
43
|
+
return this.formatError(errors, warnings, (jsonValidation.errors && jsonValidation.errors[0]) || 'Invalid JSON');
|
|
44
|
+
}
|
|
45
|
+
try {
|
|
46
|
+
input = JSON.parse(input);
|
|
47
|
+
}
|
|
48
|
+
catch (error) {
|
|
49
|
+
return this.formatError(errors, warnings, "Failed to parse JSON: " + error.message);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
// Detect format
|
|
53
|
+
var detection = this.detectFormat(input);
|
|
54
|
+
// Add warnings for ambiguous format detection
|
|
55
|
+
if (detection.ambiguousFormats && detection.ambiguousFormats.length > 0) {
|
|
56
|
+
warnings.push("Ambiguous format detected.");
|
|
57
|
+
warnings.push("Using " + detection.format + " format (" + (detection.format === 'json-schema' ? 'properties priority' : 'pages priority') + ")");
|
|
58
|
+
}
|
|
59
|
+
// Parse based on format
|
|
60
|
+
var components = [];
|
|
61
|
+
switch (detection.format) {
|
|
62
|
+
case 'configured-schema':
|
|
63
|
+
// Already in our standard format, just use directly
|
|
64
|
+
components = input.properties || [];
|
|
65
|
+
break;
|
|
66
|
+
case 'json-schema': {
|
|
67
|
+
var jsonSchemaResult = this.parseJsonSchema(input);
|
|
68
|
+
components = jsonSchemaResult.components;
|
|
69
|
+
if (jsonSchemaResult.warnings) {
|
|
70
|
+
warnings.push.apply(warnings, jsonSchemaResult.warnings);
|
|
71
|
+
}
|
|
72
|
+
break;
|
|
73
|
+
}
|
|
74
|
+
case 'surveyjs':
|
|
75
|
+
components = this.parseSurveyJS(input);
|
|
76
|
+
break;
|
|
77
|
+
case 'openapi':
|
|
78
|
+
components = this.parseOpenAPI(input);
|
|
79
|
+
break;
|
|
80
|
+
case 'data-inference':
|
|
81
|
+
components = this.parseDataInference(input);
|
|
82
|
+
// Only warn about inferred types if components were actually created
|
|
83
|
+
if (components.length > 0) {
|
|
84
|
+
warnings.push('Field types inferred from data; please verify');
|
|
85
|
+
}
|
|
86
|
+
break;
|
|
87
|
+
default:
|
|
88
|
+
errors.push('Could not determine input format');
|
|
89
|
+
}
|
|
90
|
+
if (components.length === 0) {
|
|
91
|
+
errors.push('No form fields could be extracted from input');
|
|
92
|
+
}
|
|
93
|
+
// Add default submit button if not already present
|
|
94
|
+
var hasSubmitButton = components.some(function (comp) { return comp.type === 'button' && comp.buttonType === 'submit'; });
|
|
95
|
+
if (!hasSubmitButton && components.length > 0) {
|
|
96
|
+
components.push({
|
|
97
|
+
id: this.generateComponentId('button'),
|
|
98
|
+
type: 'button',
|
|
99
|
+
label: 'Submit',
|
|
100
|
+
style: 'primary',
|
|
101
|
+
buttonType: 'submit',
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
var schema = {
|
|
105
|
+
version: input.version || "0.1.0",
|
|
106
|
+
components: components
|
|
107
|
+
};
|
|
108
|
+
var schemaValidation = validateFormSchema(schema);
|
|
109
|
+
if (!schemaValidation.valid && schemaValidation.errors) {
|
|
110
|
+
errors.push.apply(errors, schemaValidation.errors);
|
|
111
|
+
}
|
|
112
|
+
if (schemaValidation.warnings) {
|
|
113
|
+
warnings.push.apply(warnings, schemaValidation.warnings);
|
|
114
|
+
}
|
|
115
|
+
if (this.config.strict && warnings.length > 0) {
|
|
116
|
+
errors.push.apply(errors, warnings);
|
|
117
|
+
warnings.length = 0;
|
|
118
|
+
}
|
|
119
|
+
var sanitized = sanitizeFormSchema(schema);
|
|
120
|
+
return {
|
|
121
|
+
success: errors.length === 0,
|
|
122
|
+
schema: sanitized,
|
|
123
|
+
errors: errors,
|
|
124
|
+
warnings: warnings,
|
|
125
|
+
metadata: {
|
|
126
|
+
detectedFormat: detection.format,
|
|
127
|
+
confidence: detection.confidence,
|
|
128
|
+
sourceHints: detection.hints
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
};
|
|
132
|
+
UniversalJsonParser.prototype.formatError = function (errors, warnings, message) {
|
|
133
|
+
errors.push(message);
|
|
134
|
+
return {
|
|
135
|
+
success: false,
|
|
136
|
+
schema: null,
|
|
137
|
+
errors: errors,
|
|
138
|
+
warnings: warnings,
|
|
139
|
+
metadata: {
|
|
140
|
+
detectedFormat: 'unknown',
|
|
141
|
+
confidence: 'low',
|
|
142
|
+
sourceHints: []
|
|
143
|
+
}
|
|
144
|
+
};
|
|
145
|
+
};
|
|
146
|
+
UniversalJsonParser.prototype.detectFormat = function (input) {
|
|
147
|
+
var hints = [];
|
|
148
|
+
var ambiguousFormats = [];
|
|
149
|
+
if (!input || typeof input !== 'object') {
|
|
150
|
+
return {
|
|
151
|
+
format: 'unknown',
|
|
152
|
+
confidence: 'low',
|
|
153
|
+
hints: ['Input is not a valid object']
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
// Check for JSON Schema indicators
|
|
157
|
+
if (input.$schema && typeof input.$schema === 'string' && input.$schema.includes('json-schema')) {
|
|
158
|
+
hints.push('$schema property detected');
|
|
159
|
+
return { format: 'json-schema', confidence: 'high', hints: hints };
|
|
160
|
+
}
|
|
161
|
+
// Detect ambiguous formats (Test Case 8)
|
|
162
|
+
var hasProperties = input.properties && typeof input.properties === 'object';
|
|
163
|
+
var hasPages = input.pages && Array.isArray(input.pages);
|
|
164
|
+
var hasElements = input.elements && Array.isArray(input.elements);
|
|
165
|
+
if (hasProperties && hasPages) {
|
|
166
|
+
hints.push('Multiple format patterns detected');
|
|
167
|
+
hints.push('Selected based on priority rules');
|
|
168
|
+
ambiguousFormats.push('properties format', 'pages format');
|
|
169
|
+
// JSON Schema has priority
|
|
170
|
+
return {
|
|
171
|
+
format: 'json-schema',
|
|
172
|
+
confidence: 'medium',
|
|
173
|
+
hints: hints,
|
|
174
|
+
ambiguousFormats: ambiguousFormats
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
// Check for SurveyJS with pages
|
|
178
|
+
if (hasPages) {
|
|
179
|
+
hints.push('pages array detected');
|
|
180
|
+
if (input.pages[0] && input.pages[0].elements)
|
|
181
|
+
hints.push('elements structure matched');
|
|
182
|
+
return { format: 'surveyjs', confidence: 'high', hints: hints };
|
|
183
|
+
}
|
|
184
|
+
// Check for SurveyJS with elements at root
|
|
185
|
+
if (hasElements && !hasProperties) {
|
|
186
|
+
hints.push('elements array at root level');
|
|
187
|
+
return { format: 'surveyjs', confidence: 'medium', hints: hints };
|
|
188
|
+
}
|
|
189
|
+
// Check for JSON Schema with properties
|
|
190
|
+
if (hasProperties) {
|
|
191
|
+
hints.push('properties object detected');
|
|
192
|
+
if (input.type === 'object')
|
|
193
|
+
hints.push('type: object matched');
|
|
194
|
+
if (input.required && Array.isArray(input.required))
|
|
195
|
+
hints.push('required array found');
|
|
196
|
+
// Check for API schema indicators (example fields pattern)
|
|
197
|
+
if (this.hasExampleFields(input.properties)) {
|
|
198
|
+
hints.push('example fields detected (API schema pattern)');
|
|
199
|
+
return { format: 'openapi', confidence: 'high', hints: hints };
|
|
200
|
+
}
|
|
201
|
+
return { format: 'json-schema', confidence: 'high', hints: hints };
|
|
202
|
+
}
|
|
203
|
+
// Check for Data Inference
|
|
204
|
+
if (this.isDataInferenceCandidate(input)) {
|
|
205
|
+
hints.push('Simple object with primitive values');
|
|
206
|
+
hints.push('No schema indicators found');
|
|
207
|
+
return { format: 'data-inference', confidence: 'medium', hints: hints };
|
|
208
|
+
}
|
|
209
|
+
return {
|
|
210
|
+
format: 'unknown',
|
|
211
|
+
confidence: 'low',
|
|
212
|
+
hints: ['Could not identify format']
|
|
213
|
+
};
|
|
214
|
+
};
|
|
215
|
+
UniversalJsonParser.prototype.hasExampleFields = function (properties) {
|
|
216
|
+
if (!properties || typeof properties !== 'object')
|
|
217
|
+
return false;
|
|
218
|
+
var keys = Object.keys(properties);
|
|
219
|
+
for (var _i = 0, keys_1 = keys; _i < keys_1.length; _i++) {
|
|
220
|
+
var key = keys_1[_i];
|
|
221
|
+
var prop = properties[key];
|
|
222
|
+
if (prop && 'example' in prop) {
|
|
223
|
+
return true;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
return false;
|
|
227
|
+
};
|
|
228
|
+
UniversalJsonParser.prototype.isDataInferenceCandidate = function (input) {
|
|
229
|
+
if (!input || typeof input !== 'object')
|
|
230
|
+
return false;
|
|
231
|
+
if (input.$schema || input.properties || input.pages || input.elements)
|
|
232
|
+
return false;
|
|
233
|
+
var inputKeys = Object.keys(input);
|
|
234
|
+
return inputKeys.every(function (k) {
|
|
235
|
+
var val = input[k];
|
|
236
|
+
if (val === null || val === undefined)
|
|
237
|
+
return true;
|
|
238
|
+
if (typeof val === 'string' || typeof val === 'number' || typeof val === 'boolean')
|
|
239
|
+
return true;
|
|
240
|
+
if (Array.isArray(val)) {
|
|
241
|
+
return val.every(function (item) {
|
|
242
|
+
return typeof item === 'string' || typeof item === 'number' || typeof item === 'boolean';
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
return false;
|
|
246
|
+
});
|
|
247
|
+
};
|
|
248
|
+
UniversalJsonParser.prototype.inferComponentType = function (fieldName, value) {
|
|
249
|
+
var valueType = this.inferTypeFromValue(fieldName, value);
|
|
250
|
+
if (valueType.type) {
|
|
251
|
+
return __assign({}, valueType, { confidence: 'high', method: 'value-type' });
|
|
252
|
+
}
|
|
253
|
+
var patternMatch = this.matchFieldNamePattern(fieldName);
|
|
254
|
+
if (patternMatch.type) {
|
|
255
|
+
return __assign({}, patternMatch, { confidence: 'high', method: 'name-pattern' });
|
|
256
|
+
}
|
|
257
|
+
return {
|
|
258
|
+
type: this.config.defaultTextType,
|
|
259
|
+
confidence: 'low',
|
|
260
|
+
method: 'fallback'
|
|
261
|
+
};
|
|
262
|
+
};
|
|
263
|
+
UniversalJsonParser.prototype.inferTypeFromValue = function (fieldName, value) {
|
|
264
|
+
if (!this.config.inferTypeFromValue)
|
|
265
|
+
return { type: 'textbox' };
|
|
266
|
+
if (value === null || value === undefined) {
|
|
267
|
+
// Even with null/undefined values, check field name patterns
|
|
268
|
+
return this.matchFieldNamePattern(fieldName);
|
|
269
|
+
}
|
|
270
|
+
if (typeof value === 'string') {
|
|
271
|
+
// Check value-based patterns first (highest confidence)
|
|
272
|
+
if (value.includes('@') && value.includes('.')) {
|
|
273
|
+
return { type: 'textbox', textboxType: 'email' };
|
|
274
|
+
}
|
|
275
|
+
// eslint-disable-next-line security/detect-unsafe-regex
|
|
276
|
+
if (/^(https?:\/\/)?(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}/.test(value)) {
|
|
277
|
+
return { type: 'textbox', textboxType: 'url' };
|
|
278
|
+
}
|
|
279
|
+
if (/^\d{4}-\d{2}-\d{2}/.test(value)) {
|
|
280
|
+
return { type: 'date' };
|
|
281
|
+
}
|
|
282
|
+
// For generic strings, check field name patterns
|
|
283
|
+
var fieldNameMatch = this.matchFieldNamePattern(fieldName);
|
|
284
|
+
if (fieldNameMatch.type !== 'textbox' || fieldNameMatch.textboxType) {
|
|
285
|
+
return fieldNameMatch;
|
|
286
|
+
}
|
|
287
|
+
return { type: this.config.defaultTextType };
|
|
288
|
+
}
|
|
289
|
+
if (typeof value === 'number') {
|
|
290
|
+
return { type: 'number' };
|
|
291
|
+
}
|
|
292
|
+
if (typeof value === 'boolean') {
|
|
293
|
+
return { type: 'checkbox' };
|
|
294
|
+
}
|
|
295
|
+
if (Array.isArray(value)) {
|
|
296
|
+
return { type: 'multiselect' };
|
|
297
|
+
}
|
|
298
|
+
return { type: 'textbox' };
|
|
299
|
+
};
|
|
300
|
+
UniversalJsonParser.prototype.matchFieldNamePattern = function (fieldName) {
|
|
301
|
+
if (this.config.customTypeMap) {
|
|
302
|
+
var customType = this.config.customTypeMap[fieldName.toLowerCase()];
|
|
303
|
+
if (customType)
|
|
304
|
+
return { type: customType };
|
|
305
|
+
}
|
|
306
|
+
var lower = fieldName.toLowerCase();
|
|
307
|
+
var normalized = lower.replace(/[_\-\s]+/g, ' ');
|
|
308
|
+
if (/email|mail|e-?mail/.test(normalized))
|
|
309
|
+
return { type: 'textbox', textboxType: 'email' };
|
|
310
|
+
if (/date|birth|birthday|dob|created|updated/.test(normalized))
|
|
311
|
+
return { type: 'date' };
|
|
312
|
+
if (/phone|tel|mobile|cell|cellphone|msisdn/.test(normalized))
|
|
313
|
+
return { type: 'textbox', textboxType: 'number' };
|
|
314
|
+
if (/url|link|uri|website/.test(normalized))
|
|
315
|
+
return { type: 'textbox', textboxType: 'url' };
|
|
316
|
+
if (/password|pwd|pass|security|secret|key|token/.test(normalized))
|
|
317
|
+
return { type: 'textbox', textboxType: 'password' };
|
|
318
|
+
if (/\b(?:age|count|qty|quantity|amount|price|cost|salary|fee|rate|number|num)\b/.test(normalized))
|
|
319
|
+
return { type: 'number' };
|
|
320
|
+
if (/active|enabled|visible|deleted|archived|approved|confirmed/.test(normalized))
|
|
321
|
+
return { type: 'checkbox' };
|
|
322
|
+
if (/select|choice|option|type|status|category|kind/.test(normalized))
|
|
323
|
+
return { type: 'dropdown' };
|
|
324
|
+
if (/description|comment|note|bio|biography|about|message|content|summary|details/.test(normalized))
|
|
325
|
+
return { type: 'textarea' };
|
|
326
|
+
return { type: 'textbox' };
|
|
327
|
+
};
|
|
328
|
+
UniversalJsonParser.prototype.parseJsonSchema = function (schema) {
|
|
329
|
+
var components = [];
|
|
330
|
+
var warnings = [];
|
|
331
|
+
if (!schema.properties || typeof schema.properties !== 'object')
|
|
332
|
+
return { components: components, warnings: warnings };
|
|
333
|
+
var flattenedProperties = this.flattenNestedProperties(schema.properties, '', warnings);
|
|
334
|
+
var flatKeys = Object.keys(flattenedProperties);
|
|
335
|
+
for (var _i = 0, flatKeys_1 = flatKeys; _i < flatKeys_1.length; _i++) {
|
|
336
|
+
var key = flatKeys_1[_i];
|
|
337
|
+
var propDef = flattenedProperties[key];
|
|
338
|
+
var typeInfo = this.mapJsonSchemaType(propDef);
|
|
339
|
+
var requiredArr = schema.required || [];
|
|
340
|
+
var isRequired = requiredArr.indexOf(key) !== -1;
|
|
341
|
+
components.push(this.createComponent(key, propDef, typeInfo, { required: isRequired }));
|
|
342
|
+
}
|
|
343
|
+
return { components: components, warnings: warnings };
|
|
344
|
+
};
|
|
345
|
+
UniversalJsonParser.prototype.flattenNestedProperties = function (properties, prefix, warnings) {
|
|
346
|
+
var flattened = {};
|
|
347
|
+
var hasNested = false;
|
|
348
|
+
var propKeys = Object.keys(properties);
|
|
349
|
+
for (var _i = 0, propKeys_1 = propKeys; _i < propKeys_1.length; _i++) {
|
|
350
|
+
var key = propKeys_1[_i];
|
|
351
|
+
var propDef = properties[key];
|
|
352
|
+
var fullKey = prefix ? prefix + "_" + key : key;
|
|
353
|
+
// Check if this is a nested object (Test Case 9)
|
|
354
|
+
if (propDef.type === 'object' && propDef.properties && typeof propDef.properties === 'object') {
|
|
355
|
+
hasNested = true;
|
|
356
|
+
var nestedFlattened = this.flattenNestedProperties(propDef.properties, fullKey, warnings);
|
|
357
|
+
Object.assign(flattened, nestedFlattened);
|
|
358
|
+
}
|
|
359
|
+
else {
|
|
360
|
+
flattened[fullKey] = propDef;
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
// Add warnings for nested objects
|
|
364
|
+
if (hasNested && !prefix) {
|
|
365
|
+
warnings.push('NESTED_OBJECTS_FLATTENED: Nested objects converted to flat structure');
|
|
366
|
+
var outerKeys = Object.keys(properties);
|
|
367
|
+
for (var _a = 0, outerKeys_1 = outerKeys; _a < outerKeys_1.length; _a++) {
|
|
368
|
+
var key = outerKeys_1[_a];
|
|
369
|
+
var propDef = properties[key];
|
|
370
|
+
if (propDef.type === 'object' && propDef.properties) {
|
|
371
|
+
this.collectFlattenedFieldNames(propDef.properties, key, warnings);
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
return flattened;
|
|
376
|
+
};
|
|
377
|
+
UniversalJsonParser.prototype.collectFlattenedFieldNames = function (properties, prefix, warnings) {
|
|
378
|
+
var collKeys = Object.keys(properties);
|
|
379
|
+
for (var _i = 0, collKeys_1 = collKeys; _i < collKeys_1.length; _i++) {
|
|
380
|
+
var key = collKeys_1[_i];
|
|
381
|
+
var propDef = properties[key];
|
|
382
|
+
var fullKey = prefix + "_" + key;
|
|
383
|
+
warnings.push("Field '" + prefix + "." + key + "' flattened to '" + fullKey + "'");
|
|
384
|
+
if (propDef.type === 'object' && propDef.properties) {
|
|
385
|
+
this.collectFlattenedFieldNames(propDef.properties, fullKey, warnings);
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
};
|
|
389
|
+
UniversalJsonParser.prototype.parseSurveyJS = function (schema) {
|
|
390
|
+
var _this = this;
|
|
391
|
+
var components = [];
|
|
392
|
+
if (schema.pages && Array.isArray(schema.pages)) {
|
|
393
|
+
schema.pages.forEach(function (page) {
|
|
394
|
+
if (page.elements && Array.isArray(page.elements)) {
|
|
395
|
+
page.elements.forEach(function (element) {
|
|
396
|
+
components.push(_this.createComponentFromSurveyJS(element));
|
|
397
|
+
});
|
|
398
|
+
}
|
|
399
|
+
});
|
|
400
|
+
}
|
|
401
|
+
if (!components.length && schema.elements && Array.isArray(schema.elements)) {
|
|
402
|
+
schema.elements.forEach(function (element) {
|
|
403
|
+
components.push(_this.createComponentFromSurveyJS(element));
|
|
404
|
+
});
|
|
405
|
+
}
|
|
406
|
+
return components;
|
|
407
|
+
};
|
|
408
|
+
UniversalJsonParser.prototype.createComponentFromSurveyJS = function (element) {
|
|
409
|
+
var type = this.mapSurveyJSType(element.type || 'text');
|
|
410
|
+
var validation = {};
|
|
411
|
+
// Only add required if explicitly true
|
|
412
|
+
if (element.isRequired === true) {
|
|
413
|
+
validation.required = true;
|
|
414
|
+
}
|
|
415
|
+
if (element.validators && Array.isArray(element.validators)) {
|
|
416
|
+
element.validators.forEach(function (validator) {
|
|
417
|
+
if (validator.type === 'numeric') {
|
|
418
|
+
if (validator.minValue !== undefined)
|
|
419
|
+
validation.minValue = validator.minValue;
|
|
420
|
+
if (validator.maxValue !== undefined)
|
|
421
|
+
validation.maxValue = validator.maxValue;
|
|
422
|
+
}
|
|
423
|
+
if (validator.type === 'text') {
|
|
424
|
+
if (validator.minLength !== undefined)
|
|
425
|
+
validation.minLength = validator.minLength;
|
|
426
|
+
if (validator.maxLength !== undefined)
|
|
427
|
+
validation.maxLength = validator.maxLength;
|
|
428
|
+
}
|
|
429
|
+
});
|
|
430
|
+
}
|
|
431
|
+
var component = __assign({ id: this.generateComponentId(type), type: type, label: element.title || element.label || this.humanizeFieldName(element.name), defaultValue: element.defaultValue, expressionValue: element.expressionValue }, Object.keys(validation).length > 0 ? validation : undefined);
|
|
432
|
+
if (type === 'dropdown' || type === 'multiselect' || type === 'radio' || type === 'splitButton') {
|
|
433
|
+
if (element.choices && Array.isArray(element.choices)) {
|
|
434
|
+
component.options = element.choices;
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
return component;
|
|
438
|
+
};
|
|
439
|
+
UniversalJsonParser.prototype.mapSurveyJSType = function (surveyType) {
|
|
440
|
+
var typeMap = {
|
|
441
|
+
text: 'textbox',
|
|
442
|
+
email: 'email',
|
|
443
|
+
number: 'number',
|
|
444
|
+
checkbox: 'checkbox',
|
|
445
|
+
radiogroup: 'radio',
|
|
446
|
+
dropdown: 'dropdown',
|
|
447
|
+
tagbox: 'multiselect',
|
|
448
|
+
multiselect: 'multiselect',
|
|
449
|
+
rating: 'number',
|
|
450
|
+
comment: 'textarea',
|
|
451
|
+
date: 'date'
|
|
452
|
+
};
|
|
453
|
+
return typeMap[surveyType] || 'textbox';
|
|
454
|
+
};
|
|
455
|
+
UniversalJsonParser.prototype.parseOpenAPI = function (schema) {
|
|
456
|
+
var components = [];
|
|
457
|
+
if (!schema.properties || typeof schema.properties !== 'object')
|
|
458
|
+
return components;
|
|
459
|
+
var openAPIKeys = Object.keys(schema.properties);
|
|
460
|
+
var requiredArr = schema.required || [];
|
|
461
|
+
for (var _i = 0, openAPIKeys_1 = openAPIKeys; _i < openAPIKeys_1.length; _i++) {
|
|
462
|
+
var key = openAPIKeys_1[_i];
|
|
463
|
+
var propDef = schema.properties[key];
|
|
464
|
+
var typeInfo = this.mapJsonSchemaType(propDef);
|
|
465
|
+
var isRequired = requiredArr.indexOf(key) !== -1;
|
|
466
|
+
components.push(this.createComponent(key, propDef, typeInfo, { required: isRequired }));
|
|
467
|
+
}
|
|
468
|
+
return components;
|
|
469
|
+
};
|
|
470
|
+
UniversalJsonParser.prototype.parseDataInference = function (data) {
|
|
471
|
+
var components = [];
|
|
472
|
+
var dataKeys = Object.keys(data);
|
|
473
|
+
for (var _i = 0, dataKeys_1 = dataKeys; _i < dataKeys_1.length; _i++) {
|
|
474
|
+
var key = dataKeys_1[_i];
|
|
475
|
+
var value = data[key];
|
|
476
|
+
var typeInference = this.inferComponentType(key, value);
|
|
477
|
+
var component = {
|
|
478
|
+
id: this.generateComponentId(typeInference.type),
|
|
479
|
+
type: typeInference.type,
|
|
480
|
+
label: this.humanizeFieldName(key),
|
|
481
|
+
defaultValue: value,
|
|
482
|
+
expressionValue: undefined
|
|
483
|
+
};
|
|
484
|
+
if (typeInference.textboxType) {
|
|
485
|
+
component.textboxType = typeInference.textboxType;
|
|
486
|
+
// Add default regex patterns for email and url
|
|
487
|
+
if (typeInference.textboxType === 'email') {
|
|
488
|
+
component.regex = VALIDATION_REGEX['EMAIL'];
|
|
489
|
+
}
|
|
490
|
+
else if (typeInference.textboxType === 'url') {
|
|
491
|
+
component.regex = VALIDATION_REGEX['URL'];
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
if (typeInference.type === 'date' && component.defaultValue !== undefined && component.defaultValue !== null) {
|
|
495
|
+
var formatted = this.formatDateTimeValue(component.defaultValue);
|
|
496
|
+
if (formatted)
|
|
497
|
+
component.defaultValue = formatted;
|
|
498
|
+
}
|
|
499
|
+
if (Array.isArray(value) && value.length > 0) {
|
|
500
|
+
component.options = value;
|
|
501
|
+
}
|
|
502
|
+
components.push(component);
|
|
503
|
+
}
|
|
504
|
+
return components;
|
|
505
|
+
};
|
|
506
|
+
UniversalJsonParser.prototype.createComponent = function (fieldName, propDef, typeInfo, context) {
|
|
507
|
+
var validation = {};
|
|
508
|
+
// Only add required if explicitly true
|
|
509
|
+
var isRequired = propDef.required !== undefined ? propDef.required : context.required;
|
|
510
|
+
if (isRequired === true) {
|
|
511
|
+
validation.required = true;
|
|
512
|
+
}
|
|
513
|
+
if (propDef.minLength)
|
|
514
|
+
validation.minLength = propDef.minLength;
|
|
515
|
+
if (propDef.maxLength)
|
|
516
|
+
validation.maxLength = propDef.maxLength;
|
|
517
|
+
if (propDef.minDate)
|
|
518
|
+
validation.minDate = propDef.minDate;
|
|
519
|
+
if (propDef.maxDate)
|
|
520
|
+
validation.maxDate = propDef.maxDate;
|
|
521
|
+
if (propDef.minTime)
|
|
522
|
+
validation.minTime = propDef.minTime;
|
|
523
|
+
if (propDef.minValue)
|
|
524
|
+
validation.minValue = propDef.minValue;
|
|
525
|
+
if (propDef.maxValue)
|
|
526
|
+
validation.maxValue = propDef.maxValue;
|
|
527
|
+
if (propDef.pattern) {
|
|
528
|
+
validation.pattern = propDef.pattern;
|
|
529
|
+
}
|
|
530
|
+
var rawId = propDef.id || this.generateComponentId(typeInfo.type);
|
|
531
|
+
var safeGeneratedId = sanitizeId(rawId, this.generateComponentId(typeInfo.type));
|
|
532
|
+
var component = __assign({ id: safeGeneratedId, name: propDef.name, type: typeInfo.type, label: propDef.title || propDef.label || this.humanizeFieldName(fieldName), defaultValue: propDef.default || propDef.defaultValue || undefined, expressionValue: propDef.expressionValue || undefined, content: propDef.content, buttonType: propDef.buttonType, textboxType: propDef.textboxType }, Object.keys(validation).length > 0 ? validation : undefined);
|
|
533
|
+
if (typeInfo.textboxType) {
|
|
534
|
+
component.textboxType = typeInfo.textboxType;
|
|
535
|
+
// Add default regex patterns for email and url
|
|
536
|
+
if (typeInfo.textboxType === 'email') {
|
|
537
|
+
if (!validation.pattern) {
|
|
538
|
+
validation.regex = '^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$'; // Standard email regex
|
|
539
|
+
validation.validationMessage = 'Please enter a valid email address';
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
else if (typeInfo.textboxType === 'url') {
|
|
543
|
+
if (!validation.pattern) {
|
|
544
|
+
validation.regex = '^(https?:\\/\\/)?(www\\.)?[-a-zA-Z0-9@:%._\\+~#=]{1,256}\\.[a-zA-Z0-9()]{1,6}\\b([-a-zA-Z0-9()@:%_\\+.~#?&//=]*)$';
|
|
545
|
+
validation.validationMessage = 'Please enter a valid URL';
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
if (typeInfo.type === 'date' && component.defaultValue !== undefined && component.defaultValue !== null) {
|
|
550
|
+
var formatted = this.formatDateTimeValue(component.defaultValue);
|
|
551
|
+
if (formatted)
|
|
552
|
+
component.defaultValue = formatted;
|
|
553
|
+
}
|
|
554
|
+
if ((typeInfo.type === 'splitButton' || typeInfo.type === 'dropdown' || typeInfo.type === 'multiselect' || typeInfo.type === 'radio') && (propDef.enum || propDef.options)) {
|
|
555
|
+
component.options = propDef.enum || propDef.options;
|
|
556
|
+
}
|
|
557
|
+
return component;
|
|
558
|
+
};
|
|
559
|
+
UniversalJsonParser.prototype.parseDateFromValue = function (value) {
|
|
560
|
+
if (value == null)
|
|
561
|
+
return null;
|
|
562
|
+
// numeric timestamps
|
|
563
|
+
if (typeof value === 'number') {
|
|
564
|
+
// assume seconds if small
|
|
565
|
+
if (value < 1e12)
|
|
566
|
+
return new Date(value * 1000);
|
|
567
|
+
return new Date(value);
|
|
568
|
+
}
|
|
569
|
+
if (typeof value === 'string') {
|
|
570
|
+
var s = value.trim();
|
|
571
|
+
// Try ISO / RFC parse
|
|
572
|
+
var dIso = new Date(s);
|
|
573
|
+
if (!isNaN(dIso.getTime()))
|
|
574
|
+
return dIso;
|
|
575
|
+
// yyyy-mm-dd[ T hh:mm(:ss)]
|
|
576
|
+
// eslint-disable-next-line security/detect-unsafe-regex
|
|
577
|
+
var m = s.match(/^(\d{4})-(\d{2})-(\d{2})(?:[T ](\d{2}):(\d{2})(?::(\d{2}))?)?/);
|
|
578
|
+
if (m)
|
|
579
|
+
return new Date(Number(m[1]), Number(m[2]) - 1, Number(m[3]), Number(m[4] || 0), Number(m[5] || 0), Number(m[6] || 0));
|
|
580
|
+
// mm/dd/yyyy or m/d/yyyy
|
|
581
|
+
// eslint-disable-next-line security/detect-unsafe-regex
|
|
582
|
+
var m2 = s.match(/^(\d{1,2})\/(\d{1,2})\/(\d{4})(?:[ T](\d{1,2}):(\d{2})(?:[:](\d{2}))?)?/);
|
|
583
|
+
if (m2)
|
|
584
|
+
return new Date(Number(m2[3]), Number(m2[1]) - 1, Number(m2[2]), Number(m2[4] || 0), Number(m2[5] || 0), Number(m2[6] || 0));
|
|
585
|
+
}
|
|
586
|
+
return null;
|
|
587
|
+
};
|
|
588
|
+
UniversalJsonParser.prototype.formatDate = function (d) {
|
|
589
|
+
var monthNum = d.getMonth() + 1;
|
|
590
|
+
var dayNum = d.getDate();
|
|
591
|
+
var mm = monthNum < 10 ? '0' + monthNum : String(monthNum);
|
|
592
|
+
var dd = dayNum < 10 ? '0' + dayNum : String(dayNum);
|
|
593
|
+
var yyyy = d.getFullYear();
|
|
594
|
+
return mm + "/" + dd + "/" + yyyy;
|
|
595
|
+
};
|
|
596
|
+
// private formatTime(d: Date): string {
|
|
597
|
+
// let hours = d.getHours();
|
|
598
|
+
// const minutes = d.getMinutes().toString().padStart(2, '0');
|
|
599
|
+
// const ampm = hours >= 12 ? 'PM' : 'AM';
|
|
600
|
+
// hours = hours % 12;
|
|
601
|
+
// if (hours === 0) hours = 12;
|
|
602
|
+
// return `${hours.toString().padStart(2, '0')}:${minutes} ${ampm}`;
|
|
603
|
+
// }
|
|
604
|
+
UniversalJsonParser.prototype.formatDateTimeValue = function (value) {
|
|
605
|
+
var d = this.parseDateFromValue(value);
|
|
606
|
+
if (!d)
|
|
607
|
+
return undefined;
|
|
608
|
+
var datePart = this.formatDate(d);
|
|
609
|
+
var hasTime = d.getHours() !== 0 || d.getMinutes() !== 0 || /\dT\d{2}:\d{2}/.test(String(value));
|
|
610
|
+
if (hasTime)
|
|
611
|
+
return "" + datePart;
|
|
612
|
+
return datePart;
|
|
613
|
+
};
|
|
614
|
+
UniversalJsonParser.prototype.mapJsonSchemaType = function (propDef) {
|
|
615
|
+
var schemaType = propDef.type;
|
|
616
|
+
if (schemaType === 'string') {
|
|
617
|
+
var fmt = (propDef.format || '').toString().toLowerCase();
|
|
618
|
+
var text = ((propDef.title || propDef.label || '') + ' ' + (propDef.description || '')).toLowerCase();
|
|
619
|
+
if (/email|mail|e-?mail/.test(fmt) || /email|mail|e-?mail/.test(text))
|
|
620
|
+
return { type: 'textbox', textboxType: 'email' };
|
|
621
|
+
if (/uri|url|link|website/.test(fmt) || /uri|url|link|website/.test(text))
|
|
622
|
+
return { type: 'textbox', textboxType: 'url' };
|
|
623
|
+
if (/phone|tel|mobile|cell|msisdn/.test(fmt) || /phone|tel|mobile|cell|msisdn/.test(text))
|
|
624
|
+
return { type: 'textbox', textboxType: 'number' };
|
|
625
|
+
if (/password|pwd|pass|security|secret|key/.test(fmt) || /password|pwd|pass|security|secret|key/.test(text))
|
|
626
|
+
return { type: 'textbox', textboxType: 'password' };
|
|
627
|
+
if (fmt === 'date' || fmt === 'date-time' || /date|birthday|dob/.test(text))
|
|
628
|
+
return { type: 'date' };
|
|
629
|
+
if (propDef.enum)
|
|
630
|
+
return { type: 'dropdown' };
|
|
631
|
+
if (propDef.options)
|
|
632
|
+
return { type: 'dropdown' };
|
|
633
|
+
return { type: this.config.defaultTextType };
|
|
634
|
+
}
|
|
635
|
+
if (schemaType === 'number' || schemaType === 'integer')
|
|
636
|
+
return { type: 'number' };
|
|
637
|
+
if (schemaType === 'boolean')
|
|
638
|
+
return { type: 'checkbox' };
|
|
639
|
+
if (schemaType === 'array')
|
|
640
|
+
return { type: 'multiselect' };
|
|
641
|
+
// Presentation / custom widget types
|
|
642
|
+
if (schemaType === 'message')
|
|
643
|
+
return { type: 'message' };
|
|
644
|
+
if (schemaType === 'button')
|
|
645
|
+
return { type: 'button' };
|
|
646
|
+
if (schemaType === 'signature' || schemaType === 'sign')
|
|
647
|
+
return { type: 'signature' };
|
|
648
|
+
if (schemaType === 'image' || schemaType === 'imageEditor')
|
|
649
|
+
return { type: 'imageEditor' };
|
|
650
|
+
if (schemaType === 'file' || schemaType === 'fileUpload')
|
|
651
|
+
return { type: 'fileUpload' };
|
|
652
|
+
if (schemaType === 'color' || schemaType === 'colorPicker')
|
|
653
|
+
return { type: 'colorPicker' };
|
|
654
|
+
if (schemaType === 'splitButton')
|
|
655
|
+
return { type: 'splitButton' };
|
|
656
|
+
return { type: this.config.defaultTextType };
|
|
657
|
+
};
|
|
658
|
+
UniversalJsonParser.prototype.generateComponentId = function (type) {
|
|
659
|
+
if (!this.config.generateIds)
|
|
660
|
+
return '';
|
|
661
|
+
var timestamp = Date.now();
|
|
662
|
+
var random = Math.floor(Math.random() * 1000);
|
|
663
|
+
return type + "_" + timestamp + "_" + random;
|
|
664
|
+
};
|
|
665
|
+
UniversalJsonParser.prototype.humanizeFieldName = function (fieldName) {
|
|
666
|
+
var result = fieldName.replace(/_/g, ' ');
|
|
667
|
+
result = result.replace(/([a-z])([A-Z])/g, '$1 $2');
|
|
668
|
+
return result;
|
|
669
|
+
};
|
|
670
|
+
return UniversalJsonParser;
|
|
671
|
+
}());
|
|
672
|
+
export { UniversalJsonParser };
|
|
673
|
+
/**
|
|
674
|
+
* @private
|
|
675
|
+
*/
|
|
676
|
+
export var validateJSON = function (jsonString) {
|
|
677
|
+
try {
|
|
678
|
+
JSON.parse(jsonString);
|
|
679
|
+
return { valid: true };
|
|
680
|
+
}
|
|
681
|
+
catch (error) {
|
|
682
|
+
return {
|
|
683
|
+
valid: false,
|
|
684
|
+
errors: ["Invalid JSON syntax: " + error.message]
|
|
685
|
+
};
|
|
686
|
+
}
|
|
687
|
+
};
|
|
688
|
+
/**
|
|
689
|
+
* @private
|
|
690
|
+
*/
|
|
691
|
+
export var validateFormSchema = function (schema) {
|
|
692
|
+
var errors = [];
|
|
693
|
+
var warnings = [];
|
|
694
|
+
if (!schema.components) {
|
|
695
|
+
errors.push('Missing required property: components');
|
|
696
|
+
}
|
|
697
|
+
else if (!Array.isArray(schema.components)) {
|
|
698
|
+
errors.push('Property "components" must be an array');
|
|
699
|
+
}
|
|
700
|
+
// Validate component structure
|
|
701
|
+
if (Array.isArray(schema.components)) {
|
|
702
|
+
var componentIds_1 = new Set();
|
|
703
|
+
var validateComponent_1 = function (comp, path) {
|
|
704
|
+
if (path === void 0) { path = 'root'; }
|
|
705
|
+
if (!comp.id) {
|
|
706
|
+
errors.push("Component at " + path + " is missing \"id\" property");
|
|
707
|
+
}
|
|
708
|
+
else {
|
|
709
|
+
if (componentIds_1.has(comp.id)) {
|
|
710
|
+
errors.push("Duplicate component ID found: " + comp.id);
|
|
711
|
+
}
|
|
712
|
+
componentIds_1.add(comp.id);
|
|
713
|
+
}
|
|
714
|
+
if (!comp.type) {
|
|
715
|
+
errors.push("Component \"" + (comp.id || 'unknown') + "\" is missing \"type\" property");
|
|
716
|
+
}
|
|
717
|
+
if (comp.children && Array.isArray(comp.children)) {
|
|
718
|
+
comp.children.forEach(function (child, index) {
|
|
719
|
+
validateComponent_1(child, path + ".children[" + index + "]");
|
|
720
|
+
});
|
|
721
|
+
}
|
|
722
|
+
if (comp.tabItems && Array.isArray(comp.tabItems)) {
|
|
723
|
+
comp.tabItems.forEach(function (tab, tabIndex) {
|
|
724
|
+
if (tab.content && Array.isArray(tab.content)) {
|
|
725
|
+
tab.content.forEach(function (child, index) {
|
|
726
|
+
validateComponent_1(child, path + ".tabItems[" + tabIndex + "].content[" + index + "]");
|
|
727
|
+
});
|
|
728
|
+
}
|
|
729
|
+
});
|
|
730
|
+
}
|
|
731
|
+
if (comp.tableCells && Array.isArray(comp.tableCells)) {
|
|
732
|
+
comp.tableCells.forEach(function (row, rowIndex) {
|
|
733
|
+
if (Array.isArray(row)) {
|
|
734
|
+
row.forEach(function (cell, colIndex) {
|
|
735
|
+
if (Array.isArray(cell)) {
|
|
736
|
+
cell.forEach(function (child, index) {
|
|
737
|
+
validateComponent_1(child, path + ".tableCells[" + rowIndex + "][" + colIndex + "][" + index + "]");
|
|
738
|
+
});
|
|
739
|
+
}
|
|
740
|
+
});
|
|
741
|
+
}
|
|
742
|
+
});
|
|
743
|
+
}
|
|
744
|
+
};
|
|
745
|
+
schema.components.forEach(function (comp, index) {
|
|
746
|
+
validateComponent_1(comp, "components[" + index + "]");
|
|
747
|
+
});
|
|
748
|
+
}
|
|
749
|
+
return {
|
|
750
|
+
valid: errors.length === 0,
|
|
751
|
+
errors: errors.length > 0 ? errors : undefined,
|
|
752
|
+
warnings: warnings.length > 0 ? warnings : undefined
|
|
753
|
+
};
|
|
754
|
+
};
|
|
755
|
+
/**
|
|
756
|
+
* @private
|
|
757
|
+
*/
|
|
758
|
+
export var sanitizeFormSchema = function (schema) {
|
|
759
|
+
var sanitized = {
|
|
760
|
+
version: schema.version || "0.1.0",
|
|
761
|
+
components: schema.components || []
|
|
762
|
+
};
|
|
763
|
+
var sanitizeComponent = function (comp) {
|
|
764
|
+
var sanitizedComp = __assign({}, comp, { _configured: true });
|
|
765
|
+
if (comp.children && Array.isArray(comp.children)) {
|
|
766
|
+
sanitizedComp.children = comp.children.map(sanitizeComponent);
|
|
767
|
+
}
|
|
768
|
+
if (comp.tabItems && Array.isArray(comp.tabItems)) {
|
|
769
|
+
sanitizedComp.tabItems = comp.tabItems.map(function (tab) { return (__assign({}, tab, { content: tab.content ? tab.content.map(sanitizeComponent) : [] })); });
|
|
770
|
+
}
|
|
771
|
+
if (comp.tableCells && Array.isArray(comp.tableCells)) {
|
|
772
|
+
sanitizedComp.tableCells = comp.tableCells.map(function (row) {
|
|
773
|
+
return row.map(function (cell) {
|
|
774
|
+
return Array.isArray(cell) ? cell.map(sanitizeComponent) : [];
|
|
775
|
+
});
|
|
776
|
+
});
|
|
777
|
+
}
|
|
778
|
+
return sanitizedComp;
|
|
779
|
+
};
|
|
780
|
+
sanitized.components = sanitized.components.map(sanitizeComponent);
|
|
781
|
+
return sanitized;
|
|
782
|
+
};
|
|
783
|
+
/**
|
|
784
|
+
* @private
|
|
785
|
+
*/
|
|
786
|
+
export var exportFormSchema = function (schema) {
|
|
787
|
+
return JSON.stringify(schema, null, 2);
|
|
788
|
+
};
|