From 120f97be2601fcf47294d9f4ab1f7c06f7bc6c05 Mon Sep 17 00:00:00 2001 From: toasted-nutbread Date: Sun, 10 Nov 2019 13:36:35 -0500 Subject: Refactor apiOptionsSet --- ext/bg/js/api.js | 34 ++++++++++++++-------------------- 1 file changed, 14 insertions(+), 20 deletions(-) (limited to 'ext/bg/js/api.js') diff --git a/ext/bg/js/api.js b/ext/bg/js/api.js index 3209cc31..9fed99a1 100644 --- a/ext/bg/js/api.js +++ b/ext/bg/js/api.js @@ -25,42 +25,36 @@ async function apiOptionsSet(changedOptions, optionsContext, source) { const options = await apiOptionsGet(optionsContext); function getValuePaths(obj) { - let valuePaths = []; - let nodes = [{ - obj, - path: [] - }]; + const valuePaths = []; + const nodes = [{obj, path: []}]; while (nodes.length > 0) { - let node = nodes.pop(); - Object.keys(node.obj).forEach((key) => { - let path = node.path.concat(key); - let value = node.obj[key]; - if (typeof value === 'object') { - nodes.unshift({ - obj: value, - path: path - }); + const node = nodes.pop(); + for (const key of Object.keys(node.obj)) { + const path = node.path.concat(key); + const obj = node.obj[key]; + if (obj !== null && typeof obj === 'object') { + nodes.unshift({obj, path}); } else { - valuePaths.push([value, path]); + valuePaths.push([obj, path]); } - }); + } } return valuePaths; } function modifyOption(path, value, options) { let pivot = options; - for (let pathKey of path.slice(0, -1)) { - if (!(pathKey in pivot)) { + for (const key of path.slice(0, -1)) { + if (!pivot.hasOwnProperty(key)) { return false; } - pivot = pivot[pathKey]; + pivot = pivot[key]; } pivot[path[path.length - 1]] = value; return true; } - for (let [value, path] of getValuePaths(changedOptions)) { + for (const [value, path] of getValuePaths(changedOptions)) { modifyOption(path, value, options); } -- cgit v1.2.3 From af1662acadbfb7a96e06257a9dfad71ed6e2c478 Mon Sep 17 00:00:00 2001 From: toasted-nutbread Date: Mon, 4 Nov 2019 20:09:34 -0500 Subject: Update how apiTermsFind works --- ext/bg/js/api.js | 16 +--------------- ext/bg/js/translator.js | 38 +++++++++++++++++++++++++++----------- 2 files changed, 28 insertions(+), 26 deletions(-) (limited to 'ext/bg/js/api.js') diff --git a/ext/bg/js/api.js b/ext/bg/js/api.js index 9fed99a1..9751d4a1 100644 --- a/ext/bg/js/api.js +++ b/ext/bg/js/api.js @@ -74,21 +74,7 @@ async function apiOptionsSave(source) { async function apiTermsFind(text, optionsContext) { const options = await apiOptionsGet(optionsContext); - const translator = utilBackend().translator; - - const searcher = { - 'merge': translator.findTermsMerged, - 'split': translator.findTermsSplit, - 'group': translator.findTermsGrouped - }[options.general.resultOutputMode].bind(translator); - - const {definitions, length} = await searcher( - text, - dictEnabledSet(options), - options.scanning.alphanumeric, - options - ); - + const [definitions, length] = await utilBackend().translator.findTerms(text, options); return { length, definitions: definitions.slice(0, options.general.maxResults) diff --git a/ext/bg/js/translator.js b/ext/bg/js/translator.js index 305619a5..d33a2e27 100644 --- a/ext/bg/js/translator.js +++ b/ext/bg/js/translator.js @@ -141,9 +141,23 @@ class Translator { return result; } - async findTermsGrouped(text, dictionaries, alphanumeric, options) { + async findTerms(text, options) { + switch (options.general.resultOutputMode) { + case 'group': + return await this.findTermsGrouped(text, options); + case 'merge': + return await this.findTermsMerged(text, options); + case 'split': + return await this.findTermsSplit(text, options); + default: + return [[], 0]; + } + } + + async findTermsGrouped(text, options) { + const dictionaries = dictEnabledSet(options); const titles = Object.keys(dictionaries); - const {length, definitions} = await this.findTermsInternal(text, dictionaries, alphanumeric); + const [definitions, length] = await this.findTermsInternal(text, dictionaries, options.scanning.alphanumeric); const definitionsGrouped = dictTermsGroup(definitions, dictionaries); await this.buildTermFrequencies(definitionsGrouped, titles); @@ -154,13 +168,14 @@ class Translator { } } - return {length, definitions: definitionsGrouped}; + return [definitionsGrouped, length]; } - async findTermsMerged(text, dictionaries, alphanumeric, options) { + async findTermsMerged(text, options) { + const dictionaries = dictEnabledSet(options); const secondarySearchTitles = Object.keys(options.dictionaries).filter(dict => options.dictionaries[dict].allowSecondarySearches); const titles = Object.keys(dictionaries); - const {length, definitions} = await this.findTermsInternal(text, dictionaries, alphanumeric); + const [definitions, length] = await this.findTermsInternal(text, dictionaries, options.scanning.alphanumeric); const {sequencedDefinitions, defaultDefinitions} = await this.getSequencedDefinitions(definitions, options.general.mainDictionary); const definitionsMerged = []; const mergedByTermIndices = new Set(); @@ -191,23 +206,24 @@ class Translator { } } - return {length, definitions: dictTermsSort(definitionsMerged)}; + return [dictTermsSort(definitionsMerged), length]; } - async findTermsSplit(text, dictionaries, alphanumeric) { + async findTermsSplit(text, options) { + const dictionaries = dictEnabledSet(options); const titles = Object.keys(dictionaries); - const {length, definitions} = await this.findTermsInternal(text, dictionaries, alphanumeric); + const [definitions, length] = await this.findTermsInternal(text, dictionaries, options.scanning.alphanumeric); await this.buildTermFrequencies(definitions, titles); - return {length, definitions}; + return [definitions, length]; } async findTermsInternal(text, dictionaries, alphanumeric) { if (!alphanumeric && text.length > 0) { const c = text[0]; if (!jpIsKana(c) && !jpIsKanji(c)) { - return {length: 0, definitions: []}; + return [[], 0]; } } @@ -246,7 +262,7 @@ class Translator { length = Math.max(length, definition.source.length); } - return {length, definitions}; + return [definitions, length]; } async findTermDeinflections(text, text2, titles) { -- cgit v1.2.3 From 58c099799940fce56c7a57ce566c522c7eb0eb12 Mon Sep 17 00:00:00 2001 From: toasted-nutbread Date: Mon, 4 Nov 2019 20:13:03 -0500 Subject: Give findKanji the same API as findTerms --- ext/bg/js/api.js | 2 +- ext/bg/js/translator.js | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'ext/bg/js/api.js') diff --git a/ext/bg/js/api.js b/ext/bg/js/api.js index 9751d4a1..f379e65a 100644 --- a/ext/bg/js/api.js +++ b/ext/bg/js/api.js @@ -83,7 +83,7 @@ async function apiTermsFind(text, optionsContext) { async function apiKanjiFind(text, optionsContext) { const options = await apiOptionsGet(optionsContext); - const definitions = await utilBackend().translator.findKanji(text, dictEnabledSet(options)); + const definitions = await utilBackend().translator.findKanji(text, options); return definitions.slice(0, options.general.maxResults); } diff --git a/ext/bg/js/translator.js b/ext/bg/js/translator.js index d33a2e27..1cdd79db 100644 --- a/ext/bg/js/translator.js +++ b/ext/bg/js/translator.js @@ -330,7 +330,8 @@ class Translator { return deinflections; } - async findKanji(text, dictionaries) { + async findKanji(text, options) { + const dictionaries = dictEnabledSet(options); const titles = Object.keys(dictionaries); const kanjiUnique = {}; const kanjiList = []; -- cgit v1.2.3 From 7093d8f06e26daf825745be26238d92ed122e60b Mon Sep 17 00:00:00 2001 From: toasted-nutbread Date: Mon, 4 Nov 2019 20:14:51 -0500 Subject: Simplify how definition count is limited --- ext/bg/js/api.js | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'ext/bg/js/api.js') diff --git a/ext/bg/js/api.js b/ext/bg/js/api.js index f379e65a..c50db76f 100644 --- a/ext/bg/js/api.js +++ b/ext/bg/js/api.js @@ -75,16 +75,15 @@ async function apiOptionsSave(source) { async function apiTermsFind(text, optionsContext) { const options = await apiOptionsGet(optionsContext); const [definitions, length] = await utilBackend().translator.findTerms(text, options); - return { - length, - definitions: definitions.slice(0, options.general.maxResults) - }; + definitions.splice(options.general.maxResults); + return {length, definitions}; } async function apiKanjiFind(text, optionsContext) { const options = await apiOptionsGet(optionsContext); const definitions = await utilBackend().translator.findKanji(text, options); - return definitions.slice(0, options.general.maxResults); + definitions.splice(options.general.maxResults); + return definitions; } async function apiDefinitionAdd(definition, mode, context, optionsContext) { -- cgit v1.2.3 From 3a225c3f916d435e04fb30afa731c30c4309fc7f Mon Sep 17 00:00:00 2001 From: toasted-nutbread Date: Mon, 4 Nov 2019 20:43:40 -0500 Subject: Add details field to apiTermsFind --- ext/bg/js/api.js | 4 ++-- ext/bg/js/backend.js | 2 +- ext/bg/js/search.js | 2 +- ext/bg/js/translator.js | 22 +++++++++++----------- ext/fg/js/api.js | 4 ++-- ext/fg/js/frontend.js | 2 +- ext/mixed/js/display.js | 2 +- 7 files changed, 19 insertions(+), 19 deletions(-) (limited to 'ext/bg/js/api.js') diff --git a/ext/bg/js/api.js b/ext/bg/js/api.js index c50db76f..df73aa2a 100644 --- a/ext/bg/js/api.js +++ b/ext/bg/js/api.js @@ -72,9 +72,9 @@ async function apiOptionsSave(source) { backend.onOptionsUpdated(source); } -async function apiTermsFind(text, optionsContext) { +async function apiTermsFind(text, details, optionsContext) { const options = await apiOptionsGet(optionsContext); - const [definitions, length] = await utilBackend().translator.findTerms(text, options); + const [definitions, length] = await utilBackend().translator.findTerms(text, details, options); definitions.splice(options.general.maxResults); return {length, definitions}; } diff --git a/ext/bg/js/backend.js b/ext/bg/js/backend.js index 71393467..efad153a 100644 --- a/ext/bg/js/backend.js +++ b/ext/bg/js/backend.js @@ -179,7 +179,7 @@ Backend.messageHandlers = { optionsGet: ({optionsContext}) => apiOptionsGet(optionsContext), optionsSet: ({changedOptions, optionsContext, source}) => apiOptionsSet(changedOptions, optionsContext, source), kanjiFind: ({text, optionsContext}) => apiKanjiFind(text, optionsContext), - termsFind: ({text, optionsContext}) => apiTermsFind(text, optionsContext), + termsFind: ({text, details, optionsContext}) => apiTermsFind(text, details, optionsContext), definitionAdd: ({definition, mode, context, optionsContext}) => apiDefinitionAdd(definition, mode, context, optionsContext), definitionsAddable: ({definitions, modes, optionsContext}) => apiDefinitionsAddable(definitions, modes, optionsContext), noteView: ({noteId}) => apiNoteView(noteId), diff --git a/ext/bg/js/search.js b/ext/bg/js/search.js index ad579918..abd40640 100644 --- a/ext/bg/js/search.js +++ b/ext/bg/js/search.js @@ -207,7 +207,7 @@ class DisplaySearch extends Display { this.setIntroVisible(!valid, animate); this.updateSearchButton(); if (valid) { - const {definitions} = await apiTermsFind(query, this.optionsContext); + const {definitions} = await apiTermsFind(query, {}, this.optionsContext); this.setContentTerms(definitions, { focus: false, sentence: null, diff --git a/ext/bg/js/translator.js b/ext/bg/js/translator.js index 1cdd79db..dac53f93 100644 --- a/ext/bg/js/translator.js +++ b/ext/bg/js/translator.js @@ -141,23 +141,23 @@ class Translator { return result; } - async findTerms(text, options) { + async findTerms(text, details, options) { switch (options.general.resultOutputMode) { case 'group': - return await this.findTermsGrouped(text, options); + return await this.findTermsGrouped(text, details, options); case 'merge': - return await this.findTermsMerged(text, options); + return await this.findTermsMerged(text, details, options); case 'split': - return await this.findTermsSplit(text, options); + return await this.findTermsSplit(text, details, options); default: return [[], 0]; } } - async findTermsGrouped(text, options) { + async findTermsGrouped(text, details, options) { const dictionaries = dictEnabledSet(options); const titles = Object.keys(dictionaries); - const [definitions, length] = await this.findTermsInternal(text, dictionaries, options.scanning.alphanumeric); + const [definitions, length] = await this.findTermsInternal(text, dictionaries, options.scanning.alphanumeric, details); const definitionsGrouped = dictTermsGroup(definitions, dictionaries); await this.buildTermFrequencies(definitionsGrouped, titles); @@ -171,11 +171,11 @@ class Translator { return [definitionsGrouped, length]; } - async findTermsMerged(text, options) { + async findTermsMerged(text, details, options) { const dictionaries = dictEnabledSet(options); const secondarySearchTitles = Object.keys(options.dictionaries).filter(dict => options.dictionaries[dict].allowSecondarySearches); const titles = Object.keys(dictionaries); - const [definitions, length] = await this.findTermsInternal(text, dictionaries, options.scanning.alphanumeric); + const [definitions, length] = await this.findTermsInternal(text, dictionaries, options.scanning.alphanumeric, details); const {sequencedDefinitions, defaultDefinitions} = await this.getSequencedDefinitions(definitions, options.general.mainDictionary); const definitionsMerged = []; const mergedByTermIndices = new Set(); @@ -209,17 +209,17 @@ class Translator { return [dictTermsSort(definitionsMerged), length]; } - async findTermsSplit(text, options) { + async findTermsSplit(text, details, options) { const dictionaries = dictEnabledSet(options); const titles = Object.keys(dictionaries); - const [definitions, length] = await this.findTermsInternal(text, dictionaries, options.scanning.alphanumeric); + const [definitions, length] = await this.findTermsInternal(text, dictionaries, options.scanning.alphanumeric, details); await this.buildTermFrequencies(definitions, titles); return [definitions, length]; } - async findTermsInternal(text, dictionaries, alphanumeric) { + async findTermsInternal(text, dictionaries, alphanumeric, details) { if (!alphanumeric && text.length > 0) { const c = text[0]; if (!jpIsKana(c) && !jpIsKanji(c)) { diff --git a/ext/fg/js/api.js b/ext/fg/js/api.js index 54818702..945ba076 100644 --- a/ext/fg/js/api.js +++ b/ext/fg/js/api.js @@ -25,8 +25,8 @@ function apiOptionsSet(changedOptions, optionsContext, source) { return utilInvoke('optionsSet', {changedOptions, optionsContext, source}); } -function apiTermsFind(text, optionsContext) { - return utilInvoke('termsFind', {text, optionsContext}); +function apiTermsFind(text, details, optionsContext) { + return utilInvoke('termsFind', {text, details, optionsContext}); } function apiKanjiFind(text, optionsContext) { diff --git a/ext/fg/js/frontend.js b/ext/fg/js/frontend.js index 7c62b51b..6002dfcb 100644 --- a/ext/fg/js/frontend.js +++ b/ext/fg/js/frontend.js @@ -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); diff --git a/ext/mixed/js/display.js b/ext/mixed/js/display.js index 801011df..8ad3ee1b 100644 --- a/ext/mixed/js/display.js +++ b/ext/mixed/js/display.js @@ -112,7 +112,7 @@ class Display { try { textSource.setEndOffset(this.options.scanning.length); - ({definitions, length} = await apiTermsFind(textSource.text(), this.getOptionsContext())); + ({definitions, length} = await apiTermsFind(textSource.text(), {}, this.getOptionsContext())); if (definitions.length === 0) { return false; } -- cgit v1.2.3 From c35a05cd62d43ff435c022a353de55510b020277 Mon Sep 17 00:00:00 2001 From: siikamiika Date: Wed, 30 Oct 2019 03:58:24 +0200 Subject: add kana to text --- ext/bg/js/api.js | 37 +++++++++++++++ ext/bg/js/backend.js | 1 + ext/bg/js/search-query-parser.js | 97 ++++++++++++++++++++++++++++++++++++---- ext/fg/js/api.js | 4 ++ ext/mixed/css/display.css | 4 ++ ext/mixed/js/display.js | 78 +++++++++++++++++++++----------- 6 files changed, 188 insertions(+), 33 deletions(-) (limited to 'ext/bg/js/api.js') diff --git a/ext/bg/js/api.js b/ext/bg/js/api.js index df73aa2a..064903ca 100644 --- a/ext/bg/js/api.js +++ b/ext/bg/js/api.js @@ -79,6 +79,43 @@ async function apiTermsFind(text, details, optionsContext) { return {length, definitions}; } +async function apiTextParse(text, optionsContext) { + const options = await apiOptionsGet(optionsContext); + const translator = utilBackend().translator; + + const results = []; + while (text) { + let [definitions, length] = await translator.findTerms(text, {}, options); + if (definitions.length > 0) { + definitions = dictTermsSort(definitions); + const {expression, source, reading} = definitions[0]; + + let stemLength = source.length; + while (source[stemLength - 1] !== expression[stemLength - 1]) { + --stemLength; + } + const offset = source.length - stemLength; + + for (const result of jpDistributeFurigana( + source.slice(0, offset === 0 ? source.length : source.length - offset), + reading.slice(0, offset === 0 ? reading.length : source.length + (reading.length - expression.length) - offset) + )) { + results.push(result); + } + + if (stemLength !== source.length) { + results.push({text: source.slice(stemLength)}); + } + + text = text.slice(source.length); + } else { + results.push({text: text[0]}); + text = text.slice(1); + } + } + return results; +} + async function apiKanjiFind(text, optionsContext) { const options = await apiOptionsGet(optionsContext); const definitions = await utilBackend().translator.findKanji(text, options); diff --git a/ext/bg/js/backend.js b/ext/bg/js/backend.js index efad153a..d0e404f2 100644 --- a/ext/bg/js/backend.js +++ b/ext/bg/js/backend.js @@ -180,6 +180,7 @@ Backend.messageHandlers = { optionsSet: ({changedOptions, optionsContext, source}) => apiOptionsSet(changedOptions, optionsContext, source), kanjiFind: ({text, optionsContext}) => apiKanjiFind(text, optionsContext), termsFind: ({text, details, optionsContext}) => apiTermsFind(text, details, optionsContext), + textParse: ({text, optionsContext}) => apiTextParse(text, optionsContext), definitionAdd: ({definition, mode, context, optionsContext}) => apiDefinitionAdd(definition, mode, context, optionsContext), definitionsAddable: ({definitions, modes, optionsContext}) => apiDefinitionsAddable(definitions, modes, optionsContext), noteView: ({noteId}) => apiNoteView(noteId), diff --git a/ext/bg/js/search-query-parser.js b/ext/bg/js/search-query-parser.js index debe53b4..c3a3900b 100644 --- a/ext/bg/js/search-query-parser.js +++ b/ext/bg/js/search-query-parser.js @@ -23,22 +23,103 @@ class QueryParser { this.queryParser = document.querySelector('#query-parser'); - // TODO also enable for mouseover scanning - this.queryParser.addEventListener('click', (e) => this.onTermLookup(e)); + this.queryParser.addEventListener('click', (e) => this.onClick(e)); + this.queryParser.addEventListener('mousemove', (e) => this.onMouseMove(e)); } onError(error) { logError(error, false); } - async onTermLookup(e) { - const {textSource} = await this.search.onTermLookup(e, {isQueryParser: true}); - if (textSource) { - textSource.select(); + onClick(e) { + this.onTermLookup(e, {disableScroll: true, selectText: true}); + } + + async onMouseMove(e) { + if ( + (e.buttons & 0x1) !== 0x0 // Left mouse button + ) { + return; + } + + const scanningOptions = this.search.options.scanning; + const scanningModifier = scanningOptions.modifier; + if (!( + QueryParser.isScanningModifierPressed(scanningModifier, e) || + (scanningOptions.middleMouse && (e.buttons & 0x4) !== 0x0) // Middle mouse button + )) { + return; } + + await this.onTermLookup(e, {disableScroll: true, selectText: true, disableHistory: true}) + } + + onTermLookup(e, params) { + this.search.onTermLookup(e, params); } - setText(text) { - this.queryParser.innerText = text; + async setText(text) { + this.search.setSpinnerVisible(true); + + const results = await apiTextParse(text, this.search.getOptionsContext()); + + const tempContainer = document.createElement('div'); + for (const {text, furigana} of results) { + if (furigana) { + const rubyElement = document.createElement('ruby'); + const furiganaElement = document.createElement('rt'); + furiganaElement.innerText = furigana; + rubyElement.appendChild(document.createTextNode(text)); + rubyElement.appendChild(furiganaElement); + tempContainer.appendChild(rubyElement); + } else { + tempContainer.appendChild(document.createTextNode(text)); + } + } + this.queryParser.innerHTML = ''; + this.queryParser.appendChild(tempContainer); + + this.search.setSpinnerVisible(false); + } + + async parseText(text) { + const results = []; + while (text) { + const {definitions, length} = await apiTermsFind(text, {}, this.search.getOptionsContext()); + if (length) { + results.push(definitions); + text = text.slice(length); + } else { + results.push(text[0]); + text = text.slice(1); + } + } + return results; + } + + popupTimerSet(callback) { + const delay = this.options.scanning.delay; + if (delay > 0) { + this.popupTimer = window.setTimeout(callback, delay); + } else { + Promise.resolve().then(callback); + } + } + + popupTimerClear() { + if (this.popupTimer !== null) { + window.clearTimeout(this.popupTimer); + this.popupTimer = null; + } + } + + static isScanningModifierPressed(scanningModifier, mouseEvent) { + switch (scanningModifier) { + case 'alt': return mouseEvent.altKey; + case 'ctrl': return mouseEvent.ctrlKey; + case 'shift': return mouseEvent.shiftKey; + case 'none': return true; + default: return false; + } } } diff --git a/ext/fg/js/api.js b/ext/fg/js/api.js index 945ba076..cc1e0e90 100644 --- a/ext/fg/js/api.js +++ b/ext/fg/js/api.js @@ -29,6 +29,10 @@ function apiTermsFind(text, details, optionsContext) { return utilInvoke('termsFind', {text, details, optionsContext}); } +function apiTextParse(text, optionsContext) { + return utilInvoke('textParse', {text, optionsContext}); +} + function apiKanjiFind(text, optionsContext) { return utilInvoke('kanjiFind', {text, optionsContext}); } diff --git a/ext/mixed/css/display.css b/ext/mixed/css/display.css index 5e5213ff..81109fc6 100644 --- a/ext/mixed/css/display.css +++ b/ext/mixed/css/display.css @@ -73,6 +73,10 @@ ol, ul { } +html:root[data-yomichan-page=search] body { + min-height: 101vh; /* always show scroll bar to avoid scanning problems */ +} + /* * Search page */ diff --git a/ext/mixed/js/display.js b/ext/mixed/js/display.js index 07a851f5..82385bf9 100644 --- a/ext/mixed/js/display.js +++ b/ext/mixed/js/display.js @@ -98,17 +98,62 @@ class Display { } } - async onTermLookup(e) { + async onTermLookup(e, {disableScroll, selectText, disableHistory}) { + const termLookupResults = await this.termLookup(e); + if (!termLookupResults) { + return false; + } + + try { + const {textSource, definitions} = termLookupResults; + + const scannedElement = e.target; + const sentence = docSentenceExtract(textSource, this.options.anki.sentenceExt); + + if (!disableScroll) { + this.windowScroll.toY(0); + } + let context; + if (disableHistory) { + const {url, source} = this.context || {}; + context = {sentence, url, source, disableScroll}; + } else { + context = { + disableScroll, + source: { + definitions: this.definitions, + index: this.entryIndexFind(scannedElement), + scroll: this.windowScroll.y + } + }; + + if (this.context) { + context.sentence = sentence; + context.url = this.context.url; + context.source.source = this.context.source; + } + } + + this.setContentTerms(definitions, context); + + if (selectText) { + textSource.select(); + } + } catch (error) { + this.onError(error); + } + } + + async termLookup(e) { try { e.preventDefault(); - const clickedElement = e.target; const textSource = docRangeFromPoint(e.clientX, e.clientY, this.options); if (textSource === null) { return false; } - let definitions, length, sentence; + let definitions, length; try { textSource.setEndOffset(this.options.scanning.length); @@ -118,30 +163,11 @@ class Display { } textSource.setEndOffset(length); - - sentence = docSentenceExtract(textSource, this.options.anki.sentenceExt); } finally { textSource.cleanup(); } - this.windowScroll.toY(0); - const context = { - source: { - definitions: this.definitions, - index: this.entryIndexFind(clickedElement), - scroll: this.windowScroll.y - } - }; - - if (this.context) { - context.sentence = sentence; - context.url = this.context.url; - context.source.source = this.context.source; - } - - this.setContentTerms(definitions, context); - - return {textSource}; + return {textSource, definitions}; } catch (error) { this.onError(error); } @@ -338,8 +364,10 @@ class Display { const content = await apiTemplateRender('terms.html', params); this.container.innerHTML = content; - const {index, scroll} = context || {}; - this.entryScrollIntoView(index || 0, scroll); + const {index, scroll, disableScroll} = context || {}; + if (!disableScroll) { + this.entryScrollIntoView(index || 0, scroll); + } if (options.audio.enabled && options.audio.autoPlay) { this.autoPlayAudio(); -- cgit v1.2.3 From d19f447b80e286610a83114e2294a976a27adca5 Mon Sep 17 00:00:00 2001 From: siikamiika Date: Wed, 30 Oct 2019 12:04:49 +0200 Subject: fix stem length checking Starting from the end and stopping at first match doesn't guarantee correctness. Starting from the beginning does. --- ext/bg/js/api.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'ext/bg/js/api.js') diff --git a/ext/bg/js/api.js b/ext/bg/js/api.js index 064903ca..174a439e 100644 --- a/ext/bg/js/api.js +++ b/ext/bg/js/api.js @@ -90,9 +90,10 @@ async function apiTextParse(text, optionsContext) { definitions = dictTermsSort(definitions); const {expression, source, reading} = definitions[0]; - let stemLength = source.length; - while (source[stemLength - 1] !== expression[stemLength - 1]) { - --stemLength; + let stemLength = 0; + const shortest = Math.min(source.length, expression.length); + while (stemLength < shortest && source[stemLength] === expression[stemLength]) { + ++stemLength; } const offset = source.length - stemLength; -- cgit v1.2.3 From e6a1b781648b8ab965a4508ea29ab85f0e070b35 Mon Sep 17 00:00:00 2001 From: siikamiika Date: Wed, 30 Oct 2019 18:13:45 +0200 Subject: use correct source text --- ext/bg/js/api.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'ext/bg/js/api.js') diff --git a/ext/bg/js/api.js b/ext/bg/js/api.js index 174a439e..dbbe7368 100644 --- a/ext/bg/js/api.js +++ b/ext/bg/js/api.js @@ -85,10 +85,11 @@ async function apiTextParse(text, optionsContext) { const results = []; while (text) { - let [definitions, length] = await translator.findTerms(text, {}, options); + let [definitions, sourceLength] = await translator.findTerms(text, {}, options); if (definitions.length > 0) { definitions = dictTermsSort(definitions); - const {expression, source, reading} = definitions[0]; + const {expression, reading} = definitions[0]; + const source = text.slice(0, sourceLength); let stemLength = 0; const shortest = Math.min(source.length, expression.length); -- cgit v1.2.3 From 3881457e4ed3f9c7833ac21a5e7fc44c2ba00b0f Mon Sep 17 00:00:00 2001 From: siikamiika Date: Thu, 31 Oct 2019 23:56:44 +0200 Subject: use handlebars templates for query parser --- ext/bg/js/api.js | 12 +++++----- ext/bg/js/search-query-parser.js | 40 ++++++++++++++------------------- ext/bg/js/templates.js | 48 ++++++++++++++++++++++++++++++++++++++++ ext/mixed/css/display.css | 9 ++++---- tmpl/query-parser.html | 23 +++++++++++++++++++ 5 files changed, 99 insertions(+), 33 deletions(-) create mode 100644 tmpl/query-parser.html (limited to 'ext/bg/js/api.js') diff --git a/ext/bg/js/api.js b/ext/bg/js/api.js index dbbe7368..7c9a72a7 100644 --- a/ext/bg/js/api.js +++ b/ext/bg/js/api.js @@ -85,6 +85,7 @@ async function apiTextParse(text, optionsContext) { const results = []; while (text) { + const term = []; let [definitions, sourceLength] = await translator.findTerms(text, {}, options); if (definitions.length > 0) { definitions = dictTermsSort(definitions); @@ -98,22 +99,23 @@ async function apiTextParse(text, optionsContext) { } const offset = source.length - stemLength; - for (const result of jpDistributeFurigana( + for (const {text, furigana} of jpDistributeFurigana( source.slice(0, offset === 0 ? source.length : source.length - offset), - reading.slice(0, offset === 0 ? reading.length : source.length + (reading.length - expression.length) - offset) + reading.slice(0, offset === 0 ? reading.length : reading.length - expression.length + stemLength) )) { - results.push(result); + term.push({text, reading: furigana || ''}); } if (stemLength !== source.length) { - results.push({text: source.slice(stemLength)}); + term.push({text: source.slice(stemLength)}); } text = text.slice(source.length); } else { - results.push({text: text[0]}); + term.push({text: text[0]}); text = text.slice(1); } + results.push(term); } return results; } diff --git a/ext/bg/js/search-query-parser.js b/ext/bg/js/search-query-parser.js index 9bea6508..8a7db69a 100644 --- a/ext/bg/js/search-query-parser.js +++ b/ext/bg/js/search-query-parser.js @@ -59,39 +59,33 @@ class QueryParser { } async setText(text) { - this.queryParser.innerHTML = ''; this.search.setSpinnerVisible(true); + const previewTerms = []; let previewText = text; while (previewText) { const tempText = previewText.slice(0, 2); + previewTerms.push([{text: tempText}]); previewText = previewText.slice(2); - - const tempRuby = document.createElement('ruby'); - const tempFurigana = document.createElement('rt'); - tempRuby.appendChild(document.createTextNode(tempText)); - tempRuby.appendChild(tempFurigana); - this.queryParser.appendChild(tempRuby); } + this.queryParser.innerHTML = await apiTemplateRender('query-parser.html', { + terms: previewTerms, + preview: true + }); + const results = await apiTextParse(text, this.search.getOptionsContext()); - const textContainer = document.createElement('div'); - for (const {text, furigana} of results) { - const rubyElement = document.createElement('ruby'); - const furiganaElement = document.createElement('rt'); - if (furigana) { - furiganaElement.innerText = furigana; - rubyElement.appendChild(document.createTextNode(text)); - rubyElement.appendChild(furiganaElement); - } else { - rubyElement.appendChild(document.createTextNode(text)); - rubyElement.appendChild(furiganaElement); - } - textContainer.appendChild(rubyElement); - } - this.queryParser.innerHTML = ''; - this.queryParser.appendChild(textContainer); + const content = await apiTemplateRender('query-parser.html', { + terms: results.map((term) => { + return term.map((part) => { + part.raw = !part.text.trim() && (!part.reading || !part.reading.trim()); + return part; + }); + }) + }); + + this.queryParser.innerHTML = content; this.search.setSpinnerVisible(false); } diff --git a/ext/bg/js/templates.js b/ext/bg/js/templates.js index 823b9e6f..cc233d49 100644 --- a/ext/bg/js/templates.js +++ b/ext/bg/js/templates.js @@ -162,6 +162,54 @@ templates['kanji.html'] = template({"1":function(container,depth0,helpers,partia return fn; } +,"useDecorators":true,"usePartial":true,"useData":true,"useDepths":true}); +templates['query-parser.html'] = template({"1":function(container,depth0,helpers,partials,data) { + var stack1, alias1=depth0 != null ? depth0 : (container.nullContext || {}); + + return ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.preview : depth0),{"name":"if","hash":{},"fn":container.program(2, data, 0),"inverse":container.program(4, data, 0),"data":data})) != null ? stack1 : "") + + ((stack1 = helpers.each.call(alias1,depth0,{"name":"each","hash":{},"fn":container.program(6, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") + + ""; +},"2":function(container,depth0,helpers,partials,data) { + return ""; +},"4":function(container,depth0,helpers,partials,data) { + return ""; +},"6":function(container,depth0,helpers,partials,data) { + var stack1; + + return ((stack1 = container.invokePartial(partials.part,depth0,{"name":"part","data":data,"helpers":helpers,"partials":partials,"decorators":container.decorators})) != null ? stack1 : ""); +},"8":function(container,depth0,helpers,partials,data) { + var stack1; + + return ((stack1 = helpers["if"].call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? depth0.raw : depth0),{"name":"if","hash":{},"fn":container.program(9, data, 0),"inverse":container.program(11, data, 0),"data":data})) != null ? stack1 : ""); +},"9":function(container,depth0,helpers,partials,data) { + var helper; + + return container.escapeExpression(((helper = (helper = helpers.text || (depth0 != null ? depth0.text : depth0)) != null ? helper : helpers.helperMissing),(typeof helper === "function" ? helper.call(depth0 != null ? depth0 : (container.nullContext || {}),{"name":"text","hash":{},"data":data}) : helper))); +},"11":function(container,depth0,helpers,partials,data) { + var helper, alias1=depth0 != null ? depth0 : (container.nullContext || {}), alias2=helpers.helperMissing, alias3="function", alias4=container.escapeExpression; + + return "" + + alias4(((helper = (helper = helpers.text || (depth0 != null ? depth0.text : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"text","hash":{},"data":data}) : helper))) + + "" + + alias4(((helper = (helper = helpers.reading || (depth0 != null ? depth0.reading : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"reading","hash":{},"data":data}) : helper))) + + ""; +},"13":function(container,depth0,helpers,partials,data,blockParams,depths) { + var stack1; + + return ((stack1 = container.invokePartial(partials.term,depth0,{"name":"term","hash":{"preview":(depths[1] != null ? depths[1].preview : depths[1])},"data":data,"helpers":helpers,"partials":partials,"decorators":container.decorators})) != null ? stack1 : ""); +},"compiler":[7,">= 4.0.0"],"main":function(container,depth0,helpers,partials,data,blockParams,depths) { + var stack1; + + return ((stack1 = helpers.each.call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? depth0.terms : depth0),{"name":"each","hash":{},"fn":container.program(13, data, 0, blockParams, depths),"inverse":container.noop,"data":data})) != null ? stack1 : ""); +},"main_d": function(fn, props, container, depth0, data, blockParams, depths) { + + var decorators = container.decorators; + + fn = decorators.inline(fn,props,container,{"name":"inline","hash":{},"fn":container.program(1, data, 0, blockParams, depths),"inverse":container.noop,"args":["term"],"data":data}) || fn; + fn = decorators.inline(fn,props,container,{"name":"inline","hash":{},"fn":container.program(8, data, 0, blockParams, depths),"inverse":container.noop,"args":["part"],"data":data}) || fn; + return fn; + } + ,"useDecorators":true,"usePartial":true,"useData":true,"useDepths":true}); templates['terms.html'] = template({"1":function(container,depth0,helpers,partials,data) { var stack1, helper, options, alias1=depth0 != null ? depth0 : (container.nullContext || {}), buffer = diff --git a/ext/mixed/css/display.css b/ext/mixed/css/display.css index 65b8b466..d24aa58c 100644 --- a/ext/mixed/css/display.css +++ b/ext/mixed/css/display.css @@ -93,13 +93,12 @@ ol, ul { font-size: 24px; } -html:root[data-yomichan-page=search] body { - min-height: 101vh; /* always show scroll bar to avoid scanning problems */ +.query-parser-term { + margin-right: 5px; } -#query-parser { - margin-top: 10px; - font-size: 24px; +html:root[data-yomichan-page=search] body { + min-height: 101vh; /* always show scroll bar to avoid scanning problems */ } diff --git a/tmpl/query-parser.html b/tmpl/query-parser.html new file mode 100644 index 00000000..818650e6 --- /dev/null +++ b/tmpl/query-parser.html @@ -0,0 +1,23 @@ +{{~#*inline "term"~}} +{{~#if preview~}} + +{{~else~}} + +{{~/if~}} +{{~#each this~}} +{{> part }} +{{~/each~}} + +{{~/inline~}} + +{{~#*inline "part"~}} +{{~#if raw~}} +{{text}} +{{~else~}} +{{text}}{{reading}} +{{~/if~}} +{{~/inline~}} + +{{~#each terms~}} +{{> term preview=../preview }} +{{~/each~}} -- cgit v1.2.3 From 41020289ab68ef22a0691a9f268a79d6a706df6b Mon Sep 17 00:00:00 2001 From: siikamiika Date: Sun, 3 Nov 2019 05:08:57 +0200 Subject: add mecab support --- ext/bg/background.html | 1 + ext/bg/js/api.js | 48 ++++++++++++++++++------------ ext/bg/js/backend.js | 2 ++ ext/bg/js/mecab.js | 63 ++++++++++++++++++++++++++++++++++++++++ ext/bg/js/search-query-parser.js | 3 +- ext/fg/js/api.js | 4 +++ ext/manifest.json | 3 +- ext/mixed/js/japanese.js | 35 ++++++++++++++++++++-- 8 files changed, 136 insertions(+), 23 deletions(-) create mode 100644 ext/bg/js/mecab.js (limited to 'ext/bg/js/api.js') diff --git a/ext/bg/background.html b/ext/bg/background.html index bbfbd1e1..6e6e7c26 100644 --- a/ext/bg/background.html +++ b/ext/bg/background.html @@ -21,6 +21,7 @@ + diff --git a/ext/bg/js/api.js b/ext/bg/js/api.js index 7c9a72a7..2ab01af3 100644 --- a/ext/bg/js/api.js +++ b/ext/bg/js/api.js @@ -91,25 +91,10 @@ async function apiTextParse(text, optionsContext) { definitions = dictTermsSort(definitions); const {expression, reading} = definitions[0]; const source = text.slice(0, sourceLength); - - let stemLength = 0; - const shortest = Math.min(source.length, expression.length); - while (stemLength < shortest && source[stemLength] === expression[stemLength]) { - ++stemLength; - } - const offset = source.length - stemLength; - - for (const {text, furigana} of jpDistributeFurigana( - source.slice(0, offset === 0 ? source.length : source.length - offset), - reading.slice(0, offset === 0 ? reading.length : reading.length - expression.length + stemLength) - )) { - term.push({text, reading: furigana || ''}); - } - - if (stemLength !== source.length) { - term.push({text: source.slice(stemLength)}); + for (const {text, furigana} of jpDistributeFuriganaInflected(expression, reading, source)) { + // can't use 'furigana' in templates + term.push({text, reading: furigana}); } - text = text.slice(source.length); } else { term.push({text: text[0]}); @@ -120,6 +105,33 @@ async function apiTextParse(text, optionsContext) { return results; } +async function apiTextParseMecab(text, optionsContext) { + const options = await apiOptionsGet(optionsContext); + const mecab = utilBackend().mecab; + + const results = []; + for (const parsedLine of await mecab.parseText(text)) { + for (const {expression, reading, source} of parsedLine) { + const term = []; + if (expression && reading) { + for (const {text, furigana} of jpDistributeFuriganaInflected( + expression, + jpKatakanaToHiragana(reading), + source + )) { + // can't use 'furigana' in templates + term.push({text, reading: furigana}); + } + } else { + term.push({text: source}); + } + results.push(term); + } + results.push([{text: '\n'}]); + } + return results; +} + async function apiKanjiFind(text, optionsContext) { const options = await apiOptionsGet(optionsContext); const definitions = await utilBackend().translator.findKanji(text, options); diff --git a/ext/bg/js/backend.js b/ext/bg/js/backend.js index d0e404f2..e97f32b5 100644 --- a/ext/bg/js/backend.js +++ b/ext/bg/js/backend.js @@ -21,6 +21,7 @@ class Backend { constructor() { this.translator = new Translator(); this.anki = new AnkiNull(); + this.mecab = new Mecab(); this.options = null; this.optionsContext = { depth: 0, @@ -181,6 +182,7 @@ Backend.messageHandlers = { kanjiFind: ({text, optionsContext}) => apiKanjiFind(text, optionsContext), termsFind: ({text, details, optionsContext}) => apiTermsFind(text, details, optionsContext), textParse: ({text, optionsContext}) => apiTextParse(text, optionsContext), + textParseMecab: ({text, optionsContext}) => apiTextParseMecab(text, optionsContext), definitionAdd: ({definition, mode, context, optionsContext}) => apiDefinitionAdd(definition, mode, context, optionsContext), definitionsAddable: ({definitions, modes, optionsContext}) => apiDefinitionsAddable(definitions, modes, optionsContext), noteView: ({noteId}) => apiNoteView(noteId), diff --git a/ext/bg/js/mecab.js b/ext/bg/js/mecab.js new file mode 100644 index 00000000..dc46ded2 --- /dev/null +++ b/ext/bg/js/mecab.js @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2019 Alex Yatskov + * Author: Alex Yatskov + * + * 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 . + */ + + +class Mecab { + constructor() { + this.listeners = {}; + this.sequence = 0; + this.startListener(); + } + + async parseText(text) { + return await this.invoke('parse_text', {text}); + } + + startListener() { + this.port = chrome.runtime.connectNative('mecab'); + this.port.onMessage.addListener((message) => { + const {sequence, data} = message; + const {callback, timer} = this.listeners[sequence] || {}; + if (timer) { + clearTimeout(timer); + delete this.listeners[sequence]; + callback(data); + } + }); + } + + invoke(action, params) { + return new Promise((resolve, reject) => { + const sequence = this.sequence++; + + this.listeners[sequence] = { + callback: (data) => { + resolve(data); + }, + timer: setTimeout(() => { + delete this.listeners[sequence]; + reject(`Mecab invoke timed out in ${Mecab.timeout} ms`); + }, 1000) + } + + this.port.postMessage({action, params, sequence}); + }); + } +} + +Mecab.timeout = 1000; diff --git a/ext/bg/js/search-query-parser.js b/ext/bg/js/search-query-parser.js index 8a7db69a..0c74e550 100644 --- a/ext/bg/js/search-query-parser.js +++ b/ext/bg/js/search-query-parser.js @@ -74,7 +74,8 @@ class QueryParser { preview: true }); - const results = await apiTextParse(text, this.search.getOptionsContext()); + // const results = await apiTextParse(text, this.search.getOptionsContext()); + const results = await apiTextParseMecab(text, this.search.getOptionsContext()); const content = await apiTemplateRender('query-parser.html', { terms: results.map((term) => { diff --git a/ext/fg/js/api.js b/ext/fg/js/api.js index cc1e0e90..92330d9c 100644 --- a/ext/fg/js/api.js +++ b/ext/fg/js/api.js @@ -33,6 +33,10 @@ function apiTextParse(text, optionsContext) { return utilInvoke('textParse', {text, optionsContext}); } +function apiTextParseMecab(text, optionsContext) { + return utilInvoke('textParseMecab', {text, optionsContext}); +} + function apiKanjiFind(text, optionsContext) { return utilInvoke('kanjiFind', {text, optionsContext}); } diff --git a/ext/manifest.json b/ext/manifest.json index fabceafd..4d75cd54 100644 --- a/ext/manifest.json +++ b/ext/manifest.json @@ -42,7 +42,8 @@ "", "storage", "clipboardWrite", - "unlimitedStorage" + "unlimitedStorage", + "nativeMessaging" ], "optional_permissions": [ "clipboardRead" diff --git a/ext/mixed/js/japanese.js b/ext/mixed/js/japanese.js index d24f56a6..78c419b2 100644 --- a/ext/mixed/js/japanese.js +++ b/ext/mixed/js/japanese.js @@ -61,12 +61,11 @@ function jpDistributeFurigana(expression, reading) { const group = groups[0]; if (group.mode === 'kana') { - if (reading.startsWith(group.text)) { - const readingUsed = reading.substring(0, group.text.length); + if (jpKatakanaToHiragana(reading).startsWith(jpKatakanaToHiragana(group.text))) { const readingLeft = reading.substring(group.text.length); const segs = segmentize(readingLeft, groups.splice(1)); if (segs) { - return [{text: readingUsed}].concat(segs); + return [{text: group.text}].concat(segs); } } } else { @@ -95,3 +94,33 @@ function jpDistributeFurigana(expression, reading) { return segmentize(reading, groups) || fallback; } + +function jpDistributeFuriganaInflected(expression, reading, source) { + const output = []; + + let stemLength = 0; + const shortest = Math.min(source.length, expression.length); + const sourceHiragana = jpKatakanaToHiragana(source); + const expressionHiragana = jpKatakanaToHiragana(expression); + while ( + stemLength < shortest && + // sometimes an expression can use a kanji that's different from the source + (!jpIsKana(source[stemLength]) || (sourceHiragana[stemLength] === expressionHiragana[stemLength])) + ) { + ++stemLength; + } + const offset = source.length - stemLength; + + for (const segment of jpDistributeFurigana( + source.slice(0, offset === 0 ? source.length : source.length - offset), + reading.slice(0, offset === 0 ? reading.length : reading.length - expression.length + stemLength) + )) { + output.push(segment); + } + + if (stemLength !== source.length) { + output.push({text: source.slice(stemLength)}); + } + + return output; +} -- cgit v1.2.3 From 955e131f9673e006556bc2c5e0b3551a614ccc48 Mon Sep 17 00:00:00 2001 From: siikamiika Date: Tue, 5 Nov 2019 15:56:45 +0200 Subject: add parser selection options --- ext/bg/js/api.js | 37 +++++++++++++++++++++---------------- ext/bg/js/mecab.js | 2 +- ext/bg/js/options.js | 5 +++++ ext/bg/js/search-query-parser.js | 40 +++++++++++++++++++++++++--------------- ext/bg/js/settings.js | 6 ++++++ ext/bg/settings.html | 29 +++++++++++++++++++++++++++++ 6 files changed, 87 insertions(+), 32 deletions(-) (limited to 'ext/bg/js/api.js') diff --git a/ext/bg/js/api.js b/ext/bg/js/api.js index 2ab01af3..967bded7 100644 --- a/ext/bg/js/api.js +++ b/ext/bg/js/api.js @@ -109,25 +109,30 @@ async function apiTextParseMecab(text, optionsContext) { const options = await apiOptionsGet(optionsContext); const mecab = utilBackend().mecab; - const results = []; - for (const parsedLine of await mecab.parseText(text)) { - for (const {expression, reading, source} of parsedLine) { - const term = []; - if (expression && reading) { - for (const {text, furigana} of jpDistributeFuriganaInflected( - expression, - jpKatakanaToHiragana(reading), - source - )) { - // can't use 'furigana' in templates - term.push({text, reading: furigana}); + const results = {}; + const rawResults = await mecab.parseText(text); + for (const mecabName in rawResults) { + const result = []; + for (const parsedLine of rawResults[mecabName]) { + for (const {expression, reading, source} of parsedLine) { + const term = []; + if (expression && reading) { + for (const {text, furigana} of jpDistributeFuriganaInflected( + expression, + jpKatakanaToHiragana(reading), + source + )) { + // can't use 'furigana' in templates + term.push({text, reading: furigana}); + } + } else { + term.push({text: source}); } - } else { - term.push({text: source}); + result.push(term); } - results.push(term); + result.push([{text: '\n'}]); } - results.push([{text: '\n'}]); + results[mecabName] = result; } return results; } diff --git a/ext/bg/js/mecab.js b/ext/bg/js/mecab.js index 14f68393..fba9b2eb 100644 --- a/ext/bg/js/mecab.js +++ b/ext/bg/js/mecab.js @@ -60,4 +60,4 @@ class Mecab { } } -Mecab.timeout = 1000; +Mecab.timeout = 5000; diff --git a/ext/bg/js/options.js b/ext/bg/js/options.js index be1ccfbb..f1bafaf9 100644 --- a/ext/bg/js/options.js +++ b/ext/bg/js/options.js @@ -311,6 +311,11 @@ function profileOptionsCreateDefaults() { dictionaries: {}, + parsing: { + enableScanningParser: true, + enableMecabParser: false + }, + anki: { enable: false, server: 'http://127.0.0.1:8765', diff --git a/ext/bg/js/search-query-parser.js b/ext/bg/js/search-query-parser.js index 1cf00425..81eb18c3 100644 --- a/ext/bg/js/search-query-parser.js +++ b/ext/bg/js/search-query-parser.js @@ -86,22 +86,32 @@ class QueryParser { this.search.setSpinnerVisible(true); await this.setPreview(text); - // const results = await apiTextParse(text, this.search.getOptionsContext()); - const results = await apiTextParseMecab(text, this.search.getOptionsContext()); - - const content = await apiTemplateRender('query-parser.html', { - terms: results.map((term) => { - return term.filter(part => part.text.trim()).map((part) => { - return { - text: Array.from(part.text), - reading: part.reading, - raw: !part.reading || !part.reading.trim(), - }; - }); - }) - }); + const results = {}; + if (this.search.options.parsing.enableScanningParser) { + results['scan'] = await apiTextParse(text, this.search.getOptionsContext()); + } + if (this.search.options.parsing.enableMecabParser) { + let mecabResults = await apiTextParseMecab(text, this.search.getOptionsContext()); + for (const mecabDictName in mecabResults) { + results[`mecab-${mecabDictName}`] = mecabResults[mecabDictName]; + } + } - this.queryParser.innerHTML = content; + const contents = await Promise.all(Object.values(results).map(async result => { + return await apiTemplateRender('query-parser.html', { + terms: result.map((term) => { + return term.filter(part => part.text.trim()).map((part) => { + return { + text: Array.from(part.text), + reading: part.reading, + raw: !part.reading || !part.reading.trim(), + }; + }); + }) + }); + })); + + this.queryParser.innerHTML = contents.join('
'); this.queryParser.querySelectorAll('.query-parser-char').forEach((charElement) => { this.activateScanning(charElement); diff --git a/ext/bg/js/settings.js b/ext/bg/js/settings.js index e562c54e..f4fe032a 100644 --- a/ext/bg/js/settings.js +++ b/ext/bg/js/settings.js @@ -64,6 +64,9 @@ async function formRead(options) { options.scanning.modifier = $('#scan-modifier-key').val(); options.scanning.popupNestingMaxDepth = parseInt($('#popup-nesting-max-depth').val(), 10); + options.parsing.enableScanningParser = $('#parsing-scan-enable').prop('checked'); + options.parsing.enableMecabParser = $('#parsing-mecab-enable').prop('checked'); + const optionsAnkiEnableOld = options.anki.enable; options.anki.enable = $('#anki-enable').prop('checked'); options.anki.tags = utilBackgroundIsolate($('#card-tags').val().split(/[,; ]+/)); @@ -126,6 +129,9 @@ async function formWrite(options) { $('#scan-modifier-key').val(options.scanning.modifier); $('#popup-nesting-max-depth').val(options.scanning.popupNestingMaxDepth); + $('#parsing-scan-enable').prop('checked', options.parsing.enableScanningParser); + $('#parsing-mecab-enable').prop('checked', options.parsing.enableMecabParser); + $('#anki-enable').prop('checked', options.anki.enable); $('#card-tags').val(options.anki.tags.join(' ')); $('#sentence-detection-extent').val(options.anki.sentenceExt); diff --git a/ext/bg/settings.html b/ext/bg/settings.html index bdcc11d3..8505567b 100644 --- a/ext/bg/settings.html +++ b/ext/bg/settings.html @@ -587,6 +587,35 @@ +
+

Text Parsing Options

+ +

+ Yomichan can attempt to parse entire sentences or longer text blocks on the search page, + adding furigana above words and a small space between words. +

+ +

+ Two types of parsers are supported. The first one, enabled by default, works using the built-in + scanning functionality by automatically advancing in the sentence after a matching word. +

+ +

+ The second type is an external program called MeCab + that uses its own dictionaries and a special parsing algorithm. To get it working, you must first + install it and a native messaging component + that acts as a bridge between the program and Yomichan. +

+ +
+ +
+ +
+ +
+
+
-- cgit v1.2.3 From b336ab3a9a0a2ac9a569ae217b506ceeeab6fda0 Mon Sep 17 00:00:00 2001 From: siikamiika Date: Mon, 11 Nov 2019 01:43:35 +0200 Subject: use const --- ext/bg/js/api.js | 4 ++-- ext/bg/js/search-query-parser.js | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'ext/bg/js/api.js') diff --git a/ext/bg/js/api.js b/ext/bg/js/api.js index 967bded7..40e9b6d2 100644 --- a/ext/bg/js/api.js +++ b/ext/bg/js/api.js @@ -86,9 +86,9 @@ async function apiTextParse(text, optionsContext) { const results = []; while (text) { const term = []; - let [definitions, sourceLength] = await translator.findTerms(text, {}, options); + const [definitions, sourceLength] = await translator.findTerms(text, {}, options); if (definitions.length > 0) { - definitions = dictTermsSort(definitions); + dictTermsSort(definitions); const {expression, reading} = definitions[0]; const source = text.slice(0, sourceLength); for (const {text, furigana} of jpDistributeFuriganaInflected(expression, reading, source)) { diff --git a/ext/bg/js/search-query-parser.js b/ext/bg/js/search-query-parser.js index 2e17688e..f8e53963 100644 --- a/ext/bg/js/search-query-parser.js +++ b/ext/bg/js/search-query-parser.js @@ -113,9 +113,9 @@ class QueryParser { this.queryParser.innerHTML = contents.join('
'); - this.queryParser.querySelectorAll('.query-parser-char').forEach((charElement) => { + for (const charElement of this.queryParser.querySelectorAll('.query-parser-char')) { this.activateScanning(charElement); - }); + } this.search.setSpinnerVisible(false); } @@ -133,9 +133,9 @@ class QueryParser { preview: true }); - this.queryParser.querySelectorAll('.query-parser-char').forEach((charElement) => { + for (const charElement of this.queryParser.querySelectorAll('.query-parser-char')) { this.activateScanning(charElement); - }); + } } activateScanning(element) { -- cgit v1.2.3 From b02a30a2fddb3b660a62f66541e90dba519cb270 Mon Sep 17 00:00:00 2001 From: siikamiika Date: Mon, 11 Nov 2019 21:43:35 +0200 Subject: explicit checks in while and if --- ext/bg/js/api.js | 4 ++-- ext/bg/js/search-query-parser.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'ext/bg/js/api.js') diff --git a/ext/bg/js/api.js b/ext/bg/js/api.js index 40e9b6d2..bc9dfba1 100644 --- a/ext/bg/js/api.js +++ b/ext/bg/js/api.js @@ -84,7 +84,7 @@ async function apiTextParse(text, optionsContext) { const translator = utilBackend().translator; const results = []; - while (text) { + while (text.length > 0) { const term = []; const [definitions, sourceLength] = await translator.findTerms(text, {}, options); if (definitions.length > 0) { @@ -116,7 +116,7 @@ async function apiTextParseMecab(text, optionsContext) { for (const parsedLine of rawResults[mecabName]) { for (const {expression, reading, source} of parsedLine) { const term = []; - if (expression && reading) { + if (expression !== null && reading !== null) { for (const {text, furigana} of jpDistributeFuriganaInflected( expression, jpKatakanaToHiragana(reading), diff --git a/ext/bg/js/search-query-parser.js b/ext/bg/js/search-query-parser.js index 2aee45dd..14b78105 100644 --- a/ext/bg/js/search-query-parser.js +++ b/ext/bg/js/search-query-parser.js @@ -122,7 +122,7 @@ class QueryParser { async setPreview(text) { const previewTerms = []; - while (text) { + while (text.length > 0) { const tempText = text.slice(0, 2); previewTerms.push([{text: Array.from(tempText)}]); text = text.slice(2); -- cgit v1.2.3 From cc8221c6ea686521261e2ac562d3d5a6d0b9913a Mon Sep 17 00:00:00 2001 From: siikamiika Date: Wed, 13 Nov 2019 20:24:11 +0200 Subject: add reading modes --- ext/bg/js/api.js | 14 ++++++++------ ext/bg/js/options.js | 3 ++- ext/bg/js/settings.js | 2 ++ ext/bg/settings.html | 9 +++++++++ ext/mixed/js/japanese.js | 37 +++++++++++++++++++++++++++++++++++++ 5 files changed, 58 insertions(+), 7 deletions(-) (limited to 'ext/bg/js/api.js') diff --git a/ext/bg/js/api.js b/ext/bg/js/api.js index bc9dfba1..228447c3 100644 --- a/ext/bg/js/api.js +++ b/ext/bg/js/api.js @@ -92,12 +92,13 @@ async function apiTextParse(text, optionsContext) { const {expression, reading} = definitions[0]; const source = text.slice(0, sourceLength); for (const {text, furigana} of jpDistributeFuriganaInflected(expression, reading, source)) { - // can't use 'furigana' in templates - term.push({text, reading: furigana}); + const reading = jpConvertReading(text, furigana, options.parsing.readingMode); + term.push({text, reading}); } text = text.slice(source.length); } else { - term.push({text: text[0]}); + const reading = jpConvertReading(text[0], null, options.parsing.readingMode); + term.push({text: text[0], reading}); text = text.slice(1); } results.push(term); @@ -122,11 +123,12 @@ async function apiTextParseMecab(text, optionsContext) { jpKatakanaToHiragana(reading), source )) { - // can't use 'furigana' in templates - term.push({text, reading: furigana}); + const reading = jpConvertReading(text, furigana, options.parsing.readingMode); + term.push({text, reading}); } } else { - term.push({text: source}); + const reading = jpConvertReading(source, null, options.parsing.readingMode); + term.push({text: source, reading}); } result.push(term); } diff --git a/ext/bg/js/options.js b/ext/bg/js/options.js index 053fb13d..b9bf85f3 100644 --- a/ext/bg/js/options.js +++ b/ext/bg/js/options.js @@ -314,7 +314,8 @@ function profileOptionsCreateDefaults() { parsing: { enableScanningParser: true, enableMecabParser: false, - selectedParser: null + selectedParser: null, + readingMode: 'hiragana' }, anki: { diff --git a/ext/bg/js/settings.js b/ext/bg/js/settings.js index f4fe032a..ab267c32 100644 --- a/ext/bg/js/settings.js +++ b/ext/bg/js/settings.js @@ -66,6 +66,7 @@ async function formRead(options) { options.parsing.enableScanningParser = $('#parsing-scan-enable').prop('checked'); options.parsing.enableMecabParser = $('#parsing-mecab-enable').prop('checked'); + options.parsing.readingMode = $('#parsing-reading-mode').val(); const optionsAnkiEnableOld = options.anki.enable; options.anki.enable = $('#anki-enable').prop('checked'); @@ -131,6 +132,7 @@ async function formWrite(options) { $('#parsing-scan-enable').prop('checked', options.parsing.enableScanningParser); $('#parsing-mecab-enable').prop('checked', options.parsing.enableMecabParser); + $('#parsing-reading-mode').val(options.parsing.readingMode); $('#anki-enable').prop('checked', options.anki.enable); $('#card-tags').val(options.anki.tags.join(' ')); diff --git a/ext/bg/settings.html b/ext/bg/settings.html index 08b9b6c1..0badb817 100644 --- a/ext/bg/settings.html +++ b/ext/bg/settings.html @@ -437,6 +437,15 @@
+ +
+ + +
diff --git a/ext/mixed/js/japanese.js b/ext/mixed/js/japanese.js index e2d7a090..a7cd0452 100644 --- a/ext/mixed/js/japanese.js +++ b/ext/mixed/js/japanese.js @@ -48,6 +48,43 @@ function jpKatakanaToHiragana(text) { return result; } +function jpHiraganaToKatakana(text) { + let result = ''; + for (const c of text) { + if (wanakana.isHiragana(c)) { + result += wanakana.toKatakana(c); + } else { + result += c; + } + } + + return result; +} + +function jpToRomaji(text) { + return wanakana.toRomaji(text); +} + +function jpConvertReading(expressionFragment, readingFragment, readingMode) { + switch (readingMode) { + case 'hiragana': + return jpKatakanaToHiragana(readingFragment || ''); + case 'katakana': + return jpHiraganaToKatakana(readingFragment || ''); + case 'romaji': + if (readingFragment) { + return jpToRomaji(readingFragment); + } else { + if (jpIsKana(expressionFragment)) { + return jpToRomaji(expressionFragment); + } + } + return readingFragment; + default: + return readingFragment; + } +} + function jpDistributeFurigana(expression, reading) { const fallback = [{furigana: reading, text: expression}]; if (!reading) { -- cgit v1.2.3 From 2577d4054e344d2e6dc08d2cf95e83478c05bee6 Mon Sep 17 00:00:00 2001 From: siikamiika Date: Sat, 23 Nov 2019 18:08:22 +0200 Subject: fix scanning parser --- ext/bg/js/api.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'ext/bg/js/api.js') diff --git a/ext/bg/js/api.js b/ext/bg/js/api.js index 228447c3..766fb0ed 100644 --- a/ext/bg/js/api.js +++ b/ext/bg/js/api.js @@ -86,7 +86,12 @@ async function apiTextParse(text, optionsContext) { const results = []; while (text.length > 0) { const term = []; - const [definitions, sourceLength] = await translator.findTerms(text, {}, options); + const [definitions, sourceLength] = await translator.findTermsInternal( + text.slice(0, options.scanning.length), + dictEnabledSet(options), + options.scanning.alphanumeric, + {} + ); if (definitions.length > 0) { dictTermsSort(definitions); const {expression, reading} = definitions[0]; -- cgit v1.2.3 From 0aed27b66d9c496e4cd57ef95d982c4e634a8666 Mon Sep 17 00:00:00 2001 From: toasted-nutbread Date: Mon, 25 Nov 2019 14:19:18 -0500 Subject: Replace hasOwnProperty with simplified hasOwn function --- ext/bg/js/api.js | 4 ++-- ext/bg/js/audio.js | 6 +++--- ext/bg/js/backend.js | 2 +- ext/bg/js/conditions-ui.js | 20 ++++++++++---------- ext/bg/js/conditions.js | 30 +++++++++++++++--------------- ext/bg/js/database.js | 2 +- ext/bg/js/dictionary.js | 4 ++-- ext/bg/js/mecab.js | 2 +- ext/bg/js/options.js | 2 +- ext/bg/js/search.js | 2 +- ext/bg/js/settings-dictionaries.js | 4 ++-- ext/bg/js/settings-popup-preview.js | 2 +- ext/bg/js/translator.js | 12 ++++++------ ext/fg/js/float.js | 4 ++-- ext/fg/js/frontend-api-receiver.js | 2 +- ext/fg/js/frontend-api-sender.js | 6 +++--- ext/fg/js/frontend.js | 4 ++-- ext/fg/js/popup-proxy-host.js | 4 ++-- ext/mixed/js/audio.js | 2 +- ext/mixed/js/core.js | 4 ++++ ext/mixed/js/display.js | 4 ++-- 21 files changed, 63 insertions(+), 59 deletions(-) (limited to 'ext/bg/js/api.js') diff --git a/ext/bg/js/api.js b/ext/bg/js/api.js index 766fb0ed..12257e92 100644 --- a/ext/bg/js/api.js +++ b/ext/bg/js/api.js @@ -45,7 +45,7 @@ async function apiOptionsSet(changedOptions, optionsContext, source) { function modifyOption(path, value, options) { let pivot = options; for (const key of path.slice(0, -1)) { - if (!pivot.hasOwnProperty(key)) { + if (!hasOwn(pivot, key)) { return false; } pivot = pivot[key]; @@ -236,7 +236,7 @@ async function apiTemplateRender(template, data, dynamic) { async function apiCommandExec(command, params) { const handlers = apiCommandExec.handlers; - if (handlers.hasOwnProperty(command)) { + if (hasOwn(handlers, command)) { const handler = handlers[command]; handler(params); } diff --git a/ext/bg/js/audio.js b/ext/bg/js/audio.js index cd42a158..9bbbf902 100644 --- a/ext/bg/js/audio.js +++ b/ext/bg/js/audio.js @@ -107,12 +107,12 @@ const audioUrlBuilders = { 'custom': async (definition, optionsContext) => { const options = await apiOptionsGet(optionsContext); const customSourceUrl = options.audio.customSourceUrl; - return customSourceUrl.replace(/\{([^\}]*)\}/g, (m0, m1) => (definition.hasOwnProperty(m1) ? `${definition[m1]}` : m0)); + return customSourceUrl.replace(/\{([^\}]*)\}/g, (m0, m1) => (hasOwn(definition, m1) ? `${definition[m1]}` : m0)); } }; async function audioGetUrl(definition, mode, optionsContext, download) { - if (audioUrlBuilders.hasOwnProperty(mode)) { + if (hasOwn(audioUrlBuilders, mode)) { const handler = audioUrlBuilders[mode]; try { return await handler(definition, optionsContext, download); @@ -171,7 +171,7 @@ async function audioInject(definition, fields, sources, optionsContext) { try { let audioSourceDefinition = definition; - if (definition.hasOwnProperty('expressions')) { + if (hasOwn(definition, 'expressions')) { audioSourceDefinition = definition.expressions[0]; } diff --git a/ext/bg/js/backend.js b/ext/bg/js/backend.js index 45db9660..4190116b 100644 --- a/ext/bg/js/backend.js +++ b/ext/bg/js/backend.js @@ -73,7 +73,7 @@ class Backend { onMessage({action, params}, sender, callback) { const handlers = Backend.messageHandlers; - if (handlers.hasOwnProperty(action)) { + if (hasOwn(handlers, action)) { const handler = handlers[action]; const promise = handler(params, sender); promise.then( diff --git a/ext/bg/js/conditions-ui.js b/ext/bg/js/conditions-ui.js index 43c6dc08..cc9db087 100644 --- a/ext/bg/js/conditions-ui.js +++ b/ext/bg/js/conditions-ui.js @@ -84,7 +84,7 @@ ConditionsUI.Container = class Container { createDefaultCondition(type) { let operator = ''; let value = ''; - if (this.conditionDescriptors.hasOwnProperty(type)) { + if (hasOwn(this.conditionDescriptors, type)) { const conditionDescriptor = this.conditionDescriptors[type]; operator = conditionDescriptor.defaultOperator; ({value} = this.getOperatorDefaultValue(type, operator)); @@ -96,15 +96,15 @@ ConditionsUI.Container = class Container { } getOperatorDefaultValue(type, operator) { - if (this.conditionDescriptors.hasOwnProperty(type)) { + if (hasOwn(this.conditionDescriptors, type)) { const conditionDescriptor = this.conditionDescriptors[type]; - if (conditionDescriptor.operators.hasOwnProperty(operator)) { + if (hasOwn(conditionDescriptor.operators, operator)) { const operatorDescriptor = conditionDescriptor.operators[operator]; - if (operatorDescriptor.hasOwnProperty('defaultValue')) { + if (hasOwn(operatorDescriptor, 'defaultValue')) { return {value: operatorDescriptor.defaultValue, fromOperator: true}; } } - if (conditionDescriptor.hasOwnProperty('defaultValue')) { + if (hasOwn(conditionDescriptor, 'defaultValue')) { return {value: conditionDescriptor.defaultValue, fromOperator: false}; } } @@ -219,7 +219,7 @@ ConditionsUI.Condition = class Condition { optionGroup.empty(); const type = this.condition.type; - if (conditionDescriptors.hasOwnProperty(type)) { + if (hasOwn(conditionDescriptors, type)) { const conditionDescriptor = conditionDescriptors[type]; const operators = conditionDescriptor.operators; for (const operatorName of Object.keys(operators)) { @@ -240,23 +240,23 @@ ConditionsUI.Condition = class Condition { }; const objects = []; - if (conditionDescriptors.hasOwnProperty(type)) { + if (hasOwn(conditionDescriptors, type)) { const conditionDescriptor = conditionDescriptors[type]; objects.push(conditionDescriptor); - if (conditionDescriptor.operators.hasOwnProperty(operator)) { + if (hasOwn(conditionDescriptor.operators, operator)) { const operatorDescriptor = conditionDescriptor.operators[operator]; objects.push(operatorDescriptor); } } for (const object of objects) { - if (object.hasOwnProperty('placeholder')) { + if (hasOwn(object, 'placeholder')) { props.placeholder = object.placeholder; } if (object.type === 'number') { props.type = 'number'; for (const prop of ['step', 'min', 'max']) { - if (object.hasOwnProperty(prop)) { + if (hasOwn(object, prop)) { props[prop] = object[prop]; } } diff --git a/ext/bg/js/conditions.js b/ext/bg/js/conditions.js index ed4b14f5..c0f0f301 100644 --- a/ext/bg/js/conditions.js +++ b/ext/bg/js/conditions.js @@ -18,14 +18,14 @@ function conditionsValidateOptionValue(object, value) { - if (object.hasOwnProperty('validate') && !object.validate(value)) { + if (hasOwn(object, 'validate') && !object.validate(value)) { throw new Error('Invalid value for condition'); } - if (object.hasOwnProperty('transform')) { + if (hasOwn(object, 'transform')) { value = object.transform(value); - if (object.hasOwnProperty('validateTransformed') && !object.validateTransformed(value)) { + if (hasOwn(object, 'validateTransformed') && !object.validateTransformed(value)) { throw new Error('Invalid value for condition'); } } @@ -34,12 +34,12 @@ function conditionsValidateOptionValue(object, value) { } function conditionsNormalizeOptionValue(descriptors, type, operator, optionValue) { - if (!descriptors.hasOwnProperty(type)) { + if (!hasOwn(descriptors, type)) { throw new Error('Invalid type'); } const conditionDescriptor = descriptors[type]; - if (!conditionDescriptor.operators.hasOwnProperty(operator)) { + if (!hasOwn(conditionDescriptor.operators, operator)) { throw new Error('Invalid operator'); } @@ -48,28 +48,28 @@ function conditionsNormalizeOptionValue(descriptors, type, operator, optionValue let transformedValue = conditionsValidateOptionValue(conditionDescriptor, optionValue); transformedValue = conditionsValidateOptionValue(operatorDescriptor, transformedValue); - if (operatorDescriptor.hasOwnProperty('transformReverse')) { + if (hasOwn(operatorDescriptor, 'transformReverse')) { transformedValue = operatorDescriptor.transformReverse(transformedValue); } return transformedValue; } function conditionsTestValueThrowing(descriptors, type, operator, optionValue, value) { - if (!descriptors.hasOwnProperty(type)) { + if (!hasOwn(descriptors, type)) { throw new Error('Invalid type'); } const conditionDescriptor = descriptors[type]; - if (!conditionDescriptor.operators.hasOwnProperty(operator)) { + if (!hasOwn(conditionDescriptor.operators, operator)) { throw new Error('Invalid operator'); } const operatorDescriptor = conditionDescriptor.operators[operator]; - if (operatorDescriptor.hasOwnProperty('transform')) { - if (operatorDescriptor.hasOwnProperty('transformCache')) { + if (hasOwn(operatorDescriptor, 'transform')) { + if (hasOwn(operatorDescriptor, 'transformCache')) { const key = `${optionValue}`; const transformCache = operatorDescriptor.transformCache; - if (transformCache.hasOwnProperty(key)) { + if (hasOwn(transformCache, key)) { optionValue = transformCache[key]; } else { optionValue = operatorDescriptor.transform(optionValue); @@ -93,23 +93,23 @@ function conditionsTestValue(descriptors, type, operator, optionValue, value) { function conditionsClearCaches(descriptors) { for (const type in descriptors) { - if (!descriptors.hasOwnProperty(type)) { + if (!hasOwn(descriptors, type)) { continue; } const conditionDescriptor = descriptors[type]; - if (conditionDescriptor.hasOwnProperty('transformCache')) { + if (hasOwn(conditionDescriptor, 'transformCache')) { conditionDescriptor.transformCache = {}; } const operatorDescriptors = conditionDescriptor.operators; for (const operator in operatorDescriptors) { - if (!operatorDescriptors.hasOwnProperty(operator)) { + if (!hasOwn(operatorDescriptors, operator)) { continue; } const operatorDescriptor = operatorDescriptors[operator]; - if (operatorDescriptor.hasOwnProperty('transformCache')) { + if (hasOwn(operatorDescriptor, 'transformCache')) { operatorDescriptor.transformCache = {}; } } diff --git a/ext/bg/js/database.js b/ext/bg/js/database.js index 9b560f78..c53c9f77 100644 --- a/ext/bg/js/database.js +++ b/ext/bg/js/database.js @@ -137,7 +137,7 @@ class Database { const visited = {}; const results = []; const processRow = (row, index) => { - if (titles.includes(row.dictionary) && !visited.hasOwnProperty(row.id)) { + if (titles.includes(row.dictionary) && !hasOwn(visited, row.id)) { visited[row.id] = true; results.push(Database.createTerm(row, index)); } diff --git a/ext/bg/js/dictionary.js b/ext/bg/js/dictionary.js index 9aa0af9c..affce9e9 100644 --- a/ext/bg/js/dictionary.js +++ b/ext/bg/js/dictionary.js @@ -81,7 +81,7 @@ function dictTermsUndupe(definitions) { const definitionGroups = {}; for (const definition of definitions) { const definitionExisting = definitionGroups[definition.id]; - if (!definitionGroups.hasOwnProperty(definition.id) || definition.expression.length > definitionExisting.expression.length) { + if (!hasOwn(definitionGroups, definition.id) || definition.expression.length > definitionExisting.expression.length) { definitionGroups[definition.id] = definition; } } @@ -131,7 +131,7 @@ function dictTermsGroup(definitions, dictionaries) { } const keyString = key.toString(); - if (groups.hasOwnProperty(keyString)) { + if (hasOwn(groups, keyString)) { groups[keyString].push(definition); } else { groups[keyString] = [definition]; diff --git a/ext/bg/js/mecab.js b/ext/bg/js/mecab.js index 246f8bba..297432e2 100644 --- a/ext/bg/js/mecab.js +++ b/ext/bg/js/mecab.js @@ -60,7 +60,7 @@ class Mecab { } onNativeMessage({sequence, data}) { - if (this.listeners.hasOwnProperty(sequence)) { + if (hasOwn(this.listeners, sequence)) { const {callback, timer} = this.listeners[sequence]; clearTimeout(timer); callback(data); diff --git a/ext/bg/js/options.js b/ext/bg/js/options.js index 63d88789..358a6b45 100644 --- a/ext/bg/js/options.js +++ b/ext/bg/js/options.js @@ -336,7 +336,7 @@ function profileOptionsSetDefaults(options) { const combine = (target, source) => { for (const key in source) { - if (!target.hasOwnProperty(key)) { + if (!hasOwn(target, key)) { target[key] = source[key]; } } diff --git a/ext/bg/js/search.js b/ext/bg/js/search.js index 0922d938..16cbfbbd 100644 --- a/ext/bg/js/search.js +++ b/ext/bg/js/search.js @@ -234,7 +234,7 @@ class DisplaySearch extends Display { onRuntimeMessage({action, params}, sender, callback) { const handlers = DisplaySearch.runtimeMessageHandlers; - if (handlers.hasOwnProperty(action)) { + if (hasOwn(handlers, action)) { const handler = handlers[action]; const result = handler(this, params); callback(result); diff --git a/ext/bg/js/settings-dictionaries.js b/ext/bg/js/settings-dictionaries.js index ebd380ac..177379b0 100644 --- a/ext/bg/js/settings-dictionaries.js +++ b/ext/bg/js/settings-dictionaries.js @@ -81,7 +81,7 @@ class SettingsDictionaryListUI { let changed = false; let optionsDictionary; const optionsDictionaries = this.optionsDictionaries; - if (optionsDictionaries.hasOwnProperty(title)) { + if (hasOwn(optionsDictionaries, title)) { optionsDictionary = optionsDictionaries[title]; } else { optionsDictionary = SettingsDictionaryListUI.createDictionaryOptions(); @@ -466,7 +466,7 @@ function dictionaryErrorsShow(errors) { for (let e of errors) { console.error(e); e = dictionaryErrorToString(e); - uniqueErrors[e] = uniqueErrors.hasOwnProperty(e) ? uniqueErrors[e] + 1 : 1; + uniqueErrors[e] = hasOwn(uniqueErrors, e) ? uniqueErrors[e] + 1 : 1; } for (const e in uniqueErrors) { diff --git a/ext/bg/js/settings-popup-preview.js b/ext/bg/js/settings-popup-preview.js index 7d641c46..49409968 100644 --- a/ext/bg/js/settings-popup-preview.js +++ b/ext/bg/js/settings-popup-preview.js @@ -106,7 +106,7 @@ class SettingsPopupPreview { onMessage(e) { const {action, params} = e.data; const handlers = SettingsPopupPreview.messageHandlers; - if (handlers.hasOwnProperty(action)) { + if (hasOwn(handlers, action)) { const handler = handlers[action]; handler(this, params); } diff --git a/ext/bg/js/translator.js b/ext/bg/js/translator.js index e27cbdff..0a0ce663 100644 --- a/ext/bg/js/translator.js +++ b/ext/bg/js/translator.js @@ -297,7 +297,7 @@ class Translator { for (const deinflection of deinflections) { const term = deinflection.term; let deinflectionArray; - if (uniqueDeinflectionsMap.hasOwnProperty(term)) { + if (hasOwn(uniqueDeinflectionsMap, term)) { deinflectionArray = uniqueDeinflectionsMap[term]; } else { deinflectionArray = []; @@ -355,7 +355,7 @@ class Translator { const kanjiUnique = {}; const kanjiList = []; for (const c of text) { - if (!kanjiUnique.hasOwnProperty(c)) { + if (!hasOwn(kanjiUnique, c)) { kanjiList.push(c); kanjiUnique[c] = true; } @@ -417,7 +417,7 @@ class Translator { const expression = term.expression; term.frequencies = []; - if (termsUniqueMap.hasOwnProperty(expression)) { + if (hasOwn(termsUniqueMap, expression)) { termsUniqueMap[expression].push(term); } else { const termList = [term]; @@ -464,7 +464,7 @@ class Translator { const category = meta.category; const group = ( - stats.hasOwnProperty(category) ? + hasOwn(stats, category) ? stats[category] : (stats[category] = []) ); @@ -484,7 +484,7 @@ class Translator { async getTagMetaList(names, title) { const tagMetaList = []; const cache = ( - this.tagCache.hasOwnProperty(title) ? + hasOwn(this.tagCache, title) ? this.tagCache[title] : (this.tagCache[title] = {}) ); @@ -492,7 +492,7 @@ class Translator { for (const name of names) { const base = Translator.getNameBase(name); - if (cache.hasOwnProperty(base)) { + if (hasOwn(cache, base)) { tagMetaList.push(cache[base]); } else { const tagMeta = await this.database.findTagForTitle(base, title); 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..bde14646 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; } 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 ee653d78..16302e82 100644 --- a/ext/fg/js/frontend.js +++ b/ext/fg/js/frontend.js @@ -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); 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/mixed/js/audio.js b/ext/mixed/js/audio.js index 4e9d04fa..7d5ffedd 100644 --- a/ext/mixed/js/audio.js +++ b/ext/mixed/js/audio.js @@ -113,7 +113,7 @@ function audioGetFromUrl(url, willDownload) { async function audioGetFromSources(expression, sources, optionsContext, willDownload, cache=null) { const key = `${expression.expression}:${expression.reading}`; - if (cache !== null && cache.hasOwnProperty(expression)) { + if (cache !== null && hasOwn(cache, expression)) { return cache[key]; } diff --git a/ext/mixed/js/core.js b/ext/mixed/js/core.js index 8a8a2368..d82b9b4b 100644 --- a/ext/mixed/js/core.js +++ b/ext/mixed/js/core.js @@ -94,6 +94,10 @@ function isObject(value) { return typeof value === 'object' && value !== null && !Array.isArray(value); } +function hasOwn(object, property) { + return Object.prototype.hasOwnProperty.call(object, property); +} + // toIterable is required on Edge for cross-window origin objects. function toIterable(value) { if (typeof Symbol !== 'undefined' && typeof value[Symbol.iterator] !== 'undefined') { diff --git a/ext/mixed/js/display.js b/ext/mixed/js/display.js index 854418f4..ce43b22c 100644 --- a/ext/mixed/js/display.js +++ b/ext/mixed/js/display.js @@ -194,7 +194,7 @@ class Display { onKeyDown(e) { const key = Display.getKeyFromEvent(e); const handlers = Display.onKeyDownHandlers; - if (handlers.hasOwnProperty(key)) { + if (hasOwn(handlers, key)) { const handler = handlers[key]; if (handler(this, e)) { e.preventDefault(); @@ -216,7 +216,7 @@ class Display { onRuntimeMessage({action, params}, sender, callback) { const handlers = Display.runtimeMessageHandlers; - if (handlers.hasOwnProperty(action)) { + if (hasOwn(handlers, action)) { const handler = handlers[action]; const result = handler(this, params); callback(result); -- cgit v1.2.3 From 1daed122909532f5ec5c4b470ddf7f791944cf73 Mon Sep 17 00:00:00 2001 From: toasted-nutbread Date: Mon, 25 Nov 2019 14:22:43 -0500 Subject: Comment empty blocks --- ext/bg/js/api.js | 4 +++- ext/bg/js/settings.js | 8 ++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) (limited to 'ext/bg/js/api.js') diff --git a/ext/bg/js/api.js b/ext/bg/js/api.js index 12257e92..d5256acb 100644 --- a/ext/bg/js/api.js +++ b/ext/bg/js/api.js @@ -404,7 +404,9 @@ async function apiGetBrowser() { if (info.name === 'Fennec') { return 'firefox-mobile'; } - } catch (e) { } + } catch (e) { + // NOP + } return 'firefox'; } else { return 'chrome'; diff --git a/ext/bg/js/settings.js b/ext/bg/js/settings.js index f5c086ef..48026794 100644 --- a/ext/bg/js/settings.js +++ b/ext/bg/js/settings.js @@ -737,7 +737,9 @@ function storageBytesToLabeledString(size) { async function storageEstimate() { try { return (storageEstimate.mostRecent = await navigator.storage.estimate()); - } catch (e) { } + } catch (e) { + // NOP + } return null; } storageEstimate.mostRecent = null; @@ -745,7 +747,9 @@ storageEstimate.mostRecent = null; async function isStoragePeristent() { try { return await navigator.storage.persisted(); - } catch (e) { } + } catch (e) { + // NOP + } return false; } -- cgit v1.2.3 From 5a1046bc906a74ca39906a52acc62fc702a658f2 Mon Sep 17 00:00:00 2001 From: toasted-nutbread Date: Tue, 26 Nov 2019 22:01:54 -0500 Subject: Update arrow-parens to always --- .eslintrc.json | 2 +- ext/bg/js/anki.js | 2 +- ext/bg/js/api.js | 2 +- ext/bg/js/backend-api-forwarder.js | 4 ++-- ext/bg/js/backend.js | 6 +++--- ext/bg/js/context.js | 2 +- ext/bg/js/database.js | 22 +++++++++++----------- ext/bg/js/dictionary.js | 10 +++++----- ext/bg/js/options.js | 6 +++--- ext/bg/js/profile-conditions.js | 2 +- ext/bg/js/request.js | 2 +- ext/bg/js/search-query-parser.js | 4 ++-- ext/bg/js/settings-dictionaries.js | 10 +++++----- ext/bg/js/settings-profiles.js | 2 +- ext/bg/js/settings.js | 8 ++++---- ext/bg/js/translator.js | 8 ++++---- ext/bg/js/util.js | 4 ++-- ext/fg/js/frontend-api-receiver.js | 4 ++-- ext/fg/js/popup.js | 4 ++-- ext/mixed/js/core.js | 2 +- 20 files changed, 53 insertions(+), 53 deletions(-) (limited to 'ext/bg/js/api.js') diff --git a/.eslintrc.json b/.eslintrc.json index fce4b884..0e3b939a 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -8,7 +8,7 @@ "/ext/bg/js/templates.js" ], "rules": { - "arrow-parens": ["error", "as-needed"], + "arrow-parens": ["error", "always"], "comma-dangle": ["error", "never"], "curly": ["error", "all"], "dot-notation": "error", diff --git a/ext/bg/js/anki.js b/ext/bg/js/anki.js index ac45784b..17b93620 100644 --- a/ext/bg/js/anki.js +++ b/ext/bg/js/anki.js @@ -74,7 +74,7 @@ class AnkiConnect { async findNoteIds(notes) { await this.checkVersion(); - const actions = notes.map(note => ({ + const actions = notes.map((note) => ({ action: 'findNotes', params: { query: `deck:"${AnkiConnect.escapeQuery(note.deckName)}" ${AnkiConnect.fieldsToQuery(note.fields)}` diff --git a/ext/bg/js/api.js b/ext/bg/js/api.js index d5256acb..b489b8d2 100644 --- a/ext/bg/js/api.js +++ b/ext/bg/js/api.js @@ -207,7 +207,7 @@ async function apiDefinitionsAddable(definitions, modes, optionsContext) { } if (cannotAdd.length > 0) { - const noteIdsArray = await anki.findNoteIds(cannotAdd.map(e => e[0])); + const noteIdsArray = await anki.findNoteIds(cannotAdd.map((e) => e[0])); for (let i = 0, ii = Math.min(cannotAdd.length, noteIdsArray.length); i < ii; ++i) { const noteIds = noteIdsArray[i]; if (noteIds.length > 0) { diff --git a/ext/bg/js/backend-api-forwarder.js b/ext/bg/js/backend-api-forwarder.js index 979afd16..db4d30b9 100644 --- a/ext/bg/js/backend-api-forwarder.js +++ b/ext/bg/js/backend-api-forwarder.js @@ -37,8 +37,8 @@ class BackendApiForwarder { const forwardPort = chrome.tabs.connect(tabId, {name: 'frontend-api-receiver'}); - port.onMessage.addListener(message => forwardPort.postMessage(message)); - forwardPort.onMessage.addListener(message => port.postMessage(message)); + port.onMessage.addListener((message) => forwardPort.postMessage(message)); + forwardPort.onMessage.addListener((message) => port.postMessage(message)); port.onDisconnect.addListener(() => forwardPort.disconnect()); forwardPort.onDisconnect.addListener(() => port.disconnect()); } diff --git a/ext/bg/js/backend.js b/ext/bg/js/backend.js index 73df7cf5..d9f9b586 100644 --- a/ext/bg/js/backend.js +++ b/ext/bg/js/backend.js @@ -60,7 +60,7 @@ class Backend { this.applyOptions(); const callback = () => this.checkLastError(chrome.runtime.lastError); - chrome.tabs.query({}, tabs => { + chrome.tabs.query({}, (tabs) => { for (const tab of tabs) { chrome.tabs.sendMessage(tab.id, {action: 'optionsUpdate', params: {source}}, callback); } @@ -77,8 +77,8 @@ class Backend { const handler = handlers[action]; const promise = handler(params, sender); promise.then( - result => callback({result}), - error => callback({error: errorToJson(error)}) + (result) => callback({result}), + (error) => callback({error: errorToJson(error)}) ); } diff --git a/ext/bg/js/context.js b/ext/bg/js/context.js index b288a79a..38a82636 100644 --- a/ext/bg/js/context.js +++ b/ext/bg/js/context.js @@ -63,7 +63,7 @@ window.addEventListener('DOMContentLoaded', () => { depth: 0, url: window.location.href }; - apiOptionsGet(optionsContext).then(options => { + apiOptionsGet(optionsContext).then((options) => { const toggle = document.querySelector('#enable-search'); toggle.checked = options.general.enable; toggle.addEventListener('change', () => apiCommandExec('toggle'), false); diff --git a/ext/bg/js/database.js b/ext/bg/js/database.js index c53c9f77..a20d5f15 100644 --- a/ext/bg/js/database.js +++ b/ext/bg/js/database.js @@ -257,7 +257,7 @@ class Database { const dbTerms = dbTransaction.objectStore('tagMeta'); const dbIndex = dbTerms.index('name'); const only = IDBKeyRange.only(name); - await Database.getAll(dbIndex, only, null, row => { + await Database.getAll(dbIndex, only, null, (row) => { if (title === row.dictionary) { result = row; } @@ -273,7 +273,7 @@ class Database { const dbTransaction = this.db.transaction(['dictionaries'], 'readonly'); const dbDictionaries = dbTransaction.objectStore('dictionaries'); - await Database.getAll(dbDictionaries, null, null, info => results.push(info)); + await Database.getAll(dbDictionaries, null, null, (info) => results.push(info)); return results; } @@ -308,7 +308,7 @@ class Database { counts.push(null); const index = i; const query2 = IDBKeyRange.only(dictionaryNames[i]); - const countPromise = Database.getCounts(targets, query2).then(v => counts[index] = v); + const countPromise = Database.getCounts(targets, query2).then((v) => counts[index] = v); countPromises.push(countPromise); } await Promise.all(countPromises); @@ -346,7 +346,7 @@ class Database { } }; - const indexDataLoaded = async summary => { + const indexDataLoaded = async (summary) => { if (summary.version > 3) { throw new Error('Unsupported dictionary version'); } @@ -522,13 +522,13 @@ class Database { await indexDataLoaded(summary); - const buildTermBankName = index => `term_bank_${index + 1}.json`; - const buildTermMetaBankName = index => `term_meta_bank_${index + 1}.json`; - const buildKanjiBankName = index => `kanji_bank_${index + 1}.json`; - const buildKanjiMetaBankName = index => `kanji_meta_bank_${index + 1}.json`; - const buildTagBankName = index => `tag_bank_${index + 1}.json`; + const buildTermBankName = (index) => `term_bank_${index + 1}.json`; + const buildTermMetaBankName = (index) => `term_meta_bank_${index + 1}.json`; + const buildKanjiBankName = (index) => `kanji_bank_${index + 1}.json`; + const buildKanjiMetaBankName = (index) => `kanji_meta_bank_${index + 1}.json`; + const buildTagBankName = (index) => `tag_bank_${index + 1}.json`; - const countBanks = namer => { + const countBanks = (namer) => { let count = 0; while (zip.files[namer(count)]) { ++count; @@ -657,7 +657,7 @@ class Database { const counts = {}; for (const [objectStoreName, index] of targets) { const n = objectStoreName; - const countPromise = Database.getCount(index, query).then(count => counts[n] = count); + const countPromise = Database.getCount(index, query).then((count) => counts[n] = count); countPromises.push(countPromise); } return Promise.all(countPromises).then(() => counts); diff --git a/ext/bg/js/dictionary.js b/ext/bg/js/dictionary.js index 409bed85..0b35e32e 100644 --- a/ext/bg/js/dictionary.js +++ b/ext/bg/js/dictionary.js @@ -99,8 +99,8 @@ function dictTermsCompressTags(definitions) { let lastPartOfSpeech = ''; for (const definition of definitions) { - const dictionary = JSON.stringify(definition.definitionTags.filter(tag => tag.category === 'dictionary').map(tag => tag.name).sort()); - const partOfSpeech = JSON.stringify(definition.definitionTags.filter(tag => tag.category === 'partOfSpeech').map(tag => tag.name).sort()); + const dictionary = JSON.stringify(definition.definitionTags.filter((tag) => tag.category === 'dictionary').map((tag) => tag.name).sort()); + const partOfSpeech = JSON.stringify(definition.definitionTags.filter((tag) => tag.category === 'partOfSpeech').map((tag) => tag.name).sort()); const filterOutCategories = []; @@ -117,7 +117,7 @@ function dictTermsCompressTags(definitions) { lastPartOfSpeech = partOfSpeech; } - definition.definitionTags = definition.definitionTags.filter(tag => !filterOutCategories.includes(tag.category)); + definition.definitionTags = definition.definitionTags.filter((tag) => !filterOutCategories.includes(tag.category)); } } @@ -231,7 +231,7 @@ function dictTermsMergeByGloss(result, definitions, appendTo, mergedIndices) { result.reading.add(definition.reading); for (const tag of definition.definitionTags) { - if (!definitionsByGloss[gloss].definitionTags.find(existingTag => existingTag.name === tag.name)) { + if (!definitionsByGloss[gloss].definitionTags.find((existingTag) => existingTag.name === tag.name)) { definitionsByGloss[gloss].definitionTags.push(tag); } } @@ -246,7 +246,7 @@ function dictTermsMergeByGloss(result, definitions, appendTo, mergedIndices) { } for (const tag of definition.termTags) { - if (!result.expressions.get(definition.expression).get(definition.reading).find(existingTag => existingTag.name === tag.name)) { + if (!result.expressions.get(definition.expression).get(definition.reading).find((existingTag) => existingTag.name === tag.name)) { result.expressions.get(definition.expression).get(definition.reading).push(tag); } } diff --git a/ext/bg/js/options.js b/ext/bg/js/options.js index 358a6b45..e53a8a13 100644 --- a/ext/bg/js/options.js +++ b/ext/bg/js/options.js @@ -429,7 +429,7 @@ function optionsUpdateVersion(options, defaultProfileOptions) { function optionsLoad() { return new Promise((resolve, reject) => { - chrome.storage.local.get(['options'], store => { + chrome.storage.local.get(['options'], (store) => { const error = chrome.runtime.lastError; if (error) { reject(new Error(error)); @@ -437,7 +437,7 @@ function optionsLoad() { resolve(store.options); } }); - }).then(optionsStr => { + }).then((optionsStr) => { if (typeof optionsStr === 'string') { const options = JSON.parse(optionsStr); if (isObject(options)) { @@ -447,7 +447,7 @@ function optionsLoad() { return {}; }).catch(() => { return {}; - }).then(options => { + }).then((options) => { return ( Array.isArray(options.profiles) ? optionsUpdateVersion(options, {}) : diff --git a/ext/bg/js/profile-conditions.js b/ext/bg/js/profile-conditions.js index 8272e5dd..ebc6680a 100644 --- a/ext/bg/js/profile-conditions.js +++ b/ext/bg/js/profile-conditions.js @@ -86,7 +86,7 @@ const profileConditionsDescriptor = { placeholder: 'Comma separated list of domains', defaultValue: 'example.com', transformCache: {}, - transform: (optionValue) => optionValue.split(/[,;\s]+/).map(v => v.trim().toLowerCase()).filter(v => v.length > 0), + transform: (optionValue) => optionValue.split(/[,;\s]+/).map((v) => v.trim().toLowerCase()).filter((v) => v.length > 0), transformReverse: (transformedOptionValue) => transformedOptionValue.join(', '), validateTransformed: (transformedOptionValue) => (transformedOptionValue.length > 0), test: ({url}, transformedOptionValue) => _profileConditionTestDomainList(url, transformedOptionValue) diff --git a/ext/bg/js/request.js b/ext/bg/js/request.js index 3afc1506..7d73d49b 100644 --- a/ext/bg/js/request.js +++ b/ext/bg/js/request.js @@ -29,7 +29,7 @@ function requestJson(url, action, params) { } else { xhr.send(); } - }).then(responseText => { + }).then((responseText) => { try { return JSON.parse(responseText); } diff --git a/ext/bg/js/search-query-parser.js b/ext/bg/js/search-query-parser.js index 74ef32d8..c7222212 100644 --- a/ext/bg/js/search-query-parser.js +++ b/ext/bg/js/search-query-parser.js @@ -107,7 +107,7 @@ class QueryParser { } getParseResult() { - return this.parseResults.find(r => r.id === this.selectedParser); + return this.parseResults.find((r) => r.id === this.selectedParser); } async setText(text) { @@ -216,7 +216,7 @@ class QueryParser { static processParseResultForDisplay(result) { return result.map((term) => { - return term.filter(part => part.text.trim()).map((part) => { + return term.filter((part) => part.text.trim()).map((part) => { return { text: Array.from(part.text), reading: part.reading, diff --git a/ext/bg/js/settings-dictionaries.js b/ext/bg/js/settings-dictionaries.js index 177379b0..065a8abc 100644 --- a/ext/bg/js/settings-dictionaries.js +++ b/ext/bg/js/settings-dictionaries.js @@ -62,8 +62,8 @@ class SettingsDictionaryListUI { this.updateDictionaryOrder(); - const titles = this.dictionaryEntries.map(e => e.dictionaryInfo.title); - const removeKeys = Object.keys(this.optionsDictionaries).filter(key => titles.indexOf(key) < 0); + const titles = this.dictionaryEntries.map((e) => e.dictionaryInfo.title); + const removeKeys = Object.keys(this.optionsDictionaries).filter((key) => titles.indexOf(key) < 0); if (removeKeys.length > 0) { for (const key of toIterable(removeKeys)) { delete this.optionsDictionaries[key]; @@ -161,7 +161,7 @@ class SettingsDictionaryListUI { delete n.dataset.dict; $(n).modal('hide'); - const index = this.dictionaryEntries.findIndex(e => e.dictionaryInfo.title === title); + const index = this.dictionaryEntries.findIndex((e) => e.dictionaryInfo.title === title); if (index >= 0) { this.dictionaryEntries[index].deleteDictionary(); } @@ -377,7 +377,7 @@ async function onDatabaseUpdated(options) { updateMainDictionarySelect(options, dictionaries); - const {counts, total} = await utilDatabaseGetDictionaryCounts(dictionaries.map(v => v.title), true); + const {counts, total} = await utilDatabaseGetDictionaryCounts(dictionaries.map((v) => v.title), true); dictionaryUI.setCounts(counts, total); } catch (e) { dictionaryErrorsShow([e]); @@ -564,7 +564,7 @@ async function onDictionaryImport(e) { dictionaryErrorsShow(null); dictionarySpinnerShow(true); - const setProgress = percent => dictProgress.find('.progress-bar').css('width', `${percent}%`); + const setProgress = (percent) => dictProgress.find('.progress-bar').css('width', `${percent}%`); const updateProgress = (total, current) => { setProgress(current / total * 100.0); if (storageEstimate.mostRecent !== null && !storageUpdateStats.isUpdating) { diff --git a/ext/bg/js/settings-profiles.js b/ext/bg/js/settings-profiles.js index 9532e3eb..8c218e97 100644 --- a/ext/bg/js/settings-profiles.js +++ b/ext/bg/js/settings-profiles.js @@ -147,7 +147,7 @@ function profileOptionsCreateCopyName(name, profiles, maxUniqueAttempts) { let i = 0; while (true) { const newName = `${prefix}${space}${index}${suffix}`; - if (i++ >= maxUniqueAttempts || profiles.findIndex(profile => profile.name === newName) < 0) { + if (i++ >= maxUniqueAttempts || profiles.findIndex((profile) => profile.name === newName) < 0) { return newName; } if (typeof index !== 'number') { diff --git a/ext/bg/js/settings.js b/ext/bg/js/settings.js index 48026794..abe6f389 100644 --- a/ext/bg/js/settings.js +++ b/ext/bg/js/settings.js @@ -18,7 +18,7 @@ async function getOptionsArray() { const optionsFull = await apiOptionsGetFull(); - return optionsFull.profiles.map(profile => profile.options); + return optionsFull.profiles.map((profile) => profile.options); } async function formRead(options) { @@ -484,12 +484,12 @@ async function ankiDeckAndModelPopulate(options) { const deckNames = await utilAnkiGetDeckNames(); const ankiDeck = $('.anki-deck'); ankiDeck.find('option').remove(); - deckNames.sort().forEach(name => ankiDeck.append($('