fcad-core-dragon 2.0.0-beta.3 → 2.0.0-beta.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (95) hide show
  1. package/.editorconfig +33 -33
  2. package/.eslintignore +29 -29
  3. package/.eslintrc.cjs +81 -81
  4. package/CHANGELOG +373 -364
  5. package/README.md +71 -71
  6. package/bk.scss +117 -117
  7. package/package.json +61 -61
  8. package/src/$locales/en.json +143 -143
  9. package/src/$locales/fr.json +105 -105
  10. package/src/assets/data/onboardingMessages.json +47 -47
  11. package/src/components/AppBase.vue +1147 -1054
  12. package/src/components/AppBaseButton.vue +87 -87
  13. package/src/components/AppBaseErrorDisplay.vue +438 -438
  14. package/src/components/AppBaseFlipCard.vue +84 -84
  15. package/src/components/AppBaseModule.vue +1636 -1673
  16. package/src/components/AppBasePage.vue +779 -779
  17. package/src/components/AppBasePopover.vue +41 -41
  18. package/src/components/AppCompAudio.vue +234 -234
  19. package/src/components/AppCompBranchButtons.vue +552 -552
  20. package/src/components/AppCompButtonProgress.vue +126 -126
  21. package/src/components/AppCompCarousel.vue +298 -298
  22. package/src/components/AppCompInputCheckBoxNext.vue +195 -195
  23. package/src/components/AppCompInputDropdownNext.vue +159 -159
  24. package/src/components/AppCompInputRadioNext.vue +152 -152
  25. package/src/components/AppCompInputTextNext.vue +106 -106
  26. package/src/components/AppCompInputTextTableNext.vue +141 -141
  27. package/src/components/AppCompInputTextToFillDropdownNext.vue +230 -230
  28. package/src/components/AppCompInputTextToFillNext.vue +171 -171
  29. package/src/components/AppCompJauge.vue +74 -74
  30. package/src/components/AppCompMenu.vue +423 -413
  31. package/src/components/AppCompMenuItem.vue +228 -228
  32. package/src/components/AppCompNavigation.vue +959 -960
  33. package/src/components/AppCompNoteCall.vue +133 -133
  34. package/src/components/AppCompNoteCredit.vue +292 -292
  35. package/src/components/AppCompPlayBar.vue +1218 -1218
  36. package/src/components/AppCompPlayBarNext.vue +2052 -2052
  37. package/src/components/AppCompPlayBarProgress.vue +82 -82
  38. package/src/components/AppCompPopUpNext.vue +503 -503
  39. package/src/components/AppCompQuizNext.vue +2904 -2904
  40. package/src/components/AppCompQuizRecall.vue +276 -276
  41. package/src/components/AppCompSVGNext.vue +347 -347
  42. package/src/components/AppCompSettingsMenu.vue +172 -172
  43. package/src/components/AppCompTableOfContent.vue +387 -387
  44. package/src/components/AppCompTranscript.vue +24 -24
  45. package/src/components/AppCompVideoPlayer.vue +368 -368
  46. package/src/components/AppCompViewDisplay.vue +6 -6
  47. package/src/components/BaseModule.vue +72 -72
  48. package/src/composables/useQuiz.js +206 -206
  49. package/src/externalComps/ModuleView.vue +22 -22
  50. package/src/externalComps/SummaryView.vue +91 -91
  51. package/src/main.js +272 -272
  52. package/src/mixins/$mediaMixins.js +819 -819
  53. package/src/mixins/timerMixin.js +155 -155
  54. package/src/module/stores/appStore.js +901 -893
  55. package/src/module/xapi/ADL.js +380 -376
  56. package/src/module/xapi/Crypto/Hasher.js +241 -241
  57. package/src/module/xapi/Crypto/WordArray.js +278 -278
  58. package/src/module/xapi/Crypto/algorithms/BufferedBlockAlgorithm.js +103 -103
  59. package/src/module/xapi/Crypto/algorithms/C_algo.js +315 -315
  60. package/src/module/xapi/Crypto/algorithms/HMAC.js +9 -9
  61. package/src/module/xapi/Crypto/algorithms/SHA1.js +9 -9
  62. package/src/module/xapi/Crypto/encoders/Base.js +105 -105
  63. package/src/module/xapi/Crypto/encoders/Base64.js +99 -99
  64. package/src/module/xapi/Crypto/encoders/Hex.js +61 -61
  65. package/src/module/xapi/Crypto/encoders/Latin1.js +61 -61
  66. package/src/module/xapi/Crypto/encoders/Utf8.js +45 -45
  67. package/src/module/xapi/Crypto/index.js +53 -53
  68. package/src/module/xapi/Statement/activity.js +47 -47
  69. package/src/module/xapi/Statement/agent.js +55 -55
  70. package/src/module/xapi/Statement/group.js +26 -26
  71. package/src/module/xapi/Statement/index.js +259 -259
  72. package/src/module/xapi/Statement/statement.js +253 -253
  73. package/src/module/xapi/Statement/statementRef.js +23 -23
  74. package/src/module/xapi/Statement/substatement.js +22 -22
  75. package/src/module/xapi/Statement/verb.js +36 -36
  76. package/src/module/xapi/activitytypes.js +17 -17
  77. package/src/module/xapi/launch.js +157 -157
  78. package/src/module/xapi/utils.js +167 -167
  79. package/src/module/xapi/verbs.js +294 -294
  80. package/src/module/xapi/wrapper.js +1963 -1963
  81. package/src/module/xapi/xapiStatement.js +444 -444
  82. package/src/plugins/bus.js +8 -8
  83. package/src/plugins/gsap.js +14 -14
  84. package/src/plugins/helper.js +314 -308
  85. package/src/plugins/i18n.js +44 -44
  86. package/src/plugins/idb.js +227 -219
  87. package/src/plugins/save.js +37 -37
  88. package/src/plugins/scorm.js +287 -287
  89. package/src/plugins/xapi.js +11 -11
  90. package/src/public/index.html +33 -33
  91. package/src/router/index.js +43 -43
  92. package/src/router/routes.js +312 -312
  93. package/src/shared/generalfuncs.js +210 -210
  94. package/src/shared/validators.js +1069 -1069
  95. package/vite.config.js +0 -27
