@supernal/tts-widget 1.0.0 → 1.0.3
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/README.md +39 -1
- package/dist/loader.js +6 -6
- package/dist/loader.js.map +3 -3
- package/dist/widget.d.ts +11 -0
- package/dist/widget.d.ts.map +1 -1
- package/dist/widget.js +6 -6
- package/dist/widget.js.map +3 -3
- package/package.json +4 -1
package/dist/widget.d.ts
CHANGED
|
@@ -85,10 +85,21 @@ export declare class SupernalTTS {
|
|
|
85
85
|
private progressUpdateInterval;
|
|
86
86
|
private audioQueue;
|
|
87
87
|
constructor(options?: SupernalTTSOptions);
|
|
88
|
+
/**
|
|
89
|
+
* Auto-detect API key from common framework environment variables
|
|
90
|
+
* Checks in order: NEXT_PUBLIC_TTS_API_KEY, VITE_TTS_API_KEY, PUBLIC_TTS_API_KEY, REACT_APP_TTS_API_KEY
|
|
91
|
+
*/
|
|
92
|
+
private detectApiKey;
|
|
88
93
|
private init;
|
|
89
94
|
private observeDOM;
|
|
90
95
|
private initializeWidgets;
|
|
91
96
|
private setupWidget;
|
|
97
|
+
/**
|
|
98
|
+
* Scrub text to remove URLs and convert markdown links to plain text
|
|
99
|
+
* - Markdown links [text](url) -> text
|
|
100
|
+
* - Bare URLs -> "link"
|
|
101
|
+
*/
|
|
102
|
+
private scrubText;
|
|
92
103
|
/**
|
|
93
104
|
* Parse widget configuration from data attributes
|
|
94
105
|
*/
|
package/dist/widget.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"widget.d.ts","sourceRoot":"","sources":["../src/widget.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"widget.d.ts","sourceRoot":"","sources":["../src/widget.ts"],"names":[],"mappings":"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"}
|
package/dist/widget.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
var L=class w{constructor(e={}){this.currentAudio=null;this.currentButton=null;this.isProcessing=!1;this.lastClickTime=0;this.debounceDelay=300;this.progressUpdateInterval=null;this.audioQueue=[];this.apiUrl=e.apiUrl||"https://www.tts.supernal.ai",this.defaultVoice=e.voice||"default",this.defaultProvider=e.provider||"openai",this.defaultSpeed=e.speed||1,this.autoHash=e.autoHash!==!1,this.cacheExpiry=e.cacheExpiry||7*24*60*60*1e3,this.apiKey=e.apiKey
|
|
1
|
+
var L=class w{constructor(e={}){this.currentAudio=null;this.currentButton=null;this.isProcessing=!1;this.lastClickTime=0;this.debounceDelay=300;this.progressUpdateInterval=null;this.audioQueue=[];this.apiUrl=e.apiUrl||"https://www.tts.supernal.ai",this.defaultVoice=e.voice||"default",this.defaultProvider=e.provider||"openai",this.defaultSpeed=e.speed||1,this.autoHash=e.autoHash!==!1,this.cacheExpiry=e.cacheExpiry||7*24*60*60*1e3,this.apiKey=e.apiKey||this.detectApiKey(),this.showBranding=e.showBranding!==!1,this.version=e.version||"1.0.0",this.devMode=e.devMode===!0,this.clientSideSpeed=e.clientSideSpeed!==!1,this.generationMode=e.generationMode||"standard",this.progressiveThreshold=e.progressiveThreshold||2e3,this.cache=new Map,this.loadCacheFromStorage(),this.init()}detectApiKey(){if(typeof window>"u")return;let e=["NEXT_PUBLIC_TTS_API_KEY","VITE_TTS_API_KEY","PUBLIC_TTS_API_KEY","REACT_APP_TTS_API_KEY"];for(let t of e)try{let s=globalThis.process?.env;if(s?.[t])return console.log(`[TTS Widget] Auto-detected API key from process.env.${t}`),s[t];let r=globalThis.import?.meta?.env;if(r?.[t])return console.log(`[TTS Widget] Auto-detected API key from import.meta.env.${t}`),r[t]}catch{continue}}init(){document.readyState==="loading"?document.addEventListener("DOMContentLoaded",()=>this.initializeWidgets()):this.initializeWidgets(),this.observeDOM()}observeDOM(){new MutationObserver(t=>{t.forEach(s=>{s.addedNodes.forEach(r=>{if(r.nodeType===Node.ELEMENT_NODE){let o=r;o.classList?.contains("supernal-tts-widget")?this.setupWidget(o):o.querySelectorAll?.(".supernal-tts-widget")?.forEach(i=>this.setupWidget(i))}})})}).observe(document.body,{childList:!0,subtree:!0})}initializeWidgets(){let e=document.querySelectorAll(".supernal-tts-widget");e.forEach(t=>this.setupWidget(t)),this.devMode&&e.length>0&&this.addDevModeClearButton()}setupWidget(e){if(e.classList.contains("supernal-tts-widget-initialized"))return;let t=this.parseWidgetConfig(e);if(!t.text){console.warn("TTS Widget: No text found for widget",e);return}let s=this.generateHash(t.text,{voice:t.voice,provider:t.provider,speed:t.speed}),r=e.dataset.controls;if(r==="advanced"||r==="true"){this.setupAdvancedWidget(e,t.text,{voice:t.voice,provider:t.provider,speed:t.speed,hash:s,apiKey:t.apiKey});return}else if(r==="compact"){this.setupCompactWidget(e,t.text,{voice:t.voice,provider:t.provider,speed:t.speed,hash:s,apiKey:t.apiKey});return}this.setupModularWidget(e,t,s)}scrubText(e){if(!e)return"";let t=e;return t=t.replace(/\[([^\]]+)\]\(([^)]+)\)/g,"$1"),t=t.replace(/https?:\/\/[^\s]+/g,"link"),t=t.replace(/www\.[^\s]+/g,"link"),t}parseWidgetConfig(e){let t=e.dataset.text||e.textContent?.trim()||"",s=this.scrubText(t),r=e.dataset.voice||this.defaultVoice,o=e.dataset.provider||this.defaultProvider,n=e.dataset.speed?parseFloat(e.dataset.speed):this.defaultSpeed,i=e.dataset.voices||"",a=i?i.split(",").map(v=>v.trim()).filter(Boolean):[],l=e.dataset.enableSpeed==="true",d=e.dataset.enableProgress==="true",h=e.dataset.apiKey||this.apiKey;return{text:s,voices:a,enableSpeed:l,enableProgress:d,speed:n,provider:o,voice:r,apiKey:h}}setupBasicWidget(e,t,s){let{voice:r,provider:o,speed:n,hash:i,apiKey:a}=s;if(e.classList.contains("supernal-tts-widget-initialized"))return;let l=document.createElement("div");l.className="supernal-tts-button-container";let d=e.querySelector(".supernal-tts-play");if(d||(d=this.createPlayButton()),l.appendChild(d),this.showBranding&&!e.querySelector(".supernal-badge")){let h=this.createBrandingBadge();l.appendChild(h)}e.appendChild(l),e.classList.add("supernal-tts-widget-initialized"),d.addEventListener("click",h=>{h.preventDefault(),this.handlePlayClick(d,t,{voice:r,provider:o,speed:n,hash:i,apiKey:a})}),e._ttsWidget={text:t,voice:r,provider:o,speed:n,hash:i,playButton:d}}setupCompactWidget(e,t,s){let{hash:r,apiKey:o}=s,{voice:n,provider:i,speed:a}=s;if(e.classList.contains("supernal-tts-widget-initialized"))return;let l=document.createElement("div");l.className="supernal-tts-compact-widget";let d=document.createElement("div");d.className="supernal-tts-top-row";let h=this.createPlayButton(),v=document.createElement("select");if(v.className="supernal-tts-voice-select",v.innerHTML=`
|
|
2
2
|
<option value="alloy" ${n==="alloy"?"selected":""}>Alloy</option>
|
|
3
3
|
<option value="echo" ${n==="echo"?"selected":""}>Echo</option>
|
|
4
4
|
<option value="fable" ${n==="fable"?"selected":""}>Fable</option>
|
|
@@ -6,10 +6,10 @@ var L=class w{constructor(e={}){this.currentAudio=null;this.currentButton=null;t
|
|
|
6
6
|
<option value="nova" ${n==="nova"?"selected":""}>Nova</option>
|
|
7
7
|
<option value="shimmer" ${n==="shimmer"?"selected":""}>Shimmer</option>
|
|
8
8
|
<option value="coral" ${n==="coral"?"selected":""}>Coral</option>
|
|
9
|
-
`,d.appendChild(h),d.appendChild(
|
|
9
|
+
`,d.appendChild(h),d.appendChild(v),this.showBranding){let m=this.createBrandingBadge();d.appendChild(m)}let g=document.createElement("div");g.className="supernal-tts-speed-control",g.innerHTML=`
|
|
10
10
|
<label>Speed: <span class="supernal-tts-speed-value">${a}x</span></label>
|
|
11
11
|
<input type="range" class="supernal-tts-speed-slider" min="0.25" max="4.0" step="0.25" value="${a}">
|
|
12
|
-
`,l.appendChild(d),l.appendChild(
|
|
12
|
+
`,l.appendChild(d),l.appendChild(g),e.innerHTML="",e.appendChild(l),e.classList.add("supernal-tts-widget-initialized","supernal-tts-widget-compact");let f=g.querySelector(".supernal-tts-speed-slider"),c=g.querySelector(".supernal-tts-speed-value");h.addEventListener("click",m=>{m.preventDefault(),a=parseFloat(f.value),n=v.value;let T=this.generateHash(t,{voice:n,provider:i,speed:a});this.handlePlayClick(h,t,{voice:n,provider:i,speed:a,hash:T,apiKey:o})}),f.addEventListener("input",m=>{a=parseFloat(m.target.value),c.textContent=`${a}x`}),v.addEventListener("change",()=>{n=v.value}),e._ttsWidget={text:t,voice:n,provider:i,speed:a,hash:r,playButton:h,compact:!0}}setupAdvancedWidget(e,t,s){let{hash:r,apiKey:o}=s,{voice:n,provider:i,speed:a}=s,l=document.createElement("div");l.className="supernal-tts-advanced-widget";let d=document.createElement("div");d.className="supernal-tts-button-group";let h=this.createPlayButton(),v=this.createStopButton();d.appendChild(h),d.appendChild(v);let g=document.createElement("select");g.className="supernal-tts-voice-select",g.innerHTML=`
|
|
13
13
|
<option value="alloy" ${n==="alloy"?"selected":""}>Alloy</option>
|
|
14
14
|
<option value="echo" ${n==="echo"?"selected":""}>Echo</option>
|
|
15
15
|
<option value="fable" ${n==="fable"?"selected":""}>Fable</option>
|
|
@@ -23,7 +23,7 @@ var L=class w{constructor(e={}){this.currentAudio=null;this.currentButton=null;t
|
|
|
23
23
|
`;let c=document.createElement("div");if(c.className="supernal-tts-progress",c.innerHTML=`
|
|
24
24
|
<input type="range" class="supernal-tts-progress-slider" min="0" max="100" value="0" step="0.1">
|
|
25
25
|
<div class="supernal-tts-time"><span class="supernal-tts-current-time">0:00</span> / <span class="supernal-tts-duration">0:00</span></div>
|
|
26
|
-
`,l.appendChild(d),l.appendChild(
|
|
26
|
+
`,l.appendChild(d),l.appendChild(g),l.appendChild(f),l.appendChild(c),this.showBranding){let p=this.createBrandingBadge();l.appendChild(p)}e.innerHTML="",e.appendChild(l),e.classList.add("supernal-tts-widget-initialized","supernal-tts-widget-advanced");let m=f.querySelector(".supernal-tts-speed-slider"),T=f.querySelector(".supernal-tts-speed-value"),y=c.querySelector(".supernal-tts-progress-slider");h.addEventListener("click",p=>{p.preventDefault(),a=parseFloat(m.value),n=g.value;let S=this.generateHash(t,{voice:n,provider:i,speed:a});this.handlePlayClick(h,t,{voice:n,provider:i,speed:a,hash:S,apiKey:o})}),v.addEventListener("click",p=>{p.preventDefault(),this.stopAudio()}),m.addEventListener("input",p=>{a=parseFloat(p.target.value),T.textContent=`${a}x`}),g.addEventListener("change",()=>{n=g.value}),y.addEventListener("input",p=>{if(this.currentAudio){let S=parseFloat(p.target.value)/100;this.currentAudio.currentTime=this.currentAudio.duration*S}}),setInterval(()=>{if(this.currentAudio&&e._ttsWidget===this.currentWidget){let p=this.currentAudio.currentTime/this.currentAudio.duration*100;y.value=p.toString();let S=this.formatTime(this.currentAudio.currentTime),E=this.formatTime(this.currentAudio.duration);c.querySelector(".supernal-tts-current-time").textContent=S,c.querySelector(".supernal-tts-duration").textContent=E}},100),e._ttsWidget={text:t,voice:n,provider:i,speed:a,hash:r,playButton:h,stopButton:v,voiceSelect:g,speedSlider:m,progressSlider:y,advanced:!0},this.currentWidget=e._ttsWidget}setupModularWidget(e,t,s){let r=t.voice,o=t.speed,{text:n,voices:i,enableSpeed:a,enableProgress:l,provider:d,apiKey:h}=t,v=0,g=document.createElement("div");g.className="supernal-tts-modular-widget";let f=document.createElement("div");f.className="supernal-tts-controls-row";let c=this.createPlayButton(!0);f.appendChild(c);let m=null;i.length>0&&(m=this.createVoiceDropdown(i,r),f.appendChild(m),m.addEventListener("voice-changed",u=>{let p=u.detail.voice;if(p!==r&&this.currentButton===c&&this.currentAudio){r=p,this.currentAudio.duration>0&&(v=this.currentAudio.currentTime/this.currentAudio.duration);let E=e._ttsWidget?.progressBar;this.cleanStopAudioKeepProgress(E),setTimeout(()=>{this.handlePlayClickFromPosition(c,n,{voice:r,provider:d,speed:o,hash:this.generateHash(n,{voice:r,provider:d,speed:o}),progressBar:E,apiKey:h},v)},50)}else r=p}));let T=null;if(a&&(T=this.createSpeedDropdown(o),f.appendChild(T),T.addEventListener("speed-changed",u=>{let p=u.detail.speed;if(p!==o){if(o=p,this.clientSideSpeed&&this.currentAudio&&this.currentButton===c)this.currentAudio.playbackRate=p;else if(!this.clientSideSpeed&&this.currentButton===c&&this.currentAudio){this.currentAudio.duration>0&&(v=this.currentAudio.currentTime/this.currentAudio.duration);let E=e._ttsWidget?.progressBar;this.cleanStopAudioKeepProgress(E),setTimeout(()=>{this.handlePlayClickFromPosition(c,n,{voice:r,provider:d,speed:o,hash:this.generateHash(n,{voice:r,provider:d,speed:o}),progressBar:E,apiKey:h},v)},50)}}})),this.showBranding){let u=this.createBrandingBadge();f.appendChild(u)}g.appendChild(f);let y=null;l&&(y=this.createProgressBar(),g.appendChild(y)),e.insertBefore(g,e.firstChild),e.classList.add("supernal-tts-widget-initialized","supernal-tts-widget-modular"),l&&e.classList.add("has-progress"),c.addEventListener("click",u=>{u.preventDefault();let p=this.generateHash(n,{voice:r,provider:d,speed:o});this.handlePlayClick(c,n,{voice:r,provider:d,speed:o,hash:p,progressBar:y,apiKey:h})}),e._ttsWidget={text:n,voice:r,provider:d,speed:o,hash:s,playButton:c,voiceDropdown:m,speedDropdown:T,progressBar:y}}createVoiceDropdown(e,t){let s=document.createElement("div");s.className="supernal-tts-voice-control";let r=document.createElement("button");r.className="supernal-tts-voice-toggle",r.setAttribute("aria-label","Select voice"),r.setAttribute("aria-expanded","false"),r.innerHTML=`
|
|
27
27
|
<svg class="supernal-tts-voice-icon" width="20" height="20" viewBox="0 0 24 24" fill="currentColor">
|
|
28
28
|
<path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 3c1.66 0 3 1.34 3 3s-1.34 3-3 3-3-1.34-3-3 1.34-3 3-3zm0 14.2c-2.5 0-4.71-1.28-6-3.22.03-1.99 4-3.08 6-3.08 1.99 0 5.97 1.09 6 3.08-1.29 1.94-3.5 3.22-6 3.22z"/>
|
|
29
29
|
</svg>
|
|
@@ -90,7 +90,7 @@ var L=class w{constructor(e={}){this.currentAudio=null;this.currentButton=null;t
|
|
|
90
90
|
<span>\u{1F5D1}\uFE0F</span>
|
|
91
91
|
<span>Clear Cache</span>
|
|
92
92
|
<span style="opacity: 0.7; font-size: 10px;">\xD7</span>
|
|
93
|
-
`;let r=i=>{i.addEventListener("mouseenter",()=>{i.style.transform="scale(1.05)",i.style.boxShadow="0 4px 12px rgba(0,0,0,0.4)"}),i.addEventListener("mouseleave",()=>{i.style.transform="scale(1)",i.style.boxShadow="0 2px 8px rgba(0,0,0,0.3)"})};r(s),r(t);let o=()=>{let i=this.cache.size;this.cache.clear(),localStorage.removeItem("supernal-tts-cache"),s.innerHTML=`<span>\u2713</span><span>Cleared ${i}</span><span style="opacity: 0.7; font-size: 10px;">\xD7</span>`,s.style.background="#28a745",setTimeout(()=>{s.innerHTML='<span>\u{1F5D1}\uFE0F</span><span>Clear Cache</span><span style="opacity: 0.7; font-size: 10px;">\xD7</span>',s.style.background="#dc3545"},2e3),console.log(`[Supernal TTS Dev] Cleared ${i} cached items`)};s.addEventListener("click",i=>{i.preventDefault();let a=i.clientX-i.target.getBoundingClientRect().left,l=s.getBoundingClientRect().width;a>l*.8?(s.style.display="none",t.style.display="block",localStorage.setItem("supernal-tts-dev-minimized","true")):o()}),t.addEventListener("click",i=>{i.preventDefault(),t.style.display="none",s.style.display="flex",localStorage.setItem("supernal-tts-dev-minimized","false")}),localStorage.getItem("supernal-tts-dev-minimized")==="true"&&(s.style.display="none",t.style.display="block"),e.appendChild(s),e.appendChild(t),document.body?document.body.appendChild(e):document.addEventListener("DOMContentLoaded",()=>{document.body.appendChild(e)})}async handlePlayClick(e,t,s){let{hash:r,progressBar:o}=s;if(e.classList.contains("supernal-tts-playing")&&this.currentButton===e){this.pauseAudio();return}if(e.classList.contains("supernal-tts-paused")&&this.currentButton===e){this.resumeAudio();return}if(!this.isProcessing){this.currentAudio&&this.currentButton&&this.currentButton!==e&&this.stopAudio();try{this.isProcessing=!0,this.setButtonState(e,"loading");let n=this.getCachedAudioUrl(r);if(!n)if(this.generationMode==="progressive"||this.generationMode==="standard"&&t.length>this.progressiveThreshold){await this.generateAudioProgressive(t,s,e,o);return}else{let a=await this.generateAudio(t,s);n=a.audioUrl.startsWith("http")?a.audioUrl:`${this.apiUrl}${a.audioUrl}`,this.cacheAudioUrl(r,n,a)}await this.playAudio(n,e,o)}catch(n){console.error("TTS Error:",n),this.setButtonState(e,"error"),this.showError(e,n.message),setTimeout(()=>this.setButtonState(e,"ready"),3e3),this.isProcessing=!1}}}async generateAudio(e,t){let s={text:e,options:{provider:t.provider,voice:t.voice,speed:t.speed||1}},r={"Content-Type":"application/json"},o=t.apiKey||this.apiKey;console.log("[TTS Widget] Generate Audio - API Key present:",!!o),console.log("[TTS Widget] Generate Audio - this.apiKey:",!!this.apiKey),console.log("[TTS Widget] Generate Audio - options.apiKey:",!!t.apiKey),o?(r.Authorization=`Bearer ${o}`,console.log("[TTS Widget] Generate Audio - Authorization header added")):console.warn("[TTS Widget] Generate Audio - NO API KEY, Authorization header NOT added");try{let n=await fetch(`${this.apiUrl}/api/v1/generate`,{method:"POST",headers:r,body:JSON.stringify(s)});if(!n.ok){let a=await n.json().catch(()=>({}));throw new Error(a.error||`HTTP ${n.status}: ${n.statusText}`)}let i=await n.json();return{audioUrl:`${this.apiUrl}${i.audioUrl}`,hash:i.hash,cached:i.cached,duration:i.duration,cost:i.cost}}catch(n){if(console.error("TTS generation failed:",n),n.message.includes("Failed to fetch")||n.message.includes("NetworkError")){let i=n.message;throw new Error(`TTS API unreachable: ${i}. Check if ${this.apiUrl} is accessible.`)}throw n}}async generateAudioProgressive(e,t,s,r){let o={text:e,options:{provider:t.provider,voice:t.voice,speed:t.speed||1}},n={"Content-Type":"application/json",Accept:"text/event-stream"},i=t.apiKey||this.apiKey;i&&(n.Authorization=`Bearer ${i}`);try{let a=await fetch(`${this.apiUrl}/api/v1/generate-progressive`,{method:"POST",headers:n,body:JSON.stringify(o)});if(!a.ok){let c=await a.json().catch(()=>({}));throw new Error(c.error||`HTTP ${a.status}: ${a.statusText}`)}if(!a.body)throw new Error("No response body for SSE stream");let l=a.body.getReader(),d=new TextDecoder,h="",
|
|
93
|
+
`;let r=i=>{i.addEventListener("mouseenter",()=>{i.style.transform="scale(1.05)",i.style.boxShadow="0 4px 12px rgba(0,0,0,0.4)"}),i.addEventListener("mouseleave",()=>{i.style.transform="scale(1)",i.style.boxShadow="0 2px 8px rgba(0,0,0,0.3)"})};r(s),r(t);let o=()=>{let i=this.cache.size;this.cache.clear(),localStorage.removeItem("supernal-tts-cache"),s.innerHTML=`<span>\u2713</span><span>Cleared ${i}</span><span style="opacity: 0.7; font-size: 10px;">\xD7</span>`,s.style.background="#28a745",setTimeout(()=>{s.innerHTML='<span>\u{1F5D1}\uFE0F</span><span>Clear Cache</span><span style="opacity: 0.7; font-size: 10px;">\xD7</span>',s.style.background="#dc3545"},2e3),console.log(`[Supernal TTS Dev] Cleared ${i} cached items`)};s.addEventListener("click",i=>{i.preventDefault();let a=i.clientX-i.target.getBoundingClientRect().left,l=s.getBoundingClientRect().width;a>l*.8?(s.style.display="none",t.style.display="block",localStorage.setItem("supernal-tts-dev-minimized","true")):o()}),t.addEventListener("click",i=>{i.preventDefault(),t.style.display="none",s.style.display="flex",localStorage.setItem("supernal-tts-dev-minimized","false")}),localStorage.getItem("supernal-tts-dev-minimized")==="true"&&(s.style.display="none",t.style.display="block"),e.appendChild(s),e.appendChild(t),document.body?document.body.appendChild(e):document.addEventListener("DOMContentLoaded",()=>{document.body.appendChild(e)})}async handlePlayClick(e,t,s){let{hash:r,progressBar:o}=s;if(e.classList.contains("supernal-tts-playing")&&this.currentButton===e){this.pauseAudio();return}if(e.classList.contains("supernal-tts-paused")&&this.currentButton===e){this.resumeAudio();return}if(!this.isProcessing){this.currentAudio&&this.currentButton&&this.currentButton!==e&&this.stopAudio();try{this.isProcessing=!0,this.setButtonState(e,"loading");let n=this.getCachedAudioUrl(r);if(!n)if(this.generationMode==="progressive"||this.generationMode==="standard"&&t.length>this.progressiveThreshold){await this.generateAudioProgressive(t,s,e,o);return}else{let a=await this.generateAudio(t,s);n=a.audioUrl.startsWith("http")?a.audioUrl:`${this.apiUrl}${a.audioUrl}`,this.cacheAudioUrl(r,n,a)}await this.playAudio(n,e,o)}catch(n){console.error("TTS Error:",n),this.setButtonState(e,"error"),this.showError(e,n.message),setTimeout(()=>this.setButtonState(e,"ready"),3e3),this.isProcessing=!1}}}async generateAudio(e,t){let s={text:e,options:{provider:t.provider,voice:t.voice,speed:t.speed||1}},r={"Content-Type":"application/json"},o=t.apiKey||this.apiKey;console.log("[TTS Widget] Generate Audio - API Key present:",!!o),console.log("[TTS Widget] Generate Audio - this.apiKey:",!!this.apiKey),console.log("[TTS Widget] Generate Audio - options.apiKey:",!!t.apiKey),o?(r.Authorization=`Bearer ${o}`,console.log("[TTS Widget] Generate Audio - Authorization header added")):console.warn("[TTS Widget] Generate Audio - NO API KEY, Authorization header NOT added");try{let n=await fetch(`${this.apiUrl}/api/v1/generate`,{method:"POST",headers:r,body:JSON.stringify(s)});if(!n.ok){let a=await n.json().catch(()=>({}));throw new Error(a.error||`HTTP ${n.status}: ${n.statusText}`)}let i=await n.json();return{audioUrl:`${this.apiUrl}${i.audioUrl}`,hash:i.hash,cached:i.cached,duration:i.duration,cost:i.cost}}catch(n){if(console.error("TTS generation failed:",n),n.message.includes("Failed to fetch")||n.message.includes("NetworkError")){let i=n.message;throw new Error(`TTS API unreachable: ${i}. Check if ${this.apiUrl} is accessible.`)}throw n}}async generateAudioProgressive(e,t,s,r){let o={text:e,options:{provider:t.provider,voice:t.voice,speed:t.speed||1}},n={"Content-Type":"application/json",Accept:"text/event-stream"},i=t.apiKey||this.apiKey;i&&(n.Authorization=`Bearer ${i}`);try{let a=await fetch(`${this.apiUrl}/api/v1/generate-progressive`,{method:"POST",headers:n,body:JSON.stringify(o)});if(!a.ok){let c=await a.json().catch(()=>({}));throw new Error(c.error||`HTTP ${a.status}: ${a.statusText}`)}if(!a.body)throw new Error("No response body for SSE stream");let l=a.body.getReader(),d=new TextDecoder,h="",v=0,g=0,f=(c,m)=>{if(r){let T=c/m*100,y=r.querySelector(".supernal-tts-progress-slider");y&&(y.value=T.toString());let u=r.querySelector(".current");u&&(u.textContent=`Chunk ${c}/${m}`)}};for(;;){let{done:c,value:m}=await l.read();if(c)break;h+=d.decode(m,{stream:!0});let T=h.split(`
|
|
94
94
|
|
|
95
|
-
`);h=T.pop()||"";for(let y of T)if(y.startsWith("data: "))try{let u=JSON.parse(y.substring(6));switch(u.type){case"started":g=u.totalChunks,console.log(`[Progressive TTS] Started: ${g} chunks`),this.setButtonState(s,"loading");break;case"progress":v=u.completed,console.log(`[Progressive TTS] Progress: ${v}/${g}`),f(v,g);break;case"complete":console.log("[Progressive TTS] Complete:",u);let p=u.audioUrl.startsWith("http")?u.audioUrl:`${this.apiUrl}${u.audioUrl}`;this.cacheAudioUrl(t.hash,p,{hash:u.hash,cached:!1,duration:u.duration,cost:u.cost}),await this.playAudio(p,s,r);break;case"error":throw new Error(u.message||"Progressive generation failed")}}catch(u){console.warn("[Progressive TTS] Failed to parse event:",y,u)}}}catch(a){throw console.error("Progressive TTS generation failed:",a),this.isProcessing=!1,a}}async playAudio(e,t,s,r){return new Promise((o,n)=>{let i=new Audio(e);this.currentAudio=i,this.currentButton=t,this.clientSideSpeed&&(i.preservesPitch=!0,i.mozPreservesPitch=!0,i.webkitPreservesPitch=!0),r!==void 0&&this.clientSideSpeed&&(i.playbackRate=r),this.progressUpdateInterval&&(clearInterval(this.progressUpdateInterval),this.progressUpdateInterval=null),i.addEventListener("loadstart",()=>{this.currentAudio===i&&this.setButtonState(t,"loading")}),i.addEventListener("canplay",()=>{if(this.currentAudio===i){this.setButtonState(t,"playing"),this.isProcessing=!1;let a=i.play();a!==void 0&&a.catch(l=>{console.error("Audio play failed:",l),this.currentAudio===i&&(this.setButtonState(t,"error"),this.currentAudio=null,this.currentButton=null,this.isProcessing=!1,n(new Error("Audio playback failed")))}),s&&(s.classList.add("playing"),this.progressUpdateInterval=window.setInterval(()=>{this.updateProgressBar(i,s)},100))}}),i.addEventListener("ended",()=>{if(this.currentAudio===i){if(this.setButtonState(t,"ready"),this.currentAudio=null,this.currentButton=null,this.progressUpdateInterval&&(clearInterval(this.progressUpdateInterval),this.progressUpdateInterval=null),s){s.classList.remove("playing");let a=s.querySelector(".supernal-tts-progress-slider");a&&(a.value="0");let l=s.querySelector(".supernal-tts-time-display");l&&(l.innerHTML='<span class="current">0:00</span> / <span class="duration">0:00</span>')}o()}}),i.addEventListener("error",a=>{this.currentAudio===i&&(this.setButtonState(t,"error"),this.currentAudio=null,this.currentButton=null,this.progressUpdateInterval&&(clearInterval(this.progressUpdateInterval),this.progressUpdateInterval=null),s&&s.classList.remove("playing"),n(new Error("Audio playback failed")))}),i.load()})}updateProgressBar(e,t){if(!e||!t)return;let s=t.querySelector(".supernal-tts-progress-slider"),r=t.querySelector(".current"),o=t.querySelector(".duration");if(s&&!isNaN(e.duration)){let n=e.currentTime/e.duration*100;s.value=n.toString()}r&&(r.textContent=this.formatTime(e.currentTime)),o&&!isNaN(e.duration)&&(o.textContent=this.formatTime(e.duration))}pauseAudio(){this.currentAudio&&!this.currentAudio.paused&&this.currentAudio.pause(),this.currentButton&&this.setButtonState(this.currentButton,"paused")}resumeAudio(){if(this.currentAudio&&this.currentAudio.paused){let e=this.currentAudio.play();e!==void 0&&e.then(()=>{this.currentButton&&this.setButtonState(this.currentButton,"playing")}).catch(t=>{console.error("Audio resume failed:",t),this.currentButton&&this.setButtonState(this.currentButton,"error")})}}stopAudio(){this.progressUpdateInterval&&(clearInterval(this.progressUpdateInterval),this.progressUpdateInterval=null),this.currentAudio&&(this.currentAudio.pause(),this.currentAudio.currentTime=0,this.currentAudio=null),this.currentButton&&(this.setButtonState(this.currentButton,"ready"),this.currentButton=null),this.isProcessing=!1}cleanStopAudio(e){if(this.progressUpdateInterval&&(clearInterval(this.progressUpdateInterval),this.progressUpdateInterval=null),this.currentAudio&&(this.currentAudio.pause(),this.currentAudio.currentTime=0,this.currentAudio=null),this.currentButton&&(this.setButtonState(this.currentButton,"ready"),this.currentButton=null),e){e.classList.remove("playing");let t=e.querySelector(".supernal-tts-progress-slider");t&&(t.value="0");let s=e.querySelector(".supernal-tts-time-display");s&&(s.innerHTML='<span class="current">0:00</span> / <span class="duration">0:00</span>')}this.isProcessing=!1}cleanStopAudioKeepProgress(e){this.progressUpdateInterval&&(clearInterval(this.progressUpdateInterval),this.progressUpdateInterval=null),this.currentAudio&&(this.currentAudio.pause(),this.currentAudio.currentTime=0,this.currentAudio=null),this.currentButton&&this.setButtonState(this.currentButton,"loading"),this.isProcessing=!1}async handlePlayClickFromPosition(e,t,s,r){let{hash:o,progressBar:n}=s;if(!this.isProcessing)try{this.isProcessing=!0,this.setButtonState(e,"loading");let i=this.getCachedAudioUrl(o);if(!i){let a=await this.generateAudio(t,s);i=a.audioUrl.startsWith("http")?a.audioUrl:`${this.apiUrl}${a.audioUrl}`,this.cacheAudioUrl(o,i,a)}await this.playAudioFromPosition(i,e,n,r)}catch(i){console.error("TTS Error:",i),this.setButtonState(e,"error"),this.showError(e,i.message),setTimeout(()=>this.setButtonState(e,"ready"),3e3),this.isProcessing=!1}}async playAudioFromPosition(e,t,s,r){return new Promise((o,n)=>{let i=new Audio(e);this.currentAudio=i,this.currentButton=t,this.clientSideSpeed&&(i.preservesPitch=!0,i.mozPreservesPitch=!0,i.webkitPreservesPitch=!0),this.progressUpdateInterval&&(clearInterval(this.progressUpdateInterval),this.progressUpdateInterval=null);let a=!1;i.addEventListener("loadstart",()=>{this.currentAudio===i&&this.setButtonState(t,"loading")}),i.addEventListener("loadedmetadata",()=>{this.currentAudio===i&&!a&&r>0&&(i.currentTime=i.duration*r,a=!0)}),i.addEventListener("canplay",()=>{if(this.currentAudio===i){!a&&r>0&&i.duration>0&&(i.currentTime=i.duration*r,a=!0),this.setButtonState(t,"playing"),this.isProcessing=!1;let l=i.play();l!==void 0&&l.catch(d=>{console.error("Audio play failed:",d),this.currentAudio===i&&(this.setButtonState(t,"error"),this.currentAudio=null,this.currentButton=null,this.isProcessing=!1,n(new Error("Audio playback failed")))}),s&&(s.classList.add("playing"),this.progressUpdateInterval=window.setInterval(()=>{this.updateProgressBar(i,s)},100))}}),i.addEventListener("ended",()=>{if(this.currentAudio===i){if(this.setButtonState(t,"ready"),this.currentAudio=null,this.currentButton=null,this.progressUpdateInterval&&(clearInterval(this.progressUpdateInterval),this.progressUpdateInterval=null),s){s.classList.remove("playing");let l=s.querySelector(".supernal-tts-progress-slider");l&&(l.value="0");let d=s.querySelector(".supernal-tts-time-display");d&&(d.innerHTML='<span class="current">0:00</span> / <span class="duration">0:00</span>')}o()}}),i.addEventListener("error",l=>{this.currentAudio===i&&(this.setButtonState(t,"error"),this.currentAudio=null,this.currentButton=null,this.progressUpdateInterval&&(clearInterval(this.progressUpdateInterval),this.progressUpdateInterval=null),s&&s.classList.remove("playing"),n(new Error("Audio playback failed")))}),i.load()})}setButtonState(e,t){e.classList.remove("supernal-tts-loading","supernal-tts-playing","supernal-tts-paused","supernal-tts-error");let s=e.querySelector(".supernal-tts-play-icon"),r=e.querySelector(".supernal-tts-text");switch(t){case"loading":e.classList.add("supernal-tts-loading"),e.disabled=!0,r&&(r.textContent="Loading...");break;case"playing":e.classList.add("supernal-tts-playing"),e.disabled=!1,s&&(s.innerHTML='<rect x="6" y="4" width="4" height="16"/><rect x="14" y="4" width="4" height="16"/>'),r&&(r.textContent="Pause");break;case"paused":e.classList.add("supernal-tts-paused"),e.disabled=!1,s&&(s.innerHTML='<path d="M8 5v14l11-7z"/>'),r&&(r.textContent="Resume");break;case"error":e.classList.add("supernal-tts-error"),e.disabled=!1,s&&(s.innerHTML='<path d="M12 2L2 7v10c0 5.55 3.84 9.95 9 11 5.16-1.05 9-5.45 9-11V7l-10-5z"/>'),r&&(r.textContent="Error");break;default:e.disabled=!1,s&&(s.innerHTML='<path d="M8 5v14l11-7z"/>'),r&&(r.textContent="Listen");break}}showError(e,t){let s=document.createElement("div");s.className="supernal-tts-error-tooltip",t.includes("development mode")?s.textContent=t:t.includes("Failed to fetch")?s.textContent="Service unavailable (dev mode)":s.textContent="Audio generation failed",e.parentNode?.appendChild(s),setTimeout(()=>{s.parentNode&&s.parentNode.removeChild(s)},3e3)}generateHash(e,t={}){let s=e+JSON.stringify(t),r=0;for(let o=0;o<s.length;o++){let n=s.charCodeAt(o);r=(r<<5)-r+n,r=r&r}return Math.abs(r).toString(36)}getCachedAudioUrl(e){let t=this.cache.get(e);if(!t)return null;if(Date.now()>t.expiry)return this.cache.delete(e),this.saveCacheToStorage(),null;let s=t.audioUrl;return s.startsWith("http")?s:`${this.apiUrl}${s}`}cacheAudioUrl(e,t,s={}){this.cache.set(e,{audioUrl:t,metadata:s,expiry:Date.now()+this.cacheExpiry,timestamp:Date.now()}),this.saveCacheToStorage()}loadCacheFromStorage(){try{let e=localStorage.getItem("supernal-tts-cache");if(e){let t=JSON.parse(e);this.cache=new Map(Object.entries(t))}}catch(e){console.warn("Failed to load TTS cache:",e)}}saveCacheToStorage(){try{let e=Object.fromEntries(this.cache);localStorage.setItem("supernal-tts-cache",JSON.stringify(e))}catch(e){console.warn("Failed to save TTS cache:",e)}}static init(e){return window.SupernalTTSInstance?(console.debug("SupernalTTS already initialized, returning existing instance"),window.SupernalTTSInstance):(window.SupernalTTSInstance=new w(e),window.SupernalTTSInstance)}static getInstance(){return window.SupernalTTSInstance}addWidget(e,t,s={}){let r=null;if(typeof e=="string"?r=document.querySelector(e):r=e,!r){console.error("TTS Widget: Element not found");return}r.classList.add("supernal-tts-widget"),r.dataset.text=t,s.voice&&(r.dataset.voice=s.voice),s.provider&&(r.dataset.provider=s.provider),this.setupWidget(r)}};if(typeof window<"u")if(window.SupernalTTS)console.debug("SupernalTTS already loaded, skipping redeclaration");else{window.SupernalTTS=L;let w=document.querySelector("script[data-supernal-tts-auto-init]");if(w&&w.dataset){let e=JSON.parse(w.dataset.supernalTtsAutoInit||"{}");L.init(e)}}var b=L;export{L as SupernalTTS,b as default};
|
|
95
|
+
`);h=T.pop()||"";for(let y of T)if(y.startsWith("data: "))try{let u=JSON.parse(y.substring(6));switch(u.type){case"started":v=u.totalChunks,console.log(`[Progressive TTS] Started: ${v} chunks`),this.setButtonState(s,"loading");break;case"progress":g=u.completed,console.log(`[Progressive TTS] Progress: ${g}/${v}`),f(g,v);break;case"complete":console.log("[Progressive TTS] Complete:",u);let p=u.audioUrl.startsWith("http")?u.audioUrl:`${this.apiUrl}${u.audioUrl}`;this.cacheAudioUrl(t.hash,p,{hash:u.hash,cached:!1,duration:u.duration,cost:u.cost}),await this.playAudio(p,s,r);break;case"error":throw new Error(u.message||"Progressive generation failed")}}catch(u){console.warn("[Progressive TTS] Failed to parse event:",y,u)}}}catch(a){throw console.error("Progressive TTS generation failed:",a),this.isProcessing=!1,a}}async playAudio(e,t,s,r){return new Promise((o,n)=>{let i=new Audio(e);this.currentAudio=i,this.currentButton=t,this.clientSideSpeed&&(i.preservesPitch=!0,i.mozPreservesPitch=!0,i.webkitPreservesPitch=!0),r!==void 0&&this.clientSideSpeed&&(i.playbackRate=r),this.progressUpdateInterval&&(clearInterval(this.progressUpdateInterval),this.progressUpdateInterval=null),i.addEventListener("loadstart",()=>{this.currentAudio===i&&this.setButtonState(t,"loading")}),i.addEventListener("canplay",()=>{if(this.currentAudio===i){this.setButtonState(t,"playing"),this.isProcessing=!1;let a=i.play();a!==void 0&&a.catch(l=>{console.error("Audio play failed:",l),this.currentAudio===i&&(this.setButtonState(t,"error"),this.currentAudio=null,this.currentButton=null,this.isProcessing=!1,n(new Error("Audio playback failed")))}),s&&(s.classList.add("playing"),this.progressUpdateInterval=window.setInterval(()=>{this.updateProgressBar(i,s)},100))}}),i.addEventListener("ended",()=>{if(this.currentAudio===i){if(this.setButtonState(t,"ready"),this.currentAudio=null,this.currentButton=null,this.progressUpdateInterval&&(clearInterval(this.progressUpdateInterval),this.progressUpdateInterval=null),s){s.classList.remove("playing");let a=s.querySelector(".supernal-tts-progress-slider");a&&(a.value="0");let l=s.querySelector(".supernal-tts-time-display");l&&(l.innerHTML='<span class="current">0:00</span> / <span class="duration">0:00</span>')}o()}}),i.addEventListener("error",a=>{this.currentAudio===i&&(this.setButtonState(t,"error"),this.currentAudio=null,this.currentButton=null,this.progressUpdateInterval&&(clearInterval(this.progressUpdateInterval),this.progressUpdateInterval=null),s&&s.classList.remove("playing"),n(new Error("Audio playback failed")))}),i.load()})}updateProgressBar(e,t){if(!e||!t)return;let s=t.querySelector(".supernal-tts-progress-slider"),r=t.querySelector(".current"),o=t.querySelector(".duration");if(s&&!isNaN(e.duration)){let n=e.currentTime/e.duration*100;s.value=n.toString()}r&&(r.textContent=this.formatTime(e.currentTime)),o&&!isNaN(e.duration)&&(o.textContent=this.formatTime(e.duration))}pauseAudio(){this.currentAudio&&!this.currentAudio.paused&&this.currentAudio.pause(),this.currentButton&&this.setButtonState(this.currentButton,"paused")}resumeAudio(){if(this.currentAudio&&this.currentAudio.paused){let e=this.currentAudio.play();e!==void 0&&e.then(()=>{this.currentButton&&this.setButtonState(this.currentButton,"playing")}).catch(t=>{console.error("Audio resume failed:",t),this.currentButton&&this.setButtonState(this.currentButton,"error")})}}stopAudio(){this.progressUpdateInterval&&(clearInterval(this.progressUpdateInterval),this.progressUpdateInterval=null),this.currentAudio&&(this.currentAudio.pause(),this.currentAudio.currentTime=0,this.currentAudio=null),this.currentButton&&(this.setButtonState(this.currentButton,"ready"),this.currentButton=null),this.isProcessing=!1}cleanStopAudio(e){if(this.progressUpdateInterval&&(clearInterval(this.progressUpdateInterval),this.progressUpdateInterval=null),this.currentAudio&&(this.currentAudio.pause(),this.currentAudio.currentTime=0,this.currentAudio=null),this.currentButton&&(this.setButtonState(this.currentButton,"ready"),this.currentButton=null),e){e.classList.remove("playing");let t=e.querySelector(".supernal-tts-progress-slider");t&&(t.value="0");let s=e.querySelector(".supernal-tts-time-display");s&&(s.innerHTML='<span class="current">0:00</span> / <span class="duration">0:00</span>')}this.isProcessing=!1}cleanStopAudioKeepProgress(e){this.progressUpdateInterval&&(clearInterval(this.progressUpdateInterval),this.progressUpdateInterval=null),this.currentAudio&&(this.currentAudio.pause(),this.currentAudio.currentTime=0,this.currentAudio=null),this.currentButton&&this.setButtonState(this.currentButton,"loading"),this.isProcessing=!1}async handlePlayClickFromPosition(e,t,s,r){let{hash:o,progressBar:n}=s;if(!this.isProcessing)try{this.isProcessing=!0,this.setButtonState(e,"loading");let i=this.getCachedAudioUrl(o);if(!i){let a=await this.generateAudio(t,s);i=a.audioUrl.startsWith("http")?a.audioUrl:`${this.apiUrl}${a.audioUrl}`,this.cacheAudioUrl(o,i,a)}await this.playAudioFromPosition(i,e,n,r)}catch(i){console.error("TTS Error:",i),this.setButtonState(e,"error"),this.showError(e,i.message),setTimeout(()=>this.setButtonState(e,"ready"),3e3),this.isProcessing=!1}}async playAudioFromPosition(e,t,s,r){return new Promise((o,n)=>{let i=new Audio(e);this.currentAudio=i,this.currentButton=t,this.clientSideSpeed&&(i.preservesPitch=!0,i.mozPreservesPitch=!0,i.webkitPreservesPitch=!0),this.progressUpdateInterval&&(clearInterval(this.progressUpdateInterval),this.progressUpdateInterval=null);let a=!1;i.addEventListener("loadstart",()=>{this.currentAudio===i&&this.setButtonState(t,"loading")}),i.addEventListener("loadedmetadata",()=>{this.currentAudio===i&&!a&&r>0&&(i.currentTime=i.duration*r,a=!0)}),i.addEventListener("canplay",()=>{if(this.currentAudio===i){!a&&r>0&&i.duration>0&&(i.currentTime=i.duration*r,a=!0),this.setButtonState(t,"playing"),this.isProcessing=!1;let l=i.play();l!==void 0&&l.catch(d=>{console.error("Audio play failed:",d),this.currentAudio===i&&(this.setButtonState(t,"error"),this.currentAudio=null,this.currentButton=null,this.isProcessing=!1,n(new Error("Audio playback failed")))}),s&&(s.classList.add("playing"),this.progressUpdateInterval=window.setInterval(()=>{this.updateProgressBar(i,s)},100))}}),i.addEventListener("ended",()=>{if(this.currentAudio===i){if(this.setButtonState(t,"ready"),this.currentAudio=null,this.currentButton=null,this.progressUpdateInterval&&(clearInterval(this.progressUpdateInterval),this.progressUpdateInterval=null),s){s.classList.remove("playing");let l=s.querySelector(".supernal-tts-progress-slider");l&&(l.value="0");let d=s.querySelector(".supernal-tts-time-display");d&&(d.innerHTML='<span class="current">0:00</span> / <span class="duration">0:00</span>')}o()}}),i.addEventListener("error",l=>{this.currentAudio===i&&(this.setButtonState(t,"error"),this.currentAudio=null,this.currentButton=null,this.progressUpdateInterval&&(clearInterval(this.progressUpdateInterval),this.progressUpdateInterval=null),s&&s.classList.remove("playing"),n(new Error("Audio playback failed")))}),i.load()})}setButtonState(e,t){e.classList.remove("supernal-tts-loading","supernal-tts-playing","supernal-tts-paused","supernal-tts-error");let s=e.querySelector(".supernal-tts-play-icon"),r=e.querySelector(".supernal-tts-text");switch(t){case"loading":e.classList.add("supernal-tts-loading"),e.disabled=!0,r&&(r.textContent="Loading...");break;case"playing":e.classList.add("supernal-tts-playing"),e.disabled=!1,s&&(s.innerHTML='<rect x="6" y="4" width="4" height="16"/><rect x="14" y="4" width="4" height="16"/>'),r&&(r.textContent="Pause");break;case"paused":e.classList.add("supernal-tts-paused"),e.disabled=!1,s&&(s.innerHTML='<path d="M8 5v14l11-7z"/>'),r&&(r.textContent="Resume");break;case"error":e.classList.add("supernal-tts-error"),e.disabled=!1,s&&(s.innerHTML='<path d="M12 2L2 7v10c0 5.55 3.84 9.95 9 11 5.16-1.05 9-5.45 9-11V7l-10-5z"/>'),r&&(r.textContent="Error");break;default:e.disabled=!1,s&&(s.innerHTML='<path d="M8 5v14l11-7z"/>'),r&&(r.textContent="Listen");break}}showError(e,t){let s=document.createElement("div");s.className="supernal-tts-error-tooltip",t.includes("development mode")?s.textContent=t:t.includes("Failed to fetch")?s.textContent="Service unavailable (dev mode)":s.textContent="Audio generation failed",e.parentNode?.appendChild(s),setTimeout(()=>{s.parentNode&&s.parentNode.removeChild(s)},3e3)}generateHash(e,t={}){let s=e+JSON.stringify(t),r=0;for(let o=0;o<s.length;o++){let n=s.charCodeAt(o);r=(r<<5)-r+n,r=r&r}return Math.abs(r).toString(36)}getCachedAudioUrl(e){let t=this.cache.get(e);if(!t)return null;if(Date.now()>t.expiry)return this.cache.delete(e),this.saveCacheToStorage(),null;let s=t.audioUrl;return s.startsWith("http")?s:`${this.apiUrl}${s}`}cacheAudioUrl(e,t,s={}){this.cache.set(e,{audioUrl:t,metadata:s,expiry:Date.now()+this.cacheExpiry,timestamp:Date.now()}),this.saveCacheToStorage()}loadCacheFromStorage(){try{let e=localStorage.getItem("supernal-tts-cache");if(e){let t=JSON.parse(e);this.cache=new Map(Object.entries(t))}}catch(e){console.warn("Failed to load TTS cache:",e)}}saveCacheToStorage(){try{let e=Object.fromEntries(this.cache);localStorage.setItem("supernal-tts-cache",JSON.stringify(e))}catch(e){console.warn("Failed to save TTS cache:",e)}}static init(e){return window.SupernalTTSInstance?(console.debug("SupernalTTS already initialized, returning existing instance"),window.SupernalTTSInstance):(window.SupernalTTSInstance=new w(e),window.SupernalTTSInstance)}static getInstance(){return window.SupernalTTSInstance}addWidget(e,t,s={}){let r=null;if(typeof e=="string"?r=document.querySelector(e):r=e,!r){console.error("TTS Widget: Element not found");return}r.classList.add("supernal-tts-widget"),r.dataset.text=this.scrubText(t),s.voice&&(r.dataset.voice=s.voice),s.provider&&(r.dataset.provider=s.provider),this.setupWidget(r)}};if(typeof window<"u")if(window.SupernalTTS)console.debug("SupernalTTS already loaded, skipping redeclaration");else{window.SupernalTTS=L;let w=document.querySelector("script[data-supernal-tts-auto-init]");if(w&&w.dataset){let e=JSON.parse(w.dataset.supernalTtsAutoInit||"{}");L.init(e)}}var A=L;export{L as SupernalTTS,A as default};
|
|
96
96
|
//# sourceMappingURL=widget.js.map
|