tiny-essentials 1.28.19 → 1.29.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 (556) hide show
  1. package/README.md +1 -1
  2. package/changelog/1/28/19.md +24 -0
  3. package/changelog/1/29/0.md +58 -0
  4. package/changelog/1/29/1.md +11 -0
  5. package/dist/v1/ColorSafeStringify.min.js +1 -1
  6. package/dist/v1/TinyAdvancedRaffle.min.js +1 -1
  7. package/dist/v1/TinyAfterScrollWatcher.min.js +1 -1
  8. package/dist/v1/TinyAnalogClock.min.js +1 -1
  9. package/dist/v1/TinyArrayComparator.min.js +1 -1
  10. package/dist/v1/TinyArrayPaginator.min.js +1 -1
  11. package/dist/v1/TinyBasicsEs.min.js +1 -1
  12. package/dist/v1/TinyBrowserMonitor.min.js +1 -0
  13. package/dist/v1/TinyClassManager.min.js +1 -1
  14. package/dist/v1/TinyClipboard.min.js +1 -1
  15. package/dist/v1/TinyCloner.min.js +1 -0
  16. package/dist/v1/TinyColorConverter.min.js +1 -1
  17. package/dist/v1/TinyColorValidator.min.js +1 -1
  18. package/dist/v1/TinyCookieConsent.min.js +1 -1
  19. package/dist/v1/TinyDayNightCycle.min.js +1 -1
  20. package/dist/v1/TinyDebugger.min.js +1 -1
  21. package/dist/v1/TinyDomReadyManager.min.js +1 -1
  22. package/dist/v1/TinyDragDropDetector.min.js +1 -1
  23. package/dist/v1/TinyDragger.min.js +1 -1
  24. package/dist/v1/TinyElementObserver.min.js +1 -1
  25. package/dist/v1/TinyEssentials.min.js +1 -1
  26. package/dist/v1/TinyGamepad.min.js +1 -1
  27. package/dist/v1/TinyHtml.min.js +1 -1
  28. package/dist/v1/TinyHtmlTagRegexBuilder.min.js +1 -0
  29. package/dist/v1/TinyHttpResponseRegistry.min.js +1 -0
  30. package/dist/v1/TinyI18.min.js +1 -1
  31. package/dist/v1/TinyIframeEvents.min.js +1 -1
  32. package/dist/v1/TinyInventory.min.js +1 -1
  33. package/dist/v1/TinyInventoryTrader.min.js +1 -1
  34. package/dist/v1/TinyLevelUp.min.js +1 -1
  35. package/dist/v1/TinyLoadingScreen.min.js +1 -1
  36. package/dist/v1/TinyLocalStorage.min.js +1 -1
  37. package/dist/v1/TinyMaInSys.min.js +1 -1
  38. package/dist/v1/TinyMapCache.min.js +1 -0
  39. package/dist/v1/TinyMediaPlayer.min.js +1 -1
  40. package/dist/v1/TinyNeedBar.min.js +1 -1
  41. package/dist/v1/TinyNewWinEvents.min.js +1 -1
  42. package/dist/v1/TinyNotificationAdapter.min.js +1 -0
  43. package/dist/v1/TinyNotifications.min.js +1 -1
  44. package/dist/v1/TinyNotifyCenter.min.js +1 -1
  45. package/dist/v1/TinyOPFSFileSystem.min.js +1 -0
  46. package/dist/v1/TinyPasswordValidator.min.js +1 -0
  47. package/dist/v1/TinyPluginPackage.min.js +1 -0
  48. package/dist/v1/TinyPromiseQueue.min.js +1 -1
  49. package/dist/v1/TinyPushManager.min.js +1 -0
  50. package/dist/v1/TinyPushPayload.min.js +1 -0
  51. package/dist/v1/TinyPushRouter.min.js +1 -0
  52. package/dist/v1/TinyRadioFm.min.js +1 -1
  53. package/dist/v1/TinyRateLimiter.min.js +1 -1
  54. package/dist/v1/TinyRegexEs.min.js +1 -0
  55. package/dist/v1/TinyRouter.min.js +1 -0
  56. package/dist/v1/TinyServiceWorker.min.js +1 -0
  57. package/dist/v1/TinyServiceWorkerEngine.min.js +1 -0
  58. package/dist/v1/TinySetMapPackage.min.js +1 -0
  59. package/dist/v1/TinySimpleDice.min.js +1 -1
  60. package/dist/v1/TinySmartScroller.min.js +1 -1
  61. package/dist/v1/TinyStorageBucketFileSystem.min.js +1 -0
  62. package/dist/v1/TinyTextDiffer.min.js +1 -1
  63. package/dist/v1/TinyTextRangeEditor.min.js +1 -1
  64. package/dist/v1/TinyTextarea.min.js +1 -1
  65. package/dist/v1/TinyThrottledApi.min.js +1 -0
  66. package/dist/v1/TinyTimeout.min.js +1 -1
  67. package/dist/v1/TinyToastNotify.min.js +1 -1
  68. package/dist/v1/TinyUploadClicker.min.js +1 -1
  69. package/dist/v1/TinyUriParser.min.js +1 -0
  70. package/dist/v1/TinyVersion.min.js +1 -0
  71. package/dist/v1/TinyWebWorker.min.js +1 -0
  72. package/dist/v1/TinyWebWorkerEngine.min.js +1 -0
  73. package/dist/v1/UltraRandomMsgGen.min.js +1 -1
  74. package/dist/v1/basics/array.cjs +2 -2
  75. package/dist/v1/basics/array.d.mts +2 -0
  76. package/dist/v1/basics/array.d.mts.map +1 -1
  77. package/dist/v1/basics/array.mjs +2 -1
  78. package/dist/v1/basics/browserDetector.cjs +37 -12
  79. package/dist/v1/basics/browserDetector.d.mts +8 -0
  80. package/dist/v1/basics/browserDetector.d.mts.map +1 -1
  81. package/dist/v1/basics/browserDetector.mjs +32 -13
  82. package/dist/v1/basics/crypto.cjs +23 -0
  83. package/dist/v1/basics/crypto.d.mts +10 -0
  84. package/dist/v1/basics/crypto.d.mts.map +1 -0
  85. package/dist/v1/basics/crypto.mjs +18 -0
  86. package/dist/v1/basics/html.cjs +0 -3
  87. package/dist/v1/basics/html.d.mts.map +1 -1
  88. package/dist/v1/basics/html.mjs +0 -2
  89. package/dist/v1/basics/index.cjs +8 -1
  90. package/dist/v1/basics/index.d.mts +6 -5
  91. package/dist/v1/basics/index.d.mts.map +1 -1
  92. package/dist/v1/basics/index.mjs +6 -5
  93. package/dist/v1/basics/objChecker.cjs +88 -0
  94. package/dist/v1/basics/objChecker.d.mts +26 -0
  95. package/dist/v1/basics/objChecker.d.mts.map +1 -1
  96. package/dist/v1/basics/objChecker.mjs +74 -0
  97. package/dist/v1/basics/objFilter.cjs +234 -93
  98. package/dist/v1/basics/objFilter.d.mts +96 -22
  99. package/dist/v1/basics/objFilter.d.mts.map +1 -1
  100. package/dist/v1/basics/objFilter.mjs +216 -92
  101. package/dist/v1/basics/promiseUtils.cjs +48 -12
  102. package/dist/v1/basics/promiseUtils.d.mts +45 -12
  103. package/dist/v1/basics/promiseUtils.d.mts.map +1 -1
  104. package/dist/v1/basics/promiseUtils.mjs +47 -12
  105. package/dist/v1/basics/text.cjs +0 -12
  106. package/dist/v1/basics/text.d.mts +0 -10
  107. package/dist/v1/basics/text.d.mts.map +1 -1
  108. package/dist/v1/basics/text.mjs +0 -10
  109. package/dist/v1/index.cjs +88 -3
  110. package/dist/v1/index.d.mts +31 -6
  111. package/dist/v1/index.d.mts.map +1 -1
  112. package/dist/v1/index.mjs +32 -7
  113. package/dist/v1/jsdoc/EventEmitter.cjs +4 -0
  114. package/dist/v1/jsdoc/EventEmitter.d.mts +33 -0
  115. package/dist/v1/jsdoc/EventEmitter.d.mts.map +1 -0
  116. package/dist/v1/jsdoc/EventEmitter.mjs +18 -0
  117. package/dist/v1/libs/array/TinyArrayComparator.cjs +240 -25
  118. package/dist/v1/libs/array/TinyArrayComparator.d.mts +130 -22
  119. package/dist/v1/libs/array/TinyArrayComparator.d.mts.map +1 -1
  120. package/dist/v1/libs/array/TinyArrayComparator.mjs +210 -24
  121. package/dist/v1/libs/fs/constants.cjs +74 -0
  122. package/dist/v1/libs/fs/constants.d.mts +22 -0
  123. package/dist/v1/libs/fs/constants.d.mts.map +1 -0
  124. package/dist/v1/libs/fs/constants.mjs +53 -0
  125. package/dist/v1/libs/fs/encoding.cjs +118 -0
  126. package/dist/v1/libs/fs/encoding.d.mts +50 -0
  127. package/dist/v1/libs/fs/encoding.d.mts.map +1 -0
  128. package/dist/v1/libs/fs/encoding.mjs +102 -0
  129. package/dist/v1/libs/fs/error.cjs +188 -0
  130. package/dist/v1/libs/fs/error.d.mts +105 -0
  131. package/dist/v1/libs/fs/error.d.mts.map +1 -0
  132. package/dist/v1/libs/fs/error.mjs +158 -0
  133. package/dist/v1/libs/fs/handle.cjs +121 -0
  134. package/dist/v1/libs/fs/handle.d.mts +56 -0
  135. package/dist/v1/libs/fs/handle.d.mts.map +1 -0
  136. package/dist/v1/libs/fs/handle.mjs +100 -0
  137. package/dist/v1/libs/fs/index.cjs +700 -0
  138. package/dist/v1/libs/fs/index.d.mts +377 -0
  139. package/dist/v1/libs/fs/index.d.mts.map +1 -0
  140. package/dist/v1/libs/fs/index.mjs +630 -0
  141. package/dist/v1/libs/fs/path.cjs +234 -0
  142. package/dist/v1/libs/fs/path.d.mts +176 -0
  143. package/dist/v1/libs/fs/path.d.mts.map +1 -0
  144. package/dist/v1/libs/fs/path.mjs +197 -0
  145. package/dist/v1/libs/fs/plugins/OPFS/StorageBucket.cjs +202 -0
  146. package/dist/v1/libs/fs/plugins/OPFS/StorageBucket.d.mts +121 -0
  147. package/dist/v1/libs/fs/plugins/OPFS/StorageBucket.d.mts.map +1 -0
  148. package/dist/v1/libs/fs/plugins/OPFS/StorageBucket.mjs +172 -0
  149. package/dist/v1/libs/fs/plugins/OPFS/index.cjs +334 -0
  150. package/dist/v1/libs/fs/plugins/OPFS/index.d.mts +98 -0
  151. package/dist/v1/libs/fs/plugins/OPFS/index.d.mts.map +1 -0
  152. package/dist/v1/libs/fs/plugins/OPFS/index.mjs +300 -0
  153. package/dist/v1/libs/fs/stats.cjs +245 -0
  154. package/dist/v1/libs/fs/stats.d.mts +226 -0
  155. package/dist/v1/libs/fs/stats.d.mts.map +1 -0
  156. package/dist/v1/libs/fs/stats.mjs +197 -0
  157. package/dist/v1/libs/html/events/TinyIframeEvents.cjs +10 -1
  158. package/dist/v1/libs/html/events/TinyIframeEvents.d.mts +9 -2
  159. package/dist/v1/libs/html/events/TinyIframeEvents.d.mts.map +1 -1
  160. package/dist/v1/libs/html/events/TinyIframeEvents.mjs +8 -1
  161. package/dist/v1/libs/html/events/TinyNewWinEvents.cjs +14 -3
  162. package/dist/v1/libs/html/events/TinyNewWinEvents.d.mts +21 -5
  163. package/dist/v1/libs/html/events/TinyNewWinEvents.d.mts.map +1 -1
  164. package/dist/v1/libs/html/events/TinyNewWinEvents.mjs +12 -3
  165. package/dist/v1/libs/html/scroll/TinySmartScroller.cjs +13 -1
  166. package/dist/v1/libs/html/scroll/TinySmartScroller.d.mts +29 -2
  167. package/dist/v1/libs/html/scroll/TinySmartScroller.d.mts.map +1 -1
  168. package/dist/v1/libs/html/scroll/TinySmartScroller.mjs +11 -1
  169. package/dist/v1/libs/math/TinyAdvancedRaffle.cjs +13 -1
  170. package/dist/v1/libs/math/TinyAdvancedRaffle.d.mts +32 -2
  171. package/dist/v1/libs/math/TinyAdvancedRaffle.d.mts.map +1 -1
  172. package/dist/v1/libs/math/TinyAdvancedRaffle.mjs +11 -1
  173. package/dist/v1/libs/math/TinyTimeout.cjs +0 -14
  174. package/dist/v1/libs/math/TinyTimeout.d.mts +0 -11
  175. package/dist/v1/libs/math/TinyTimeout.d.mts.map +1 -1
  176. package/dist/v1/libs/math/TinyTimeout.mjs +0 -13
  177. package/dist/v1/libs/media/TinyMediaPlayer/index.cjs +25 -1
  178. package/dist/v1/libs/media/TinyMediaPlayer/index.d.mts +35 -2
  179. package/dist/v1/libs/media/TinyMediaPlayer/index.d.mts.map +1 -1
  180. package/dist/v1/libs/media/TinyMediaPlayer/index.mjs +23 -1
  181. package/dist/v1/libs/media/TinyMediaPlayer.cjs +2 -2
  182. package/dist/v1/libs/media/TinyMediaPlayer.d.mts +2 -2
  183. package/dist/v1/libs/media/TinyMediaPlayer.d.mts.map +1 -1
  184. package/dist/v1/libs/media/TinyMediaPlayer.mjs +2 -2
  185. package/dist/v1/libs/media/TinyRadioFm.cjs +19 -1
  186. package/dist/v1/libs/media/TinyRadioFm.d.mts +78 -2
  187. package/dist/v1/libs/media/TinyRadioFm.d.mts.map +1 -1
  188. package/dist/v1/libs/media/TinyRadioFm.mjs +17 -1
  189. package/dist/v1/libs/plugin/TinyPlugin.cjs +1630 -0
  190. package/dist/v1/libs/plugin/TinyPlugin.d.mts +753 -0
  191. package/dist/v1/libs/plugin/TinyPlugin.d.mts.map +1 -0
  192. package/dist/v1/libs/plugin/TinyPlugin.mjs +1376 -0
  193. package/dist/v1/libs/plugin/TinyVersion.cjs +204 -0
  194. package/dist/v1/libs/plugin/TinyVersion.d.mts +70 -0
  195. package/dist/v1/libs/plugin/TinyVersion.d.mts.map +1 -0
  196. package/dist/v1/libs/plugin/TinyVersion.mjs +179 -0
  197. package/dist/v1/libs/router/TinyRouter.cjs +661 -0
  198. package/dist/v1/libs/router/TinyRouter.d.mts +320 -0
  199. package/dist/v1/libs/router/TinyRouter.d.mts.map +1 -0
  200. package/dist/v1/libs/router/TinyRouter.mjs +572 -0
  201. package/dist/v1/libs/storage/TinyLocalStorage.cjs +20 -1
  202. package/dist/v1/libs/storage/TinyLocalStorage.d.mts +64 -2
  203. package/dist/v1/libs/storage/TinyLocalStorage.d.mts.map +1 -1
  204. package/dist/v1/libs/storage/TinyLocalStorage.mjs +18 -1
  205. package/dist/v1/libs/storage/TinyMapCache.cjs +373 -0
  206. package/dist/v1/libs/storage/TinyMapCache.d.mts +274 -0
  207. package/dist/v1/libs/storage/TinyMapCache.d.mts.map +1 -0
  208. package/dist/v1/libs/storage/TinyMapCache.mjs +333 -0
  209. package/dist/v1/libs/storage/TinySetMapDatabase.cjs +1167 -0
  210. package/dist/v1/libs/storage/TinySetMapDatabase.d.mts +603 -0
  211. package/dist/v1/libs/storage/TinySetMapDatabase.d.mts.map +1 -0
  212. package/dist/v1/libs/storage/TinySetMapDatabase.mjs +1059 -0
  213. package/dist/v1/libs/sw/browser/TinyNotificationAdapter.cjs +126 -0
  214. package/dist/v1/libs/sw/browser/TinyNotificationAdapter.d.mts +132 -0
  215. package/dist/v1/libs/sw/browser/TinyNotificationAdapter.d.mts.map +1 -0
  216. package/dist/v1/libs/sw/browser/TinyNotificationAdapter.mjs +109 -0
  217. package/dist/v1/libs/sw/browser/TinyPushManager.cjs +310 -0
  218. package/dist/v1/libs/sw/browser/TinyPushManager.d.mts +168 -0
  219. package/dist/v1/libs/sw/browser/TinyPushManager.d.mts.map +1 -0
  220. package/dist/v1/libs/sw/browser/TinyPushManager.mjs +264 -0
  221. package/dist/v1/libs/sw/browser/TinyServiceWorker.cjs +1060 -0
  222. package/dist/v1/libs/sw/browser/TinyServiceWorker.d.mts +348 -0
  223. package/dist/v1/libs/sw/browser/TinyServiceWorker.d.mts.map +1 -0
  224. package/dist/v1/libs/sw/browser/TinyServiceWorker.mjs +933 -0
  225. package/dist/v1/libs/sw/browser/plugins/TabManager.cjs +315 -0
  226. package/dist/v1/libs/sw/browser/plugins/TabManager.d.mts +178 -0
  227. package/dist/v1/libs/sw/browser/plugins/TabManager.d.mts.map +1 -0
  228. package/dist/v1/libs/sw/browser/plugins/TabManager.mjs +274 -0
  229. package/dist/v1/libs/sw/browser/utils.cjs +28 -0
  230. package/dist/v1/libs/sw/browser/utils.d.mts +8 -0
  231. package/dist/v1/libs/sw/browser/utils.d.mts.map +1 -0
  232. package/dist/v1/libs/sw/browser/utils.mjs +21 -0
  233. package/dist/v1/libs/sw/service/TinyPushRouter.cjs +222 -0
  234. package/dist/v1/libs/sw/service/TinyPushRouter.d.mts +138 -0
  235. package/dist/v1/libs/sw/service/TinyPushRouter.d.mts.map +1 -0
  236. package/dist/v1/libs/sw/service/TinyPushRouter.mjs +201 -0
  237. package/dist/v1/libs/sw/service/TinyServiceWorkerEngine.cjs +3016 -0
  238. package/dist/v1/libs/sw/service/TinyServiceWorkerEngine.d.mts +993 -0
  239. package/dist/v1/libs/sw/service/TinyServiceWorkerEngine.d.mts.map +1 -0
  240. package/dist/v1/libs/sw/service/TinyServiceWorkerEngine.mjs +2558 -0
  241. package/dist/v1/libs/sw/service/plugins/GlobBypassPlugin.cjs +88 -0
  242. package/dist/v1/libs/sw/service/plugins/GlobBypassPlugin.d.mts +32 -0
  243. package/dist/v1/libs/sw/service/plugins/GlobBypassPlugin.d.mts.map +1 -0
  244. package/dist/v1/libs/sw/service/plugins/GlobBypassPlugin.mjs +69 -0
  245. package/dist/v1/libs/sw/service/plugins/GlobCachePlugin.cjs +112 -0
  246. package/dist/v1/libs/sw/service/plugins/GlobCachePlugin.d.mts +31 -0
  247. package/dist/v1/libs/sw/service/plugins/GlobCachePlugin.d.mts.map +1 -0
  248. package/dist/v1/libs/sw/service/plugins/GlobCachePlugin.mjs +91 -0
  249. package/dist/v1/libs/sw/service/plugins/Ping.cjs +32 -0
  250. package/dist/v1/libs/sw/service/plugins/Ping.d.mts +9 -0
  251. package/dist/v1/libs/sw/service/plugins/Ping.d.mts.map +1 -0
  252. package/dist/v1/libs/sw/service/plugins/Ping.mjs +25 -0
  253. package/dist/v1/libs/sw/service/plugins/TabManager.cjs +457 -0
  254. package/dist/v1/libs/sw/service/plugins/TabManager.d.mts +91 -0
  255. package/dist/v1/libs/sw/service/plugins/TabManager.d.mts.map +1 -0
  256. package/dist/v1/libs/sw/service/plugins/TabManager.mjs +372 -0
  257. package/dist/v1/libs/sw/service/plugins/ViteFileDetector.cjs +180 -0
  258. package/dist/v1/libs/sw/service/plugins/ViteFileDetector.d.mts +28 -0
  259. package/dist/v1/libs/sw/service/plugins/ViteFileDetector.d.mts.map +1 -0
  260. package/dist/v1/libs/sw/service/plugins/ViteFileDetector.mjs +148 -0
  261. package/dist/v1/libs/sw/service/shared/TinyPushPayload.cjs +199 -0
  262. package/dist/v1/libs/sw/service/shared/TinyPushPayload.d.mts +80 -0
  263. package/dist/v1/libs/sw/service/shared/TinyPushPayload.d.mts.map +1 -0
  264. package/dist/v1/libs/sw/service/shared/TinyPushPayload.mjs +174 -0
  265. package/dist/v1/libs/sw/utils.cjs +57 -0
  266. package/dist/v1/libs/sw/utils.d.mts +173 -0
  267. package/dist/v1/libs/sw/utils.d.mts.map +1 -0
  268. package/dist/v1/libs/sw/utils.mjs +50 -0
  269. package/dist/v1/libs/text/TinyI18/Browser-NON-DOM.cjs +57 -0
  270. package/dist/v1/libs/text/TinyI18/Browser-NON-DOM.d.mts +39 -0
  271. package/dist/v1/libs/text/TinyI18/Browser-NON-DOM.d.mts.map +1 -0
  272. package/dist/v1/libs/text/TinyI18/Browser-NON-DOM.mjs +48 -0
  273. package/dist/v1/libs/text/TinyI18/Browser.cjs +64 -0
  274. package/dist/v1/libs/text/TinyI18/Browser.d.mts +47 -0
  275. package/dist/v1/libs/text/TinyI18/Browser.d.mts.map +1 -0
  276. package/dist/v1/libs/text/TinyI18/Browser.mjs +57 -0
  277. package/dist/v1/libs/text/TinyI18/Node.cjs +49 -0
  278. package/dist/v1/libs/text/TinyI18/Node.d.mts +38 -0
  279. package/dist/v1/libs/text/TinyI18/Node.d.mts.map +1 -0
  280. package/dist/v1/libs/text/TinyI18/Node.mjs +43 -0
  281. package/dist/v1/libs/text/TinyI18/browser-utils.cjs +17 -0
  282. package/dist/v1/libs/text/TinyI18/browser-utils.d.mts +8 -0
  283. package/dist/v1/libs/text/TinyI18/browser-utils.d.mts.map +1 -0
  284. package/dist/v1/libs/text/TinyI18/browser-utils.mjs +13 -0
  285. package/dist/v1/libs/text/{TinyI18.cjs → TinyI18/index.cjs} +205 -104
  286. package/dist/v1/libs/text/{TinyI18.d.mts → TinyI18/index.d.mts} +141 -92
  287. package/dist/v1/libs/text/TinyI18/index.d.mts.map +1 -0
  288. package/dist/v1/libs/text/{TinyI18.mjs → TinyI18/index.mjs} +195 -101
  289. package/dist/v1/libs/tools/TinyBrowserMonitor.cjs +1088 -0
  290. package/dist/v1/libs/tools/TinyBrowserMonitor.d.mts +621 -0
  291. package/dist/v1/libs/tools/TinyBrowserMonitor.d.mts.map +1 -0
  292. package/dist/v1/libs/tools/TinyBrowserMonitor.mjs +940 -0
  293. package/dist/v1/libs/tools/TinyDebugger.cjs +180 -19
  294. package/dist/v1/libs/tools/TinyDebugger.d.mts +220 -24
  295. package/dist/v1/libs/tools/TinyDebugger.d.mts.map +1 -1
  296. package/dist/v1/libs/tools/TinyDebugger.mjs +161 -19
  297. package/dist/v1/libs/tools/TinyHtmlTagRegexBuilder.cjs +256 -0
  298. package/dist/v1/libs/tools/TinyHtmlTagRegexBuilder.d.mts +125 -0
  299. package/dist/v1/libs/tools/TinyHtmlTagRegexBuilder.d.mts.map +1 -0
  300. package/dist/v1/libs/tools/TinyHtmlTagRegexBuilder.mjs +223 -0
  301. package/dist/v1/libs/tools/TinyHttpResponseRegistry/Browser-NON-DOM.cjs +23 -0
  302. package/dist/v1/libs/tools/TinyHttpResponseRegistry/Browser-NON-DOM.d.mts +17 -0
  303. package/dist/v1/libs/tools/TinyHttpResponseRegistry/Browser-NON-DOM.d.mts.map +1 -0
  304. package/dist/v1/libs/tools/TinyHttpResponseRegistry/Browser-NON-DOM.mjs +19 -0
  305. package/dist/v1/libs/tools/TinyHttpResponseRegistry/Browser.cjs +23 -0
  306. package/dist/v1/libs/tools/TinyHttpResponseRegistry/Browser.d.mts +17 -0
  307. package/dist/v1/libs/tools/TinyHttpResponseRegistry/Browser.d.mts.map +1 -0
  308. package/dist/v1/libs/tools/TinyHttpResponseRegistry/Browser.mjs +19 -0
  309. package/dist/v1/libs/tools/TinyHttpResponseRegistry/EmptyRequestCodes.cjs +390 -0
  310. package/dist/v1/libs/tools/TinyHttpResponseRegistry/EmptyRequestCodes.d.mts +9 -0
  311. package/dist/v1/libs/tools/TinyHttpResponseRegistry/EmptyRequestCodes.d.mts.map +1 -0
  312. package/dist/v1/libs/tools/TinyHttpResponseRegistry/EmptyRequestCodes.mjs +387 -0
  313. package/dist/v1/libs/tools/TinyHttpResponseRegistry/JsDoc.cjs +2 -0
  314. package/dist/v1/libs/tools/TinyHttpResponseRegistry/JsDoc.d.mts +27 -0
  315. package/dist/v1/libs/tools/TinyHttpResponseRegistry/JsDoc.d.mts.map +1 -0
  316. package/dist/v1/libs/tools/TinyHttpResponseRegistry/JsDoc.mjs +12 -0
  317. package/dist/v1/libs/tools/TinyHttpResponseRegistry/MozillaRequestCodes/LICENSE +53 -0
  318. package/dist/v1/libs/tools/TinyHttpResponseRegistry/MozillaRequestCodes/index.cjs +405 -0
  319. package/dist/v1/libs/tools/TinyHttpResponseRegistry/MozillaRequestCodes/index.d.mts +34 -0
  320. package/dist/v1/libs/tools/TinyHttpResponseRegistry/MozillaRequestCodes/index.d.mts.map +1 -0
  321. package/dist/v1/libs/tools/TinyHttpResponseRegistry/MozillaRequestCodes/index.mjs +342 -0
  322. package/dist/v1/libs/tools/TinyHttpResponseRegistry/Node.cjs +23 -0
  323. package/dist/v1/libs/tools/TinyHttpResponseRegistry/Node.d.mts +17 -0
  324. package/dist/v1/libs/tools/TinyHttpResponseRegistry/Node.d.mts.map +1 -0
  325. package/dist/v1/libs/tools/TinyHttpResponseRegistry/Node.mjs +19 -0
  326. package/dist/v1/libs/tools/TinyHttpResponseRegistry/RequestCodes.cjs +327 -0
  327. package/dist/v1/libs/tools/TinyHttpResponseRegistry/RequestCodes.d.mts +9 -0
  328. package/dist/v1/libs/tools/TinyHttpResponseRegistry/RequestCodes.d.mts.map +1 -0
  329. package/dist/v1/libs/tools/TinyHttpResponseRegistry/RequestCodes.mjs +324 -0
  330. package/dist/v1/libs/tools/TinyHttpResponseRegistry/index.cjs +268 -0
  331. package/dist/v1/libs/tools/TinyHttpResponseRegistry/index.d.mts +107 -0
  332. package/dist/v1/libs/tools/TinyHttpResponseRegistry/index.d.mts.map +1 -0
  333. package/dist/v1/libs/tools/TinyHttpResponseRegistry/index.mjs +238 -0
  334. package/dist/v1/libs/tools/TinyPasswordValidator.cjs +491 -0
  335. package/dist/v1/libs/tools/TinyPasswordValidator.d.mts +246 -0
  336. package/dist/v1/libs/tools/TinyPasswordValidator.d.mts.map +1 -0
  337. package/dist/v1/libs/tools/TinyPasswordValidator.mjs +434 -0
  338. package/dist/v1/libs/tools/TinyPkgExportValidator.cjs +48 -0
  339. package/dist/v1/libs/tools/TinyPkgExportValidator.d.mts +14 -0
  340. package/dist/v1/libs/tools/TinyPkgExportValidator.d.mts.map +1 -1
  341. package/dist/v1/libs/tools/TinyPkgExportValidator.mjs +44 -0
  342. package/dist/v1/libs/tools/TinySiteMap.cjs +1029 -0
  343. package/dist/v1/libs/tools/TinySiteMap.d.mts +429 -0
  344. package/dist/v1/libs/tools/TinySiteMap.d.mts.map +1 -0
  345. package/dist/v1/libs/tools/TinySiteMap.mjs +910 -0
  346. package/dist/v1/libs/tools/TinySiteMapStream.cjs +121 -0
  347. package/dist/v1/libs/tools/TinySiteMapStream.d.mts +51 -0
  348. package/dist/v1/libs/tools/TinySiteMapStream.d.mts.map +1 -0
  349. package/dist/v1/libs/tools/TinySiteMapStream.mjs +85 -0
  350. package/dist/v1/libs/tools/TinyURLSecurityVerifier.cjs +444 -0
  351. package/dist/v1/libs/tools/TinyURLSecurityVerifier.d.mts +217 -0
  352. package/dist/v1/libs/tools/TinyURLSecurityVerifier.d.mts.map +1 -0
  353. package/dist/v1/libs/tools/TinyURLSecurityVerifier.mjs +394 -0
  354. package/dist/v1/libs/tools/TinyUriParser/BlueSky.cjs +613 -0
  355. package/dist/v1/libs/tools/TinyUriParser/BlueSky.d.mts +152 -0
  356. package/dist/v1/libs/tools/TinyUriParser/BlueSky.d.mts.map +1 -0
  357. package/dist/v1/libs/tools/TinyUriParser/BlueSky.mjs +527 -0
  358. package/dist/v1/libs/tools/TinyUriParser/Discord.cjs +1119 -0
  359. package/dist/v1/libs/tools/TinyUriParser/Discord.d.mts +306 -0
  360. package/dist/v1/libs/tools/TinyUriParser/Discord.d.mts.map +1 -0
  361. package/dist/v1/libs/tools/TinyUriParser/Discord.mjs +968 -0
  362. package/dist/v1/libs/tools/TinyUriParser/MatrixProtocol.cjs +469 -0
  363. package/dist/v1/libs/tools/TinyUriParser/MatrixProtocol.d.mts +80 -0
  364. package/dist/v1/libs/tools/TinyUriParser/MatrixProtocol.d.mts.map +1 -0
  365. package/dist/v1/libs/tools/TinyUriParser/MatrixProtocol.mjs +379 -0
  366. package/dist/v1/libs/tools/TinyUriParser.cjs +217 -0
  367. package/dist/v1/libs/tools/TinyUriParser.d.mts +109 -0
  368. package/dist/v1/libs/tools/TinyUriParser.d.mts.map +1 -0
  369. package/dist/v1/libs/tools/TinyUriParser.mjs +183 -0
  370. package/dist/v1/libs/utils/TinyCloner.cjs +466 -0
  371. package/dist/v1/libs/utils/TinyCloner.d.mts +221 -0
  372. package/dist/v1/libs/utils/TinyCloner.d.mts.map +1 -0
  373. package/dist/v1/libs/utils/TinyCloner.mjs +416 -0
  374. package/dist/v1/libs/utils/TinyPromiseQueue.cjs +1 -1
  375. package/dist/v1/libs/utils/TinyPromiseQueue.d.mts +2 -2
  376. package/dist/v1/libs/utils/TinyPromiseQueue.d.mts.map +1 -1
  377. package/dist/v1/libs/utils/TinyPromiseQueue.mjs +1 -1
  378. package/dist/v1/libs/utils/TinyThrottledApi.cjs +333 -0
  379. package/dist/v1/libs/utils/TinyThrottledApi.d.mts +163 -0
  380. package/dist/v1/libs/utils/TinyThrottledApi.d.mts.map +1 -0
  381. package/dist/v1/libs/utils/TinyThrottledApi.mjs +294 -0
  382. package/dist/v1/libs/worker/browser/TinyWebWorker.cjs +342 -0
  383. package/dist/v1/libs/worker/browser/TinyWebWorker.d.mts +97 -0
  384. package/dist/v1/libs/worker/browser/TinyWebWorker.d.mts.map +1 -0
  385. package/dist/v1/libs/worker/browser/TinyWebWorker.mjs +305 -0
  386. package/dist/v1/libs/worker/engine/TinyWebWorkerEngine.cjs +346 -0
  387. package/dist/v1/libs/worker/engine/TinyWebWorkerEngine.d.mts +127 -0
  388. package/dist/v1/libs/worker/engine/TinyWebWorkerEngine.d.mts.map +1 -0
  389. package/dist/v1/libs/worker/engine/TinyWebWorkerEngine.mjs +304 -0
  390. package/dist/v1/regexp/Email.cjs +185 -0
  391. package/dist/v1/regexp/Email.d.mts +73 -0
  392. package/dist/v1/regexp/Email.d.mts.map +1 -0
  393. package/dist/v1/regexp/Email.mjs +153 -0
  394. package/dist/v1/regexp/Glob.cjs +293 -0
  395. package/dist/v1/regexp/Glob.d.mts +45 -0
  396. package/dist/v1/regexp/Glob.d.mts.map +1 -0
  397. package/dist/v1/regexp/Glob.mjs +260 -0
  398. package/dist/v1/regexp/Ipv4.cjs +57 -0
  399. package/dist/v1/regexp/Ipv4.d.mts +29 -0
  400. package/dist/v1/regexp/Ipv4.d.mts.map +1 -0
  401. package/dist/v1/regexp/Ipv4.mjs +45 -0
  402. package/dist/v1/regexp/Ipv6.cjs +67 -0
  403. package/dist/v1/regexp/Ipv6.d.mts +29 -0
  404. package/dist/v1/regexp/Ipv6.d.mts.map +1 -0
  405. package/dist/v1/regexp/Ipv6.mjs +54 -0
  406. package/dist/v1/regexp/SegmentExtractor.cjs +145 -0
  407. package/dist/v1/regexp/SegmentExtractor.d.mts +91 -0
  408. package/dist/v1/regexp/SegmentExtractor.d.mts.map +1 -0
  409. package/dist/v1/regexp/SegmentExtractor.mjs +116 -0
  410. package/dist/v1/regexp/UrlDetector.cjs +125 -0
  411. package/dist/v1/regexp/UrlDetector.d.mts +67 -0
  412. package/dist/v1/regexp/UrlDetector.d.mts.map +1 -0
  413. package/dist/v1/regexp/UrlDetector.mjs +102 -0
  414. package/dist/v1/regexp/Username/index.cjs +233 -0
  415. package/dist/v1/regexp/Username/index.d.mts +77 -0
  416. package/dist/v1/regexp/Username/index.d.mts.map +1 -0
  417. package/dist/v1/regexp/Username/index.mjs +199 -0
  418. package/dist/v1/regexp/Username/jsDoc.cjs +2 -0
  419. package/dist/v1/regexp/Username/jsDoc.d.mts +57 -0
  420. package/dist/v1/regexp/Username/jsDoc.d.mts.map +1 -0
  421. package/dist/v1/regexp/Username/jsDoc.mjs +18 -0
  422. package/dist/v1/regexp/Username/templates/BlueSky.cjs +56 -0
  423. package/dist/v1/regexp/Username/templates/BlueSky.d.mts +35 -0
  424. package/dist/v1/regexp/Username/templates/BlueSky.d.mts.map +1 -0
  425. package/dist/v1/regexp/Username/templates/BlueSky.mjs +52 -0
  426. package/dist/v1/regexp/Username/templates/Discord.cjs +505 -0
  427. package/dist/v1/regexp/Username/templates/Discord.d.mts +209 -0
  428. package/dist/v1/regexp/Username/templates/Discord.d.mts.map +1 -0
  429. package/dist/v1/regexp/Username/templates/Discord.mjs +458 -0
  430. package/dist/v1/regexp/Username/templates/MatrixProtocol.cjs +143 -0
  431. package/dist/v1/regexp/Username/templates/MatrixProtocol.d.mts +70 -0
  432. package/dist/v1/regexp/Username/templates/MatrixProtocol.d.mts.map +1 -0
  433. package/dist/v1/regexp/Username/templates/MatrixProtocol.mjs +128 -0
  434. package/dist/v1/regexp/Username/templates/deprecated/Discord.cjs +24 -0
  435. package/dist/v1/regexp/Username/templates/deprecated/Discord.d.mts +17 -0
  436. package/dist/v1/regexp/Username/templates/deprecated/Discord.d.mts.map +1 -0
  437. package/dist/v1/regexp/Username/templates/deprecated/Discord.mjs +20 -0
  438. package/dist/v1/regexp/Username/templates/index.cjs +11 -0
  439. package/dist/v1/regexp/Username/templates/index.d.mts +5 -0
  440. package/dist/v1/regexp/Username/templates/index.d.mts.map +1 -0
  441. package/dist/v1/regexp/Username/templates/index.mjs +4 -0
  442. package/dist/v1/regexp/index.cjs +41 -0
  443. package/dist/v1/regexp/index.d.mts +9 -0
  444. package/dist/v1/regexp/index.d.mts.map +1 -0
  445. package/dist/v1/regexp/index.mjs +8 -0
  446. package/dist/v1/webTemplates/ag-psd/31.0/ProcessSolidFilters/Browser.cjs +64 -0
  447. package/dist/v1/webTemplates/ag-psd/31.0/ProcessSolidFilters/Browser.d.mts +11 -0
  448. package/dist/v1/webTemplates/ag-psd/31.0/ProcessSolidFilters/Browser.d.mts.map +1 -0
  449. package/dist/v1/webTemplates/ag-psd/31.0/ProcessSolidFilters/Browser.mjs +51 -0
  450. package/dist/v1/webTemplates/ag-psd/31.0/ProcessSolidFilters/FileInput.cjs +66 -0
  451. package/dist/v1/webTemplates/ag-psd/31.0/ProcessSolidFilters/FileInput.d.mts +11 -0
  452. package/dist/v1/webTemplates/ag-psd/31.0/ProcessSolidFilters/FileInput.d.mts.map +1 -0
  453. package/dist/v1/webTemplates/ag-psd/31.0/ProcessSolidFilters/FileInput.mjs +51 -0
  454. package/dist/v1/webTemplates/ag-psd/31.0/ProcessSolidFilters/Node.cjs +39 -0
  455. package/dist/v1/webTemplates/ag-psd/31.0/ProcessSolidFilters/Node.d.mts +11 -0
  456. package/dist/v1/webTemplates/ag-psd/31.0/ProcessSolidFilters/Node.d.mts.map +1 -0
  457. package/dist/v1/webTemplates/ag-psd/31.0/ProcessSolidFilters/Node.mjs +28 -0
  458. package/dist/v1/webTemplates/ag-psd/31.0/ProcessSolidFilters/Template.cjs +494 -0
  459. package/dist/v1/webTemplates/ag-psd/31.0/ProcessSolidFilters/Template.d.mts +142 -0
  460. package/dist/v1/webTemplates/ag-psd/31.0/ProcessSolidFilters/Template.d.mts.map +1 -0
  461. package/dist/v1/webTemplates/ag-psd/31.0/ProcessSolidFilters/Template.mjs +445 -0
  462. package/dist/v1/webTemplates/bootstrap/5.3/html/BootstrapDialogs.cjs +30 -4
  463. package/dist/v1/webTemplates/bootstrap/5.3/html/BootstrapDialogs.d.mts +5 -2
  464. package/dist/v1/webTemplates/bootstrap/5.3/html/BootstrapDialogs.d.mts.map +1 -1
  465. package/dist/v1/webTemplates/bootstrap/5.3/html/BootstrapDialogs.mjs +29 -5
  466. package/dist/v1/webTemplates/media/MediaValidator/v1/Browser/index.cjs +135 -0
  467. package/dist/v1/webTemplates/media/MediaValidator/v1/Browser/index.d.mts +83 -0
  468. package/dist/v1/webTemplates/media/MediaValidator/v1/Browser/index.d.mts.map +1 -0
  469. package/dist/v1/webTemplates/media/MediaValidator/v1/Browser/index.mjs +120 -0
  470. package/dist/v1/webTemplates/media/MediaValidator/v1/Node/index.cjs +127 -0
  471. package/dist/v1/webTemplates/media/MediaValidator/v1/Node/index.d.mts +95 -0
  472. package/dist/v1/webTemplates/media/MediaValidator/v1/Node/index.d.mts.map +1 -0
  473. package/dist/v1/webTemplates/media/MediaValidator/v1/Node/index.mjs +109 -0
  474. package/dist/v1/webTemplates/multiformats/14.0/IPFSHasher/index.cjs +83 -0
  475. package/dist/v1/webTemplates/multiformats/14.0/IPFSHasher/index.d.mts +46 -0
  476. package/dist/v1/webTemplates/multiformats/14.0/IPFSHasher/index.d.mts.map +1 -0
  477. package/dist/v1/webTemplates/multiformats/14.0/IPFSHasher/index.mjs +71 -0
  478. package/dist/v1/webTemplates/vite/7.3/plugins/TinyVitePwaPlugin.cjs +493 -0
  479. package/dist/v1/webTemplates/vite/7.3/plugins/TinyVitePwaPlugin.d.mts +67 -0
  480. package/dist/v1/webTemplates/vite/7.3/plugins/TinyVitePwaPlugin.d.mts.map +1 -0
  481. package/dist/v1/webTemplates/vite/7.3/plugins/TinyVitePwaPlugin.mjs +399 -0
  482. package/dist/v1/webTemplates/vite/7.3/plugins/githubUtils.cjs +35 -0
  483. package/dist/v1/webTemplates/vite/7.3/plugins/githubUtils.d.mts +6 -0
  484. package/dist/v1/webTemplates/vite/7.3/plugins/githubUtils.d.mts.map +1 -0
  485. package/dist/v1/webTemplates/vite/7.3/plugins/githubUtils.mjs +29 -0
  486. package/docs/info/RegExp.md +74 -0
  487. package/docs/v1/Exports.md +101 -0
  488. package/docs/v1/README.md +113 -15
  489. package/docs/v1/basics/asyncReplace.md +2 -0
  490. package/docs/v1/basics/browserDetector.md +28 -11
  491. package/docs/v1/basics/crypto.md +85 -0
  492. package/docs/v1/basics/deprecated/html.md +2 -0
  493. package/docs/v1/basics/deprecated/objFilter.md +2 -0
  494. package/docs/v1/basics/html.md +2 -0
  495. package/docs/v1/basics/objChecker.md +55 -0
  496. package/docs/v1/basics/objFilter.md +57 -86
  497. package/docs/v1/basics/promiseUtils.md +12 -3
  498. package/docs/v1/basics/text.md +0 -1
  499. package/docs/v1/libs/array/TinyArrayComparator.md +50 -39
  500. package/docs/v1/libs/fs/TinyFS.md +752 -0
  501. package/docs/v1/libs/fs/TinyOPFSFileSystem.md +495 -0
  502. package/docs/v1/libs/fs/TinyStorageBucketFileSystem.md +407 -0
  503. package/docs/v1/libs/plugin/TinyPlugin.md +441 -0
  504. package/docs/v1/libs/plugin/TinyVersion.md +145 -0
  505. package/docs/v1/libs/router/TinyRouter.md +216 -0
  506. package/docs/v1/libs/storage/TinyMapCache.md +219 -0
  507. package/docs/v1/libs/storage/TinySetMapDatabase.md +478 -0
  508. package/docs/v1/libs/sw/browser/TinyNotificationAdapter.md +280 -0
  509. package/docs/v1/libs/sw/browser/TinyPushManager.md +782 -0
  510. package/docs/v1/libs/sw/browser/TinyServiceWorker.md +365 -0
  511. package/docs/v1/libs/sw/browser/plugins/TabManager.md +133 -0
  512. package/docs/v1/libs/sw/service/TinyPushRouter.md +314 -0
  513. package/docs/v1/libs/sw/service/TinyServiceWorkerEngine.md +748 -0
  514. package/docs/v1/libs/sw/service/plugins/GlobBypassPlugin.md +229 -0
  515. package/docs/v1/libs/sw/service/plugins/GlobCachePlugin.md +91 -0
  516. package/docs/v1/libs/sw/service/plugins/Ping.md +36 -0
  517. package/docs/v1/libs/sw/service/plugins/TabManager.md +64 -0
  518. package/docs/v1/libs/sw/service/plugins/ViteFileDetector.md +92 -0
  519. package/docs/v1/libs/sw/service/shared/TinyPushPayload.md +316 -0
  520. package/docs/v1/libs/text/TinyI18.md +80 -56
  521. package/docs/v1/libs/tools/TinyBrowserMonitor.md +170 -0
  522. package/docs/v1/libs/tools/TinyDebugger.md +117 -1
  523. package/docs/v1/libs/tools/TinyHtmlTagRegexBuilder.md +141 -0
  524. package/docs/v1/libs/tools/TinyHttpResponseRegistry.md +129 -0
  525. package/docs/v1/libs/tools/TinyPasswordValidator.md +153 -0
  526. package/docs/v1/libs/tools/TinyPkgExportValidator.md +45 -1
  527. package/docs/v1/libs/tools/TinySiteMap.md +134 -0
  528. package/docs/v1/libs/tools/TinySiteMapStream.md +97 -0
  529. package/docs/v1/libs/tools/TinyURLSecurityVerifier.md +146 -0
  530. package/docs/v1/libs/tools/TinyUriParser/Discord.md +374 -0
  531. package/docs/v1/libs/tools/TinyUriParser/MatrixProtocol.md +54 -0
  532. package/docs/v1/libs/tools/TinyUriParser.md +128 -0
  533. package/docs/v1/libs/utils/TinyCloner.md +126 -0
  534. package/docs/v1/libs/utils/TinyPromiseQueue.md +1 -1
  535. package/docs/v1/libs/utils/TinyThrottledApi.md +219 -0
  536. package/docs/v1/libs/worker/browser/TinyWebWorker.md +331 -0
  537. package/docs/v1/libs/worker/engine/TinyWebWorkerEngine.md +137 -0
  538. package/docs/v1/regexp/Email.md +127 -0
  539. package/docs/v1/regexp/Glob.md +155 -0
  540. package/docs/v1/regexp/IPv4.md +103 -0
  541. package/docs/v1/regexp/IPv6.md +122 -0
  542. package/docs/v1/regexp/SegmentExtractor.md +120 -0
  543. package/docs/v1/regexp/UrlDetector.md +117 -0
  544. package/docs/v1/regexp/Username/Base.md +131 -0
  545. package/docs/v1/regexp/Username/Discord.md +267 -0
  546. package/docs/v1/regexp/Username/MatrixProtocol.md +131 -0
  547. package/docs/v1/webTemplates/ag-psd/31.0/ProcessSolidFilters.md +565 -0
  548. package/docs/v1/webTemplates/bootstrap/5.3/html/BootstrapDialogs.md +19 -7
  549. package/docs/v1/webTemplates/media/MediaValidator/v1/Browser.md +123 -0
  550. package/docs/v1/webTemplates/media/MediaValidator/v1/Node.md +136 -0
  551. package/docs/v1/webTemplates/multiformats/14.0/IPFSHasher.md +310 -0
  552. package/docs/v1/webTemplates/vite/7.3/plugins/TinyVitePwaPlugin.md +131 -0
  553. package/docs/v1/webTemplates/vite/7.3/plugins/githubUtils.md +50 -0
  554. package/package.json +340 -22
  555. package/types/EventEmitter.d.ts +48 -0
  556. package/dist/v1/libs/text/TinyI18.d.mts.map +0 -1
