diff options
-rw-r--r-- | ext/fg/js/client.js | 94 |
1 files changed, 72 insertions, 22 deletions
diff --git a/ext/fg/js/client.js b/ext/fg/js/client.js index 9806b96a..2c46e9cf 100644 --- a/ext/fg/js/client.js +++ b/ext/fg/js/client.js @@ -78,29 +78,8 @@ class Client { } } - textSourceFromPoint(point) { - const element = document.elementFromPoint(point.x, point.y); - if (element !== null) { - switch (element.nodeName) { - case 'IMG': - return new TextSourceImage(element); - case 'INPUT': - case 'BUTTON': - case 'TEXTAREA': - return new TextSourceInput(element); - } - } - - const range = document.caretRangeFromPoint(point.x, point.y); - if (range !== null) { - return new TextSourceRange(range); - } - - return null; - } - searchAt(point) { - const textSource = this.textSourceFromPoint(point); + const textSource = Client.textSourceFromPoint(point); if (textSource === null || !textSource.containsPoint(point)) { this.hidePopup(); return; @@ -218,6 +197,77 @@ class Client { ); }); } + + static textSourceFromPoint(point) { + const element = document.elementFromPoint(point.x, point.y); + if (element !== null) { + switch (element.nodeName) { + case 'IMG': + return new TextSourceImage(element); + case 'INPUT': + case 'BUTTON': + case 'TEXTAREA': + return new TextSourceInput(element); + } + } + + const range = document.caretRangeFromPoint(point.x, point.y); + if (range !== null) { + return new TextSourceRange(range); + } + + return null; + } + + static extractSentence(content, position) { + const quotesFwd = {'「': '」', '『': '』', "'": "'", '"': '"'}; + const quotesBwd = {'」': '「', '』': '『', "'": "'", '"': '"'}; + const terminators = '…。..??!!'; + + let quoteStack = []; + + let startPos = 0; + for (let i = position; i >= startPos; --i) { + const c = content[i]; + + if (quoteStack.length === 0 && (terminators.indexOf(c) !== -1 || c in quotesFwd)) { + startPos = i + 1; + break; + } + + if (quoteStack.length > 0 && c === quoteStack[0]) { + quoteStack.pop(); + } else if (c in quotesBwd) { + quoteStack = [quotesBwd[c]].concat(quoteStack); + } + } + + quoteStack = []; + + let endPos = content.length; + for (let i = position; i < endPos; ++i) { + const c = content[i]; + + if (quoteStack.length === 0) { + if (terminators.indexOf(c) !== -1) { + endPos = i + 1; + break; + } + else if (c in quotesBwd) { + endPos = i; + break; + } + } + + if (quoteStack.length > 0 && c === quoteStack[0]) { + quoteStack.pop(); + } else if (c in quotesFwd) { + quoteStack = [quotesFwd[c]].concat(quoteStack); + } + } + + return content.substring(startPos, endPos).trim(); + } } window.yomiClient = new Client(); |