cloudinary-video-player 3.12.1 → 3.12.2-edge.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (86) hide show
  1. package/dist/134.min.js +8 -0
  2. package/dist/309.min.js +6 -0
  3. package/dist/adaptive-streaming.js +9 -9
  4. package/dist/adaptive-streaming.min.js +2 -2
  5. package/dist/chapters.js +4 -4
  6. package/dist/chapters.min.js +3 -3
  7. package/dist/cld-player-core.js +37 -0
  8. package/dist/cld-player-core.min.js +6 -0
  9. package/dist/cld-video-player-lazy.js +494 -0
  10. package/dist/cld-video-player-lazy.min.js +6 -0
  11. package/dist/cld-video-player.css +2 -2
  12. package/dist/cld-video-player.js +366 -332
  13. package/dist/cld-video-player.light.js +366 -332
  14. package/dist/cld-video-player.light.min.js +4 -4
  15. package/dist/cld-video-player.min.css +2 -2
  16. package/dist/cld-video-player.min.js +4 -4
  17. package/dist/colors.js +4 -4
  18. package/dist/colors.min.js +2 -2
  19. package/dist/dash.js +6 -6
  20. package/dist/dash.min.js +2 -2
  21. package/dist/debug.js +8 -8
  22. package/dist/debug.min.js +3 -3
  23. package/dist/ima.js +9 -9
  24. package/dist/ima.min.js +2 -2
  25. package/dist/interaction-areas.js +11 -11
  26. package/dist/interaction-areas.min.js +2 -2
  27. package/dist/node_modules_lodash_throttle_js.js +8 -8
  28. package/dist/playlist.js +31 -31
  29. package/dist/playlist.min.js +3 -3
  30. package/dist/recommendations-overlay.js +10 -10
  31. package/dist/recommendations-overlay.min.js +2 -2
  32. package/dist/schema.json +19 -0
  33. package/dist/share.js +5 -5
  34. package/dist/share.min.js +3 -3
  35. package/dist/shoppable.js +12 -12
  36. package/dist/shoppable.min.js +2 -2
  37. package/dist/utils_fetch-config_js.js +81 -0
  38. package/dist/video-player_js.js +3111 -0
  39. package/dist/visual-search.js +7 -7
  40. package/dist/visual-search.min.js +2 -2
  41. package/lib/_commonjsHelpers.js +7 -0
  42. package/lib/_videojs-proxy.js +30294 -0
  43. package/lib/abr-strategies.js +31 -0
  44. package/lib/adaptive-streaming.js +468 -2
  45. package/lib/all.js +25 -2
  46. package/lib/chapters.js +205 -1
  47. package/lib/cld-video-player.min.css +5 -22
  48. package/lib/colors.js +59 -1
  49. package/lib/{schema.json → config/configSchema.json} +19 -0
  50. package/lib/dash.js +69943 -2
  51. package/lib/debug.js +322 -1
  52. package/lib/document.js +770 -0
  53. package/lib/download-button.js +48 -0
  54. package/lib/fetch-config.js +93 -0
  55. package/lib/ima.js +6851 -1
  56. package/lib/index.js +27 -0
  57. package/lib/interaction-areas.const.js +24 -0
  58. package/lib/interaction-areas.service.js +469 -0
  59. package/lib/lazy.js +20 -0
  60. package/lib/noop.js +33 -0
  61. package/lib/player-api.js +469 -0
  62. package/lib/player.js +7 -2
  63. package/lib/playlist-panel.js +602 -0
  64. package/lib/playlist.js +637 -1
  65. package/lib/querystring.js +81 -0
  66. package/lib/recommendations-overlay.js +320 -1
  67. package/lib/share.js +129 -1
  68. package/lib/shoppable-post-widget.js +572 -0
  69. package/lib/shoppable-widget.js +77 -0
  70. package/lib/throttle.js +318 -0
  71. package/lib/toNumber.js +134 -0
  72. package/lib/validators-functions.js +485 -0
  73. package/lib/video-player.js +16241 -0
  74. package/lib/videoPlayer.js +7 -2
  75. package/lib/videojs-contrib-hlsjs.js +37638 -0
  76. package/lib/visual-search.js +235 -1
  77. package/package.json +31 -15
  78. package/lib/adaptive-streaming.js.LICENSE.txt +0 -3
  79. package/lib/all.js.LICENSE.txt +0 -25
  80. package/lib/cld-video-player.js +0 -2
  81. package/lib/cld-video-player.js.LICENSE.txt +0 -21
  82. package/lib/dash.js.LICENSE.txt +0 -1842
  83. package/lib/interaction-areas.js +0 -1
  84. package/lib/player.js.LICENSE.txt +0 -21
  85. package/lib/shoppable.js +0 -1
  86. package/lib/videoPlayer.js.LICENSE.txt +0 -21
