diff options
| author | toasted-nutbread <toasted-nutbread@users.noreply.github.com> | 2024-01-31 08:40:57 -0500 | 
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-01-31 13:40:57 +0000 | 
| commit | 2356223942a21d1683ac38eed8e7b9485f453d87 (patch) | |
| tree | 4e97b53a9d4829378ebc60eb5b8e40b6f5b665ee | |
| parent | 87ed7c8affd3ade9d3cd2d9ed1a61dd5f224e473 (diff) | |
Document util + google docs util state refactor (#590)
* Remove static from GoogleDocsUtil since it has state
* Create TextSourceGenerator
* Remove DocumentUtil custom registrations
* Use TextSourceGenerator
| -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 | ||||
| -rw-r--r-- | types/ext/display.d.ts | 2 | ||||
| -rw-r--r-- | types/ext/document-util.d.ts | 16 | ||||
| -rw-r--r-- | types/ext/text-scanner.d.ts | 2 | ||||
| -rw-r--r-- | types/ext/text-source-generator.d.ts | 33 | 
11 files changed, 117 insertions, 48 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              }); diff --git a/types/ext/display.d.ts b/types/ext/display.d.ts index b11d54e1..da24af75 100644 --- a/types/ext/display.d.ts +++ b/types/ext/display.d.ts @@ -17,6 +17,7 @@  import type {DisplayContentManager} from '../../ext/js/display/display-content-manager';  import type {HotkeyHelpController} from '../../ext/js/input/hotkey-help-controller'; +import type {TextSourceGenerator} from '../../ext/js/dom/text-source-generator';  import type * as Dictionary from './dictionary';  import type * as Extension from './extension';  import type * as Settings from './settings'; @@ -127,6 +128,7 @@ export type GetSearchContextCallback = TextScannerTypes.GetSearchContextCallback  export type QueryParserConstructorDetails = {      getSearchContext: GetSearchContextCallback; +    textSourceGenerator: TextSourceGenerator;  };  export type QueryParserOptions = { diff --git a/types/ext/document-util.d.ts b/types/ext/document-util.d.ts index 3f042c97..ec862596 100644 --- a/types/ext/document-util.d.ts +++ b/types/ext/document-util.d.ts @@ -15,8 +15,6 @@   * along with this program.  If not, see <https://www.gnu.org/licenses/>.   */ -import type * as TextSource from './text-source'; -  export type NormalizedWritingMode = 'horizontal-tb' | 'vertical-rl' | 'vertical-lr' | 'sideways-rl' | 'sideways-lr';  /** @@ -34,20 +32,6 @@ export type GetRangeFromPointOptions = {      normalizeCssZoom: boolean;  }; -/** - * Scans the document for text or elements with text information at the given coordinate. - * Coordinates are provided in [client space](https://developer.mozilla.org/en-US/docs/Web/CSS/CSSOM_View/Coordinate_systems). - * @returns A range for the hovered text or element, or `null` if no applicable content was found. - */ -export type GetRangeFromPointHandler = ( -    /** The x coordinate to search at. */ -    x: number, -    /** The y coordinate to search at. */ -    y: number, -    /** Options to configure how element detection is performed. */ -    options: GetRangeFromPointOptions, -) => (TextSource.TextSource | null); -  export type ToNumberConstraints = {      min?: string | number;      max?: string | number; diff --git a/types/ext/text-scanner.d.ts b/types/ext/text-scanner.d.ts index ff56b443..3e1cb6c2 100644 --- a/types/ext/text-scanner.d.ts +++ b/types/ext/text-scanner.d.ts @@ -16,6 +16,7 @@   */  import type {TextScanner} from '../../ext/js/language/text-scanner'; +import type {TextSourceGenerator} from '../../ext/js/dom/text-source-generator';  import type * as Dictionary from './dictionary';  import type * as Display from './display';  import type * as Input from './input'; @@ -145,6 +146,7 @@ export type ConstructorDetails = {      searchKanji?: boolean;      searchOnClick?: boolean;      searchOnClickOnly?: boolean; +    textSourceGenerator: TextSourceGenerator;  };  export type SearchContext = { diff --git a/types/ext/text-source-generator.d.ts b/types/ext/text-source-generator.d.ts new file mode 100644 index 00000000..13d88c3f --- /dev/null +++ b/types/ext/text-source-generator.d.ts @@ -0,0 +1,33 @@ +/* + * 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 type {TextSource} from './text-source'; +import type {GetRangeFromPointOptions} from './document-util'; + +/** + * Scans the document for text or elements with text information at the given coordinate. + * Coordinates are provided in [client space](https://developer.mozilla.org/en-US/docs/Web/CSS/CSSOM_View/Coordinate_systems). + * @returns A range for the hovered text or element, or `null` if no applicable content was found. + */ +export type GetRangeFromPointHandler = ( +    /** The x coordinate to search at. */ +    x: number, +    /** The y coordinate to search at. */ +    y: number, +    /** Options to configure how element detection is performed. */ +    options: GetRangeFromPointOptions, +) => (TextSource | null); |