From a39a1fa9e4700d1189dfc5073b5fcb2557965671 Mon Sep 17 00:00:00 2001
From: toasted-nutbread <toasted-nutbread@users.noreply.github.com>
Date: Thu, 22 Aug 2019 19:44:31 -0400
Subject: Add support for Edge browser

---
 ext/mixed/js/extension.js | 53 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 53 insertions(+)
 create mode 100644 ext/mixed/js/extension.js

(limited to 'ext/mixed')

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;
+}
-- 
cgit v1.2.3


From ad0dca7bb12d13545b559e9c738fcc0767ba20d5 Mon Sep 17 00:00:00 2001
From: toasted-nutbread <toasted-nutbread@users.noreply.github.com>
Date: Sat, 31 Aug 2019 14:57:24 -0400
Subject: Make the imposter element tracked using TextSourceRange

---
 ext/fg/js/document.js   | 22 +++++++++++-----------
 ext/fg/js/frontend.js   |  6 +++---
 ext/fg/js/source.js     | 15 +++++++++++++--
 ext/mixed/js/display.js | 20 +++++++++++++-------
 4 files changed, 40 insertions(+), 23 deletions(-)

(limited to 'ext/mixed')

diff --git a/ext/fg/js/document.js b/ext/fg/js/document.js
index a017a0a6..e6a16bd5 100644
--- a/ext/fg/js/document.js
+++ b/ext/fg/js/document.js
@@ -70,12 +70,6 @@ function docImposterCreate(element) {
     return imposter;
 }
 
