diff options
-rw-r--r-- | README.md | 2 | ||||
-rw-r--r-- | ext/bg/background.html | 2 | ||||
-rw-r--r-- | ext/bg/context.html | 2 | ||||
-rw-r--r-- | ext/bg/js/search.js | 2 | ||||
-rw-r--r-- | ext/bg/js/settings.js | 49 | ||||
-rw-r--r-- | ext/bg/js/util.js | 16 | ||||
-rw-r--r-- | ext/bg/search.html | 2 | ||||
-rw-r--r-- | ext/bg/settings.html | 2 | ||||
-rw-r--r-- | ext/fg/float.html | 2 | ||||
-rw-r--r-- | ext/fg/js/float.js | 2 | ||||
-rw-r--r-- | ext/manifest.json | 6 | ||||
-rw-r--r-- | ext/mixed/js/extension.js | 53 |
12 files changed, 111 insertions, 29 deletions
@@ -165,6 +165,7 @@ Flashcard fields can be configured with the following steps: `{sentence}` | Sentence, quote, or phrase in which the term appears in the source content. `{tags}` | Grammar and usage tags providing information about the term (unavailable in *grouped* mode). `{url}` | Address of the web page in which the term appeared in. + `{screenshot}` | Screenshot of the web page taken at the time the term was added. #### Markers for Kanji Cards #### @@ -180,6 +181,7 @@ Flashcard fields can be configured with the following steps: `{onyomi}` | Onyomi (Chinese reading) for the Kanji expressed as Hiragana. `{sentence}` | Sentence, quote, or phrase in which the character appears in the source content. `{url}` | Address of the web page in which the Kanji appeared in. + `{screenshot}` | Screenshot of the web page taken at the time the Kanji was added. When creating your model for Yomichan, *please make sure that you pick a unique field to be first*; fields that will contain `{expression}` or `{character}` are ideal candidates for this. Anki does not require duplicate flashcards to be diff --git a/ext/bg/background.html b/ext/bg/background.html index 3262f2a1..5978f10f 100644 --- a/ext/bg/background.html +++ b/ext/bg/background.html @@ -10,6 +10,8 @@ <script src="/mixed/lib/jszip.min.js"></script> <script src="/mixed/lib/wanakana.min.js"></script> + <script src="/mixed/js/extension.js"></script> + <script src="/bg/js/anki.js"></script> <script src="/bg/js/api.js"></script> <script src="/bg/js/audio.js"></script> diff --git a/ext/bg/context.html b/ext/bg/context.html index 01b4fb30..198ccd42 100644 --- a/ext/bg/context.html +++ b/ext/bg/context.html @@ -32,6 +32,8 @@ <script src="/mixed/lib/jquery.min.js"></script> <script src="/mixed/lib/bootstrap-toggle/bootstrap-toggle.min.js"></script> + <script src="/mixed/js/extension.js"></script> + <script src="/bg/js/api.js"></script> <script src="/bg/js/options.js"></script> <script src="/bg/js/util.js"></script> diff --git a/ext/bg/js/search.js b/ext/bg/js/search.js index f08f22da..a3382398 100644 --- a/ext/bg/js/search.js +++ b/ext/bg/js/search.js @@ -25,7 +25,7 @@ class DisplaySearch extends Display { this.query = $('#query').on('input', this.onSearchInput.bind(this)); this.intro = $('#intro'); - this.dependencies = {...this.dependencies, ...{docRangeFromPoint, docSentenceExtract}}; + this.dependencies = Object.assign({}, this.dependencies, {docRangeFromPoint, docSentenceExtract}); window.wanakana.bind(this.query.get(0)); } diff --git a/ext/bg/js/settings.js b/ext/bg/js/settings.js index 75082f3e..cdcdae77 100644 --- a/ext/bg/js/settings.js +++ b/ext/bg/js/settings.js @@ -116,7 +116,7 @@ async function formMainDictionaryOptionsPopulate(options) { select.append($('<option class="text-muted" value="">Not selected</option>')); let mainDictionary = ''; - for (const dictRow of await utilDatabaseSummarize()) { + for (const dictRow of toIterable(await utilDatabaseSummarize())) { if (dictRow.sequenced) { select.append($(`<option value="${dictRow.title}">${dictRow.title}</option>`)); if (dictRow.title === options.general.mainDictionary) { @@ -314,12 +314,12 @@ async function dictionaryGroupsPopulate(options) { const dictGroups = $('#dict-groups').empty(); const dictWarning = $('#dict-warning').hide(); - const dictRows = await utilDatabaseSummarize(); + const dictRows = toIterable(await utilDatabaseSummarize()); if (dictRows.length === 0) { dictWarning.show(); } - for (const dictRow of dictRowsSort(dictRows, options)) { + for (const dictRow of toIterable(dictRowsSort(dictRows, options))) { const dictOptions = options.dictionaries[dictRow.title] || { enabled: false, priority: 0, @@ -581,26 +581,25 @@ async function onAnkiFieldTemplatesReset(e) { */ async function getBrowser() { - if (typeof chrome !== "undefined") { - if (typeof browser !== "undefined") { - try { - const info = await browser.runtime.getBrowserInfo(); - if (info.name === "Fennec") { - return "firefox-mobile"; - } - } catch (e) { } - return "firefox"; - } else { - return "chrome"; - } + if (EXTENSION_IS_BROWSER_EDGE) { + return 'edge'; + } + if (typeof browser !== 'undefined') { + try { + const info = await browser.runtime.getBrowserInfo(); + if (info.name === 'Fennec') { + return 'firefox-mobile'; + } + } catch (e) { } + return 'firefox'; } else { - return "edge"; + return 'chrome'; } } function storageBytesToLabeledString(size) { const base = 1000; - const labels = ["bytes", "KB", "MB", "GB"]; + const labels = ['bytes', 'KB', 'MB', 'GB']; let labelIndex = 0; while (size >= base) { size /= base; @@ -620,14 +619,14 @@ storageEstimate.mostRecent = null; async function storageInfoInitialize() { const browser = await getBrowser(); - const container = document.querySelector("#storage-info"); - container.setAttribute("data-browser", browser); + const container = document.querySelector('#storage-info'); + container.setAttribute('data-browser', browser); await storageShowInfo(); - container.classList.remove("storage-hidden"); + container.classList.remove('storage-hidden'); - document.querySelector("#storage-refresh").addEventListener('click', () => storageShowInfo(), false); + document.querySelector('#storage-refresh').addEventListener('click', () => storageShowInfo(), false); } async function storageUpdateStats() { @@ -637,8 +636,8 @@ async function storageUpdateStats() { const valid = (estimate !== null); if (valid) { - document.querySelector("#storage-usage").textContent = storageBytesToLabeledString(estimate.usage); - document.querySelector("#storage-quota").textContent = storageBytesToLabeledString(estimate.quota); + document.querySelector('#storage-usage').textContent = storageBytesToLabeledString(estimate.usage); + document.querySelector('#storage-quota').textContent = storageBytesToLabeledString(estimate.quota); } storageUpdateStats.isUpdating = false; @@ -650,8 +649,8 @@ async function storageShowInfo() { storageSpinnerShow(true); const valid = await storageUpdateStats(); - document.querySelector("#storage-use").classList.toggle("storage-hidden", !valid); - document.querySelector("#storage-error").classList.toggle("storage-hidden", valid); + document.querySelector('#storage-use').classList.toggle('storage-hidden', !valid); + document.querySelector('#storage-error').classList.toggle('storage-hidden', valid); storageSpinnerShow(false); } diff --git a/ext/bg/js/util.js b/ext/bg/js/util.js index 34b06ddb..3dc7c900 100644 --- a/ext/bg/js/util.js +++ b/ext/bg/js/util.js @@ -87,6 +87,20 @@ function utilDatabasePurge() { return utilBackend().translator.database.purge(); } -function utilDatabaseImport(data, progress, exceptions) { +async function utilDatabaseImport(data, progress, exceptions) { + // Edge cannot read data on the background page due to the File object + // being created from a different window. Read on the same page instead. + if (EXTENSION_IS_BROWSER_EDGE) { + data = await utilReadFile(data); + } return utilBackend().translator.database.importDictionary(data, progress, exceptions); } + +function utilReadFile(file) { + return new Promise((resolve, reject) => { + const reader = new FileReader(); + reader.onload = () => resolve(reader.result); + reader.onerror = () => reject(reader.error); + reader.readAsBinaryString(file); + }); +} diff --git a/ext/bg/search.html b/ext/bg/search.html index ce156578..05c0daab 100644 --- a/ext/bg/search.html +++ b/ext/bg/search.html @@ -37,6 +37,8 @@ <script src="/mixed/lib/jquery.min.js"></script> <script src="/mixed/lib/wanakana.min.js"></script> + <script src="/mixed/js/extension.js"></script> + <script src="/bg/js/api.js"></script> <script src="/bg/js/audio.js"></script> <script src="/bg/js/dictionary.js"></script> diff --git a/ext/bg/settings.html b/ext/bg/settings.html index c6677018..0704140e 100644 --- a/ext/bg/settings.html +++ b/ext/bg/settings.html @@ -399,6 +399,8 @@ <script src="/mixed/lib/bootstrap/js/bootstrap.min.js"></script> <script src="/mixed/lib/handlebars.min.js"></script> + <script src="/mixed/js/extension.js"></script> + <script src="/bg/js/anki.js"></script> <script src="/bg/js/api.js"></script> <script src="/bg/js/dictionary.js"></script> diff --git a/ext/fg/float.html b/ext/fg/float.html index 07f2d58b..0133e653 100644 --- a/ext/fg/float.html +++ b/ext/fg/float.html @@ -34,6 +34,8 @@ <script src="/mixed/lib/jquery.min.js"></script> <script src="/mixed/lib/wanakana.min.js"></script> + <script src="/mixed/js/extension.js"></script> + <script src="/fg/js/api.js"></script> <script src="/fg/js/util.js"></script> <script src="/fg/js/document.js"></script> diff --git a/ext/fg/js/float.js b/ext/fg/js/float.js index 090839a1..c0ec8a15 100644 --- a/ext/fg/js/float.js +++ b/ext/fg/js/float.js @@ -23,7 +23,7 @@ class DisplayFloat extends Display { this.autoPlayAudioTimer = null; this.styleNode = null; - this.dependencies = {...this.dependencies, ...{docRangeFromPoint, docSentenceExtract}}; + this.dependencies = Object.assign({}, this.dependencies, {docRangeFromPoint, docSentenceExtract}); $(window).on('message', utilAsync(this.onMessage.bind(this))); } diff --git a/ext/manifest.json b/ext/manifest.json index 4184273d..e12f85ad 100644 --- a/ext/manifest.json +++ b/ext/manifest.json @@ -11,10 +11,14 @@ }, "author": "Alex Yatskov", - "background": {"page": "bg/background.html"}, + "background": { + "page": "bg/background.html", + "persistent": true + }, "content_scripts": [{ "matches": ["http://*/*", "https://*/*", "file://*/*"], "js": [ + "mixed/js/extension.js", "fg/js/api.js", "fg/js/document.js", "fg/js/popup.js", diff --git a/ext/mixed/js/extension.js b/ext/mixed/js/extension.js new file mode 100644 index 00000000..d7085e5b --- /dev/null +++ b/ext/mixed/js/extension.js @@ -0,0 +1,53 @@ +/* + * 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/>. + */ + + +function toIterable(value) { + if (typeof Symbol !== 'undefined' && typeof value[Symbol.iterator] !== 'undefined') { + return value; + } + + const array = JSON.parse(JSON.stringify(value)); + return Array.isArray(array) ? array : []; +} + +function extensionHasChrome() { + try { + return typeof chrome === 'object' && chrome !== null; + } catch (e) { + return false; + } +} + +function extensionHasBrowser() { + try { + return typeof browser === 'object' && browser !== null; + } catch (e) { + return false; + } +} + +const EXTENSION_IS_BROWSER_EDGE = ( + extensionHasBrowser() && + (!extensionHasChrome() || (typeof chrome.runtime === 'undefined' && typeof browser.runtime !== 'undefined')) +); + +if (EXTENSION_IS_BROWSER_EDGE) { + // Edge does not have chrome defined. + chrome = browser; +} |