@@ -1,1069 +1,1069 @@
1
- /**
2
- * @description Validator for the content of menu setting file
3
- * @param {String} fName- name of the file for use case
4
- * @param {Object} fData: file's data to validate
5
- * @param {Object} [requiredArgs] list of arguments to include consider in validation ()
6
- */
7
- const validatefileContent = (fName, fData, requiredArgs = {}) => {
8
- let err = null
9
- if (import.meta.env.DEV) {
10
- switch (fName) {
11
- case 'menuSettings': {
12
- const {
13
- keys4Lesson,
14
- keys4ActivityMando,
15
- keys4ActivityOpt,
16
- keys4Anchors
17
- } = requiredArgs
18
-
19
- //*validate that data is an {Object}. if Not send error message
20
- if (fData.constructor !== Object)
21
- err = '💥Invalid file provided for menu settings'
22
-
23
- if (Object.entries(fData).length > 0) {
24
- const content = Object.entries(fData)
25
- if (content.length != keys4Lesson.length) {
26
- err = `!!!! 💥 Missing activity in➡ menu.setting.js \n 🚩Must declare all activity in menu.setting.js`
27
- break
28
- } else {
29
- for (let [index, el] of content.entries()) {
30
- //validate that the content of each entry is valide
31
- if (el[0] !== keys4Lesson[index]) {
32
- err = `!!!! 💥 invalid data provided for key 👉 ${el[0]} 👈 in ➡ menu.setting.js \n 🚩 All activity must be listed and you must have a lesson title`
33
- break
34
- }
35
- }
36
- }
37
-
38
- // Validate that each entry has the required key
39
- if (!err) {
40
- // remove key lessonTitle
41
- content.shift()
42
- for (let el of content) {
43
- const entry = el[1]
44
- const tabEntrykey = Object.keys(entry)
45
-
46
- //Validate that entry has optional key
47
- if (!tabEntrykey.includes(keys4ActivityOpt[0])) {
48
- if (!tabEntrykey.includes(keys4ActivityOpt[1])) {
49
- err = `💥 Missing 👉 ${keys4ActivityOpt[0]} or ${keys4ActivityOpt[1]} 👈 in ${el[0]} in ➡ menu.setting.js \n 🚩One of thess two keys are mandatory : 👉 ${keys4ActivityOpt}`
50
- break
51
- }
52
- }
53
-
54
- //Validate that entry has mandatory key
55
- for (let m of keys4ActivityMando) {
56
- if (!tabEntrykey.includes(m)) {
57
- err = `💥 Missing 👉 ${m} 👈 in ${el[0]} in ➡ menu.setting.js \n 🚩All this key are mandatory : 👉 ${keys4ActivityMando}`
58
- break
59
- } else {
60
- switch (m) {
61
- case 'anchors':
62
- if (entry[m].constructor !== Array)
63
- err = `💥 Invalid anchors declaration for 👉 ${el[0]} 👈 in ➡ menu.setting.j \n 🚩Must be of type {Array}`
64
- else {
65
- const anchors = entry.anchors
66
-
67
- for (let a of anchors) {
68
- //trow error if numbers of keys are not the same as required
69
- const a_numb = anchors.indexOf(a) + 1
70
- if (Object.keys(a).length !== keys4Anchors.length) {
71
- err = `💥 Invalid declaration in 👉anchor ${a_numb}👈 for ➡ ${el[0]} in ➡ menu.setting.js \n 🚩 Allowed indexes are: 👉 ${keys4Anchors}`
72
- break
73
- }
74
- // Validated that required keys condition and type is met
75
- for (let k of keys4Anchors) {
76
- if (!a[k]) {
77
- err = `💥 Missing 👉 ${k} 👈 for anchor ${a_numb} ➡ ${el[0]} ➡ menu.setting.js \n 🚩 Allowed indexes are: 👉 ${keys4Anchors}`
78
- } else if (a[k].constructor !== String) {
79
- err = `💥 Invalid 👉 ${k} 👈 declaration for anchor ${a_numb} ➡ ${el[0]} ➡ menu.setting.js \n 🚩 Must be of type {String}`
80
- }
81
- if (err) break
82
- }
83
- if (err) break
84
- }
85
- }
86
-
87
- break
88
- default:
89
- if (entry[m].constructor !== String)
90
- err = `Invalid 👉 ${m} 👈 declaration for ➡ ${el[0]} in ➡ menu.setting.js \n 🚩 Must be of type {String}`
91
- break
92
- }
93
- }
94
- }
95
- }
96
- }
97
- }
98
- break
99
- }
100
- }
101
- }
102
- return err
103
- }
104
-
105
- /**
106
- * @description Validator for the content of menu setting file
107
- * @param {Object} data- Object definition to validate
108
- **/
109
- const validateVideoData = (data) => {
110
- const errorList = []
111
- if (import.meta.env.DEV) {
112
- let errStringInConsole = null
113
- let errString = null
114
- const expectedKeys = [
115
- 'id',
116
- 'mSources',
117
- 'mSubtitles',
118
- 'mPoster',
119
- 'mTranscript'
120
- ]
121
-
122
- if (!data || data.constructor !== Object || Object.keys(data).length < 1) {
123
- errStringInConsole = `\n 💥 Invalid declaration for video element`
124
- console.warn(
125
- `%c WARNING!>>> VIDEO: ${errStringInConsole}`,
126
- 'background: orange; color: white; display: block; border-radius:5px; margin:5px;'
127
- )
128
- errString = `Declaration invalide pour Objet video.`
129
- errorList.push(errString)
130
- }
131
- //Must have mSources
132
- if (!data['mSources']) {
133
- errStringInConsole = ` Missing 👉 mSources 👈 declaration for video element`
134
-
135
- errString = `l'Attribut <b>mSources</b> pour l'Objet video n'est pas defini. `
136
- console.warn(
137
- `%c WARNING!>>> ${errStringInConsole}`,
138
- 'background: orange; color: white; display: block; border-radius:5px; margin:5px;'
139
- )
140
- errorList.push(errString)
141
- }
142
- //Must have id
143
- if (!data['id']) {
144
- errStringInConsole = ` Missing 👉 id 👈 declaration for video element`
145
-
146
- errString = `l'Attribut <b>id</b> pour l'objet video n'est pas defini. `
147
- console.warn(
148
- `%c WARNING!>>> ${errStringInConsole}`,
149
- 'background: orange; color: white; display: block; border-radius:5px; margin:5px;'
150
- )
151
- errorList.push(errString)
152
- }
153
- //Start validation of keys in data
154
- if (!errString) {
155
- expectedKeys.forEach((k) => {
156
- if (!data[k] && k !== 'mSources') return
157
-
158
- switch (k) {
159
- case 'id':
160
- if (data['id'].constructor !== String || data['id'].length < 1) {
161
- errStringInConsole =
162
- '\n 💥 Invalid type declaration for id.\n 🚩 Must be of type Array'
163
-
164
- errString = `l'Attribut <b>id</b> pour le media doit être de type <i>String</i>`
165
-
166
- errorList.push(errString)
167
- console.warn(
168
- `%c WARNING!>>> ${errStringInConsole}`,
169
- 'background: orange; color: white; display: block; border-radius:5px; margin:5px;'
170
- )
171
- }
172
- break
173
- case 'mSources':
174
- if (
175
- data['mSources'].constructor !== Array ||
176
- data['mSources'].length < 1
177
- ) {
178
- errStringInConsole =
179
- '\n 💥 Invalid type declaration for mSources.\n 🚩 Must be of type Array'
180
-
181
- errString = `l'Attribut 👉 mSources 👈 pour le media doit être de type Array`
182
-
183
- errorList.push(errString)
184
- console.warn(
185
- `%c WARNING!>>> ${errStringInConsole}`,
186
- 'background: orange; color: white; display: block; border-radius:5px; margin:5px;'
187
- )
188
- }
189
- break
190
-
191
- case 'mSubtitles':
192
- {
193
- //Validate required keys in Subtitle definition
194
- let expectedKeys = ['label', 'src', 'srclang']
195
- //we only accept one subtitle and must be defined as an Object with 3 keys
196
- if (
197
- data['mSubtitles'].constructor !== Array ||
198
- !data['mSubtitles'].length
199
- ) {
200
- errStringInConsole = `\n 💥 Invalid type declaration for mSubtitles.\n 🚩 Must be of type Array with at list one Object defined with: ${expectedKeys}`
201
-
202
- errString = `l'Attribut 👉 mSubtitles 👈 doit être de type Array avec au moins un Objet: {${expectedKeys}} `
203
-
204
- console.warn(
205
- `%c WARNING!>>> ${errStringInConsole}`,
206
- 'background: orange; color: white; display: block; border-radius:5px; margin:5px;'
207
- )
208
-
209
- return errorList.push(errString)
210
- }
211
- //Validate definition for each Subtitle Object
212
- for (const obj of data['mSubtitles']) {
213
- const objIndex = data['mSubtitles'].indexOf(obj)
214
- expectedKeys.forEach((expected) => {
215
- if (!obj[expected]) {
216
- errStringInConsole = `\n 💥 Missing key 👉 ${expected} 👈 for mSubtitles No.${
217
- objIndex + 1
218
- }.\n 🚩 required keys are: ${expectedKeys} `
219
-
220
- errString = `l'Attribut 👉 ${expected} 👈 pour le sous-titre No.${
221
- objIndex + 1
222
- } n'est pas défini`
223
-
224
- console.warn(
225
- `%c WARNING!>>> ${errStringInConsole}`,
226
- 'background: orange; color: white; display: block; border-radius:5px; margin:5px;'
227
- )
228
- return errorList.push(errString)
229
- }
230
-
231
- // Only none empty String type Accepted
232
- if (
233
- obj[expected].constructor === String &&
234
- obj[expected].trim().length
235
- )
236
- return
237
-
238
- errStringInConsole = `\n 💥 Invalid type declaration for 👉${expected}👈 in mSubtitles No.${
239
- objIndex + 1
240
- }.\n 🚩 Must be none-empty String `
241
-
242
- errString = `l'Attribut 👉${expected}👈 du sous-titre No.${
243
- objIndex + 1
244
- } doit être de type String et ne peut pas être vide. `
245
-
246
- console.warn(
247
- `%c WARNING!>>> ${errStringInConsole}`,
248
- 'background: orange; color: white; display: block; border-radius:5px; margin:5px;'
249
- )
250
-
251
- errorList.push(errString)
252
- })
253
- }
254
- }
255
- break
256
- case 'mPoster':
257
- //Only type String allowed and must not be empty
258
- if (
259
- data['mPoster'] &&
260
- data['mPoster'].constructor == String &&
261
- data['mPoster'].trim().length
262
- )
263
- return
264
-
265
- errStringInConsole = `\n 💥 Invalid type declaration for 👉 mPoster 👈.\n 🚩 Must be none-empty String `
266
-
267
- errString = `l'Attribut 👉 mPoster 👈 doit être de type String et ne peut pas être vide. `
268
-
269
- errorList.push(errString)
270
- console.warn(
271
- `%c WARNING!>>> VIDEO: ${errStringInConsole}`,
272
- 'background: orange; color: white; display: block; border-radius:5px; margin:5px;'
273
- )
274
-
275
- break
276
- case 'mTranscript':
277
- //Only type String allowed and must not be empty
278
- if (
279
- data['mTranscript'] &&
280
- data['mTranscript'].constructor == String &&
281
- data['mTranscript'].trim().length
282
- )
283
- return
284
-
285
- errStringInConsole = `\n 💥 Invalid type declaration for 👉 mTranscript 👈 .\n 🚩 Must be none-empty String `
286
-
287
- errString = `l'Attribut 👉 mTranscript 👈 doit être de type String et ne peut pas être vide. `
288
-
289
- console.warn(
290
- `%c WARNING!>>> VIDEO: ${errStringInConsole}`,
291
- 'background: orange; color: white; display: block; border-radius:5px; margin:5px;'
292
- )
293
- errorList.push(errString)
294
-
295
- break
296
- }
297
- })
298
- }
299
- }
300
- return errorList
301
- }
302
-
303
- /**
304
- * @description Validator for the content of audio props
305
- * @param {Object} data- Object definition to validate
306
- **/
307
- const validateAudioData = (data) => {
308
- const errorList = []
309
- let currentProperties = Object.getOwnPropertyNames(data)
310
- if (process.env.NODE_ENV === 'development') {
311
- //errorList.push('test')
312
-
313
- const requiredProperties = ['id', 'mTitle', 'mSources', 'mTranscript']
314
-
315
- const optionalProperties = ['mPoster', 'mAlt']
316
-
317
- const allProperties = [
318
- ...requiredProperties,
319
- ...optionalProperties,
320
- ...['__ob__']
321
- ]
322
-
323
- let errStringInConsole = null
324
- let errString = null
325
-
326
- //** Validate if data exist and is an object**/
327
- if (!data || data.constructor !== Object || Object.keys(data).length < 1) {
328
- errStringInConsole = `\n 💥 Invalid declaration for audio element`
329
- console.warn(
330
- `%c WARNING!>>> AUDIO: ${errStringInConsole}`,
331
- 'background: orange; color: white; display: block; border-radius:5px; margin:5px;'
332
- )
333
- errString = `Déclaration invalide pour Objet audData. Ce doit être un objet non vide.`
334
- errorList.push(errString)
335
- return errorList
336
- }
337
- //** Validate if all the properties are right**/
338
- let wrongProperties = checkerWrong(allProperties, currentProperties)
339
- if (wrongProperties.length > 0) {
340
- console.warn(
341
- `%c WARNING!>>> AppCompAudio : audData property ${wrongProperties} invalid. Required properties: ${requiredProperties} . Optional properties: ${optionalProperties}`,
342
- 'background: orange; color: white; display: block; margin:5px;'
343
- )
344
- errString = `Propriété invalide pour audData: ${wrongProperties}. Les propriétés requises sont: ${requiredProperties} et les propriétés facultatives sont: ${optionalProperties}`
345
- errorList.push(errString)
346
- return errorList
347
- }
348
-
349
- //** Validate if all the required properties are in the data */
350
- let missingRequired = checkerMissing(requiredProperties, currentProperties)
351
- if (missingRequired.length > 0) {
352
- console.warn(
353
- `%c WARNING!>>> AppCompAudio : audData missing required ${missingRequired} property. Required properties: ${requiredProperties} . Optional properties: ${optionalProperties}`,
354
- 'background: orange; color: white; display: block; margin:5px;'
355
- )
356
- errString = `Propriété requise manquante pour audData: <b>${missingRequired}</b>. Les propriétés requises sont: <i>${requiredProperties}</i> et les propriétés facultatives sont: <i>${optionalProperties}</i>`
357
- errorList.push(errString)
358
- return errorList
359
- }
360
- /***Validate data values */
361
- if (errorList.length == 0) {
362
- let invalidString = []
363
- let invalidArray = []
364
- let invalidProperties = []
365
- currentProperties.forEach((p) => {
366
- switch (p) {
367
- case 'mTitle':
368
- case 'mTranscript':
369
- case 'mPoster':
370
- case 'mAlt':
371
- if (data[p] && data[p].constructor == String) {
372
- data[p].trim().length == 0 ? invalidString.push(p) : ''
373
- } else {
374
- invalidString.push(p)
375
- }
376
- break
377
- case 'mSources': {
378
- if (data[p] && data[p].constructor == Array) {
379
- data[p].length == 0 ? invalidArray.push(p) : ''
380
- } else {
381
- invalidArray.push(p)
382
- }
383
- if (invalidArray.length === 0) {
384
- //Valider les attributs de mSources
385
- for (let i in data[p]) {
386
- let object = data[p][i]
387
- if ('src' in object && 'type' in object) {
388
- if (
389
- object['src'].constructor != String &&
390
- object['type'].constructor != String
391
- ) {
392
- invalidProperties.push(p)
393
- } else {
394
- object['src'].trim().length == 0
395
- ? invalidString.push(p)
396
- : ''
397
- object['type'].trim().length == 0
398
- ? invalidString.push(p)
399
- : ''
400
- }
401
- } else {
402
- invalidProperties.push(p)
403
- }
404
- }
405
- }
406
- break
407
- }
408
- }
409
- })
410
- //Display error for each type
411
- //String
412
- let sL = invalidString.length
413
- if (sL > 0) {
414
- errStringInConsole = `\n 💥 Invalid value type for 👉${invalidString}👈 \n 🚩 Must be none-empty String `
415
-
416
- errString = `${sL > 1 ? 'Les ' : "L'"}attribut${
417
- sL > 1 ? 's ' : ''
418
- } 👉${invalidString}👈 doi${
419
- sL > 1 ? 'ven' : ''
420
- }t être de type String et ne peu${sL > 1 ? 'ven' : ''}t pas être vide. `
421
-
422
- console.warn(
423
- `%c WARNING!>>> ${errStringInConsole}`,
424
- 'background: orange; color: white; display: block; border-radius:5px; margin:5px;'
425
- )
426
- errorList.push(errString)
427
- }
428
- //Array
429
- let aL = invalidArray.length
430
- if (aL > 0) {
431
- errStringInConsole = `\n 💥 Invalid value type for 👉${invalidArray}👈 \n 🚩 Must be none-empty Array`
432
-
433
- errString = `${aL > 1 ? 'Les ' : "L'"}attribut${
434
- aL > 1 ? 's ' : ''
435
- } 👉${invalidArray}👈 doi${
436
- sL > 1 ? 'ven' : ''
437
- }t être de type Array et ne peu${aL > 1 ? 'ven' : ''}t pas être vide. `
438
-
439
- console.warn(
440
- `%c WARNING!>>> ${errStringInConsole}`,
441
- 'background: orange; color: white; display: block; border-radius:5px; margin:5px;'
442
- )
443
- errorList.push(errString)
444
- }
445
- let pL = invalidProperties.length
446
- if (pL > 0) {
447
- errStringInConsole = `\n 💥 Invalid value type for 👉src and/or type👈 in mSources \n 🚩 They are required and must be none-empty strings`
448
-
449
- errString = `${pL > 1 ? 'Les ' : "L'"}attribut${
450
- pL > 1 ? 's ' : ''
451
- } 👉src and/or type👈 de mSources doi${
452
- sL > 1 ? 'ven' : ''
453
- }t être de type String et ne peu${pL > 1 ? 'ven' : ''}t pas être vide. `
454
-
455
- console.warn(
456
- `%c WARNING!>>> ${errStringInConsole}`,
457
- 'background: orange; color: white; display: block; border-radius:5px; margin:5px;'
458
- )
459
- errorList.push(errString)
460
- }
461
- }
462
- /*if (process.env.NODE_ENV === 'development') {
463
- let errStringInConsole = null
464
- let errString = null
465
- const expectedKeys = ['mSources', 'mSubtitles', 'mPoster', 'mTranscript']
466
-
467
- if (!data || data.constructor !== Object || Object.keys(data).length < 1) {
468
- errStringInConsole = `\n 💥 Invalid declaration for video element`
469
- console.warn(
470
- `%c WARNING!>>> VIDEO: ${errStringInConsole}`,
471
- 'background: orange; color: white; display: block; border-radius:5px; margin:5px;'
472
- )
473
- errString = `Declaration invalide pour Objet video.`
474
- errorList.push(errString)
475
- }
476
-
477
- if (!data['mSources']) {
478
- errStringInConsole = ` Missing 👉 mSources 👈 declaration for video element`
479
-
480
- errString = `l'Attribut 👉 mSources 👈 pour l'Objet video n'est pas defini. `
481
- console.warn(
482
- `%c WARNING!>>> ${errStringInConsole}`,
483
- 'background: orange; color: white; display: block; border-radius:5px; margin:5px;'
484
- )
485
- errorList.push(errString)
486
- }
487
-
488
- //Start validation of keys in data
489
- if (!errString) {
490
- expectedKeys.forEach((k) => {
491
- if (!data[k] && k !== 'mSources') return
492
-
493
- switch (k) {
494
- case 'mSources':
495
- if (
496
- data['mSources'].constructor !== Array ||
497
- data['mSources'].length < 1
498
- ) {
499
- errStringInConsole =
500
- '\n 💥 Invalid type declaration for mSources.\n 🚩 Must be of type Array'
501
-
502
- errString = `l'Attribut 👉 mSources 👈 pour le media doit être de type Array`
503
-
504
- errorList.push(errString)
505
- console.warn(
506
- `%c WARNING!>>> ${errStringInConsole}`,
507
- 'background: orange; color: white; display: block; border-radius:5px; margin:5px;'
508
- )
509
- }
510
- break
511
-
512
- case 'mSubtitles':
513
- {
514
- //Validate required keys in Subtitle definition
515
- let expectedKeys = ['label', 'src', 'srclang']
516
- //we only accept one subtitle and must be defined as an Object with 3 keys
517
- if (
518
- data['mSubtitles'].constructor !== Array ||
519
- !data['mSubtitles'].length
520
- ) {
521
- errStringInConsole = `\n 💥 Invalid type declaration for mSubtitles.\n 🚩 Must be of type Array with at list one Object defined with: ${expectedKeys}`
522
-
523
- errString = `l'Attribut 👉 mSubtitles 👈 doit être de type Array avec au moins un Objet: {${expectedKeys}} `
524
-
525
- console.warn(
526
- `%c WARNING!>>> ${errStringInConsole}`,
527
- 'background: orange; color: white; display: block; border-radius:5px; margin:5px;'
528
- )
529
-
530
- return errorList.push(errString)
531
- }
532
- //Validate definition for each Subtitle Object
533
- for (const obj of data['mSubtitles']) {
534
- const objIndex = data['mSubtitles'].indexOf(obj)
535
- expectedKeys.forEach((expected) => {
536
- if (!obj[expected]) {
537
- errStringInConsole = `\n 💥 Missing key 👉 ${expected} 👈 for mSubtitles No.${objIndex +
538
- 1}.\n 🚩 required keys are: ${expectedKeys} `
539
-
540
- errString = `l'Attribut 👉 ${expected} 👈 pour le sous-titre No.${objIndex +
541
- 1} n'est pas défini`
542
-
543
- console.warn(
544
- `%c WARNING!>>> ${errStringInConsole}`,
545
- 'background: orange; color: white; display: block; border-radius:5px; margin:5px;'
546
- )
547
- return errorList.push(errString)
548
- }
549
-
550
- // Only none empty String type Accepted
551
- if (
552
- obj[expected].constructor === String &&
553
- obj[expected].trim().length
554
- )
555
- return
556
-
557
- errStringInConsole = `\n 💥 Invalid type declaration for 👉${expected}👈 in mSubtitles No.${objIndex +
558
- 1}.\n 🚩 Must be none-empty String `
559
-
560
- errString = `l'Attribut 👉${expected}👈 du sous-titre No.${objIndex +
561
- 1} doit être de type String et ne peut pas être vide. `
562
-
563
- console.warn(
564
- `%c WARNING!>>> ${errStringInConsole}`,
565
- 'background: orange; color: white; display: block; border-radius:5px; margin:5px;'
566
- )
567
-
568
- errorList.push(errString)
569
- })
570
- }
571
- }
572
- break
573
- case 'mPoster':
574
- //Only type String allowed and must not be empty
575
- if (
576
- data['mPoster'] &&
577
- data['mPoster'].constructor == String &&
578
- data['mPoster'].trim().length
579
- )
580
- return
581
-
582
- errStringInConsole = `\n 💥 Invalid type declaration for 👉 mPoster 👈.\n 🚩 Must be none-empty String `
583
-
584
- errString = `l'Attribut 👉 mPoster 👈 doit être de type String et ne peut pas être vide. `
585
-
586
- errorList.push(errString)
587
- console.warn(
588
- `%c WARNING!>>> VIDEO: ${errStringInConsole}`,
589
- 'background: orange; color: white; display: block; border-radius:5px; margin:5px;'
590
- )
591
-
592
- break
593
- case 'mTranscript':
594
- //Only type String allowed and must not be empty
595
- if (
596
- data['mTranscript'] &&
597
- data['mTranscript'].constructor == String &&
598
- data['mTranscript'].trim().length
599
- )
600
- return
601
-
602
- errStringInConsole = `\n 💥 Invalid type declaration for 👉 mTranscript 👈 .\n 🚩 Must be none-empty String `
603
-
604
- errString = `l'Attribut 👉 mTranscript 👈 doit être de type String et ne peut pas être vide. `
605
-
606
- console.warn(
607
- `%c WARNING!>>> VIDEO: ${errStringInConsole}`,
608
- 'background: orange; color: white; display: block; border-radius:5px; margin:5px;'
609
- )
610
- errorList.push(errString)
611
-
612
- break
613
- }
614
- })
615
- }
616
- }*/
617
- }
618
- return errorList
619
- }
620
- //Get all the invalids properties from the object
621
- /*Add element from target array that are NOT in arr to the wrongArray*/
622
- const checkerWrong = (arr, target) => {
623
- let wrongArray = []
624
- target.every((v) => {
625
- if (arr.includes(v)) {
626
- return true
627
- } else {
628
- wrongArray.push(v)
629
- return true
630
- }
631
- })
632
- return wrongArray
633
- }
634
- //Get all the required properties that are missing from the object
635
- /*Add element from the arr that are NOT in target arr to the missingArray*/
636
- const checkerMissing = (arr, target) => {
637
- let missingArray = []
638
- arr.every((v) => {
639
- if (target.includes(v)) {
640
- return true
641
- } else {
642
- missingArray.push(v)
643
- return true
644
- }
645
- })
646
- return missingArray
647
- }
648
-
649
- const ERR_TYPE = {
650
- err0: `\n 💥 Missing \x1B[1m$attr$ \x1B[0mfor $comp$. \x1B[1m$attr$ \x1B[0m should be provided with following attributes: \x1B[1m{$data$}`,
651
- err1: `\n 💥 Invalid declaration for \x1B[1m$wrd$ \x1B[0m object`,
652
- err2: `\n 💥 Invalid type declaration for 👉\x1B[1m$attr$ \x1B[0m👈 in \x1B[1m$el$\x1B[0m. Expected is \x1B[3m$type$ \x1B[0mtype with some value`,
653
- err3: `\n 💥 Missing required argument 👉\x1B[1m$key$\x1B[0m👈 in \x1B[1m$el$\x1B[0m. Required arguments are: \x1B[1m$args$`,
654
- err4: `\n 💥 Missing required argument 👉\x1B[1m$key$\x1B[0m👈 in \x1B[1m$el$\x1B[0m. Required arguments are: \x1B[1m$args$`
655
- }
656
-
657
- const ERR_TYPE_MSG = {
658
- err0: `\n Données manquantes pour <span style='text-transform: uppercase;'>$comp$</span>. Assurez-vous que le composant reçoit l'attribut <b>$attr$</b> avec des données pour: <b>$data$</b>`,
659
- err1: `\n Déclaration invalide pour <b>$wrd$</b>. Assurez-vous que l'application a du data.`,
660
- err2: `\n Vous avez une declaration invalide dans <b>$attr$</b>. 👉<b>$el$</b>👈 n'accepte que le type <i>$type$</i> et ne peut pas être vide`,
661
- err3: `\n L'attribut 👉<b>$key$</b>👈 est manquant dans <b>$el$</b>. Les attributs requis sont: <b>$args$</b>`
662
- }
663
-
664
- /**
665
- * @description Validator for the content of app data.
666
- * App data is used as setting for the application
667
- * @param {Object} data - the Object definition to validate
668
- * @param {Boolean} silent - if Validator should diplay error in console
669
- *
670
- **/
671
-
672
- const validateAppContent = (data, silent = false) => {
673
- let errorInConsole = []
674
- let errorList = []
675
-
676
- const requiredArgs = [
677
- 'lang',
678
- 'specification',
679
- 'id',
680
- 'crs_id',
681
- 'idb_id',
682
- 'no_menu',
683
- 'is_single_activity',
684
- 'auto_next_activity'
685
- ]
686
-
687
- //Validate not empty data
688
- if (Object.keys(data).length == 0) {
689
- const reg = /(\$comp\$)|(\$data\$)|(\$attr\$)/g
690
-
691
- errorInConsole.push(
692
- ERR_TYPE.err0.replace(reg, (e) => {
693
- if (e == '$comp$') return 'app-base'
694
- if (e == '$data$') return requiredArgs.toString().replaceAll(',', ', ')
695
- if (e == '$attr$') return 'app-config'
696
- })
697
- )
698
-
699
- errorList.push(
700
- ERR_TYPE_MSG.err0.replace(reg, (e) => {
701
- if (e == '$comp$') return 'app-base'
702
- if (e == '$data$') return requiredArgs.toString().replaceAll(',', ', ')
703
- if (e == '$attr$') return 'app-config'
704
- })
705
- )
706
-
707
- console.warn(errorInConsole[0])
708
-
709
- return errorList
710
- }
711
-
712
- let stringType = ['lang', 'specification', 'id', 'crs_id', 'idb_id']
713
- let boolType = [
714
- 'no_menu',
715
- 'is_single_activity',
716
- 'auto_next_activity',
717
- 'remote'
718
- ]
719
- let objectType = ['actor', 'linkedResource']
720
- let optionalArgs = ['remote', 'actor', 'linkedResource']
721
-
722
- const { errorInConsole: errCons, errorList: errList } = validateObjType(
723
- data,
724
- {
725
- stringType,
726
- boolType,
727
- objectType
728
- },
729
- optionalArgs,
730
- 'App.vue'
731
- )
732
-
733
- errorList = [...errorList, ...errList]
734
- errorInConsole = [...errorInConsole, ...errCons]
735
-
736
- //===========Optional Keys should be of correct type when declared =================//
737
- // Has actor defined
738
- if (data['actor']) {
739
- let { errorInConsole: err1, errorList: err2 } = validateObjType(
740
- data['actor'],
741
- {
742
- stringType: ['name', 'mbox']
743
- },
744
- 'actor'
745
- )
746
-
747
- errorList = [...errorList, ...err2]
748
- errorInConsole = [...errorInConsole, ...err1]
749
- }
750
- // Has LinkedResource defined
751
- if (data['linkedResource']) {
752
- let { errorInConsole: err1, errorList: err2 } = validateObjType(
753
- data['linkedResource'],
754
- {
755
- stringType: ['url', 'id']
756
- },
757
- 'linkedResource'
758
- )
759
-
760
- errorList = [...errorList, ...err2]
761
- errorInConsole = [...errorInConsole, ...err1]
762
- }
763
- // Has endpointConfig defined
764
- if (data['endpointConfig']) {
765
- let { errorInConsole: err1, errorList: err2 } = validateObjType(
766
- data['endpointConfig'],
767
- {
768
- stringType: ['auth', 'endpoint']
769
- },
770
- 'endpointConfig'
771
- )
772
- errorList = [...errorList, ...err2]
773
- errorInConsole = [...errorInConsole, ...err1]
774
- }
775
- //================== END Optional Keys ====================//
776
-
777
- //Should display error to console
778
- if (errorList.length && !silent) {
779
- let txt = '⚠️ You have the following Errors:'
780
- console.group(`%c ${txt}`, 'background:#ffc13a7d')
781
- errorInConsole.forEach((err) => console.warn(err))
782
- console.groupEnd()
783
- }
784
-
785
- return errorList
786
- }
787
-
788
- /**
789
- * @description - Method to validate that given object attributes hold expected types
790
- * @param {Object} Obj - object to validate
791
- * @param {Object} Args - List of expected type groups - each type group must be an array of attributes with the same type
792
- * @param {Array} notRequiredArgs - list of field that should be considered as optional in the object. Will not give error if not * provided but will be validated if they are present with wrong type or empty
793
- * @param {Array} compName - Name of the component- will be display in error message
794
- * @param {Array} err - list off errors to be added to
795
- * @return {Object} list of errors - {errorInConsole, errorList} : errorlist can be used to display messages on template and
796
- * errorInConsole to display messages in browser console
797
- * @exemple - Given $user= {name:'toto', username:'totoEscargot', id:'id001', age:23, books:['one', 'two', 'three'] }
798
- * Use validator on $user: validateObjType($user, {stringType:['name', 'username' , 'id'], numbType:['age'], arrayType:['books']})
799
- * Will fail if any listed attribute not in $user or have wrong value. Error messages will be in console
800
- *
801
- */
802
-
803
- const validateObjType = (
804
- Obj,
805
- Args = {
806
- boolType: null,
807
- arrayType: null,
808
- stringType: null,
809
- objectType: null,
810
- numbType: null
811
- },
812
- notRequiredArgs = null,
813
- compName = 'component',
814
- err = null
815
- ) => {
816
- let errorInConsole = err && err.errorInConsole ? err.errorInConsole : []
817
- let errorList = err && err.errorList ? err.errorLIst : []
818
- let optionalArgs =
819
- notRequiredArgs && notRequiredArgs.length ? notRequiredArgs : []
820
- //=====Expected Arguments validation =================//
821
- //Should have an object argument
822
- if (!Obj) throw new Error(`No valid arguments provided`)
823
-
824
- //validate Args Keys type
825
- for (const _type in Args) {
826
- // Should be a required type
827
- if (
828
- ![
829
- 'boolType',
830
- 'arrayType',
831
- 'stringType',
832
- 'objectType',
833
- 'numbType'
834
- ].includes(_type)
835
- )
836
- throw new Error(`Unknown types declaration : ${_type}`)
837
-
838
- if (Args[_type] && Args[_type].length) {
839
- for (let el of Args[_type]) {
840
- //Check that each given element is a string
841
- if (el.constructor !== String)
842
- throw new Error(
843
- `Invalid type detected in ${JSON.stringify(
844
- Args[_type]
845
- )}. Item ${Args[_type].indexOf(el) + 1} should be a String`
846
- )
847
-
848
- let reg = /(\$el\$)|(\$type\$)|(\$attr\$)/g
849
-
850
- let isOptionalArg = optionalArgs.includes(el) ? true : false
851
-
852
- switch (true) {
853
- // Check That each given element exist in data if not optional
854
- case Obj[el] === undefined && !isOptionalArg: {
855
- reg = /(\$key\$)|(\$el\$)|(\$args\$)/g
856
- const reg2 = /\[|\]|/g
857
-
858
- errorInConsole.push(
859
- ERR_TYPE.err3.replace(reg, (e) => {
860
- if (e == '$key$') return el
861
- if (e == '$el$') return compName
862
- if (e == '$args$') return JSON.stringify(Args[_type])
863
- })
864
- )
865
-
866
- errorList.push(
867
- ERR_TYPE_MSG.err3.replace(reg, (e) => {
868
- if (e == '$key$') return el
869
- if (e == '$el$') return compName || 'Composant'
870
- if (e == '$args$')
871
- return JSON.stringify(Args[_type]).replaceAll(reg2, '')
872
- })
873
- )
874
- break
875
- }
876
- //Should have Correct Types $attr$ $el$ $type$
877
- case _type == 'boolType' &&
878
- Obj[el] !== undefined &&
879
- Obj[el].constructor !== Boolean:
880
- errorInConsole.push(
881
- ERR_TYPE.err2.replace(reg, (e) => {
882
- if (e == '$attr$') return compName || 'Composant'
883
- if (e == '$el$') return el
884
- if (e == '$type$') return 'Boolean'
885
- })
886
- )
887
- errorList.push(
888
- ERR_TYPE_MSG.err2.replace(reg, (e) => {
889
- if (e == '$attr$') return compName || 'Composant'
890
- if (e == '$el$') return el
891
- if (e == '$type$') return 'Boolean'
892
- })
893
- )
894
- break
895
-
896
- case _type == 'stringType' &&
897
- Obj[el] !== undefined &&
898
- (Obj[el].constructor !== String || !Obj[el].trim().length):
899
- errorInConsole.push(
900
- ERR_TYPE.err2.replace(reg, (e) => {
901
- if (e == '$attr$') return compName || 'Composant'
902
- if (e == '$el$') return el
903
- if (e == '$type$') return 'String'
904
- })
905
- )
906
- errorList.push(
907
- ERR_TYPE_MSG.err2.replace(reg, (e) => {
908
- if (e == '$attr$') return compName || 'Composant'
909
- if (e == '$el$') return el
910
- if (e == '$type$') return 'String'
911
- })
912
- )
913
- break
914
-
915
- case _type == 'arrayType' &&
916
- Obj[el] !== undefined &&
917
- (Obj[el].constructor !== Array || !Obj[el].length):
918
- errorInConsole.push(
919
- ERR_TYPE.err2.replace(reg, (e) => {
920
- if (e == '$attr$') return compName || 'Composant'
921
- if (e == '$el$') return el
922
- if (e == '$type$') return 'Array'
923
- })
924
- )
925
- errorList.push(
926
- ERR_TYPE_MSG.err2.replace(reg, (e) => {
927
- if (e == '$attr$') return compName || 'Composant'
928
- if (e == '$el$') return el
929
- if (e == '$type$') return 'Array'
930
- })
931
- )
932
- break
933
-
934
- case _type == 'numberType' &&
935
- Obj[el] !== undefined &&
936
- Obj[el].constructor !== Number:
937
- errorInConsole.push(
938
- ERR_TYPE.err2.replace(reg, (e) => {
939
- if (e == '$attr$') return compName || 'Composant'
940
- if (e == '$el$') return el
941
- if (e == '$type$') return 'Number'
942
- })
943
- )
944
- errorList.push(
945
- ERR_TYPE_MSG.err2.replace(reg, (e) => {
946
- if (e == '$attr$') return compName || 'Composant'
947
- if (e == '$el$') return el
948
- if (e == '$type$') return 'Number'
949
- })
950
- )
951
- break
952
-
953
- case _type == 'objectType' &&
954
- Obj[el] !== undefined &&
955
- Obj[el].constructor !== Object:
956
- errorInConsole.push(
957
- ERR_TYPE.err2.replace(reg, (e) => {
958
- if (e == '$attr$') return compName || 'Composant'
959
- if (e == '$el$') return el
960
- if (e == '$type$') return 'Object'
961
- })
962
- )
963
- errorList.push(
964
- ERR_TYPE_MSG.err2.replace(reg, (e) => {
965
- if (e == '$attr$') return compName || 'Composant'
966
- if (e == '$el$') return el
967
- if (e == '$type$') return 'Object'
968
- })
969
- )
970
- break
971
- }
972
- }
973
- }
974
- }
975
-
976
- return { errorInConsole, errorList }
977
- }
978
- /**
979
- * @description - Method validate the definition of SVG data.
980
- * @param {Array || Object } SVGData - the data defining the SVG to render
981
- * @return true - if valid
982
- * */
983
-
984
- const validateSvgDefinition = (SVGData) => {
985
- //Should be Array of Object
986
- if (SVGData.constructor !== Array && SVGData.constructor !== Object)
987
- throw new Error('Unsupported Type for SVG data')
988
- let Errors = []
989
- let SVGDef = SVGData.constructor == Object ? new Array(SVGData) : SVGData
990
- //Should validate the entries for each SVG definition as the required entries
991
-
992
- for (const s_def of SVGDef) {
993
- let i = SVGDef.indexOf(s_def)
994
- let stringType = ['id', 'viewBox']
995
- let arrayType = ['paths']
996
- let { errorInConsole: errCons } = validateObjType(
997
- s_def,
998
- {
999
- stringType,
1000
- arrayType
1001
- },
1002
- 'viewBox',
1003
- `SVG ${i + 1}`
1004
- )
1005
- Errors.push(...errCons)
1006
- if (errCons.length) {
1007
- errCons.forEach((err) => console.warn(err))
1008
- break
1009
- }
1010
-
1011
- //Should validate that each element in the path attributes is an object of type string and has the id attribute
1012
-
1013
- for (const _path of s_def.paths) {
1014
- let index = s_def.paths.indexOf(_path)
1015
- if (_path.constructor !== Object)
1016
- throw Error(
1017
- `Unexpected definition for path ${index + 1} in SVG ${i + 1}. Expecting Object but received ${typeof _path}`
1018
- )
1019
-
1020
- let stringType = ['d']
1021
-
1022
- let { errorInConsole: errCons } = validateObjType(
1023
- _path,
1024
- {
1025
- stringType
1026
- },
1027
- null,
1028
- `SVG path ${index + 1}`
1029
- )
1030
- Errors.push(...errCons)
1031
- if (errCons.length) {
1032
- errCons.forEach((err) => console.warn(err))
1033
- break
1034
- }
1035
-
1036
- //validate each entries in path
1037
- for (const _key in _path) {
1038
- if (_key == 'd') continue //skip
1039
- //all keys in path should be of type String and not empty
1040
- let stringType = [_key]
1041
-
1042
- let { errorInConsole: errCons } = validateObjType(
1043
- _path,
1044
- {
1045
- stringType
1046
- },
1047
- null,
1048
- `SVG path ${index + 1}`
1049
- )
1050
- Errors.push(...errCons)
1051
- if (errCons.length) {
1052
- errCons.forEach((err) => console.log(err))
1053
- break
1054
- }
1055
- }
1056
- }
1057
- }
1058
-
1059
- if (Errors.length) throw new Error('Error SVG')
1060
- return true
1061
- }
1062
-
1063
- export {
1064
- validateVideoData,
1065
- validateAudioData,
1066
- validatefileContent,
1067
- validateAppContent,
1068
- validateSvgDefinition
1069
- }
1
+ /**
2
+ * @description Validator for the content of menu setting file
3
+ * @param {String} fName- name of the file for use case
4
+ * @param {Object} fData: file's data to validate
5
+ * @param {Object} [requiredArgs] list of arguments to include consider in validation ()
6
+ */
7
+ const validatefileContent = (fName, fData, requiredArgs = {}) => {
8
+ let err = null
9
+ if (import.meta.env.DEV) {
10
+ switch (fName) {
11
+ case 'menuSettings': {
12
+ const {
13
+ keys4Lesson,
14
+ keys4ActivityMando,
15
+ keys4ActivityOpt,
16
+ keys4Anchors
17
+ } = requiredArgs
18
+
19
+ //*validate that data is an {Object}. if Not send error message
20
+ if (fData.constructor !== Object)
21
+ err = '💥Invalid file provided for menu settings'
22
+
23
+ if (Object.entries(fData).length > 0) {
24
+ const content = Object.entries(fData)
25
+ if (content.length != keys4Lesson.length) {
26
+ err = `!!!! 💥 Missing activity in➡ menu.setting.js \n 🚩Must declare all activity in menu.setting.js`
27
+ break
28
+ } else {
29
+ for (let [index, el] of content.entries()) {
30
+ //validate that the content of each entry is valide
31
+ if (el[0] !== keys4Lesson[index]) {
32
+ err = `!!!! 💥 invalid data provided for key 👉 ${el[0]} 👈 in ➡ menu.setting.js \n 🚩 All activity must be listed and you must have a lesson title`
33
+ break
34
+ }
35
+ }
36
+ }
37
+
38
+ // Validate that each entry has the required key
39
+ if (!err) {
40
+ // remove key lessonTitle
41
+ content.shift()
42
+ for (let el of content) {
43
+ const entry = el[1]
44
+ const tabEntrykey = Object.keys(entry)
45
+
46
+ //Validate that entry has optional key
47
+ if (!tabEntrykey.includes(keys4ActivityOpt[0])) {
48
+ if (!tabEntrykey.includes(keys4ActivityOpt[1])) {
49
+ err = `💥 Missing 👉 ${keys4ActivityOpt[0]} or ${keys4ActivityOpt[1]} 👈 in ${el[0]} in ➡ menu.setting.js \n 🚩One of thess two keys are mandatory : 👉 ${keys4ActivityOpt}`
50
+ break
51
+ }
52
+ }
53
+
54
+ //Validate that entry has mandatory key
55
+ for (let m of keys4ActivityMando) {
56
+ if (!tabEntrykey.includes(m)) {
57
+ err = `💥 Missing 👉 ${m} 👈 in ${el[0]} in ➡ menu.setting.js \n 🚩All this key are mandatory : 👉 ${keys4ActivityMando}`
58
+ break
59
+ } else {
60
+ switch (m) {
61
+ case 'anchors':
62
+ if (entry[m].constructor !== Array)
63
+ err = `💥 Invalid anchors declaration for 👉 ${el[0]} 👈 in ➡ menu.setting.j \n 🚩Must be of type {Array}`
64
+ else {
65
+ const anchors = entry.anchors
66
+
67
+ for (let a of anchors) {
68
+ //trow error if numbers of keys are not the same as required
69
+ const a_numb = anchors.indexOf(a) + 1
70
+ if (Object.keys(a).length !== keys4Anchors.length) {
71
+ err = `💥 Invalid declaration in 👉anchor ${a_numb}👈 for ➡ ${el[0]} in ➡ menu.setting.js \n 🚩 Allowed indexes are: 👉 ${keys4Anchors}`
72
+ break
73
+ }
74
+ // Validated that required keys condition and type is met
75
+ for (let k of keys4Anchors) {
76
+ if (!a[k]) {
77
+ err = `💥 Missing 👉 ${k} 👈 for anchor ${a_numb} ➡ ${el[0]} ➡ menu.setting.js \n 🚩 Allowed indexes are: 👉 ${keys4Anchors}`
78
+ } else if (a[k].constructor !== String) {
79
+ err = `💥 Invalid 👉 ${k} 👈 declaration for anchor ${a_numb} ➡ ${el[0]} ➡ menu.setting.js \n 🚩 Must be of type {String}`
80
+ }
81
+ if (err) break
82
+ }
83
+ if (err) break
84
+ }
85
+ }
86
+
87
+ break
88
+ default:
89
+ if (entry[m].constructor !== String)
90
+ err = `Invalid 👉 ${m} 👈 declaration for ➡ ${el[0]} in ➡ menu.setting.js \n 🚩 Must be of type {String}`
91
+ break
92
+ }
93
+ }
94
+ }
95
+ }
96
+ }
97
+ }
98
+ break
99
+ }
100
+ }
101
+ }
102
+ return err
103
+ }
104
+
105
+ /**
106
+ * @description Validator for the content of menu setting file
107
+ * @param {Object} data- Object definition to validate
108
+ **/
109
+ const validateVideoData = (data) => {
110
+ const errorList = []
111
+ if (import.meta.env.DEV) {
112
+ let errStringInConsole = null
113
+ let errString = null
114
+ const expectedKeys = [
115
+ 'id',
116
+ 'mSources',
117
+ 'mSubtitles',
118
+ 'mPoster',
119
+ 'mTranscript'
120
+ ]
121
+
122
+ if (!data || data.constructor !== Object || Object.keys(data).length < 1) {
123
+ errStringInConsole = `\n 💥 Invalid declaration for video element`
124
+ console.warn(
125
+ `%c WARNING!>>> VIDEO: ${errStringInConsole}`,
126
+ 'background: orange; color: white; display: block; border-radius:5px; margin:5px;'
127
+ )
128
+ errString = `Declaration invalide pour Objet video.`
129
+ errorList.push(errString)
130
+ }
131
+ //Must have mSources
132
+ if (!data['mSources']) {
133
+ errStringInConsole = ` Missing 👉 mSources 👈 declaration for video element`
134
+
135
+ errString = `l'Attribut <b>mSources</b> pour l'Objet video n'est pas defini. `
136
+ console.warn(
137
+ `%c WARNING!>>> ${errStringInConsole}`,
138
+ 'background: orange; color: white; display: block; border-radius:5px; margin:5px;'
139
+ )
140
+ errorList.push(errString)
141
+ }
142
+ //Must have id
143
+ if (!data['id']) {
144
+ errStringInConsole = ` Missing 👉 id 👈 declaration for video element`
145
+
146
+ errString = `l'Attribut <b>id</b> pour l'objet video n'est pas defini. `
147
+ console.warn(
148
+ `%c WARNING!>>> ${errStringInConsole}`,
149
+ 'background: orange; color: white; display: block; border-radius:5px; margin:5px;'
150
+ )
151
+ errorList.push(errString)
152
+ }
153
+ //Start validation of keys in data
154
+ if (!errString) {
155
+ expectedKeys.forEach((k) => {
156
+ if (!data[k] && k !== 'mSources') return
157
+
158
+ switch (k) {
159
+ case 'id':
160
+ if (data['id'].constructor !== String || data['id'].length < 1) {
161
+ errStringInConsole =
162
+ '\n 💥 Invalid type declaration for id.\n 🚩 Must be of type Array'
163
+
164
+ errString = `l'Attribut <b>id</b> pour le media doit être de type <i>String</i>`
165
+
166
+ errorList.push(errString)
167
+ console.warn(
168
+ `%c WARNING!>>> ${errStringInConsole}`,
169
+ 'background: orange; color: white; display: block; border-radius:5px; margin:5px;'
170
+ )
171
+ }
172
+ break
173
+ case 'mSources':
174
+ if (
175
+ data['mSources'].constructor !== Array ||
176
+ data['mSources'].length < 1
177
+ ) {
178
+ errStringInConsole =
179
+ '\n 💥 Invalid type declaration for mSources.\n 🚩 Must be of type Array'
180
+
181
+ errString = `l'Attribut 👉 mSources 👈 pour le media doit être de type Array`
182
+
183
+ errorList.push(errString)
184
+ console.warn(
185
+ `%c WARNING!>>> ${errStringInConsole}`,
186
+ 'background: orange; color: white; display: block; border-radius:5px; margin:5px;'
187
+ )
188
+ }
189
+ break
190
+
191
+ case 'mSubtitles':
192
+ {
193
+ //Validate required keys in Subtitle definition
194
+ let expectedKeys = ['label', 'src', 'srclang']
195
+ //we only accept one subtitle and must be defined as an Object with 3 keys
196
+ if (
197
+ data['mSubtitles'].constructor !== Array ||
198
+ !data['mSubtitles'].length
199
+ ) {
200
+ errStringInConsole = `\n 💥 Invalid type declaration for mSubtitles.\n 🚩 Must be of type Array with at list one Object defined with: ${expectedKeys}`
201
+
202
+ errString = `l'Attribut 👉 mSubtitles 👈 doit être de type Array avec au moins un Objet: {${expectedKeys}} `
203
+
204
+ console.warn(
205
+ `%c WARNING!>>> ${errStringInConsole}`,
206
+ 'background: orange; color: white; display: block; border-radius:5px; margin:5px;'
207
+ )
208
+
209
+ return errorList.push(errString)
210
+ }
211
+ //Validate definition for each Subtitle Object
212
+ for (const obj of data['mSubtitles']) {
213
+ const objIndex = data['mSubtitles'].indexOf(obj)
214
+ expectedKeys.forEach((expected) => {
215
+ if (!obj[expected]) {
216
+ errStringInConsole = `\n 💥 Missing key 👉 ${expected} 👈 for mSubtitles No.${
217
+ objIndex + 1
218
+ }.\n 🚩 required keys are: ${expectedKeys} `
219
+
220
+ errString = `l'Attribut 👉 ${expected} 👈 pour le sous-titre No.${
221
+ objIndex + 1
222
+ } n'est pas défini`
223
+
224
+ console.warn(
225
+ `%c WARNING!>>> ${errStringInConsole}`,
226
+ 'background: orange; color: white; display: block; border-radius:5px; margin:5px;'
227
+ )
228
+ return errorList.push(errString)
229
+ }
230
+
231
+ // Only none empty String type Accepted
232
+ if (
233
+ obj[expected].constructor === String &&
234
+ obj[expected].trim().length
235
+ )
236
+ return
237
+
238
+ errStringInConsole = `\n 💥 Invalid type declaration for 👉${expected}👈 in mSubtitles No.${
239
+ objIndex + 1
240
+ }.\n 🚩 Must be none-empty String `
241
+
242
+ errString = `l'Attribut 👉${expected}👈 du sous-titre No.${
243
+ objIndex + 1
244
+ } doit être de type String et ne peut pas être vide. `
245
+
246
+ console.warn(
247
+ `%c WARNING!>>> ${errStringInConsole}`,
248
+ 'background: orange; color: white; display: block; border-radius:5px; margin:5px;'
249
+ )
250
+
251
+ errorList.push(errString)
252
+ })
253
+ }
254
+ }
255
+ break
256
+ case 'mPoster':
257
+ //Only type String allowed and must not be empty
258
+ if (
259
+ data['mPoster'] &&
260
+ data['mPoster'].constructor == String &&
261
+ data['mPoster'].trim().length
262
+ )
263
+ return
264
+
265
+ errStringInConsole = `\n 💥 Invalid type declaration for 👉 mPoster 👈.\n 🚩 Must be none-empty String `
266
+
267
+ errString = `l'Attribut 👉 mPoster 👈 doit être de type String et ne peut pas être vide. `
268
+
269
+ errorList.push(errString)
270
+ console.warn(
271
+ `%c WARNING!>>> VIDEO: ${errStringInConsole}`,
272
+ 'background: orange; color: white; display: block; border-radius:5px; margin:5px;'
273
+ )
274
+
275
+ break
276
+ case 'mTranscript':
277
+ //Only type String allowed and must not be empty
278
+ if (
279
+ data['mTranscript'] &&
280
+ data['mTranscript'].constructor == String &&
281
+ data['mTranscript'].trim().length
282
+ )
283
+ return
284
+
285
+ errStringInConsole = `\n 💥 Invalid type declaration for 👉 mTranscript 👈 .\n 🚩 Must be none-empty String `
286
+
287
+ errString = `l'Attribut 👉 mTranscript 👈 doit être de type String et ne peut pas être vide. `
288
+
289
+ console.warn(
290
+ `%c WARNING!>>> VIDEO: ${errStringInConsole}`,
291
+ 'background: orange; color: white; display: block; border-radius:5px; margin:5px;'
292
+ )
293
+ errorList.push(errString)
294
+
295
+ break
296
+ }
297
+ })
298
+ }
299
+ }
300
+ return errorList
301
+ }
302
+
303
+ /**
304
+ * @description Validator for the content of audio props
305
+ * @param {Object} data- Object definition to validate
306
+ **/
307
+ const validateAudioData = (data) => {
308
+ const errorList = []
309
+ let currentProperties = Object.getOwnPropertyNames(data)
310
+ if (process.env.NODE_ENV === 'development') {
311
+ //errorList.push('test')
312
+
313
+ const requiredProperties = ['id', 'mTitle', 'mSources', 'mTranscript']
314
+
315
+ const optionalProperties = ['mPoster', 'mAlt']
316
+
317
+ const allProperties = [
318
+ ...requiredProperties,
319
+ ...optionalProperties,
320
+ ...['__ob__']
321
+ ]
322
+
323
+ let errStringInConsole = null
324
+ let errString = null
325
+
326
+ //** Validate if data exist and is an object**/
327
+ if (!data || data.constructor !== Object || Object.keys(data).length < 1) {
328
+ errStringInConsole = `\n 💥 Invalid declaration for audio element`
329
+ console.warn(
330
+ `%c WARNING!>>> AUDIO: ${errStringInConsole}`,
331
+ 'background: orange; color: white; display: block; border-radius:5px; margin:5px;'
332
+ )
333
+ errString = `Déclaration invalide pour Objet audData. Ce doit être un objet non vide.`
334
+ errorList.push(errString)
335
+ return errorList
336
+ }
337
+ //** Validate if all the properties are right**/
338
+ let wrongProperties = checkerWrong(allProperties, currentProperties)
339
+ if (wrongProperties.length > 0) {
340
+ console.warn(
341
+ `%c WARNING!>>> AppCompAudio : audData property ${wrongProperties} invalid. Required properties: ${requiredProperties} . Optional properties: ${optionalProperties}`,
342
+ 'background: orange; color: white; display: block; margin:5px;'
343
+ )
344
+ errString = `Propriété invalide pour audData: ${wrongProperties}. Les propriétés requises sont: ${requiredProperties} et les propriétés facultatives sont: ${optionalProperties}`
345
+ errorList.push(errString)
346
+ return errorList
347
+ }
348
+
349
+ //** Validate if all the required properties are in the data */
350
+ let missingRequired = checkerMissing(requiredProperties, currentProperties)
351
+ if (missingRequired.length > 0) {
352
+ console.warn(
353
+ `%c WARNING!>>> AppCompAudio : audData missing required ${missingRequired} property. Required properties: ${requiredProperties} . Optional properties: ${optionalProperties}`,
354
+ 'background: orange; color: white; display: block; margin:5px;'
355
+ )
356
+ errString = `Propriété requise manquante pour audData: <b>${missingRequired}</b>. Les propriétés requises sont: <i>${requiredProperties}</i> et les propriétés facultatives sont: <i>${optionalProperties}</i>`
357
+ errorList.push(errString)
358
+ return errorList
359
+ }
360
+ /***Validate data values */
361
+ if (errorList.length == 0) {
362
+ let invalidString = []
363
+ let invalidArray = []
364
+ let invalidProperties = []
365
+ currentProperties.forEach((p) => {
366
+ switch (p) {
367
+ case 'mTitle':
368
+ case 'mTranscript':
369
+ case 'mPoster':
370
+ case 'mAlt':
371
+ if (data[p] && data[p].constructor == String) {
372
+ data[p].trim().length == 0 ? invalidString.push(p) : ''
373
+ } else {
374
+ invalidString.push(p)
375
+ }
376
+ break
377
+ case 'mSources': {
378
+ if (data[p] && data[p].constructor == Array) {
379
+ data[p].length == 0 ? invalidArray.push(p) : ''
380
+ } else {
381
+ invalidArray.push(p)
382
+ }
383
+ if (invalidArray.length === 0) {
384
+ //Valider les attributs de mSources
385
+ for (let i in data[p]) {
386
+ let object = data[p][i]
387
+ if ('src' in object && 'type' in object) {
388
+ if (
389
+ object['src'].constructor != String &&
390
+ object['type'].constructor != String
391
+ ) {
392
+ invalidProperties.push(p)
393
+ } else {
394
+ object['src'].trim().length == 0
395
+ ? invalidString.push(p)
396
+ : ''
397
+ object['type'].trim().length == 0
398
+ ? invalidString.push(p)
399
+ : ''
400
+ }
401
+ } else {
402
+ invalidProperties.push(p)
403
+ }
404
+ }
405
+ }
406
+ break
407
+ }
408
+ }
409
+ })
410
+ //Display error for each type
411
+ //String
412
+ let sL = invalidString.length
413
+ if (sL > 0) {
414
+ errStringInConsole = `\n 💥 Invalid value type for 👉${invalidString}👈 \n 🚩 Must be none-empty String `
415
+
416
+ errString = `${sL > 1 ? 'Les ' : "L'"}attribut${
417
+ sL > 1 ? 's ' : ''
418
+ } 👉${invalidString}👈 doi${
419
+ sL > 1 ? 'ven' : ''
420
+ }t être de type String et ne peu${sL > 1 ? 'ven' : ''}t pas être vide. `
421
+
422
+ console.warn(
423
+ `%c WARNING!>>> ${errStringInConsole}`,
424
+ 'background: orange; color: white; display: block; border-radius:5px; margin:5px;'
425
+ )
426
+ errorList.push(errString)
427
+ }
428
+ //Array
429
+ let aL = invalidArray.length
430
+ if (aL > 0) {
431
+ errStringInConsole = `\n 💥 Invalid value type for 👉${invalidArray}👈 \n 🚩 Must be none-empty Array`
432
+
433
+ errString = `${aL > 1 ? 'Les ' : "L'"}attribut${
434
+ aL > 1 ? 's ' : ''
435
+ } 👉${invalidArray}👈 doi${
436
+ sL > 1 ? 'ven' : ''
437
+ }t être de type Array et ne peu${aL > 1 ? 'ven' : ''}t pas être vide. `
438
+
439
+ console.warn(
440
+ `%c WARNING!>>> ${errStringInConsole}`,
441
+ 'background: orange; color: white; display: block; border-radius:5px; margin:5px;'
442
+ )
443
+ errorList.push(errString)
444
+ }
445
+ let pL = invalidProperties.length
446
+ if (pL > 0) {
447
+ errStringInConsole = `\n 💥 Invalid value type for 👉src and/or type👈 in mSources \n 🚩 They are required and must be none-empty strings`
448
+
449
+ errString = `${pL > 1 ? 'Les ' : "L'"}attribut${
450
+ pL > 1 ? 's ' : ''
451
+ } 👉src and/or type👈 de mSources doi${
452
+ sL > 1 ? 'ven' : ''
453
+ }t être de type String et ne peu${pL > 1 ? 'ven' : ''}t pas être vide. `
454
+
455
+ console.warn(
456
+ `%c WARNING!>>> ${errStringInConsole}`,
457
+ 'background: orange; color: white; display: block; border-radius:5px; margin:5px;'
458
+ )
459
+ errorList.push(errString)
460
+ }
461
+ }
462
+ /*if (process.env.NODE_ENV === 'development') {
463
+ let errStringInConsole = null
464
+ let errString = null
465
+ const expectedKeys = ['mSources', 'mSubtitles', 'mPoster', 'mTranscript']
466
+
467
+ if (!data || data.constructor !== Object || Object.keys(data).length < 1) {
468
+ errStringInConsole = `\n 💥 Invalid declaration for video element`
469
+ console.warn(
470
+ `%c WARNING!>>> VIDEO: ${errStringInConsole}`,
471
+ 'background: orange; color: white; display: block; border-radius:5px; margin:5px;'
472
+ )
473
+ errString = `Declaration invalide pour Objet video.`
474
+ errorList.push(errString)
475
+ }
476
+
477
+ if (!data['mSources']) {
478
+ errStringInConsole = ` Missing 👉 mSources 👈 declaration for video element`
479
+
480
+ errString = `l'Attribut 👉 mSources 👈 pour l'Objet video n'est pas defini. `
481
+ console.warn(
482
+ `%c WARNING!>>> ${errStringInConsole}`,
483
+ 'background: orange; color: white; display: block; border-radius:5px; margin:5px;'
484
+ )
485
+ errorList.push(errString)
486
+ }
487
+
488
+ //Start validation of keys in data
489
+ if (!errString) {
490
+ expectedKeys.forEach((k) => {
491
+ if (!data[k] && k !== 'mSources') return
492
+
493
+ switch (k) {
494
+ case 'mSources':
495
+ if (
496
+ data['mSources'].constructor !== Array ||
497
+ data['mSources'].length < 1
498
+ ) {
499
+ errStringInConsole =
500
+ '\n 💥 Invalid type declaration for mSources.\n 🚩 Must be of type Array'
501
+
502
+ errString = `l'Attribut 👉 mSources 👈 pour le media doit être de type Array`
503
+
504
+ errorList.push(errString)
505
+ console.warn(
506
+ `%c WARNING!>>> ${errStringInConsole}`,
507
+ 'background: orange; color: white; display: block; border-radius:5px; margin:5px;'
508
+ )
509
+ }
510
+ break
511
+
512
+ case 'mSubtitles':
513
+ {
514
+ //Validate required keys in Subtitle definition
515
+ let expectedKeys = ['label', 'src', 'srclang']
516
+ //we only accept one subtitle and must be defined as an Object with 3 keys
517
+ if (
518
+ data['mSubtitles'].constructor !== Array ||
519
+ !data['mSubtitles'].length
520
+ ) {
521
+ errStringInConsole = `\n 💥 Invalid type declaration for mSubtitles.\n 🚩 Must be of type Array with at list one Object defined with: ${expectedKeys}`
522
+
523
+ errString = `l'Attribut 👉 mSubtitles 👈 doit être de type Array avec au moins un Objet: {${expectedKeys}} `
524
+
525
+ console.warn(
526
+ `%c WARNING!>>> ${errStringInConsole}`,
527
+ 'background: orange; color: white; display: block; border-radius:5px; margin:5px;'
528
+ )
529
+
530
+ return errorList.push(errString)
531
+ }
532
+ //Validate definition for each Subtitle Object
533
+ for (const obj of data['mSubtitles']) {
534
+ const objIndex = data['mSubtitles'].indexOf(obj)
535
+ expectedKeys.forEach((expected) => {
536
+ if (!obj[expected]) {
537
+ errStringInConsole = `\n 💥 Missing key 👉 ${expected} 👈 for mSubtitles No.${objIndex +
538
+ 1}.\n 🚩 required keys are: ${expectedKeys} `
539
+
540
+ errString = `l'Attribut 👉 ${expected} 👈 pour le sous-titre No.${objIndex +
541
+ 1} n'est pas défini`
542
+
543
+ console.warn(
544
+ `%c WARNING!>>> ${errStringInConsole}`,
545
+ 'background: orange; color: white; display: block; border-radius:5px; margin:5px;'
546
+ )
547
+ return errorList.push(errString)
548
+ }
549
+
550
+ // Only none empty String type Accepted
551
+ if (
552
+ obj[expected].constructor === String &&
553
+ obj[expected].trim().length
554
+ )
555
+ return
556
+
557
+ errStringInConsole = `\n 💥 Invalid type declaration for 👉${expected}👈 in mSubtitles No.${objIndex +
558
+ 1}.\n 🚩 Must be none-empty String `
559
+
560
+ errString = `l'Attribut 👉${expected}👈 du sous-titre No.${objIndex +
561
+ 1} doit être de type String et ne peut pas être vide. `
562
+
563
+ console.warn(
564
+ `%c WARNING!>>> ${errStringInConsole}`,
565
+ 'background: orange; color: white; display: block; border-radius:5px; margin:5px;'
566
+ )
567
+
568
+ errorList.push(errString)
569
+ })
570
+ }
571
+ }
572
+ break
573
+ case 'mPoster':
574
+ //Only type String allowed and must not be empty
575
+ if (
576
+ data['mPoster'] &&
577
+ data['mPoster'].constructor == String &&
578
+ data['mPoster'].trim().length
579
+ )
580
+ return
581
+
582
+ errStringInConsole = `\n 💥 Invalid type declaration for 👉 mPoster 👈.\n 🚩 Must be none-empty String `
583
+
584
+ errString = `l'Attribut 👉 mPoster 👈 doit être de type String et ne peut pas être vide. `
585
+
586
+ errorList.push(errString)
587
+ console.warn(
588
+ `%c WARNING!>>> VIDEO: ${errStringInConsole}`,
589
+ 'background: orange; color: white; display: block; border-radius:5px; margin:5px;'
590
+ )
591
+
592
+ break
593
+ case 'mTranscript':
594
+ //Only type String allowed and must not be empty
595
+ if (
596
+ data['mTranscript'] &&
597
+ data['mTranscript'].constructor == String &&
598
+ data['mTranscript'].trim().length
599
+ )
600
+ return
601
+
602
+ errStringInConsole = `\n 💥 Invalid type declaration for 👉 mTranscript 👈 .\n 🚩 Must be none-empty String `
603
+
604
+ errString = `l'Attribut 👉 mTranscript 👈 doit être de type String et ne peut pas être vide. `
605
+
606
+ console.warn(
607
+ `%c WARNING!>>> VIDEO: ${errStringInConsole}`,
608
+ 'background: orange; color: white; display: block; border-radius:5px; margin:5px;'
609
+ )
610
+ errorList.push(errString)
611
+
612
+ break
613
+ }
614
+ })
615
+ }
616
+ }*/
617
+ }
618
+ return errorList
619
+ }
620
+ //Get all the invalids properties from the object
621
+ /*Add element from target array that are NOT in arr to the wrongArray*/
622
+ const checkerWrong = (arr, target) => {
623
+ let wrongArray = []
624
+ target.every((v) => {
625
+ if (arr.includes(v)) {
626
+ return true
627
+ } else {
628
+ wrongArray.push(v)
629
+ return true
630
+ }
631
+ })
632
+ return wrongArray
633
+ }
634
+ //Get all the required properties that are missing from the object
635
+ /*Add element from the arr that are NOT in target arr to the missingArray*/
636
+ const checkerMissing = (arr, target) => {
637
+ let missingArray = []
638
+ arr.every((v) => {
639
+ if (target.includes(v)) {
640
+ return true
641
+ } else {
642
+ missingArray.push(v)
643
+ return true
644
+ }
645
+ })
646
+ return missingArray
647
+ }
648
+
649
+ const ERR_TYPE = {
650
+ err0: `\n 💥 Missing \x1B[1m$attr$ \x1B[0mfor $comp$. \x1B[1m$attr$ \x1B[0m should be provided with following attributes: \x1B[1m{$data$}`,
651
+ err1: `\n 💥 Invalid declaration for \x1B[1m$wrd$ \x1B[0m object`,
652
+ err2: `\n 💥 Invalid type declaration for 👉\x1B[1m$attr$ \x1B[0m👈 in \x1B[1m$el$\x1B[0m. Expected is \x1B[3m$type$ \x1B[0mtype with some value`,
653
+ err3: `\n 💥 Missing required argument 👉\x1B[1m$key$\x1B[0m👈 in \x1B[1m$el$\x1B[0m. Required arguments are: \x1B[1m$args$`,
654
+ err4: `\n 💥 Missing required argument 👉\x1B[1m$key$\x1B[0m👈 in \x1B[1m$el$\x1B[0m. Required arguments are: \x1B[1m$args$`
655
+ }
656
+
657
+ const ERR_TYPE_MSG = {
658
+ err0: `\n Données manquantes pour <span style='text-transform: uppercase;'>$comp$</span>. Assurez-vous que le composant reçoit l'attribut <b>$attr$</b> avec des données pour: <b>$data$</b>`,
659
+ err1: `\n Déclaration invalide pour <b>$wrd$</b>. Assurez-vous que l'application a du data.`,
660
+ err2: `\n Vous avez une declaration invalide dans <b>$attr$</b>. 👉<b>$el$</b>👈 n'accepte que le type <i>$type$</i> et ne peut pas être vide`,
661
+ err3: `\n L'attribut 👉<b>$key$</b>👈 est manquant dans <b>$el$</b>. Les attributs requis sont: <b>$args$</b>`
662
+ }
663
+
664
+ /**
665
+ * @description Validator for the content of app data.
666
+ * App data is used as setting for the application
667
+ * @param {Object} data - the Object definition to validate
668
+ * @param {Boolean} silent - if Validator should diplay error in console
669
+ *
670
+ **/
671
+
672
+ const validateAppContent = (data, silent = false) => {
673
+ let errorInConsole = []
674
+ let errorList = []
675
+
676
+ const requiredArgs = [
677
+ 'lang',
678
+ 'specification',
679
+ 'id',
680
+ 'crs_id',
681
+ 'idb_id',
682
+ 'no_menu',
683
+ 'is_single_activity',
684
+ 'auto_next_activity'
685
+ ]
686
+
687
+ //Validate not empty data
688
+ if (Object.keys(data).length == 0) {
689
+ const reg = /(\$comp\$)|(\$data\$)|(\$attr\$)/g
690
+
691
+ errorInConsole.push(
692
+ ERR_TYPE.err0.replace(reg, (e) => {
693
+ if (e == '$comp$') return 'app-base'
694
+ if (e == '$data$') return requiredArgs.toString().replaceAll(',', ', ')
695
+ if (e == '$attr$') return 'app-config'
696
+ })
697
+ )
698
+
699
+ errorList.push(
700
+ ERR_TYPE_MSG.err0.replace(reg, (e) => {
701
+ if (e == '$comp$') return 'app-base'
702
+ if (e == '$data$') return requiredArgs.toString().replaceAll(',', ', ')
703
+ if (e == '$attr$') return 'app-config'
704
+ })
705
+ )
706
+
707
+ console.warn(errorInConsole[0])
708
+
709
+ return errorList
710
+ }
711
+
712
+ let stringType = ['lang', 'specification', 'id', 'crs_id', 'idb_id']
713
+ let boolType = [
714
+ 'no_menu',
715
+ 'is_single_activity',
716
+ 'auto_next_activity',
717
+ 'remote'
718
+ ]
719
+ let objectType = ['actor', 'linkedResource']
720
+ let optionalArgs = ['remote', 'actor', 'linkedResource']
721
+
722
+ const { errorInConsole: errCons, errorList: errList } = validateObjType(
723
+ data,
724
+ {
725
+ stringType,
726
+ boolType,
727
+ objectType
728
+ },
729
+ optionalArgs,
730
+ 'App.vue'
731
+ )
732
+
733
+ errorList = [...errorList, ...errList]
734
+ errorInConsole = [...errorInConsole, ...errCons]
735
+
736
+ //===========Optional Keys should be of correct type when declared =================//
737
+ // Has actor defined
738
+ if (data['actor']) {
739
+ let { errorInConsole: err1, errorList: err2 } = validateObjType(
740
+ data['actor'],
741
+ {
742
+ stringType: ['name', 'mbox']
743
+ },
744
+ 'actor'
745
+ )
746
+
747
+ errorList = [...errorList, ...err2]
748
+ errorInConsole = [...errorInConsole, ...err1]
749
+ }
750
+ // Has LinkedResource defined
751
+ if (data['linkedResource']) {
752
+ let { errorInConsole: err1, errorList: err2 } = validateObjType(
753
+ data['linkedResource'],
754
+ {
755
+ stringType: ['url', 'id']
756
+ },
757
+ 'linkedResource'
758
+ )
759
+
760
+ errorList = [...errorList, ...err2]
761
+ errorInConsole = [...errorInConsole, ...err1]
762
+ }
763
+ // Has endpointConfig defined
764
+ if (data['endpointConfig']) {
765
+ let { errorInConsole: err1, errorList: err2 } = validateObjType(
766
+ data['endpointConfig'],
767
+ {
768
+ stringType: ['auth', 'endpoint']
769
+ },
770
+ 'endpointConfig'
771
+ )
772
+ errorList = [...errorList, ...err2]
773
+ errorInConsole = [...errorInConsole, ...err1]
774
+ }
775
+ //================== END Optional Keys ====================//
776
+
777
+ //Should display error to console
778
+ if (errorList.length && !silent) {
779
+ let txt = '⚠️ You have the following Errors:'
780
+ console.group(`%c ${txt}`, 'background:#ffc13a7d')
781
+ errorInConsole.forEach((err) => console.warn(err))
782
+ console.groupEnd()
783
+ }
784
+
785
+ return errorList
786
+ }
787
+
788
+ /**
789
+ * @description - Method to validate that given object attributes hold expected types
790
+ * @param {Object} Obj - object to validate
791
+ * @param {Object} Args - List of expected type groups - each type group must be an array of attributes with the same type
792
+ * @param {Array} notRequiredArgs - list of field that should be considered as optional in the object. Will not give error if not * provided but will be validated if they are present with wrong type or empty
793
+ * @param {Array} compName - Name of the component- will be display in error message
794
+ * @param {Array} err - list off errors to be added to
795
+ * @return {Object} list of errors - {errorInConsole, errorList} : errorlist can be used to display messages on template and
796
+ * errorInConsole to display messages in browser console
797
+ * @exemple - Given $user= {name:'toto', username:'totoEscargot', id:'id001', age:23, books:['one', 'two', 'three'] }
798
+ * Use validator on $user: validateObjType($user, {stringType:['name', 'username' , 'id'], numbType:['age'], arrayType:['books']})
799
+ * Will fail if any listed attribute not in $user or have wrong value. Error messages will be in console
800
+ *
801
+ */
802
+
803
+ const validateObjType = (
804
+ Obj,
805
+ Args = {
806
+ boolType: null,
807
+ arrayType: null,
808
+ stringType: null,
809
+ objectType: null,
810
+ numbType: null
811
+ },
812
+ notRequiredArgs = null,
813
+ compName = 'component',
814
+ err = null
815
+ ) => {
816
+ let errorInConsole = err && err.errorInConsole ? err.errorInConsole : []
817
+ let errorList = err && err.errorList ? err.errorLIst : []
818
+ let optionalArgs =
819
+ notRequiredArgs && notRequiredArgs.length ? notRequiredArgs : []
820
+ //=====Expected Arguments validation =================//
821
+ //Should have an object argument
822
+ if (!Obj) throw new Error(`No valid arguments provided`)
823
+
824
+ //validate Args Keys type
825
+ for (const _type in Args) {
826
+ // Should be a required type
827
+ if (
828
+ ![
829
+ 'boolType',
830
+ 'arrayType',
831
+ 'stringType',
832
+ 'objectType',
833
+ 'numbType'
834
+ ].includes(_type)
835
+ )
836
+ throw new Error(`Unknown types declaration : ${_type}`)
837
+
838
+ if (Args[_type] && Args[_type].length) {
839
+ for (let el of Args[_type]) {
840
+ //Check that each given element is a string
841
+ if (el.constructor !== String)
842
+ throw new Error(
843
+ `Invalid type detected in ${JSON.stringify(
844
+ Args[_type]
845
+ )}. Item ${Args[_type].indexOf(el) + 1} should be a String`
846
+ )
847
+
848
+ let reg = /(\$el\$)|(\$type\$)|(\$attr\$)/g
849
+
850
+ let isOptionalArg = optionalArgs.includes(el) ? true : false
851
+
852
+ switch (true) {
853
+ // Check That each given element exist in data if not optional
854
+ case Obj[el] === undefined && !isOptionalArg: {
855
+ reg = /(\$key\$)|(\$el\$)|(\$args\$)/g
856
+ const reg2 = /\[|\]|/g
857
+
858
+ errorInConsole.push(
859
+ ERR_TYPE.err3.replace(reg, (e) => {
860
+ if (e == '$key$') return el
861
+ if (e == '$el$') return compName
862
+ if (e == '$args$') return JSON.stringify(Args[_type])
863
+ })
864
+ )
865
+
866
+ errorList.push(
867
+ ERR_TYPE_MSG.err3.replace(reg, (e) => {
868
+ if (e == '$key$') return el
869
+ if (e == '$el$') return compName || 'Composant'
870
+ if (e == '$args$')
871
+ return JSON.stringify(Args[_type]).replaceAll(reg2, '')
872
+ })
873
+ )
874
+ break
875
+ }
876
+ //Should have Correct Types $attr$ $el$ $type$
877
+ case _type == 'boolType' &&
878
+ Obj[el] !== undefined &&
879
+ Obj[el].constructor !== Boolean:
880
+ errorInConsole.push(
881
+ ERR_TYPE.err2.replace(reg, (e) => {
882
+ if (e == '$attr$') return compName || 'Composant'
883
+ if (e == '$el$') return el
884
+ if (e == '$type$') return 'Boolean'
885
+ })
886
+ )
887
+ errorList.push(
888
+ ERR_TYPE_MSG.err2.replace(reg, (e) => {
889
+ if (e == '$attr$') return compName || 'Composant'
890
+ if (e == '$el$') return el
891
+ if (e == '$type$') return 'Boolean'
892
+ })
893
+ )
894
+ break
895
+
896
+ case _type == 'stringType' &&
897
+ Obj[el] !== undefined &&
898
+ (Obj[el].constructor !== String || !Obj[el].trim().length):
899
+ errorInConsole.push(
900
+ ERR_TYPE.err2.replace(reg, (e) => {
901
+ if (e == '$attr$') return compName || 'Composant'
902
+ if (e == '$el$') return el
903
+ if (e == '$type$') return 'String'
904
+ })
905
+ )
906
+ errorList.push(
907
+ ERR_TYPE_MSG.err2.replace(reg, (e) => {
908
+ if (e == '$attr$') return compName || 'Composant'
909
+ if (e == '$el$') return el
910
+ if (e == '$type$') return 'String'
911
+ })
912
+ )
913
+ break
914
+
915
+ case _type == 'arrayType' &&
916
+ Obj[el] !== undefined &&
917
+ (Obj[el].constructor !== Array || !Obj[el].length):
918
+ errorInConsole.push(
919
+ ERR_TYPE.err2.replace(reg, (e) => {
920
+ if (e == '$attr$') return compName || 'Composant'
921
+ if (e == '$el$') return el
922
+ if (e == '$type$') return 'Array'
923
+ })
924
+ )
925
+ errorList.push(
926
+ ERR_TYPE_MSG.err2.replace(reg, (e) => {
927
+ if (e == '$attr$') return compName || 'Composant'
928
+ if (e == '$el$') return el
929
+ if (e == '$type$') return 'Array'
930
+ })
931
+ )
932
+ break
933
+
934
+ case _type == 'numberType' &&
935
+ Obj[el] !== undefined &&
936
+ Obj[el].constructor !== Number:
937
+ errorInConsole.push(
938
+ ERR_TYPE.err2.replace(reg, (e) => {
939
+ if (e == '$attr$') return compName || 'Composant'
940
+ if (e == '$el$') return el
941
+ if (e == '$type$') return 'Number'
942
+ })
943
+ )
944
+ errorList.push(
945
+ ERR_TYPE_MSG.err2.replace(reg, (e) => {
946
+ if (e == '$attr$') return compName || 'Composant'
947
+ if (e == '$el$') return el
948
+ if (e == '$type$') return 'Number'
949
+ })
950
+ )
951
+ break
952
+
953
+ case _type == 'objectType' &&
954
+ Obj[el] !== undefined &&
955
+ Obj[el].constructor !== Object:
956
+ errorInConsole.push(
957
+ ERR_TYPE.err2.replace(reg, (e) => {
958
+ if (e == '$attr$') return compName || 'Composant'
959
+ if (e == '$el$') return el
960
+ if (e == '$type$') return 'Object'
961
+ })
962
+ )
963
+ errorList.push(
964
+ ERR_TYPE_MSG.err2.replace(reg, (e) => {
965
+ if (e == '$attr$') return compName || 'Composant'
966
+ if (e == '$el$') return el
967
+ if (e == '$type$') return 'Object'
968
+ })
969
+ )
970
+ break
971
+ }
972
+ }
973
+ }
974
+ }
975
+
976
+ return { errorInConsole, errorList }
977
+ }
978
+ /**
979
+ * @description - Method validate the definition of SVG data.
980
+ * @param {Array || Object } SVGData - the data defining the SVG to render
981
+ * @return true - if valid
982
+ * */
983
+
984
+ const validateSvgDefinition = (SVGData) => {
985
+ //Should be Array of Object
986
+ if (SVGData.constructor !== Array && SVGData.constructor !== Object)
987
+ throw new Error('Unsupported Type for SVG data')
988
+ let Errors = []
989
+ let SVGDef = SVGData.constructor == Object ? new Array(SVGData) : SVGData
990
+ //Should validate the entries for each SVG definition as the required entries
991
+
992
+ for (const s_def of SVGDef) {
993
+ let i = SVGDef.indexOf(s_def)
994
+ let stringType = ['id', 'viewBox']
995
+ let arrayType = ['paths']
996
+ let { errorInConsole: errCons } = validateObjType(
997
+ s_def,
998
+ {
999
+ stringType,
1000
+ arrayType
1001
+ },
1002
+ 'viewBox',
1003
+ `SVG ${i + 1}`
1004
+ )
1005
+ Errors.push(...errCons)
1006
+ if (errCons.length) {
1007
+ errCons.forEach((err) => console.warn(err))
1008
+ break
1009
+ }
1010
+
1011
+ //Should validate that each element in the path attributes is an object of type string and has the id attribute
1012
+
1013
+ for (const _path of s_def.paths) {
1014
+ let index = s_def.paths.indexOf(_path)
1015
+ if (_path.constructor !== Object)
1016
+ throw Error(
1017
+ `Unexpected definition for path ${index + 1} in SVG ${i + 1}. Expecting Object but received ${typeof _path}`
1018
+ )
1019
+
1020
+ let stringType = ['d']
1021
+
1022
+ let { errorInConsole: errCons } = validateObjType(
1023
+ _path,
1024
+ {
1025
+ stringType
1026
+ },
1027
+ null,
1028
+ `SVG path ${index + 1}`
1029
+ )
1030
+ Errors.push(...errCons)
1031
+ if (errCons.length) {
1032
+ errCons.forEach((err) => console.warn(err))
1033
+ break
1034
+ }
1035
+
1036
+ //validate each entries in path
1037
+ for (const _key in _path) {
1038
+ if (_key == 'd') continue //skip
1039
+ //all keys in path should be of type String and not empty
1040
+ let stringType = [_key]
1041
+
1042
+ let { errorInConsole: errCons } = validateObjType(
1043
+ _path,
1044
+ {
1045
+ stringType
1046
+ },
1047
+ null,
1048
+ `SVG path ${index + 1}`
1049
+ )
1050
+ Errors.push(...errCons)
1051
+ if (errCons.length) {
1052
+ errCons.forEach((err) => console.log(err))
1053
+ break
1054
+ }
1055
+ }
1056
+ }
1057
+ }
1058
+
1059
+ if (Errors.length) throw new Error('Error SVG')
1060
+ return true
1061
+ }
1062
+
1063
+ export {
1064
+ validateVideoData,
1065
+ validateAudioData,
1066
+ validatefileContent,
1067
+ validateAppContent,
1068
+ validateSvgDefinition
1069
+ }