@ztimson/utils 0.28.11 → 0.28.13
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/dist/index.cjs +71 -24
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +71 -24
- package/dist/index.mjs.map +1 -1
- package/dist/tts.d.ts +2 -23
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -2326,7 +2326,68 @@ ${opts.message || this.desc}`;
|
|
|
2326
2326
|
function findTemplateVars(html) {
|
|
2327
2327
|
const variables = /* @__PURE__ */ new Set();
|
|
2328
2328
|
const arrays = /* @__PURE__ */ new Set();
|
|
2329
|
-
const excluded = /* @__PURE__ */ new Set([
|
|
2329
|
+
const excluded = /* @__PURE__ */ new Set([
|
|
2330
|
+
"let",
|
|
2331
|
+
"const",
|
|
2332
|
+
"var",
|
|
2333
|
+
"function",
|
|
2334
|
+
"if",
|
|
2335
|
+
"while",
|
|
2336
|
+
"do",
|
|
2337
|
+
"this",
|
|
2338
|
+
"typeof",
|
|
2339
|
+
"new",
|
|
2340
|
+
"instanceof",
|
|
2341
|
+
"in",
|
|
2342
|
+
"for",
|
|
2343
|
+
"else",
|
|
2344
|
+
"case",
|
|
2345
|
+
"break",
|
|
2346
|
+
"continue",
|
|
2347
|
+
"switch",
|
|
2348
|
+
"default",
|
|
2349
|
+
"with",
|
|
2350
|
+
"eval",
|
|
2351
|
+
"arguments",
|
|
2352
|
+
"void",
|
|
2353
|
+
"delete",
|
|
2354
|
+
"null",
|
|
2355
|
+
"undefined",
|
|
2356
|
+
"true",
|
|
2357
|
+
"false",
|
|
2358
|
+
"async",
|
|
2359
|
+
"await",
|
|
2360
|
+
"try",
|
|
2361
|
+
"catch",
|
|
2362
|
+
"finally",
|
|
2363
|
+
"throw",
|
|
2364
|
+
"return",
|
|
2365
|
+
"yield",
|
|
2366
|
+
"debugger",
|
|
2367
|
+
"extends",
|
|
2368
|
+
"import",
|
|
2369
|
+
"export",
|
|
2370
|
+
"class",
|
|
2371
|
+
"super",
|
|
2372
|
+
"static",
|
|
2373
|
+
"get",
|
|
2374
|
+
"set",
|
|
2375
|
+
"constructor",
|
|
2376
|
+
"enum",
|
|
2377
|
+
"implements",
|
|
2378
|
+
"interface",
|
|
2379
|
+
"package",
|
|
2380
|
+
"private",
|
|
2381
|
+
"protected",
|
|
2382
|
+
"public",
|
|
2383
|
+
"abstract",
|
|
2384
|
+
"final",
|
|
2385
|
+
"native",
|
|
2386
|
+
"synchronized",
|
|
2387
|
+
"throws",
|
|
2388
|
+
"transient",
|
|
2389
|
+
"volatile"
|
|
2390
|
+
]);
|
|
2330
2391
|
for (const loop of matchAll(html, /\{\{\s*?\*\s*?(.+?)\s+in\s+(.+?)\s*?}}/g)) {
|
|
2331
2392
|
const [element, index = "index"] = loop[1].replaceAll(/[()\s]/g, "").split(",");
|
|
2332
2393
|
excluded.add(element);
|
|
@@ -2537,6 +2598,7 @@ ${err.message || err.toString()}`);
|
|
|
2537
2598
|
}
|
|
2538
2599
|
class TTS {
|
|
2539
2600
|
static QUALITY_PATTERNS = ["Google", "Microsoft", "Samantha", "Premium", "Natural", "Neural"];
|
|
2601
|
+
static _errorHandlerInstalled = false;
|
|
2540
2602
|
_currentUtterance = null;
|
|
2541
2603
|
_voicesLoaded;
|
|
2542
2604
|
_stoppedUtterances = /* @__PURE__ */ new WeakSet();
|
|
@@ -2572,8 +2634,8 @@ ${err.message || err.toString()}`);
|
|
|
2572
2634
|
this._voice = value;
|
|
2573
2635
|
if (this._currentUtterance && value) this._currentUtterance.voice = value;
|
|
2574
2636
|
}
|
|
2575
|
-
/** Create a TTS instance with optional configuration */
|
|
2576
2637
|
constructor(config) {
|
|
2638
|
+
TTS.installErrorHandler();
|
|
2577
2639
|
this._voicesLoaded = this.initializeVoices();
|
|
2578
2640
|
if (config) {
|
|
2579
2641
|
if (config.rate !== void 0) this._rate = config.rate;
|
|
@@ -2582,7 +2644,13 @@ ${err.message || err.toString()}`);
|
|
|
2582
2644
|
this._voice = config.voice === null ? void 0 : config.voice || void 0;
|
|
2583
2645
|
}
|
|
2584
2646
|
}
|
|
2585
|
-
|
|
2647
|
+
static installErrorHandler() {
|
|
2648
|
+
if (this._errorHandlerInstalled) return;
|
|
2649
|
+
window.addEventListener("unhandledrejection", (event) => {
|
|
2650
|
+
if (event.reason?.error === "interrupted" && event.reason instanceof SpeechSynthesisErrorEvent) event.preventDefault();
|
|
2651
|
+
});
|
|
2652
|
+
this._errorHandlerInstalled = true;
|
|
2653
|
+
}
|
|
2586
2654
|
initializeVoices() {
|
|
2587
2655
|
return new Promise((resolve) => {
|
|
2588
2656
|
const voices = window.speechSynthesis.getVoices();
|
|
@@ -2599,11 +2667,6 @@ ${err.message || err.toString()}`);
|
|
|
2599
2667
|
}
|
|
2600
2668
|
});
|
|
2601
2669
|
}
|
|
2602
|
-
/**
|
|
2603
|
-
* Selects the best available TTS voice, prioritizing high-quality options
|
|
2604
|
-
* @param lang Speaking language
|
|
2605
|
-
* @returns Highest quality voice
|
|
2606
|
-
*/
|
|
2607
2670
|
static bestVoice(lang = "en") {
|
|
2608
2671
|
const voices = window.speechSynthesis.getVoices();
|
|
2609
2672
|
for (const pattern of this.QUALITY_PATTERNS) {
|
|
@@ -2612,11 +2675,9 @@ ${err.message || err.toString()}`);
|
|
|
2612
2675
|
}
|
|
2613
2676
|
return voices.find((v) => v.lang.startsWith(lang));
|
|
2614
2677
|
}
|
|
2615
|
-
/** Cleans text for TTS by removing emojis, markdown and code block */
|
|
2616
2678
|
static cleanText(text) {
|
|
2617
2679
|
return removeEmojis(text).replace(/```[\s\S]*?```/g, " code block ").replace(/[#*_~`]/g, "");
|
|
2618
2680
|
}
|
|
2619
|
-
/** Creates a speech utterance with current options */
|
|
2620
2681
|
createUtterance(text) {
|
|
2621
2682
|
const cleanedText = TTS.cleanText(text);
|
|
2622
2683
|
const utterance = new SpeechSynthesisUtterance(cleanedText);
|
|
@@ -2627,7 +2688,6 @@ ${err.message || err.toString()}`);
|
|
|
2627
2688
|
utterance.volume = this._volume;
|
|
2628
2689
|
return utterance;
|
|
2629
2690
|
}
|
|
2630
|
-
/** Speaks text and returns a Promise which resolves once complete */
|
|
2631
2691
|
async speak(text) {
|
|
2632
2692
|
if (!text.trim()) return Promise.resolve();
|
|
2633
2693
|
await this._voicesLoaded;
|
|
@@ -2646,24 +2706,11 @@ ${err.message || err.toString()}`);
|
|
|
2646
2706
|
window.speechSynthesis.speak(utterance);
|
|
2647
2707
|
});
|
|
2648
2708
|
}
|
|
2649
|
-
/** Stops all TTS */
|
|
2650
2709
|
stop() {
|
|
2651
2710
|
if (this._currentUtterance) this._stoppedUtterances.add(this._currentUtterance);
|
|
2652
2711
|
window.speechSynthesis.cancel();
|
|
2653
2712
|
this._currentUtterance = null;
|
|
2654
2713
|
}
|
|
2655
|
-
/**
|
|
2656
|
-
* Initialize a stream that chunks text into sentences and speak them.
|
|
2657
|
-
*
|
|
2658
|
-
* @example
|
|
2659
|
-
* const stream = tts.speakStream();
|
|
2660
|
-
* stream.next("Hello ");
|
|
2661
|
-
* stream.next("World. How");
|
|
2662
|
-
* stream.next(" are you?");
|
|
2663
|
-
* await stream.done();
|
|
2664
|
-
*
|
|
2665
|
-
* @returns Object with next function for passing chunk of streamed text and done for completing the stream
|
|
2666
|
-
*/
|
|
2667
2714
|
speakStream() {
|
|
2668
2715
|
let buffer = "";
|
|
2669
2716
|
let streamPromise = Promise.resolve();
|