tiny-essentials 1.28.0 → 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 (168) hide show
  1. package/changelog/1/28/1.md +23 -0
  2. package/dist/v1/TinyAdvancedRaffle.min.js +1 -1
  3. package/dist/v1/TinyAfterScrollWatcher.min.js +1 -1
  4. package/dist/v1/TinyAnalogClock.min.js +1 -1
  5. package/dist/v1/TinyBasicsEs.min.js +1 -1
  6. package/dist/v1/TinyDayNightCycle.min.js +1 -1
  7. package/dist/v1/TinyDragDropDetector.min.js +1 -1
  8. package/dist/v1/TinyDragger.min.js +1 -1
  9. package/dist/v1/TinyElementObserver.min.js +1 -1
  10. package/dist/v1/TinyEssentials.min.js +1 -1
  11. package/dist/v1/TinyGamepad.min.js +1 -1
  12. package/dist/v1/TinyHtml.min.js +1 -1
  13. package/dist/v1/TinyI18.min.js +1 -1
  14. package/dist/v1/TinyIframeEvents.min.js +1 -1
  15. package/dist/v1/TinyLocalStorage.min.js +1 -1
  16. package/dist/v1/TinyMediaPlayer.min.js +1 -1
  17. package/dist/v1/TinyNewWinEvents.min.js +1 -1
  18. package/dist/v1/TinyNotifyCenter.min.js +1 -1
  19. package/dist/v1/TinyRadioFm.min.js +1 -1
  20. package/dist/v1/TinyRateLimiter.min.js +1 -1
  21. package/dist/v1/TinySmartScroller.min.js +1 -1
  22. package/dist/v1/TinyTextDiffer.min.js +1 -1
  23. package/dist/v1/TinyTextarea.min.js +1 -1
  24. package/dist/v1/TinyTimeout.min.js +1 -1
  25. package/dist/v1/TinyToastNotify.min.js +1 -1
  26. package/dist/v1/TinyUploadClicker.min.js +1 -1
  27. package/dist/v1/UltraRandomMsgGen.min.js +1 -1
  28. package/dist/v1/basics/array.cjs +57 -9
  29. package/dist/v1/basics/array.d.mts +27 -11
  30. package/dist/v1/basics/array.mjs +51 -9
  31. package/dist/v1/basics/clock.cjs +94 -42
  32. package/dist/v1/basics/clock.d.mts +10 -10
  33. package/dist/v1/basics/clock.mjs +91 -54
  34. package/dist/v1/basics/deprecated/html.cjs +246 -0
  35. package/dist/v1/basics/deprecated/html.d.mts +63 -0
  36. package/dist/v1/basics/deprecated/html.mjs +190 -0
  37. package/dist/v1/basics/html.cjs +149 -130
  38. package/dist/v1/basics/html.d.mts +26 -61
  39. package/dist/v1/basics/html.mjs +113 -105
  40. package/dist/v1/basics/index.cjs +2 -0
  41. package/dist/v1/basics/index.d.mts +3 -1
  42. package/dist/v1/basics/index.mjs +3 -3
  43. package/dist/v1/basics/mediaContent.cjs +51 -9
  44. package/dist/v1/basics/mediaContent.d.mts +0 -87
  45. package/dist/v1/basics/mediaContent.mjs +40 -10
  46. package/dist/v1/basics/objChecker.cjs +7 -5
  47. package/dist/v1/basics/objChecker.d.mts +3 -2
  48. package/dist/v1/basics/objChecker.mjs +6 -6
  49. package/dist/v1/basics/objFilter.cjs +40 -7
  50. package/dist/v1/basics/objFilter.d.mts +6 -6
  51. package/dist/v1/basics/objFilter.mjs +32 -7
  52. package/dist/v1/basics/simpleMath.cjs +81 -25
  53. package/dist/v1/basics/simpleMath.d.mts +2 -2
  54. package/dist/v1/basics/simpleMath.mjs +70 -27
  55. package/dist/v1/basics/text.cjs +76 -31
  56. package/dist/v1/basics/text.d.mts +69 -7
  57. package/dist/v1/basics/text.mjs +62 -31
  58. package/dist/v1/index.cjs +4 -0
  59. package/dist/v1/index.d.mts +4 -1
  60. package/dist/v1/index.mjs +4 -3
  61. package/dist/v1/libs/TinyAdvancedRaffle.cjs +64 -50
  62. package/dist/v1/libs/TinyAdvancedRaffle.d.mts +4 -13
  63. package/dist/v1/libs/TinyAdvancedRaffle.mjs +62 -49
  64. package/dist/v1/libs/TinyAfterScrollWatcher.cjs +17 -1
  65. package/dist/v1/libs/TinyAfterScrollWatcher.d.mts +4 -1
  66. package/dist/v1/libs/TinyAfterScrollWatcher.mjs +15 -1
  67. package/dist/v1/libs/TinyAnalogClock.cjs +60 -0
  68. package/dist/v1/libs/TinyAnalogClock.d.mts +6 -0
  69. package/dist/v1/libs/TinyAnalogClock.mjs +57 -0
  70. package/dist/v1/libs/TinyClipboard.cjs +2 -0
  71. package/dist/v1/libs/TinyClipboard.d.mts +4 -2
  72. package/dist/v1/libs/TinyClipboard.mjs +2 -0
  73. package/dist/v1/libs/TinyColorConverter.cjs +1 -0
  74. package/dist/v1/libs/TinyColorConverter.d.mts +2 -1
  75. package/dist/v1/libs/TinyColorConverter.mjs +1 -0
  76. package/dist/v1/libs/TinyDayNightCycle.cjs +67 -42
  77. package/dist/v1/libs/TinyDayNightCycle.d.mts +2 -7
  78. package/dist/v1/libs/TinyDayNightCycle.mjs +65 -41
  79. package/dist/v1/libs/TinyDragDropDetector.cjs +25 -0
  80. package/dist/v1/libs/TinyDragDropDetector.d.mts +6 -0
  81. package/dist/v1/libs/TinyDragDropDetector.mjs +22 -0
  82. package/dist/v1/libs/TinyDragger.cjs +46 -19
  83. package/dist/v1/libs/TinyDragger.mjs +45 -18
  84. package/dist/v1/libs/TinyElementObserver.cjs +39 -0
  85. package/dist/v1/libs/TinyElementObserver.d.mts +6 -0
  86. package/dist/v1/libs/TinyElementObserver.mjs +36 -0
  87. package/dist/v1/libs/TinyGamepad.cjs +131 -1
  88. package/dist/v1/libs/TinyGamepad.mjs +129 -1
  89. package/dist/v1/libs/TinyHtml.cjs +1 -1
  90. package/dist/v1/libs/TinyHtml.mjs +2 -2
  91. package/dist/v1/libs/TinyI18.cjs +61 -0
  92. package/dist/v1/libs/TinyI18.d.mts +14 -0
  93. package/dist/v1/libs/TinyI18.mjs +55 -0
  94. package/dist/v1/libs/TinyIframeEvents.cjs +18 -1
  95. package/dist/v1/libs/TinyIframeEvents.mjs +18 -1
  96. package/dist/v1/libs/TinyLocalStorage.cjs +48 -0
  97. package/dist/v1/libs/TinyLocalStorage.d.mts +6 -0
  98. package/dist/v1/libs/TinyLocalStorage.mjs +45 -0
  99. package/dist/v1/libs/TinyMediaPlayer.cjs +72 -0
  100. package/dist/v1/libs/TinyMediaPlayer.d.mts +10 -0
  101. package/dist/v1/libs/TinyMediaPlayer.mjs +66 -0
  102. package/dist/v1/libs/TinyNewWinEvents.cjs +29 -0
  103. package/dist/v1/libs/TinyNewWinEvents.d.mts +6 -0
  104. package/dist/v1/libs/TinyNewWinEvents.mjs +26 -0
  105. package/dist/v1/libs/TinyNotifyCenter.cjs +36 -0
  106. package/dist/v1/libs/TinyNotifyCenter.d.mts +6 -0
  107. package/dist/v1/libs/TinyNotifyCenter.mjs +32 -0
  108. package/dist/v1/libs/TinyRadioFm.cjs +38 -0
  109. package/dist/v1/libs/TinyRadioFm.d.mts +1 -0
  110. package/dist/v1/libs/TinyRadioFm.mjs +35 -0
  111. package/dist/v1/libs/TinyRateLimiter.cjs +52 -0
  112. package/dist/v1/libs/TinyRateLimiter.d.mts +6 -0
  113. package/dist/v1/libs/TinyRateLimiter.mjs +48 -0
  114. package/dist/v1/libs/TinySmartScroller.cjs +52 -3
  115. package/dist/v1/libs/TinySmartScroller.d.mts +17 -15
  116. package/dist/v1/libs/TinySmartScroller.mjs +51 -5
  117. package/dist/v1/libs/TinyTextDiffer.cjs +19 -18
  118. package/dist/v1/libs/TinyTextDiffer.d.mts +1 -0
  119. package/dist/v1/libs/TinyTextDiffer.mjs +16 -17
  120. package/dist/v1/libs/TinyTextarea.cjs +19 -0
  121. package/dist/v1/libs/TinyTextarea.d.mts +6 -0
  122. package/dist/v1/libs/TinyTextarea.mjs +17 -0
  123. package/dist/v1/libs/TinyTimeout.cjs +11 -1
  124. package/dist/v1/libs/TinyTimeout.mjs +9 -1
  125. package/dist/v1/libs/TinyToastNotify.cjs +35 -0
  126. package/dist/v1/libs/TinyToastNotify.d.mts +6 -0
  127. package/dist/v1/libs/TinyToastNotify.mjs +31 -0
  128. package/dist/v1/libs/TinyUploadClicker.cjs +19 -0
  129. package/dist/v1/libs/TinyUploadClicker.d.mts +6 -0
  130. package/dist/v1/libs/TinyUploadClicker.mjs +17 -0
  131. package/dist/v1/libs/UltraRandomMsgGen.cjs +148 -35
  132. package/dist/v1/libs/UltraRandomMsgGen.d.mts +17 -3
  133. package/dist/v1/libs/UltraRandomMsgGen.mjs +133 -34
  134. package/dist/v1/libs/utils.cjs +21 -0
  135. package/dist/v1/libs/utils.d.mts +2 -0
  136. package/dist/v1/libs/utils.mjs +16 -0
  137. package/docs/v1/README.md +1 -0
  138. package/docs/v1/basics/array.md +2 -2
  139. package/docs/v1/basics/deprecated/html.md +17 -0
  140. package/docs/v1/basics/fullScreen.md +1 -1
  141. package/docs/v1/basics/html.md +12 -26
  142. package/docs/v1/basics/mediaContent.md +1 -1
  143. package/docs/v1/basics/objChecker.md +1 -1
  144. package/docs/v1/basics/text.md +2 -2
  145. package/docs/v1/fileManager/main.md +1 -1
  146. package/docs/v1/libs/ColorSafeStringify.md +1 -1
  147. package/docs/v1/libs/TinyAfterScrollWatcher.md +1 -1
  148. package/docs/v1/libs/TinyAnalogClock.md +1 -1
  149. package/docs/v1/libs/TinyArrayComparator.md +1 -1
  150. package/docs/v1/libs/TinyArrayPaginator.md +1 -1
  151. package/docs/v1/libs/TinyClassManager/TinyPluginInliner.md +2 -2
  152. package/docs/v1/libs/TinyClassManager.md +1 -1
  153. package/docs/v1/libs/TinyClipboard.md +1 -1
  154. package/docs/v1/libs/TinyCookieConsent.md +1 -1
  155. package/docs/v1/libs/TinyDomReadyManager.md +1 -1
  156. package/docs/v1/libs/TinyDragDropDetector.md +1 -1
  157. package/docs/v1/libs/TinyDragger.md +1 -1
  158. package/docs/v1/libs/TinyElementObserver.md +1 -1
  159. package/docs/v1/libs/TinyHtml.md +1 -1
  160. package/docs/v1/libs/TinyIframeEvents.md +2 -2
  161. package/docs/v1/libs/TinyLevelUp.md +1 -1
  162. package/docs/v1/libs/TinyLoadingScreen.md +1 -1
  163. package/docs/v1/libs/TinyNewWinEvents.md +2 -2
  164. package/docs/v1/libs/TinyNotifications.md +1 -1
  165. package/docs/v1/libs/TinyPromiseQueue.md +2 -2
  166. package/docs/v1/libs/TinyTextDiffer.md +1 -1
  167. package/docs/v1/libs/TinyTextarea.md +1 -1
  168. package/package.json +10 -1
