aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md2
-rw-r--r--ext/bg/background.html2
-rw-r--r--ext/bg/context.html2
-rw-r--r--ext/bg/js/search.js2
-rw-r--r--ext/bg/js/settings.js49
-rw-r--r--ext/bg/js/util.js16
-rw-r--r--ext/bg/search.html2
-rw-r--r--ext/bg/settings.html2
-rw-r--r--ext/fg/float.html2
-rw-r--r--ext/fg/js/float.js2
-rw-r--r--ext/manifest.json6
-rw-r--r--ext/mixed/js/extension.js53
12 files changed, 111 insertions, 29 deletions
diff --git a/README.md b/README.md
index ebb05386..5671e5de 100644
--- a/README.md
+++ b/README.md
@@ -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;
+}