tiny-essentials 1.27.1 → 1.28.1

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 (188) hide show
  1. package/README.md +1 -0
  2. package/changelog/1/28/0.md +16 -0
  3. package/changelog/1/28/1.md +23 -0
  4. package/dist/v1/TinyAdvancedRaffle.min.js +1 -1
  5. package/dist/v1/TinyAfterScrollWatcher.min.js +1 -1
  6. package/dist/v1/TinyAnalogClock.min.js +1 -1
  7. package/dist/v1/TinyBasicsEs.min.js +1 -2
  8. package/dist/v1/TinyDayNightCycle.min.js +1 -1
  9. package/dist/v1/TinyDragDropDetector.min.js +1 -1
  10. package/dist/v1/TinyDragger.min.js +1 -1
  11. package/dist/v1/TinyElementObserver.min.js +1 -1
  12. package/dist/v1/TinyEssentials.min.js +1 -2
  13. package/dist/v1/TinyGamepad.min.js +1 -1
  14. package/dist/v1/TinyHtml.min.js +1 -1
  15. package/dist/v1/TinyI18.min.js +1 -1
  16. package/dist/v1/TinyIframeEvents.min.js +1 -1
  17. package/dist/v1/TinyLocalStorage.min.js +1 -1
  18. package/dist/v1/TinyMediaPlayer.min.js +1 -1
  19. package/dist/v1/TinyNewWinEvents.min.js +1 -1
  20. package/dist/v1/TinyNotifyCenter.min.js +1 -1
  21. package/dist/v1/TinyRadioFm.min.js +1 -1
  22. package/dist/v1/TinyRateLimiter.min.js +1 -1
  23. package/dist/v1/TinySmartScroller.min.js +1 -1
  24. package/dist/v1/TinyTextDiffer.min.js +1 -1
  25. package/dist/v1/TinyTextarea.min.js +1 -1
  26. package/dist/v1/TinyTimeout.min.js +1 -1
  27. package/dist/v1/TinyToastNotify.min.js +1 -1
  28. package/dist/v1/TinyUploadClicker.min.js +1 -2
  29. package/dist/v1/UltraRandomMsgGen.min.js +1 -1
  30. package/dist/v1/basics/array.cjs +57 -9
  31. package/dist/v1/basics/array.d.mts +27 -11
  32. package/dist/v1/basics/array.mjs +51 -9
  33. package/dist/v1/basics/clock.cjs +94 -42
  34. package/dist/v1/basics/clock.d.mts +10 -10
  35. package/dist/v1/basics/clock.mjs +91 -54
  36. package/dist/v1/basics/deprecated/html.cjs +246 -0
  37. package/dist/v1/basics/deprecated/html.d.mts +63 -0
  38. package/dist/v1/basics/deprecated/html.mjs +190 -0
  39. package/dist/v1/basics/extendObjType/Buffer.cjs +13 -0
  40. package/dist/v1/basics/extendObjType/Buffer.d.mts +4 -0
  41. package/dist/v1/basics/extendObjType/Buffer.mjs +8 -0
  42. package/dist/v1/basics/html.cjs +149 -130
  43. package/dist/v1/basics/html.d.mts +26 -61
  44. package/dist/v1/basics/html.mjs +113 -105
  45. package/dist/v1/basics/index.cjs +2 -0
  46. package/dist/v1/basics/index.d.mts +3 -1
  47. package/dist/v1/basics/index.mjs +3 -3
  48. package/dist/v1/basics/mediaContent.cjs +51 -9
  49. package/dist/v1/basics/mediaContent.d.mts +0 -87
  50. package/dist/v1/basics/mediaContent.mjs +40 -10
  51. package/dist/v1/basics/objChecker.cjs +7 -5
  52. package/dist/v1/basics/objChecker.d.mts +3 -2
  53. package/dist/v1/basics/objChecker.mjs +6 -6
  54. package/dist/v1/basics/objFilter.cjs +40 -18
  55. package/dist/v1/basics/objFilter.d.mts +6 -6
  56. package/dist/v1/basics/objFilter.mjs +32 -17
  57. package/dist/v1/basics/simpleMath.cjs +81 -25
  58. package/dist/v1/basics/simpleMath.d.mts +2 -2
  59. package/dist/v1/basics/simpleMath.mjs +70 -27
  60. package/dist/v1/basics/text.cjs +76 -31
  61. package/dist/v1/basics/text.d.mts +69 -7
  62. package/dist/v1/basics/text.mjs +62 -31
  63. package/dist/v1/index.cjs +4 -2
  64. package/dist/v1/index.d.mts +4 -2
  65. package/dist/v1/index.mjs +4 -4
  66. package/dist/v1/libs/TinyAdvancedRaffle.cjs +71 -255
  67. package/dist/v1/libs/TinyAdvancedRaffle.d.mts +6 -134
  68. package/dist/v1/libs/TinyAdvancedRaffle.mjs +69 -228
  69. package/dist/v1/libs/TinyAfterScrollWatcher.cjs +17 -1
  70. package/dist/v1/libs/TinyAfterScrollWatcher.d.mts +4 -1
  71. package/dist/v1/libs/TinyAfterScrollWatcher.mjs +15 -1
  72. package/dist/v1/libs/TinyAnalogClock.cjs +60 -0
  73. package/dist/v1/libs/TinyAnalogClock.d.mts +6 -0
  74. package/dist/v1/libs/TinyAnalogClock.mjs +57 -0
  75. package/dist/v1/libs/TinyClipboard.cjs +2 -0
  76. package/dist/v1/libs/TinyClipboard.d.mts +4 -2
  77. package/dist/v1/libs/TinyClipboard.mjs +2 -0
  78. package/dist/v1/libs/TinyColorConverter.cjs +1 -0
  79. package/dist/v1/libs/TinyColorConverter.d.mts +2 -1
  80. package/dist/v1/libs/TinyColorConverter.mjs +1 -0
  81. package/dist/v1/libs/TinyDayNightCycle.cjs +67 -42
  82. package/dist/v1/libs/TinyDayNightCycle.d.mts +2 -7
  83. package/dist/v1/libs/TinyDayNightCycle.mjs +65 -41
  84. package/dist/v1/libs/TinyDragDropDetector.cjs +25 -0
  85. package/dist/v1/libs/TinyDragDropDetector.d.mts +6 -0
  86. package/dist/v1/libs/TinyDragDropDetector.mjs +22 -0
  87. package/dist/v1/libs/TinyDragger.cjs +46 -19
  88. package/dist/v1/libs/TinyDragger.mjs +45 -18
  89. package/dist/v1/libs/TinyElementObserver.cjs +39 -0
  90. package/dist/v1/libs/TinyElementObserver.d.mts +6 -0
  91. package/dist/v1/libs/TinyElementObserver.mjs +36 -0
  92. package/dist/v1/libs/TinyGamepad.cjs +131 -1
  93. package/dist/v1/libs/TinyGamepad.mjs +129 -1
  94. package/dist/v1/libs/TinyHtml.cjs +1 -1
  95. package/dist/v1/libs/TinyHtml.mjs +2 -2
  96. package/dist/v1/libs/TinyI18.cjs +61 -0
  97. package/dist/v1/libs/TinyI18.d.mts +14 -0
  98. package/dist/v1/libs/TinyI18.mjs +55 -0
  99. package/dist/v1/libs/TinyIframeEvents.cjs +26 -196
  100. package/dist/v1/libs/TinyIframeEvents.d.mts +3 -122
  101. package/dist/v1/libs/TinyIframeEvents.mjs +26 -171
  102. package/dist/v1/libs/TinyLocalStorage.cjs +53 -205
  103. package/dist/v1/libs/TinyLocalStorage.d.mts +6 -127
  104. package/dist/v1/libs/TinyLocalStorage.mjs +50 -178
  105. package/dist/v1/libs/TinyMediaPlayer.cjs +74 -2
  106. package/dist/v1/libs/TinyMediaPlayer.d.mts +12 -2
  107. package/dist/v1/libs/TinyMediaPlayer.mjs +68 -2
  108. package/dist/v1/libs/TinyNewWinEvents.cjs +39 -197
  109. package/dist/v1/libs/TinyNewWinEvents.d.mts +6 -119
  110. package/dist/v1/libs/TinyNewWinEvents.mjs +36 -172
  111. package/dist/v1/libs/TinyNotifyCenter.cjs +36 -0
  112. package/dist/v1/libs/TinyNotifyCenter.d.mts +6 -0
  113. package/dist/v1/libs/TinyNotifyCenter.mjs +32 -0
  114. package/dist/v1/libs/TinyRadioFm.cjs +40 -3
  115. package/dist/v1/libs/TinyRadioFm.d.mts +3 -3
  116. package/dist/v1/libs/TinyRadioFm.mjs +37 -3
  117. package/dist/v1/libs/TinyRateLimiter.cjs +52 -0
  118. package/dist/v1/libs/TinyRateLimiter.d.mts +6 -0
  119. package/dist/v1/libs/TinyRateLimiter.mjs +48 -0
  120. package/dist/v1/libs/TinySmartScroller.cjs +56 -205
  121. package/dist/v1/libs/TinySmartScroller.d.mts +19 -152
  122. package/dist/v1/libs/TinySmartScroller.mjs +55 -181
  123. package/dist/v1/libs/TinyTextDiffer.cjs +19 -18
  124. package/dist/v1/libs/TinyTextDiffer.d.mts +1 -0
  125. package/dist/v1/libs/TinyTextDiffer.mjs +16 -17
  126. package/dist/v1/libs/TinyTextarea.cjs +19 -0
  127. package/dist/v1/libs/TinyTextarea.d.mts +6 -0
  128. package/dist/v1/libs/TinyTextarea.mjs +17 -0
  129. package/dist/v1/libs/TinyTimeout.cjs +11 -1
  130. package/dist/v1/libs/TinyTimeout.mjs +9 -1
  131. package/dist/v1/libs/TinyToastNotify.cjs +35 -0
  132. package/dist/v1/libs/TinyToastNotify.d.mts +6 -0
  133. package/dist/v1/libs/TinyToastNotify.mjs +31 -0
  134. package/dist/v1/libs/TinyUploadClicker.cjs +20 -0
  135. package/dist/v1/libs/TinyUploadClicker.d.mts +6 -0
  136. package/dist/v1/libs/TinyUploadClicker.mjs +17 -0
  137. package/dist/v1/libs/UltraRandomMsgGen.cjs +148 -35
  138. package/dist/v1/libs/UltraRandomMsgGen.d.mts +17 -3
  139. package/dist/v1/libs/UltraRandomMsgGen.mjs +133 -34
  140. package/dist/v1/libs/utils.cjs +21 -0
  141. package/dist/v1/libs/utils.d.mts +2 -0
  142. package/dist/v1/libs/utils.mjs +16 -0
  143. package/docs/v1/Exports.md +0 -1
  144. package/docs/v1/README.md +1 -1
  145. package/docs/v1/basics/array.md +2 -2
  146. package/docs/v1/basics/deprecated/html.md +17 -0
  147. package/docs/v1/basics/fullScreen.md +1 -1
  148. package/docs/v1/basics/html.md +12 -26
  149. package/docs/v1/basics/mediaContent.md +1 -1
  150. package/docs/v1/basics/objChecker.md +1 -1
  151. package/docs/v1/basics/objFilter.md +1 -1
  152. package/docs/v1/basics/text.md +2 -2
  153. package/docs/v1/fileManager/main.md +1 -1
  154. package/docs/v1/libs/ColorSafeStringify.md +1 -1
  155. package/docs/v1/libs/TinyAfterScrollWatcher.md +1 -1
  156. package/docs/v1/libs/TinyAnalogClock.md +1 -1
  157. package/docs/v1/libs/TinyArrayComparator.md +1 -1
  158. package/docs/v1/libs/TinyArrayPaginator.md +1 -1
  159. package/docs/v1/libs/TinyClassManager/TinyPluginInliner.md +2 -2
  160. package/docs/v1/libs/TinyClassManager.md +1 -1
  161. package/docs/v1/libs/TinyClipboard.md +1 -1
  162. package/docs/v1/libs/TinyCookieConsent.md +1 -1
  163. package/docs/v1/libs/TinyDomReadyManager.md +1 -1
  164. package/docs/v1/libs/TinyDragDropDetector.md +1 -1
  165. package/docs/v1/libs/TinyDragger.md +1 -1
  166. package/docs/v1/libs/TinyElementObserver.md +1 -1
  167. package/docs/v1/libs/TinyHtml.md +1 -1
  168. package/docs/v1/libs/TinyIframeEvents.md +10 -10
  169. package/docs/v1/libs/TinyLevelUp.md +1 -1
  170. package/docs/v1/libs/TinyLoadingScreen.md +1 -1
  171. package/docs/v1/libs/TinyLocalStorage.md +3 -3
  172. package/docs/v1/libs/TinyNewWinEvents.md +10 -11
  173. package/docs/v1/libs/TinyNotifications.md +1 -1
  174. package/docs/v1/libs/TinyPromiseQueue.md +2 -2
  175. package/docs/v1/libs/TinyTextDiffer.md +1 -1
  176. package/docs/v1/libs/TinyTextarea.md +1 -1
  177. package/package.json +15 -5
  178. package/dist/v1/TinyBasicsEs.min.js.LICENSE.txt +0 -8
  179. package/dist/v1/TinyEssentials.min.js.LICENSE.txt +0 -8
  180. package/dist/v1/TinyEvents.min.js +0 -1
  181. package/dist/v1/TinyUploadClicker.min.js.LICENSE.txt +0 -8
  182. package/dist/v1/build/TinyEvents.cjs +0 -7
  183. package/dist/v1/build/TinyEvents.d.mts +0 -3
  184. package/dist/v1/build/TinyEvents.mjs +0 -2
  185. package/dist/v1/libs/TinyEvents.cjs +0 -395
  186. package/dist/v1/libs/TinyEvents.d.mts +0 -164
  187. package/dist/v1/libs/TinyEvents.mjs +0 -360
  188. package/docs/v1/libs/TinyEvents.md +0 -187
