@applicaster/zapp-react-dom-app 14.0.9-alpha.4253701132 → 14.0.9-alpha.7320033430
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.
|
@@ -109,7 +109,7 @@ describe("QuickBrickCommunicationModule Polyfill", () => {
|
|
|
109
109
|
});
|
|
110
110
|
});
|
|
111
111
|
|
|
112
|
-
it("should
|
|
112
|
+
it("should fallback to default language if browser / device locale (en-UK) does not match list of supported languages", () => {
|
|
113
113
|
// localizations: ["en", "en-US", "fr", "fr-FR"], device_language: en, device_region: UK -> ui: en, language: en, region: UK
|
|
114
114
|
|
|
115
115
|
global.window.navigator.language = "en-UK";
|
|
@@ -118,22 +118,8 @@ describe("QuickBrickCommunicationModule Polyfill", () => {
|
|
|
118
118
|
expect(result).toEqual({
|
|
119
119
|
uiLanguage: "en",
|
|
120
120
|
languageCode: "en",
|
|
121
|
-
countryLocale: "
|
|
122
|
-
languageLocale: "en
|
|
123
|
-
});
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
it("should partial match fr language when browser / device locale (fr-CA) does not exact match list of supported languages", () => {
|
|
127
|
-
// localizations: ["en", "en-US", "fr", "fr-FR"], device_language: en, device_region: UK -> ui: en, language: en, region: UK
|
|
128
|
-
|
|
129
|
-
global.window.navigator.language = "fr-CA";
|
|
130
|
-
const result = QuickBrickModule.getMatchingLanguageFromBuildData();
|
|
131
|
-
|
|
132
|
-
expect(result).toEqual({
|
|
133
|
-
uiLanguage: "fr",
|
|
134
|
-
languageCode: "fr",
|
|
135
|
-
countryLocale: "CA",
|
|
136
|
-
languageLocale: "fr-CA",
|
|
121
|
+
countryLocale: "",
|
|
122
|
+
languageLocale: "en",
|
|
137
123
|
});
|
|
138
124
|
});
|
|
139
125
|
|
|
@@ -204,312 +190,6 @@ describe("QuickBrickCommunicationModule Polyfill", () => {
|
|
|
204
190
|
languageLocale: "fr-FR",
|
|
205
191
|
});
|
|
206
192
|
});
|
|
207
|
-
|
|
208
|
-
it("should not attempt to use user-selected language if it is improperly stored as undefined, null, or empty string", () => {
|
|
209
|
-
mockGetAppData.mockReturnValue(
|
|
210
|
-
getMockAppData({
|
|
211
|
-
languages: ["en", "es", "fr", "en-UK", "en-GB", "ar"],
|
|
212
|
-
})
|
|
213
|
-
);
|
|
214
|
-
|
|
215
|
-
global.window.navigator.language = "fr-CA";
|
|
216
|
-
|
|
217
|
-
// Test with undefined
|
|
218
|
-
window.localStorage.getItem.mockReturnValue("undefined");
|
|
219
|
-
let result = QuickBrickModule.getMatchingLanguageFromBuildData();
|
|
220
|
-
|
|
221
|
-
expect(result).toEqual({
|
|
222
|
-
uiLanguage: "fr",
|
|
223
|
-
languageCode: "fr",
|
|
224
|
-
countryLocale: "CA",
|
|
225
|
-
languageLocale: "fr-CA",
|
|
226
|
-
});
|
|
227
|
-
|
|
228
|
-
// Test with null
|
|
229
|
-
window.localStorage.getItem.mockReturnValue("null");
|
|
230
|
-
result = QuickBrickModule.getMatchingLanguageFromBuildData();
|
|
231
|
-
|
|
232
|
-
expect(result).toEqual({
|
|
233
|
-
uiLanguage: "fr",
|
|
234
|
-
languageCode: "fr",
|
|
235
|
-
countryLocale: "CA",
|
|
236
|
-
languageLocale: "fr-CA",
|
|
237
|
-
});
|
|
238
|
-
|
|
239
|
-
// Test with empty string
|
|
240
|
-
window.localStorage.getItem.mockReturnValue("");
|
|
241
|
-
result = QuickBrickModule.getMatchingLanguageFromBuildData();
|
|
242
|
-
|
|
243
|
-
expect(result).toEqual({
|
|
244
|
-
uiLanguage: "fr",
|
|
245
|
-
languageCode: "fr",
|
|
246
|
-
countryLocale: "CA",
|
|
247
|
-
languageLocale: "fr-CA",
|
|
248
|
-
});
|
|
249
|
-
});
|
|
250
|
-
|
|
251
|
-
describe("user-selected language scenarios", () => {
|
|
252
|
-
it("should use exact match user-selected language when available, ignoring browser locale", () => {
|
|
253
|
-
window.localStorage.getItem.mockReturnValue("fr-FR");
|
|
254
|
-
global.window.navigator.language = "en-US";
|
|
255
|
-
|
|
256
|
-
const result = QuickBrickModule.getMatchingLanguageFromBuildData();
|
|
257
|
-
|
|
258
|
-
expect(result).toEqual({
|
|
259
|
-
uiLanguage: "fr-FR",
|
|
260
|
-
languageCode: "fr",
|
|
261
|
-
countryLocale: "FR",
|
|
262
|
-
languageLocale: "fr-FR",
|
|
263
|
-
});
|
|
264
|
-
});
|
|
265
|
-
|
|
266
|
-
it("should use base language user-selected when available (single language code)", () => {
|
|
267
|
-
window.localStorage.getItem.mockReturnValue("en");
|
|
268
|
-
global.window.navigator.language = "fr-FR";
|
|
269
|
-
|
|
270
|
-
const result = QuickBrickModule.getMatchingLanguageFromBuildData();
|
|
271
|
-
|
|
272
|
-
expect(result).toEqual({
|
|
273
|
-
uiLanguage: "en",
|
|
274
|
-
languageCode: "en",
|
|
275
|
-
countryLocale: "",
|
|
276
|
-
languageLocale: "en",
|
|
277
|
-
});
|
|
278
|
-
});
|
|
279
|
-
|
|
280
|
-
it("should use base language fr user-selected when available", () => {
|
|
281
|
-
window.localStorage.getItem.mockReturnValue("fr");
|
|
282
|
-
global.window.navigator.language = "en-US";
|
|
283
|
-
|
|
284
|
-
const result = QuickBrickModule.getMatchingLanguageFromBuildData();
|
|
285
|
-
|
|
286
|
-
expect(result).toEqual({
|
|
287
|
-
uiLanguage: "fr",
|
|
288
|
-
languageCode: "fr",
|
|
289
|
-
countryLocale: "",
|
|
290
|
-
languageLocale: "fr",
|
|
291
|
-
});
|
|
292
|
-
});
|
|
293
|
-
|
|
294
|
-
it("should fallback to browser exact match when user-selected language not available", () => {
|
|
295
|
-
window.localStorage.getItem.mockReturnValue("de-DE");
|
|
296
|
-
global.window.navigator.language = "fr-FR";
|
|
297
|
-
|
|
298
|
-
const result = QuickBrickModule.getMatchingLanguageFromBuildData();
|
|
299
|
-
|
|
300
|
-
expect(result).toEqual({
|
|
301
|
-
uiLanguage: "fr-FR",
|
|
302
|
-
languageCode: "fr",
|
|
303
|
-
countryLocale: "FR",
|
|
304
|
-
languageLocale: "fr-FR",
|
|
305
|
-
});
|
|
306
|
-
});
|
|
307
|
-
|
|
308
|
-
it("should fallback to browser partial match when user-selected language not available", () => {
|
|
309
|
-
window.localStorage.getItem.mockReturnValue("de-DE");
|
|
310
|
-
global.window.navigator.language = "fr-CA";
|
|
311
|
-
|
|
312
|
-
const result = QuickBrickModule.getMatchingLanguageFromBuildData();
|
|
313
|
-
|
|
314
|
-
expect(result).toEqual({
|
|
315
|
-
uiLanguage: "fr",
|
|
316
|
-
languageCode: "fr",
|
|
317
|
-
countryLocale: "CA",
|
|
318
|
-
languageLocale: "fr-CA",
|
|
319
|
-
});
|
|
320
|
-
});
|
|
321
|
-
|
|
322
|
-
it("should fallback to default language when both user-selected and browser locales not available", () => {
|
|
323
|
-
window.localStorage.getItem.mockReturnValue("de-DE");
|
|
324
|
-
global.window.navigator.language = "ja-JP";
|
|
325
|
-
|
|
326
|
-
const result = QuickBrickModule.getMatchingLanguageFromBuildData();
|
|
327
|
-
|
|
328
|
-
expect(result).toEqual({
|
|
329
|
-
uiLanguage: "en",
|
|
330
|
-
languageCode: "en",
|
|
331
|
-
countryLocale: "",
|
|
332
|
-
languageLocale: "en",
|
|
333
|
-
});
|
|
334
|
-
});
|
|
335
|
-
});
|
|
336
|
-
|
|
337
|
-
describe("browser/device locale scenarios", () => {
|
|
338
|
-
beforeEach(() => {
|
|
339
|
-
window.localStorage.getItem.mockReturnValue(null);
|
|
340
|
-
});
|
|
341
|
-
|
|
342
|
-
it("should use exact match browser locale when no user selection", () => {
|
|
343
|
-
global.window.navigator.language = "en-US";
|
|
344
|
-
|
|
345
|
-
const result = QuickBrickModule.getMatchingLanguageFromBuildData();
|
|
346
|
-
|
|
347
|
-
expect(result).toEqual({
|
|
348
|
-
uiLanguage: "en-US",
|
|
349
|
-
languageCode: "en",
|
|
350
|
-
countryLocale: "US",
|
|
351
|
-
languageLocale: "en-US",
|
|
352
|
-
});
|
|
353
|
-
});
|
|
354
|
-
|
|
355
|
-
it("should use partial match browser locale when exact match not available", () => {
|
|
356
|
-
global.window.navigator.language = "en-AU";
|
|
357
|
-
|
|
358
|
-
const result = QuickBrickModule.getMatchingLanguageFromBuildData();
|
|
359
|
-
|
|
360
|
-
expect(result).toEqual({
|
|
361
|
-
uiLanguage: "en",
|
|
362
|
-
languageCode: "en",
|
|
363
|
-
countryLocale: "AU",
|
|
364
|
-
languageLocale: "en-AU",
|
|
365
|
-
});
|
|
366
|
-
});
|
|
367
|
-
|
|
368
|
-
it("should fallback to default language when browser locale not available at all", () => {
|
|
369
|
-
global.window.navigator.language = "de-DE";
|
|
370
|
-
|
|
371
|
-
const result = QuickBrickModule.getMatchingLanguageFromBuildData();
|
|
372
|
-
|
|
373
|
-
expect(result).toEqual({
|
|
374
|
-
uiLanguage: "en",
|
|
375
|
-
languageCode: "en",
|
|
376
|
-
countryLocale: "",
|
|
377
|
-
languageLocale: "en",
|
|
378
|
-
});
|
|
379
|
-
});
|
|
380
|
-
|
|
381
|
-
it("should handle browser locale without country code (base language only)", () => {
|
|
382
|
-
global.window.navigator.language = "fr";
|
|
383
|
-
|
|
384
|
-
const result = QuickBrickModule.getMatchingLanguageFromBuildData();
|
|
385
|
-
|
|
386
|
-
expect(result).toEqual({
|
|
387
|
-
uiLanguage: "fr",
|
|
388
|
-
languageCode: "fr",
|
|
389
|
-
countryLocale: "",
|
|
390
|
-
languageLocale: "fr",
|
|
391
|
-
});
|
|
392
|
-
});
|
|
393
|
-
|
|
394
|
-
it("should handle browser locale without country code when only regional variants available", () => {
|
|
395
|
-
mockGetAppData.mockReturnValue(
|
|
396
|
-
getMockAppData({ languages: ["en-US", "en-GB", "fr-FR", "fr-CA"] })
|
|
397
|
-
);
|
|
398
|
-
|
|
399
|
-
jest.resetModules();
|
|
400
|
-
QuickBrickModule = require("../index");
|
|
401
|
-
|
|
402
|
-
global.window.navigator.language = "fr";
|
|
403
|
-
|
|
404
|
-
const result = QuickBrickModule.getMatchingLanguageFromBuildData();
|
|
405
|
-
|
|
406
|
-
expect(result).toEqual({
|
|
407
|
-
uiLanguage: "fr-FR",
|
|
408
|
-
languageCode: "fr",
|
|
409
|
-
countryLocale: "",
|
|
410
|
-
languageLocale: "fr",
|
|
411
|
-
});
|
|
412
|
-
});
|
|
413
|
-
});
|
|
414
|
-
|
|
415
|
-
describe("edge cases", () => {
|
|
416
|
-
beforeEach(() => {
|
|
417
|
-
window.localStorage.getItem.mockReturnValue(null);
|
|
418
|
-
});
|
|
419
|
-
|
|
420
|
-
it("should fallback to locale when browser language is undefined", () => {
|
|
421
|
-
global.window.navigator.language = undefined;
|
|
422
|
-
|
|
423
|
-
const result = QuickBrickModule.getMatchingLanguageFromBuildData();
|
|
424
|
-
|
|
425
|
-
expect(result).toEqual({
|
|
426
|
-
uiLanguage: "en",
|
|
427
|
-
languageCode: "en",
|
|
428
|
-
countryLocale: "",
|
|
429
|
-
languageLocale: "en",
|
|
430
|
-
});
|
|
431
|
-
});
|
|
432
|
-
|
|
433
|
-
it("should prefer exact match over partial match when both are available", () => {
|
|
434
|
-
mockGetAppData.mockReturnValue(
|
|
435
|
-
getMockAppData({ languages: ["en", "en-US", "en-GB", "fr"] })
|
|
436
|
-
);
|
|
437
|
-
|
|
438
|
-
jest.resetModules();
|
|
439
|
-
QuickBrickModule = require("../index");
|
|
440
|
-
|
|
441
|
-
global.window.navigator.language = "en-GB";
|
|
442
|
-
|
|
443
|
-
const result = QuickBrickModule.getMatchingLanguageFromBuildData();
|
|
444
|
-
|
|
445
|
-
expect(result).toEqual({
|
|
446
|
-
uiLanguage: "en-GB",
|
|
447
|
-
languageCode: "en",
|
|
448
|
-
countryLocale: "GB",
|
|
449
|
-
languageLocale: "en-GB",
|
|
450
|
-
});
|
|
451
|
-
});
|
|
452
|
-
|
|
453
|
-
it("should use first partial match when multiple base languages could match", () => {
|
|
454
|
-
mockGetAppData.mockReturnValue(
|
|
455
|
-
getMockAppData({ languages: ["en-US", "en-GB", "fr-FR", "fr-CA"] })
|
|
456
|
-
);
|
|
457
|
-
|
|
458
|
-
jest.resetModules();
|
|
459
|
-
QuickBrickModule = require("../index");
|
|
460
|
-
|
|
461
|
-
global.window.navigator.language = "en-AU";
|
|
462
|
-
|
|
463
|
-
const result = QuickBrickModule.getMatchingLanguageFromBuildData();
|
|
464
|
-
|
|
465
|
-
expect(result).toEqual({
|
|
466
|
-
uiLanguage: "en-US",
|
|
467
|
-
languageCode: "en",
|
|
468
|
-
countryLocale: "AU",
|
|
469
|
-
languageLocale: "en-AU",
|
|
470
|
-
});
|
|
471
|
-
});
|
|
472
|
-
|
|
473
|
-
it("should handle complex regional variants like zh-Hans-CN", () => {
|
|
474
|
-
mockGetAppData.mockReturnValue(
|
|
475
|
-
getMockAppData({ languages: ["en", "zh-CN", "zh-TW"] })
|
|
476
|
-
);
|
|
477
|
-
|
|
478
|
-
jest.resetModules();
|
|
479
|
-
QuickBrickModule = require("../index");
|
|
480
|
-
|
|
481
|
-
global.window.navigator.language = "zh-CN";
|
|
482
|
-
|
|
483
|
-
const result = QuickBrickModule.getMatchingLanguageFromBuildData();
|
|
484
|
-
|
|
485
|
-
expect(result).toEqual({
|
|
486
|
-
uiLanguage: "zh-CN",
|
|
487
|
-
languageCode: "zh",
|
|
488
|
-
countryLocale: "CN",
|
|
489
|
-
languageLocale: "zh-CN",
|
|
490
|
-
});
|
|
491
|
-
});
|
|
492
|
-
|
|
493
|
-
it("should fallback to first language when supported languages list is populated but browser locale cannot be parsed", () => {
|
|
494
|
-
mockGetAppData.mockReturnValue(
|
|
495
|
-
getMockAppData({ languages: ["ar", "he", "fa"] })
|
|
496
|
-
);
|
|
497
|
-
|
|
498
|
-
jest.resetModules();
|
|
499
|
-
QuickBrickModule = require("../index");
|
|
500
|
-
|
|
501
|
-
global.window.navigator.language = "en-US";
|
|
502
|
-
|
|
503
|
-
const result = QuickBrickModule.getMatchingLanguageFromBuildData();
|
|
504
|
-
|
|
505
|
-
expect(result).toEqual({
|
|
506
|
-
uiLanguage: "ar",
|
|
507
|
-
languageCode: "ar",
|
|
508
|
-
countryLocale: "",
|
|
509
|
-
languageLocale: "ar",
|
|
510
|
-
});
|
|
511
|
-
});
|
|
512
|
-
});
|
|
513
193
|
});
|
|
514
194
|
|
|
515
195
|
describe("setAppLanguage", () => {
|
|
@@ -13,27 +13,6 @@ const { log_error, log_debug, log_warning } = createLogger({
|
|
|
13
13
|
|
|
14
14
|
const QuickBrickEventEmitter = {};
|
|
15
15
|
|
|
16
|
-
const getUserSelectedLanguage = () => {
|
|
17
|
-
const userSelectedLanguage = window.localStorage.getItem(
|
|
18
|
-
"applicaster.v2_::_uiLanguage"
|
|
19
|
-
);
|
|
20
|
-
|
|
21
|
-
if (
|
|
22
|
-
userSelectedLanguage === "null" ||
|
|
23
|
-
userSelectedLanguage === "undefined" ||
|
|
24
|
-
userSelectedLanguage === ""
|
|
25
|
-
) {
|
|
26
|
-
log_warning(
|
|
27
|
-
"Invalid user selected language found in localStorage:",
|
|
28
|
-
userSelectedLanguage
|
|
29
|
-
);
|
|
30
|
-
|
|
31
|
-
return null;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
return userSelectedLanguage;
|
|
35
|
-
};
|
|
36
|
-
|
|
37
16
|
export const QuickBrickEvents = (function (eventEmitter) {
|
|
38
17
|
let listeners = [];
|
|
39
18
|
|
|
@@ -143,12 +122,9 @@ export const getMatchingLanguageFromBuildData = () => {
|
|
|
143
122
|
const browserLocale = getBrowserLocale();
|
|
144
123
|
|
|
145
124
|
if (!Array.isArray(languages)) {
|
|
146
|
-
log_error(
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
buildTimeData,
|
|
150
|
-
}
|
|
151
|
-
);
|
|
125
|
+
log_error("Missing required 'languages' from the build time data.", {
|
|
126
|
+
buildTimeData,
|
|
127
|
+
});
|
|
152
128
|
|
|
153
129
|
return {
|
|
154
130
|
uiLanguage: locale,
|
|
@@ -158,7 +134,9 @@ export const getMatchingLanguageFromBuildData = () => {
|
|
|
158
134
|
};
|
|
159
135
|
}
|
|
160
136
|
|
|
161
|
-
const userSelectedLanguage =
|
|
137
|
+
const userSelectedLanguage = window.localStorage.getItem(
|
|
138
|
+
"applicaster.v2_::_uiLanguage"
|
|
139
|
+
);
|
|
162
140
|
|
|
163
141
|
if (userSelectedLanguage) {
|
|
164
142
|
if (languages.find((lang) => lang === userSelectedLanguage)) {
|
|
@@ -174,6 +152,7 @@ export const getMatchingLanguageFromBuildData = () => {
|
|
|
174
152
|
|
|
175
153
|
log_debug(
|
|
176
154
|
"User selected language is not present in available localizations, selecting language using browser or device locale",
|
|
155
|
+
|
|
177
156
|
{ userSelectedLanguage, languages }
|
|
178
157
|
);
|
|
179
158
|
}
|
|
@@ -193,37 +172,21 @@ export const getMatchingLanguageFromBuildData = () => {
|
|
|
193
172
|
}
|
|
194
173
|
|
|
195
174
|
// Exact match
|
|
196
|
-
const [
|
|
175
|
+
const [browserLanguageCode, browserCountryLocale] = browserLocale.split("-");
|
|
197
176
|
const browserLocaleMatch = languages.find((lang) => lang === browserLocale);
|
|
198
177
|
|
|
199
178
|
if (browserLocaleMatch) {
|
|
200
179
|
return {
|
|
201
180
|
uiLanguage: browserLocaleMatch,
|
|
202
|
-
languageCode:
|
|
181
|
+
languageCode: browserLanguageCode,
|
|
203
182
|
countryLocale: browserCountryLocale || "",
|
|
204
183
|
languageLocale: browserLocaleMatch,
|
|
205
184
|
};
|
|
206
185
|
}
|
|
207
186
|
|
|
208
|
-
// Partial match: try to match the base language (e.g., "fr" from "fr-CA")
|
|
209
|
-
const partialMatch = languages.find((lang) => {
|
|
210
|
-
const [supportedBaseLanguage] = lang.split("-");
|
|
211
|
-
|
|
212
|
-
return supportedBaseLanguage === browserBaseLanguage;
|
|
213
|
-
});
|
|
214
|
-
|
|
215
|
-
if (partialMatch) {
|
|
216
|
-
return {
|
|
217
|
-
uiLanguage: partialMatch,
|
|
218
|
-
languageCode: browserBaseLanguage,
|
|
219
|
-
countryLocale: browserCountryLocale || "",
|
|
220
|
-
languageLocale: browserLocale,
|
|
221
|
-
};
|
|
222
|
-
}
|
|
223
|
-
|
|
224
187
|
// If there is no user-selected language, or the user-selected language is not found in the list of supported languages,
|
|
225
188
|
// and the browser locale is also not found in the list of supported languages,
|
|
226
|
-
// then fallback to the
|
|
189
|
+
// then fallback to the default language from the list of supported languages, while preserving the country locale from the browser.
|
|
227
190
|
const defaultLanguage = languages[0];
|
|
228
191
|
|
|
229
192
|
if (defaultLanguage) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@applicaster/zapp-react-dom-app",
|
|
3
|
-
"version": "14.0.9-alpha.
|
|
3
|
+
"version": "14.0.9-alpha.7320033430",
|
|
4
4
|
"description": "Zapp App Component for Applicaster's Quick Brick React Native App",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -22,11 +22,11 @@
|
|
|
22
22
|
},
|
|
23
23
|
"homepage": "https://github.com/applicaster/zapp-react-dom-app#readme",
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@applicaster/zapp-react-dom-ui-components": "14.0.9-alpha.
|
|
26
|
-
"@applicaster/zapp-react-native-bridge": "14.0.9-alpha.
|
|
27
|
-
"@applicaster/zapp-react-native-redux": "14.0.9-alpha.
|
|
28
|
-
"@applicaster/zapp-react-native-ui-components": "14.0.9-alpha.
|
|
29
|
-
"@applicaster/zapp-react-native-utils": "14.0.9-alpha.
|
|
25
|
+
"@applicaster/zapp-react-dom-ui-components": "14.0.9-alpha.7320033430",
|
|
26
|
+
"@applicaster/zapp-react-native-bridge": "14.0.9-alpha.7320033430",
|
|
27
|
+
"@applicaster/zapp-react-native-redux": "14.0.9-alpha.7320033430",
|
|
28
|
+
"@applicaster/zapp-react-native-ui-components": "14.0.9-alpha.7320033430",
|
|
29
|
+
"@applicaster/zapp-react-native-utils": "14.0.9-alpha.7320033430",
|
|
30
30
|
"abortcontroller-polyfill": "^1.7.5",
|
|
31
31
|
"typeface-montserrat": "^0.0.54",
|
|
32
32
|
"video.js": "7.14.3",
|