@@ -0,0 +1,469 @@
1
+ import { c as commonjsGlobal, g as getDefaultExportFromCjs } from './_commonjsHelpers.js';
2
+
3
+ const LEGACY_CONDITIONAL_OPERATORS = {
4
+ "=": 'eq',
5
+ "!=": 'ne',
6
+ "<": 'lt',
7
+ ">": 'gt',
8
+ "<=": 'lte',
9
+ ">=": 'gte',
10
+ "&&": 'and',
11
+ "||": 'or',
12
+ "*": "mul",
13
+ "/": "div",
14
+ "+": "add",
15
+ "-": "sub",
16
+ "^": "pow"
17
+ };
18
+ const OLD_AKAMAI_SHARED_CDN = "cloudinary-a.akamaihd.net";
19
+ const AKAMAI_SHARED_CDN = "res.cloudinary.com";
20
+ const SHARED_CDN = AKAMAI_SHARED_CDN;
21
+ const LEGACY_PREDEFINED_VARS = {
22
+ "aspect_ratio": "ar",
23
+ "aspectRatio": "ar",
24
+ "current_page": "cp",
25
+ "currentPage": "cp",
26
+ "duration": "du",
27
+ "face_count": "fc",
28
+ "faceCount": "fc",
29
+ "height": "h",
30
+ "initial_aspect_ratio": "iar",
31
+ "initial_height": "ih",
32
+ "initial_width": "iw",
33
+ "initialAspectRatio": "iar",
34
+ "initialHeight": "ih",
35
+ "initialWidth": "iw",
36
+ "initial_duration": "idu",
37
+ "initialDuration": "idu",
38
+ "page_count": "pc",
39
+ "page_x": "px",
40
+ "page_y": "py",
41
+ "pageCount": "pc",
42
+ "pageX": "px",
43
+ "pageY": "py",
44
+ "tags": "tags",
45
+ "width": "w"
46
+ };
47
+ const NUMBER_PATTERN = "([0-9]*)\\.([0-9]+)|([0-9]+)";
48
+ const OFFSET_ANY_PATTERN = `(${NUMBER_PATTERN})([%pP])?`;
49
+ const RANGE_VALUE_RE = RegExp(`^${OFFSET_ANY_PATTERN}$`);
50
+ const OFFSET_ANY_PATTERN_RE = RegExp(`(${OFFSET_ANY_PATTERN})\\.\\.(${OFFSET_ANY_PATTERN})`);
51
+ const LAYER_KEYWORD_PARAMS = {
52
+ font_weight: "normal",
53
+ font_style: "normal",
54
+ text_decoration: "none",
55
+ text_align: '',
56
+ stroke: "none"
57
+ };
58
+
59
+ function unsigned_url_prefix(source, cloud_name, private_cdn, cdn_subdomain, secure_cdn_subdomain, cname, secure, secure_distribution) {
60
+ let prefix;
61
+ if (cloud_name.indexOf("/") === 0) {
62
+ return '/res' + cloud_name;
63
+ }
64
+ let shared_domain = !private_cdn;
65
+ if (secure) {
66
+ if ((secure_distribution == null) || secure_distribution === OLD_AKAMAI_SHARED_CDN) {
67
+ secure_distribution = private_cdn ? cloud_name + "-res.cloudinary.com" : SHARED_CDN;
68
+ }
69
+ if (shared_domain == null) {
70
+ shared_domain = secure_distribution === SHARED_CDN;
71
+ }
72
+ prefix = 'https://' + secure_distribution;
73
+ }
74
+ else if (cname) {
75
+ // let subdomain = cdn_subdomain ? 'a' + ((crc32(source) % 5) + 1) + '.' : '';
76
+ prefix = 'http://' + cname;
77
+ }
78
+ else {
79
+ let cdn_part = private_cdn ? cloud_name + '-' : '';
80
+ let host = [cdn_part, 'res', '.cloudinary.com'].join('');
81
+ prefix = 'http://' + host;
82
+ }
83
+ if (shared_domain) {
84
+ prefix += '/' + cloud_name;
85
+ }
86
+ return prefix;
87
+ }
88
+
89
+ const getCloudinaryUrlPrefix = cloudinaryConfig => {
90
+ return unsigned_url_prefix(null, cloudinaryConfig.cloud_name, cloudinaryConfig.private_cdn, cloudinaryConfig.cdn_subdomain, cloudinaryConfig.secure_cdn_subdomain, cloudinaryConfig.cname, cloudinaryConfig.secure ?? true, cloudinaryConfig.secure_distribution);
91
+ };
92
+
93
+ var css_escape$1 = {exports: {}};
94
+
95
+ /*! https://mths.be/cssescape v1.5.1 by @mathias | MIT license */
96
+ var css_escape = css_escape$1.exports;
97
+
98
+ var hasRequiredCss_escape;
99
+
100
+ function requireCss_escape () {
101
+ if (hasRequiredCss_escape) return css_escape$1.exports;
102
+ hasRequiredCss_escape = 1;
103
+ (function (module, exports$1) {
104
+ (function(root, factory) {
105
+ // https://github.com/umdjs/umd/blob/master/returnExports.js
106
+ {
107
+ // For Node.js.
108
+ module.exports = factory(root);
109
+ }
110
+ }(typeof commonjsGlobal != 'undefined' ? commonjsGlobal : css_escape, function(root) {
111
+
112
+ if (root.CSS && root.CSS.escape) {
113
+ return root.CSS.escape;
114
+ }
115
+
116
+ // https://drafts.csswg.org/cssom/#serialize-an-identifier
117
+ var cssEscape = function(value) {
118
+ if (arguments.length == 0) {
119
+ throw new TypeError('`CSS.escape` requires an argument.');
120
+ }
121
+ var string = String(value);
122
+ var length = string.length;
123
+ var index = -1;
124
+ var codeUnit;
125
+ var result = '';
126
+ var firstCodeUnit = string.charCodeAt(0);
127
+ while (++index < length) {
128
+ codeUnit = string.charCodeAt(index);
129
+ // Note: there’s no need to special-case astral symbols, surrogate
130
+ // pairs, or lone surrogates.
131
+
132
+ // If the character is NULL (U+0000), then the REPLACEMENT CHARACTER
133
+ // (U+FFFD).
134
+ if (codeUnit == 0x0000) {
135
+ result += '\uFFFD';
136
+ continue;
137
+ }
138
+
139
+ if (
140
+ // If the character is in the range [\1-\1F] (U+0001 to U+001F) or is
141
+ // U+007F, […]
142
+ (codeUnit >= 0x0001 && codeUnit <= 0x001F) || codeUnit == 0x007F ||
143
+ // If the character is the first character and is in the range [0-9]
144
+ // (U+0030 to U+0039), […]
145
+ (index == 0 && codeUnit >= 0x0030 && codeUnit <= 0x0039) ||
146
+ // If the character is the second character and is in the range [0-9]
147
+ // (U+0030 to U+0039) and the first character is a `-` (U+002D), […]
148
+ (
149
+ index == 1 &&
150
+ codeUnit >= 0x0030 && codeUnit <= 0x0039 &&
151
+ firstCodeUnit == 0x002D
152
+ )
153
+ ) {
154
+ // https://drafts.csswg.org/cssom/#escape-a-character-as-code-point
155
+ result += '\\' + codeUnit.toString(16) + ' ';
156
+ continue;
157
+ }
158
+
159
+ if (
160
+ // If the character is the first character and is a `-` (U+002D), and
161
+ // there is no second character, […]
162
+ index == 0 &&
163
+ length == 1 &&
164
+ codeUnit == 0x002D
165
+ ) {
166
+ result += '\\' + string.charAt(index);
167
+ continue;
168
+ }
169
+
170
+ // If the character is not handled by one of the above rules and is
171
+ // greater than or equal to U+0080, is `-` (U+002D) or `_` (U+005F), or
172
+ // is in one of the ranges [0-9] (U+0030 to U+0039), [A-Z] (U+0041 to
173
+ // U+005A), or [a-z] (U+0061 to U+007A), […]
174
+ if (
175
+ codeUnit >= 0x0080 ||
176
+ codeUnit == 0x002D ||
177
+ codeUnit == 0x005F ||
178
+ codeUnit >= 0x0030 && codeUnit <= 0x0039 ||
179
+ codeUnit >= 0x0041 && codeUnit <= 0x005A ||
180
+ codeUnit >= 0x0061 && codeUnit <= 0x007A
181
+ ) {
182
+ // the character itself
183
+ result += string.charAt(index);
184
+ continue;
185
+ }
186
+
187
+ // Otherwise, the escaped character.
188
+ // https://drafts.csswg.org/cssom/#escape-a-character
189
+ result += '\\' + string.charAt(index);
190
+
191
+ }
192
+ return result;
193
+ };
194
+
195
+ if (!root.CSS) {
196
+ root.CSS = {};
197
+ }
198
+
199
+ root.CSS.escape = cssEscape;
200
+ return cssEscape;
201
+
202
+ }));
203
+ } (css_escape$1));
204
+ return css_escape$1.exports;
205
+ }
206
+
207
+ var css_escapeExports = requireCss_escape();
208
+ var cssEscape = /*@__PURE__*/getDefaultExportFromCjs(css_escapeExports);
209
+
210
+ /**
211
+ * Minimal Cloudinary poster URL builder for video first frame.
212
+ * Used by schedule bootstrap when outside schedule (no full player loaded).
213
+ */
214
+ const POSTER_TRANSFORMATION = 'so_0,f_auto,q_auto';
215
+
216
+ /**
217
+ * Build Cloudinary video poster (first frame) URL.
218
+ * @param {string} cloudName - Cloudinary cloud name
219
+ * @param {string} publicId - Video public ID
220
+ * @param {object} [cloudinaryConfig] - Optional: secure, private_cdn, cdn_subdomain, cname, secure_distribution
221
+ * @returns {string} Poster image URL
222
+ */
223
+ const buildPosterUrl = function (cloudName, publicId) {
224
+ let cloudinaryConfig = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
225
+ const config = {
226
+ cloud_name: cloudName || cloudinaryConfig.cloud_name,
227
+ ...cloudinaryConfig,
228
+ secure: cloudinaryConfig.secure ?? true
229
+ };
230
+ const prefix = getCloudinaryUrlPrefix(config);
231
+ return `${prefix}/video/upload/${POSTER_TRANSFORMATION}/${publicId}`;
232
+ };
233
+
234
+ /**
235
+ * Schedule utilities: weekly time-range parsing and bootstrap (poster rendering).
236
+ * Uses browser local time. No videojs dependency for the bootstrap path.
237
+ */
238
+ const INTERNAL_ANALYTICS_URL = 'https://analytics-api-s.cloudinary.com';
239
+ const sendScheduleImageAnalytics = options => {
240
+ const allowReport = options?.sourceOptions?.allowUsageReport ?? options?.allowUsageReport;
241
+ if (allowReport === false) return;
242
+ try {
243
+ const params = new URLSearchParams({
244
+ scheduleImageRendered: 'true',
245
+ cloudName: options?.cloudName || options?.cloudinaryConfig?.cloud_name || ''
246
+ }).toString();
247
+ fetch(`${INTERNAL_ANALYTICS_URL}/video_player_source?${params}`);
248
+ } catch {
249
+ // noop
250
+ }
251
+ };
252
+ const getCloudNameFromOptions = options => options?.cloudName || options?.cloud_name || options?.cloudinaryConfig?.cloud_name;
253
+ const getPublicIdFromOptions = options => options?.publicId || options?.sourceOptions?.publicId;
254
+
255
+ /**
256
+ * Returns true when schedule.weekly is configured and current time is outside the schedule.
257
+ * @param {object} options - player options
258
+ * @returns {boolean}
259
+ */
260
+ const shouldUseScheduleBootstrap = options => {
261
+ const schedule = options?.schedule;
262
+ const weekly = schedule?.weekly;
263
+ return Array.isArray(weekly) && weekly.length > 0 && !isWithinSchedule(schedule, new Date());
264
+ };
265
+
266
+ /**
267
+ * Bootstrap path when outside schedule: render poster, return stub with loadPlayer().
268
+ * @param {string|HTMLElement} elem - Element id or video element
269
+ * @param {object} options - player options
270
+ * @returns {object} Stub with source() and loadPlayer()
271
+ */
272
+ const scheduleBootstrap = (elem, options) => {
273
+ const videoElement = getElementForSchedule(elem);
274
+ const cloudName = getCloudNameFromOptions(options);
275
+ const publicId = getPublicIdFromOptions(options);
276
+ if (!cloudName || !publicId) {
277
+ throw new Error('schedule.weekly requires cloudName and publicId when outside schedule');
278
+ }
279
+ const cloudinaryConfig = options?.cloudinaryConfig || {
280
+ cloud_name: cloudName
281
+ };
282
+ const posterUrl = buildPosterUrl(cloudName, publicId, cloudinaryConfig);
283
+ const fluid = options?.fluid !== false;
284
+ const {
285
+ container,
286
+ videoElement: vEl
287
+ } = renderScheduleImage(videoElement, posterUrl, {
288
+ fluid,
289
+ width: options?.width,
290
+ height: options?.height,
291
+ cropMode: options?.sourceOptions?.cropMode
292
+ });
293
+ sendScheduleImageAnalytics(options);
294
+ const stub = {
295
+ source: () => stub,
296
+ loadPlayer: () => {
297
+ if (container && container.parentNode) {
298
+ container.parentNode.removeChild(container);
299
+ }
300
+ vEl.style.display = '';
301
+ return import('./video-player.js').then(function (n) { return n.v; }).then(m => m.createVideoPlayer(vEl, options));
302
+ }
303
+ };
304
+ return stub;
305
+ };
306
+ const DAY_MAP = {
307
+ sunday: 0,
308
+ sun: 0,
309
+ monday: 1,
310
+ mon: 1,
311
+ tuesday: 2,
312
+ tue: 2,
313
+ tues: 2,
314
+ wednesday: 3,
315
+ wed: 3,
316
+ thursday: 4,
317
+ thu: 4,
318
+ thur: 4,
319
+ thurs: 4,
320
+ friday: 5,
321
+ fri: 5,
322
+ saturday: 6,
323
+ sat: 6
324
+ };
325
+ const FLUID_CLASS = 'cld-fluid';
326
+
327
+ /**
328
+ * Parse readable day-of-week string to JS Date.getDay() value (0=Sun .. 6=Sat).
329
+ * @param {string} day - Full or abbreviated day name (case-insensitive)
330
+ * @returns {number|null} 0-6, or null if invalid
331
+ */
332
+ const parseDay = day => {
333
+ if (typeof day !== 'string') return null;
334
+ const key = day.toLowerCase().trim();
335
+ return DAY_MAP[key] ?? null;
336
+ };
337
+
338
+ /**
339
+ * Parse "HH:mm" string to minutes since midnight.
340
+ * @param {string} timeStr - "09:00" or "17:30"
341
+ * @returns {number|null} minutes, or null if invalid
342
+ */
343
+ const parseTime = timeStr => {
344
+ if (typeof timeStr !== 'string') return null;
345
+ const match = timeStr.trim().match(/^(\d{1,2}):(\d{2})$/);
346
+ if (!match) return null;
347
+ const h = parseInt(match[1], 10);
348
+ const m = parseInt(match[2], 10);
349
+ if (h < 0 || h > 23 || m < 0 || m > 59) return null;
350
+ return h * 60 + m;
351
+ };
352
+
353
+ /**
354
+ * Check if a date falls within any configured weekly slot (local time).
355
+ * @param {{ weekly?: Array<{ day: string, start: string, duration: number }> }} schedule - schedule config
356
+ * @param {Date} date - date to check (uses local time)
357
+ * @returns {boolean} true if within a slot
358
+ */
359
+ const isWithinSchedule = (schedule, date) => {
360
+ const weekly = schedule?.weekly;
361
+ if (!Array.isArray(weekly) || weekly.length === 0) return true;
362
+ const WEEK = 7 * 1440;
363
+ const nowInWeek = date.getDay() * 1440 + date.getHours() * 60 + date.getMinutes();
364
+ for (const slot of weekly) {
365
+ const slotDay = parseDay(slot.day);
366
+ if (slotDay === null) continue;
367
+ const startMin = parseTime(slot.start);
368
+ if (startMin === null || typeof slot.duration !== 'number' || slot.duration <= 0) continue;
369
+ const slotStart = slotDay * 1440 + startMin;
370
+ const durationMin = slot.duration * 60;
371
+ const elapsed = (nowInWeek - slotStart + WEEK) % WEEK;
372
+ if (elapsed < durationMin) return true;
373
+ }
374
+ return false;
375
+ };
376
+
377
+ /**
378
+ * Resolve video element by id or return element. No videojs.
379
+ * @param {string|HTMLElement} elem - Element id (with or without #) or video element
380
+ * @returns {HTMLVideoElement}
381
+ */
382
+ const getElementForSchedule = elem => {
383
+ if (typeof elem === 'string') {
384
+ let id = elem;
385
+ if (id.indexOf('#') === 0) id = id.slice(1);
386
+ try {
387
+ elem = document.querySelector(`#${cssEscape(id)}`);
388
+ } catch {
389
+ elem = null;
390
+ }
391
+ if (!elem) throw new Error(`Could not find element with id ${id}`);
392
+ }
393
+ if (!elem?.tagName) throw new Error('Must specify either an element or an element id.');
394
+ if (elem.tagName !== 'VIDEO') throw new Error('Element is not a video tag.');
395
+ return elem;
396
+ };
397
+
398
+ /**
399
+ * Hide video, show poster image overlay. Keeps video in DOM for load().
400
+ * @param {HTMLVideoElement} videoElement
401
+ * @param {string} posterUrl
402
+ * @param {object} options - fluid, width, height, etc.
403
+ * @returns {{ img: HTMLImageElement, container: HTMLElement, videoElement: HTMLVideoElement }}
404
+ */
405
+ const renderScheduleImage = function (videoElement, posterUrl) {
406
+ let options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
407
+ const fluid = options.fluid !== false;
408
+ const parent = videoElement.parentNode;
409
+ const container = document.createElement('div');
410
+ container.className = 'cld-schedule-poster-container';
411
+ container.style.cssText = 'position:relative;width:100%;height:100%;';
412
+ const img = document.createElement('img');
413
+ img.src = posterUrl;
414
+ img.alt = '';
415
+ img.setAttribute('data-cld-schedule-poster', 'true');
416
+ img.style.cssText = 'display:block;width:100%;height:100%;object-fit:contain;';
417
+ if (fluid) {
418
+ container.classList.add(FLUID_CLASS);
419
+ img.style.objectFit = options.cropMode === 'fill' ? 'cover' : 'contain';
420
+ }
421
+ if (options.width) container.style.width = `${options.width}px`;
422
+ if (options.height) container.style.height = `${options.height}px`;
423
+ videoElement.style.display = 'none';
424
+ container.appendChild(img);
425
+ parent.insertBefore(container, videoElement);
426
+ return {
427
+ img,
428
+ container,
429
+ videoElement
430
+ };
431
+ };
432
+
433
+ const createAsyncPlayer = async (id, playerOptions, ready, createFn) => {
434
+ const mergedOptions = Object.assign({}, playerOptions);
435
+ const videoElement = getElementForSchedule(id);
436
+ const opts = await (async () => {
437
+ try {
438
+ const {
439
+ fetchAndMergeConfig
440
+ } = await import('./fetch-config.js');
441
+ const fetched = await fetchAndMergeConfig(mergedOptions);
442
+ return Object.assign({}, fetched, mergedOptions);
443
+ } catch {
444
+ return mergedOptions;
445
+ }
446
+ })();
447
+ if (shouldUseScheduleBootstrap(opts)) {
448
+ return scheduleBootstrap(id, opts);
449
+ }
450
+ return createFn(videoElement, opts, ready);
451
+ };
452
+ const createMultiplePlayers = async (selector, playerOptions, ready, playerFn) => {
453
+ const nodeList = document.querySelectorAll(selector);
454
+ return Promise.all([...nodeList].map(node => playerFn(node, playerOptions, ready)));
455
+ };
456
+ const createMultipleSync = (selector, playerOptions, ready, playerFn) => {
457
+ const nodeList = document.querySelectorAll(selector);
458
+ return [...nodeList].map(node => playerFn(node, playerOptions, ready));
459
+ };
460
+ const setupCloudinaryGlobal = methods => {
461
+ const cloudinary = {
462
+ ...(window.cloudinary || {}),
463
+ ...methods
464
+ };
465
+ window.cloudinary = cloudinary;
466
+ return cloudinary;
467
+ };
468
+
469
+ export { LAYER_KEYWORD_PARAMS as L, OFFSET_ANY_PATTERN_RE as O, RANGE_VALUE_RE as R, createAsyncPlayer as a, LEGACY_CONDITIONAL_OPERATORS as b, createMultiplePlayers as c, LEGACY_PREDEFINED_VARS as d, cssEscape as e, createMultipleSync as f, getCloudinaryUrlPrefix as g, setupCloudinaryGlobal as s, unsigned_url_prefix as u };