@@ -501,7 +501,7 @@ class TinyHtml {
501
501
  const oldStyles = TinyHtml.parseStyle(oldVal);
502
502
  const newStyles = TinyHtml.parseStyle(newVal);
503
503
 
504
- const changes = text.diffStrings(oldStyles, newStyles);
504
+ const changes = text.diffObjList(oldStyles, newStyles);
505
505
 
506
506
  if (
507
507
  Object.keys(changes.added).length ||
@@ -1,5 +1,5 @@
1
1
  import { diffArrayList } from '../basics/array.mjs';
2
- import { diffStrings } from '../basics/text.mjs';
2
+ import { diffObjList } from '../basics/text.mjs';
3
3
  import * as TinyCollision from '../basics/collision.mjs';
4
4
  import TinyElementObserver from './TinyElementObserver.mjs';
5
5
  // TITLE: Introduction
@@ -432,7 +432,7 @@ class TinyHtml {
432
432
  const newVal = mutation.target.getAttribute('style') || '';
433
433
  const oldStyles = TinyHtml.parseStyle(oldVal);
434
434
  const newStyles = TinyHtml.parseStyle(newVal);
435
- const changes = diffStrings(oldStyles, newStyles);
435
+ const changes = diffObjList(oldStyles, newStyles);
436
436
  if (Object.keys(changes.added).length ||
437
437
  Object.keys(changes.removed).length ||
438
438
  Object.keys(changes.modified).length) {
@@ -3,6 +3,9 @@
3
3
  var promises = require('fs/promises');
4
4
  var fs = require('fs');
5
5
  var path = require('path');
6
+ var utils = require('./utils.cjs');
7
+
8
+ const checkDestroy = utils.createCheckDestroyed('TinyI18');
6
9
 
7
10
  /**
8
11
  * Supported operating modes for TinyI18.
@@ -168,6 +171,21 @@ class TinyI18 {
168
171
  await promises.writeFile(output, JSON.stringify(merged, null, spaces), 'utf-8');
169
172
  }
170
173
 
174
+ /**
175
+ * Tracks whether the instance has been destroyed.
176
+ * @type {boolean}
177
+ */
178
+ #destroyed = false;
179
+
180
+ /**
181
+ * Gets the current destruction status of the instance.
182
+ *
183
+ * @returns {boolean} True if the instance is destroyed, false otherwise.
184
+ */
185
+ get destroyed() {
186
+ return this.#destroyed;
187
+ }
188
+
171
189
  /** @type {ModeTypes} */
172
190
  #mode;
173
191
  /** @type {LocaleCode} */
@@ -197,6 +215,7 @@ class TinyI18 {
197
215
  * @returns {LocaleCode|null}
198
216
  */
199
217
  get currentLocale() {
218
+ checkDestroy(this.#destroyed);
200
219
  return this.#currentLocale;
201
220
  }
202
221
 
@@ -206,6 +225,7 @@ class TinyI18 {
206
225
  * @type {LocaleCode}
207
226
  */
208
227
  get defaultLocale() {
228
+ checkDestroy(this.#destroyed);
209
229
  return this.#defaultLocale;
210
230
  }
211
231
 
@@ -216,6 +236,7 @@ class TinyI18 {
216
236
  * @type {ModeTypes}
217
237
  */
218
238
  get mode() {
239
+ checkDestroy(this.#destroyed);
219
240
  return this.#mode;
220
241
  }
221
242
 
@@ -226,6 +247,7 @@ class TinyI18 {
226
247
  * @type {boolean}
227
248
  */
228
249
  get strict() {
250
+ checkDestroy(this.#destroyed);
229
251
  return this.#strict;
230
252
  }
231
253
 
@@ -236,6 +258,7 @@ class TinyI18 {
236
258
  * @type {string|null}
237
259
  */
238
260
  get basePath() {
261
+ checkDestroy(this.#destroyed);
239
262
  return this.#basePath;
240
263
  }
241
264
 
@@ -244,6 +267,7 @@ class TinyI18 {
244
267
  * @returns {StatLocale[]}
245
268
  */
246
269
  get stats() {
270
+ checkDestroy(this.#destroyed);
247
271
  const locales = [];
248
272
  for (const loc of this.#stringTables.keys()) locales.push(this.getStatsForLocale(loc));
249
273
  return locales;
@@ -255,6 +279,7 @@ class TinyI18 {
255
279
  * @returns {Record<string, Dict>}
256
280
  */
257
281
  get stringTables() {
282
+ checkDestroy(this.#destroyed);
258
283
  /** @type {Record<string, Dict>} */
259
284
  const obj = {};
260
285
  for (const [locale, dict] of this.#stringTables.entries()) {
@@ -269,6 +294,7 @@ class TinyI18 {
269
294
  * @returns {Record<string, PatternEntry[]>}
270
295
  */
271
296
  get patternTables() {
297
+ checkDestroy(this.#destroyed);
272
298
  /** @type {Record<string, PatternEntry[]>} */
273
299
  const obj = {};
274
300
  for (const [locale, arr] of this.#patternTables.entries()) {
@@ -287,6 +313,7 @@ class TinyI18 {
287
313
  * @returns {Record<string, HelperCallback>}
288
314
  */
289
315
  get helpers() {
316
+ checkDestroy(this.#destroyed);
290
317
  /** @type {Record<string, HelperCallback>} */
291
318
  const obj = {};
292
319
  for (const [name, fn] of this.#helpers.entries()) {
@@ -301,6 +328,7 @@ class TinyI18 {
301
328
  * @returns {Record<string, RegExp>}
302
329
  */
303
330
  get regexCache() {
331
+ checkDestroy(this.#destroyed);
304
332
  /** @type {Record<string, RegExp>} */
305
333
  const obj = {};
306
334
  for (const [key, re] of this.#regexCache.entries()) {
@@ -765,6 +793,7 @@ class TinyI18 {
765
793
  * management is always controlled via the API instead of direct access.
766
794
  */
767
795
  clearRegexCache() {
796
+ checkDestroy(this.#destroyed);
768
797
  this.#regexCache.clear();
769
798
  }
770
799
 
@@ -774,6 +803,7 @@ class TinyI18 {
774
803
  * @param {HelperCallback} fn
775
804
  */
776
805
  registerHelper(name, fn) {
806
+ checkDestroy(this.#destroyed);
777
807
  if (typeof name !== 'string' || !name)
778
808
  throw new TypeError('registerHelper: "name" must be non-empty string');
779
809
  if (typeof fn !== 'function') throw new TypeError('registerHelper: "fn" must be a function');
@@ -789,6 +819,7 @@ class TinyI18 {
789
819
  * @returns {boolean} `true` if the helper was removed, `false` if it was not found.
790
820
  */
791
821
  unregisterHelper(name) {
822
+ checkDestroy(this.#destroyed);
792
823
  if (typeof name !== 'string' || !name)
793
824
  throw new TypeError('unregisterHelper: "name" must be non-empty string');
794
825
  return this.#helpers.delete(name);
@@ -800,6 +831,7 @@ class TinyI18 {
800
831
  * @param {Dict} data
801
832
  */
802
833
  loadLocaleLocal(locale, data) {
834
+ checkDestroy(this.#destroyed);
803
835
  if (this.#mode !== 'local')
804
836
  throw new TypeError('loadLocaleLocal is only available in "local" mode');
805
837
  this.#ingestLocale(locale, data);
@@ -811,6 +843,7 @@ class TinyI18 {
811
843
  * @param {LocaleCode|null} locale - null -> keep only default
812
844
  */
813
845
  async setLocale(locale) {
846
+ checkDestroy(this.#destroyed);
814
847
  if (locale !== null && (typeof locale !== 'string' || !locale))
815
848
  throw new TypeError('setLocale: "locale" must be string or null');
816
849
 
@@ -856,6 +889,7 @@ class TinyI18 {
856
889
  * @returns {any}
857
890
  */
858
891
  get(key, params = undefined, options = undefined) {
892
+ checkDestroy(this.#destroyed);
859
893
  if (typeof key !== 'string' || !key)
860
894
  throw new TypeError('get: "key" must be a non-empty string');
861
895
 
@@ -891,6 +925,7 @@ class TinyI18 {
891
925
  * @returns {any}
892
926
  */
893
927
  resolveByPattern(key, options) {
928
+ checkDestroy(this.#destroyed);
894
929
  if (typeof key !== 'string' || !key)
895
930
  throw new TypeError('get: "key" must be a non-empty string');
896
931
  const { locale: forceLocale } = options || {};
@@ -908,6 +943,7 @@ class TinyI18 {
908
943
  * Selected locale becomes null.
909
944
  */
910
945
  resetToDefaultOnly() {
946
+ checkDestroy(this.#destroyed);
911
947
  if (this.#mode === 'file') {
912
948
  for (const loc of Array.from(this.#stringTables.keys())) {
913
949
  if (loc !== this.#defaultLocale) {
@@ -925,6 +961,7 @@ class TinyI18 {
925
961
  * @throws {Error} If the locale is not registered.
926
962
  */
927
963
  getStatsForLocale(locale) {
964
+ checkDestroy(this.#destroyed);
928
965
  if (typeof locale !== 'string' || !locale)
929
966
  throw new TypeError('getStatsForLocale: "locale" must be a non-empty string');
930
967
  if (!this.#stringTables.has(locale))
@@ -941,6 +978,30 @@ class TinyI18 {
941
978
  isCurrent: locale === this.#currentLocale,
942
979
  };
943
980
  }
981
+
982
+ /**
983
+ * Destroys the TinyI18 instance, clearing all internal maps and references
984
+ * to free up memory. Once destroyed, the instance cannot be reused.
985
+ *
986
+ * @throws {Error} If the instance has already been destroyed.
987
+ * @returns {void}
988
+ */
989
+ destroy() {
990
+ if (this.#destroyed) return;
991
+
992
+ // Clear all internal maps to release memory
993
+ this.#stringTables.clear();
994
+ this.#patternTables.clear();
995
+ this.#helpers.clear();
996
+ this.#regexCache.clear();
997
+
998
+ // Reset locale and path configurations
999
+ this.#currentLocale = null;
1000
+ this.#basePath = null;
1001
+
1002
+ // Mark the instance as destroyed
1003
+ this.#destroyed = true;
1004
+ }
944
1005
  }
945
1006
 
946
1007
  module.exports = TinyI18;
@@ -267,6 +267,12 @@ declare class TinyI18 {
267
267
  * @param {TinyI18Options} options - Configuration options for the instance.
268
268
  */
269
269
  constructor(options: TinyI18Options);
270
+ /**
271
+ * Gets the current destruction status of the instance.
272
+ *
273
+ * @returns {boolean} True if the instance is destroyed, false otherwise.
274
+ */
275
+ get destroyed(): boolean;
270
276
  /**
271
277
  * Gets the currently selected locale, or null if only default is active.
272
278
  * @returns {LocaleCode|null}
@@ -413,6 +419,14 @@ declare class TinyI18 {
413
419
  * @throws {Error} If the locale is not registered.
414
420
  */
415
421
  getStatsForLocale(locale: LocaleCode): StatLocale;
422
+ /**
423
+ * Destroys the TinyI18 instance, clearing all internal maps and references
424
+ * to free up memory. Once destroyed, the instance cannot be reused.
425
+ *
426
+ * @throws {Error} If the instance has already been destroyed.
427
+ * @returns {void}
428
+ */
429
+ destroy(): void;
416
430
  #private;
417
431
  }
418
432
  //# sourceMappingURL=TinyI18.d.mts.map
@@ -1,6 +1,8 @@
1
1
  import { readFile, writeFile } from 'fs/promises';
2
2
  import { existsSync } from 'fs';
3
3
  import { join as pathJoin } from 'path';
4
+ import { createCheckDestroyed } from './utils.mjs';
5
+ const checkDestroy = createCheckDestroyed('TinyI18');
4
6
  /**
5
7
  * Supported operating modes for TinyI18.
6
8
  * - `"local"` → All translations are managed entirely in memory (browser + Node.js).
@@ -148,6 +150,19 @@ class TinyI18 {
148
150
  }
149
151
  await writeFile(output, JSON.stringify(merged, null, spaces), 'utf-8');
150
152
  }
153
+ /**
154
+ * Tracks whether the instance has been destroyed.
155
+ * @type {boolean}
156
+ */
157
+ #destroyed = false;
158
+ /**
159
+ * Gets the current destruction status of the instance.
160
+ *
161
+ * @returns {boolean} True if the instance is destroyed, false otherwise.
162
+ */
163
+ get destroyed() {
164
+ return this.#destroyed;
165
+ }
151
166
  /** @type {ModeTypes} */
152
167
  #mode;
153
168
  /** @type {LocaleCode} */
@@ -172,6 +187,7 @@ class TinyI18 {
172
187
  * @returns {LocaleCode|null}
173
188
  */
174
189
  get currentLocale() {
190
+ checkDestroy(this.#destroyed);
175
191
  return this.#currentLocale;
176
192
  }
177
193
  /**
@@ -180,6 +196,7 @@ class TinyI18 {
180
196
  * @type {LocaleCode}
181
197
  */
182
198
  get defaultLocale() {
199
+ checkDestroy(this.#destroyed);
183
200
  return this.#defaultLocale;
184
201
  }
185
202
  /**
@@ -189,6 +206,7 @@ class TinyI18 {
189
206
  * @type {ModeTypes}
190
207
  */
191
208
  get mode() {
209
+ checkDestroy(this.#destroyed);
192
210
  return this.#mode;
193
211
  }
194
212
  /**
@@ -198,6 +216,7 @@ class TinyI18 {
198
216
  * @type {boolean}
199
217
  */
200
218
  get strict() {
219
+ checkDestroy(this.#destroyed);
201
220
  return this.#strict;
202
221
  }
203
222
  /**
@@ -207,6 +226,7 @@ class TinyI18 {
207
226
  * @type {string|null}
208
227
  */
209
228
  get basePath() {
229
+ checkDestroy(this.#destroyed);
210
230
  return this.#basePath;
211
231
  }
212
232
  /**
@@ -214,6 +234,7 @@ class TinyI18 {
214
234
  * @returns {StatLocale[]}
215
235
  */
216
236
  get stats() {
237
+ checkDestroy(this.#destroyed);
217
238
  const locales = [];
218
239
  for (const loc of this.#stringTables.keys())
219
240
  locales.push(this.getStatsForLocale(loc));
@@ -225,6 +246,7 @@ class TinyI18 {
225
246
  * @returns {Record<string, Dict>}
226
247
  */
227
248
  get stringTables() {
249
+ checkDestroy(this.#destroyed);
228
250
  /** @type {Record<string, Dict>} */
229
251
  const obj = {};
230
252
  for (const [locale, dict] of this.#stringTables.entries()) {
@@ -238,6 +260,7 @@ class TinyI18 {
238
260
  * @returns {Record<string, PatternEntry[]>}
239
261
  */
240
262
  get patternTables() {
263
+ checkDestroy(this.#destroyed);
241
264
  /** @type {Record<string, PatternEntry[]>} */
242
265
  const obj = {};
243
266
  for (const [locale, arr] of this.#patternTables.entries()) {
@@ -255,6 +278,7 @@ class TinyI18 {
255
278
  * @returns {Record<string, HelperCallback>}
256
279
  */
257
280
  get helpers() {
281
+ checkDestroy(this.#destroyed);
258
282
  /** @type {Record<string, HelperCallback>} */
259
283
  const obj = {};
260
284
  for (const [name, fn] of this.#helpers.entries()) {
@@ -268,6 +292,7 @@ class TinyI18 {
268
292
  * @returns {Record<string, RegExp>}
269
293
  */
270
294
  get regexCache() {
295
+ checkDestroy(this.#destroyed);
271
296
  /** @type {Record<string, RegExp>} */
272
297
  const obj = {};
273
298
  for (const [key, re] of this.#regexCache.entries()) {
@@ -707,6 +732,7 @@ class TinyI18 {
707
732
  * management is always controlled via the API instead of direct access.
708
733
  */
709
734
  clearRegexCache() {
735
+ checkDestroy(this.#destroyed);
710
736
  this.#regexCache.clear();
711
737
  }
712
738
  /**
@@ -715,6 +741,7 @@ class TinyI18 {
715
741
  * @param {HelperCallback} fn
716
742
  */
717
743
  registerHelper(name, fn) {
744
+ checkDestroy(this.#destroyed);
718
745
  if (typeof name !== 'string' || !name)
719
746
  throw new TypeError('registerHelper: "name" must be non-empty string');
720
747
  if (typeof fn !== 'function')
@@ -730,6 +757,7 @@ class TinyI18 {
730
757
  * @returns {boolean} `true` if the helper was removed, `false` if it was not found.
731
758
  */
732
759
  unregisterHelper(name) {
760
+ checkDestroy(this.#destroyed);
733
761
  if (typeof name !== 'string' || !name)
734
762
  throw new TypeError('unregisterHelper: "name" must be non-empty string');
735
763
  return this.#helpers.delete(name);
@@ -740,6 +768,7 @@ class TinyI18 {
740
768
  * @param {Dict} data
741
769
  */
742
770
  loadLocaleLocal(locale, data) {
771
+ checkDestroy(this.#destroyed);
743
772
  if (this.#mode !== 'local')
744
773
  throw new TypeError('loadLocaleLocal is only available in "local" mode');
745
774
  this.#ingestLocale(locale, data);
@@ -750,6 +779,7 @@ class TinyI18 {
750
779
  * @param {LocaleCode|null} locale - null -> keep only default
751
780
  */
752
781
  async setLocale(locale) {
782
+ checkDestroy(this.#destroyed);
753
783
  if (locale !== null && (typeof locale !== 'string' || !locale))
754
784
  throw new TypeError('setLocale: "locale" must be string or null');
755
785
  const prev = this.#currentLocale;
@@ -791,6 +821,7 @@ class TinyI18 {
791
821
  * @returns {any}
792
822
  */
793
823
  get(key, params = undefined, options = undefined) {
824
+ checkDestroy(this.#destroyed);
794
825
  if (typeof key !== 'string' || !key)
795
826
  throw new TypeError('get: "key" must be a non-empty string');
796
827
  const { locale: forceLocale } = options || {};
@@ -822,6 +853,7 @@ class TinyI18 {
822
853
  * @returns {any}
823
854
  */
824
855
  resolveByPattern(key, options) {
856
+ checkDestroy(this.#destroyed);
825
857
  if (typeof key !== 'string' || !key)
826
858
  throw new TypeError('get: "key" must be a non-empty string');
827
859
  const { locale: forceLocale } = options || {};
@@ -839,6 +871,7 @@ class TinyI18 {
839
871
  * Selected locale becomes null.
840
872
  */
841
873
  resetToDefaultOnly() {
874
+ checkDestroy(this.#destroyed);
842
875
  if (this.#mode === 'file') {
843
876
  for (const loc of Array.from(this.#stringTables.keys())) {
844
877
  if (loc !== this.#defaultLocale) {
@@ -855,6 +888,7 @@ class TinyI18 {
855
888
  * @throws {Error} If the locale is not registered.
856
889
  */
857
890
  getStatsForLocale(locale) {
891
+ checkDestroy(this.#destroyed);
858
892
  if (typeof locale !== 'string' || !locale)
859
893
  throw new TypeError('getStatsForLocale: "locale" must be a non-empty string');
860
894
  if (!this.#stringTables.has(locale))
@@ -869,5 +903,26 @@ class TinyI18 {
869
903
  isCurrent: locale === this.#currentLocale,
870
904
  };
871
905
  }
906
+ /**
907
+ * Destroys the TinyI18 instance, clearing all internal maps and references
908
+ * to free up memory. Once destroyed, the instance cannot be reused.
909
+ *
910
+ * @throws {Error} If the instance has already been destroyed.
911
+ * @returns {void}
912
+ */
913
+ destroy() {
914
+ if (this.#destroyed)
915
+ return;
916
+ // Clear all internal maps to release memory
917
+ this.#stringTables.clear();
918
+ this.#patternTables.clear();
919
+ this.#helpers.clear();
920
+ this.#regexCache.clear();
921
+ // Reset locale and path configurations
922
+ this.#currentLocale = null;
923
+ this.#basePath = null;
924
+ // Mark the instance as destroyed
925
+ this.#destroyed = true;
926
+ }
872
927
  }
873
928
  export default TinyI18;
@@ -2,6 +2,9 @@
2
2
 
3
3
  var events = require('events');
4
4
  var objChecker = require('../basics/objChecker.cjs');
5
+ var utils = require('./utils.cjs');
6
+
7
+ const checkDestroy = utils.createCheckDestroyed('TinyIframeEvents');
5
8
 
6
9
  /** @type {WeakMap<Window, TinyIframeEvents>} */
7
10
  const instances = new WeakMap();
@@ -51,6 +54,7 @@ class TinyIframeEvents extends events.EventEmitter {
51
54
  #targetWindow;
52
55
 
53
56
  get targetWindow() {
57
+ checkDestroy(this.#isDestroyed);
54
58
  return this.#targetWindow;
55
59
  }
56
60
 
@@ -58,6 +62,7 @@ class TinyIframeEvents extends events.EventEmitter {
58
62
  #targetIframeElement;
59
63
 
60
64
  get targetIframeElement() {
65
+ checkDestroy(this.#isDestroyed);
61
66
  return this.#targetIframeElement;
62
67
  }
63
68
 
@@ -65,6 +70,7 @@ class TinyIframeEvents extends events.EventEmitter {
65
70
  #targetOrigin;
66
71
 
67
72
  get targetOrigin() {
73
+ checkDestroy(this.#isDestroyed);
68
74
  return this.#targetOrigin;
69
75
  }
70
76
 
@@ -72,6 +78,7 @@ class TinyIframeEvents extends events.EventEmitter {
72
78
  #selfType;
73
79
 
74
80
  get selfType() {
81
+ checkDestroy(this.#isDestroyed);
75
82
  return this.#selfType;
76
83
  }
77
84
 
@@ -82,6 +89,7 @@ class TinyIframeEvents extends events.EventEmitter {
82
89
  #ready = false;
83
90
 
84
91
  get ready() {
92
+ checkDestroy(this.#isDestroyed);
85
93
  return this.#ready;
86
94
  }
87
95
 
@@ -92,6 +100,7 @@ class TinyIframeEvents extends events.EventEmitter {
92
100
  * @param {function(): void} handler - The callback function to execute.
93
101
  */
94
102
  onReady(handler) {
103
+ checkDestroy(this.#isDestroyed);
95
104
  if (this.#ready) {
96
105
  handler();
97
106
  } else {
@@ -168,6 +177,7 @@ class TinyIframeEvents extends events.EventEmitter {
168
177
  * @returns {string}
169
178
  */
170
179
  get secretEventName() {
180
+ checkDestroy(this.#isDestroyed);
171
181
  return this.#secretEventName;
172
182
  }
173
183
 
@@ -177,6 +187,7 @@ class TinyIframeEvents extends events.EventEmitter {
177
187
  * @throws {TypeError} If the value is not a string.
178
188
  */
179
189
  set secretEventName(name) {
190
+ checkDestroy(this.#isDestroyed);
180
191
  if (typeof name !== 'string')
181
192
  throw new TypeError('TinyIframeEvents: secretEventName must be a string.');
182
193
  this.#secretEventName = name;
@@ -187,6 +198,7 @@ class TinyIframeEvents extends events.EventEmitter {
187
198
  * @returns {string}
188
199
  */
189
200
  get handshakeEventName() {
201
+ checkDestroy(this.#isDestroyed);
190
202
  return this.#handshakeEventName;
191
203
  }
192
204
 
@@ -196,6 +208,7 @@ class TinyIframeEvents extends events.EventEmitter {
196
208
  * @throws {TypeError} If the value is not a string.
197
209
  */
198
210
  set handshakeEventName(name) {
211
+ checkDestroy(this.#isDestroyed);
199
212
  if (typeof name !== 'string')
200
213
  throw new TypeError('TinyIframeEvents: handshakeEventName must be a string.');
201
214
  this.#handshakeEventName = name;
@@ -206,6 +219,7 @@ class TinyIframeEvents extends events.EventEmitter {
206
219
  * @returns {string}
207
220
  */
208
221
  get readyEventName() {
222
+ checkDestroy(this.#isDestroyed);
209
223
  return this.#readyEventName;
210
224
  }
211
225
 
@@ -215,6 +229,7 @@ class TinyIframeEvents extends events.EventEmitter {
215
229
  * @throws {TypeError} If the value is not a string.
216
230
  */
217
231
  set readyEventName(name) {
232
+ checkDestroy(this.#isDestroyed);
218
233
  if (typeof name !== 'string')
219
234
  throw new TypeError('TinyIframeEvents: readyEventName must be a string.');
220
235
  this.#readyEventName = name;
@@ -339,6 +354,7 @@ class TinyIframeEvents extends events.EventEmitter {
339
354
  * @throws {Error} If instance has been destroyed.
340
355
  */
341
356
  winEmit(eventName, payload) {
357
+ checkDestroy(this.#isDestroyed);
342
358
  if (typeof eventName !== 'string') throw new TypeError('Event name must be a string.');
343
359
  if (this.#isDestroyed) throw new Error('Cannot emit: instance has been destroyed.');
344
360
 
@@ -372,7 +388,7 @@ class TinyIframeEvents extends events.EventEmitter {
372
388
  * Call this when the instance is no longer needed to prevent memory leaks.
373
389
  */
374
390
  destroy() {
375
- this.#isDestroyed = true;
391
+ if (this.#isDestroyed) return;
376
392
  this.#ready = false;
377
393
 
378
394
  window.removeEventListener('message', this._boundWindowMessage);
@@ -389,6 +405,7 @@ class TinyIframeEvents extends events.EventEmitter {
389
405
  this.removeAllListeners();
390
406
  this.#pendingQueue = [];
391
407
  instances.delete(this.#targetWindow);
408
+ this.#isDestroyed = true;
392
409
  }
393
410
  }
394
411