-function docImposterDestroy() {
-    for (const element of document.getElementsByClassName('yomichan-imposter')) {
-        element.parentNode.removeChild(element);
-    }
-}
-
 function docRangeFromPoint(point) {
     const element = document.elementFromPoint(point.x, point.y);
     let imposter = null;
@@ -92,12 +86,18 @@ function docRangeFromPoint(point) {
     }
 
     const range = document.caretRangeFromPoint(point.x, point.y);
-    if (imposter !== null) {
-        imposter.style.zIndex = -2147483646;
-        imposter.style.pointerEvents = 'none';
+    if (range !== null && isPointInRange(point, range)) {
+        if (imposter !== null) {
+            imposter.style.zIndex = -2147483646;
+            imposter.style.pointerEvents = 'none';
+        }
+        return new TextSourceRange(range, '', imposter);
+    } else {
+        if (imposter !== null) {
+            imposter.parentNode.removeChild(imposter);
+        }
+        return null;
     }
-
-    return range !== null && isPointInRange(point, range) ? new TextSourceRange(range) : null;
 }
 
 function docSentenceExtract(source, extent) {
diff --git a/ext/fg/js/frontend.js b/ext/fg/js/frontend.js
index 3c5f2ac8..ebff768e 100644
--- a/ext/fg/js/frontend.js
+++ b/ext/fg/js/frontend.js
@@ -307,10 +307,11 @@ class Frontend {
                 this.onError(e);
             }
         } finally {
+            if (textSource !== null) {
+                textSource.cleanup();
+            }
             if (hideResults && this.options.scanning.autoHideResults) {
                 this.searchClear();
-            } else {
-                docImposterDestroy();
             }
 
             this.pendingLookup = false;
@@ -371,7 +372,6 @@ class Frontend {
     }
 
     searchClear() {
-        docImposterDestroy();
         this.popup.hide();
         this.popup.clearAutoPlayTimer();
 
diff --git a/ext/fg/js/source.js b/ext/fg/js/source.js
index a360b331..409e81aa 100644
--- a/ext/fg/js/source.js
+++ b/ext/fg/js/source.js
@@ -25,13 +25,20 @@ const IGNORE_TEXT_PATTERN = /\u200c/;
  */
 
 class TextSourceRange {
-    constructor(range, content='') {
+    constructor(range, content, imposter) {
         this.range = range;
         this.content = content;
+        this.imposter = imposter;
     }
 
     clone() {
-        return new TextSourceRange(this.range.cloneRange(), this.content);
+        return new TextSourceRange(this.range.cloneRange(), this.content, this.imposter);
+    }
+
+    cleanup() {
+        if (this.imposter !== null && this.imposter.parentNode !== null) {
+            this.imposter.parentNode.removeChild(this.imposter);
+        }
     }
 
     text() {
@@ -221,6 +228,10 @@ class TextSourceElement {
         return new TextSourceElement(this.element, this.content);
     }
 
+    cleanup() {
+        // NOP
+    }
+
     text() {
         return this.content;
     }
diff --git a/ext/mixed/js/display.js b/ext/mixed/js/display.js
index a2707bd0..4620e198 100644
--- a/ext/mixed/js/display.js
+++ b/ext/mixed/js/display.js
@@ -84,16 +84,22 @@ class Display {
             if (textSource === null) {
                 return false;
             }
-            textSource.setEndOffset(this.options.scanning.length);
 
-            const {definitions, length} = await apiTermsFind(textSource.text());
-            if (definitions.length === 0) {
-                return false;
-            }
+            let definitions, length, sentence;
+            try {
+                textSource.setEndOffset(this.options.scanning.length);
 
-            textSource.setEndOffset(length);
+                ({definitions, length} = await apiTermsFind(textSource.text()));
+                if (definitions.length === 0) {
+                    return false;
+                }
 
-            const sentence = docSentenceExtract(textSource, this.options.anki.sentenceExt);
+                textSource.setEndOffset(length);
+
+                sentence = docSentenceExtract(textSource, this.options.anki.sentenceExt);
+            } finally {
+                textSource.cleanup();
+            }
 
             const context = {
                 source: {
-- 
cgit v1.2.3


From 171e3f1097a86b993ba1e16c07c4ad6d5bff75ee Mon Sep 17 00:00:00 2001
From: toasted-nutbread <toasted-nutbread@users.noreply.github.com>
Date: Sat, 31 Aug 2019 22:12:21 -0400
Subject: Add option for enabling deep scanning

---
 ext/bg/js/options.js    | 3 ++-
 ext/bg/js/settings.js   | 2 ++
 ext/bg/settings.html    | 4 ++++
 ext/fg/js/document.js   | 4 ++--
 ext/fg/js/frontend.js   | 2 +-
 ext/mixed/js/display.js | 2 +-
 6 files changed, 12 insertions(+), 5 deletions(-)

(limited to 'ext/mixed')

diff --git a/ext/bg/js/options.js b/ext/bg/js/options.js
index c76525b9..7d993987 100644
--- a/ext/bg/js/options.js
+++ b/ext/bg/js/options.js
@@ -218,7 +218,8 @@ function optionsSetDefaults(options) {
             autoHideResults: false,
             delay: 20,
             length: 10,
-            modifier: 'shift'
+            modifier: 'shift',
+            deepDomScan: false
         },
 
         dictionaries: {},
diff --git a/ext/bg/js/settings.js b/ext/bg/js/settings.js
index c4eb4842..f5d669b2 100644
--- a/ext/bg/js/settings.js
+++ b/ext/bg/js/settings.js
@@ -47,6 +47,7 @@ async function formRead() {
     optionsNew.scanning.selectText = $('#select-matched-text').prop('checked');
     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.delay = parseInt($('#scan-delay').val(), 10);
     optionsNew.scanning.length = parseInt($('#scan-length').val(), 10);
     optionsNew.scanning.modifier = $('#scan-modifier-key').val();
@@ -187,6 +188,7 @@ async function onReady() {
     $('#select-matched-text').prop('checked', options.scanning.selectText);
     $('#search-alphanumeric').prop('checked', options.scanning.alphanumeric);
     $('#auto-hide-results').prop('checked', options.scanning.autoHideResults);
+    $('#deep-dom-scan').prop('checked', options.scanning.deepDomScan);
     $('#scan-delay').val(options.scanning.delay);
     $('#scan-length').val(options.scanning.length);
     $('#scan-modifier-key').val(options.scanning.modifier);
diff --git a/ext/bg/settings.html b/ext/bg/settings.html
index 778dcee0..cc140023 100644
--- a/ext/bg/settings.html
+++ b/ext/bg/settings.html
@@ -192,6 +192,10 @@
                     <label><input type="checkbox" id="auto-hide-results"> Automatically hide results</label>
                 </div>
 
+                <div class="checkbox options-advanced">
+                    <label><input type="checkbox" id="deep-dom-scan"> Deep DOM scan</label>
+                </div>
+
                 <div class="form-group options-advanced">
                     <label for="scan-delay">Scan delay (in milliseconds)</label>
                     <input type="number" min="1" id="scan-delay" class="form-control">
diff --git a/ext/fg/js/document.js b/ext/fg/js/document.js
index 8bb857e7..727bc5d2 100644
--- a/ext/fg/js/document.js
+++ b/ext/fg/js/document.js
@@ -89,7 +89,7 @@ function docImposterCreate(element, isTextarea) {
     return [imposter, container];
 }
 
-function docRangeFromPoint({x, y}) {
+function docRangeFromPoint({x, y}, options) {
     const elements = document.elementsFromPoint(x, y);
     let imposter = null;
     let imposterContainer = null;
@@ -108,7 +108,7 @@ function docRangeFromPoint({x, y}) {
         }
     }
 
-    const range = caretRangeFromPointExt(x, y, elements);
+    const range = caretRangeFromPointExt(x, y, options.scanning.deepDomScan ? elements : []);
     if (range !== null) {
         if (imposter !== null) {
             docSetImposterStyle(imposterContainer.style, 'z-index', '-2147483646');
diff --git a/ext/fg/js/frontend.js b/ext/fg/js/frontend.js
index 5a8d18c1..8a5c48d0 100644
--- a/ext/fg/js/frontend.js
+++ b/ext/fg/js/frontend.js
@@ -285,7 +285,7 @@ class Frontend {
             return;
         }
 
-        const textSource = docRangeFromPoint(point);
+        const textSource = docRangeFromPoint(point, this.options);
         let hideResults = !textSource || !textSource.containsPoint(point);
         let searched = false;
         let success = false;
diff --git a/ext/mixed/js/display.js b/ext/mixed/js/display.js
index 4620e198..ebf56897 100644
--- a/ext/mixed/js/display.js
+++ b/ext/mixed/js/display.js
@@ -80,7 +80,7 @@ class Display {
             const {docRangeFromPoint, docSentenceExtract} = this.dependencies;
 
             const clickedElement = $(e.target);
-            const textSource = docRangeFromPoint({x: e.clientX, y: e.clientY});
+            const textSource = docRangeFromPoint({x: e.clientX, y: e.clientY}, this.options);
             if (textSource === null) {
                 return false;
             }
-- 
cgit v1.2.3