diff options
Diffstat (limited to 'ext/bg')
-rw-r--r-- | ext/bg/background.html | 1 | ||||
-rw-r--r-- | ext/bg/js/api.js | 5 | ||||
-rw-r--r-- | ext/bg/js/backend-api-forwarder.js | 45 | ||||
-rw-r--r-- | ext/bg/js/backend.js | 6 | ||||
-rw-r--r-- | ext/bg/js/dictionary.js | 11 | ||||
-rw-r--r-- | ext/bg/js/options.js | 5 | ||||
-rw-r--r-- | ext/bg/js/search-frontend.js | 51 | ||||
-rw-r--r-- | ext/bg/js/settings.js | 6 | ||||
-rw-r--r-- | ext/bg/js/translator.js | 17 | ||||
-rw-r--r-- | ext/bg/search.html | 1 | ||||
-rw-r--r-- | ext/bg/settings.html | 13 |
11 files changed, 149 insertions, 12 deletions
diff --git a/ext/bg/background.html b/ext/bg/background.html index 5978f10f..90a56024 100644 --- a/ext/bg/background.html +++ b/ext/bg/background.html @@ -15,6 +15,7 @@ <script src="/bg/js/anki.js"></script> <script src="/bg/js/api.js"></script> <script src="/bg/js/audio.js"></script> + <script src="/bg/js/backend-api-forwarder.js"></script> <script src="/bg/js/database.js"></script> <script src="/bg/js/deinflector.js"></script> <script src="/bg/js/dictionary.js"></script> diff --git a/ext/bg/js/api.js b/ext/bg/js/api.js index 4b2bacd7..b8ef4362 100644 --- a/ext/bg/js/api.js +++ b/ext/bg/js/api.js @@ -205,3 +205,8 @@ function apiForward(action, params, sender) { chrome.tabs.sendMessage(tabId, {action, params}, (response) => resolve(response)); }); } + +function apiFrameInformationGet(sender) { + const frameId = sender.frameId; + return Promise.resolve({frameId}); +} diff --git a/ext/bg/js/backend-api-forwarder.js b/ext/bg/js/backend-api-forwarder.js new file mode 100644 index 00000000..979afd16 --- /dev/null +++ b/ext/bg/js/backend-api-forwarder.js @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2019 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/>. + */ + + +class BackendApiForwarder { + constructor() { + chrome.runtime.onConnect.addListener(this.onConnect.bind(this)); + } + + onConnect(port) { + if (port.name !== 'backend-api-forwarder') { return; } + + let tabId; + if (!( + port.sender && + port.sender.tab && + (typeof (tabId = port.sender.tab.id)) === 'number' + )) { + port.disconnect(); + return; + } + + const forwardPort = chrome.tabs.connect(tabId, {name: 'frontend-api-receiver'}); + + port.onMessage.addListener(message => forwardPort.postMessage(message)); + forwardPort.onMessage.addListener(message => port.postMessage(message)); + port.onDisconnect.addListener(() => forwardPort.disconnect()); + forwardPort.onDisconnect.addListener(() => port.disconnect()); + } +} diff --git a/ext/bg/js/backend.js b/ext/bg/js/backend.js index d95cb82d..39fd4288 100644 --- a/ext/bg/js/backend.js +++ b/ext/bg/js/backend.js @@ -22,6 +22,8 @@ class Backend { this.translator = new Translator(); this.anki = new AnkiNull(); this.options = null; + + this.apiForwarder = new BackendApiForwarder(); } async prepare() { @@ -125,6 +127,10 @@ class Backend { forward: ({action, params}) => { forward(apiForward(action, params, sender), callback); + }, + + frameInformationGet: () => { + forward(apiFrameInformationGet(sender), callback); } }; diff --git a/ext/bg/js/dictionary.js b/ext/bg/js/dictionary.js index 49afc368..498eafcd 100644 --- a/ext/bg/js/dictionary.js +++ b/ext/bg/js/dictionary.js @@ -140,16 +140,17 @@ function dictTermsCompressTags(definitions) { function dictTermsGroup(definitions, dictionaries) { const groups = {}; for (const definition of definitions) { - const key = [definition.source, definition.expression].concat(definition.reasons); + const key = [definition.source, definition.expression]; + key.push(...definition.reasons); if (definition.reading) { key.push(definition.reading); } - const group = groups[key]; - if (group) { - group.push(definition); + const keyString = key.toString(); + if (groups.hasOwnProperty(keyString)) { + groups[keyString].push(definition); } else { - groups[key] = [definition]; + groups[keyString] = [definition]; } } diff --git a/ext/bg/js/options.js b/ext/bg/js/options.js index 7d993987..df95aae9 100644 --- a/ext/bg/js/options.js +++ b/ext/bg/js/options.js @@ -219,7 +219,10 @@ function optionsSetDefaults(options) { delay: 20, length: 10, modifier: 'shift', - deepDomScan: false + deepDomScan: false, + popupNestingMaxDepth: 0, + enableOnPopupExpressions: false, + enableOnSearchPage: true }, dictionaries: {}, diff --git a/ext/bg/js/search-frontend.js b/ext/bg/js/search-frontend.js new file mode 100644 index 00000000..840a1ea8 --- /dev/null +++ b/ext/bg/js/search-frontend.js @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2019 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/>. + */ + + +async function searchFrontendSetup() { + const options = await apiOptionsGet(); + if (!options.scanning.enableOnSearchPage) { return; } + + const scriptSrcs = [ + '/fg/js/api.js', + '/fg/js/frontend-api-receiver.js', + '/fg/js/popup.js', + '/fg/js/util.js', + '/fg/js/popup-proxy-host.js', + '/fg/js/frontend.js' + ]; + for (const src of scriptSrcs) { + const script = document.createElement('script'); + script.async = false; + script.src = src; + document.body.appendChild(script); + } + + const styleSrcs = [ + '/fg/css/client.css' + ]; + for (const src of styleSrcs) { + const style = document.createElement('link'); + style.rel = 'stylesheet'; + style.type = 'text/css'; + style.href = src; + document.head.appendChild(style); + } +} + +searchFrontendSetup(); diff --git a/ext/bg/js/settings.js b/ext/bg/js/settings.js index f5d669b2..83f4528c 100644 --- a/ext/bg/js/settings.js +++ b/ext/bg/js/settings.js @@ -48,9 +48,12 @@ async function formRead() { optionsNew.scanning.alphanumeric = $('#search-alphanumeric').prop('checked'); optionsNew.scanning.autoHideResults = $('#auto-hide-results').prop('checked'); optionsNew.scanning.deepDomScan = $('#deep-dom-scan').prop('checked'); + optionsNew.scanning.enableOnPopupExpressions = $('#enable-scanning-of-popup-expressions').prop('checked'); + optionsNew.scanning.enableOnSearchPage = $('#enable-scanning-on-search-page').prop('checked'); optionsNew.scanning.delay = parseInt($('#scan-delay').val(), 10); optionsNew.scanning.length = parseInt($('#scan-length').val(), 10); optionsNew.scanning.modifier = $('#scan-modifier-key').val(); + optionsNew.scanning.popupNestingMaxDepth = parseInt($('#popup-nesting-max-depth').val(), 10); optionsNew.anki.enable = $('#anki-enable').prop('checked'); optionsNew.anki.tags = $('#card-tags').val().split(/[,; ]+/); @@ -189,9 +192,12 @@ async function onReady() { $('#search-alphanumeric').prop('checked', options.scanning.alphanumeric); $('#auto-hide-results').prop('checked', options.scanning.autoHideResults); $('#deep-dom-scan').prop('checked', options.scanning.deepDomScan); + $('#enable-scanning-of-popup-expressions').prop('checked', options.scanning.enableOnPopupExpressions); + $('#enable-scanning-on-search-page').prop('checked', options.scanning.enableOnSearchPage); $('#scan-delay').val(options.scanning.delay); $('#scan-length').val(options.scanning.length); $('#scan-modifier-key').val(options.scanning.modifier); + $('#popup-nesting-max-depth').val(options.scanning.popupNestingMaxDepth); $('#dict-purge-link').click(utilAsync(onDictionaryPurge)); $('#dict-file').change(utilAsync(onDictionaryImport)); diff --git a/ext/bg/js/translator.js b/ext/bg/js/translator.js index c6af1f4e..c89b43ff 100644 --- a/ext/bg/js/translator.js +++ b/ext/bg/js/translator.js @@ -186,7 +186,7 @@ class Translator { let deinflections = await this.findTermDeinflections(text, titles, cache); const textHiragana = jpKatakanaToHiragana(text); if (text !== textHiragana) { - deinflections = deinflections.concat(await this.findTermDeinflections(textHiragana, titles, cache)); + deinflections.push(...await this.findTermDeinflections(textHiragana, titles, cache)); } let definitions = []; @@ -235,7 +235,7 @@ class Translator { let deinflections = []; for (let i = text.length; i > 0; --i) { const textSlice = text.slice(0, i); - deinflections = deinflections.concat(await this.deinflector.deinflect(textSlice, definer)); + deinflections.push(...await this.deinflector.deinflect(textSlice, definer)); } return deinflections; @@ -247,7 +247,7 @@ class Translator { const titles = Object.keys(dictionaries); for (const c of text) { if (!processed[c]) { - definitions = definitions.concat(await this.database.findKanji(c, titles)); + definitions.push(...await this.database.findKanji(c, titles)); processed[c] = true; } } @@ -277,7 +277,7 @@ class Translator { async buildTermFrequencies(definition, titles) { let terms = []; if (definition.expressions) { - terms = terms.concat(definition.expressions); + terms.push(...definition.expressions); } else { terms.push(definition); } @@ -299,7 +299,7 @@ class Translator { async expandTags(names, title) { const tags = []; for (const name of names) { - const base = name.split(':')[0]; + const base = Translator.getNameBase(name); const meta = await this.database.findTagForTitle(base, title); const tag = {name}; @@ -318,7 +318,7 @@ class Translator { async expandStats(items, title) { const stats = {}; for (const name in items) { - const base = name.split(':')[0]; + const base = Translator.getNameBase(name); const meta = await this.database.findTagForTitle(base, title); const group = stats[meta.category] = stats[meta.category] || []; @@ -346,4 +346,9 @@ class Translator { return stats; } + + static getNameBase(name) { + const pos = name.indexOf(':'); + return (pos >= 0 ? name.substr(0, pos) : name); + } } diff --git a/ext/bg/search.html b/ext/bg/search.html index 05c0daab..38c5a4e9 100644 --- a/ext/bg/search.html +++ b/ext/bg/search.html @@ -51,5 +51,6 @@ <script src="/mixed/js/japanese.js"></script> <script src="/bg/js/search.js"></script> + <script src="/bg/js/search-frontend.js"></script> </body> </html> diff --git a/ext/bg/settings.html b/ext/bg/settings.html index cc140023..85b7ee5f 100644 --- a/ext/bg/settings.html +++ b/ext/bg/settings.html @@ -193,6 +193,14 @@ </div> <div class="checkbox options-advanced"> + <label><input type="checkbox" id="enable-scanning-of-popup-expressions"> Enable scanning of popup expressions</label> + </div> + + <div class="checkbox"> + <label><input type="checkbox" id="enable-scanning-on-search-page"> Enable scanning on search page</label> + </div> + + <div class="checkbox options-advanced"> <label><input type="checkbox" id="deep-dom-scan"> Deep DOM scan</label> </div> @@ -215,6 +223,11 @@ <option value="shift">Shift</option> </select> </div> + + <div class="form-group options-advanced"> + <label for="popup-nesting-max-depth">Maximum nested popup depth</label> + <input type="number" min="0" id="popup-nesting-max-depth" class="form-control"> + </div> </div> <div> |