diff options
Diffstat (limited to 'ext/mixed/js/text-scanner.js')
| -rw-r--r-- | ext/mixed/js/text-scanner.js | 982 | 
1 files changed, 0 insertions, 982 deletions
diff --git a/ext/mixed/js/text-scanner.js b/ext/mixed/js/text-scanner.js deleted file mode 100644 index 7672b69d..00000000 --- a/ext/mixed/js/text-scanner.js +++ /dev/null @@ -1,982 +0,0 @@ -/* - * Copyright (C) 2019-2021  Yomichan 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/>. - */ - -/* global - * DocumentUtil - * api - */ - -class TextScanner extends EventDispatcher { -    constructor({ -        node, -        documentUtil, -        getSearchContext, -        ignoreElements=null, -        ignorePoint=null, -        searchTerms=false, -        searchKanji=false, -        searchOnClick=false, -        searchOnClickOnly=false -    }) { -        super(); -        this._node = node; -        this._documentUtil = documentUtil; -        this._getSearchContext = getSearchContext; -        this._ignoreElements = ignoreElements; -        this._ignorePoint = ignorePoint; -        this._searchTerms = searchTerms; -        this._searchKanji = searchKanji; -        this._searchOnClick = searchOnClick; -        this._searchOnClickOnly = searchOnClickOnly; - -        this._isPrepared = false; -        this._includeSelector = null; -        this._excludeSelector = null; - -        this._inputInfoCurrent = null; -        this._scanTimerPromise = null; -        this._textSourceCurrent = null; -        this._textSourceCurrentSelected = false; -        this._pendingLookup = false; - -        this._deepContentScan = false; -        this._selectText = false; -        this._delay = 0; -        this._touchInputEnabled = false; -        this._pointerEventsEnabled = false; -        this._scanLength = 1; -        this._layoutAwareScan = false; -        this._preventMiddleMouse = false; -        this._sentenceScanExtent = 0; -        this._sentenceTerminatorMap = new Map(); -        this._sentenceForwardQuoteMap = new Map(); -        this._sentenceBackwardQuoteMap = new Map(); -        this._inputs = []; - -        this._enabled = false; -        this._enabledValue = false; -        this._eventListeners = new EventListenerCollection(); - -        this._primaryTouchIdentifier = null; -        this._preventNextContextMenu = false; -        this._preventNextMouseDown = false; -        this._preventNextClick = false; -        this._preventScroll = false; -        this._penPointerPressed = false; -        this._penPointerReleased = false; -        this._pointerIdTypeMap = new Map(); - -        this._canClearSelection = true; -    } - -    get canClearSelection() { -        return this._canClearSelection; -    } - -    set canClearSelection(value) { -        this._canClearSelection = value; -    } - -    get includeSelector() { -        return this._includeSelector; -    } - -    set includeSelector(value) { -        this._includeSelector = value; -    } - -    get excludeSelector() { -        return this._excludeSelector; -    } - -    set excludeSelector(value) { -        this._excludeSelector = value; -    } - -    prepare() { -        this._isPrepared = true; -        this.setEnabled(this._enabled); -    } - -    setEnabled(enabled) { -        this._enabled = enabled; - -        const value = enabled && this._isPrepared; -        if (this._enabledValue === value) { return; } - -        this._eventListeners.removeAllEventListeners(); -        this._primaryTouchIdentifier = null; -        this._preventNextContextMenu = false; -        this._preventNextMouseDown = false; -        this._preventNextClick = false; -        this._preventScroll = false; -        this._penPointerPressed = false; -        this._penPointerReleased = false; -        this._pointerIdTypeMap.clear(); - -        this._enabledValue = value; - -        if (value) { -            this._hookEvents(); -        } else { -            this.clearSelection(true); -        } -    } - -    setOptions({ -        inputs, -        deepContentScan, -        selectText, -        delay, -        touchInputEnabled, -        pointerEventsEnabled, -        scanLength, -        layoutAwareScan, -        preventMiddleMouse, -        sentenceParsingOptions -    }) { -        if (Array.isArray(inputs)) { -            this._inputs = inputs.map(({ -                include, -                exclude, -                types, -                options: { -                    searchTerms, -                    searchKanji, -                    scanOnTouchMove, -                    scanOnPenHover, -                    scanOnPenPress, -                    scanOnPenRelease, -                    preventTouchScrolling -                } -            }) => ({ -                include: this._getInputArray(include), -                exclude: this._getInputArray(exclude), -                types: this._getInputTypeSet(types), -                options: { -                    searchTerms, -                    searchKanji, -                    scanOnTouchMove, -                    scanOnPenHover, -                    scanOnPenPress, -                    scanOnPenRelease, -                    preventTouchScrolling -                } -            })); -        } -        if (typeof deepContentScan === 'boolean') { -            this._deepContentScan = deepContentScan; -        } -        if (typeof selectText === 'boolean') { -            this._selectText = selectText; -        } -        if (typeof delay === 'number') { -            this._delay = delay; -        } -        if (typeof touchInputEnabled === 'boolean') { -            this._touchInputEnabled = touchInputEnabled; -        } -        if (typeof pointerEventsEnabled === 'boolean') { -            this._pointerEventsEnabled = pointerEventsEnabled; -        } -        if (typeof scanLength === 'number') { -            this._scanLength = scanLength; -        } -        if (typeof layoutAwareScan === 'boolean') { -            this._layoutAwareScan = layoutAwareScan; -        } -        if (typeof preventMiddleMouse === 'boolean') { -            this._preventMiddleMouse = preventMiddleMouse; -        } -        if (typeof sentenceParsingOptions === 'object' && sentenceParsingOptions !== null) { -            const {scanExtent, enableTerminationCharacters, terminationCharacters} = sentenceParsingOptions; -            const hasTerminationCharacters = (typeof terminationCharacters === 'object' && Array.isArray(terminationCharacters)); -            if (typeof scanExtent === 'number') { -                this._sentenceScanExtent = sentenceParsingOptions.scanExtent; -            } -            if (typeof enableTerminationCharacters === 'boolean' || hasTerminationCharacters) { -                const sentenceTerminatorMap = this._sentenceTerminatorMap; -                const sentenceForwardQuoteMap = this._sentenceForwardQuoteMap; -                const sentenceBackwardQuoteMap = this._sentenceBackwardQuoteMap; -                sentenceTerminatorMap.clear(); -                sentenceForwardQuoteMap.clear(); -                sentenceBackwardQuoteMap.clear(); -                if (enableTerminationCharacters !== false && hasTerminationCharacters) { -                    for (const {enabled, character1, character2, includeCharacterAtStart, includeCharacterAtEnd} of terminationCharacters) { -                        if (!enabled) { continue; } -                        if (character2 === null) { -                            sentenceTerminatorMap.set(character1, [includeCharacterAtStart, includeCharacterAtEnd]); -                        } else { -                            sentenceForwardQuoteMap.set(character1, [character2, includeCharacterAtStart]); -                            sentenceBackwardQuoteMap.set(character2, [character1, includeCharacterAtEnd]); -                        } -                    } -                } -            } -        } -    } - -    getTextSourceContent(textSource, length, layoutAwareScan) { -        const clonedTextSource = textSource.clone(); - -        clonedTextSource.setEndOffset(length, layoutAwareScan); - -        const includeSelector = this._includeSelector; -        const excludeSelector = this._excludeSelector; -        if (includeSelector !== null || excludeSelector !== null) { -            this._constrainTextSource(clonedTextSource, includeSelector, excludeSelector, layoutAwareScan); -        } - -        return clonedTextSource.text(); -    } - -    hasSelection() { -        return (this._textSourceCurrent !== null); -    } - -    clearSelection(passive) { -        if (!this._canClearSelection) { return; } -        if (this._textSourceCurrent !== null) { -            if (this._textSourceCurrentSelected) { -                this._textSourceCurrent.deselect(); -            } -            this._textSourceCurrent = null; -            this._textSourceCurrentSelected = false; -            this._inputInfoCurrent = null; -        } -        this.trigger('clearSelection', {passive}); -    } - -    getCurrentTextSource() { -        return this._textSourceCurrent; -    } - -    setCurrentTextSource(textSource) { -        this._textSourceCurrent = textSource; -        if (this._selectText) { -            this._textSourceCurrent.select(); -            this._textSourceCurrentSelected = true; -        } else { -            this._textSourceCurrentSelected = false; -        } -    } - -    async searchLast() { -        if (this._textSourceCurrent !== null && this._inputInfoCurrent !== null) { -            await this._search(this._textSourceCurrent, this._searchTerms, this._searchKanji, this._inputInfoCurrent); -            return true; -        } -        return false; -    } - -    async search(textSource, inputDetail) { -        const inputInfo = this._createInputInfo(null, 'script', 'script', true, [], [], inputDetail); -        return await this._search(textSource, this._searchTerms, this._searchKanji, inputInfo); -    } - -    // Private - -    _createOptionsContextForInput(baseOptionsContext, inputInfo) { -        const optionsContext = clone(baseOptionsContext); -        const {modifiers, modifierKeys} = inputInfo; -        optionsContext.modifiers = [...modifiers]; -        optionsContext.modifierKeys = [...modifierKeys]; -        return optionsContext; -    } - -    async _search(textSource, searchTerms, searchKanji, inputInfo) { -        let definitions = null; -        let sentence = null; -        let type = null; -        let error = null; -        let searched = false; -        let optionsContext = null; -        let detail = null; - -        try { -            if (this._textSourceCurrent !== null && this._textSourceCurrent.hasSameStart(textSource)) { -                return null; -            } - -            ({optionsContext, detail} = await this._getSearchContext()); -            optionsContext = this._createOptionsContextForInput(optionsContext, inputInfo); - -            searched = true; - -            const result = await this._findDefinitions(textSource, searchTerms, searchKanji, optionsContext); -            if (result !== null) { -                ({definitions, sentence, type} = result); -                this._inputInfoCurrent = inputInfo; -                this.setCurrentTextSource(textSource); -            } -        } catch (e) { -            error = e; -        } - -        if (!searched) { return null; } - -        const results = { -            textScanner: this, -            type, -            definitions, -            sentence, -            inputInfo, -            textSource, -            optionsContext, -            detail, -            error -        }; -        this.trigger('searched', results); -        return results; -    } - -    _onMouseOver(e) { -        if (this._ignoreElements !== null && this._ignoreElements().includes(e.target)) { -            this._scanTimerClear(); -        } -    } - -    _onMouseMove(e) { -        this._scanTimerClear(); - -        const inputInfo = this._getMatchingInputGroupFromEvent('mouse', 'mouseMove', e); -        if (inputInfo === null) { return; } - -        this._searchAtFromMouseMove(e.clientX, e.clientY, inputInfo); -    } - -    _onMouseDown(e) { -        if (this._preventNextMouseDown) { -            this._preventNextMouseDown = false; -            this._preventNextClick = true; -            e.preventDefault(); -            e.stopPropagation(); -            return false; -        } - -        switch (e.button) { -            case 0: // Primary -                this._scanTimerClear(); -                this.clearSelection(false); -                break; -            case 1: // Middle -                if (this._preventMiddleMouse) { -                    e.preventDefault(); -                    e.stopPropagation(); -                    return false; -                } -                break; -        } -    } - -    _onMouseOut() { -        this._scanTimerClear(); -    } - -    _onClick(e) { -        if (this._searchOnClick) { -            const modifiers = DocumentUtil.getActiveModifiersAndButtons(e); -            const modifierKeys = DocumentUtil.getActiveModifiers(e); -            const inputInfo = this._createInputInfo(null, 'mouse', 'click', false, modifiers, modifierKeys); -            this._searchAt(e.clientX, e.clientY, inputInfo); -        } - -        if (this._preventNextClick) { -            this._preventNextClick = false; -            e.preventDefault(); -            e.stopPropagation(); -            return false; -        } -    } - -    _onAuxClick() { -        this._preventNextContextMenu = false; -    } - -    _onContextMenu(e) { -        if (this._preventNextContextMenu) { -            this._preventNextContextMenu = false; -            e.preventDefault(); -            e.stopPropagation(); -            return false; -        } -    } - -    _onTouchStart(e) { -        if (this._primaryTouchIdentifier !== null || e.changedTouches.length === 0) { -            return; -        } - -        const {clientX, clientY, identifier} = e.changedTouches[0]; -        this._onPrimaryTouchStart(e, clientX, clientY, identifier); -    } - -    _onPrimaryTouchStart(e, x, y, identifier) { -        this._preventScroll = false; -        this._preventNextContextMenu = false; -        this._preventNextMouseDown = false; -        this._preventNextClick = false; - -        if (DocumentUtil.isPointInSelection(x, y, window.getSelection())) { -            return; -        } - -        this._primaryTouchIdentifier = identifier; - -        this._searchAtFromTouchStart(e, x, y); -    } - -    _onTouchEnd(e) { -        if ( -            this._primaryTouchIdentifier === null || -            this._getTouch(e.changedTouches, this._primaryTouchIdentifier) === null -        ) { -            return; -        } - -        this._onPrimaryTouchEnd(); -    } - -    _onPrimaryTouchEnd() { -        this._primaryTouchIdentifier = null; -        this._preventScroll = false; -        this._preventNextClick = false; -        // Don't revert context menu and mouse down prevention, since these events can occur after the touch has ended. -        // I.e. this._preventNextContextMenu and this._preventNextMouseDown should not be assigned to false. -    } - -    _onTouchCancel(e) { -        this._onTouchEnd(e); -    } - -    _onTouchMove(e) { -        if (!this._preventScroll || !e.cancelable || this._primaryTouchIdentifier === null) { -            return; -        } - -        const primaryTouch = this._getTouch(e.changedTouches, this._primaryTouchIdentifier); -        if (primaryTouch === null) { -            return; -        } - -        const inputInfo = this._getMatchingInputGroupFromEvent('touch', 'touchMove', e); -        if (inputInfo === null) { return; } - -        if (inputInfo.input.options.scanOnTouchMove) { -            this._searchAt(primaryTouch.clientX, primaryTouch.clientY, inputInfo); -        } - -        e.preventDefault(); // Disable scroll -    } - -    _onPointerOver(e) { -        const {pointerType, pointerId, isPrimary} = e; -        if (pointerType === 'pen') { -            this._pointerIdTypeMap.set(pointerId, pointerType); -        } - -        if (!isPrimary) { return; } -        switch (pointerType) { -            case 'mouse': return this._onMousePointerOver(e); -            case 'touch': return this._onTouchPointerOver(e); -            case 'pen': return this._onPenPointerOver(e); -        } -    } - -    _onPointerDown(e) { -        if (!e.isPrimary) { return; } -        switch (this._getPointerEventType(e)) { -            case 'mouse': return this._onMousePointerDown(e); -            case 'touch': return this._onTouchPointerDown(e); -            case 'pen': return this._onPenPointerDown(e); -        } -    } - -    _onPointerMove(e) { -        if (!e.isPrimary) { return; } -        switch (this._getPointerEventType(e)) { -            case 'mouse': return this._onMousePointerMove(e); -            case 'touch': return this._onTouchPointerMove(e); -            case 'pen': return this._onPenPointerMove(e); -        } -    } - -    _onPointerUp(e) { -        if (!e.isPrimary) { return; } -        switch (this._getPointerEventType(e)) { -            case 'mouse': return this._onMousePointerUp(e); -            case 'touch': return this._onTouchPointerUp(e); -            case 'pen': return this._onPenPointerUp(e); -        } -    } - -    _onPointerCancel(e) { -        this._pointerIdTypeMap.delete(e.pointerId); -        if (!e.isPrimary) { return; } -        switch (e.pointerType) { -            case 'mouse': return this._onMousePointerCancel(e); -            case 'touch': return this._onTouchPointerCancel(e); -            case 'pen': return this._onPenPointerCancel(e); -        } -    } - -    _onPointerOut(e) { -        this._pointerIdTypeMap.delete(e.pointerId); -        if (!e.isPrimary) { return; } -        switch (e.pointerType) { -            case 'mouse': return this._onMousePointerOut(e); -            case 'touch': return this._onTouchPointerOut(e); -            case 'pen': return this._onPenPointerOut(e); -        } -    } - -    _onMousePointerOver(e) { -        return this._onMouseOver(e); -    } - -    _onMousePointerDown(e) { -        return this._onMouseDown(e); -    } - -    _onMousePointerMove(e) { -        return this._onMouseMove(e); -    } - -    _onMousePointerUp() { -        // NOP -    } - -    _onMousePointerCancel(e) { -        return this._onMouseOut(e); -    } - -    _onMousePointerOut(e) { -        return this._onMouseOut(e); -    } - -    _onTouchPointerOver() { -        // NOP -    } - -    _onTouchPointerDown(e) { -        const {clientX, clientY, pointerId} = e; -        return this._onPrimaryTouchStart(e, clientX, clientY, pointerId); -    } - -    _onTouchPointerMove(e) { -        if (!this._preventScroll || !e.cancelable) { -            return; -        } - -        const inputInfo = this._getMatchingInputGroupFromEvent('touch', 'touchMove', e); -        if (inputInfo === null || !inputInfo.input.options.scanOnTouchMove) { return; } - -        this._searchAt(e.clientX, e.clientY, inputInfo); -    } - -    _onTouchPointerUp() { -        return this._onPrimaryTouchEnd(); -    } - -    _onTouchPointerCancel() { -        return this._onPrimaryTouchEnd(); -    } - -    _onTouchPointerOut() { -        // NOP -    } - -    _onTouchMovePreventScroll(e) { -        if (!this._preventScroll) { return; } - -        if (e.cancelable) { -            e.preventDefault(); -        } else { -            this._preventScroll = false; -        } -    } - -    _onPenPointerOver(e) { -        this._penPointerPressed = false; -        this._penPointerReleased = false; -        this._searchAtFromPen(e, e.clientX, e.clientY, 'pointerOver', false); -    } - -    _onPenPointerDown(e) { -        this._penPointerPressed = true; -        this._searchAtFromPen(e, e.clientX, e.clientY, 'pointerDown', true); -    } - -    _onPenPointerMove(e) { -        if (this._penPointerPressed && (!this._preventScroll || !e.cancelable)) { return; } -        this._searchAtFromPen(e, e.clientX, e.clientY, 'pointerMove', true); -    } - -    _onPenPointerUp() { -        this._penPointerPressed = false; -        this._penPointerReleased = true; -        this._preventScroll = false; -    } - -    _onPenPointerCancel(e) { -        this._onPenPointerOut(e); -    } - -    _onPenPointerOut() { -        this._penPointerPressed = false; -        this._penPointerReleased = false; -        this._preventScroll = false; -        this._preventNextContextMenu = false; -        this._preventNextMouseDown = false; -        this._preventNextClick = false; -    } - -    async _scanTimerWait() { -        const delay = this._delay; -        const promise = promiseTimeout(delay, true); -        this._scanTimerPromise = promise; -        try { -            return await promise; -        } finally { -            if (this._scanTimerPromise === promise) { -                this._scanTimerPromise = null; -            } -        } -    } - -    _scanTimerClear() { -        if (this._scanTimerPromise !== null) { -            this._scanTimerPromise.resolve(false); -            this._scanTimerPromise = null; -        } -    } - -    _arePointerEventsSupported() { -        return (this._pointerEventsEnabled && typeof PointerEvent !== 'undefined'); -    } - -    _hookEvents() { -        let eventListenerInfos; -        if (this._searchOnClickOnly) { -            eventListenerInfos = this._getMouseClickOnlyEventListeners(); -        } else if (this._arePointerEventsSupported()) { -            eventListenerInfos = this._getPointerEventListeners(); -        } else { -            eventListenerInfos = this._getMouseEventListeners(); -            if (this._touchInputEnabled) { -                eventListenerInfos.push(...this._getTouchEventListeners()); -            } -        } - -        for (const args of eventListenerInfos) { -            this._eventListeners.addEventListener(...args); -        } -    } - -    _getPointerEventListeners() { -        return [ -            [this._node, 'pointerover', this._onPointerOver.bind(this)], -            [this._node, 'pointerdown', this._onPointerDown.bind(this)], -            [this._node, 'pointermove', this._onPointerMove.bind(this)], -            [this._node, 'pointerup', this._onPointerUp.bind(this)], -            [this._node, 'pointercancel', this._onPointerCancel.bind(this)], -            [this._node, 'pointerout', this._onPointerOut.bind(this)], -            [this._node, 'touchmove', this._onTouchMovePreventScroll.bind(this), {passive: false}], -            [this._node, 'mousedown', this._onMouseDown.bind(this)], -            [this._node, 'click', this._onClick.bind(this)], -            [this._node, 'auxclick', this._onAuxClick.bind(this)] -        ]; -    } - -    _getMouseEventListeners() { -        return [ -            [this._node, 'mousedown', this._onMouseDown.bind(this)], -            [this._node, 'mousemove', this._onMouseMove.bind(this)], -            [this._node, 'mouseover', this._onMouseOver.bind(this)], -            [this._node, 'mouseout', this._onMouseOut.bind(this)], -            [this._node, 'click', this._onClick.bind(this)] -        ]; -    } - -    _getMouseClickOnlyEventListeners() { -        return [ -            [this._node, 'click', this._onClick.bind(this)] -        ]; -    } -    _getTouchEventListeners() { -        return [ -            [this._node, 'auxclick', this._onAuxClick.bind(this)], -            [this._node, 'touchstart', this._onTouchStart.bind(this)], -            [this._node, 'touchend', this._onTouchEnd.bind(this)], -            [this._node, 'touchcancel', this._onTouchCancel.bind(this)], -            [this._node, 'touchmove', this._onTouchMove.bind(this), {passive: false}], -            [this._node, 'contextmenu', this._onContextMenu.bind(this)] -        ]; -    } - -    _getTouch(touchList, identifier) { -        for (const touch of touchList) { -            if (touch.identifier === identifier) { -                return touch; -            } -        } -        return null; -    } - -    async _findDefinitions(textSource, searchTerms, searchKanji, optionsContext) { -        if (textSource === null) { -            return null; -        } -        if (searchTerms) { -            const results = await this._findTerms(textSource, optionsContext); -            if (results !== null) { return results; } -        } -        if (searchKanji) { -            const results = await this._findKanji(textSource, optionsContext); -            if (results !== null) { return results; } -        } -        return null; -    } - -    async _findTerms(textSource, optionsContext) { -        const scanLength = this._scanLength; -        const sentenceScanExtent = this._sentenceScanExtent; -        const sentenceTerminatorMap = this._sentenceTerminatorMap; -        const sentenceForwardQuoteMap = this._sentenceForwardQuoteMap; -        const sentenceBackwardQuoteMap = this._sentenceBackwardQuoteMap; -        const layoutAwareScan = this._layoutAwareScan; -        const searchText = this.getTextSourceContent(textSource, scanLength, layoutAwareScan); -        if (searchText.length === 0) { return null; } - -        const {definitions, length} = await api.termsFind(searchText, {}, optionsContext); -        if (definitions.length === 0) { return null; } - -        textSource.setEndOffset(length, layoutAwareScan); -        const sentence = this._documentUtil.extractSentence( -            textSource, -            layoutAwareScan, -            sentenceScanExtent, -            sentenceTerminatorMap, -            sentenceForwardQuoteMap, -            sentenceBackwardQuoteMap -        ); - -        return {definitions, sentence, type: 'terms'}; -    } - -    async _findKanji(textSource, optionsContext) { -        const sentenceScanExtent = this._sentenceScanExtent; -        const sentenceTerminatorMap = this._sentenceTerminatorMap; -        const sentenceForwardQuoteMap = this._sentenceForwardQuoteMap; -        const sentenceBackwardQuoteMap = this._sentenceBackwardQuoteMap; -        const layoutAwareScan = this._layoutAwareScan; -        const searchText = this.getTextSourceContent(textSource, 1, layoutAwareScan); -        if (searchText.length === 0) { return null; } - -        const definitions = await api.kanjiFind(searchText, optionsContext); -        if (definitions.length === 0) { return null; } - -        textSource.setEndOffset(1, layoutAwareScan); -        const sentence = this._documentUtil.extractSentence( -            textSource, -            layoutAwareScan, -            sentenceScanExtent, -            sentenceTerminatorMap, -            sentenceForwardQuoteMap, -            sentenceBackwardQuoteMap -        ); - -        return {definitions, sentence, type: 'kanji'}; -    } - -    async _searchAt(x, y, inputInfo) { -        if (this._pendingLookup) { return; } - -        try { -            const sourceInput = inputInfo.input; -            let searchTerms = this._searchTerms; -            let searchKanji = this._searchKanji; -            if (sourceInput !== null) { -                if (searchTerms && !sourceInput.options.searchTerms) { searchTerms = false; } -                if (searchKanji && !sourceInput.options.searchKanji) { searchKanji = false; } -            } - -            this._pendingLookup = true; -            this._scanTimerClear(); - -            if (typeof this._ignorePoint === 'function' && await this._ignorePoint(x, y)) { -                return; -            } - -            const textSource = this._documentUtil.getRangeFromPoint(x, y, this._deepContentScan); -            try { -                await this._search(textSource, searchTerms, searchKanji, inputInfo); -            } finally { -                if (textSource !== null) { -                    textSource.cleanup(); -                } -            } -        } catch (e) { -            yomichan.logError(e); -        } finally { -            this._pendingLookup = false; -        } -    } - -    async _searchAtFromMouseMove(x, y, inputInfo) { -        if (this._pendingLookup) { return; } - -        if (inputInfo.passive) { -            if (!await this._scanTimerWait()) { -                // Aborted -                return; -            } -        } - -        await this._searchAt(x, y, inputInfo); -    } - -    async _searchAtFromTouchStart(e, x, y) { -        if (this._pendingLookup) { return; } - -        const inputInfo = this._getMatchingInputGroupFromEvent('touch', 'touchStart', e); -        if (inputInfo === null) { return; } - -        const textSourceCurrentPrevious = this._textSourceCurrent !== null ? this._textSourceCurrent.clone() : null; -        const preventScroll = inputInfo.input.options.preventTouchScrolling; - -        await this._searchAt(x, y, inputInfo); - -        if ( -            this._textSourceCurrent !== null && -            !this._textSourceCurrent.hasSameStart(textSourceCurrentPrevious) -        ) { -            this._preventScroll = preventScroll; -            this._preventNextContextMenu = true; -            this._preventNextMouseDown = true; -        } -    } - -    async _searchAtFromPen(e, x, y, eventType, prevent) { -        if (this._pendingLookup) { return; } - -        const inputInfo = this._getMatchingInputGroupFromEvent('pen', eventType, e); -        if (inputInfo === null) { return; } - -        const {input: {options}} = inputInfo; -        if ( -            (!options.scanOnPenRelease && this._penPointerReleased) || -            !(this._penPointerPressed ? options.scanOnPenPress : options.scanOnPenHover) -        ) { -            return; -        } - -        const preventScroll = inputInfo.input.options.preventTouchScrolling; - -        await this._searchAt(x, y, inputInfo); - -        if ( -            prevent && -            this._textSourceCurrent !== null -        ) { -            this._preventScroll = preventScroll; -            this._preventNextContextMenu = true; -            this._preventNextMouseDown = true; -            this._preventNextClick = true; -        } -    } - -    _getMatchingInputGroupFromEvent(pointerType, eventType, event) { -        const modifiers = DocumentUtil.getActiveModifiersAndButtons(event); -        const modifierKeys = DocumentUtil.getActiveModifiers(event); -        return this._getMatchingInputGroup(pointerType, eventType, modifiers, modifierKeys); -    } - -    _getMatchingInputGroup(pointerType, eventType, modifiers, modifierKeys) { -        let fallbackIndex = -1; -        const modifiersSet = new Set(modifiers); -        for (let i = 0, ii = this._inputs.length; i < ii; ++i) { -            const input = this._inputs[i]; -            const {include, exclude, types} = input; -            if (!types.has(pointerType)) { continue; } -            if (this._setHasAll(modifiersSet, include) && (exclude.length === 0 || !this._setHasAll(modifiersSet, exclude))) { -                if (include.length > 0) { -                    return this._createInputInfo(input, pointerType, eventType, false, modifiers, modifierKeys); -                } else if (fallbackIndex < 0) { -                    fallbackIndex = i; -                } -            } -        } - -        return ( -            fallbackIndex >= 0 ? -            this._createInputInfo(this._inputs[fallbackIndex], pointerType, eventType, true, modifiers, modifierKeys) : -            null -        ); -    } - -    _createInputInfo(input, pointerType, eventType, passive, modifiers, modifierKeys, detail) { -        return {input, pointerType, eventType, passive, modifiers, modifierKeys, detail}; -    } - -    _setHasAll(set, values) { -        for (const value of values) { -            if (!set.has(value)) { -                return false; -            } -        } -        return true; -    } - -    _getInputArray(value) { -        return ( -            typeof value === 'string' ? -            value.split(/[,;\s]+/).map((v) => v.trim().toLowerCase()).filter((v) => v.length > 0) : -            [] -        ); -    } - -    _getInputTypeSet({mouse, touch, pen}) { -        const set = new Set(); -        if (mouse) { set.add('mouse'); } -        if (touch) { set.add('touch'); } -        if (pen) { set.add('pen'); } -        return set; -    } - -    _getPointerEventType(e) { -        // Workaround for Firefox bug not detecting certain 'touch' events as 'pen' events. -        const cachedPointerType = this._pointerIdTypeMap.get(e.pointerId); -        return (typeof cachedPointerType !== 'undefined' ? cachedPointerType : e.pointerType); -    } - -    _constrainTextSource(textSource, includeSelector, excludeSelector, layoutAwareScan) { -        let length = textSource.text().length; -        while (length > 0) { -            const nodes = textSource.getNodesInRange(); -            if ( -                (includeSelector !== null && !DocumentUtil.everyNodeMatchesSelector(nodes, includeSelector)) || -                (excludeSelector !== null && DocumentUtil.anyNodeMatchesSelector(nodes, excludeSelector)) -            ) { -                --length; -                textSource.setEndOffset(length, layoutAwareScan); -            } else { -                break; -            } -        } -    } -}  |