diff options
Diffstat (limited to 'ext/fg/js')
-rw-r--r-- | ext/fg/js/api.js | 70 | ||||
-rw-r--r-- | ext/fg/js/document.js | 23 | ||||
-rw-r--r-- | ext/fg/js/float.js | 4 | ||||
-rw-r--r-- | ext/fg/js/frontend-api-receiver.js | 6 | ||||
-rw-r--r-- | ext/fg/js/frontend-api-sender.js | 6 | ||||
-rw-r--r-- | ext/fg/js/frontend.js | 53 | ||||
-rw-r--r-- | ext/fg/js/popup-nested.js | 5 | ||||
-rw-r--r-- | ext/fg/js/popup-proxy-host.js | 4 | ||||
-rw-r--r-- | ext/fg/js/popup.js | 10 | ||||
-rw-r--r-- | ext/fg/js/source.js | 16 | ||||
-rw-r--r-- | ext/fg/js/util.js | 52 |
11 files changed, 99 insertions, 150 deletions
diff --git a/ext/fg/js/api.js b/ext/fg/js/api.js index 54818702..0e100b59 100644 --- a/ext/fg/js/api.js +++ b/ext/fg/js/api.js @@ -18,65 +18,101 @@ function apiOptionsGet(optionsContext) { - return utilInvoke('optionsGet', {optionsContext}); + return _apiInvoke('optionsGet', {optionsContext}); } function apiOptionsSet(changedOptions, optionsContext, source) { - return utilInvoke('optionsSet', {changedOptions, optionsContext, source}); + return _apiInvoke('optionsSet', {changedOptions, optionsContext, source}); } -function apiTermsFind(text, optionsContext) { - return utilInvoke('termsFind', {text, optionsContext}); +function apiTermsFind(text, details, optionsContext) { + return _apiInvoke('termsFind', {text, details, optionsContext}); +} + +function apiTextParse(text, optionsContext) { + return _apiInvoke('textParse', {text, optionsContext}); +} + +function apiTextParseMecab(text, optionsContext) { + return _apiInvoke('textParseMecab', {text, optionsContext}); } function apiKanjiFind(text, optionsContext) { - return utilInvoke('kanjiFind', {text, optionsContext}); + return _apiInvoke('kanjiFind', {text, optionsContext}); } function apiDefinitionAdd(definition, mode, context, optionsContext) { - return utilInvoke('definitionAdd', {definition, mode, context, optionsContext}); + return _apiInvoke('definitionAdd', {definition, mode, context, optionsContext}); } function apiDefinitionsAddable(definitions, modes, optionsContext) { - return utilInvoke('definitionsAddable', {definitions, modes, optionsContext}).catch(() => null); + return _apiInvoke('definitionsAddable', {definitions, modes, optionsContext}).catch(() => null); } function apiNoteView(noteId) { - return utilInvoke('noteView', {noteId}); + return _apiInvoke('noteView', {noteId}); } function apiTemplateRender(template, data, dynamic) { - return utilInvoke('templateRender', {data, template, dynamic}); + return _apiInvoke('templateRender', {data, template, dynamic}); } function apiAudioGetUrl(definition, source, optionsContext) { - return utilInvoke('audioGetUrl', {definition, source, optionsContext}); + return _apiInvoke('audioGetUrl', {definition, source, optionsContext}); } function apiCommandExec(command, params) { - return utilInvoke('commandExec', {command, params}); + return _apiInvoke('commandExec', {command, params}); } function apiScreenshotGet(options) { - return utilInvoke('screenshotGet', {options}); + return _apiInvoke('screenshotGet', {options}); } function apiForward(action, params) { - return utilInvoke('forward', {action, params}); + return _apiInvoke('forward', {action, params}); } function apiFrameInformationGet() { - return utilInvoke('frameInformationGet'); + return _apiInvoke('frameInformationGet'); } function apiInjectStylesheet(css) { - return utilInvoke('injectStylesheet', {css}); + return _apiInvoke('injectStylesheet', {css}); } function apiGetEnvironmentInfo() { - return utilInvoke('getEnvironmentInfo'); + return _apiInvoke('getEnvironmentInfo'); } function apiClipboardGet() { - return utilInvoke('clipboardGet'); + return _apiInvoke('clipboardGet'); +} + +function _apiInvoke(action, params={}) { + const data = {action, params}; + return new Promise((resolve, reject) => { + try { + chrome.runtime.sendMessage(data, (response) => { + _apiCheckLastError(chrome.runtime.lastError); + if (response !== null && typeof response === 'object') { + if (typeof response.error !== 'undefined') { + reject(jsonToError(response.error)); + } else { + resolve(response.result); + } + } else { + const message = response === null ? 'Unexpected null response' : `Unexpected response of type ${typeof response}`; + reject(new Error(`${message} (${JSON.stringify(data)})`)); + } + }); + } catch (e) { + window.yomichan_orphaned = true; + reject(e); + } + }); +} + +function _apiCheckLastError() { + // NOP } diff --git a/ext/fg/js/document.js b/ext/fg/js/document.js index a168705e..10dea7df 100644 --- a/ext/fg/js/document.js +++ b/ext/fg/js/document.js @@ -17,7 +17,7 @@ */ -const REGEX_TRANSPARENT_COLOR = /rgba\s*\([^\)]*,\s*0(?:\.0+)?\s*\)/; +const REGEX_TRANSPARENT_COLOR = /rgba\s*\([^)]*,\s*0(?:\.0+)?\s*\)/; function docSetImposterStyle(style, propertyName, value) { style.setProperty(propertyName, value, 'important'); @@ -223,7 +223,7 @@ function isPointInRange(x, y, range) { const {node, offset, content} = TextSourceRange.seekForward(range.endContainer, range.endOffset, 1); range.setEnd(node, offset); - if (!isWhitespace(content) && isPointInAnyRect(x, y, range.getClientRects())) { + if (!isWhitespace(content) && DOM.isPointInAnyRect(x, y, range.getClientRects())) { return true; } } finally { @@ -234,7 +234,7 @@ function isPointInRange(x, y, range) { const {node, offset, content} = TextSourceRange.seekBackward(range.startContainer, range.startOffset, 1); range.setStart(node, offset); - if (!isWhitespace(content) && isPointInAnyRect(x, y, range.getClientRects())) { + if (!isWhitespace(content) && DOM.isPointInAnyRect(x, y, range.getClientRects())) { // This purposefully leaves the starting offset as modified and sets the range length to 0. range.setEnd(node, offset); return true; @@ -248,21 +248,6 @@ function isWhitespace(string) { return string.trim().length === 0; } -function isPointInAnyRect(x, y, rects) { - for (const rect of rects) { - if (isPointInRect(x, y, rect)) { - return true; - } - } - return false; -} - -function isPointInRect(x, y, rect) { - return ( - x >= rect.left && x < rect.right && - y >= rect.top && y < rect.bottom); -} - const caretRangeFromPoint = (() => { if (typeof document.caretRangeFromPoint === 'function') { // Chrome, Edge @@ -359,7 +344,7 @@ function isElementTransparent(element) { } const style = window.getComputedStyle(element); return ( - parseFloat(style.opacity) < 0 || + parseFloat(style.opacity) <= 0 || style.visibility === 'hidden' || (style.backgroundImage === 'none' && isColorTransparent(style.backgroundColor)) ); diff --git a/ext/fg/js/float.js b/ext/fg/js/float.js index 089c9422..ae54be00 100644 --- a/ext/fg/js/float.js +++ b/ext/fg/js/float.js @@ -49,7 +49,7 @@ class DisplayFloat extends Display { onMessage(e) { const {action, params} = e.data; const handlers = DisplayFloat.messageHandlers; - if (handlers.hasOwnProperty(action)) { + if (hasOwn(handlers, action)) { const handler = handlers[action]; handler(this, params); } @@ -58,7 +58,7 @@ class DisplayFloat extends Display { onKeyDown(e) { const key = Display.getKeyFromEvent(e); const handlers = DisplayFloat.onKeyDownHandlers; - if (handlers.hasOwnProperty(key)) { + if (hasOwn(handlers, key)) { const handler = handlers[key]; if (handler(this, e)) { e.preventDefault(); diff --git a/ext/fg/js/frontend-api-receiver.js b/ext/fg/js/frontend-api-receiver.js index fbfb3ab0..7d38ddd5 100644 --- a/ext/fg/js/frontend-api-receiver.js +++ b/ext/fg/js/frontend-api-receiver.js @@ -34,7 +34,7 @@ class FrontendApiReceiver { onMessage(port, {id, action, params, target, senderId}) { if ( target !== this.source || - !this.handlers.hasOwnProperty(action) + !hasOwn(this.handlers, action) ) { return; } @@ -43,10 +43,10 @@ class FrontendApiReceiver { const handler = this.handlers[action]; handler(params).then( - result => { + (result) => { this.sendResult(port, id, senderId, {result}); }, - error => { + (error) => { this.sendResult(port, id, senderId, {error: errorToJson(error)}); }); } diff --git a/ext/fg/js/frontend-api-sender.js b/ext/fg/js/frontend-api-sender.js index c6eeaeb2..af998a8f 100644 --- a/ext/fg/js/frontend-api-sender.js +++ b/ext/fg/js/frontend-api-sender.js @@ -78,7 +78,7 @@ class FrontendApiSender { } onAck(id) { - if (!this.callbacks.hasOwnProperty(id)) { + if (!hasOwn(this.callbacks, id)) { console.warn(`ID ${id} not found for ack`); return; } @@ -95,7 +95,7 @@ class FrontendApiSender { } onResult(id, data) { - if (!this.callbacks.hasOwnProperty(id)) { + if (!hasOwn(this.callbacks, id)) { console.warn(`ID ${id} not found`); return; } @@ -118,7 +118,7 @@ class FrontendApiSender { } onError(id, reason) { - if (!this.callbacks.hasOwnProperty(id)) { return; } + if (!hasOwn(this.callbacks, id)) { return; } const info = this.callbacks[id]; delete this.callbacks[id]; info.timer = null; diff --git a/ext/fg/js/frontend.js b/ext/fg/js/frontend.js index e67008df..9a1d507b 100644 --- a/ext/fg/js/frontend.js +++ b/ext/fg/js/frontend.js @@ -80,7 +80,7 @@ class Frontend { onMouseMove(e) { this.popupTimerClear(); - if (this.pendingLookup || Frontend.isMouseButton('primary', e)) { + if (this.pendingLookup || DOM.isMouseButtonDown(e, 'primary')) { return; } @@ -88,7 +88,7 @@ class Frontend { const scanningModifier = scanningOptions.modifier; if (!( Frontend.isScanningModifierPressed(scanningModifier, e) || - (scanningOptions.middleMouse && Frontend.isMouseButton('auxiliary', e)) + (scanningOptions.middleMouse && DOM.isMouseButtonDown(e, 'auxiliary')) )) { return; } @@ -122,7 +122,7 @@ class Frontend { } } - onMouseOut(e) { + onMouseOut() { this.popupTimerClear(); } @@ -135,7 +135,7 @@ class Frontend { } } - onAuxClick(e) { + onAuxClick() { this.preventNextContextMenu = false; } @@ -159,7 +159,7 @@ class Frontend { this.preventNextClick = false; const primaryTouch = e.changedTouches[0]; - if (Frontend.selectionContainsPoint(window.getSelection(), primaryTouch.clientX, primaryTouch.clientY)) { + if (DOM.isPointInSelection(primaryTouch.clientX, primaryTouch.clientY, window.getSelection())) { return; } @@ -237,7 +237,7 @@ class Frontend { onWindowMessage(e) { const action = e.data; const handlers = Frontend.windowMessageHandlers; - if (handlers.hasOwnProperty(action)) { + if (hasOwn(handlers, action)) { const handler = handlers[action]; handler(this); } @@ -245,7 +245,7 @@ class Frontend { onRuntimeMessage({action, params}, sender, callback) { const handlers = Frontend.runtimeMessageHandlers; - if (handlers.hasOwnProperty(action)) { + if (hasOwn(handlers, action)) { const handler = handlers[action]; const result = handler(this, params); callback(result); @@ -398,7 +398,7 @@ class Frontend { textSource.getRect(), textSource.getWritingMode(), type, - {definitions, context: {sentence, url, focus}} + {definitions, context: {sentence, url, focus, disableHistory: true}} ); this.textSourceCurrent = textSource; @@ -413,7 +413,7 @@ class Frontend { const searchText = textSource.text(); if (searchText.length === 0) { return null; } - const {definitions, length} = await apiTermsFind(searchText, this.getOptionsContext()); + const {definitions, length} = await apiTermsFind(searchText, {}, this.getOptionsContext()); if (definitions.length === 0) { return null; } textSource.setEndOffset(length); @@ -447,8 +447,8 @@ class Frontend { } getIndexOfTouch(touchList, identifier) { - for (let i in touchList) { - let t = touchList[i]; + for (const i in touchList) { + const t = touchList[i]; if (t.identifier === identifier) { return i; } @@ -456,18 +456,6 @@ class Frontend { return -1; } - static selectionContainsPoint(selection, x, y) { - for (let i = 0; i < selection.rangeCount; ++i) { - const range = selection.getRangeAt(i); - for (const rect of range.getClientRects()) { - if (x >= rect.left && x <= rect.right && y >= rect.top && y <= rect.bottom) { - return true; - } - } - } - return false; - } - setTextSourceScanLength(textSource, length) { textSource.setEndOffset(length); if (this.ignoreNodes === null || !textSource.range) { @@ -499,25 +487,6 @@ class Frontend { default: return false; } } - - static isMouseButton(button, mouseEvent) { - switch (mouseEvent.type) { - case 'mouseup': - case 'mousedown': - case 'click': switch (button) { - case 'primary': return mouseEvent.button === 0; - case 'secondary': return mouseEvent.button === 2; - case 'auxiliary': return mouseEvent.button === 1; - default: return false; - } - default: switch (button) { - case 'primary': return (mouseEvent.buttons & 0x1) !== 0x0; - case 'secondary': return (mouseEvent.buttons & 0x2) !== 0x0; - case 'auxiliary': return (mouseEvent.buttons & 0x4) !== 0x0; - default: return false; - } - } - } } Frontend.windowMessageHandlers = { diff --git a/ext/fg/js/popup-nested.js b/ext/fg/js/popup-nested.js index cec95aea..31cb1cda 100644 --- a/ext/fg/js/popup-nested.js +++ b/ext/fg/js/popup-nested.js @@ -33,7 +33,10 @@ async function popupNestedInitialize(id, depth, parentFrameId, url) { return; } - const ignoreNodes = options.scanning.enableOnPopupExpressions ? [] : [ '.expression', '.expression *' ]; + const ignoreNodes = ['.scan-disable', '.scan-disable *']; + if (!options.scanning.enableOnPopupExpressions) { + ignoreNodes.push('.expression-scan-toggle', '.expression-scan-toggle *'); + } window.frontendInitializationData = {id, depth, parentFrameId, ignoreNodes, url, proxy: true}; diff --git a/ext/fg/js/popup-proxy-host.js b/ext/fg/js/popup-proxy-host.js index d8dec4df..b2f18b97 100644 --- a/ext/fg/js/popup-proxy-host.js +++ b/ext/fg/js/popup-proxy-host.js @@ -50,7 +50,7 @@ class PopupProxyHost { } createPopup(parentId, depth) { - const parent = (typeof parentId === 'string' && this.popups.hasOwnProperty(parentId) ? this.popups[parentId] : null); + const parent = (typeof parentId === 'string' && hasOwn(this.popups, parentId) ? this.popups[parentId] : null); const id = `${this.nextId}`; if (parent !== null) { depth = parent.depth + 1; @@ -70,7 +70,7 @@ class PopupProxyHost { } getPopup(id) { - if (!this.popups.hasOwnProperty(id)) { + if (!hasOwn(this.popups, id)) { throw new Error('Invalid popup ID'); } diff --git a/ext/fg/js/popup.js b/ext/fg/js/popup.js index 1f9317e0..42475d96 100644 --- a/ext/fg/js/popup.js +++ b/ext/fg/js/popup.js @@ -28,8 +28,8 @@ class Popup { this.childrenSupported = true; this.container = document.createElement('iframe'); this.container.className = 'yomichan-float'; - this.container.addEventListener('mousedown', e => e.stopPropagation()); - this.container.addEventListener('scroll', e => e.stopPropagation()); + this.container.addEventListener('mousedown', (e) => e.stopPropagation()); + this.container.addEventListener('scroll', (e) => e.stopPropagation()); this.container.setAttribute('src', chrome.runtime.getURL('/fg/float.html')); this.container.style.width = '0px'; this.container.style.height = '0px'; @@ -303,7 +303,7 @@ class Popup { } static getColorInfo(cssColor) { - const m = /^\s*rgba?\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*([\d\.]+)\s*)?\)\s*$/.exec(cssColor); + const m = /^\s*rgba?\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*([\d.]+)\s*)?\)\s*$/.exec(cssColor); if (m === null) { return null; } const m4 = m[4]; @@ -391,7 +391,7 @@ class Popup { static isOnExtensionPage() { try { const url = chrome.runtime.getURL('/'); - return window.location.href.substr(0, url.length) === url; + return window.location.href.substring(0, url.length) === url; } catch (e) { // NOP } @@ -401,7 +401,7 @@ class Popup { if (Popup.outerStylesheet === null) { if (!css) { return; } Popup.outerStylesheet = document.createElement('style'); - Popup.outerStylesheet.id = "yomichan-popup-outer-stylesheet"; + Popup.outerStylesheet.id = 'yomichan-popup-outer-stylesheet'; } const outerStylesheet = Popup.outerStylesheet; diff --git a/ext/fg/js/source.js b/ext/fg/js/source.js index c3da9f46..a84feed4 100644 --- a/ext/fg/js/source.js +++ b/ext/fg/js/source.js @@ -99,15 +99,19 @@ class TextSourceRange { static getRubyElement(node) { node = TextSourceRange.getParentElement(node); - if (node !== null && node.nodeName.toUpperCase() === "RT") { + if (node !== null && node.nodeName.toUpperCase() === 'RT') { node = node.parentNode; - return (node !== null && node.nodeName.toUpperCase() === "RUBY") ? node : null; + return (node !== null && node.nodeName.toUpperCase() === 'RUBY') ? node : null; } return null; } static seekForward(node, offset, length) { const state = {node, offset, remainder: length, content: ''}; + if (length <= 0) { + return state; + } + const TEXT_NODE = Node.TEXT_NODE; const ELEMENT_NODE = Node.ELEMENT_NODE; let resetOffset = false; @@ -166,6 +170,10 @@ class TextSourceRange { static seekBackward(node, offset, length) { const state = {node, offset, remainder: length, content: ''}; + if (length <= 0) { + return state; + } + const TEXT_NODE = Node.TEXT_NODE; const ELEMENT_NODE = Node.ELEMENT_NODE; let resetOffset = false; @@ -353,7 +361,7 @@ class TextSourceElement { let consumed = 0; let content = ''; - for (let currentChar of this.content || '') { + for (const currentChar of this.content || '') { if (consumed >= length) { break; } else if (!currentChar.match(IGNORE_TEXT_PATTERN)) { @@ -367,7 +375,7 @@ class TextSourceElement { return this.content.length; } - setStartOffset(length) { + setStartOffset() { return 0; } diff --git a/ext/fg/js/util.js b/ext/fg/js/util.js deleted file mode 100644 index 9a7968a7..00000000 --- a/ext/fg/js/util.js +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2016-2017 Alex Yatskov <alex@foosoft.net> - * Author: Alex Yatskov <alex@foosoft.net> - * - * 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 <http://www.gnu.org/licenses/>. - */ - - -function utilAsync(func) { - return function(...args) { - func.apply(this, args); - }; -} - -function utilInvoke(action, params={}) { - const data = {action, params}; - return new Promise((resolve, reject) => { - try { - chrome.runtime.sendMessage(data, (response) => { - utilCheckLastError(chrome.runtime.lastError); - if (response !== null && typeof response === 'object') { - if (typeof response.error !== 'undefined') { - reject(jsonToError(response.error)); - } else { - resolve(response.result); - } - } else { - const message = response === null ? 'Unexpected null response' : `Unexpected response of type ${typeof response}`; - reject(new Error(`${message} (${JSON.stringify(data)})`)); - } - }); - } catch (e) { - window.yomichan_orphaned = true; - reject(e); - } - }); -} - -function utilCheckLastError(e) { - // NOP -} |