diff options
Diffstat (limited to 'ext/fg/js/util.js')
| -rw-r--r-- | ext/fg/js/util.js | 114 | 
1 files changed, 114 insertions, 0 deletions
| diff --git a/ext/fg/js/util.js b/ext/fg/js/util.js new file mode 100644 index 00000000..176765fc --- /dev/null +++ b/ext/fg/js/util.js @@ -0,0 +1,114 @@ +/* + * Copyright (C) 2016  Alex Yatskov <alex@foosoft.net> + * Author: Alex Yatskov <alex@foosoft.net> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program.  If not, see <http://www.gnu.org/licenses/>. + */ + + +function sendMessage(action, params) { +    return new Promise((resolve, reject) => chrome.runtime.sendMessage({action, params}, resolve)); +} + +function findTerm(text) { +    return sendMessage('findTerm', {text}); +} + +function findKanji(text) { +    return sendMessage('findKanji', {text}); +} + +function renderText(data, template) { +    return sendMessage('renderText', {data, template}); +} + +function canAddDefinitions(definitions, modes) { +    return sendMessage('canAddDefinitions', {definitions, modes}); +} + +function addDefinition(definition, mode) { +    return sendMessage('addDefinition', {definition, mode}); +} + +function textSourceFromPoint(point) { +    const element = document.elementFromPoint(point.x, point.y); +    if (element !== null) { +        const names = ['IMG', 'INPUT', 'BUTTON', 'TEXTAREA']; +        if (names.includes(element.nodeName)) { +            return new TextSourceElement(element); +        } +    } + +    const range = document.caretRangeFromPoint(point.x, point.y); +    if (range !== null) { +        return new TextSourceRange(range); +    } + +    return null; +} + +function extractSentence(source, extent) { +    const quotesFwd = {'「': '」', '『': '』', "'": "'", '"': '"'}; +    const quotesBwd = {'」': '「', '』': '『', "'": "'", '"': '"'}; +    const terminators = '…。..??!!'; + +    const sourceLocal = source.clone(); +    const position = sourceLocal.setStartOffset(extent); +    sourceLocal.setEndOffset(position + extent); +    const content = sourceLocal.text(); + +    let quoteStack = []; + +    let startPos = 0; +    for (let i = position; i >= startPos; --i) { +        const c = content[i]; + +        if (quoteStack.length === 0 && (terminators.includes(c) || 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.includes(c)) { +                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(); +} |