@creativeorange/azure-text-to-speech 3.0.2 → 3.0.4
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/TextToSpeech.d.ts
CHANGED
|
@@ -75,6 +75,12 @@ export declare class TextToSpeech {
|
|
|
75
75
|
private startHighlightingInterval;
|
|
76
76
|
private updateHighlightForCurrentTime;
|
|
77
77
|
private highlightTextRange;
|
|
78
|
+
private getSpokenTextDomOffset;
|
|
79
|
+
private isRangeVisuallyVisible;
|
|
80
|
+
private getClippingRect;
|
|
81
|
+
private isClippingElement;
|
|
82
|
+
private isClippingOverflowValue;
|
|
83
|
+
private rectsOverlap;
|
|
78
84
|
private setHighlightTargetFromNode;
|
|
79
85
|
private shouldHighlight;
|
|
80
86
|
private resetHighlightState;
|
package/dist/co-azure-tts.es.js
CHANGED
|
@@ -9188,7 +9188,8 @@ class TextToSpeech {
|
|
|
9188
9188
|
segment.highlightDiv,
|
|
9189
9189
|
segment.originalHighlightDivInnerHTML,
|
|
9190
9190
|
relativeTextOffset,
|
|
9191
|
-
wordBoundary.wordLength
|
|
9191
|
+
wordBoundary.wordLength,
|
|
9192
|
+
segment.text
|
|
9192
9193
|
);
|
|
9193
9194
|
this.previousWordBoundary = wordBoundary;
|
|
9194
9195
|
}
|
|
@@ -9437,17 +9438,20 @@ class TextToSpeech {
|
|
|
9437
9438
|
this.highlightDiv,
|
|
9438
9439
|
this.originalHighlightDivInnerHTML,
|
|
9439
9440
|
normalizedTextOffset,
|
|
9440
|
-
wordBoundary.wordLength
|
|
9441
|
+
wordBoundary.wordLength,
|
|
9442
|
+
this.textToRead
|
|
9441
9443
|
);
|
|
9442
9444
|
this.previousWordBoundary = wordBoundary;
|
|
9443
9445
|
this.currentWord = wordBoundary.text;
|
|
9444
9446
|
this.wordBoundaryOffset = wordBoundary.textOffset;
|
|
9445
9447
|
}
|
|
9446
|
-
highlightTextRange(target, originalHtml, textOffset, wordLength) {
|
|
9447
|
-
if (!target || wordLength <= 0) {
|
|
9448
|
+
highlightTextRange(target, originalHtml, textOffset, wordLength, spokenText) {
|
|
9449
|
+
if (!target || wordLength <= 0 || textOffset < 0) {
|
|
9448
9450
|
return;
|
|
9449
9451
|
}
|
|
9450
9452
|
target.innerHTML = originalHtml;
|
|
9453
|
+
const alignmentOffset = this.getSpokenTextDomOffset(target, spokenText);
|
|
9454
|
+
const mappedOffset = textOffset + alignmentOffset;
|
|
9451
9455
|
const walker = document.createTreeWalker(
|
|
9452
9456
|
target,
|
|
9453
9457
|
NodeFilter.SHOW_TEXT
|
|
@@ -9457,15 +9461,15 @@ class TextToSpeech {
|
|
|
9457
9461
|
let endNode;
|
|
9458
9462
|
let startOffset = 0;
|
|
9459
9463
|
let endOffset = 0;
|
|
9460
|
-
const requestedEnd =
|
|
9464
|
+
const requestedEnd = mappedOffset + wordLength;
|
|
9461
9465
|
while (walker.nextNode()) {
|
|
9462
9466
|
const node = walker.currentNode;
|
|
9463
9467
|
const nodeLength = node.data.length;
|
|
9464
9468
|
const nodeStart = currentOffset;
|
|
9465
9469
|
const nodeEnd = currentOffset + nodeLength;
|
|
9466
|
-
if (!startNode &&
|
|
9470
|
+
if (!startNode && mappedOffset >= nodeStart && mappedOffset < nodeEnd) {
|
|
9467
9471
|
startNode = node;
|
|
9468
|
-
startOffset =
|
|
9472
|
+
startOffset = mappedOffset - nodeStart;
|
|
9469
9473
|
}
|
|
9470
9474
|
if (requestedEnd > nodeStart && requestedEnd <= nodeEnd) {
|
|
9471
9475
|
endNode = node;
|
|
@@ -9481,6 +9485,9 @@ class TextToSpeech {
|
|
|
9481
9485
|
try {
|
|
9482
9486
|
range.setStart(startNode, startOffset);
|
|
9483
9487
|
range.setEnd(endNode, endOffset);
|
|
9488
|
+
if (!this.isRangeVisuallyVisible(range, target)) {
|
|
9489
|
+
return;
|
|
9490
|
+
}
|
|
9484
9491
|
const mark = document.createElement("mark");
|
|
9485
9492
|
mark.className = "co-tts-highlight";
|
|
9486
9493
|
mark.appendChild(range.extractContents());
|
|
@@ -9489,6 +9496,67 @@ class TextToSpeech {
|
|
|
9489
9496
|
target.innerHTML = originalHtml;
|
|
9490
9497
|
}
|
|
9491
9498
|
}
|
|
9499
|
+
getSpokenTextDomOffset(target, spokenText) {
|
|
9500
|
+
var _a;
|
|
9501
|
+
if (!spokenText) {
|
|
9502
|
+
return 0;
|
|
9503
|
+
}
|
|
9504
|
+
const targetText = (_a = target.textContent) != null ? _a : "";
|
|
9505
|
+
if (targetText === "" || targetText === spokenText) {
|
|
9506
|
+
return 0;
|
|
9507
|
+
}
|
|
9508
|
+
const index = targetText.indexOf(spokenText);
|
|
9509
|
+
return index >= 0 ? index : 0;
|
|
9510
|
+
}
|
|
9511
|
+
isRangeVisuallyVisible(range, target) {
|
|
9512
|
+
if (typeof range.getClientRects !== "function") {
|
|
9513
|
+
return true;
|
|
9514
|
+
}
|
|
9515
|
+
let rects;
|
|
9516
|
+
try {
|
|
9517
|
+
rects = Array.from(range.getClientRects()).filter(
|
|
9518
|
+
(rect) => rect.width > 0 && rect.height > 0
|
|
9519
|
+
);
|
|
9520
|
+
} catch {
|
|
9521
|
+
return true;
|
|
9522
|
+
}
|
|
9523
|
+
if (rects.length === 0) {
|
|
9524
|
+
return true;
|
|
9525
|
+
}
|
|
9526
|
+
const clipRect = this.getClippingRect(target);
|
|
9527
|
+
return rects.some((rect) => this.rectsOverlap(rect, clipRect));
|
|
9528
|
+
}
|
|
9529
|
+
getClippingRect(target) {
|
|
9530
|
+
let clipElement = target;
|
|
9531
|
+
while (clipElement) {
|
|
9532
|
+
if (this.isClippingElement(clipElement)) {
|
|
9533
|
+
return clipElement.getBoundingClientRect();
|
|
9534
|
+
}
|
|
9535
|
+
clipElement = clipElement.parentElement;
|
|
9536
|
+
}
|
|
9537
|
+
return target.getBoundingClientRect();
|
|
9538
|
+
}
|
|
9539
|
+
isClippingElement(element) {
|
|
9540
|
+
var _a;
|
|
9541
|
+
const style = (_a = globalThis.getComputedStyle) == null ? void 0 : _a.call(globalThis, element);
|
|
9542
|
+
if (!style) {
|
|
9543
|
+
return false;
|
|
9544
|
+
}
|
|
9545
|
+
const overflowX = style.overflowX || style.overflow;
|
|
9546
|
+
const overflowY = style.overflowY || style.overflow;
|
|
9547
|
+
const clipsOverflow = this.isClippingOverflowValue(overflowX) || this.isClippingOverflowValue(overflowY);
|
|
9548
|
+
if (clipsOverflow) {
|
|
9549
|
+
return true;
|
|
9550
|
+
}
|
|
9551
|
+
const lineClamp = style.getPropertyValue("-webkit-line-clamp").trim();
|
|
9552
|
+
return lineClamp !== "" && lineClamp !== "none";
|
|
9553
|
+
}
|
|
9554
|
+
isClippingOverflowValue(value) {
|
|
9555
|
+
return value === "hidden" || value === "auto" || value === "scroll" || value === "clip";
|
|
9556
|
+
}
|
|
9557
|
+
rectsOverlap(a, b) {
|
|
9558
|
+
return a.right > b.left && a.left < b.right && a.bottom > b.top && a.top < b.bottom;
|
|
9559
|
+
}
|
|
9492
9560
|
setHighlightTargetFromNode(node) {
|
|
9493
9561
|
var _a;
|
|
9494
9562
|
const highlightDiv = this.getHighlightDivForNode(node);
|