Skip to content

Commit

Permalink
Document util + google docs util state refactor (#590)
Browse files Browse the repository at this point in the history
* Remove static from GoogleDocsUtil since it has state

* Create TextSourceGenerator

* Remove DocumentUtil custom registrations

* Use TextSourceGenerator
  • Loading branch information
toasted-nutbread authored Jan 31, 2024
1 parent 87ed7c8 commit 2356223
Show file tree
Hide file tree
Showing 11 changed files with 117 additions and 48 deletions.
18 changes: 10 additions & 8 deletions ext/js/accessibility/google-docs-util.js
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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);
Expand All @@ -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;}',
Expand All @@ -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');
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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');
}
}
9 changes: 7 additions & 2 deletions ext/js/app/frontend.js
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -84,14 +85,17 @@ 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,
ignoreElements: this._ignoreElements.bind(this),
ignorePoint: this._ignorePoint.bind(this),
getSearchContext: this._getSearchContext.bind(this),
searchTerms: true,
searchKanji: true
searchKanji: true,
textSourceGenerator: this._textSourceGenerator
});
/** @type {boolean} */
this._textScannerHasBeenEnabled = false;
Expand Down Expand Up @@ -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));
}
}
9 changes: 7 additions & 2 deletions ext/js/display/display.js
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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');
Expand Down Expand Up @@ -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 *';
Expand Down
5 changes: 3 additions & 2 deletions ext/js/display/query-parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
17 changes: 1 addition & 16 deletions ext/js/dom/document-util.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,23 +28,16 @@ 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.
* Coordinates are provided in [client space](https://developer.mozilla.org/en-US/docs/Web/CSS/CSSOM_View/Coordinate_systems).
* @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);
Expand Down Expand Up @@ -93,14 +86,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`.
Expand Down
47 changes: 47 additions & 0 deletions ext/js/dom/text-source-generator.js
Original file line number Diff line number Diff line change
@@ -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);
}
}
7 changes: 5 additions & 2 deletions ext/js/language/text-scanner.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ export class TextScanner extends EventDispatcher {
searchTerms = false,
searchKanji = false,
searchOnClick = false,
searchOnClickOnly = false
searchOnClickOnly = false,
textSourceGenerator
}) {
super();
/** @type {HTMLElement|Window} */
Expand All @@ -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;
Expand Down Expand Up @@ -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
});
Expand Down
2 changes: 2 additions & 0 deletions types/ext/display.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -127,6 +128,7 @@ export type GetSearchContextCallback = TextScannerTypes.GetSearchContextCallback

export type QueryParserConstructorDetails = {
getSearchContext: GetSearchContextCallback;
textSourceGenerator: TextSourceGenerator;
};

export type QueryParserOptions = {
Expand Down
16 changes: 0 additions & 16 deletions types/ext/document-util.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';

/**
Expand All @@ -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;
Expand Down
2 changes: 2 additions & 0 deletions types/ext/text-scanner.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -145,6 +146,7 @@ export type ConstructorDetails = {
searchKanji?: boolean;
searchOnClick?: boolean;
searchOnClickOnly?: boolean;
textSourceGenerator: TextSourceGenerator;
};

export type SearchContext = {
Expand Down
33 changes: 33 additions & 0 deletions types/ext/text-source-generator.d.ts
Original file line number Diff line number Diff line change
@@ -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);

0 comments on commit 2356223

Please sign in to comment.