tiny-essentials 1.26.4 → 1.27.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/node.js.yml +1 -1
- package/README.md +0 -1
- package/changelog/1/27/0.md +24 -0
- package/dist/v1/ColorSafeStringify.min.js +1 -1
- package/dist/v1/TinyAdvancedRaffle.min.js +1 -1
- package/dist/v1/TinyAfterScrollWatcher.min.js +1 -1
- package/dist/v1/TinyAnalogClock.min.js +1 -1
- package/dist/v1/TinyArrayComparator.min.js +1 -1
- package/dist/v1/TinyArrayPaginator.min.js +1 -1
- package/dist/v1/TinyBasicsEs.min.js +1 -1
- package/dist/v1/TinyClassManager.min.js +1 -1
- package/dist/v1/TinyClipboard.min.js +1 -1
- package/dist/v1/TinyColorConverter.min.js +1 -1
- package/dist/v1/TinyColorValidator.min.js +1 -1
- package/dist/v1/TinyCookieConsent.min.js +1 -1
- package/dist/v1/TinyDayNightCycle.min.js +1 -1
- package/dist/v1/TinyDomReadyManager.min.js +1 -1
- package/dist/v1/TinyDragDropDetector.min.js +1 -1
- package/dist/v1/TinyDragger.min.js +1 -1
- package/dist/v1/TinyElementObserver.min.js +1 -1
- package/dist/v1/TinyEssentials.min.js +1 -1
- package/dist/v1/TinyEvents.min.js +1 -1
- package/dist/v1/TinyGamepad.min.js +1 -1
- package/dist/v1/TinyHtml.min.js +1 -1
- package/dist/v1/TinyI18.min.js +1 -1
- package/dist/v1/TinyIframeEvents.min.js +1 -1
- package/dist/v1/TinyInventory.min.js +1 -1
- package/dist/v1/TinyInventoryTrader.min.js +1 -1
- package/dist/v1/TinyLevelUp.min.js +1 -1
- package/dist/v1/TinyLoadingScreen.min.js +1 -1
- package/dist/v1/TinyLocalStorage.min.js +1 -1
- package/dist/v1/TinyMaInSys.min.js +1 -1
- package/dist/v1/TinyMediaPlayer.min.js +1 -0
- package/dist/v1/TinyNeedBar.min.js +1 -1
- package/dist/v1/TinyNewWinEvents.min.js +1 -1
- package/dist/v1/TinyNotifications.min.js +1 -1
- package/dist/v1/TinyNotifyCenter.min.js +1 -1
- package/dist/v1/TinyPromiseQueue.min.js +1 -1
- package/dist/v1/TinyRadioFm.min.js +1 -0
- package/dist/v1/TinyRateLimiter.min.js +1 -1
- package/dist/v1/TinySimpleDice.min.js +1 -1
- package/dist/v1/TinySmartScroller.min.js +1 -1
- package/dist/v1/TinyTextDiffer.min.js +1 -1
- package/dist/v1/TinyTextRangeEditor.min.js +1 -1
- package/dist/v1/TinyTextarea.min.js +1 -1
- package/dist/v1/TinyTimeout.min.js +1 -1
- package/dist/v1/TinyToastNotify.min.js +1 -1
- package/dist/v1/TinyUploadClicker.min.js +1 -1
- package/dist/v1/UltraRandomMsgGen.min.js +1 -1
- package/dist/v1/basics/index.cjs +5 -0
- package/dist/v1/basics/index.d.mts +5 -1
- package/dist/v1/basics/index.mjs +2 -1
- package/dist/v1/basics/mediaContent.cjs +644 -0
- package/dist/v1/basics/mediaContent.d.mts +296 -0
- package/dist/v1/basics/mediaContent.mjs +557 -0
- package/dist/v1/build/TinyMediaPlayer.cjs +7 -0
- package/dist/v1/build/TinyMediaPlayer.d.mts +3 -0
- package/dist/v1/build/TinyMediaPlayer.mjs +2 -0
- package/dist/v1/build/TinyRadioFm.cjs +7 -0
- package/dist/v1/build/TinyRadioFm.d.mts +3 -0
- package/dist/v1/build/TinyRadioFm.mjs +2 -0
- package/dist/v1/index.cjs +9 -0
- package/dist/v1/index.d.mts +7 -1
- package/dist/v1/index.mjs +5 -2
- package/dist/v1/libs/ColorSafeStringify.d.mts +1 -1
- package/dist/v1/libs/TinyAfterScrollWatcher.cjs +16 -3
- package/dist/v1/libs/TinyAfterScrollWatcher.d.mts +7 -3
- package/dist/v1/libs/TinyAfterScrollWatcher.mjs +13 -3
- package/dist/v1/libs/TinyArrayComparator.cjs +14 -11
- package/dist/v1/libs/TinyArrayComparator.d.mts +22 -19
- package/dist/v1/libs/TinyArrayComparator.mjs +14 -11
- package/dist/v1/libs/TinyArrayPaginator.cjs +23 -16
- package/dist/v1/libs/TinyArrayPaginator.d.mts +57 -30
- package/dist/v1/libs/TinyArrayPaginator.mjs +22 -16
- package/dist/v1/libs/TinyClassManager/TinyPluginInliner.cjs +265 -0
- package/dist/v1/libs/TinyClassManager/TinyPluginInliner.d.mts +92 -0
- package/dist/v1/libs/TinyClassManager/TinyPluginInliner.mjs +223 -0
- package/dist/v1/libs/TinyClassManager.cjs +52 -22
- package/dist/v1/libs/TinyClassManager.d.mts +26 -16
- package/dist/v1/libs/TinyClassManager.mjs +50 -21
- package/dist/v1/libs/TinyColorValidator.d.mts +16 -16
- package/dist/v1/libs/TinyDragDropDetector.cjs +9 -34
- package/dist/v1/libs/TinyDragDropDetector.d.mts +7 -21
- package/dist/v1/libs/TinyDragDropDetector.mjs +9 -24
- package/dist/v1/libs/TinyDragger.cjs +5 -5
- package/dist/v1/libs/TinyDragger.d.mts +4 -3
- package/dist/v1/libs/TinyDragger.mjs +5 -5
- package/dist/v1/libs/TinyElementObserver.cjs +6 -21
- package/dist/v1/libs/TinyElementObserver.d.mts +6 -15
- package/dist/v1/libs/TinyElementObserver.mjs +6 -20
- package/dist/v1/libs/TinyGamepad.cjs +4 -6
- package/dist/v1/libs/TinyGamepad.d.mts +1 -1
- package/dist/v1/libs/TinyHtml/TinyHtmlIcon.d.mts +1 -1
- package/dist/v1/libs/TinyHtml/TinyHtmlTemplate.d.mts +1 -1
- package/dist/v1/libs/TinyHtml/TinyHtmlTextarea.d.mts +1 -1
- package/dist/v1/libs/TinyHtml/index.d.mts +1 -1
- package/dist/v1/libs/TinyHtml.cjs +72 -98
- package/dist/v1/libs/TinyHtml.d.mts +15 -32
- package/dist/v1/libs/TinyHtml.mjs +53 -77
- package/dist/v1/libs/TinyInventory.d.mts +1 -1
- package/dist/v1/libs/TinyMediaPlayer.cjs +844 -0
- package/dist/v1/libs/TinyMediaPlayer.d.mts +306 -0
- package/dist/v1/libs/TinyMediaPlayer.mjs +755 -0
- package/dist/v1/libs/TinyRadioFm.cjs +1378 -0
- package/dist/v1/libs/TinyRadioFm.d.mts +554 -0
- package/dist/v1/libs/TinyRadioFm.mjs +1137 -0
- package/dist/v1/libs/TinySmartScroller.cjs +39 -26
- package/dist/v1/libs/TinySmartScroller.d.mts +16 -62
- package/dist/v1/libs/TinySmartScroller.mjs +35 -26
- package/dist/v1/libs/UltraRandomMsgGen.d.mts +7 -7
- package/docs/v1/README.md +6 -0
- package/docs/v1/basics/mediaContent.md +131 -0
- package/docs/v1/libs/TinyClassManager/TinyPluginInliner.md +107 -0
- package/docs/v1/libs/TinyDragDropDetector.md +5 -9
- package/docs/v1/libs/TinyElementObserver.md +3 -6
- package/docs/v1/libs/TinyHtml.md +0 -29
- package/docs/v1/libs/TinyMediaPlayer.md +100 -0
- package/docs/v1/libs/TinyRadioFm.md +141 -0
- package/docs/v1/libs/TinySmartScroller.md +3 -3
- package/package.json +40 -22
|
@@ -0,0 +1 @@
|
|
|
1
|
+
(()=>{"use strict";const t={d:(e,i)=>{if(Array.isArray(i))for(var n=0;n<i.length;){var r=i[n++],s=i[n++];t.o(e,r)?0===s&&n++:0===s?Object.defineProperty(e,r,{enumerable:!0,value:i[n++]}):Object.defineProperty(e,r,{enumerable:!0,get:s})}else for(var r in i)t.o(i,r)&&!t.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:i[r]})},o:(t,e)=>Object.prototype.hasOwnProperty.call(t,e)};let e={};t.d(e,{TinyRadioFm:()=>d});const i=new Map;class n extends Error{constructor(t,e,i){super(t),this.name="MediaLoadingError",this.url=e,this.stage=i}}const r=async t=>{const e=(new TextEncoder).encode(t),i=await crypto.subtle.digest("SHA-1",e);return Array.from(new Uint8Array(i)).map(t=>t.toString(16).padStart(2,"0")).join("").substring(0,8)},s=(t,e="image/jpeg")=>{const n=t=>{const e=URL.createObjectURL(t),n=i.get(e);return i.set(e,"number"==typeof n?n+1:1),e};if(t instanceof Uint8Array)return n(new Blob([t],{type:e}));if("string"==typeof t&&t.startsWith("data:")){const i=t.split(",")[1],r=atob(i),s=new Uint8Array(r.length);for(let t=0;t<r.length;t++)s[t]=r.charCodeAt(t);return n(new Blob([s],{type:e}))}return"string"==typeof t?t:""},o=async t=>{if("string"!=typeof t||!t.startsWith("blob:"))return t;try{const e=await fetch(t),i=await e.blob();return await new Promise((t,e)=>{const n=new FileReader;n.onloadend=()=>t(String(n.result)),n.onerror=e,n.readAsDataURL(i)})}catch(e){return console.warn(`[TinyAudioUtils] Failed to convert Blob URL to Base64 on export: ${t}`,e),t}},a=t=>{t&&Array.isArray(t.picture)&&t.picture.forEach(t=>{if("string"==typeof t.data&&t.data.startsWith("blob:")){const e=i.get(t.data)??0;e>1?i.set(t.data,e-1):i.delete(t.data),e<=1&&URL.revokeObjectURL(t.data)}})},c=async(t,e)=>{if("string"!=typeof t)throw new TypeError(`Expected url to be a string, but received ${typeof t}.`);if("function"!=typeof e)throw new TypeError(`Expected parseFile to be a function, but received ${typeof e}.`);try{const i=await fetch(t);if(!i.ok)throw new Error(`Failed to fetch audio file: ${i.status} ${i.statusText}`);const n=await i.blob(),r=await e(n);if(!r||"object"!=typeof r.common)throw new TypeError('Invalid metadata: "common" property is missing or not an object.');const o=r.common;return(t=>{((t,e)=>{const i=t=>e&&void 0===t,n=t=>i(t)||"string"==typeof t||null===t,r=(t,e)=>!!i(t)||!(!Array.isArray(t)||!t.every(e));if(!n(t.title))throw new TypeError('Invalid metadata: "title" must be a string or null.');if(!n(t.album))throw new TypeError('Invalid metadata: "album" must be a string or null.');if(!n(t.albumartist))throw new TypeError('Invalid metadata: "albumartist" must be a string or null.');if(!n(t.artist))throw new TypeError('Invalid metadata: "artist" must be a string or null.');if(s=t.year,!i(s)&&"number"!=typeof s&&null!==s)throw new TypeError('Invalid metadata: "year" must be a number or null.');var s;if(!r(t.albumartists,t=>"string"==typeof t))throw new TypeError('Invalid metadata: "albumartists" must be an array of string.');if(!r(t.genre,t=>"string"==typeof t))throw new TypeError('Invalid metadata: "genre" must be an array of string.');if(!r(t.label,t=>"string"==typeof t))throw new TypeError('Invalid metadata: "label" must be an array of string.');if(!r(t.composer,t=>"string"==typeof t))throw new TypeError('Invalid metadata: "composer" must be an array of string.');if(!r(t.artists,t=>"string"==typeof t))throw new TypeError('Invalid metadata: "artists" must be an array of string.');if(!r(t.picture,t=>!(void 0!==t.description&&"string"!=typeof t.description||void 0!==t.name&&"string"!=typeof t.name||void 0!==t.type&&"string"!=typeof t.type||"string"!=typeof t.format||!(t.data instanceof Uint8Array||"string"==typeof t.data))))throw new TypeError('Invalid metadata: "picture" must be an array of pictures.');const o=(t,e)=>{if(!i(t)){if(null==t)throw new TypeError(`Invalid metadata: "${e}" is required.`);if("object"!=typeof t)throw new TypeError(`Invalid metadata: "${e}" must be an object or null.`);if("number"!=typeof t.no&&null!==t.no)throw new TypeError(`Invalid metadata: "${e}.no" must be a number or null.`);if("number"!=typeof t.of&&null!==t.of)throw new TypeError(`Invalid metadata: "${e}.of" must be a number or null.`)}};o(t.disk,"disk"),o(t.track,"track")})(t,!0)})(o),{title:o?.title??null,album:o?.album??null,albumartist:o?.albumartist??null,albumartists:o?.albumartists??[],genre:o?.genre??[],label:o?.label??[],composer:o?.composer??[],year:o?.year??null,artist:o?.artist??null,artists:o?.artists??[],disk:o?.disk?{no:o.disk.no,of:o.disk.of}:{no:null,of:null},track:o?.track?{no:o.track.no,of:o.track.of}:{no:null,of:null},picture:o?.picture?.map(t=>({...t,data:s(t.data,t.format)}))??[]}}catch(t){throw t}},l=class{#t=new Map;#e=10;#i=!1;#n(t,e){if("string"==typeof t)return[t];if(Array.isArray(t)&&t.every(t=>"string"==typeof t))return t;throw new TypeError(`${e}(event): event must be a string or string[]`)}setThrowOnMaxListeners(t){if("boolean"!=typeof t)throw new TypeError("setThrowOnMaxListeners(value): value must be a boolean");this.#i=t}getThrowOnMaxListeners(){return this.#i}#r(t,e,{once:i=!1}={}){let n=this.#t.get(t);Array.isArray(n)||(n=[],this.#t.set(t,n)),n.unshift({handler:e,config:{once:i}});const r=this.#e;if(r>0&&n.length>r){const e=`Possible memory leak detected. ${n.length} "${t}" listeners added. Use setMaxListeners() to increase limit.`;if(this.#i)throw new Error(e);console.warn(e)}}prependListener(t,e){const i=this.#n(t,"prependListener");if("function"!=typeof e)throw new TypeError("prependListener(event, handler): handler must be a function");for(const t of i)this.#r(t,e)}prependListenerOnce(t,e){const i=this.#n(t,"prependListenerOnce");if("function"!=typeof e)throw new TypeError("prependListenerOnce(event, handler): handler must be a function");const n=[];for(const t of i){const i=(...n)=>{this.off(t,i),e(...n)};this.#r(t,i,{once:!0}),n.push(i)}return n}#s(t,e,{once:i=!1}={}){const n=this.#n(t,"on");for(const t of n){let n=this.#t.get(t);Array.isArray(n)||(n=[],this.#t.set(t,n)),n.push({handler:e,config:{once:i}});const r=this.#e;if(r>0&&n.length>r){const e=`Possible memory leak detected. ${n.length} "${t}" listeners added. Use setMaxListeners() to increase limit.`;if(this.#i)throw new Error(e);console.warn(e)}}}on(t,e){if("function"!=typeof e)throw new TypeError("on(event, handler): handler must be a function");return this.#s(t,e)}once(t,e){const i=this.#n(t,"once");if("function"!=typeof e)throw new TypeError("once(event, handler): handler must be a function");const n=[];for(const t of i){const i=(...n)=>{this.off(t,i),e(...n)};this.#s(t,i,{once:!0}),n.push(i)}return n}appendListener(t,e){return this.on(t,e)}appendListenerOnce(t,e){return this.once(t,e)}off(t,e){const i=this.#n(t,"off");if("function"!=typeof e)throw new TypeError("off(event, handler): handler must be a function");for(const t of i){const i=this.#t.get(t);if(!Array.isArray(i))continue;const n=i.findIndex(t=>t.handler===e);-1!==n&&i.splice(n,1),0===i.length&&this.#t.delete(t)}}offAll(t){const e=this.#n(t,"offAll");for(const t of e)this.#t.delete(t)}offAllTypes(){this.#t.clear()}removeAllListeners(){return this.offAllTypes()}listenerCount(t){if("string"!=typeof t)throw new TypeError("listenerCount(event): event name must be a string");const e=this.#t.get(t);return Array.isArray(e)?e.length:0}listeners(t){if("string"!=typeof t)throw new TypeError("listeners(event): event name must be a string");const e=this.#t.get(t);return Array.isArray(e)?[...e].filter(t=>!t.config.once).map(t=>t.handler):[]}onceListeners(t){if("string"!=typeof t)throw new TypeError("onceListeners(event): event name must be a string");const e=this.#t.get(t);return Array.isArray(e)?[...e].filter(t=>t.config.once).map(t=>t.handler):[]}allListeners(t){if("string"!=typeof t)throw new TypeError("allListeners(event): event name must be a string");const e=this.#t.get(t);return Array.isArray(e)?[...e].map(t=>t.handler):[]}eventNames(){return[...this.#t.keys()]}emit(t,...e){const i=this.#n(t,"emit"),n=[];for(const t of i){const i=this.#t.get(t);Array.isArray(i)&&0!==i.length?(i.forEach(t=>t.handler(...e)),n.push(!0)):n.push(!1)}return n}setMaxListeners(t){if(!Number.isInteger(t)||t<0)throw new TypeError("setMaxListeners(n): n must be a non-negative integer");this.#e=t}getMaxListeners(){return this.#e}};class u extends l{static async parseContent(t,e,i,s,o){return(async(t,e={},i={},s=t=>new Promise((t,e)=>e(new TypeError("parseFile library not found."))),o={},a="null")=>{if("string"!=typeof t&&!(t instanceof HTMLMediaElement))throw new TypeError("Source must be a string or an HTMLMediaElement.");if(o.onProgress&&"function"!=typeof o.onProgress)throw new TypeError("callbacks.onProgress must be a function.");if(o.onError&&"function"!=typeof o.onError)throw new TypeError("callbacks.onError must be a function.");let l,u="";const d=(e,i)=>{o.onProgress&&o.onProgress({event:i,status:"loading",stage:e,url:u||(t instanceof HTMLMediaElement?t.src:"unknown")})},h=(e,i)=>{o.onError&&o.onError({error:e,url:u||(t instanceof HTMLMediaElement?t.src:"unknown"),stage:i})};try{d("INITIALIZING"),"string"==typeof t?(u=t,l=new Audio(u)):(l=t,u=l.src);try{await new Promise((t,e)=>{const i=t=>d("DOWNLOADING",t),n=()=>{s(),t(void 0)},r=t=>{s(),e(new Error(`HTMLMediaElement failed to load: ${t.message||"Unknown error"}`))},s=()=>{l.removeEventListener("progress",i),l.removeEventListener("loadedmetadata",n),l.removeEventListener("error",r)};l.addEventListener("progress",i),l.addEventListener("loadedmetadata",n),l.addEventListener("error",r),l.readyState>=1&&(s(),t(void 0))}),d("METADATA_LOADED")}catch(t){throw new n(t instanceof Error?t.message:"UNKNOWN ERROR",u,"METADATA")}const m={id:i.id||await r(u),duration:Math.floor(1e3*l.duration),url:u,weight:i.weight??1};let f={};d("EXTRACTING_ID3");try{f=await c(u,s)}catch(t){h(t instanceof Error?t:new Error("Unknown Error"),"ID3"),console.warn(`[TinyAudioUtils] ID3 extraction failed for ${u}. Falling back to filename.`)}const p=t=>{try{return(t.split(/[?#]/)[0].split("/").pop()??"").replace(/\.[^/.]+$/,"")||"Unknown Track"}catch{return"Unknown Track"}},y={...m,...e,...f,...i,title:f.title||i.title||p(u),artist:f.artist||i.artist||("string"==typeof a?a:String(a()))};return o.onProgress&&o.onProgress({status:"success",stage:"COMPLETE",url:u}),y}catch(t){if(t instanceof n)throw t;{const e=new n(t instanceof Error?t.message:"UNKNOWN ERROR",u,"INITIALIZING");throw h(e,"INITIALIZING"),e}}})(t,e,i,s,o,u.#o)}static#o="Unknown Artist";static get unknownArtist(){return u.#o}static set unknownArtist(t){if("string"!=typeof t&&"function"!=typeof t)throw new TypeError("unknownArtist must have an string or function.");u.#o=t}get size(){return this.#a.length+this.#c.length}get musicSize(){return this.#a.length}get voiceSize(){return this.#c.length}get customPosSize(){return this.#l.length}get tasksSize(){return this.#u.length}get cycleCacheSize(){return this.#d.size}#a=[];get musicList(){return structuredClone(this.#a)}#c=[];get voiceList(){return structuredClone(this.#c)}#l=[];get customPositions(){return structuredClone(this.#l)}#u=[];get scheduledTasks(){return structuredClone(this.#u)}get allList(){return[...this.musicList,...this.voiceList]}#h=0;get seed(){return this.#h}set seed(t){if("number"!=typeof t)throw new TypeError("Seed must be a number.");this.#h=t,this.#d.clear(),this.emit("seedChanged",{seed:t})}#m=Date.now();get anchorDate(){return this.#m}#d=new Map;#f={mode:"playlist",voiceMode:"playlist",silenceDuration:0,queryLimit:1e5,voiceAfterMusic:!0,voiceMin:0,voiceMax:1,musicMaxConsecutive:0,voiceMaxConsecutive:0};get config(){return structuredClone(this.#f)}set config(t){this.#p(t),this.#f=structuredClone(t),this.#d.clear(),this.emit("configChanged",{config:this.config})}#p(t){if("object"!=typeof t||null===t)throw new TypeError("Configuration must be a valid object.");const e=["playlist","random"];if(void 0!==t.mode&&!e.includes(t.mode))throw new TypeError(`Invalid mode: "${t.mode}". Must be one of: ${e.join(", ")}.`);if(void 0!==t.voiceMode&&!e.includes(t.voiceMode))throw new TypeError(`Invalid voiceMode: "${t.voiceMode}". Must be one of: ${e.join(", ")}.`);if(void 0!==t.silenceDuration&&("number"!=typeof t.silenceDuration||t.silenceDuration<0))throw new TypeError("silenceDuration must be a non-negative number.");if(void 0!==t.queryLimit&&("number"!=typeof t.queryLimit||t.queryLimit<=0))throw new TypeError("queryLimit must be a positive number.");if(void 0!==t.voiceAfterMusic&&"boolean"!=typeof t.voiceAfterMusic)throw new TypeError("voiceAfterMusic must be a boolean.");if(void 0!==t.voiceMin&&("number"!=typeof t.voiceMin||t.voiceMin<0))throw new TypeError("voiceMin must be a non-negative number.");if(void 0!==t.voiceMax&&("number"!=typeof t.voiceMax||t.voiceMax<0))throw new TypeError("voiceMax must be a non-negative number.");if(void 0!==t.musicMaxConsecutive&&("number"!=typeof t.musicMaxConsecutive||t.musicMaxConsecutive<-1))throw new TypeError("musicMaxConsecutive must be a number >= -1.");if(void 0!==t.voiceMaxConsecutive&&("number"!=typeof t.voiceMaxConsecutive||t.voiceMaxConsecutive<-1))throw new TypeError("voiceMaxConsecutive must be a number >= -1.");const i=t.voiceMin??this.#f.voiceMin,n=t.voiceMax??this.#f.voiceMax;if(n<i)throw new RangeError(`Logical error: voiceMax (${n}) cannot be less than voiceMin (${i}).`)}constructor(t=null,e=0){if(super(),null!==t&&"object"!=typeof t)throw new TypeError("initialData must be an object or null.");if("number"!=typeof e)throw new TypeError("seed must be a number.");this.#h=e,t?this.#y(t):this.#m=Date.now()}add(t,e,i=!0){if(!["music","voice","custom"].includes(t))throw new TypeError('Type must be "music", "voice", or "custom".');if(!e||"string"!=typeof e.id||"number"!=typeof e.duration)throw new TypeError("Content must have a string ID and a valid numerical duration in milliseconds.");if("boolean"!=typeof i)throw new TypeError("smartQueue must be a boolean.");"music"===t?(this.#a.push(e),this.#d.clear()):"voice"===t?(this.#c.push(e),this.#d.clear()):"custom"===t&&this.#g(e,i),this.#w(Date.now()),this.emit("contentAdded",{type:t,data:structuredClone(e)})}scheduleTask(t,e,i,n,r=!0){if("number"!=typeof t||isNaN(t))throw new TypeError("timestamp must be a valid number.");if(!["add","remove","move"].includes(e))throw new TypeError('action must be "add", "remove", or "move".');if(!["music","voice"].includes(i))throw new TypeError('type must be "music" or "voice".');if("boolean"!=typeof r)throw new TypeError("smartQueue must be a boolean.");if("add"===e){if("object"!=typeof n||null===n||"string"!=typeof n.id||"number"!=typeof n.duration)throw new TypeError('Payload for "add" must be a MediaContent object (id: string, duration: number).')}else if("remove"===e){if("string"!=typeof n)throw new TypeError('Payload for "remove" must be a string (the content ID).')}else if("move"===e&&("object"!=typeof n||null===n||"string"!=typeof n.id||"number"!=typeof n.newIndex))throw new TypeError('Payload for "move" must be a ScheduledMovePayload (id: string, newIndex: number).');let s=t;if(r){const e=this.#v(t,t);e&&(s=e.absoluteEnd)}const o={timestamp:s,action:e,type:i,payload:n};this.#u.push(o),this.#w(Date.now()),this.emit("taskScheduled",structuredClone(o))}remove(t){if("string"!=typeof t)throw new TypeError("id must be a string.");this.#a.filter(e=>e.id===t).forEach(t=>a(t)),this.#c.filter(e=>e.id===t).forEach(t=>a(t)),this.#l.filter(e=>e.content?.id===t).forEach(t=>a(t.content));const e=e=>e.id!==t&&e.content?.id!==t;this.#a=this.#a.filter(e),this.#c=this.#c.filter(e),this.#l=this.#l.filter(e),this.#u=this.#u.filter(e=>"add"===e.action&&"object"==typeof e.payload&&null!==e.payload&&"id"in e.payload?e.payload.id!==t||(a(e.payload),!1):e.payload!==t),this.#d.clear(),this.emit("contentRemoved",{id:t})}setConfig(t){this.#p(t);const e={...this.#f,...t};this.#p(e),this.#f=e,this.#d.clear(),this.emit("configChanged",{config:this.config})}getCurrentEvent(){const t=Date.now();return this.#w(t),this.#v(t,t)}queryTimeline(t,e=10){if("number"!=typeof e||isNaN(e))throw new TypeError("Invalid query limit value. Ensure it is a number.");if(e>this.#f.queryLimit||e<=0)throw new RangeError(`Invalid query limit. Ensure it is > 0 and <= ${this.#f.queryLimit}.`);const i=new u(JSON.parse(this._exportState())),n=[];let r=t;for(let s=0;s<e;s++){i.#w(r);const e=i.#b(r,t);if(!e)break;n.push(e),r=e.absoluteEnd}return i.destroy(!1),this.emit("timelineQueried",{targetDate:t,limit:e,resultCount:n.length}),n}searchCustomPositions(){return this.#w(Date.now()),[...this.#l]}async _processListForExport(t){return Promise.all(t.map(async t=>{const e=structuredClone(t);return e.picture&&Array.isArray(e.picture)&&(e.picture=await Promise.all(e.picture.map(async t=>({...t,data:await o(t.data)})))),e}))}_exportState(){return JSON.stringify({music:this.#a,voice:this.#c,custom:this.#l,tasks:this.#u,seed:this.#h,anchorDate:this.#m,config:this.#f})}async exportState(){const t=await this._processListForExport(this.#a),e=await this._processListForExport(this.#c),i=await Promise.all(this.#l.map(async t=>{const e=await this._processListForExport([t.content]);return{...t,content:e[0]}})),n=await Promise.all(this.#u.map(async t=>{if("add"===t.action&&t.payload&&"object"==typeof t.payload&&"title"in t.payload){const e=await this._processListForExport([t.payload]);return{...t,payload:e[0]}}return t}));return JSON.stringify({music:t,voice:e,custom:i,tasks:n,seed:this.#h,anchorDate:this.#m,config:this.#f})}importState(t){let e;if("string"==typeof t)try{e=JSON.parse(t)}catch{throw new TypeError("Provided string is not valid JSON.")}else{if("object"!=typeof t||null===t)throw new TypeError("Import data must be a valid JSON string or an object.");e=t}this.#y(e),this.emit("stateImported",{data:structuredClone(e)})}_prng(t){return function(){let e=t+=1831565813;return e=Math.imul(e^e>>>15,1|e),e^=e+Math.imul(e^e>>>7,61|e),((e^e>>>14)>>>0)/4294967296}}#E(t,e,i,n=0){if(0===t.length)return[];if("random"!==i)return[...t];const r=t.map(t=>({...t,weight:t.weight??1})),s=this._prng(e),o=[];let a=null,c=0;for(;r.length>0;){let t=r;-1!==n&&null!==a&&c>n&&(t=r.filter(t=>t.id!==a),0===t.length&&(t=r));const e=t.reduce((t,e)=>t+e.weight,0);if(e<=0){o.push(...t);break}const i=s()*e;let l=0,u=null,d=-1;for(let e=0;e<t.length;e++)if(l+=t[e].weight,i<=l){u=t[e],d=r.findIndex(t=>u&&t.id===u.id);break}u&&-1!==d||(u=t[0],d=r.findIndex(t=>u&&t.id===u.id)),o.push(u),r.splice(d,1),u.id===a?c++:(a=u.id,c=1)}return o}#T(t){const e=this.#h+t,i=this._prng(10*e),n=this.#E(this.#a,e+1,this.#f.mode,this.#f.musicMaxConsecutive),r=this.#E(this.#c,e+2,this.#f.voiceMode,this.#f.voiceMaxConsecutive),s=[];let o=0,a=0;for(let t=0;t<n.length;t++){const e=n[t];if(s.push({...e,cycleStart:o,cycleEnd:o+e.duration}),o+=e.duration+this.#f.silenceDuration,this.#f.voiceAfterMusic&&r.length>0){const t=this.#f.voiceMax-this.#f.voiceMin+1,e=Math.floor(i()*t)+this.#f.voiceMin;for(let t=0;t<e;t++){const t=r[a%r.length];a++,s.push({...t,cycleStart:o,cycleEnd:o+t.duration}),o+=t.duration+this.#f.silenceDuration}}}return{items:s,duration:o}}#L(t){if(0===this.#a.length)return null;let e=this.#m,i=0;for(;;){if(i>this.#f.queryLimit)throw new Error("Safety limit hit during cycle location.");let n=this.#d.get(i);if(n||(n=this.#T(i),this.#d.set(i,n)),0===n.duration)return null;if(t>=e&&t<e+n.duration)return{block:n,startTimestamp:e,loopIndex:i};e+=n.duration,i++}}#b(t,e){const i=this.#l.filter(e=>e.intendedTimestamp+e.content.duration>t).sort((t,e)=>t.intendedTimestamp-e.intendedTimestamp)[0];let n=null;if(i){const t=Math.max(e,i.intendedTimestamp);n=this.#M(i.content,i.intendedTimestamp,t,!0)}const r=this.#A(t,e);return r||n?r?n?n.absoluteStart<=r.absoluteStart?n:(n.absoluteStart<r.absoluteEnd&&(r.absoluteEnd=n.absoluteStart,r.duration=r.absoluteEnd-r.absoluteStart,r.remainingTime=Math.max(0,r.absoluteEnd-e),r.progress=Math.min(1,r.elapsedTime/r.duration)),r):r:n:null}#A(t,e){let i=this.#L(t);if(!i)return null;const{block:n,startTimestamp:r}=i,s=t-r;let o,a=n.items.find(t=>t.cycleEnd>s);if(a)o=r+a.cycleStart;else{if(i=this.#L(r+n.duration),!i||0===i.block.items.length)return null;a=i.block.items[0],o=i.startTimestamp+a.cycleStart}const c=Math.max(e,o);return this.#M(a,o,c,!1)}#v(t,e){const i=this.#l.find(e=>t>=e.intendedTimestamp&&t<e.intendedTimestamp+e.content.duration);if(i)return this.#M(i.content,i.intendedTimestamp,e,!0);const n=this.#L(t);if(!n)return null;const{block:r,startTimestamp:s}=n,o=t-s,a=r.items.find(t=>o>=t.cycleStart&&o<t.cycleEnd);return a?this.#M(a,s+a.cycleStart,e,!1):null}#M(t,e,i,n){const r=i-e;return{id:t.id,title:t.title,artist:t.artist,duration:t.duration,url:t.url,absoluteStart:e,absoluteEnd:e+t.duration,elapsedTime:r,remainingTime:t.duration-r,progress:Math.min(1,r/t.duration),isCustom:n}}#g(t,e){let i=t.timestamp||Date.now();const n=t.duration;if(e){const t=this.#v(i,i);t&&(i=t.absoluteEnd)}const r=[...this.#l].sort((t,e)=>t.intendedTimestamp-e.intendedTimestamp);let s=i;if(r.some(t=>i<t.intendedTimestamp+t.content.duration&&i+n>t.intendedTimestamp)){const t=[];let e=Date.now();for(const i of r)i.intendedTimestamp>e&&t.push({start:e,end:i.intendedTimestamp}),e=Math.max(e,i.intendedTimestamp+i.content.duration+this.#f.silenceDuration);t.push({start:e,end:1/0});let o=1/0;for(const e of t)if(e.end-e.start>=n){let t=null;if(i>=e.start&&i+n<=e.end?t=i:i<e.start?t=e.start:i>e.end&&(t=e.end-n),null!==t){const e=Math.abs(i-t);e<o&&(o=e,s=t)}}}this.#l.push({content:t,intendedTimestamp:s,originalTimestamp:t.timestamp||Date.now()})}#w(t){const e=this.#u.filter(e=>e.timestamp<=t);this.#u=this.#u.filter(e=>e.timestamp>t);const i=this.#l.filter(e=>e.intendedTimestamp+e.content.duration<=t);this.#l=this.#l.filter(e=>e.intendedTimestamp+e.content.duration>t);let n=!1;i.forEach(t=>{a(t.content),this.#h+=t.content.id.length,n=!0,this.emit("customPositionExpired",{contentId:t.content.id})}),e.length>0&&e.sort((t,e)=>t.timestamp-e.timestamp).forEach(t=>{const e="music"===t.type?this.#a:this.#c;if("add"===t.action)e.push(t.payload);else if("remove"===t.action){const i=t.payload,n=e.findIndex(t=>t.id===i);if(-1!==n){const[t]=e.splice(n,1);a(t)}}else if("move"===t.action){const i=t.payload,n=e.findIndex(t=>t.id===i.id);if(-1!==n){const[t]=e.splice(n,1);e.splice(i.newIndex,0,t)}}this.#m=t.timestamp,this.#h+=1,n=!0,this.emit("taskExecuted",structuredClone(t))}),n&&this.#d.clear()}#y(t){this.#a.forEach(t=>a(t)),this.#c.forEach(t=>a(t)),this.#l.forEach(t=>a(t.content)),this.#u.forEach(t=>{"add"===t.action&&t.payload&&"object"==typeof t.payload&&"title"in t.payload&&a(t.payload)});const e=t=>t.map(t=>{const e={...t};return e.picture&&Array.isArray(e.picture)&&(e.picture=e.picture.map(t=>({...t,data:s(t.data,t.format)}))),e});this.#a=e(t.music),this.#c=e(t.voice),this.#h=t.seed||0,this.#m=t.anchorDate||Date.now(),this.#f={...this.#f,...t.config||{}},this.#l=t.custom.map(t=>({...t,content:e([t.content])[0]})),this.#u=t.tasks.map(t=>"add"===t.action&&t.payload&&"object"==typeof t.payload&&"title"in t.payload?{...t,payload:e([t.payload])[0]}:t)}destroy(t=!0){t&&(this.#a.forEach(t=>a(t)),this.#c.forEach(t=>a(t)),this.#l.forEach(t=>a(t.content)),this.#u.forEach(t=>{"add"===t.action&&t.payload&&"object"==typeof t.payload&&"title"in t.payload&&a(t.payload)})),this.#a=[],this.#c=[],this.#l=[],this.#u=[],this.#d.clear(),this.emit("destroyed",{timestamp:Date.now()}),this.removeAllListeners()}}const d=u;window.TinyRadioFm=e.TinyRadioFm})();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
(()=>{"use strict";
|
|
1
|
+
(()=>{"use strict";const e={d:(t,r)=>{if(Array.isArray(r))for(var i=0;i<r.length;){var s=r[i++],n=r[i++];e.o(t,s)?0===n&&i++:0===n?Object.defineProperty(t,s,{enumerable:!0,value:r[i++]}):Object.defineProperty(t,s,{enumerable:!0,get:n})}else for(var s in r)e.o(r,s)&&!e.o(t,s)&&Object.defineProperty(t,s,{enumerable:!0,get:r[s]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t)};let t={};e.d(t,{TinyRateLimiter:()=>r});const r=class{#e=null;#t=null;#r=null;#i=null;#s=null;#n=null;groupData=new Map;lastSeen=new Map;userToGroup=new Map;groupFlags=new Map;groupTTL=new Map;#o=null;setOnMemoryExceeded(e){if("function"!=typeof e)throw new Error("onMemoryExceeded must be a function");this.#o=e}clearOnMemoryExceeded(){this.#o=null}#a=null;setOnGroupExpired(e){if("function"!=typeof e)throw new Error("onGroupExpired must be a function");this.#a=e}clearOnGroupExpired(){this.#a=null}constructor({maxHits:e,interval:t,cleanupInterval:r,maxIdle:i=3e5,maxMemory:s=1e5}){const n=e=>"number"==typeof e&&Number.isFinite(e)&&e>=1&&Number.isInteger(e),o=n(e),a=n(t),u=n(r),l=n(i);if(!o&&!a)throw new Error("RateLimiter requires at least one valid option: 'maxHits' or 'interval'.");if(void 0!==e&&!o)throw new Error("'maxHits' must be a positive integer if defined.");if(void 0!==t&&!a)throw new Error("'interval' must be a positive integer in milliseconds if defined.");if(void 0!==r&&!u)throw new Error("'cleanupInterval' must be a positive integer in milliseconds if defined.");if(!l)throw new Error("'maxIdle' must be a positive integer in milliseconds.");if("number"==typeof s&&Number.isFinite(s)&&s>0)this.#e=Math.floor(s);else{if(null!=s)throw new Error("maxMemory must be a positive number or null");this.#e=null}this.#r=o?e:null,this.#i=a?t:null,this.#s=u?r:null,this.#n=i,null!==this.#s&&(this.#t=setInterval(()=>this._cleanup(),this.#s))}isGroupId(e){const t=this.groupFlags.get(e);return"boolean"==typeof t&&t}getUsersInGroup(e){const t=[];for(const[r,i]of this.userToGroup.entries())i===e&&t.push(r);return t}setGroupTTL(e,t){if("number"!=typeof t||!Number.isFinite(t)||t<=0)throw new Error("TTL must be a positive number in milliseconds");this.groupTTL.set(e,t)}getGroupTTL(e){return this.groupTTL.get(e)??null}deleteGroupTTL(e){this.groupTTL.delete(e)}assignToGroup(e,t){const r=this.userToGroup.get(e);if(r&&r!==t)throw new Error(`User ${e} is already assigned to group ${r}`);if(r===t)return;const i=this.groupData.get(e);if(this.isGroupId(e)){for(const[r,i]of this.userToGroup.entries())i===e&&this.userToGroup.set(r,t);this.userToGroup.delete(e)}else this.userToGroup.set(e,t);if(!i)return;const s=this.groupData.get(t);if(s)for(const e of i)s.push(e);else{const e=[];for(const t of i)e.push(t);this.groupData.set(t,e)}this.lastSeen.set(t,Date.now()),this.groupFlags.delete(e),this.groupData.delete(e),this.lastSeen.delete(e),this.groupTTL.delete(e),this.groupFlags.set(t,!0)}getGroupId(e){return this.userToGroup.get(e)||e}hit(e){const t=this.getGroupId(e),r=Date.now();this.groupData.has(t)||(this.groupData.set(t,[]),this.groupFlags.set(t,!1));const i=this.groupData.get(t);if(!i)throw new Error(`No data found for groupId: ${t}`);if(i.push(r),this.lastSeen.set(t,r),null!==this.#i){const e=r-this.getInterval();for(;i.length&&i[0]<e;)i.shift()}null!==this.#e&&"number"==typeof this.#e&&i.length>this.#e&&(i.splice(0,i.length-this.#e),"function"==typeof this.#o&&this.#o(t))}isRateLimited(e){const t=this.getGroupId(e);if(!this.groupData.has(t))return!1;const r=this.groupData.get(t);if(!r)throw new Error(`No data found for groupId: ${t}`);if(null!==this.#i){const e=Date.now()-this.getInterval();let t=0;for(let i=r.length-1;i>=0&&r[i]>e;i--)t++;return null!==this.#r?t>this.getMaxHits():t>0}return null!==this.#r&&r.length>this.getMaxHits()}resetGroup(e){this.groupFlags.delete(e),this.groupData.delete(e),this.lastSeen.delete(e),this.groupTTL.delete(e)}resetUserGroup(e){this.userToGroup.delete(e)}setData(e,t){if(!Array.isArray(t))throw new Error("timestamps must be an array of numbers.");for(const e of t)if("number"!=typeof e||!Number.isFinite(e))throw new Error("All timestamps must be finite numbers.");this.groupData.has(e)||this.groupFlags.set(e,!1),this.groupData.set(e,t),this.lastSeen.set(e,Date.now())}hasData(e){return this.groupData.has(e)}getData(e){return this.groupData.get(e)||[]}getMaxIdle(){if("number"!=typeof this.#n||!Number.isFinite(this.#n)||this.#n<0)throw new Error("'maxIdle' must be a non-negative finite number.");return this.#n}setMaxIdle(e){if("number"!=typeof e||!Number.isFinite(e)||e<0)throw new Error("'maxIdle' must be a non-negative finite number.");this.#n=e}_cleanup(){const e=Date.now();for(const[t,r]of this.lastSeen.entries())e-r>(this.getGroupTTL(t)??this.getMaxIdle())&&(this.groupFlags.delete(t),this.groupData.delete(t),this.lastSeen.delete(t),this.groupTTL.delete(t),"function"==typeof this.#a&&this.#a(t))}getActiveGroups(){return Array.from(this.groupData.keys())}getAllUserMappings(){return Object.fromEntries(this.userToGroup)}getInterval(){if("number"!=typeof this.#i||!Number.isFinite(this.#i))throw new Error("'interval' is not a valid finite number.");return this.#i}getMaxHits(){if("number"!=typeof this.#r||!Number.isFinite(this.#r))throw new Error("'maxHits' is not a valid finite number.");return this.#r}getTotalHits(e){const t=this.groupData.get(e);return Array.isArray(t)?t.length:0}getLastHit(e){const t=this.groupData.get(e);return t?.length?t[t.length-1]:null}getTimeSinceLastHit(e){const t=this.getLastHit(e);return null!==t?Date.now()-t:null}_calculateAverageSpacing(e){if(!Array.isArray(e)||e.length<2)return null;let t=0;for(let r=1;r<e.length;r++)t+=e[r]-e[r-1];return t/(e.length-1)}getAverageHitSpacing(e){return this._calculateAverageSpacing(this.groupData.get(e))}getMetrics(e){const t=this.groupData.get(e);if(!Array.isArray(t)||0===t.length)return{totalHits:0,lastHit:null,timeSinceLastHit:null,averageHitSpacing:null};const r=t.length,i=t[r-1];return{totalHits:r,lastHit:i,timeSinceLastHit:Date.now()-i,averageHitSpacing:this._calculateAverageSpacing(t)}}destroy(){this.#t&&clearInterval(this.#t),this._cleanup(),this.groupData.clear(),this.lastSeen.clear(),this.userToGroup.clear(),this.groupTTL.clear(),this.groupFlags.clear()}};window.TinyRateLimiter=t.TinyRateLimiter})();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
(()=>{"use strict";
|
|
1
|
+
(()=>{"use strict";const e={d:(r,t)=>{if(Array.isArray(t))for(var o=0;o<t.length;){var n=t[o++],s=t[o++];e.o(r,n)?0===s&&o++:0===s?Object.defineProperty(r,n,{enumerable:!0,value:t[o++]}):Object.defineProperty(r,n,{enumerable:!0,get:s})}else for(var n in t)e.o(t,n)&&!e.o(r,n)&&Object.defineProperty(r,n,{enumerable:!0,get:t[n]})},o:(e,r)=>Object.prototype.hasOwnProperty.call(e,r)};let r={};function t(e){return null!==e&&"object"==typeof e&&!Array.isArray(e)&&"[object Object]"===Object.prototype.toString.call(e)}e.d(r,{TinySimpleDice:()=>n});class o{static _safeEvaluate(e){if(!/^[\d+\-*/%.()\s^]+$/.test(e))throw new Error(`Invalid characters in expression: "${e}"`);const r=e.replace(/\^/g,"**");try{return Function(`"use strict"; return (${r})`)()}catch(r){if(!(r instanceof Error))throw new Error("Unknown Error");throw new Error(`Invalid expression "${e}": ${r.message}`)}}static replaceValues(e,r){let t=0;return e.replace(/(\d*)d(\d+)/g,(e,o)=>{const n=o?Number(o):1;let s=0;for(let e=0;e<n;e++){const e=r[t++];s+=void 0!==e?e:0}return String(s)})}static tokenizeValues(e,r){const t=o.replaceValues(e,r),n=[],s=/\d+|[()+\-*/]/g;let a;for(;null!==(a=s.exec(t));)/^\d+$/.test(a[0])?n.push(Number(a[0])):n.push(a[0]);return{tokens:n,text:t}}static parseString(e){if("string"!=typeof e)throw new TypeError("Input must be a string.");const r=e.split(",").map(e=>e.trim()).filter(Boolean),t=[],o=[];if(r.forEach((e,r)=>{const n=/\b(?:(\d+)?d(\d+))\b/g;let s;const a=[],i=e.replace(/\(([^()]+?\|[^()]+?)\)/g,(e,r)=>{const t="string"==typeof r?r.split("|").map(e=>e.trim()).filter(Boolean):[];if(0===t.length)throw new Error(`Invalid random-choice group: "${e}"`);return t[Math.floor(Math.random()*t.length)]});for(;null!==(s=n.exec(i));){const e=parseInt(s[1]||"1",10),t=parseInt(s[2],10);if(isNaN(t))throw new Error(`Invalid dice sides in expression "${s[0]}" at position ${r+1}.`);a.push({count:e,sides:t})}if(0===a.length&&Number.isNaN(parseFloat(i)))throw new Error(`Invalid dice expression at position ${r+1}: "${e}"`);t.push(...a),o.push({index:r,original:e,expression:i})}),0===t.length)throw new Error("Invalid dice amount.");return{sides:t,modifiers:o}}static applyModifiers(e,r){if(!Array.isArray(e)||!e.every(e=>"number"==typeof e&&!Number.isNaN(e)||t(e)&&"number"==typeof e.value&&!Number.isNaN(e.value)&&"number"==typeof e.sides&&!Number.isNaN(e.sides)))throw new TypeError("Bases must be a valid numbers.");if(!Array.isArray(r))throw new TypeError("Modifiers must be an array of modifier objects.");let n=0;const s=[],a=[...e];for(const e in r){const i=r[e];if("string"!=typeof i.expression)throw new Error("Each modifier must include an expression string.");const l=i.original,u=i.expression,c=[],p=[],f=[],h=e=>e.match(/\(\s*[^()]+\|\s*[^()]+\s*\)|\b\d*d\d+\b|[-+]?\d+(?:\.\d+)?|[+\-*/%^()]/g)||[],d=h(u),m=h(l),w=[...d],b=[],y=u.replace(/\b\d*d\d+\b/g,e=>{const r=e.split("d"),o=()=>{for(const r in d)if(d[r]===e&&b.indexOf(r)<0){b.push(r),f.push(Number(r));break}},n=e=>{if(e.value>e.sides)throw new Error(`Invalid dice roll: value (${e.value}) must be between 1 and ${e.sides}.`)};if(0===r[0].trim().length){const r=a.shift(),s="number"==typeof r?r:t(r)?r.value:0;t(r)&&n(r),c.push([s]);for(const r in w)if(w[r]===e){w[r]=String(s),p.push(Number(r));break}return o(),s}const s=[],i=Number(r[0]),l=["("];let u="(";for(let e=0;e<i;e++){const r=a.shift(),o="number"==typeof r?r:t(r)?r.value:0;t(r)&&n(r),l.push(String(o));const c=e<i-1?" + ":")";l.push(c),u+=`${o}${c}`,s.push(o)}for(const r in w){const t=Number(r);if(w[t]===e){w.splice(t,1,...l);let e=1;for(let r=0;r<i;r++)p.push(t+r+e),e++;break}}return c.push(s),o(),u});let g;try{g=o._safeEvaluate(y)}catch(e){if(!(e instanceof Error))throw new Error("Unknown Error");throw new Error(`Error evaluating expression "${y}" (from "${u}"): ${e.message}`)}s.push({rawTokensP:d,rawTokens:m,tokens:w,rawDiceTokenSlots:f,diceTokenSlots:p,dicesResult:c,total:g}),n+=g}return{final:n,steps:s}}static rollArrayIndex(e){const r=Array.isArray(e),t=e instanceof Set;if(!r&&!t)throw new TypeError("rollArrayIndex expects an array or Set.");return Math.floor(Math.random()*(r?e.length:e.size))}#e;#r;get maxValue(){return this.#e}set maxValue(e){if(!Number.isInteger(e)||e<0)throw new TypeError("maxValue must be an integer greater than -1.");this.#e=e}get allowZero(){return this.#r}set allowZero(e){if("boolean"!=typeof e)throw new TypeError("allowZero must be a boolean.");this.#r=e}constructor({maxValue:e,allowZero:r=!0}){if("boolean"!=typeof r)throw new TypeError("allowZero must be an boolean.");if(!Number.isInteger(e)||e<0)throw new TypeError("maxValue must be an integer greater than -1.");this.#e=e,this.#r=r}roll(){const e=this.#r?0:1;return Math.floor(Math.random()*(this.#e-e+1))+e}}const n=o;window.TinySimpleDice=r.TinySimpleDice})();
|