@@ -104,6 +104,22 @@
104
104
 
105
105
  //////////////////////////////////////////////////////////////////
106
106
 
107
+ const checkString = (/** @type {string} */ val, /** @type {string} */ name) => {
108
+ if (typeof val !== 'string')
109
+ throw new TypeError(`Expected "${name}" to be a string, but received ${typeof val}.`);
110
+ };
111
+ const checkFunction = (/** @type {Function} */ val, /** @type {string} */ name) => {
112
+ if (typeof val !== 'function')
113
+ throw new TypeError(`Expected "${name}" to be a function, but received ${typeof val}.`);
114
+ };
115
+ const checkObject = (/** @type {Object<string, any> | null} */ val, /** @type {string} */ name) => {
116
+ if (typeof val !== 'object' || val === null || Array.isArray(val)) {
117
+ throw new TypeError(
118
+ `Expected "${name}" to be a plain object, but received ${val === null ? 'null' : Array.isArray(val) ? 'array' : typeof val}.`,
119
+ );
120
+ }
121
+ };
122
+
107
123
  /** @type {Map<string, number>} */
108
124
  const _blobCounter = new Map();
109
125
 
@@ -145,6 +161,11 @@ class MediaLoadingError extends Error {
145
161
  * @param {LoadingErrorStage} stage - The stage where the error occurred.
146
162
  */
147
163
  constructor(message, url, stage) {
164
+ checkString(message, 'message');
165
+ checkString(url, 'url');
166
+ if (typeof stage !== 'string')
167
+ throw new TypeError(`Expected "stage" to be a string, but received ${typeof stage}.`);
168
+
148
169
  super(message);
149
170
  this.name = 'MediaLoadingError';
150
171
  this.url = url;
@@ -159,6 +180,8 @@ class MediaLoadingError extends Error {
159
180
  * @private
160
181
  */
161
182
  const generateSimpleHash = async (str) => {
183
+ checkString(str, 'str');
184
+
162
185
  const msgUint8 = new TextEncoder().encode(str);
163
186
  const hashBuffer = await crypto.subtle.digest('SHA-1', msgUint8);
164
187
  const hashArray = Array.from(new Uint8Array(hashBuffer));
@@ -174,9 +197,15 @@ const generateSimpleHash = async (str) => {
174
197
  * @param {Uint8Array|string} data
175
198
  * @param {string} format
176
199
  * @returns {string} The generated Blob URL or original string if already valid.
177
- * @private
178
200
  */
179
201
  const convertToBlobUrl = (data, format = 'image/jpeg') => {
202
+ if (!(data instanceof Uint8Array) && typeof data !== 'string') {
203
+ throw new TypeError(
204
+ `Expected "data" to be an instance of Uint8Array or a string, but received ${typeof data}.`,
205
+ );
206
+ }
207
+ checkString(format, 'format');
208
+
180
209
  const createBlobCounter = (/** @type {Blob} */ blob) => {
181
210
  const url = URL.createObjectURL(blob);
182
211
  const blobUrlUsage = _blobCounter.get(url);
@@ -205,10 +234,11 @@ const convertToBlobUrl = (data, format = 'image/jpeg') => {
205
234
  * Asynchronous helper to convert a Blob URL back to Base64 (Date URL) at export time.
206
235
  * @param {string} url
207
236
  * @returns {Promise<string>}
208
- * @private
209
237
  */
210
238
  const blobUrlToBase64 = async (url) => {
211
- if (typeof url !== 'string' || !url.startsWith('blob:')) return url;
239
+ checkString(url, 'url');
240
+
241
+ if (!url.startsWith('blob:')) return url;
212
242
  try {
213
243
  const response = await fetch(url);
214
244
  const blob = await response.blob();
@@ -227,9 +257,10 @@ const blobUrlToBase64 = async (url) => {
227
257
  /**
228
258
  * Safely revokes Blob URLs to prevent memory leaks from createObjectURL.
229
259
  * @param {MediaContent} content
230
- * @private
231
260
  */
232
261
  const revokeContentUrls = (content) => {
262
+ checkObject(content, 'content');
263
+
233
264
  if (content && Array.isArray(content.picture)) {
234
265
  content.picture.forEach((pic) => {
235
266
  if (typeof pic.data === 'string' && pic.data.startsWith('blob:')) {
@@ -248,7 +279,9 @@ const revokeContentUrls = (content) => {
248
279
  * @param {boolean} isPartial - If true, properties can be undefined.
249
280
  */
250
281
  const validateMediaContent = (common, isPartial) => {
251
- // Helper to check if the property can be ignored in partial mode
282
+ checkObject(common, 'common');
283
+ if (typeof isPartial !== 'boolean') throw new TypeError('Expected "isPartial" to be a boolean.');
284
+
252
285
  const isUndefinedAllowed = (/** @type {any} */ v) => isPartial && typeof v === 'undefined';
253
286
 
254
287
  const isString = (/** @type {string | null | undefined} */ v) =>
@@ -293,6 +326,8 @@ const validateMediaContent = (common, isPartial) => {
293
326
  !isArray(
294
327
  common.picture,
295
328
  (value) =>
329
+ value &&
330
+ typeof value === 'object' &&
296
331
  (typeof value.description === 'undefined' || typeof value.description === 'string') &&
297
332
  (typeof value.name === 'undefined' || typeof value.name === 'string') &&
298
333
  (typeof value.type === 'undefined' || typeof value.type === 'string') &&
@@ -351,10 +386,8 @@ const valMediaContentMetadataPartial = (common) => validateMediaContent(common,
351
386
  */
352
387
  const extractMediaId3Tags = async (url, parseFile) => {
353
388
  // Argument Validation
354
- if (typeof url !== 'string')
355
- throw new TypeError(`Expected url to be a string, but received ${typeof url}.`);
356
- if (typeof parseFile !== 'function')
357
- throw new TypeError(`Expected parseFile to be a function, but received ${typeof parseFile}.`);
389
+ checkString(url, 'url');
390
+ checkFunction(parseFile, 'parseFile');
358
391
 
359
392
  try {
360
393
  // 1. Download the file from the provided URL
@@ -459,11 +492,20 @@ const parseMediaMetadata = async (
459
492
  if (typeof source !== 'string' && !(source instanceof HTMLMediaElement))
460
493
  throw new TypeError('Source must be a string or an HTMLMediaElement.');
461
494
 
495
+ checkObject(defaultMetadata, 'defaultMetadata');
496
+ checkObject(metadata, 'metadata');
497
+ checkFunction(parseFile, 'parseFile');
498
+ checkObject(callbacks, 'callbacks');
499
+
462
500
  if (callbacks.onProgress && typeof callbacks.onProgress !== 'function')
463
501
  throw new TypeError('callbacks.onProgress must be a function.');
464
502
  if (callbacks.onError && typeof callbacks.onError !== 'function')
465
503
  throw new TypeError('callbacks.onError must be a function.');
466
504
 
505
+ if (typeof unknownArtist !== 'string' && typeof unknownArtist !== 'function') {
506
+ throw new TypeError('unknownArtist must be a string or a function returning a string.');
507
+ }
508
+
467
509
  /** @type {HTMLMediaElement} */
468
510
  let audio;
469
511
  /** @type {string} */
@@ -1,90 +1,3 @@
1
- /**
2
- * @typedef {string|(() => string)} UnknownArtistGetter
3
- */
4
- /**
5
- * Represents an image attachment template.
6
- * @template {Uint8Array|string} PictureData
7
- * @typedef {Object} IPictureTemplate
8
- * @property {string} format - The MIME type of the image (e.g., 'image/jpeg').
9
- * @property {PictureData} data - The raw binary data of the image.
10
- * @property {string} [description] - An optional textual description of the image.
11
- * @property {string} [type] - The specific type of picture (e.g., 'cover', 'front', 'back').
12
- * @property {string} [name] - The filename associated with the image.
13
- */
14
- /**
15
- * Represents an image attachment, such as album art.
16
- * @typedef {IPictureTemplate<string>} IPicture
17
- */
18
- /**
19
- * A numeric structure representing track or disk indexing.
20
- * @typedef {{no: number|null, of: number|null}} MediaNumber
21
- */
22
- /**
23
- * This metadata structure is modeled template.
24
- *
25
- * @template {IPictureTemplate<Uint8Array|string>} IPictureContent
26
- * @typedef {Object} ContentMetadataTemplate
27
- * @property {string|null} title - The title of the track.
28
- * @property {string|null} album - The name of the album.
29
- * @property {string|null} albumartist - The primary artist of the album.
30
- * @property {string[]} albumartists - An array of artists associated with the album.
31
- * @property {string[]} genre - An array of genres associated with the track.
32
- * @property {string[]} label - The record label.
33
- * @property {string[]} composer - The composer of the track.
34
- * @property {number|null} year - The release year.
35
- * @property {string|null} artist - The primary artist of the track.
36
- * @property {string[]} artists - An array of artists associated with the track.
37
- * @property {MediaNumber} disk - Disk information containing the current disk number and total disks.
38
- * @property {MediaNumber} track - Track information containing the current track number and total tracks.
39
- * @property {IPictureContent[]} [picture] - An array of picture objects containing album art.
40
- */
41
- /**
42
- * This metadata structure is modeled after the standard output of the
43
- * `music-metadata@11.13.0` npm package.
44
- *
45
- * @typedef {ContentMetadataTemplate<IPicture>} MediaContentMetadata
46
- */
47
- /**
48
- * The core properties required for any content item within the media system.
49
- * @typedef {Object} MediaContentBase
50
- * @property {string} id - Unique identifier.
51
- * @property {string} title - Name of the track/message.
52
- * @property {string} artist - Artist or speaker name.
53
- * @property {number} duration - Duration in milliseconds.
54
- * @property {string} url - Source URL/Path.
55
- * @property {number} [weight=1] - Probability multiplier for random selection mode.
56
- */
57
- /**
58
- * The final content object used within the media, combining
59
- * core playback properties with rich metadata.
60
- *
61
- * @typedef {MediaContentBase & MediaContentMetadata} MediaContent
62
- */
63
- /**
64
- * A promise that resolves to an object containing the extracted metadata.
65
- * @callback ParseMediaContentMetadata
66
- * @param {Blob} data - The raw file blob.
67
- * @returns {Promise<{ common: Partial<ContentMetadataTemplate<IPictureTemplate<Uint8Array|string>>> }>} A promise resolving to the common metadata properties.
68
- */
69
- /**
70
- * @typedef {Object} LoadingMediaProgress
71
- * @property {'loading'|'success'} status - The current status of the operation.
72
- * @property {LoadingProgressStage} stage - The current execution stage.
73
- * @property {ProgressEvent<EventTarget>} [event] - The current loading event.
74
- * @property {string} url - The URL being processed.
75
- */
76
- /**
77
- * @typedef {'INITIALIZING'|'DOWNLOADING'|'METADATA_LOADED'|'EXTRACTING_ID3'|'COMPLETE'} LoadingProgressStage
78
- */
79
- /**
80
- * @typedef {'INITIALIZING'|'DOWNLOADING'|'METADATA'|'ID3'|'UNKNOWN'} LoadingErrorStage
81
- */
82
- /**
83
- * @typedef {Object} MediaLoadingErrorData
84
- * @property {Error} error - The original error object.
85
- * @property {string} url - The URL that failed.
86
- * @property {LoadingErrorStage} stage - The stage where it failed.
87
- */
88
1
  /** @type {Map<string, number>} */
89
2
  export const _blobCounter: Map<string, number>;
90
3
  export function getMediaContentBase(): MediaContentBase;
@@ -87,6 +87,19 @@
87
87
  * @property {LoadingErrorStage} stage - The stage where it failed.
88
88
  */
89
89
  //////////////////////////////////////////////////////////////////
90
+ const checkString = (/** @type {string} */ val, /** @type {string} */ name) => {
91
+ if (typeof val !== 'string')
92
+ throw new TypeError(`Expected "${name}" to be a string, but received ${typeof val}.`);
93
+ };
94
+ const checkFunction = (/** @type {Function} */ val, /** @type {string} */ name) => {
95
+ if (typeof val !== 'function')
96
+ throw new TypeError(`Expected "${name}" to be a function, but received ${typeof val}.`);
97
+ };
98
+ const checkObject = (/** @type {Object<string, any> | null} */ val, /** @type {string} */ name) => {
99
+ if (typeof val !== 'object' || val === null || Array.isArray(val)) {
100
+ throw new TypeError(`Expected "${name}" to be a plain object, but received ${val === null ? 'null' : Array.isArray(val) ? 'array' : typeof val}.`);
101
+ }
102
+ };
90
103
  /** @type {Map<string, number>} */
91
104
  export const _blobCounter = new Map();
92
105
  /** @returns {MediaContentBase} */
@@ -125,6 +138,10 @@ export class MediaLoadingError extends Error {
125
138
  * @param {LoadingErrorStage} stage - The stage where the error occurred.
126
139
  */
127
140
  constructor(message, url, stage) {
141
+ checkString(message, 'message');
142
+ checkString(url, 'url');
143
+ if (typeof stage !== 'string')
144
+ throw new TypeError(`Expected "stage" to be a string, but received ${typeof stage}.`);
128
145
  super(message);
129
146
  this.name = 'MediaLoadingError';
130
147
  this.url = url;
@@ -138,6 +155,7 @@ export class MediaLoadingError extends Error {
138
155
  * @private
139
156
  */
140
157
  export const generateSimpleHash = async (str) => {
158
+ checkString(str, 'str');
141
159
  const msgUint8 = new TextEncoder().encode(str);
142
160
  const hashBuffer = await crypto.subtle.digest('SHA-1', msgUint8);
143
161
  const hashArray = Array.from(new Uint8Array(hashBuffer));
@@ -152,9 +170,12 @@ export const generateSimpleHash = async (str) => {
152
170
  * @param {Uint8Array|string} data
153
171
  * @param {string} format
154
172
  * @returns {string} The generated Blob URL or original string if already valid.
155
- * @private
156
173
  */
157
174
  export const convertToBlobUrl = (data, format = 'image/jpeg') => {
175
+ if (!(data instanceof Uint8Array) && typeof data !== 'string') {
176
+ throw new TypeError(`Expected "data" to be an instance of Uint8Array or a string, but received ${typeof data}.`);
177
+ }
178
+ checkString(format, 'format');
158
179
  const createBlobCounter = (/** @type {Blob} */ blob) => {
159
180
  const url = URL.createObjectURL(blob);
160
181
  const blobUrlUsage = _blobCounter.get(url);
@@ -182,10 +203,10 @@ export const convertToBlobUrl = (data, format = 'image/jpeg') => {
182
203
  * Asynchronous helper to convert a Blob URL back to Base64 (Date URL) at export time.
183
204
  * @param {string} url
184
205
  * @returns {Promise<string>}
185
- * @private
186
206
  */
187
207
  export const blobUrlToBase64 = async (url) => {
188
- if (typeof url !== 'string' || !url.startsWith('blob:'))
208
+ checkString(url, 'url');
209
+ if (!url.startsWith('blob:'))
189
210
  return url;
190
211
  try {
191
212
  const response = await fetch(url);
@@ -205,9 +226,9 @@ export const blobUrlToBase64 = async (url) => {
205
226
  /**
206
227
  * Safely revokes Blob URLs to prevent memory leaks from createObjectURL.
207
228
  * @param {MediaContent} content
208
- * @private
209
229
  */
210
230
  export const revokeContentUrls = (content) => {
231
+ checkObject(content, 'content');
211
232
  if (content && Array.isArray(content.picture)) {
212
233
  content.picture.forEach((pic) => {
213
234
  if (typeof pic.data === 'string' && pic.data.startsWith('blob:')) {
@@ -228,7 +249,9 @@ export const revokeContentUrls = (content) => {
228
249
  * @param {boolean} isPartial - If true, properties can be undefined.
229
250
  */
230
251
  const validateMediaContent = (common, isPartial) => {
231
- // Helper to check if the property can be ignored in partial mode
252
+ checkObject(common, 'common');
253
+ if (typeof isPartial !== 'boolean')
254
+ throw new TypeError('Expected "isPartial" to be a boolean.');
232
255
  const isUndefinedAllowed = (/** @type {any} */ v) => isPartial && typeof v === 'undefined';
233
256
  const isString = (/** @type {string | null | undefined} */ v) => isUndefinedAllowed(v) || typeof v === 'string' || v === null;
234
257
  const isNumber = (/** @type {number | null | undefined}} */ v) => isUndefinedAllowed(v) || typeof v === 'number' || v === null;
@@ -263,7 +286,9 @@ const validateMediaContent = (common, isPartial) => {
263
286
  throw new TypeError('Invalid metadata: "composer" must be an array of string.');
264
287
  if (!isArray(common.artists, (value) => typeof value === 'string'))
265
288
  throw new TypeError('Invalid metadata: "artists" must be an array of string.');
266
- if (!isArray(common.picture, (value) => (typeof value.description === 'undefined' || typeof value.description === 'string') &&
289
+ if (!isArray(common.picture, (value) => value &&
290
+ typeof value === 'object' &&
291
+ (typeof value.description === 'undefined' || typeof value.description === 'string') &&
267
292
  (typeof value.name === 'undefined' || typeof value.name === 'string') &&
268
293
  (typeof value.type === 'undefined' || typeof value.type === 'string') &&
269
294
  typeof value.format === 'string' &&
@@ -313,10 +338,8 @@ export const valMediaContentMetadataPartial = (common) => validateMediaContent(c
313
338
  */
314
339
  export const extractMediaId3Tags = async (url, parseFile) => {
315
340
  // Argument Validation
316
- if (typeof url !== 'string')
317
- throw new TypeError(`Expected url to be a string, but received ${typeof url}.`);
318
- if (typeof parseFile !== 'function')
319
- throw new TypeError(`Expected parseFile to be a function, but received ${typeof parseFile}.`);
341
+ checkString(url, 'url');
342
+ checkFunction(parseFile, 'parseFile');
320
343
  try {
321
344
  // 1. Download the file from the provided URL
322
345
  const response = await fetch(url);
@@ -405,10 +428,17 @@ export const parseMediaMetadata = async (source, defaultMetadata = {}, metadata
405
428
  // Argument Validation
406
429
  if (typeof source !== 'string' && !(source instanceof HTMLMediaElement))
407
430
  throw new TypeError('Source must be a string or an HTMLMediaElement.');
431
+ checkObject(defaultMetadata, 'defaultMetadata');
432
+ checkObject(metadata, 'metadata');
433
+ checkFunction(parseFile, 'parseFile');
434
+ checkObject(callbacks, 'callbacks');
408
435
  if (callbacks.onProgress && typeof callbacks.onProgress !== 'function')
409
436
  throw new TypeError('callbacks.onProgress must be a function.');
410
437
  if (callbacks.onError && typeof callbacks.onError !== 'function')
411
438
  throw new TypeError('callbacks.onError must be a function.');
439
+ if (typeof unknownArtist !== 'string' && typeof unknownArtist !== 'function') {
440
+ throw new TypeError('unknownArtist must be a string or a function returning a string.');
441
+ }
412
442
  /** @type {HTMLMediaElement} */
413
443
  let audio;
414
444
  /** @type {string} */
@@ -4,20 +4,22 @@
4
4
  * Counts the number of elements in an array or the number of properties in an object.
5
5
  *
6
6
  * @param {Array<*>|Record<string | number | symbol, any>} obj - The array or object to count.
7
- * @returns {number} - The count of items (array elements or object keys), or `0` if the input is neither an array nor an object.
7
+ * @returns {number} - The count of items (array elements or object keys).
8
+ * @throws {TypeError} If the input is neither an array nor a pure object.
8
9
  *
9
10
  * @example
10
11
  * countObj([1, 2, 3]); // 3
11
12
  * countObj({ a: 1, b: 2 }); // 2
12
- * countObj('not an object'); // 0
13
+ * countObj('not an object'); // Throws TypeError
13
14
  */
14
15
  function countObj(obj) {
16
+ if (!Array.isArray(obj) && !isJsonObject(obj))
17
+ throw new TypeError('Argument must be either an Array or a pure JSON Object.');
18
+
15
19
  // Is Array
16
20
  if (Array.isArray(obj)) return obj.length;
17
21
  // Object
18
- if (isJsonObject(obj)) return Object.keys(obj).length;
19
- // Nothing
20
- return 0;
22
+ return Object.keys(obj).length;
21
23
  }
22
24
 
23
25
  /**
@@ -2,12 +2,13 @@
2
2
  * Counts the number of elements in an array or the number of properties in an object.
3
3
  *
4
4
  * @param {Array<*>|Record<string | number | symbol, any>} obj - The array or object to count.
5
- * @returns {number} - The count of items (array elements or object keys), or `0` if the input is neither an array nor an object.
5
+ * @returns {number} - The count of items (array elements or object keys).
6
+ * @throws {TypeError} If the input is neither an array nor a pure object.
6
7
  *
7
8
  * @example
8
9
  * countObj([1, 2, 3]); // 3
9
10
  * countObj({ a: 1, b: 2 }); // 2
10
- * countObj('not an object'); // 0
11
+ * countObj('not an object'); // Throws TypeError
11
12
  */
12
13
  export function countObj(obj: Array<any> | Record<string | number | symbol, any>): number;
13
14
  /**
@@ -2,22 +2,22 @@
2
2
  * Counts the number of elements in an array or the number of properties in an object.
3
3
  *
4
4
  * @param {Array<*>|Record<string | number | symbol, any>} obj - The array or object to count.
5
- * @returns {number} - The count of items (array elements or object keys), or `0` if the input is neither an array nor an object.
5
+ * @returns {number} - The count of items (array elements or object keys).
6
+ * @throws {TypeError} If the input is neither an array nor a pure object.
6
7
  *
7
8
  * @example
8
9
  * countObj([1, 2, 3]); // 3
9
10
  * countObj({ a: 1, b: 2 }); // 2
10
- * countObj('not an object'); // 0
11
+ * countObj('not an object'); // Throws TypeError
11
12
  */
12
13
  export function countObj(obj) {
14
+ if (!Array.isArray(obj) && !isJsonObject(obj))
15
+ throw new TypeError('Argument must be either an Array or a pure JSON Object.');
13
16
  // Is Array
14
17
  if (Array.isArray(obj))
15
18
  return obj.length;
16
19
  // Object
17
- if (isJsonObject(obj))
18
- return Object.keys(obj).length;
19
- // Nothing
20
- return 0;
20
+ return Object.keys(obj).length;
21
21
  }
22
22
  /**
23
23
  * Determines whether a given value is a pure JSON object (plain object).
@@ -1,6 +1,5 @@
1
1
  'use strict';
2
2
 
3
- var buffer = require('buffer');
4
3
  var objChecker = require('./objChecker.cjs');
5
4
 
6
5
  const isBrowser = typeof window !== 'undefined' && typeof window.document !== 'undefined';
@@ -34,26 +33,48 @@ const typeValidator = {
34
33
  * If no index is provided, the type is inserted just before 'object' (if it exists), or at the end.
35
34
  *
36
35
  * @param {ExtendObjType|ExtendObjTypeArray} newItems
37
- * - New type validators to be added.
36
+ * - New type validators to be added.
38
37
  * @param {number} [index] - Optional. Position at which to insert each new type. Ignored if the type already exists.
39
38
  * @returns {string[]} - A list of successfully added type names.
40
39
  *
41
40
  * @example
42
41
  * extendObjType({
43
- * htmlElement2: val => typeof HTMLElement !== 'undefined' && val instanceof HTMLElement
42
+ * htmlElement2: val => typeof HTMLElement !== 'undefined' && val instanceof HTMLElement
44
43
  * });
45
44
  *
46
45
  * @example
47
46
  * extendObjType([
48
- * ['alpha', val => typeof val === 'string'],
49
- * ['beta', val => Array.isArray(val)]
47
+ * ['alpha', val => typeof val === 'string'],
48
+ * ['beta', val => Array.isArray(val)]
50
49
  * ]);
51
50
  */
52
51
  function extendObjType(newItems, index) {
52
+ if (typeof newItems !== 'object' || newItems === null) {
53
+ throw new TypeError("Argument 'newItems' must be an object or an array.");
54
+ }
55
+
56
+ if (typeof index !== 'undefined' && typeof index !== 'number') {
57
+ throw new TypeError("Argument 'index' must be a number.");
58
+ }
59
+
53
60
  const added = [];
54
61
 
55
62
  const entries = Array.isArray(newItems) ? newItems : Object.entries(newItems);
56
- for (const [key, fn] of entries) {
63
+
64
+ for (const entry of entries) {
65
+ if (!Array.isArray(entry) || entry.length < 2) {
66
+ throw new TypeError("Each item in 'newItems' array must be a [key, function] pair.");
67
+ }
68
+
69
+ const [key, fn] = entry;
70
+
71
+ if (typeof key !== 'string') {
72
+ throw new TypeError('Validator key must be a string.');
73
+ }
74
+ if (typeof fn !== 'function') {
75
+ throw new TypeError(`Validator for key '${key}' must be a function.`);
76
+ }
77
+
57
78
  if (!typeValidator.items.hasOwnProperty(key)) {
58
79
  // @ts-ignore
59
80
  typeValidator.items[key] = fn;
@@ -87,10 +108,17 @@ function extendObjType(newItems, index) {
87
108
  *
88
109
  * @example
89
110
  * reorderObjTypeOrder([
90
- * 'string', 'number', 'array', 'object'
111
+ * 'string', 'number', 'array', 'object'
91
112
  * ]);
92
113
  */
93
114
  function reorderObjTypeOrder(newOrder) {
115
+ if (!Array.isArray(newOrder)) {
116
+ throw new TypeError("Argument 'newOrder' must be an array of strings.");
117
+ }
118
+ if (!newOrder.every((item) => typeof item === 'string')) {
119
+ throw new TypeError("All elements in 'newOrder' must be strings.");
120
+ }
121
+
94
122
  const currentOrder = [...typeValidator.order]; // shallow clone
95
123
 
96
124
  // All keys in newOrder must exist in currentOrder
@@ -148,7 +176,7 @@ const getType = (val) => {
148
176
  * @param {*} obj - The object to check or identify.
149
177
  * @param {string} [type] - Optional. If provided, checks whether the object matches this type (e.g., "object", "array", "string").
150
178
  * @returns {boolean|string|null} - Returns `true` if the type matches, `false` if not,
151
- * the type string if no type is provided, or `null` if the object is `undefined`.
179
+ * the type string if no type is provided, or `null` if the object is `undefined`.
152
180
  *
153
181
  * @example
154
182
  * objType([], 'array'); // true
@@ -158,6 +186,10 @@ const getType = (val) => {
158
186
  */
159
187
  function objType(obj, type) {
160
188
  if (typeof obj === 'undefined') return null;
189
+ if (typeof type !== 'undefined' && typeof type !== 'string') {
190
+ throw new TypeError("Argument 'type' must be a string.");
191
+ }
192
+
161
193
  const result = getType(obj);
162
194
  if (typeof type === 'string') return result === type.toLowerCase();
163
195
  return result;
@@ -245,16 +277,6 @@ extendObjType([
245
277
  ],
246
278
  ]);
247
279
 
248
- if (!isBrowser) {
249
- extendObjType([
250
- [
251
- 'buffer',
252
- /** @param {*} val @returns {val is Buffer} */
253
- (val) => typeof buffer.Buffer !== 'undefined' && buffer.Buffer.isBuffer(val),
254
- ],
255
- ]);
256
- }
257
-
258
280
  if (isBrowser) {
259
281
  extendObjType([
260
282
  [
@@ -7,19 +7,19 @@
7
7
  * If no index is provided, the type is inserted just before 'object' (if it exists), or at the end.
8
8
  *
9
9
  * @param {ExtendObjType|ExtendObjTypeArray} newItems
10
- * - New type validators to be added.
10
+ * - New type validators to be added.
11
11
  * @param {number} [index] - Optional. Position at which to insert each new type. Ignored if the type already exists.
12
12
  * @returns {string[]} - A list of successfully added type names.
13
13
  *
14
14
  * @example
15
15
  * extendObjType({
16
- * htmlElement2: val => typeof HTMLElement !== 'undefined' && val instanceof HTMLElement
16
+ * htmlElement2: val => typeof HTMLElement !== 'undefined' && val instanceof HTMLElement
17
17
  * });
18
18
  *
19
19
  * @example
20
20
  * extendObjType([
21
- * ['alpha', val => typeof val === 'string'],
22
- * ['beta', val => Array.isArray(val)]
21
+ * ['alpha', val => typeof val === 'string'],
22
+ * ['beta', val => Array.isArray(val)]
23
23
  * ]);
24
24
  */
25
25
  export function extendObjType(newItems: ExtendObjType | ExtendObjTypeArray, index?: number): string[];
@@ -33,7 +33,7 @@ export function extendObjType(newItems: ExtendObjType | ExtendObjTypeArray, inde
33
33
  *
34
34
  * @example
35
35
  * reorderObjTypeOrder([
36
- * 'string', 'number', 'array', 'object'
36
+ * 'string', 'number', 'array', 'object'
37
37
  * ]);
38
38
  */
39
39
  export function reorderObjTypeOrder(newOrder: string[]): boolean;
@@ -50,7 +50,7 @@ export function cloneObjTypeOrder(): string[];
50
50
  * @param {*} obj - The object to check or identify.
51
51
  * @param {string} [type] - Optional. If provided, checks whether the object matches this type (e.g., "object", "array", "string").
52
52
  * @returns {boolean|string|null} - Returns `true` if the type matches, `false` if not,
53
- * the type string if no type is provided, or `null` if the object is `undefined`.
53
+ * the type string if no type is provided, or `null` if the object is `undefined`.
54
54
  *
55
55
  * @example
56
56
  * objType([], 'array'); // true