@cloudnest/redxplyr 1.0.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 (127) hide show
  1. package/.editorconfig +10 -0
  2. package/.gitpod.yml +6 -0
  3. package/.node-version +1 -0
  4. package/.prettierrc +7 -0
  5. package/.stickler.yml +5 -0
  6. package/.stylelintrc.json +26 -0
  7. package/CHANGELOG.md +16 -0
  8. package/CONTRIBUTING.md +34 -0
  9. package/CONTROLS.md +49 -0
  10. package/Dockerfile +32 -0
  11. package/LICENSE.md +22 -0
  12. package/README.md +194 -0
  13. package/cspell.json +48 -0
  14. package/dist/redxplyr.css +1 -0
  15. package/dist/redxplyr.js +8801 -0
  16. package/dist/redxplyr.min.js +2 -0
  17. package/dist/redxplyr.min.js.map +1 -0
  18. package/dist/redxplyr.min.mjs +1 -0
  19. package/dist/redxplyr.min.mjs.map +1 -0
  20. package/dist/redxplyr.mjs +8793 -0
  21. package/dist/redxplyr.polyfilled.js +9294 -0
  22. package/dist/redxplyr.polyfilled.min.js +2 -0
  23. package/dist/redxplyr.polyfilled.min.js.map +1 -0
  24. package/dist/redxplyr.polyfilled.min.mjs +1 -0
  25. package/dist/redxplyr.polyfilled.min.mjs.map +1 -0
  26. package/dist/redxplyr.polyfilled.mjs +9286 -0
  27. package/dist/redxplyr.svg +1 -0
  28. package/eslint.config.mjs +39 -0
  29. package/gulpfile.js +8 -0
  30. package/package.json +114 -0
  31. package/pnpm-workspace.yaml +8 -0
  32. package/src/js/captions.js +411 -0
  33. package/src/js/config/defaults.js +459 -0
  34. package/src/js/config/states.js +10 -0
  35. package/src/js/config/types.js +34 -0
  36. package/src/js/console.js +28 -0
  37. package/src/js/controls.js +1870 -0
  38. package/src/js/fullscreen.js +305 -0
  39. package/src/js/html5.js +148 -0
  40. package/src/js/listeners.js +854 -0
  41. package/src/js/media.js +61 -0
  42. package/src/js/plugins/ads.js +647 -0
  43. package/src/js/plugins/preview-thumbnails.js +706 -0
  44. package/src/js/plugins/vimeo.js +443 -0
  45. package/src/js/plugins/youtube.js +451 -0
  46. package/src/js/plyr.d.ts +729 -0
  47. package/src/js/plyr.js +1291 -0
  48. package/src/js/plyr.polyfilled.js +13 -0
  49. package/src/js/source.js +155 -0
  50. package/src/js/storage.js +70 -0
  51. package/src/js/support.js +100 -0
  52. package/src/js/ui.js +297 -0
  53. package/src/js/utils/animation.js +33 -0
  54. package/src/js/utils/arrays.js +23 -0
  55. package/src/js/utils/browser.js +21 -0
  56. package/src/js/utils/elements.js +263 -0
  57. package/src/js/utils/events.js +116 -0
  58. package/src/js/utils/fetch.js +45 -0
  59. package/src/js/utils/i18n.js +47 -0
  60. package/src/js/utils/is.js +81 -0
  61. package/src/js/utils/load-image.js +19 -0
  62. package/src/js/utils/load-script.js +14 -0
  63. package/src/js/utils/load-sprite.js +77 -0
  64. package/src/js/utils/numbers.js +17 -0
  65. package/src/js/utils/objects.js +43 -0
  66. package/src/js/utils/promise.js +14 -0
  67. package/src/js/utils/strings.js +80 -0
  68. package/src/js/utils/style.js +148 -0
  69. package/src/js/utils/time.js +36 -0
  70. package/src/js/utils/urls.js +40 -0
  71. package/src/sass/base.scss +69 -0
  72. package/src/sass/components/badges.scss +12 -0
  73. package/src/sass/components/captions.scss +58 -0
  74. package/src/sass/components/control.scss +52 -0
  75. package/src/sass/components/controls.scss +65 -0
  76. package/src/sass/components/menus.scss +205 -0
  77. package/src/sass/components/poster.scss +27 -0
  78. package/src/sass/components/progress.scss +107 -0
  79. package/src/sass/components/sliders.scss +99 -0
  80. package/src/sass/components/times.scss +20 -0
  81. package/src/sass/components/tooltips.scss +91 -0
  82. package/src/sass/components/volume.scss +18 -0
  83. package/src/sass/lib/animation.scss +31 -0
  84. package/src/sass/lib/css-vars.scss +103 -0
  85. package/src/sass/lib/functions.scss +3 -0
  86. package/src/sass/lib/mixins.scss +82 -0
  87. package/src/sass/plugins/ads.scss +53 -0
  88. package/src/sass/plugins/preview-thumbnails/index.scss +121 -0
  89. package/src/sass/plugins/preview-thumbnails/settings.scss +17 -0
  90. package/src/sass/plyr.scss +46 -0
  91. package/src/sass/settings/badges.scss +7 -0
  92. package/src/sass/settings/breakpoints.scss +9 -0
  93. package/src/sass/settings/captions.scss +10 -0
  94. package/src/sass/settings/colors.scss +18 -0
  95. package/src/sass/settings/controls.scss +30 -0
  96. package/src/sass/settings/cosmetics.scss +5 -0
  97. package/src/sass/settings/helpers.scss +7 -0
  98. package/src/sass/settings/menus.scss +13 -0
  99. package/src/sass/settings/progress.scss +18 -0
  100. package/src/sass/settings/sliders.scss +39 -0
  101. package/src/sass/settings/tooltips.scss +11 -0
  102. package/src/sass/settings/type.scss +16 -0
  103. package/src/sass/states/fullscreen.scss +15 -0
  104. package/src/sass/types/audio.scss +61 -0
  105. package/src/sass/types/video.scss +170 -0
  106. package/src/sass/utils/animation.scss +7 -0
  107. package/src/sass/utils/hidden.scss +28 -0
  108. package/src/sprite/plyr-airplay.svg +8 -0
  109. package/src/sprite/plyr-captions-off.svg +7 -0
  110. package/src/sprite/plyr-captions-on.svg +7 -0
  111. package/src/sprite/plyr-download.svg +8 -0
  112. package/src/sprite/plyr-enter-fullscreen.svg +4 -0
  113. package/src/sprite/plyr-exit-fullscreen.svg +4 -0
  114. package/src/sprite/plyr-fast-forward.svg +3 -0
  115. package/src/sprite/plyr-logo-vimeo.svg +6 -0
  116. package/src/sprite/plyr-logo-youtube.svg +6 -0
  117. package/src/sprite/plyr-muted.svg +8 -0
  118. package/src/sprite/plyr-pause.svg +8 -0
  119. package/src/sprite/plyr-pip.svg +6 -0
  120. package/src/sprite/plyr-play.svg +5 -0
  121. package/src/sprite/plyr-restart.svg +5 -0
  122. package/src/sprite/plyr-rewind.svg +3 -0
  123. package/src/sprite/plyr-settings.svg +5 -0
  124. package/src/sprite/plyr-volume.svg +11 -0
  125. package/tasks/build.js +226 -0
  126. package/tasks/deploy.js +216 -0
  127. package/tasks/utils/publish.js +34 -0
