aboutsummaryrefslogtreecommitdiff
path: root/ext/js
diff options
context:
space:
mode:
Diffstat (limited to 'ext/js')
-rw-r--r--ext/js/accessibility/google-docs-util.js18
-rw-r--r--ext/js/app/frontend.js9
-rw-r--r--ext/js/display/display.js9
-rw-r--r--ext/js/display/query-parser.js5
-rw-r--r--ext/js/dom/document-util.js17
-rw-r--r--ext/js/dom/text-source-generator.js47
-rw-r--r--ext/js/language/text-scanner.js7
7 files changed, 80 insertions, 32 deletions
diff --git a/ext/js/accessibility/google-docs-util.js b/ext/js/accessibility/google-docs-util.js
index 34a5dd555..969e650e 100644
--- a/ext/js/accessibility/google-docs-util.js
+++ b/ext/js/accessibility/google-docs-util.js
@@ -23,8 +23,10 @@ import {TextSourceRange} from '../dom/text-source-range.js';
* This class is a helper for handling Google Docs content in content scripts.
*/
export class GoogleDocsUtil {
- /** @type {HTMLStyleElement|undefined} */
- static _styleNode = void 0;
+ constructor() {
+ /** @type {?HTMLStyleElement} */
+ this._styleNode = null;
+ }
/**
* Scans the document for text or elements with text information at the given coordinate.
@@ -34,7 +36,7 @@ export class GoogleDocsUtil {
* @param {import('document-util').GetRangeFromPointOptions} options Options to configure how element detection is performed.
* @returns {?TextSourceRange} A range for the hovered text or element, or `null` if no applicable content was found.
*/
- static getRangeFromPoint(x, y, {normalizeCssZoom}) {
+ getRangeFromPoint(x, y, {normalizeCssZoom}) {
const styleNode = this._getStyleNode();
styleNode.disabled = false;
const element = document.elementFromPoint(x, y);
@@ -55,8 +57,8 @@ export class GoogleDocsUtil {
* which allows them to be included in document.elementsFromPoint's return value.
* @returns {HTMLStyleElement}
*/
- static _getStyleNode() {
- if (typeof this._styleNode === 'undefined') {
+ _getStyleNode() {
+ if (this._styleNode === null) {
const style = document.createElement('style');
style.textContent = [
'.kix-canvas-tile-content{pointer-events:none!important;}',
@@ -79,7 +81,7 @@ export class GoogleDocsUtil {
* @param {boolean} normalizeCssZoom
* @returns {TextSourceRange}
*/
- static _createRange(element, text, x, y, normalizeCssZoom) {
+ _createRange(element, text, x, y, normalizeCssZoom) {
// Create imposter
const content = document.createTextNode(text);
const svgText = document.createElementNS('http://www.w3.org/2000/svg', 'text');
@@ -120,7 +122,7 @@ export class GoogleDocsUtil {
* @param {boolean} normalizeCssZoom
* @returns {Range}
*/
- static _getRangeWithPoint(textNode, x, y, normalizeCssZoom) {
+ _getRangeWithPoint(textNode, x, y, normalizeCssZoom) {
if (normalizeCssZoom) {
const scale = DocumentUtil.computeZoomScale(textNode);
x /= scale;
@@ -149,7 +151,7 @@ export class GoogleDocsUtil {
* @param {string} propertyName
* @param {string} value
*/
- static _setImportantStyle(style, propertyName, value) {
+ _setImportantStyle(style, propertyName, value) {
style.setProperty(propertyName, value, 'important');
}
}
diff --git a/ext/js/app/frontend.js b/ext/js/app/frontend.js
index 837364ad..d1c32b03 100644
--- a/ext/js/app/frontend.js
+++ b/ext/js/app/frontend.js
@@ -22,6 +22,7 @@ import {log} from '../core/logger.js';
import {promiseAnimationFrame} from '../core/utilities.js';
import {DocumentUtil} from '../dom/document-util.js';
import {TextSourceElement} from '../dom/text-source-element.js';
+import {TextSourceGenerator} from '../dom/text-source-generator.js';
import {TextSourceRange} from '../dom/text-source-range.js';
import {TextScanner} from '../language/text-scanner.js';
import {yomitan} from '../yomitan.js';
@@ -84,6 +85,8 @@ export class Frontend {
this._contentScale = 1.0;
/** @type {Promise<void>} */
this._lastShowPromise = Promise.resolve();
+ /** @type {TextSourceGenerator} */
+ this._textSourceGenerator = new TextSourceGenerator();
/** @type {TextScanner} */
this._textScanner = new TextScanner({
node: window,
@@ -91,7 +94,8 @@ export class Frontend {
ignorePoint: this._ignorePoint.bind(this),
getSearchContext: this._getSearchContext.bind(this),
searchTerms: true,
- searchKanji: true
+ searchKanji: true,
+ textSourceGenerator: this._textSourceGenerator
});
/** @type {boolean} */
this._textScannerHasBeenEnabled = false;
@@ -949,6 +953,7 @@ export class Frontend {
*/
async _prepareGoogleDocs() {
const {GoogleDocsUtil} = await import('../accessibility/google-docs-util.js');
- DocumentUtil.registerGetRangeFromPointHandler(GoogleDocsUtil.getRangeFromPoint.bind(GoogleDocsUtil));
+ const googleDocsUtil = new GoogleDocsUtil();
+ this._textSourceGenerator.registerGetRangeFromPointHandler(googleDocsUtil.getRangeFromPoint.bind(googleDocsUtil));
}
}
diff --git a/ext/js/display/display.js b/ext/js/display/display.js
index cff87309..c7a2775d 100644
--- a/ext/js/display/display.js
+++ b/ext/js/display/display.js
@@ -29,6 +29,7 @@ import {clone, deepEqual, promiseTimeout} from '../core/utilities.js';
import {PopupMenu} from '../dom/popup-menu.js';
import {querySelectorNotNull} from '../dom/query-selector.js';
import {ScrollElement} from '../dom/scroll-element.js';
+import {TextSourceGenerator} from '../dom/text-source-generator.js';
import {HotkeyHelpController} from '../input/hotkey-help-controller.js';
import {TextScanner} from '../language/text-scanner.js';
import {yomitan} from '../yomitan.js';
@@ -126,9 +127,12 @@ export class Display extends EventDispatcher {
this._queryParserVisibleOverride = null;
/** @type {HTMLElement} */
this._queryParserContainer = querySelectorNotNull(document, '#query-parser-container');
+ /** @type {TextSourceGenerator} */
+ this._textSourceGenerator = new TextSourceGenerator();
/** @type {QueryParser} */
this._queryParser = new QueryParser({
- getSearchContext: this._getSearchContext.bind(this)
+ getSearchContext: this._getSearchContext.bind(this),
+ textSourceGenerator: this._textSourceGenerator
});
/** @type {HTMLElement} */
this._contentScrollElement = querySelectorNotNull(document, '#content-scroll');
@@ -1829,7 +1833,8 @@ export class Display extends EventDispatcher {
searchTerms: true,
searchKanji: false,
searchOnClick: true,
- searchOnClickOnly: true
+ searchOnClickOnly: true,
+ textSourceGenerator: this._textSourceGenerator
});
this._contentTextScanner.includeSelector = '.click-scannable,.click-scannable *';
this._contentTextScanner.excludeSelector = '.scan-disable,.scan-disable *';
diff --git a/ext/js/display/query-parser.js b/ext/js/display/query-parser.js
index eb053f38..178bb110 100644
--- a/ext/js/display/query-parser.js
+++ b/ext/js/display/query-parser.js
@@ -30,7 +30,7 @@ export class QueryParser extends EventDispatcher {
/**
* @param {import('display').QueryParserConstructorDetails} details
*/
- constructor({getSearchContext}) {
+ constructor({getSearchContext, textSourceGenerator}) {
super();
/** @type {import('display').GetSearchContextCallback} */
this._getSearchContext = getSearchContext;
@@ -62,7 +62,8 @@ export class QueryParser extends EventDispatcher {
getSearchContext,
searchTerms: true,
searchKanji: false,
- searchOnClick: true
+ searchOnClick: true,
+ textSourceGenerator
});
/** @type {?(import('../language/japanese-wanakana.js'))} */
this._japaneseWanakanaModule = null;
diff --git a/ext/js/dom/document-util.js b/ext/js/dom/document-util.js
index 235a42d0..27acc046 100644
--- a/ext/js/dom/document-util.js
+++ b/ext/js/dom/document-util.js
@@ -28,8 +28,6 @@ export class DocumentUtil {
static _transparentColorPattern = /rgba\s*\([^)]*,\s*0(?:\.0+)?\s*\)/;
/** @type {?boolean} */
static _cssZoomSupported = null;
- /** @type {import('document-util').GetRangeFromPointHandler[]} @readonly */
- static _getRangeFromPointHandlers = [];
/**
* Scans the document for text or elements with text information at the given coordinate.
@@ -37,14 +35,9 @@ export class DocumentUtil {
* @param {number} x The x coordinate to search at.
* @param {number} y The y coordinate to search at.
* @param {import('document-util').GetRangeFromPointOptions} options Options to configure how element detection is performed.
- * @returns {?TextSourceRange|TextSourceElement} A range for the hovered text or element, or `null` if no applicable content was found.
+ * @returns {?import('text-source').TextSource} A range for the hovered text or element, or `null` if no applicable content was found.
*/
static getRangeFromPoint(x, y, options) {
- for (const handler of this._getRangeFromPointHandlers) {
- const r = handler(x, y, options);
- if (r !== null) { return r; }
- }
-
const {deepContentScan, normalizeCssZoom} = options;
const elements = this._getElementsFromPoint(x, y, deepContentScan);
@@ -94,14 +87,6 @@ export class DocumentUtil {
}
/**
- * Registers a custom handler for scanning for text or elements at the input position.
- * @param {import('document-util').GetRangeFromPointHandler} handler The handler callback which will be invoked when calling `getRangeFromPoint`.
- */
- static registerGetRangeFromPointHandler(handler) {
- this._getRangeFromPointHandlers.push(handler);
- }
-
- /**
* Extract a sentence from a document.
* @param {TextSourceRange|TextSourceElement} source The text source object, either `TextSourceRange` or `TextSourceElement`.
* @param {boolean} layoutAwareScan Whether or not layout-aware scan mode should be used.
diff --git a/ext/js/dom/text-source-generator.js b/ext/js/dom/text-source-generator.js
new file mode 100644
index 00000000..0435e69b
--- /dev/null
+++ b/ext/js/dom/text-source-generator.js
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2024 Yomitan Authors
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+import {DocumentUtil} from './document-util.js';
+
+export class TextSourceGenerator {
+ constructor() {
+ /** @type {import('text-source-generator').GetRangeFromPointHandler[]} @readonly */
+ this._getRangeFromPointHandlers = [];
+ }
+
+ /**
+ * @param {number} x
+ * @param {number} y
+ * @param {import('document-util').GetRangeFromPointOptions} options
+ * @returns {?import('text-source').TextSource}
+ */
+ getRangeFromPoint(x, y, options) {
+ for (const handler of this._getRangeFromPointHandlers) {
+ const result = handler(x, y, options);
+ if (result !== null) { return result; }
+ }
+ return DocumentUtil.getRangeFromPoint(x, y, options);
+ }
+
+ /**
+ * Registers a custom handler for scanning for text or elements at the input position.
+ * @param {import('text-source-generator').GetRangeFromPointHandler} handler The handler callback which will be invoked when calling `getRangeFromPoint`.
+ */
+ registerGetRangeFromPointHandler(handler) {
+ this._getRangeFromPointHandlers.push(handler);
+ }
+}
diff --git a/ext/js/language/text-scanner.js b/ext/js/language/text-scanner.js
index accb53fd..6228a82c 100644
--- a/ext/js/language/text-scanner.js
+++ b/ext/js/language/text-scanner.js
@@ -39,7 +39,8 @@ export class TextScanner extends EventDispatcher {
searchTerms = false,
searchKanji = false,
searchOnClick = false,
- searchOnClickOnly = false
+ searchOnClickOnly = false,
+ textSourceGenerator
}) {
super();
/** @type {HTMLElement|Window} */
@@ -58,6 +59,8 @@ export class TextScanner extends EventDispatcher {
this._searchOnClick = searchOnClick;
/** @type {boolean} */
this._searchOnClickOnly = searchOnClickOnly;
+ /** @type {import('../dom/text-source-generator').TextSourceGenerator} */
+ this._textSourceGenerator = textSourceGenerator;
/** @type {boolean} */
this._isPrepared = false;
@@ -1274,7 +1277,7 @@ export class TextScanner extends EventDispatcher {
return;
}
- const textSource = DocumentUtil.getRangeFromPoint(x, y, {
+ const textSource = this._textSourceGenerator.getRangeFromPoint(x, y, {
deepContentScan: this._deepContentScan,
normalizeCssZoom: this._normalizeCssZoom
});