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