@@ -0,0 +1,968 @@
1
+ import TinyUriParser from '../TinyUriParser.mjs';
2
+ /**
3
+ * Discord Text Elements
4
+ * Official Documentation: https://discord.com/developers/docs/reference#message-formatting
5
+ */
6
+ /**
7
+ * The category of entity targeted by a Discord mention.
8
+ * @typedef {'user' | 'role' | 'channel'} DiscordMentionTarget
9
+ */
10
+ /**
11
+ * A plain key/value map of decoded query string parameters.
12
+ * @typedef {Record<string, string>} DiscordQueryParams
13
+ */
14
+ /**
15
+ * Represents a parsed Discord mention element.
16
+ * @typedef {Object} DiscordMentionData
17
+ * @property {'mention'} dataType - The discriminator for a mention element.
18
+ * @property {DiscordMentionTarget} target - The kind of entity being mentioned.
19
+ * @property {string} id - The snowflake identifier of the mentioned entity.
20
+ * @property {boolean} isNickname - Whether the mention uses the nickname syntax (`<@!id>`).
21
+ */
22
+ /**
23
+ * Represents a parsed Discord game profile element.
24
+ * @typedef {Object} DiscordGameProfileData
25
+ * @property {'game_profile'} dataType - The discriminator for a game profile element.
26
+ * @property {string} id - The snowflake identifier of the game.
27
+ */
28
+ /**
29
+ * The in-application navigation tab targeted by a guild navigation element.
30
+ * @typedef {'customize' | 'browse' | 'guide' | 'linked-roles'} DiscordGuildNavigationTarget
31
+ */
32
+ /**
33
+ * Represents a parsed Discord guild navigation element.
34
+ * @typedef {Object} DiscordGuildNavigationData
35
+ * @property {'guild_navigation'} dataType - The discriminator for a guild navigation element.
36
+ * @property {DiscordGuildNavigationTarget} target - The navigation tab to open.
37
+ * @property {string | null} roleId - The linked role snowflake, or `null` when the tab has no role.
38
+ */
39
+ /**
40
+ * Represents a parsed Discord custom emoji element.
41
+ * @typedef {Object} DiscordEmojiData
42
+ * @property {'emoji'} dataType - The discriminator for an emoji element.
43
+ * @property {string} name - The name of the emoji.
44
+ * @property {string} id - The snowflake identifier of the emoji.
45
+ * @property {boolean} animated - Whether the emoji is animated.
46
+ */
47
+ /**
48
+ * Represents a parsed Discord timestamp element.
49
+ * @typedef {Object} DiscordTimestampData
50
+ * @property {'timestamp'} dataType - The discriminator for a timestamp element.
51
+ * @property {number} timestamp - The Unix timestamp, in seconds.
52
+ * @property {string} style - The formatting style flag, or an empty string when omitted.
53
+ */
54
+ /**
55
+ * The structural parts of a Discord slash command path.
56
+ * @typedef {Object} DiscordCommandPath
57
+ * @property {string} command - The root command name.
58
+ * @property {string | null} subcommandGroup - The subcommand group, or `null` when absent.
59
+ * @property {string | null} subcommand - The subcommand, or `null` when absent.
60
+ */
61
+ /**
62
+ * Represents a parsed Discord slash command element.
63
+ * @typedef {Object} DiscordCommandData
64
+ * @property {'command'} dataType - The discriminator for a command element.
65
+ * @property {string} name - The full command path, without the leading slash (e.g., `play music`).
66
+ * @property {string} command - The root command name.
67
+ * @property {string | null} subcommandGroup - The subcommand group, or `null` when absent.
68
+ * @property {string | null} subcommand - The subcommand, or `null` when absent.
69
+ * @property {string} id - The snowflake identifier of the command.
70
+ */
71
+ /**
72
+ * Represents a parsed Discord invite link.
73
+ * @typedef {Object} DiscordInviteData
74
+ * @property {'invite'} dataType - The discriminator for an invite element.
75
+ * @property {string} code - The invite code or server slug.
76
+ * @property {'discord.gg' | 'discord.com' | 'discordapp.com'} host - The normalized host.
77
+ * @property {'invite' | 'servers' | null} kind - The path kind, or `null` for short links.
78
+ * @property {boolean} obfuscated - Whether the source used whitespace obfuscation.
79
+ * @property {DiscordQueryParams} params - The decoded query string parameters.
80
+ */
81
+ /**
82
+ * Represents a parsed Discord message link.
83
+ * @typedef {Object} DiscordMessageLinkData
84
+ * @property {'message_link'} dataType - The discriminator for a message link element.
85
+ * @property {string} guildId - The guild snowflake, or '@me' for direct messages.
86
+ * @property {string} channelId - The channel snowflake.
87
+ * @property {string} messageId - The message snowflake.
88
+ * @property {DiscordQueryParams} params - The decoded query string parameters.
89
+ */
90
+ /**
91
+ * The category of a Discord CDN asset.
92
+ * @typedef {'attachment' | 'emoji' | 'guild_icon' | 'guild_splash' | 'guild_discovery_splash' | 'banner' | 'default_user_avatar' | 'user_avatar' | 'guild_member_avatar' | 'avatar_decoration' | 'application_icon' | 'application_asset' | 'achievement_icon' | 'store_page_asset' | 'sticker_pack_banner' | 'team_icon' | 'sticker' | 'role_icon' | 'guild_scheduled_event_cover' | 'guild_member_banner' | 'guild_tag_badge'} DiscordCdnKind
93
+ */
94
+ /**
95
+ * The named path segments extracted from a Discord CDN URL.
96
+ * @typedef {Object} DiscordCdnSegments
97
+ * @property {string} [guildId] - The guild snowflake, when present.
98
+ * @property {string} [userId] - The user snowflake, when present.
99
+ * @property {string} [channelId] - The channel snowflake, when present.
100
+ * @property {string} [attachmentId] - The attachment snowflake, when present.
101
+ * @property {string} [applicationId] - The application snowflake, when present.
102
+ * @property {string} [achievementId] - The achievement snowflake, when present.
103
+ * @property {string} [teamId] - The team snowflake, when present.
104
+ * @property {string} [eventId] - The scheduled event snowflake, when present.
105
+ * @property {string} [roleId] - The role snowflake, when present.
106
+ * @property {string} [id] - The generic snowflake (emoji, sticker, banner), when present.
107
+ * @property {string} [index] - The default avatar index, when present.
108
+ */
109
+ /**
110
+ * Represents a parsed Discord CDN asset URL.
111
+ * @typedef {Object} DiscordCdnData
112
+ * @property {'cdn_asset'} dataType - The discriminator for a CDN asset element.
113
+ * @property {DiscordCdnKind} kind - The category of the asset.
114
+ * @property {string} host - The CDN host (e.g., `cdn.discordapp.com`).
115
+ * @property {string} path - The raw path that follows the CDN host.
116
+ * @property {string} hash - The asset hash, or the filename without its extension.
117
+ * @property {string} ext - The file extension, without the leading dot.
118
+ * @property {string | null} filename - The raw attachment filename, or `null` for non-attachments.
119
+ * @property {boolean} spoiler - Whether the attachment is flagged as a spoiler.
120
+ * @property {DiscordCdnSegments} segments - The named path segments.
121
+ * @property {DiscordQueryParams} params - The decoded query string parameters.
122
+ */
123
+ /**
124
+ * A supported Discord CDN route.
125
+ * @typedef {Object} DiscordCdnRoute
126
+ * @property {DiscordCdnKind} kind - The asset category.
127
+ * @property {string} template - The path template, using `:name` placeholders.
128
+ */
129
+ /**
130
+ * Matches a Discord mention: `<@id>`, `<@!id>`, `<@&id>` or `<#id>`.
131
+ * @type {RegExp}
132
+ */
133
+ const mentionRegex = /^<(?<prefix>@!?|@&|#)(?<id>\d+)>$/;
134
+ /**
135
+ * Matches a Discord game profile: `<@$id>`.
136
+ * @type {RegExp}
137
+ */
138
+ const gameProfileRegex = /^<@\$(?<id>\d+)>$/;
139
+ /**
140
+ * Matches a Discord guild navigation element: `<id:type>` or `<id:linked-roles:roleId>`.
141
+ * @type {RegExp}
142
+ */
143
+ const guildNavigationRegex = /^<id:(?<target>[a-z-]+)(?::(?<roleId>\d+))?>$/;
144
+ /**
145
+ * Matches a Discord custom emoji: `<:name:id>` or `<a:name:id>`.
146
+ * @type {RegExp}
147
+ */
148
+ const emojiRegex = /^<(?<animated>a)?:(?<name>\w+):(?<id>\d+)>$/;
149
+ /**
150
+ * Matches a Discord timestamp: `<t:unix>` or `<t:unix:style>`.
151
+ * @type {RegExp}
152
+ */
153
+ const timestampRegex = /^<t:(?<timestamp>\d+)(?::(?<style>[tTdDfFRsS]))?>$/;
154
+ /**
155
+ * Matches a Discord slash command: `</name:id>`, `</name subcommand:id>` or
156
+ * `</name group subcommand:id>`.
157
+ * @type {RegExp}
158
+ */
159
+ const commandRegex = /^<\/(?<name>[\w-]+(?: [\w-]+){0,2}):(?<id>\d+)>$/;
160
+ /**
161
+ * Matches a standard Discord invite URL, with an optional query string.
162
+ * @type {RegExp}
163
+ */
164
+ const inviteRegex = /^(?:https?:\/\/)?(?:www\.)?(?:(?<shortHost>discord\.gg)\/(?<shortCode>[\w-]+)|(?<fullHost>discord(?:app)?\.com)\/(?<kind>invite|servers)\/(?<code>[\w-]+))\/?(?:\?(?<query>[^#\s]*))?$/i;
165
+ /**
166
+ * Matches a whitespace-obfuscated Discord invite, with an optional query string.
167
+ * @type {RegExp}
168
+ */
169
+ const obfuscatedInviteRegex = /^\s*(?<host>discord(?:app)?\s*\.\s*(?:gg|co(?:m)?))(?:\s*\/\s*(?:(?<kind>invite|servers)\s*\/\s*)?)(?<code>[\w-]+)(?:\s*\?\s*(?<query>[^#\s]*))?\s*$/i;
170
+ /**
171
+ * Matches a Discord message URL, with an optional query string.
172
+ * @type {RegExp}
173
+ */
174
+ const messageLinkRegex = /^https?:\/\/(?:www\.)?discord(?:app)?\.com\/channels\/(?<guildId>@me|\d+)\/(?<channelId>\d+)\/(?<messageId>\d+)\/?(?:\?(?<query>[^#\s]*))?$/;
175
+ /**
176
+ * The hosts that serve Discord CDN assets.
177
+ * @type {readonly string[]}
178
+ */
179
+ const CDN_HOSTS = Object.freeze(['cdn.discordapp.com', 'media.discordapp.net']);
180
+ /**
181
+ * The file extensions recognized on the Discord CDN.
182
+ * @type {readonly string[]}
183
+ */
184
+ const CDN_EXTENSIONS = Object.freeze(['jpg', 'jpeg', 'png', 'webp', 'gif', 'avif', 'json']);
185
+ /**
186
+ * Matches a Discord CDN URL and captures the host, path and query string.
187
+ * @type {RegExp}
188
+ */
189
+ const cdnRegex = /^https?:\/\/(?<host>cdn\.discordapp\.com|media\.discordapp\.net)\/(?<path>[^?#]+)(?:\?(?<query>[^#\s]*))?$/;
190
+ /**
191
+ * The regular expression fragment used for each placeholder name.
192
+ * @type {Readonly<Record<string, string>>}
193
+ */
194
+ const CDN_PLACEHOLDER_PATTERNS = Object.freeze({
195
+ ext: '[a-z0-9]+',
196
+ hash: '[A-Za-z0-9_.\\-]+',
197
+ index: '\\d+',
198
+ id: '\\d+',
199
+ filename: '[^\\s/?#]+',
200
+ });
201
+ /**
202
+ * The ordered list of supported Discord CDN routes.
203
+ * Order matters: more specific routes must be declared first.
204
+ * @type {readonly DiscordCdnRoute[]}
205
+ */
206
+ const CDN_ROUTES = Object.freeze([
207
+ { kind: 'attachment', template: 'attachments/:channelId/:attachmentId/:filename' },
208
+ { kind: 'guild_member_avatar', template: 'guilds/:guildId/users/:userId/avatars/:hash.:ext' },
209
+ { kind: 'guild_member_banner', template: 'guilds/:guildId/users/:userId/banners/:hash.:ext' },
210
+ {
211
+ kind: 'achievement_icon',
212
+ template: 'app-assets/:applicationId/achievements/:achievementId/icons/:hash.:ext',
213
+ },
214
+ { kind: 'sticker_pack_banner', template: 'app-assets/:applicationId/store/:hash.:ext' },
215
+ { kind: 'store_page_asset', template: 'app-assets/:applicationId/store/:hash' },
216
+ { kind: 'application_asset', template: 'app-assets/:applicationId/:hash.:ext' },
217
+ { kind: 'application_icon', template: 'app-icons/:applicationId/:hash.:ext' },
218
+ { kind: 'guild_icon', template: 'icons/:guildId/:hash.:ext' },
219
+ { kind: 'guild_splash', template: 'splashes/:guildId/:hash.:ext' },
220
+ { kind: 'guild_discovery_splash', template: 'discovery-splashes/:guildId/:hash.:ext' },
221
+ { kind: 'banner', template: 'banners/:id/:hash.:ext' },
222
+ { kind: 'default_user_avatar', template: 'embed/avatars/:index.:ext' },
223
+ { kind: 'user_avatar', template: 'avatars/:userId/:hash.:ext' },
224
+ { kind: 'avatar_decoration', template: 'avatar-decoration-presets/:hash.:ext' },
225
+ { kind: 'team_icon', template: 'team-icons/:teamId/:hash.:ext' },
226
+ { kind: 'emoji', template: 'emojis/:id.:ext' },
227
+ { kind: 'sticker', template: 'stickers/:id.:ext' },
228
+ { kind: 'role_icon', template: 'role-icons/:roleId/:hash.:ext' },
229
+ { kind: 'guild_scheduled_event_cover', template: 'guild-events/:eventId/:hash.:ext' },
230
+ { kind: 'guild_tag_badge', template: 'guild-tag-badges/:guildId/:hash.:ext' },
231
+ ]);
232
+ /**
233
+ * The set of supported CDN asset kinds.
234
+ * @type {ReadonlySet<DiscordCdnKind>}
235
+ */
236
+ const CDN_KINDS = new Set(CDN_ROUTES.map((route) => route.kind));
237
+ /**
238
+ * Escapes a string for literal use inside a regular expression.
239
+ * @param {string} value - The literal string to escape.
240
+ * @returns {string} The escaped string.
241
+ */
242
+ const escapeRegex = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
243
+ /**
244
+ * Compiles a CDN route template into a regular expression and an ordered list of placeholder names.
245
+ * @param {string} template - The path template (e.g., `icons/:guildId/:hash.:ext`).
246
+ * @returns {{ regex: RegExp, names: string[] }} The compiled route.
247
+ */
248
+ const compileCdnTemplate = (template) => {
249
+ /** @type {string[]} */
250
+ const names = [];
251
+ let pattern = '';
252
+ let cursor = 0;
253
+ const placeholderRegex = /:(\w+)/g;
254
+ let match;
255
+ while ((match = placeholderRegex.exec(template)) !== null) {
256
+ pattern += escapeRegex(template.slice(cursor, match.index));
257
+ const name = match[1];
258
+ names.push(name);
259
+ pattern += `(${CDN_PLACEHOLDER_PATTERNS[name] ?? '\\d+'})`;
260
+ cursor = match.index + match[0].length;
261
+ }
262
+ pattern += escapeRegex(template.slice(cursor));
263
+ return { regex: new RegExp(`^${pattern}$`), names };
264
+ };
265
+ /**
266
+ * The compiled CDN routes, in declaration order.
267
+ * @type {readonly { kind: DiscordCdnKind, regex: RegExp, names: string[] }[]}
268
+ */
269
+ const COMPILED_CDN_ROUTES = Object.freeze(CDN_ROUTES.map(({ kind, template }) => ({ kind, ...compileCdnTemplate(template) })));
270
+ /**
271
+ * Builds a canonical Discord CDN URL.
272
+ * @param {string} host - The CDN host.
273
+ * @param {string} path - The path that follows the host.
274
+ * @param {DiscordQueryParams} params - The query string parameters.
275
+ * @returns {string} The canonical CDN URL.
276
+ */
277
+ const buildCdnUrl = (host, path, params) => `https://${host}/${path}${buildQuery(params)}`;
278
+ /**
279
+ * Validates a parsed Discord CDN asset object.
280
+ * @param {DiscordCdnData} data - The CDN asset data to validate.
281
+ * @returns {void}
282
+ * @throws {TypeError} If any property is missing or of an invalid type.
283
+ */
284
+ const validateCdnData = (data) => {
285
+ if (typeof data.kind !== 'string' || !CDN_KINDS.has(data.kind)) {
286
+ throw new TypeError(`DiscordCdnData: invalid kind "${data.kind}".`);
287
+ }
288
+ if (typeof data.host !== 'string' || !CDN_HOSTS.includes(data.host)) {
289
+ throw new TypeError(`DiscordCdnData: invalid host "${data.host}".`);
290
+ }
291
+ if (typeof data.path !== 'string' || data.path.length === 0) {
292
+ throw new TypeError('DiscordCdnData: path must be a non-empty string.');
293
+ }
294
+ if (typeof data.hash !== 'string') {
295
+ throw new TypeError('DiscordCdnData: hash must be a string.');
296
+ }
297
+ if (typeof data.ext !== 'string') {
298
+ throw new TypeError('DiscordCdnData: ext must be a string.');
299
+ }
300
+ // Attachments may carry any extension, so the whitelist only applies to hashed assets.
301
+ if (data.kind !== 'attachment' && data.ext !== '' && !CDN_EXTENSIONS.includes(data.ext)) {
302
+ throw new TypeError(`DiscordCdnData: unsupported extension "${data.ext}".`);
303
+ }
304
+ if (data.filename !== null && typeof data.filename !== 'string') {
305
+ throw new TypeError('DiscordCdnData: filename must be a string or null.');
306
+ }
307
+ if (typeof data.spoiler !== 'boolean') {
308
+ throw new TypeError('DiscordCdnData: spoiler must be a boolean.');
309
+ }
310
+ if (data.segments === null || typeof data.segments !== 'object' || Array.isArray(data.segments)) {
311
+ throw new TypeError('DiscordCdnData: segments must be a plain object.');
312
+ }
313
+ if (data.params === null || typeof data.params !== 'object' || Array.isArray(data.params)) {
314
+ throw new TypeError('DiscordCdnData: params must be a plain object.');
315
+ }
316
+ };
317
+ /**
318
+ * Parses a Discord CDN asset URL.
319
+ * @param {string} uri - The raw CDN URL.
320
+ * @returns {DiscordCdnData} The parsed CDN asset data.
321
+ * @throws {TypeError} If the input is not a string or fails validation.
322
+ * @throws {SyntaxError} If the input does not match any known CDN route.
323
+ */
324
+ const parseCdnAsset = (uri) => {
325
+ if (typeof uri !== 'string') {
326
+ throw new TypeError('DiscordCdnData: uri must be a string.');
327
+ }
328
+ const urlMatch = cdnRegex.exec(uri);
329
+ if (!urlMatch || !urlMatch.groups) {
330
+ throw new SyntaxError(`Invalid Discord CDN URL: ${uri}`);
331
+ }
332
+ const { host, path, query } = urlMatch.groups;
333
+ for (const route of COMPILED_CDN_ROUTES) {
334
+ const routeMatch = route.regex.exec(path);
335
+ if (!routeMatch)
336
+ continue;
337
+ /** @type {Record<string, string>} */
338
+ const captures = {};
339
+ route.names.forEach((name, index) => {
340
+ captures[name] = routeMatch[index + 1];
341
+ });
342
+ const { hash = '', ext = '', filename, ...segments } = captures;
343
+ const isAttachment = typeof filename === 'string';
344
+ const lastDot = isAttachment ? filename.lastIndexOf('.') : -1;
345
+ const resolvedExt = lastDot > 0 ? filename.slice(lastDot + 1).toLowerCase() : ext;
346
+ const resolvedHash = isAttachment
347
+ ? lastDot > 0
348
+ ? filename.slice(0, lastDot)
349
+ : filename
350
+ : hash;
351
+ const params = parseQuery(query);
352
+ /** @type {DiscordCdnData} */
353
+ const data = {
354
+ dataType: 'cdn_asset',
355
+ kind: route.kind,
356
+ host,
357
+ path,
358
+ hash: resolvedHash,
359
+ ext: resolvedExt,
360
+ filename: filename ?? null,
361
+ spoiler: isAttachment ? filename.startsWith('SPOILER_') : false,
362
+ segments: /** @type {DiscordCdnSegments} */ (segments),
363
+ params,
364
+ };
365
+ validateCdnData(data);
366
+ return data;
367
+ }
368
+ throw new SyntaxError(`Unsupported Discord CDN path: ${path}`);
369
+ };
370
+ /**
371
+ * Reconstructs a Discord CDN URL from parsed data.
372
+ * @param {DiscordCdnData} data - The CDN asset data.
373
+ * @returns {string} The reconstructed CDN URL.
374
+ * @throws {TypeError} If the data is invalid.
375
+ */
376
+ const stringifyCdnAsset = (data) => {
377
+ validateCdnData(data);
378
+ return buildCdnUrl(data.host, data.path, data.params);
379
+ };
380
+ /**
381
+ * The list of supported guild navigation targets.
382
+ * @type {readonly DiscordGuildNavigationTarget[]}
383
+ */
384
+ const GUILD_NAVIGATION_TARGETS = Object.freeze(['customize', 'browse', 'guide', 'linked-roles']);
385
+ /**
386
+ * Parses a raw query string into a plain object of key/value pairs.
387
+ * @param {string | undefined} rawQuery - The raw query string, without the leading `?`.
388
+ * @returns {DiscordQueryParams} The parsed query parameters.
389
+ */
390
+ const parseQuery = (rawQuery) => {
391
+ if (!rawQuery)
392
+ return {};
393
+ return Object.fromEntries(new URLSearchParams(rawQuery).entries());
394
+ };
395
+ /**
396
+ * Serializes a parameter map into a canonical query string.
397
+ * @param {DiscordQueryParams} params - The parameters to serialize.
398
+ * @returns {string} The serialized query string, including the leading `?`, or an empty string.
399
+ */
400
+ const buildQuery = (params) => {
401
+ const query = new URLSearchParams(params).toString();
402
+ return query ? `?${query}` : '';
403
+ };
404
+ /**
405
+ * Validates a parsed Discord mention object.
406
+ * @param {DiscordMentionData} data - The mention data to validate.
407
+ * @returns {void}
408
+ * @throws {TypeError} If any property is missing or of an invalid type.
409
+ */
410
+ const validateMentionData = (data) => {
411
+ if (!['user', 'role', 'channel'].includes(data.target)) {
412
+ throw new TypeError(`DiscordMentionData: invalid target "${data.target}".`);
413
+ }
414
+ if (typeof data.id !== 'string' || !/^\d+$/.test(data.id)) {
415
+ throw new TypeError('DiscordMentionData: id must be a numeric string.');
416
+ }
417
+ if (typeof data.isNickname !== 'boolean') {
418
+ throw new TypeError('DiscordMentionData: isNickname must be a boolean.');
419
+ }
420
+ };
421
+ /**
422
+ * Validates a parsed Discord game profile object.
423
+ * @param {DiscordGameProfileData} data - The game profile data to validate.
424
+ * @returns {void}
425
+ * @throws {TypeError} If any property is missing or of an invalid type.
426
+ */
427
+ const validateGameProfileData = (data) => {
428
+ if (typeof data.id !== 'string' || !/^\d+$/.test(data.id)) {
429
+ throw new TypeError('DiscordGameProfileData: id must be a numeric string.');
430
+ }
431
+ };
432
+ /**
433
+ * Validates a parsed Discord guild navigation object.
434
+ * @param {DiscordGuildNavigationData} data - The guild navigation data to validate.
435
+ * @returns {void}
436
+ * @throws {TypeError} If any property is missing or of an invalid type.
437
+ */
438
+ const validateGuildNavigationData = (data) => {
439
+ if (!GUILD_NAVIGATION_TARGETS.includes(data.target)) {
440
+ throw new TypeError(`DiscordGuildNavigationData: invalid target "${data.target}".`);
441
+ }
442
+ if (data.roleId !== null && (typeof data.roleId !== 'string' || !/^\d+$/.test(data.roleId))) {
443
+ throw new TypeError('DiscordGuildNavigationData: roleId must be a numeric string or null.');
444
+ }
445
+ if (data.target !== 'linked-roles' && data.roleId !== null) {
446
+ throw new TypeError('DiscordGuildNavigationData: roleId is only valid for "linked-roles".');
447
+ }
448
+ };
449
+ /**
450
+ * Validates a parsed Discord emoji object.
451
+ * @param {DiscordEmojiData} data - The emoji data to validate.
452
+ * @returns {void}
453
+ * @throws {TypeError} If any property is missing or of an invalid type.
454
+ */
455
+ const validateEmojiData = (data) => {
456
+ if (typeof data.name !== 'string' || data.name.length === 0) {
457
+ throw new TypeError('DiscordEmojiData: name must be a non-empty string.');
458
+ }
459
+ if (typeof data.id !== 'string' || !/^\d+$/.test(data.id)) {
460
+ throw new TypeError('DiscordEmojiData: id must be a numeric string.');
461
+ }
462
+ if (typeof data.animated !== 'boolean') {
463
+ throw new TypeError('DiscordEmojiData: animated must be a boolean.');
464
+ }
465
+ };
466
+ /**
467
+ * Validates a parsed Discord timestamp object.
468
+ * @param {DiscordTimestampData} data - The timestamp data to validate.
469
+ * @returns {void}
470
+ * @throws {TypeError} If any property is missing or of an invalid type.
471
+ */
472
+ const validateTimestampData = (data) => {
473
+ if (!Number.isInteger(data.timestamp) || data.timestamp < 0) {
474
+ throw new TypeError('DiscordTimestampData: timestamp must be a non-negative integer.');
475
+ }
476
+ if (typeof data.style !== 'string' || !/^[tTdDfFRsS]?$/.test(data.style)) {
477
+ throw new TypeError('DiscordTimestampData: style must be a valid style flag or an empty string.');
478
+ }
479
+ };
480
+ /**
481
+ * Splits a raw command path into its structural parts.
482
+ * @param {string} name - The raw command path (e.g., `play music`).
483
+ * @returns {DiscordCommandPath} The split command path.
484
+ * @throws {TypeError} If the name is not a valid command path.
485
+ */
486
+ const splitCommandPath = (name) => {
487
+ if (typeof name !== 'string' || !/^[\w-]+(?: [\w-]+){0,2}$/.test(name)) {
488
+ throw new TypeError('DiscordCommandData: name must contain one to three space-separated segments.');
489
+ }
490
+ const [command, second, third] = name.split(' ');
491
+ return {
492
+ command,
493
+ subcommandGroup: third === undefined ? null : second,
494
+ subcommand: second === undefined ? null : (third ?? second),
495
+ };
496
+ };
497
+ /**
498
+ * Validates a parsed Discord command object.
499
+ * @param {DiscordCommandData} data - The command data to validate.
500
+ * @returns {void}
501
+ * @throws {TypeError} If any property is missing or of an invalid type.
502
+ */
503
+ const validateCommandData = (data) => {
504
+ const expected = splitCommandPath(data.name);
505
+ if (data.command !== expected.command) {
506
+ throw new TypeError(`DiscordCommandData: command must be "${expected.command}".`);
507
+ }
508
+ if (data.subcommandGroup !== expected.subcommandGroup) {
509
+ throw new TypeError(`DiscordCommandData: subcommandGroup must be ${JSON.stringify(expected.subcommandGroup)}.`);
510
+ }
511
+ if (data.subcommand !== expected.subcommand) {
512
+ throw new TypeError(`DiscordCommandData: subcommand must be ${JSON.stringify(expected.subcommand)}.`);
513
+ }
514
+ if (typeof data.id !== 'string' || !/^\d+$/.test(data.id)) {
515
+ throw new TypeError('DiscordCommandData: id must be a numeric string.');
516
+ }
517
+ };
518
+ /**
519
+ * Validates a parsed Discord invite object.
520
+ * @param {DiscordInviteData} data - The invite data to validate.
521
+ * @returns {void}
522
+ * @throws {TypeError} If any property is missing or of an invalid type.
523
+ */
524
+ const validateInviteData = (data) => {
525
+ if (typeof data.code !== 'string' || data.code.length === 0) {
526
+ throw new TypeError('DiscordInviteData: code must be a non-empty string.');
527
+ }
528
+ if (!['discord.gg', 'discord.com', 'discordapp.com'].includes(data.host)) {
529
+ throw new TypeError(`DiscordInviteData: invalid host "${data.host}".`);
530
+ }
531
+ if (data.kind !== null && data.kind !== 'invite' && data.kind !== 'servers') {
532
+ throw new TypeError(`DiscordInviteData: invalid kind "${data.kind}".`);
533
+ }
534
+ if (data.host === 'discord.gg' && data.kind !== null) {
535
+ throw new TypeError('DiscordInviteData: discord.gg must not include a path kind.');
536
+ }
537
+ if (data.host !== 'discord.gg' && data.kind === null) {
538
+ throw new TypeError('DiscordInviteData: this host requires a path kind.');
539
+ }
540
+ if (typeof data.obfuscated !== 'boolean') {
541
+ throw new TypeError('DiscordInviteData: obfuscated must be a boolean.');
542
+ }
543
+ if (data.params === null || typeof data.params !== 'object' || Array.isArray(data.params)) {
544
+ throw new TypeError('DiscordInviteData: params must be a plain object.');
545
+ }
546
+ };
547
+ /**
548
+ * Validates a parsed Discord message link object.
549
+ * @param {DiscordMessageLinkData} data - The message link data to validate.
550
+ * @returns {void}
551
+ * @throws {TypeError} If any property is missing or of an invalid type.
552
+ */
553
+ const validateMessageLinkData = (data) => {
554
+ if (typeof data.guildId !== 'string' || data.guildId.length === 0) {
555
+ throw new TypeError('DiscordMessageLinkData: guildId must be a non-empty string.');
556
+ }
557
+ if (typeof data.channelId !== 'string' || !/^\d+$/.test(data.channelId)) {
558
+ throw new TypeError('DiscordMessageLinkData: channelId must be a numeric string.');
559
+ }
560
+ if (typeof data.messageId !== 'string' || !/^\d+$/.test(data.messageId)) {
561
+ throw new TypeError('DiscordMessageLinkData: messageId must be a numeric string.');
562
+ }
563
+ if (data.params === null || typeof data.params !== 'object' || Array.isArray(data.params)) {
564
+ throw new TypeError('DiscordMessageLinkData: params must be a plain object.');
565
+ }
566
+ };
567
+ /**
568
+ * Parses a Discord mention element.
569
+ * @param {string} uri - The raw mention string (e.g., `<@123>`, `<@&123>`, `<#123>`).
570
+ * @returns {DiscordMentionData} The parsed mention data.
571
+ * @throws {TypeError} If the input is not a string or fails validation.
572
+ * @throws {SyntaxError} If the input does not match the mention grammar.
573
+ */
574
+ const parseMention = (uri) => {
575
+ if (typeof uri !== 'string') {
576
+ throw new TypeError('DiscordMentionData: uri must be a string.');
577
+ }
578
+ const match = mentionRegex.exec(uri);
579
+ if (!match || !match.groups) {
580
+ throw new SyntaxError(`Invalid Discord mention: ${uri}`);
581
+ }
582
+ const { prefix, id } = match.groups;
583
+ /** @type {DiscordMentionTarget} */
584
+ let target = 'user';
585
+ let isNickname = false;
586
+ if (prefix === '#') {
587
+ target = 'channel';
588
+ }
589
+ else if (prefix === '@&') {
590
+ target = 'role';
591
+ }
592
+ else {
593
+ target = 'user';
594
+ isNickname = prefix === '@!';
595
+ }
596
+ /** @type {DiscordMentionData} */
597
+ const data = { dataType: 'mention', target, id, isNickname };
598
+ validateMentionData(data);
599
+ return data;
600
+ };
601
+ /**
602
+ * Parses a Discord game profile element.
603
+ * @param {string} uri - The raw game profile string (e.g., `<@$1402418491272986635>`).
604
+ * @returns {DiscordGameProfileData} The parsed game profile data.
605
+ * @throws {TypeError} If the input is not a string or fails validation.
606
+ * @throws {SyntaxError} If the input does not match the game profile grammar.
607
+ */
608
+ const parseGameProfile = (uri) => {
609
+ if (typeof uri !== 'string') {
610
+ throw new TypeError('DiscordGameProfileData: uri must be a string.');
611
+ }
612
+ const match = gameProfileRegex.exec(uri);
613
+ if (!match || !match.groups) {
614
+ throw new SyntaxError(`Invalid Discord game profile: ${uri}`);
615
+ }
616
+ /** @type {DiscordGameProfileData} */
617
+ const data = { dataType: 'game_profile', id: match.groups.id };
618
+ validateGameProfileData(data);
619
+ return data;
620
+ };
621
+ /**
622
+ * Parses a Discord guild navigation element.
623
+ * @param {string} uri - The raw guild navigation string (e.g., `<id:linked-roles:123>`).
624
+ * @returns {DiscordGuildNavigationData} The parsed guild navigation data.
625
+ * @throws {TypeError} If the input is not a string or fails validation.
626
+ * @throws {SyntaxError} If the input does not match the guild navigation grammar.
627
+ */
628
+ const parseGuildNavigation = (uri) => {
629
+ if (typeof uri !== 'string') {
630
+ throw new TypeError('DiscordGuildNavigationData: uri must be a string.');
631
+ }
632
+ const match = guildNavigationRegex.exec(uri);
633
+ if (!match || !match.groups) {
634
+ throw new SyntaxError(`Invalid Discord guild navigation: ${uri}`);
635
+ }
636
+ /** @type {DiscordGuildNavigationData} */
637
+ const data = {
638
+ dataType: 'guild_navigation',
639
+ target: /** @type {DiscordGuildNavigationTarget} */ (match.groups.target),
640
+ roleId: match.groups.roleId ?? null,
641
+ };
642
+ validateGuildNavigationData(data);
643
+ return data;
644
+ };
645
+ /**
646
+ * Parses a Discord custom emoji element.
647
+ * @param {string} uri - The raw emoji string (e.g., `<:name:123>`).
648
+ * @returns {DiscordEmojiData} The parsed emoji data.
649
+ * @throws {TypeError} If the input is not a string or fails validation.
650
+ * @throws {SyntaxError} If the input does not match the emoji grammar.
651
+ */
652
+ const parseEmoji = (uri) => {
653
+ if (typeof uri !== 'string') {
654
+ throw new TypeError('DiscordEmojiData: uri must be a string.');
655
+ }
656
+ const match = emojiRegex.exec(uri);
657
+ if (!match || !match.groups) {
658
+ throw new SyntaxError(`Invalid Discord emoji: ${uri}`);
659
+ }
660
+ /** @type {DiscordEmojiData} */
661
+ const data = {
662
+ dataType: 'emoji',
663
+ name: match.groups.name,
664
+ id: match.groups.id,
665
+ animated: Boolean(match.groups.animated),
666
+ };
667
+ validateEmojiData(data);
668
+ return data;
669
+ };
670
+ /**
671
+ * Parses a Discord timestamp element.
672
+ * @param {string} uri - The raw timestamp string (e.g., `<t:1618953630:R>`).
673
+ * @returns {DiscordTimestampData} The parsed timestamp data.
674
+ * @throws {TypeError} If the input is not a string or fails validation.
675
+ * @throws {SyntaxError} If the input does not match the timestamp grammar.
676
+ */
677
+ const parseTimestamp = (uri) => {
678
+ if (typeof uri !== 'string') {
679
+ throw new TypeError('DiscordTimestampData: uri must be a string.');
680
+ }
681
+ const match = timestampRegex.exec(uri);
682
+ if (!match || !match.groups) {
683
+ throw new SyntaxError(`Invalid Discord timestamp: ${uri}`);
684
+ }
685
+ /** @type {DiscordTimestampData} */
686
+ const data = {
687
+ dataType: 'timestamp',
688
+ timestamp: Number(match.groups.timestamp),
689
+ style: match.groups.style ?? '',
690
+ };
691
+ validateTimestampData(data);
692
+ return data;
693
+ };
694
+ /**
695
+ * Builds and validates a `DiscordCommandData` object from a raw command path.
696
+ * @param {string} name - The full command path (e.g., `play music`).
697
+ * @param {string} id - The snowflake identifier of the command.
698
+ * @returns {DiscordCommandData} The validated command data.
699
+ * @throws {TypeError} If the resulting object is invalid.
700
+ */
701
+ const buildCommandData = (name, id) => {
702
+ /** @type {DiscordCommandData} */
703
+ const data = { dataType: 'command', name, ...splitCommandPath(name), id };
704
+ validateCommandData(data);
705
+ return data;
706
+ };
707
+ /**
708
+ * Parses a Discord slash command element.
709
+ * @param {string} uri - The raw command string (e.g., `</play music:123>`).
710
+ * @returns {DiscordCommandData} The parsed command data.
711
+ * @throws {TypeError} If the input is not a string or fails validation.
712
+ * @throws {SyntaxError} If the input does not match the command grammar.
713
+ */
714
+ const parseCommand = (uri) => {
715
+ if (typeof uri !== 'string') {
716
+ throw new TypeError('DiscordCommandData: uri must be a string.');
717
+ }
718
+ const match = commandRegex.exec(uri);
719
+ if (!match || !match.groups) {
720
+ throw new SyntaxError(`Invalid Discord command: ${uri}`);
721
+ }
722
+ return buildCommandData(match.groups.name, match.groups.id);
723
+ };
724
+ /**
725
+ * Normalizes a raw host by removing whitespace and lowercasing it.
726
+ * @param {string} rawHost - The raw host captured by a regular expression.
727
+ * @returns {string} The normalized host.
728
+ */
729
+ const normalizeHost = (rawHost) => {
730
+ const compact = rawHost.replace(/\s+/g, '').toLowerCase();
731
+ return compact === 'discord.co' ? 'discord.com' : compact;
732
+ };
733
+ /**
734
+ * Builds the canonical invite URL for a normalized host, kind, code and query.
735
+ * @param {string} host - The normalized host.
736
+ * @param {string | null} kind - The path kind, or `null` for short links.
737
+ * @param {string} code - The invite code or server slug.
738
+ * @param {DiscordQueryParams} params - The query string parameters.
739
+ * @returns {string} The canonical invite URL.
740
+ */
741
+ const buildInviteUrl = (host, kind, code, params) => {
742
+ const base = kind ? `https://${host}/${kind}/${code}` : `https://${host}/${code}`;
743
+ return `${base}${buildQuery(params)}`;
744
+ };
745
+ /**
746
+ * Builds the canonical message URL for a guild, channel, message and query.
747
+ * @param {string} guildId - The guild snowflake, or '@me' for direct messages.
748
+ * @param {string} channelId - The channel snowflake.
749
+ * @param {string} messageId - The message snowflake.
750
+ * @param {DiscordQueryParams} params - The query string parameters.
751
+ * @returns {string} The canonical message URL.
752
+ */
753
+ const buildMessageLinkUrl = (guildId, channelId, messageId, params) => {
754
+ const base = `https://discord.com/channels/${guildId}/${channelId}/${messageId}`;
755
+ return `${base}${buildQuery(params)}`;
756
+ };
757
+ /**
758
+ * Builds and validates a `DiscordInviteData` object.
759
+ * @param {string} rawHost - The raw host captured by a regular expression.
760
+ * @param {string | null} rawKind - The raw path kind, or `null`.
761
+ * @param {string} code - The invite code or server slug.
762
+ * @param {string | undefined} rawQuery - The raw query string, without the leading `?`.
763
+ * @param {boolean} obfuscated - Whether the source used whitespace obfuscation.
764
+ * @returns {DiscordInviteData} The validated invite data.
765
+ * @throws {TypeError} If the resulting object is invalid.
766
+ */
767
+ const buildInviteData = (rawHost, rawKind, code, rawQuery, obfuscated) => {
768
+ const host = normalizeHost(rawHost);
769
+ const kind = rawKind ? rawKind.toLowerCase() : null;
770
+ const params = parseQuery(rawQuery);
771
+ /** @type {DiscordInviteData} */
772
+ const data = {
773
+ dataType: 'invite',
774
+ code,
775
+ host: /** @type {DiscordInviteData['host']} */ (host),
776
+ kind: /** @type {DiscordInviteData['kind']} */ (kind),
777
+ obfuscated,
778
+ params,
779
+ };
780
+ validateInviteData(data);
781
+ return data;
782
+ };
783
+ /**
784
+ * Parses a Discord invite link.
785
+ * @param {string} uri - The raw invite URL.
786
+ * @returns {DiscordInviteData} The parsed invite data.
787
+ * @throws {TypeError} If the input is not a string or fails validation.
788
+ * @throws {SyntaxError} If the input does not match the invite grammar.
789
+ */
790
+ const parseInvite = (uri) => {
791
+ if (typeof uri !== 'string') {
792
+ throw new TypeError('DiscordInviteData: uri must be a string.');
793
+ }
794
+ const cleanMatch = inviteRegex.exec(uri);
795
+ if (cleanMatch?.groups) {
796
+ const { shortHost, shortCode, fullHost, kind, code, query } = cleanMatch.groups;
797
+ return buildInviteData(shortHost ?? fullHost, kind ?? null, shortCode ?? code, query, false);
798
+ }
799
+ const obfuscatedMatch = obfuscatedInviteRegex.exec(uri);
800
+ if (obfuscatedMatch?.groups) {
801
+ const { host, kind, code, query } = obfuscatedMatch.groups;
802
+ return buildInviteData(host, kind ?? null, code, query, true);
803
+ }
804
+ throw new SyntaxError(`Invalid Discord invite: ${uri}`);
805
+ };
806
+ /**
807
+ * Parses a Discord message link.
808
+ * @param {string} uri - The raw message URL.
809
+ * @returns {DiscordMessageLinkData} The parsed message link data.
810
+ * @throws {TypeError} If the input is not a string or fails validation.
811
+ * @throws {SyntaxError} If the input does not match the message link grammar.
812
+ */
813
+ const parseMessageLink = (uri) => {
814
+ if (typeof uri !== 'string') {
815
+ throw new TypeError('DiscordMessageLinkData: uri must be a string.');
816
+ }
817
+ const match = messageLinkRegex.exec(uri);
818
+ if (!match || !match.groups) {
819
+ throw new SyntaxError(`Invalid Discord message link: ${uri}`);
820
+ }
821
+ const { guildId, channelId, messageId } = match.groups;
822
+ const params = parseQuery(match.groups.query);
823
+ /** @type {DiscordMessageLinkData} */
824
+ const data = {
825
+ dataType: 'message_link',
826
+ guildId,
827
+ channelId,
828
+ messageId,
829
+ params,
830
+ };
831
+ validateMessageLinkData(data);
832
+ return data;
833
+ };
834
+ /**
835
+ * Reconstructs a Discord mention string from parsed data.
836
+ * @param {DiscordMentionData} data - The mention data.
837
+ * @returns {string} The reconstructed mention string.
838
+ * @throws {TypeError} If the data is invalid.
839
+ */
840
+ const stringifyMention = (data) => {
841
+ validateMentionData(data);
842
+ if (data.target === 'channel')
843
+ return `<#${data.id}>`;
844
+ if (data.target === 'role')
845
+ return `<@&${data.id}>`;
846
+ return data.isNickname ? `<@!${data.id}>` : `<@${data.id}>`;
847
+ };
848
+ /**
849
+ * Reconstructs a Discord game profile string from parsed data.
850
+ * @param {DiscordGameProfileData} data - The game profile data.
851
+ * @returns {string} The reconstructed game profile string.
852
+ * @throws {TypeError} If the data is invalid.
853
+ */
854
+ const stringifyGameProfile = (data) => {
855
+ validateGameProfileData(data);
856
+ return `<@$${data.id}>`;
857
+ };
858
+ /**
859
+ * Reconstructs a Discord guild navigation string from parsed data.
860
+ * @param {DiscordGuildNavigationData} data - The guild navigation data.
861
+ * @returns {string} The reconstructed guild navigation string.
862
+ * @throws {TypeError} If the data is invalid.
863
+ */
864
+ const stringifyGuildNavigation = (data) => {
865
+ validateGuildNavigationData(data);
866
+ return data.roleId ? `<id:${data.target}:${data.roleId}>` : `<id:${data.target}>`;
867
+ };
868
+ /**
869
+ * Reconstructs a Discord custom emoji string from parsed data.
870
+ * @param {DiscordEmojiData} data - The emoji data.
871
+ * @returns {string} The reconstructed emoji string.
872
+ * @throws {TypeError} If the data is invalid.
873
+ */
874
+ const stringifyEmoji = (data) => {
875
+ validateEmojiData(data);
876
+ return `<${data.animated ? 'a' : ''}:${data.name}:${data.id}>`;
877
+ };
878
+ /**
879
+ * Reconstructs a Discord timestamp string from parsed data.
880
+ * @param {DiscordTimestampData} data - The timestamp data.
881
+ * @returns {string} The reconstructed timestamp string.
882
+ * @throws {TypeError} If the data is invalid.
883
+ */
884
+ const stringifyTimestamp = (data) => {
885
+ validateTimestampData(data);
886
+ return data.style ? `<t:${data.timestamp}:${data.style}>` : `<t:${data.timestamp}>`;
887
+ };
888
+ /**
889
+ * Reconstructs a Discord slash command string from parsed data.
890
+ * @param {DiscordCommandData} data - The command data.
891
+ * @returns {string} The reconstructed command string.
892
+ * @throws {TypeError} If the data is invalid.
893
+ */
894
+ const stringifyCommand = (data) => {
895
+ validateCommandData(data);
896
+ return `</${data.name}:${data.id}>`;
897
+ };
898
+ /**
899
+ * Reconstructs a Discord invite URL from parsed data.
900
+ * @param {DiscordInviteData} data - The invite data.
901
+ * @returns {string} The canonical invite URL.
902
+ * @throws {TypeError} If the data is invalid.
903
+ */
904
+ const stringifyInvite = (data) => {
905
+ validateInviteData(data);
906
+ return buildInviteUrl(data.host, data.kind, data.code, data.params);
907
+ };
908
+ /**
909
+ * Reconstructs a Discord message URL from parsed data.
910
+ * @param {DiscordMessageLinkData} data - The message link data.
911
+ * @returns {string} The reconstructed message URL.
912
+ * @throws {TypeError} If the data is invalid.
913
+ */
914
+ const stringifyMessageLink = (data) => {
915
+ validateMessageLinkData(data);
916
+ return buildMessageLinkUrl(data.guildId, data.channelId, data.messageId, data.params);
917
+ };
918
+ /**
919
+ * A parser pair for Discord mentions (`<@id>`, `<@!id>`, `<@&id>`, `<#id>`).
920
+ */
921
+ export const DiscordMentionParser = TinyUriParser.buildParserPair('mention', (uriString) => mentionRegex.test(uriString), parseMention, stringifyMention);
922
+ /**
923
+ * A parser pair for Discord game profiles (`<@$id>`).
924
+ */
925
+ export const DiscordGameProfileParser = TinyUriParser.buildParserPair('game_profile', (uriString) => gameProfileRegex.test(uriString), parseGameProfile, stringifyGameProfile);
926
+ /**
927
+ * A parser pair for Discord guild navigation (`<id:type>`, `<id:linked-roles:id>`).
928
+ */
929
+ export const DiscordGuildNavigationParser = TinyUriParser.buildParserPair('guild_navigation', (uriString) => guildNavigationRegex.test(uriString), parseGuildNavigation, stringifyGuildNavigation);
930
+ /**
931
+ * A parser pair for Discord custom emojis (`<:name:id>`, `<a:name:id>`).
932
+ */
933
+ export const DiscordEmojiParser = TinyUriParser.buildParserPair('emoji', (uriString) => emojiRegex.test(uriString), parseEmoji, stringifyEmoji);
934
+ /**
935
+ * A parser pair for Discord timestamps (`<t:unix>`, `<t:unix:style>`).
936
+ */
937
+ export const DiscordTimestampParser = TinyUriParser.buildParserPair('timestamp', (uriString) => timestampRegex.test(uriString), parseTimestamp, stringifyTimestamp);
938
+ /**
939
+ * A parser pair for Discord slash commands (`</name:id>`).
940
+ */
941
+ export const DiscordCommandParser = TinyUriParser.buildParserPair('command', (uriString) => commandRegex.test(uriString), parseCommand, stringifyCommand);
942
+ /**
943
+ * A parser pair for Discord invite links (`discord.gg/...`, `discord.com/invite/...`,
944
+ * `discord.com/servers/...`), including whitespace-obfuscated variants.
945
+ */
946
+ export const DiscordInviteParser = TinyUriParser.buildParserPair('invite', (uriString) => inviteRegex.test(uriString) || obfuscatedInviteRegex.test(uriString), parseInvite, stringifyInvite);
947
+ /**
948
+ * A parser pair for Discord message links (`https://discord.com/channels/...`).
949
+ */
950
+ export const DiscordMessageLinkParser = TinyUriParser.buildParserPair('message_link', (uriString) => messageLinkRegex.test(uriString), parseMessageLink, stringifyMessageLink);
951
+ /**
952
+ * A parser pair for Discord CDN assets (`https://cdn.discordapp.com/...`).
953
+ */
954
+ export const DiscordCdnParser = TinyUriParser.buildParserPair('cdn_asset', (uriString) => cdnRegex.test(uriString), parseCdnAsset, stringifyCdnAsset);
955
+ /**
956
+ * An array of Discord parser pairs, ordered from the most specific to the most permissive.
957
+ */
958
+ export const DiscordProtocolParsers = Object.freeze([
959
+ DiscordMessageLinkParser,
960
+ DiscordCdnParser,
961
+ DiscordInviteParser,
962
+ DiscordGameProfileParser,
963
+ DiscordGuildNavigationParser,
964
+ DiscordMentionParser,
965
+ DiscordEmojiParser,
966
+ DiscordTimestampParser,
967
+ DiscordCommandParser,
968
+ ]);