diff options
Diffstat (limited to 'ext/js')
-rw-r--r-- | ext/js/accessibility/google-docs-util.js | 18 | ||||
-rw-r--r-- | ext/js/app/frontend.js | 9 | ||||
-rw-r--r-- | ext/js/display/display.js | 9 | ||||
-rw-r--r-- | ext/js/display/query-parser.js | 5 | ||||
-rw-r--r-- | ext/js/dom/document-util.js | 17 | ||||
-rw-r--r-- | ext/js/dom/text-source-generator.js | 47 | ||||
-rw-r--r-- | ext/js/language/text-scanner.js | 7 |
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 }); |