@@ -0,0 +1,459 @@
1
+ // ==========================================================================
2
+ // Plyr default config
3
+ // ==========================================================================
4
+
5
+ const defaults = {
6
+ // Disable
7
+ enabled: true,
8
+
9
+ // Custom media title
10
+ title: '',
11
+
12
+ // Logging to console
13
+ debug: false,
14
+
15
+ // Auto play (if supported)
16
+ autoplay: false,
17
+
18
+ // Only allow one media playing at once (vimeo only)
19
+ autopause: true,
20
+
21
+ // Allow inline playback on iOS
22
+ playsinline: true,
23
+
24
+ // Default time to skip when rewind/fast forward
25
+ seekTime: 10,
26
+
27
+ // Default volume
28
+ volume: 1,
29
+ muted: false,
30
+
31
+ // Pass a custom duration
32
+ duration: null,
33
+
34
+ // Display the media duration on load in the current time position
35
+ // If you have opted to display both duration and currentTime, this is ignored
36
+ displayDuration: true,
37
+
38
+ // Invert the current time to be a countdown
39
+ invertTime: true,
40
+
41
+ // Clicking the currentTime inverts it's value to show time left rather than elapsed
42
+ toggleInvert: true,
43
+
44
+ // Force an aspect ratio
45
+ // The format must be `'w:h'` (e.g. `'16:9'`)
46
+ ratio: null,
47
+
48
+ // Click video container to play/pause
49
+ clickToPlay: true,
50
+
51
+ // Auto hide the controls
52
+ hideControls: true,
53
+
54
+ // Reset to start when playback ended
55
+ resetOnEnd: false,
56
+
57
+ // Disable the standard context menu
58
+ disableContextMenu: true,
59
+
60
+ // Sprite (for icons)
61
+ loadSprite: true,
62
+ iconPrefix: 'plyr',
63
+ iconUrl: 'https://redxplyr.flyingdarkdev.com/v1/redxplyr.svg',
64
+
65
+ // Blank video (used to prevent errors on source change)
66
+ blankVideo: 'https://redxplyr.flyingdarkdev.com/v1/blank.mp4',
67
+
68
+ // Quality default
69
+ quality: {
70
+ default: 576,
71
+ // The options to display in the UI, if available for the source media
72
+ options: [4320, 2880, 2160, 1440, 1080, 720, 576, 480, 360, 240],
73
+ forced: false,
74
+ onChange: null,
75
+ },
76
+
77
+ // Set loops
78
+ loop: {
79
+ active: false,
80
+ // start: null,
81
+ // end: null,
82
+ },
83
+
84
+ // Speed default and options to display
85
+ speed: {
86
+ selected: 1,
87
+ // The options to display in the UI, if available for the source media (e.g. Vimeo and YouTube only support 0.5x-4x)
88
+ options: [0.5, 0.75, 1, 1.25, 1.5, 1.75, 2, 4],
89
+ },
90
+
91
+ // Keyboard shortcut settings
92
+ keyboard: {
93
+ focused: true,
94
+ global: false,
95
+ },
96
+
97
+ // Display tooltips
98
+ tooltips: {
99
+ controls: false,
100
+ seek: true,
101
+ },
102
+
103
+ // Captions settings
104
+ captions: {
105
+ active: false,
106
+ language: 'auto',
107
+ // Listen to new tracks added after Plyr is initialized.
108
+ // This is needed for streaming captions, but may result in unselectable options
109
+ update: false,
110
+ },
111
+
112
+ // Fullscreen settings
113
+ fullscreen: {
114
+ enabled: true, // Allow fullscreen?
115
+ fallback: true, // Fallback using full viewport/window
116
+ iosNative: false, // Use the native fullscreen in iOS (disables custom controls)
117
+ // Selector for the fullscreen container so contextual / non-player content can remain visible in fullscreen mode
118
+ // Non-ancestors of the player element will be ignored
119
+ // container: null, // defaults to the player element
120
+ },
121
+
122
+ // Local storage
123
+ storage: {
124
+ enabled: true,
125
+ key: 'plyr',
126
+ },
127
+
128
+ // Default controls
129
+ controls: [
130
+ 'play-large',
131
+ // 'restart',
132
+ // 'rewind',
133
+ 'play',
134
+ // 'fast-forward',
135
+ 'progress',
136
+ 'current-time',
137
+ // 'duration',
138
+ 'mute',
139
+ 'volume',
140
+ 'captions',
141
+ 'settings',
142
+ 'pip',
143
+ 'airplay',
144
+ // 'download',
145
+ 'fullscreen',
146
+ ],
147
+ settings: ['captions', 'quality', 'speed'],
148
+
149
+ // Localisation
150
+ i18n: {
151
+ restart: 'Restart',
152
+ rewind: 'Rewind {seektime}s',
153
+ play: 'Play',
154
+ pause: 'Pause',
155
+ fastForward: 'Forward {seektime}s',
156
+ seek: 'Seek',
157
+ seekLabel: '{currentTime} of {duration}',
158
+ played: 'Played',
159
+ buffered: 'Buffered',
160
+ currentTime: 'Current time',
161
+ duration: 'Duration',
162
+ volume: 'Volume',
163
+ mute: 'Mute',
164
+ unmute: 'Unmute',
165
+ enableCaptions: 'Enable captions',
166
+ disableCaptions: 'Disable captions',
167
+ download: 'Download',
168
+ enterFullscreen: 'Enter fullscreen',
169
+ exitFullscreen: 'Exit fullscreen',
170
+ frameTitle: 'Player for {title}',
171
+ captions: 'Captions',
172
+ settings: 'Settings',
173
+ pip: 'PIP',
174
+ menuBack: 'Go back to previous menu',
175
+ speed: 'Speed',
176
+ normal: 'Normal',
177
+ quality: 'Quality',
178
+ loop: 'Loop',
179
+ start: 'Start',
180
+ end: 'End',
181
+ all: 'All',
182
+ reset: 'Reset',
183
+ disabled: 'Disabled',
184
+ enabled: 'Enabled',
185
+ advertisement: 'Ad',
186
+ qualityBadge: {
187
+ 2160: '4K',
188
+ 1440: 'HD',
189
+ 1080: 'HD',
190
+ 720: 'HD',
191
+ 576: 'SD',
192
+ 480: 'SD',
193
+ },
194
+ },
195
+
196
+ // URLs
197
+ urls: {
198
+ download: null,
199
+ vimeo: {
200
+ sdk: 'https://player.vimeo.com/api/player.js',
201
+ iframe: 'https://player.vimeo.com/video/{0}?{1}',
202
+ api: 'https://vimeo.com/api/oembed.json?url={0}',
203
+ },
204
+ youtube: {
205
+ sdk: 'https://www.youtube.com/iframe_api',
206
+ api: 'https://noembed.com/embed?url=https://www.youtube.com/watch?v={0}',
207
+ },
208
+ googleIMA: {
209
+ sdk: 'https://imasdk.googleapis.com/js/sdkloader/ima3.js',
210
+ },
211
+ },
212
+
213
+ // Custom control listeners
214
+ listeners: {
215
+ seek: null,
216
+ play: null,
217
+ pause: null,
218
+ restart: null,
219
+ rewind: null,
220
+ fastForward: null,
221
+ mute: null,
222
+ volume: null,
223
+ captions: null,
224
+ download: null,
225
+ fullscreen: null,
226
+ pip: null,
227
+ airplay: null,
228
+ speed: null,
229
+ quality: null,
230
+ loop: null,
231
+ language: null,
232
+ },
233
+
234
+ // Events to watch and bubble
235
+ events: [
236
+ // Events to watch on HTML5 media elements and bubble
237
+ // https://developer.mozilla.org/en/docs/Web/Guide/Events/Media_events
238
+ 'ended',
239
+ 'progress',
240
+ 'stalled',
241
+ 'playing',
242
+ 'waiting',
243
+ 'canplay',
244
+ 'canplaythrough',
245
+ 'loadstart',
246
+ 'loadeddata',
247
+ 'loadedmetadata',
248
+ 'timeupdate',
249
+ 'volumechange',
250
+ 'play',
251
+ 'pause',
252
+ 'error',
253
+ 'seeking',
254
+ 'seeked',
255
+ 'emptied',
256
+ 'ratechange',
257
+ 'cuechange',
258
+
259
+ // Custom events
260
+ 'download',
261
+ 'enterfullscreen',
262
+ 'exitfullscreen',
263
+ 'captionsenabled',
264
+ 'captionsdisabled',
265
+ 'languagechange',
266
+ 'controlshidden',
267
+ 'controlsshown',
268
+ 'ready',
269
+
270
+ // YouTube
271
+ 'statechange',
272
+
273
+ // Quality
274
+ 'qualitychange',
275
+
276
+ // Ads
277
+ 'adsloaded',
278
+ 'adscontentpause',
279
+ 'adscontentresume',
280
+ 'adstarted',
281
+ 'adsmidpoint',
282
+ 'adscomplete',
283
+ 'adsallcomplete',
284
+ 'adsimpression',
285
+ 'adsclick',
286
+ ],
287
+
288
+ // Selectors
289
+ // Change these to match your template if using custom HTML
290
+ selectors: {
291
+ editable: 'input, textarea, select, [contenteditable]',
292
+ container: '.plyr',
293
+ controls: {
294
+ container: null,
295
+ wrapper: '.plyr__controls',
296
+ },
297
+ labels: '[data-plyr]',
298
+ buttons: {
299
+ play: '[data-plyr="play"]',
300
+ pause: '[data-plyr="pause"]',
301
+ restart: '[data-plyr="restart"]',
302
+ rewind: '[data-plyr="rewind"]',
303
+ fastForward: '[data-plyr="fast-forward"]',
304
+ mute: '[data-plyr="mute"]',
305
+ captions: '[data-plyr="captions"]',
306
+ download: '[data-plyr="download"]',
307
+ fullscreen: '[data-plyr="fullscreen"]',
308
+ pip: '[data-plyr="pip"]',
309
+ airplay: '[data-plyr="airplay"]',
310
+ settings: '[data-plyr="settings"]',
311
+ loop: '[data-plyr="loop"]',
312
+ },
313
+ inputs: {
314
+ seek: '[data-plyr="seek"]',
315
+ volume: '[data-plyr="volume"]',
316
+ speed: '[data-plyr="speed"]',
317
+ language: '[data-plyr="language"]',
318
+ quality: '[data-plyr="quality"]',
319
+ },
320
+ display: {
321
+ currentTime: '.plyr__time--current',
322
+ duration: '.plyr__time--duration',
323
+ buffer: '.plyr__progress__buffer',
324
+ loop: '.plyr__progress__loop', // Used later
325
+ volume: '.plyr__volume--display',
326
+ },
327
+ progress: '.plyr__progress',
328
+ captions: '.plyr__captions',
329
+ caption: '.plyr__caption',
330
+ },
331
+
332
+ // Class hooks added to the player in different states
333
+ classNames: {
334
+ type: 'plyr--{0}',
335
+ provider: 'plyr--{0}',
336
+ video: 'plyr__video-wrapper',
337
+ embed: 'plyr__video-embed',
338
+ videoFixedRatio: 'plyr__video-wrapper--fixed-ratio',
339
+ embedContainer: 'plyr__video-embed__container',
340
+ poster: 'plyr__poster',
341
+ posterEnabled: 'plyr__poster-enabled',
342
+ ads: 'plyr__ads',
343
+ control: 'plyr__control',
344
+ controlPressed: 'plyr__control--pressed',
345
+ playing: 'plyr--playing',
346
+ paused: 'plyr--paused',
347
+ stopped: 'plyr--stopped',
348
+ loading: 'plyr--loading',
349
+ hover: 'plyr--hover',
350
+ tooltip: 'plyr__tooltip',
351
+ cues: 'plyr__cues',
352
+ marker: 'plyr__progress__marker',
353
+ hidden: 'plyr__sr-only',
354
+ hideControls: 'plyr--hide-controls',
355
+ isTouch: 'plyr--is-touch',
356
+ uiSupported: 'plyr--full-ui',
357
+ noTransition: 'plyr--no-transition',
358
+ display: {
359
+ time: 'plyr__time',
360
+ },
361
+ menu: {
362
+ value: 'plyr__menu__value',
363
+ badge: 'plyr__badge',
364
+ open: 'plyr--menu-open',
365
+ },
366
+ captions: {
367
+ enabled: 'plyr--captions-enabled',
368
+ active: 'plyr--captions-active',
369
+ },
370
+ fullscreen: {
371
+ enabled: 'plyr--fullscreen-enabled',
372
+ fallback: 'plyr--fullscreen-fallback',
373
+ },
374
+ pip: {
375
+ supported: 'plyr--pip-supported',
376
+ active: 'plyr--pip-active',
377
+ },
378
+ airplay: {
379
+ supported: 'plyr--airplay-supported',
380
+ active: 'plyr--airplay-active',
381
+ },
382
+ previewThumbnails: {
383
+ // Tooltip thumbs
384
+ thumbContainer: 'plyr__preview-thumb',
385
+ thumbContainerShown: 'plyr__preview-thumb--is-shown',
386
+ imageContainer: 'plyr__preview-thumb__image-container',
387
+ timeContainer: 'plyr__preview-thumb__time-container',
388
+ // Scrubbing
389
+ scrubbingContainer: 'plyr__preview-scrubbing',
390
+ scrubbingContainerShown: 'plyr__preview-scrubbing--is-shown',
391
+ },
392
+ },
393
+
394
+ // Embed attributes
395
+ attributes: {
396
+ embed: {
397
+ provider: 'data-plyr-provider',
398
+ id: 'data-plyr-embed-id',
399
+ hash: 'data-plyr-embed-hash',
400
+ },
401
+ },
402
+
403
+ // Advertisements plugin
404
+ // Register for an account here: http://vi.ai/publisher-video-monetization/?aid=plyrio
405
+ ads: {
406
+ enabled: false,
407
+ publisherId: '',
408
+ tagUrl: '',
409
+ },
410
+
411
+ // Preview Thumbnails plugin
412
+ previewThumbnails: {
413
+ enabled: false,
414
+ src: '',
415
+ withCredentials: false,
416
+ },
417
+
418
+ // Vimeo plugin
419
+ vimeo: {
420
+ byline: false,
421
+ portrait: false,
422
+ title: false,
423
+ speed: true,
424
+ transparent: false,
425
+ // Custom settings from Plyr
426
+ customControls: true,
427
+ referrerPolicy: null, // https://developer.mozilla.org/en-US/docs/Web/API/HTMLIFrameElement/referrerPolicy
428
+ // Whether the owner of the video has a Pro or Business account
429
+ // (which allows us to properly hide controls without CSS hacks, etc)
430
+ premium: false,
431
+ },
432
+
433
+ // YouTube plugin
434
+ youtube: {
435
+ rel: 0, // No related vids
436
+ showinfo: 0, // Hide info
437
+ iv_load_policy: 3, // Hide annotations
438
+ modestbranding: 1, // Hide logos as much as possible (they still show one in the corner when paused)
439
+ // Custom settings from Plyr
440
+ customControls: true,
441
+ noCookie: false, // Whether to use an alternative version of YouTube without cookies
442
+ },
443
+
444
+ // Media Metadata
445
+ mediaMetadata: {
446
+ title: '',
447
+ artist: '',
448
+ album: '',
449
+ artwork: [],
450
+ },
451
+
452
+ // Markers
453
+ markers: {
454
+ enabled: false,
455
+ points: [],
456
+ },
457
+ };
458
+
459
+ export default defaults;
@@ -0,0 +1,10 @@
1
+ // ==========================================================================
2
+ // Plyr states
3
+ // ==========================================================================
4
+
5
+ export const pip = {
6
+ active: 'picture-in-picture',
7
+ inactive: 'inline',
8
+ };
9
+
10
+ export default { pip };
@@ -0,0 +1,34 @@
1
+ // ==========================================================================
2
+ // Plyr supported types and providers
3
+ // ==========================================================================
4
+
5
+ export const providers = {
6
+ html5: 'html5',
7
+ youtube: 'youtube',
8
+ vimeo: 'vimeo',
9
+ };
10
+
11
+ export const types = {
12
+ audio: 'audio',
13
+ video: 'video',
14
+ };
15
+
16
+ /**
17
+ * Get provider by URL
18
+ * @param {string} url
19
+ */
20
+ export function getProviderByUrl(url) {
21
+ // YouTube
22
+ if (/^(?:https?:\/\/)?(?:www\.)?(?:youtube\.com|youtube-nocookie\.com|youtu\.?be)\/.+$/.test(url)) {
23
+ return providers.youtube;
24
+ }
25
+
26
+ // Vimeo
27
+ if (/^https?:\/\/player.vimeo.com\/video\/\d{0,9}(?=\b|\/)/.test(url)) {
28
+ return providers.vimeo;
29
+ }
30
+
31
+ return null;
32
+ }
33
+
34
+ export default { providers, types };
@@ -0,0 +1,28 @@
1
+ // ==========================================================================
2
+ // Console wrapper
3
+ // ==========================================================================
4
+
5
+ function noop() {}
6
+
7
+ export default class Console {
8
+ constructor(enabled = false) {
9
+ this.enabled = window.console && enabled;
10
+
11
+ if (this.enabled) {
12
+ this.log('Debugging enabled');
13
+ }
14
+ }
15
+
16
+ get log() {
17
+ // eslint-disable-next-line no-console
18
+ return this.enabled ? Function.prototype.bind.call(console.log, console) : noop;
19
+ }
20
+
21
+ get warn() {
22
+ return this.enabled ? Function.prototype.bind.call(console.warn, console) : noop;
23
+ }
24
+
25
+ get error() {
26
+ return this.enabled ? Function.prototype.bind.call(console.error, console) : noop;
27
+ }
28
+ }