From 62c881cfeb20eed816e3c317e425dc3affa0391d Mon Sep 17 00:00:00 2001 From: siikamiika Date: Mon, 25 Sep 2017 23:47:53 +0300 Subject: [PATCH 01/64] Go to next and previous result with Alt+wheel Analogous to Alt+up/down which does the same thing --- ext/mixed/js/display.js | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/ext/mixed/js/display.js b/ext/mixed/js/display.js index 75ee339a..302a6280 100644 --- a/ext/mixed/js/display.js +++ b/ext/mixed/js/display.js @@ -29,6 +29,7 @@ class Display { this.audioCache = {}; $(document).keydown(this.onKeyDown.bind(this)); + $(document).on('wheel', this.onWheel.bind(this)); } onError(error) { @@ -202,6 +203,25 @@ class Display { } } + onWheel(e) { + const event = e.originalEvent; + const handler = () => { + if (event.altKey) { + if (event.deltaY < 0) { // scroll up + this.entryScrollIntoView(this.index - 1, true); + return true; + } else if (event.deltaY > 0) { // scroll down + this.entryScrollIntoView(this.index + 1, true); + return true; + } + } + }; + + if (handler()) { + event.preventDefault(); + } + } + async termsShow(definitions, options, context) { try { window.focus(); From b24c70523479c16eca848f5aafaa887549689ac6 Mon Sep 17 00:00:00 2001 From: siikamiika Date: Fri, 29 Sep 2017 05:41:29 +0300 Subject: [PATCH 02/64] basic structure for feature-merge-similar-results --- ext/bg/js/api.js | 6 +++--- ext/bg/js/database.js | 3 ++- ext/bg/js/dictionary.js | 3 ++- ext/bg/js/options.js | 2 +- ext/bg/js/settings.js | 4 ++-- ext/bg/js/translator.js | 15 ++++++++++++++- ext/bg/settings.html | 13 +++++++++---- ext/mixed/js/display.js | 3 ++- 8 files changed, 35 insertions(+), 14 deletions(-) diff --git a/ext/bg/js/api.js b/ext/bg/js/api.js index 9f65bb07..01322357 100644 --- a/ext/bg/js/api.js +++ b/ext/bg/js/api.js @@ -29,9 +29,9 @@ async function apiTermsFind(text) { const options = utilBackend().options; const translator = utilBackend().translator; - const searcher = options.general.groupResults ? - translator.findTermsGrouped.bind(translator) : - translator.findTermsSplit.bind(translator); + const searcher = (options.general.resultOutputMode === 'merge') && translator.findTermsMerged.bind(translator) + || (options.general.resultOutputMode === 'split') && translator.findTermsSplit.bind(translator) + || (options.general.resultOutputMode === 'group') && translator.findTermsGrouped.bind(translator); const {definitions, length} = await searcher( text, diff --git a/ext/bg/js/database.js b/ext/bg/js/database.js index 6ceb3ec8..29ab6d4e 100644 --- a/ext/bg/js/database.js +++ b/ext/bg/js/database.js @@ -208,7 +208,7 @@ class Database { }); } } else { - for (const [expression, reading, tags, rules, score, glossary] of entries) { + for (const [expression, reading, tags, rules, score, glossary, sequence] of entries) { rows.push({ expression, reading, @@ -216,6 +216,7 @@ class Database { rules, score, glossary, + sequence, dictionary: summary.title }); } diff --git a/ext/bg/js/dictionary.js b/ext/bg/js/dictionary.js index 57acbe5e..f3f573d3 100644 --- a/ext/bg/js/dictionary.js +++ b/ext/bg/js/dictionary.js @@ -207,7 +207,8 @@ async function dictFieldFormat(field, definition, mode, options) { const data = { marker, definition, - group: options.general.groupResults, + group: options.general.resultOutputMode === 'group', + merge: options.general.resultOutputMode === 'merge', modeTermKanji: mode === 'term-kanji', modeTermKana: mode === 'term-kana', modeKanji: mode === 'kanji' diff --git a/ext/bg/js/options.js b/ext/bg/js/options.js index 36ab7694..de3da943 100644 --- a/ext/bg/js/options.js +++ b/ext/bg/js/options.js @@ -132,7 +132,7 @@ function optionsSetDefaults(options) { enable: true, audioSource: 'jpod101', audioVolume: 100, - groupResults: true, + resultOutputMode: 'group', debugInfo: false, maxResults: 32, showAdvanced: false, diff --git a/ext/bg/js/settings.js b/ext/bg/js/settings.js index a2f22371..c5a28a45 100644 --- a/ext/bg/js/settings.js +++ b/ext/bg/js/settings.js @@ -22,9 +22,9 @@ async function formRead() { const optionsNew = $.extend(true, {}, optionsOld); optionsNew.general.showGuide = $('#show-usage-guide').prop('checked'); + optionsNew.general.resultOutputMode = $('#result-output-mode').val(); optionsNew.general.audioSource = $('#audio-playback-source').val(); optionsNew.general.audioVolume = parseFloat($('#audio-playback-volume').val()); - optionsNew.general.groupResults = $('#group-terms-results').prop('checked'); optionsNew.general.debugInfo = $('#show-debug-info').prop('checked'); optionsNew.general.showAdvanced = $('#show-advanced-options').prop('checked'); optionsNew.general.maxResults = parseInt($('#max-displayed-results').val(), 10); @@ -124,9 +124,9 @@ async function onReady() { const options = await optionsLoad(); $('#show-usage-guide').prop('checked', options.general.showGuide); + $('#result-output-mode').val(options.general.resultOutputMode); $('#audio-playback-source').val(options.general.audioSource); $('#audio-playback-volume').val(options.general.audioVolume); - $('#group-terms-results').prop('checked', options.general.groupResults); $('#show-debug-info').prop('checked', options.general.debugInfo); $('#show-advanced-options').prop('checked', options.general.showAdvanced); $('#max-displayed-results').val(options.general.maxResults); diff --git a/ext/bg/js/translator.js b/ext/bg/js/translator.js index c915dbc0..8fa2b60b 100644 --- a/ext/bg/js/translator.js +++ b/ext/bg/js/translator.js @@ -48,6 +48,18 @@ class Translator { return {length, definitions: definitionsGrouped}; } + async findTermsMerged(text, dictionaries, alphanumeric) { + const titles = Object.keys(dictionaries); + const {length, definitions} = await this.findTerms(text, dictionaries, alphanumeric); + + const definitionsMerged = dictTermsGroup(definitions, dictionaries); + // for (const definition of definitionsMerged) { + // await this.buildTermFrequencies(definition, titles); + // } + + return {length, definitions: definitionsMerged}; + } + async findTermsSplit(text, dictionaries, alphanumeric) { const titles = Object.keys(dictionaries); const {length, definitions} = await this.findTerms(text, dictionaries, alphanumeric); @@ -90,7 +102,8 @@ class Translator { expression: definition.expression, reading: definition.reading, glossary: definition.glossary, - tags: dictTagsSort(tags) + tags: dictTagsSort(tags), + sequence: definition.sequence }); } } diff --git a/ext/bg/settings.html b/ext/bg/settings.html index 4315d74b..6274f3cb 100644 --- a/ext/bg/settings.html +++ b/ext/bg/settings.html @@ -35,10 +35,6 @@ -
- -
-
@@ -47,6 +43,15 @@ +
+ + +
+
Enable search\n
\n
\n \n \n
\n
\n \n +
From 72fe83d353f83d0559f9c53e7e18f609805d6fd6 Mon Sep 17 00:00:00 2001 From: siikamiika Date: Thu, 5 Oct 2017 06:56:45 +0300 Subject: [PATCH 08/64] merged mode: merge other results with main dict --- ext/bg/js/dictionary.js | 2 +- ext/bg/js/translator.js | 39 ++++++++++++++++++++++++++++++++++++--- 2 files changed, 37 insertions(+), 4 deletions(-) diff --git a/ext/bg/js/dictionary.js b/ext/bg/js/dictionary.js index c20df400..41c90b1c 100644 --- a/ext/bg/js/dictionary.js +++ b/ext/bg/js/dictionary.js @@ -89,7 +89,7 @@ function dictTermsSort(definitions, dictionaries=null) { return 1; } - return v2.expression.localeCompare(v1.expression); + return v2.expression.toString().localeCompare(v1.expression.toString()); }); } diff --git a/ext/bg/js/translator.js b/ext/bg/js/translator.js index 3442124f..f50c5725 100644 --- a/ext/bg/js/translator.js +++ b/ext/bg/js/translator.js @@ -55,7 +55,8 @@ class Translator { const definitionsBySequence = dictTermsMergeBySequence(definitions, options.dictionary.main); - const definitionsMerged = dictTermsGroup(definitionsBySequence['-1'], dictionaries); + // const definitionsMerged = dictTermsGroup(definitionsBySequence['-1'], dictionaries); + const definitionsMerged = []; for (const sequence in definitionsBySequence) { if (!(sequence > 0)) { continue; @@ -114,11 +115,43 @@ class Translator { result.expressions = expressions; - result.expression = Array.from(result.expression).join(', '); - result.reading = Array.from(result.reading).join(', '); + // result.expression = Array.from(result.expression).join(', '); + // result.reading = Array.from(result.reading).join(', '); definitionsMerged.push(result); } + const postMergedIndices = new Set(); + const mergeeIndicesByGloss = {}; + for (const [i, definition] of definitionsBySequence['-1'].entries()) { + for (const [j, mergedDefinition] of definitionsMerged.entries()) { + if (mergedDefinition.expression.has(definition.expression)) { + if (mergedDefinition.reading.has(definition.reading) || (definition.reading === '' && mergedDefinition.reading.size === 0)) { + if (!mergeeIndicesByGloss[definition.glossary]) { + mergeeIndicesByGloss[definition.glossary] = new Set(); + } + if (mergeeIndicesByGloss[definition.glossary].has(j)) { + continue; + } + mergedDefinition.definitions.push(definition); + mergeeIndicesByGloss[definition.glossary].add(j); + postMergedIndices.add(i); + } + } + } + } + + const strayDefinitions = []; + for (const [i, definition] of definitionsBySequence['-1'].entries()) { + if (postMergedIndices.has(i)) { + continue; + } + strayDefinitions.push(definition); + } + + for (const groupedDefinition of dictTermsGroup(strayDefinitions, dictionaries)) { + definitionsMerged.push(groupedDefinition); + } + for (const definition of definitionsMerged) { await this.buildTermFrequencies(definition, titles); } From 981d9eddb69322494589c241d049652c9091ed06 Mon Sep 17 00:00:00 2001 From: siikamiika Date: Sat, 7 Oct 2017 01:19:40 +0300 Subject: [PATCH 09/64] merged mode: rewrite previous commit --- ext/bg/js/dictionary.js | 44 ++++++++++++++++++++++++++++++++--- ext/bg/js/translator.js | 51 ++++++----------------------------------- 2 files changed, 48 insertions(+), 47 deletions(-) diff --git a/ext/bg/js/dictionary.js b/ext/bg/js/dictionary.js index 41c90b1c..7d6d176c 100644 --- a/ext/bg/js/dictionary.js +++ b/ext/bg/js/dictionary.js @@ -170,9 +170,31 @@ function dictTermsMergeBySequence(definitions, mainDictionary) { return definitionsBySequence; } -function dictTermsMergeByGloss(result, definitions) { - const definitionsByGloss = {}; - for (const definition of definitions) { +function dictTermsMergeByGloss(result, definitions, appendTo, mergedIndices) { + const definitionsByGloss = appendTo || {}; + for (const [index, definition] of definitions.entries()) { + if (appendTo) { + let match = false; + for (const expression of result.expressions.keys()) { + if (definition.expression === expression) { + for (const reading of result.expressions.get(expression).keys()) { + if (definition.reading === reading) { + match = true; + break; + } + } + } + if (match) { + break; + } + } + + if (!match) { + continue; + } else if (mergedIndices) { + mergedIndices.add(index); + } + } const gloss = JSON.stringify(definition.glossary); if (!definitionsByGloss[gloss]) { @@ -180,6 +202,7 @@ function dictTermsMergeByGloss(result, definitions) { expression: new Set(), reading: new Set(), tags: new Set(), + glossary: definition.glossary, source: result.source, reasons: [], score: definition.score, @@ -212,6 +235,21 @@ function dictTermsMergeByGloss(result, definitions) { } } + for (const gloss in definitionsByGloss) { + const definition = definitionsByGloss[gloss]; + definition.only = []; + if (!utilSetEqual(definition.expression, result.expression)) { + for (const expression of utilSetIntersection(definition.expression, result.expression)) { + definition.only.push(expression); + } + } + if (!utilSetEqual(definition.reading, result.reading)) { + for (const reading of utilSetIntersection(definition.reading, result.reading)) { + definition.only.push(reading); + } + } + } + return definitionsByGloss; } diff --git a/ext/bg/js/translator.js b/ext/bg/js/translator.js index f50c5725..f959ea35 100644 --- a/ext/bg/js/translator.js +++ b/ext/bg/js/translator.js @@ -55,8 +55,8 @@ class Translator { const definitionsBySequence = dictTermsMergeBySequence(definitions, options.dictionary.main); - // const definitionsMerged = dictTermsGroup(definitionsBySequence['-1'], dictionaries); const definitionsMerged = []; + const mergedByTermIndices = new Set(); for (const sequence in definitionsBySequence) { if (!(sequence > 0)) { continue; @@ -66,32 +66,19 @@ class Translator { const rawDefinitionsBySequence = await this.database.findTermsBySequence(Number(sequence), options.dictionary.main); const definitionsByGloss = dictTermsMergeByGloss(result, rawDefinitionsBySequence); + dictTermsMergeByGloss(result, definitionsBySequence['-1'], definitionsByGloss, mergedByTermIndices); - // postprocess glossaries for (const gloss in definitionsByGloss) { const definition = definitionsByGloss[gloss]; - definition.glossary = JSON.parse(gloss); const tags = await this.expandTags(definition.tags, definition.dictionary); tags.push(dictTagBuildSource(definition.dictionary)); definition.tags = dictTagsSort(tags); - definition.only = []; - if (!utilSetEqual(definition.expression, result.expression)) { - for (const expression of utilSetIntersection(definition.expression, result.expression)) { - definition.only.push(expression); - } - } - if (!utilSetEqual(definition.reading, result.reading)) { - for (const reading of utilSetIntersection(definition.reading, result.reading)) { - definition.only.push(reading); - } - } - result.definitions.push(definition); } - result.definitions.sort(definition => -definition.id); + dictTermsSort(result.definitions, dictionaries); // turn the Map()/Set() mess to [{expression: E1, reading: R1}, {...}] and tag popular/normal/rare instead of actual tags const expressions = []; @@ -120,34 +107,7 @@ class Translator { definitionsMerged.push(result); } - const postMergedIndices = new Set(); - const mergeeIndicesByGloss = {}; - for (const [i, definition] of definitionsBySequence['-1'].entries()) { - for (const [j, mergedDefinition] of definitionsMerged.entries()) { - if (mergedDefinition.expression.has(definition.expression)) { - if (mergedDefinition.reading.has(definition.reading) || (definition.reading === '' && mergedDefinition.reading.size === 0)) { - if (!mergeeIndicesByGloss[definition.glossary]) { - mergeeIndicesByGloss[definition.glossary] = new Set(); - } - if (mergeeIndicesByGloss[definition.glossary].has(j)) { - continue; - } - mergedDefinition.definitions.push(definition); - mergeeIndicesByGloss[definition.glossary].add(j); - postMergedIndices.add(i); - } - } - } - } - - const strayDefinitions = []; - for (const [i, definition] of definitionsBySequence['-1'].entries()) { - if (postMergedIndices.has(i)) { - continue; - } - strayDefinitions.push(definition); - } - + const strayDefinitions = definitionsBySequence['-1'].filter((definition, index) => !mergedByTermIndices.has(index)); for (const groupedDefinition of dictTermsGroup(strayDefinitions, dictionaries)) { definitionsMerged.push(groupedDefinition); } @@ -294,6 +254,9 @@ class Translator { async expandTags(names, title) { const tags = []; for (const name of names) { + if (typeof name !== 'string') { + continue; + } const base = name.split(':')[0]; const meta = await this.database.findTagForTitle(base, title); From 94d590fc85f87028d8264e93c8ad58c71d0977f2 Mon Sep 17 00:00:00 2001 From: siikamiika Date: Sat, 7 Oct 2017 07:02:50 +0300 Subject: [PATCH 10/64] merged mode: support audio and tags for terms --- ext/bg/js/dictionary.js | 1 - ext/bg/js/templates.js | 118 +++++++++++++++++++++++--------------- ext/bg/js/translator.js | 3 + ext/mixed/css/display.css | 20 ++++++- ext/mixed/js/display.js | 10 ++-- tmpl/terms.html | 16 +++++- 6 files changed, 112 insertions(+), 56 deletions(-) diff --git a/ext/bg/js/dictionary.js b/ext/bg/js/dictionary.js index 7d6d176c..b81d1411 100644 --- a/ext/bg/js/dictionary.js +++ b/ext/bg/js/dictionary.js @@ -227,7 +227,6 @@ function dictTermsMergeByGloss(result, definitions, appendTo, mergedIndices) { for (const tag of definition.tags) { if (dictIsJmdictTermTag(tag)) { - // TODO: expand tags result.expressions.get(definition.expression).get(definition.reading).add(tag); } else { definitionsByGloss[gloss].tags.add(tag); diff --git a/ext/bg/js/templates.js b/ext/bg/js/templates.js index 4341322a..01507e1c 100644 --- a/ext/bg/js/templates.js +++ b/ext/bg/js/templates.js @@ -265,85 +265,109 @@ templates['terms.html'] = template({"1":function(container,depth0,helpers,partia var stack1; return container.escapeExpression(container.lambda(((stack1 = (depth0 != null ? depth0.glossary : depth0)) != null ? stack1["0"] : stack1), depth0)); -},"16":function(container,depth0,helpers,partials,data) { +},"16":function(container,depth0,helpers,partials,data,blockParams,depths) { var stack1, alias1=depth0 != null ? depth0 : (container.nullContext || {}); return "
\n
\n" - + ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.addable : depth0),{"name":"if","hash":{},"fn":container.program(17, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") - + ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.playback : depth0),{"name":"if","hash":{},"fn":container.program(19, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") + + ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.addable : depth0),{"name":"if","hash":{},"fn":container.program(17, data, 0, blockParams, depths),"inverse":container.noop,"data":data})) != null ? stack1 : "") + + ((stack1 = helpers.unless.call(alias1,(depth0 != null ? depth0.merged : depth0),{"name":"unless","hash":{},"fn":container.program(19, data, 0, blockParams, depths),"inverse":container.noop,"data":data})) != null ? stack1 : "") + " \n
\n\n" - + ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.merged : depth0),{"name":"if","hash":{},"fn":container.program(21, data, 0),"inverse":container.program(28, data, 0),"data":data})) != null ? stack1 : "") + + ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.merged : depth0),{"name":"if","hash":{},"fn":container.program(22, data, 0, blockParams, depths),"inverse":container.program(34, data, 0, blockParams, depths),"data":data})) != null ? stack1 : "") + "\n" - + ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.reasons : depth0),{"name":"if","hash":{},"fn":container.program(30, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") + + ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.reasons : depth0),{"name":"if","hash":{},"fn":container.program(36, data, 0, blockParams, depths),"inverse":container.noop,"data":data})) != null ? stack1 : "") + "\n" - + ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.frequencies : depth0),{"name":"if","hash":{},"fn":container.program(34, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") + + ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.frequencies : depth0),{"name":"if","hash":{},"fn":container.program(40, data, 0, blockParams, depths),"inverse":container.noop,"data":data})) != null ? stack1 : "") + "\n
\n" - + ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.grouped : depth0),{"name":"if","hash":{},"fn":container.program(37, data, 0),"inverse":container.program(43, data, 0),"data":data})) != null ? stack1 : "") + + ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.grouped : depth0),{"name":"if","hash":{},"fn":container.program(43, data, 0, blockParams, depths),"inverse":container.program(49, data, 0, blockParams, depths),"data":data})) != null ? stack1 : "") + "
\n\n" - + ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.debug : depth0),{"name":"if","hash":{},"fn":container.program(46, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") + + ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.debug : depth0),{"name":"if","hash":{},"fn":container.program(52, data, 0, blockParams, depths),"inverse":container.noop,"data":data})) != null ? stack1 : "") + "
\n"; },"17":function(container,depth0,helpers,partials,data) { return " \n \n \n"; },"19":function(container,depth0,helpers,partials,data) { - return " \n"; -},"21":function(container,depth0,helpers,partials,data) { var stack1; - return ((stack1 = helpers.each.call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? depth0.expressions : depth0),{"name":"each","hash":{},"fn":container.program(22, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : ""); -},"22":function(container,depth0,helpers,partials,data) { + return ((stack1 = helpers["if"].call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? depth0.playback : depth0),{"name":"if","hash":{},"fn":container.program(20, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : ""); +},"20":function(container,depth0,helpers,partials,data) { + return " \n"; +},"22":function(container,depth0,helpers,partials,data,blockParams,depths) { + var stack1; + + return ((stack1 = helpers.each.call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? depth0.expressions : depth0),{"name":"each","hash":{},"fn":container.program(23, data, 0, blockParams, depths),"inverse":container.noop,"data":data})) != null ? stack1 : ""); +},"23":function(container,depth0,helpers,partials,data,blockParams,depths) { var stack1, helper, options, alias1=depth0 != null ? depth0 : (container.nullContext || {}), alias2=helpers.helperMissing, alias3="function", buffer = "
\n "; - stack1 = ((helper = (helper = helpers.kanjiLinks || (depth0 != null ? depth0.kanjiLinks : depth0)) != null ? helper : alias2),(options={"name":"kanjiLinks","hash":{},"fn":container.program(23, data, 0),"inverse":container.noop,"data":data}),(typeof helper === alias3 ? helper.call(alias1,options) : helper)); + stack1 = ((helper = (helper = helpers.kanjiLinks || (depth0 != null ? depth0.kanjiLinks : depth0)) != null ? helper : alias2),(options={"name":"kanjiLinks","hash":{},"fn":container.program(24, data, 0, blockParams, depths),"inverse":container.noop,"data":data}),(typeof helper === alias3 ? helper.call(alias1,options) : helper)); if (!helpers.kanjiLinks) { stack1 = helpers.blockHelperMissing.call(depth0,stack1,options)} if (stack1 != null) { buffer += stack1; } - return buffer + "" - + ((stack1 = helpers.unless.call(alias1,(data && data.last),{"name":"unless","hash":{},"fn":container.program(26, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") + return buffer + "
" + + ((stack1 = helpers["if"].call(alias1,(depths[1] != null ? depths[1].playback : depths[1]),{"name":"if","hash":{},"fn":container.program(27, data, 0, blockParams, depths),"inverse":container.noop,"data":data})) != null ? stack1 : "") + + ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.tags : depth0),{"name":"if","hash":{},"fn":container.program(29, data, 0, blockParams, depths),"inverse":container.noop,"data":data})) != null ? stack1 : "") + + "
" + + ((stack1 = helpers.unless.call(alias1,(data && data.last),{"name":"unless","hash":{},"fn":container.program(32, data, 0, blockParams, depths),"inverse":container.noop,"data":data})) != null ? stack1 : "") + "\n
\n"; -},"23":function(container,depth0,helpers,partials,data) { +},"24":function(container,depth0,helpers,partials,data) { var stack1, helper, options; - stack1 = ((helper = (helper = helpers.furigana || (depth0 != null ? depth0.furigana : depth0)) != null ? helper : helpers.helperMissing),(options={"name":"furigana","hash":{},"fn":container.program(24, data, 0),"inverse":container.noop,"data":data}),(typeof helper === "function" ? helper.call(depth0 != null ? depth0 : (container.nullContext || {}),options) : helper)); + stack1 = ((helper = (helper = helpers.furigana || (depth0 != null ? depth0.furigana : depth0)) != null ? helper : helpers.helperMissing),(options={"name":"furigana","hash":{},"fn":container.program(25, data, 0),"inverse":container.noop,"data":data}),(typeof helper === "function" ? helper.call(depth0 != null ? depth0 : (container.nullContext || {}),options) : helper)); if (!helpers.furigana) { stack1 = helpers.blockHelperMissing.call(depth0,stack1,options)} if (stack1 != null) { return stack1; } else { return ''; } -},"24":function(container,depth0,helpers,partials,data) { +},"25":function(container,depth0,helpers,partials,data) { var stack1; return ((stack1 = container.lambda(depth0, depth0)) != null ? stack1 : ""); -},"26":function(container,depth0,helpers,partials,data) { +},"27":function(container,depth0,helpers,partials,data) { + return "
\n"; +},"29":function(container,depth0,helpers,partials,data) { + var stack1; + + return ((stack1 = helpers.each.call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? depth0.tags : depth0),{"name":"each","hash":{},"fn":container.program(30, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") + + " "; +},"30":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.name || (depth0 != null ? depth0.name : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"name","hash":{},"data":data}) : helper))) + + "\n"; +},"32":function(container,depth0,helpers,partials,data) { return "、"; -},"28":function(container,depth0,helpers,partials,data) { +},"34":function(container,depth0,helpers,partials,data) { var stack1, helper, options, buffer = "
"; - stack1 = ((helper = (helper = helpers.kanjiLinks || (depth0 != null ? depth0.kanjiLinks : depth0)) != null ? helper : helpers.helperMissing),(options={"name":"kanjiLinks","hash":{},"fn":container.program(23, data, 0),"inverse":container.noop,"data":data}),(typeof helper === "function" ? helper.call(depth0 != null ? depth0 : (container.nullContext || {}),options) : helper)); + stack1 = ((helper = (helper = helpers.kanjiLinks || (depth0 != null ? depth0.kanjiLinks : depth0)) != null ? helper : helpers.helperMissing),(options={"name":"kanjiLinks","hash":{},"fn":container.program(24, data, 0),"inverse":container.noop,"data":data}),(typeof helper === "function" ? helper.call(depth0 != null ? depth0 : (container.nullContext || {}),options) : helper)); if (!helpers.kanjiLinks) { stack1 = helpers.blockHelperMissing.call(depth0,stack1,options)} if (stack1 != null) { buffer += stack1; } return buffer + "
\n"; -},"30":function(container,depth0,helpers,partials,data) { +},"36":function(container,depth0,helpers,partials,data) { var stack1; return "
\n" - + ((stack1 = helpers.each.call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? depth0.reasons : depth0),{"name":"each","hash":{},"fn":container.program(31, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") + + ((stack1 = helpers.each.call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? depth0.reasons : depth0),{"name":"each","hash":{},"fn":container.program(37, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") + "
\n"; -},"31":function(container,depth0,helpers,partials,data) { +},"37":function(container,depth0,helpers,partials,data) { var stack1; return " " + container.escapeExpression(container.lambda(depth0, depth0)) + " " - + ((stack1 = helpers.unless.call(depth0 != null ? depth0 : (container.nullContext || {}),(data && data.last),{"name":"unless","hash":{},"fn":container.program(32, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") + + ((stack1 = helpers.unless.call(depth0 != null ? depth0 : (container.nullContext || {}),(data && data.last),{"name":"unless","hash":{},"fn":container.program(38, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") + "\n"; -},"32":function(container,depth0,helpers,partials,data) { +},"38":function(container,depth0,helpers,partials,data) { return "«"; -},"34":function(container,depth0,helpers,partials,data) { +},"40":function(container,depth0,helpers,partials,data) { var stack1; return "
\n" - + ((stack1 = helpers.each.call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? depth0.frequencies : depth0),{"name":"each","hash":{},"fn":container.program(35, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") + + ((stack1 = helpers.each.call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? depth0.frequencies : depth0),{"name":"each","hash":{},"fn":container.program(41, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") + "
\n"; -},"35":function(container,depth0,helpers,partials,data) { +},"41":function(container,depth0,helpers,partials,data) { var helper, alias1=depth0 != null ? depth0 : (container.nullContext || {}), alias2=helpers.helperMissing, alias3="function", alias4=container.escapeExpression; return " " @@ -351,61 +375,61 @@ templates['terms.html'] = template({"1":function(container,depth0,helpers,partia + ":" + alias4(((helper = (helper = helpers.frequency || (depth0 != null ? depth0.frequency : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"frequency","hash":{},"data":data}) : helper))) + "\n"; -},"37":function(container,depth0,helpers,partials,data) { +},"43":function(container,depth0,helpers,partials,data) { var stack1; - return ((stack1 = helpers["if"].call(depth0 != null ? depth0 : (container.nullContext || {}),((stack1 = (depth0 != null ? depth0.definitions : depth0)) != null ? stack1["1"] : stack1),{"name":"if","hash":{},"fn":container.program(38, data, 0),"inverse":container.program(41, data, 0),"data":data})) != null ? stack1 : ""); -},"38":function(container,depth0,helpers,partials,data) { + return ((stack1 = helpers["if"].call(depth0 != null ? depth0 : (container.nullContext || {}),((stack1 = (depth0 != null ? depth0.definitions : depth0)) != null ? stack1["1"] : stack1),{"name":"if","hash":{},"fn":container.program(44, data, 0),"inverse":container.program(47, data, 0),"data":data})) != null ? stack1 : ""); +},"44":function(container,depth0,helpers,partials,data) { var stack1; return "
    \n" - + ((stack1 = helpers.each.call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? depth0.definitions : depth0),{"name":"each","hash":{},"fn":container.program(39, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") + + ((stack1 = helpers.each.call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? depth0.definitions : depth0),{"name":"each","hash":{},"fn":container.program(45, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") + "
\n"; -},"39":function(container,depth0,helpers,partials,data) { +},"45":function(container,depth0,helpers,partials,data) { var stack1; return "
  • " + ((stack1 = container.invokePartial(partials.definition,depth0,{"name":"definition","data":data,"helpers":helpers,"partials":partials,"decorators":container.decorators})) != null ? stack1 : "") + "
  • \n"; -},"41":function(container,depth0,helpers,partials,data) { +},"47":function(container,depth0,helpers,partials,data) { var stack1; return ((stack1 = container.invokePartial(partials.definition,((stack1 = (depth0 != null ? depth0.definitions : depth0)) != null ? stack1["0"] : stack1),{"name":"definition","data":data,"indent":" ","helpers":helpers,"partials":partials,"decorators":container.decorators})) != null ? stack1 : ""); -},"43":function(container,depth0,helpers,partials,data) { +},"49":function(container,depth0,helpers,partials,data,blockParams,depths) { var stack1; - return ((stack1 = helpers["if"].call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? depth0.merged : depth0),{"name":"if","hash":{},"fn":container.program(37, data, 0),"inverse":container.program(44, data, 0),"data":data})) != null ? stack1 : ""); -},"44":function(container,depth0,helpers,partials,data) { + return ((stack1 = helpers["if"].call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? depth0.merged : depth0),{"name":"if","hash":{},"fn":container.program(43, data, 0, blockParams, depths),"inverse":container.program(50, data, 0, blockParams, depths),"data":data})) != null ? stack1 : ""); +},"50":function(container,depth0,helpers,partials,data) { var stack1; return ((stack1 = container.invokePartial(partials.definition,depth0,{"name":"definition","data":data,"indent":" ","helpers":helpers,"partials":partials,"decorators":container.decorators})) != null ? stack1 : "") + " "; -},"46":function(container,depth0,helpers,partials,data) { +},"52":function(container,depth0,helpers,partials,data) { var stack1, helper, options, buffer = "
    ";
    -  stack1 = ((helper = (helper = helpers.dumpObject || (depth0 != null ? depth0.dumpObject : depth0)) != null ? helper : helpers.helperMissing),(options={"name":"dumpObject","hash":{},"fn":container.program(24, data, 0),"inverse":container.noop,"data":data}),(typeof helper === "function" ? helper.call(depth0 != null ? depth0 : (container.nullContext || {}),options) : helper));
    +  stack1 = ((helper = (helper = helpers.dumpObject || (depth0 != null ? depth0.dumpObject : depth0)) != null ? helper : helpers.helperMissing),(options={"name":"dumpObject","hash":{},"fn":container.program(25, data, 0),"inverse":container.noop,"data":data}),(typeof helper === "function" ? helper.call(depth0 != null ? depth0 : (container.nullContext || {}),options) : helper));
       if (!helpers.dumpObject) { stack1 = helpers.blockHelperMissing.call(depth0,stack1,options)}
       if (stack1 != null) { buffer += stack1; }
       return buffer + "
    \n"; -},"48":function(container,depth0,helpers,partials,data,blockParams,depths) { +},"54":function(container,depth0,helpers,partials,data,blockParams,depths) { var stack1; - return ((stack1 = helpers.each.call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? depth0.definitions : depth0),{"name":"each","hash":{},"fn":container.program(49, data, 0, blockParams, depths),"inverse":container.noop,"data":data})) != null ? stack1 : ""); -},"49":function(container,depth0,helpers,partials,data,blockParams,depths) { + return ((stack1 = helpers.each.call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? depth0.definitions : depth0),{"name":"each","hash":{},"fn":container.program(55, data, 0, blockParams, depths),"inverse":container.noop,"data":data})) != null ? stack1 : ""); +},"55":function(container,depth0,helpers,partials,data,blockParams,depths) { var stack1; - return ((stack1 = helpers.unless.call(depth0 != null ? depth0 : (container.nullContext || {}),(data && data.first),{"name":"unless","hash":{},"fn":container.program(50, data, 0, blockParams, depths),"inverse":container.noop,"data":data})) != null ? stack1 : "") + return ((stack1 = helpers.unless.call(depth0 != null ? depth0 : (container.nullContext || {}),(data && data.first),{"name":"unless","hash":{},"fn":container.program(56, data, 0, blockParams, depths),"inverse":container.noop,"data":data})) != null ? stack1 : "") + "\n" + ((stack1 = container.invokePartial(partials.term,depth0,{"name":"term","hash":{"playback":(depths[1] != null ? depths[1].playback : depths[1]),"addable":(depths[1] != null ? depths[1].addable : depths[1]),"merged":(depths[1] != null ? depths[1].merged : depths[1]),"grouped":(depths[1] != null ? depths[1].grouped : depths[1]),"debug":(depths[1] != null ? depths[1].debug : depths[1])},"data":data,"helpers":helpers,"partials":partials,"decorators":container.decorators})) != null ? stack1 : ""); -},"50":function(container,depth0,helpers,partials,data) { +},"56":function(container,depth0,helpers,partials,data) { return "
    "; -},"52":function(container,depth0,helpers,partials,data) { +},"58":function(container,depth0,helpers,partials,data) { return "

    No results found.

    \n"; },"compiler":[7,">= 4.0.0"],"main":function(container,depth0,helpers,partials,data,blockParams,depths) { var stack1; return "\n\n" - + ((stack1 = helpers["if"].call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? depth0.definitions : depth0),{"name":"if","hash":{},"fn":container.program(48, data, 0, blockParams, depths),"inverse":container.program(52, data, 0, blockParams, depths),"data":data})) != null ? stack1 : ""); + + ((stack1 = helpers["if"].call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? depth0.definitions : depth0),{"name":"if","hash":{},"fn":container.program(54, data, 0, blockParams, depths),"inverse":container.program(58, data, 0, blockParams, depths),"data":data})) != null ? stack1 : ""); },"main_d": function(fn, props, container, depth0, data, blockParams, depths) { var decorators = container.decorators; diff --git a/ext/bg/js/translator.js b/ext/bg/js/translator.js index f959ea35..678bc613 100644 --- a/ext/bg/js/translator.js +++ b/ext/bg/js/translator.js @@ -84,9 +84,11 @@ class Translator { const expressions = []; for (const expression of result.expressions.keys()) { for (const reading of result.expressions.get(expression).keys()) { + const tags = await this.expandTags(result.expressions.get(expression).get(reading), result.dictionary); expressions.push({ expression: expression, reading: reading, + tags: dictTagsSort(tags), jmdictTermFrequency: (tags => { if (tags.has('P')) { return 'popular'; @@ -109,6 +111,7 @@ class Translator { const strayDefinitions = definitionsBySequence['-1'].filter((definition, index) => !mergedByTermIndices.has(index)); for (const groupedDefinition of dictTermsGroup(strayDefinitions, dictionaries)) { + groupedDefinition.expressions = [{expression: groupedDefinition.expression, reading: groupedDefinition.reading}]; definitionsMerged.push(groupedDefinition); } diff --git a/ext/mixed/css/display.css b/ext/mixed/css/display.css index 04e6a326..147256bf 100644 --- a/ext/mixed/css/display.css +++ b/ext/mixed/css/display.css @@ -118,20 +118,34 @@ hr { font-size: 24px; } -.expression a { +.expression .kanji-link { border-bottom: 1px #777 dashed; color: #333; text-decoration: none; } -.expression-popular, .expression-popular a { +.expression-popular, .expression-popular .kanji-link { color: #0275d8; } -.expression-rare, .expression-rare a { +.expression-rare, .expression-rare .kanji-link { color: #999; } +.expression .peek-wrapper { + font-size: 14px; + white-space: nowrap; + display: inline-block; + position: relative; + width: 0px; + height: 0px; + visibility: hidden; +} + +.expression:hover .peek-wrapper { + visibility: visible; +} + .reasons { color: #777; display: inline-block; diff --git a/ext/mixed/js/display.js b/ext/mixed/js/display.js index 2dd95692..e54c8b18 100644 --- a/ext/mixed/js/display.js +++ b/ext/mixed/js/display.js @@ -71,8 +71,10 @@ class Display { onAudioPlay(e) { e.preventDefault(); - const index = Display.entryIndexFind($(e.currentTarget)); - this.audioPlay(this.definitions[index]); + const link = $(e.currentTarget); + const definitionIndex = Display.entryIndexFind(link); + const expressionIndex = $(e.currentTarget).closest('.entry').find('.expression .action-play-audio').index(link); + this.audioPlay(this.definitions[definitionIndex], expressionIndex); } onNoteAdd(e) { @@ -380,11 +382,11 @@ class Display { } } - async audioPlay(definition) { + async audioPlay(definition, expressionIndex) { try { this.spinner.show(); - let url = await apiAudioGetUrl(definition, this.options.general.audioSource); + let url = await apiAudioGetUrl(expressionIndex === -1 ? definition : definition.expressions[expressionIndex], this.options.general.audioSource); if (!url) { url = '/mixed/mp3/button.mp3'; } diff --git a/tmpl/terms.html b/tmpl/terms.html index 505ae5d4..40a44c12 100644 --- a/tmpl/terms.html +++ b/tmpl/terms.html @@ -34,16 +34,30 @@ {{/if}} + {{#unless merged}} {{#if playback}} {{/if}} + {{/unless}}
    {{#if merged}} {{#each expressions}}
    - {{#kanjiLinks}}{{#furigana}}{{{.}}}{{/furigana}}{{/kanjiLinks}}{{#unless @last}}、{{/unless}} + {{#kanjiLinks}}{{#furigana}}{{{.}}}{{/furigana}}{{/kanjiLinks}}
    + {{~#if ../playback~}} +
    + {{/if}} + {{~#if tags~}} + {{~#each tags~}} + {{name}} + {{/each}} + {{/if}}
    {{~#unless @last~}}、{{/unless}}
    {{/each}} {{else}} From 7b9ad61352dcb7ebaf8f3c5e5b2adeb32e14fae1 Mon Sep 17 00:00:00 2001 From: siikamiika Date: Sun, 8 Oct 2017 03:37:28 +0300 Subject: [PATCH 11/64] merged mode: fix regression (voice), tweak hover MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Alt+P now works again in grouped/split mode In merged mode, 「、」 is added even after the last term, but it's hidden for that. This ensures consistent behavior with voice button and tags --- ext/bg/js/templates.js | 8 ++++---- ext/mixed/css/display.css | 4 ++++ ext/mixed/js/display.js | 4 ++-- tmpl/terms.html | 4 ++-- 4 files changed, 12 insertions(+), 8 deletions(-) diff --git a/ext/bg/js/templates.js b/ext/bg/js/templates.js index 01507e1c..a89fdbb5 100644 --- a/ext/bg/js/templates.js +++ b/ext/bg/js/templates.js @@ -305,9 +305,9 @@ templates['terms.html'] = template({"1":function(container,depth0,helpers,partia return buffer + "
    " + ((stack1 = helpers["if"].call(alias1,(depths[1] != null ? depths[1].playback : depths[1]),{"name":"if","hash":{},"fn":container.program(27, data, 0, blockParams, depths),"inverse":container.noop,"data":data})) != null ? stack1 : "") + ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.tags : depth0),{"name":"if","hash":{},"fn":container.program(29, data, 0, blockParams, depths),"inverse":container.noop,"data":data})) != null ? stack1 : "") - + "
    " - + ((stack1 = helpers.unless.call(alias1,(data && data.last),{"name":"unless","hash":{},"fn":container.program(32, data, 0, blockParams, depths),"inverse":container.noop,"data":data})) != null ? stack1 : "") - + "\n \n"; + + "\n"; },"24":function(container,depth0,helpers,partials,data) { var stack1, helper, options; @@ -337,7 +337,7 @@ templates['terms.html'] = template({"1":function(container,depth0,helpers,partia + alias4(((helper = (helper = helpers.name || (depth0 != null ? depth0.name : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"name","hash":{},"data":data}) : helper))) + "\n"; },"32":function(container,depth0,helpers,partials,data) { - return "、"; + return "invisible"; },"34":function(container,depth0,helpers,partials,data) { var stack1, helper, options, buffer = "
    "; diff --git a/ext/mixed/css/display.css b/ext/mixed/css/display.css index 147256bf..fe2f6bbe 100644 --- a/ext/mixed/css/display.css +++ b/ext/mixed/css/display.css @@ -46,6 +46,10 @@ hr { display: none; } +.invisible { + visibility: hidden; +} + /* * Entries diff --git a/ext/mixed/js/display.js b/ext/mixed/js/display.js index e54c8b18..a335c694 100644 --- a/ext/mixed/js/display.js +++ b/ext/mixed/js/display.js @@ -73,7 +73,7 @@ class Display { e.preventDefault(); const link = $(e.currentTarget); const definitionIndex = Display.entryIndexFind(link); - const expressionIndex = $(e.currentTarget).closest('.entry').find('.expression .action-play-audio').index(link); + const expressionIndex = link.closest('.entry').find('.expression .action-play-audio').index(link); this.audioPlay(this.definitions[definitionIndex], expressionIndex); } @@ -185,7 +185,7 @@ class Display { 80: /* p */ () => { if (e.altKey) { if ($('.entry').eq(this.index).data('type') === 'term') { - this.audioPlay(this.definitions[this.index]); + this.audioPlay(this.definitions[this.index], -1); } return true; diff --git a/tmpl/terms.html b/tmpl/terms.html index 40a44c12..b1f080a2 100644 --- a/tmpl/terms.html +++ b/tmpl/terms.html @@ -57,8 +57,8 @@ {{/if}}
    {{~#unless @last~}}、{{/unless}} - + --> {{/each}} {{else}}
    {{#kanjiLinks}}{{#furigana}}{{{.}}}{{/furigana}}{{/kanjiLinks}}
    From ad6ffc54c3795c623eafd0f0a86dd462bc5593c4 Mon Sep 17 00:00:00 2001 From: Alex Yatskov Date: Sun, 8 Oct 2017 14:34:23 -0700 Subject: [PATCH 12/64] Updating README.md --- README.md | 107 +++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 73 insertions(+), 34 deletions(-) diff --git a/README.md b/README.md index 3e67c89a..e29069b7 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,26 @@ Yomichan provides advanced features not available in other browser-based diction * Automatic note creation for the [Anki](https://apps.ankiweb.net/) flashcard program via the [AnkiConnect](https://foosoft.net/projects/anki-connect) plugin. * Clean, modern code makes it easy for developers to [contribute](https://github.com/FooSoft/yomichan) new features. -## Downloads ## +## Table of Contents ## + +* [Installation](https://foosoft.net/projects/yomichan/#installation) +* [Dictionaries](https://foosoft.net/projects/yomichan/#dictionaries) +* [Basic Usage](https://foosoft.net/projects/yomichan/#basic-usage) +* [Custom Dictionaries](https://foosoft.net/projects/yomichan/#custom-dictionaries) +* [Anki Integration](https://foosoft.net/projects/yomichan/#anki-integration) + * [Flashcard Configuration](https://foosoft.net/projects/yomichan/#flashcard-configuration) + * [Flashcard Creation](https://foosoft.net/projects/yomichan/#flashcard-creation) +* [Keyboard Shortcuts](https://foosoft.net/projects/yomichan/#keyboard-shortcuts) +* [Development](https://foosoft.net/projects/yomichan/#development) + * [Templates](https://foosoft.net/projects/yomichan/#templates) + * [Dependencies](https://foosoft.net/projects/yomichan/#dependencies) +* [Frequently Asked Questions](https://foosoft.net/projects/yomichan/#frequently-asked-questions) +* [Screenshots](https://foosoft.net/projects/yomichan/#screenshots) +* [License](https://foosoft.net/projects/yomichan/#license) + +## Installation ## + +Download and install Yomichan from your browser's web store: * **Google Chrome** (versions 45+) @@ -239,52 +258,72 @@ versions packaged. ## Frequently Asked Questions ## -* **Why does the Kanji results page display "No data found" for several fields?** +**I'm having problems importing dictionaries in Firefox, what do I do?** - You are using data from the KANJIDIC dictionary that was exported for an earlier version of Yomichan. It does not - contain the additional information which newer versions of Yofomichan expect. Unfortunately, since major browser - implementations of IndexedDB do not provide reliable means for selective bulk data deletion, you will need purge - your database and install the latest version of the KANJIDIC to see additional information about characters. +Yomichan uses the cross-browser IndexedDB system for storing imported dictionary data into your user profile. Although +everything "just works" in Chrome, depending on settings, Firefox users can run into problems due browser bugs. +Yomichan catches errors and tries to offer suggestions about how to work around Firefox issues, but in general at least +one of the following solutions should work for you: -* **Can I still create cards without HTML formatting? The option for it is gone!** +* Make sure you have cookies enabled. It appears that disabling them also disables IndexedDB for some reason. You + can still have cookies be disabled on other sites; just make sure to add the Yomichan extension to the whitelist of + whatever tool you are using to restrict cookies. You can get the extension "URL" by looking at the address bar when + you have the search page open. +* Make sure that you have sufficient disk space available on the drive Firefox uses to store your user profile. + Firefox limits the amount of space that can be used by IndexedDB to a small fraction of the disk space actually + available on your computer. +* Make sure that you have history set to "Remember history" enabled in your privacy settings. When this option is + set to "Never remember history", IndexedDB access is once again disabled for an inexplicable reason. +* As a last resort, try using the [Refresh Firefox](https://support.mozilla.org/en-US/kb/reset-preferences-fix-problems) + feature to reset your user profile. It appears that the Firefox profile system can corrupt itself preventing + IndexedDB from being accessible to Yomichan. - Developing Yomichan is a constant balance between including useful features and keeping complexity at a minimum. - With the new user-editable card template system, it is possible to create text-only cards without having to double - the number field of templates in the extension itself. If you would like to stop HTML tags from being added to your - cards, simply copy the contents of the text-only field template into the template box on - the Anki settings page (make sure you have the *Show advanced options* checkbox ticked), making sure to replace the - existing values. +**Why does the Kanji results page display "No data found" for several fields?** -* **Will you add support for online dictionaries?** +You are using data from the KANJIDIC dictionary that was exported for an earlier version of Yomichan. It does not +contain the additional information which newer versions of Yofomichan expect. Unfortunately, since major browser +implementations of IndexedDB do not provide reliable means for selective bulk data deletion, you will need purge +your database and install the latest version of the KANJIDIC to see additional information about characters. - Online dictionaries will never be implemented because it is impossible to support them in a robust way. In order to - perform Japanese deinflection, Yomichan must execute dozens of database queries per every single word. Factoring in - network latency and the fragility of web scraping, I do not believe that it is possible to realize a good user - experience. +**Can I still create cards without HTML formatting? The option for it is gone!** -* **Is it possible to use Yomichan with files saved locally on my computer with Chrome?** +Developing Yomichan is a constant balance between including useful features and keeping complexity at a minimum. +With the new user-editable card template system, it is possible to create text-only cards without having to double +the number field of templates in the extension itself. If you would like to stop HTML tags from being added to your +cards, simply copy the contents of the text-only field template into the template box on +the Anki settings page (make sure you have the *Show advanced options* checkbox ticked), making sure to replace the +existing values. - In order to use Yomichan with local files in Chrome, you must first tick the *Allow access to file URLs* checkbox - for Yomichan on the extensions page. Due to the restrictions placed on browser addons in the WebExtensions model, it - will likely never be possible to use Yomichan with PDF files. +**Will you add support for online dictionaries?** -* **Is it possible to delete individual dictionaries without purging the database?** +Online dictionaries will never be implemented because it is impossible to support them in a robust way. In order to +perform Japanese deinflection, Yomichan must execute dozens of database queries per every single word. Factoring in +network latency and the fragility of web scraping, I do not believe that it is possible to realize a good user +experience. - Although it is technically possible to purge specific dictionaries, due to the limitations of the underlying browser - IndexedDB system, this process is *extremely* slow. For example, it can take up to ten minutes to delete a single - moderately-sized term dictionary! Instead of including a borderline unusable feature in Yomichan, I have chosen to - disable dictionary deletion entirely. +**Is it possible to use Yomichan with files saved locally on my computer with Chrome?** -* **Why aren't EPWING dictionaries bundled with Yomichan?** +In order to use Yomichan with local files in Chrome, you must first tick the *Allow access to file URLs* checkbox +for Yomichan on the extensions page. Due to the restrictions placed on browser addons in the WebExtensions model, it +will likely never be possible to use Yomichan with PDF files. - The vast majority of EPWING dictionaries are proprietary, so unfortunately I am unable to legally include them in - this extension for copyright reasons. +**Is it possible to delete individual dictionaries without purging the database?** -* **When are you going to add support for $MYLANGUAGE?** +Although it is technically possible to purge specific dictionaries, due to the limitations of the underlying browser +IndexedDB system, this process is *extremely* slow. For example, it can take up to ten minutes to delete a single +moderately-sized term dictionary! Instead of including a borderline unusable feature in Yomichan, I have chosen to +disable dictionary deletion entirely. - Developing Yomichan requires a significant understanding of Japanese sentence structure and grammar. I have no time - to invest in learning yet another language; therefore other languages will not be supported. I will also not accept - pull request containing this functionality, as I will ultimately be the one maintaining your code. +**Why aren't EPWING dictionaries bundled with Yomichan?** + +The vast majority of EPWING dictionaries are proprietary, so unfortunately I am unable to legally include them in +this extension for copyright reasons. + +**When are you going to add support for $MYLANGUAGE?** + +Developing Yomichan requires a significant understanding of Japanese sentence structure and grammar. I have no time +to invest in learning yet another language; therefore other languages will not be supported. I will also not accept +pull request containing this functionality, as I will ultimately be the one maintaining your code. ## Screenshots ## From 84420e00bfe025c93ed6ef77f81634687ff64764 Mon Sep 17 00:00:00 2001 From: siikamiika Date: Mon, 9 Oct 2017 23:22:12 +0300 Subject: [PATCH 13/64] merged mode: fix tags for non-main dictionaries --- ext/bg/js/dictionary.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ext/bg/js/dictionary.js b/ext/bg/js/dictionary.js index b81d1411..25bcaf69 100644 --- a/ext/bg/js/dictionary.js +++ b/ext/bg/js/dictionary.js @@ -228,8 +228,10 @@ function dictTermsMergeByGloss(result, definitions, appendTo, mergedIndices) { for (const tag of definition.tags) { if (dictIsJmdictTermTag(tag)) { result.expressions.get(definition.expression).get(definition.reading).add(tag); - } else { + } else if (typeof tag === 'string') { definitionsByGloss[gloss].tags.add(tag); + } else if (tag.category && tag.category !== 'dictionary') { + definitionsByGloss[gloss].tags.add(tag.name); } } } From 9f277b6a20867c65b80378ee8008d4f55974bfdf Mon Sep 17 00:00:00 2001 From: siikamiika Date: Tue, 10 Oct 2017 00:56:47 +0300 Subject: [PATCH 14/64] merged mode: support frequencies --- ext/bg/js/templates.js | 88 +++++++++++++++++++++++---------------- ext/mixed/css/display.css | 18 ++++++++ tmpl/terms.html | 12 +++++- 3 files changed, 80 insertions(+), 38 deletions(-) diff --git a/ext/bg/js/templates.js b/ext/bg/js/templates.js index a89fdbb5..9a576479 100644 --- a/ext/bg/js/templates.js +++ b/ext/bg/js/templates.js @@ -272,15 +272,15 @@ templates['terms.html'] = template({"1":function(container,depth0,helpers,partia + ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.addable : depth0),{"name":"if","hash":{},"fn":container.program(17, data, 0, blockParams, depths),"inverse":container.noop,"data":data})) != null ? stack1 : "") + ((stack1 = helpers.unless.call(alias1,(depth0 != null ? depth0.merged : depth0),{"name":"unless","hash":{},"fn":container.program(19, data, 0, blockParams, depths),"inverse":container.noop,"data":data})) != null ? stack1 : "") + " \n \n\n" - + ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.merged : depth0),{"name":"if","hash":{},"fn":container.program(22, data, 0, blockParams, depths),"inverse":container.program(34, data, 0, blockParams, depths),"data":data})) != null ? stack1 : "") + + ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.merged : depth0),{"name":"if","hash":{},"fn":container.program(22, data, 0, blockParams, depths),"inverse":container.program(37, data, 0, blockParams, depths),"data":data})) != null ? stack1 : "") + "\n" - + ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.reasons : depth0),{"name":"if","hash":{},"fn":container.program(36, data, 0, blockParams, depths),"inverse":container.noop,"data":data})) != null ? stack1 : "") + + ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.reasons : depth0),{"name":"if","hash":{},"fn":container.program(39, data, 0, blockParams, depths),"inverse":container.noop,"data":data})) != null ? stack1 : "") + "\n" - + ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.frequencies : depth0),{"name":"if","hash":{},"fn":container.program(40, data, 0, blockParams, depths),"inverse":container.noop,"data":data})) != null ? stack1 : "") + + ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.frequencies : depth0),{"name":"if","hash":{},"fn":container.program(43, data, 0, blockParams, depths),"inverse":container.noop,"data":data})) != null ? stack1 : "") + "\n
    \n" - + ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.grouped : depth0),{"name":"if","hash":{},"fn":container.program(43, data, 0, blockParams, depths),"inverse":container.program(49, data, 0, blockParams, depths),"data":data})) != null ? stack1 : "") + + ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.grouped : depth0),{"name":"if","hash":{},"fn":container.program(46, data, 0, blockParams, depths),"inverse":container.program(52, data, 0, blockParams, depths),"data":data})) != null ? stack1 : "") + "
    \n\n" - + ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.debug : depth0),{"name":"if","hash":{},"fn":container.program(52, data, 0, blockParams, depths),"inverse":container.noop,"data":data})) != null ? stack1 : "") + + ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.debug : depth0),{"name":"if","hash":{},"fn":container.program(55, data, 0, blockParams, depths),"inverse":container.noop,"data":data})) != null ? stack1 : "") + "\n"; },"17":function(container,depth0,helpers,partials,data) { return " \n \n \n"; @@ -305,8 +305,9 @@ templates['terms.html'] = template({"1":function(container,depth0,helpers,partia return buffer + "
    " + ((stack1 = helpers["if"].call(alias1,(depths[1] != null ? depths[1].playback : depths[1]),{"name":"if","hash":{},"fn":container.program(27, data, 0, blockParams, depths),"inverse":container.noop,"data":data})) != null ? stack1 : "") + ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.tags : depth0),{"name":"if","hash":{},"fn":container.program(29, data, 0, blockParams, depths),"inverse":container.noop,"data":data})) != null ? stack1 : "") - + "
    \n"; },"24":function(container,depth0,helpers,partials,data) { var stack1, helper, options; @@ -320,12 +321,13 @@ templates['terms.html'] = template({"1":function(container,depth0,helpers,partia return ((stack1 = container.lambda(depth0, depth0)) != null ? stack1 : ""); },"27":function(container,depth0,helpers,partials,data) { - return "
    \n"; + return "\n"; },"29":function(container,depth0,helpers,partials,data) { var stack1; - return ((stack1 = helpers.each.call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? depth0.tags : depth0),{"name":"each","hash":{},"fn":container.program(30, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") - + " "; + return "
    " + + ((stack1 = helpers.each.call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? depth0.tags : depth0),{"name":"each","hash":{},"fn":container.program(30, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") + + "
    \n"; },"30":function(container,depth0,helpers,partials,data) { var helper, alias1=depth0 != null ? depth0 : (container.nullContext || {}), alias2=helpers.helperMissing, alias3="function", alias4=container.escapeExpression; @@ -337,37 +339,51 @@ templates['terms.html'] = template({"1":function(container,depth0,helpers,partia + alias4(((helper = (helper = helpers.name || (depth0 != null ? depth0.name : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"name","hash":{},"data":data}) : helper))) + "
    \n"; },"32":function(container,depth0,helpers,partials,data) { + var stack1; + + return "
    " + + ((stack1 = helpers.each.call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? depth0.frequencies : depth0),{"name":"each","hash":{},"fn":container.program(33, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") + + "
    \n "; +},"33":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.dictionary || (depth0 != null ? depth0.dictionary : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"dictionary","hash":{},"data":data}) : helper))) + + ":" + + alias4(((helper = (helper = helpers.frequency || (depth0 != null ? depth0.frequency : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"frequency","hash":{},"data":data}) : helper))) + + "\n"; +},"35":function(container,depth0,helpers,partials,data) { return "invisible"; -},"34":function(container,depth0,helpers,partials,data) { +},"37":function(container,depth0,helpers,partials,data) { var stack1, helper, options, buffer = "
    "; stack1 = ((helper = (helper = helpers.kanjiLinks || (depth0 != null ? depth0.kanjiLinks : depth0)) != null ? helper : helpers.helperMissing),(options={"name":"kanjiLinks","hash":{},"fn":container.program(24, data, 0),"inverse":container.noop,"data":data}),(typeof helper === "function" ? helper.call(depth0 != null ? depth0 : (container.nullContext || {}),options) : helper)); if (!helpers.kanjiLinks) { stack1 = helpers.blockHelperMissing.call(depth0,stack1,options)} if (stack1 != null) { buffer += stack1; } return buffer + "
    \n"; -},"36":function(container,depth0,helpers,partials,data) { +},"39":function(container,depth0,helpers,partials,data) { var stack1; return "
    \n" - + ((stack1 = helpers.each.call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? depth0.reasons : depth0),{"name":"each","hash":{},"fn":container.program(37, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") + + ((stack1 = helpers.each.call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? depth0.reasons : depth0),{"name":"each","hash":{},"fn":container.program(40, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") + "
    \n"; -},"37":function(container,depth0,helpers,partials,data) { +},"40":function(container,depth0,helpers,partials,data) { var stack1; return " " + container.escapeExpression(container.lambda(depth0, depth0)) + " " - + ((stack1 = helpers.unless.call(depth0 != null ? depth0 : (container.nullContext || {}),(data && data.last),{"name":"unless","hash":{},"fn":container.program(38, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") + + ((stack1 = helpers.unless.call(depth0 != null ? depth0 : (container.nullContext || {}),(data && data.last),{"name":"unless","hash":{},"fn":container.program(41, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") + "\n"; -},"38":function(container,depth0,helpers,partials,data) { +},"41":function(container,depth0,helpers,partials,data) { return "«"; -},"40":function(container,depth0,helpers,partials,data) { +},"43":function(container,depth0,helpers,partials,data) { var stack1; return "
    \n" - + ((stack1 = helpers.each.call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? depth0.frequencies : depth0),{"name":"each","hash":{},"fn":container.program(41, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") + + ((stack1 = helpers.each.call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? depth0.frequencies : depth0),{"name":"each","hash":{},"fn":container.program(44, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") + "
    \n"; -},"41":function(container,depth0,helpers,partials,data) { +},"44":function(container,depth0,helpers,partials,data) { var helper, alias1=depth0 != null ? depth0 : (container.nullContext || {}), alias2=helpers.helperMissing, alias3="function", alias4=container.escapeExpression; return " " @@ -375,61 +391,61 @@ templates['terms.html'] = template({"1":function(container,depth0,helpers,partia + ":" + alias4(((helper = (helper = helpers.frequency || (depth0 != null ? depth0.frequency : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"frequency","hash":{},"data":data}) : helper))) + "\n"; -},"43":function(container,depth0,helpers,partials,data) { +},"46":function(container,depth0,helpers,partials,data) { var stack1; - return ((stack1 = helpers["if"].call(depth0 != null ? depth0 : (container.nullContext || {}),((stack1 = (depth0 != null ? depth0.definitions : depth0)) != null ? stack1["1"] : stack1),{"name":"if","hash":{},"fn":container.program(44, data, 0),"inverse":container.program(47, data, 0),"data":data})) != null ? stack1 : ""); -},"44":function(container,depth0,helpers,partials,data) { + return ((stack1 = helpers["if"].call(depth0 != null ? depth0 : (container.nullContext || {}),((stack1 = (depth0 != null ? depth0.definitions : depth0)) != null ? stack1["1"] : stack1),{"name":"if","hash":{},"fn":container.program(47, data, 0),"inverse":container.program(50, data, 0),"data":data})) != null ? stack1 : ""); +},"47":function(container,depth0,helpers,partials,data) { var stack1; return "
      \n" - + ((stack1 = helpers.each.call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? depth0.definitions : depth0),{"name":"each","hash":{},"fn":container.program(45, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") + + ((stack1 = helpers.each.call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? depth0.definitions : depth0),{"name":"each","hash":{},"fn":container.program(48, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") + "
    \n"; -},"45":function(container,depth0,helpers,partials,data) { +},"48":function(container,depth0,helpers,partials,data) { var stack1; return "
  • " + ((stack1 = container.invokePartial(partials.definition,depth0,{"name":"definition","data":data,"helpers":helpers,"partials":partials,"decorators":container.decorators})) != null ? stack1 : "") + "
  • \n"; -},"47":function(container,depth0,helpers,partials,data) { +},"50":function(container,depth0,helpers,partials,data) { var stack1; return ((stack1 = container.invokePartial(partials.definition,((stack1 = (depth0 != null ? depth0.definitions : depth0)) != null ? stack1["0"] : stack1),{"name":"definition","data":data,"indent":" ","helpers":helpers,"partials":partials,"decorators":container.decorators})) != null ? stack1 : ""); -},"49":function(container,depth0,helpers,partials,data,blockParams,depths) { +},"52":function(container,depth0,helpers,partials,data,blockParams,depths) { var stack1; - return ((stack1 = helpers["if"].call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? depth0.merged : depth0),{"name":"if","hash":{},"fn":container.program(43, data, 0, blockParams, depths),"inverse":container.program(50, data, 0, blockParams, depths),"data":data})) != null ? stack1 : ""); -},"50":function(container,depth0,helpers,partials,data) { + return ((stack1 = helpers["if"].call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? depth0.merged : depth0),{"name":"if","hash":{},"fn":container.program(46, data, 0, blockParams, depths),"inverse":container.program(53, data, 0, blockParams, depths),"data":data})) != null ? stack1 : ""); +},"53":function(container,depth0,helpers,partials,data) { var stack1; return ((stack1 = container.invokePartial(partials.definition,depth0,{"name":"definition","data":data,"indent":" ","helpers":helpers,"partials":partials,"decorators":container.decorators})) != null ? stack1 : "") + " "; -},"52":function(container,depth0,helpers,partials,data) { +},"55":function(container,depth0,helpers,partials,data) { var stack1, helper, options, buffer = "
    ";
       stack1 = ((helper = (helper = helpers.dumpObject || (depth0 != null ? depth0.dumpObject : depth0)) != null ? helper : helpers.helperMissing),(options={"name":"dumpObject","hash":{},"fn":container.program(25, data, 0),"inverse":container.noop,"data":data}),(typeof helper === "function" ? helper.call(depth0 != null ? depth0 : (container.nullContext || {}),options) : helper));
       if (!helpers.dumpObject) { stack1 = helpers.blockHelperMissing.call(depth0,stack1,options)}
       if (stack1 != null) { buffer += stack1; }
       return buffer + "
    \n"; -},"54":function(container,depth0,helpers,partials,data,blockParams,depths) { +},"57":function(container,depth0,helpers,partials,data,blockParams,depths) { var stack1; - return ((stack1 = helpers.each.call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? depth0.definitions : depth0),{"name":"each","hash":{},"fn":container.program(55, data, 0, blockParams, depths),"inverse":container.noop,"data":data})) != null ? stack1 : ""); -},"55":function(container,depth0,helpers,partials,data,blockParams,depths) { + return ((stack1 = helpers.each.call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? depth0.definitions : depth0),{"name":"each","hash":{},"fn":container.program(58, data, 0, blockParams, depths),"inverse":container.noop,"data":data})) != null ? stack1 : ""); +},"58":function(container,depth0,helpers,partials,data,blockParams,depths) { var stack1; - return ((stack1 = helpers.unless.call(depth0 != null ? depth0 : (container.nullContext || {}),(data && data.first),{"name":"unless","hash":{},"fn":container.program(56, data, 0, blockParams, depths),"inverse":container.noop,"data":data})) != null ? stack1 : "") + return ((stack1 = helpers.unless.call(depth0 != null ? depth0 : (container.nullContext || {}),(data && data.first),{"name":"unless","hash":{},"fn":container.program(59, data, 0, blockParams, depths),"inverse":container.noop,"data":data})) != null ? stack1 : "") + "\n" + ((stack1 = container.invokePartial(partials.term,depth0,{"name":"term","hash":{"playback":(depths[1] != null ? depths[1].playback : depths[1]),"addable":(depths[1] != null ? depths[1].addable : depths[1]),"merged":(depths[1] != null ? depths[1].merged : depths[1]),"grouped":(depths[1] != null ? depths[1].grouped : depths[1]),"debug":(depths[1] != null ? depths[1].debug : depths[1])},"data":data,"helpers":helpers,"partials":partials,"decorators":container.decorators})) != null ? stack1 : ""); -},"56":function(container,depth0,helpers,partials,data) { +},"59":function(container,depth0,helpers,partials,data) { return "
    "; -},"58":function(container,depth0,helpers,partials,data) { +},"61":function(container,depth0,helpers,partials,data) { return "

    No results found.

    \n"; },"compiler":[7,">= 4.0.0"],"main":function(container,depth0,helpers,partials,data,blockParams,depths) { var stack1; return "\n\n" - + ((stack1 = helpers["if"].call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? depth0.definitions : depth0),{"name":"if","hash":{},"fn":container.program(54, data, 0, blockParams, depths),"inverse":container.program(58, data, 0, blockParams, depths),"data":data})) != null ? stack1 : ""); + + ((stack1 = helpers["if"].call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? depth0.definitions : depth0),{"name":"if","hash":{},"fn":container.program(57, data, 0, blockParams, depths),"inverse":container.program(61, data, 0, blockParams, depths),"data":data})) != null ? stack1 : ""); },"main_d": function(fn, props, container, depth0, data, blockParams, depths) { var decorators = container.decorators; diff --git a/ext/mixed/css/display.css b/ext/mixed/css/display.css index fe2f6bbe..3c0539bd 100644 --- a/ext/mixed/css/display.css +++ b/ext/mixed/css/display.css @@ -146,6 +146,24 @@ hr { visibility: hidden; } +.expression .peek-wrapper .action-play-audio { + position: absolute; + left: 0px; + bottom: 10px; +} + +.expression .peek-wrapper .tags { + position: absolute; + left: 0px; + bottom: -10px; +} + +.expression .peek-wrapper .frequencies { + position: absolute; + left: 0px; + bottom: -30px; +} + .expression:hover .peek-wrapper { visibility: visible; } diff --git a/tmpl/terms.html b/tmpl/terms.html index b1f080a2..cc0f600e 100644 --- a/tmpl/terms.html +++ b/tmpl/terms.html @@ -48,14 +48,22 @@ {{#kanjiLinks}}{{#furigana}}{{{.}}}{{/furigana}}{{/kanjiLinks}}
    {{~#if ../playback~}} -
    + {{/if}} {{~#if tags~}} +
    {{~#each tags~}} {{name}} {{/each}} +
    + {{/if}} + {{~#if frequencies~}} +
    + {{~#each frequencies~}} + {{dictionary}}:{{frequency}} + {{/each}} +
    {{/if}}
    From b9d589374cd2105c195a8c41d71c459a53c0fae3 Mon Sep 17 00:00:00 2001 From: siikamiika Date: Tue, 10 Oct 2017 04:13:36 +0300 Subject: [PATCH 15/64] merged mode: support audio hotkey Alt+P --- ext/mixed/js/display.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/mixed/js/display.js b/ext/mixed/js/display.js index a335c694..e3b5ee50 100644 --- a/ext/mixed/js/display.js +++ b/ext/mixed/js/display.js @@ -185,7 +185,7 @@ class Display { 80: /* p */ () => { if (e.altKey) { if ($('.entry').eq(this.index).data('type') === 'term') { - this.audioPlay(this.definitions[this.index], -1); + this.audioPlay(this.definitions[this.index], this.options.general.resultOutputMode === 'merge' ? 0 : -1); } return true; From e1c5d7a401f1f974da1bedd8600524d982c2c7de Mon Sep 17 00:00:00 2001 From: siikamiika Date: Tue, 10 Oct 2017 06:04:49 +0300 Subject: [PATCH 16/64] merged mode: make gloss hash more unique MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use ['gloss', 'ary'].concat('DictName') Known collision: 日本国有鉄道 in JMdict and JMnedict --- ext/bg/js/dictionary.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/bg/js/dictionary.js b/ext/bg/js/dictionary.js index 25bcaf69..b6ca6fd5 100644 --- a/ext/bg/js/dictionary.js +++ b/ext/bg/js/dictionary.js @@ -196,7 +196,7 @@ function dictTermsMergeByGloss(result, definitions, appendTo, mergedIndices) { } } - const gloss = JSON.stringify(definition.glossary); + const gloss = JSON.stringify(definition.glossary.concat(definition.dictionary)); if (!definitionsByGloss[gloss]) { definitionsByGloss[gloss] = { expression: new Set(), From 4fb983a70cd02c0c0126a26e70d40261d5b2a51d Mon Sep 17 00:00:00 2001 From: siikamiika Date: Wed, 11 Oct 2017 09:18:55 +0300 Subject: [PATCH 17/64] add termTags The dictionary tags field can now have a '\t' in it, and it is used to separate tags associated with definitions and terms. --- ext/bg/js/database.js | 8 ++++-- ext/bg/js/dictionary.js | 31 +++++---------------- ext/bg/js/templates.js | 60 ++++++++++++++++++++++++++--------------- ext/bg/js/translator.js | 2 ++ tmpl/terms.html | 8 ++++++ 5 files changed, 61 insertions(+), 48 deletions(-) diff --git a/ext/bg/js/database.js b/ext/bg/js/database.js index 7a893fc0..1c2194df 100644 --- a/ext/bg/js/database.js +++ b/ext/bg/js/database.js @@ -68,10 +68,12 @@ class Database { const results = []; await this.db.terms.where('expression').equals(term).or('reading').equals(term).each(row => { if (titles.includes(row.dictionary)) { + const tags = row.tags.split('\t'); results.push({ expression: row.expression, reading: row.reading, - tags: dictFieldSplit(row.tags), + tags: dictFieldSplit(tags[0]), + termTags: tags.length > 1 ? dictFieldSplit(tags[1]) : [], rules: dictFieldSplit(row.rules), glossary: row.glossary, score: row.score, @@ -93,10 +95,12 @@ class Database { const results = []; await this.db.terms.where('sequence').equals(sequence).each(row => { if (row.dictionary === mainDictionary) { + const tags = row.tags.split('\t'); results.push({ expression: row.expression, reading: row.reading, - tags: dictFieldSplit(row.tags), + tags: dictFieldSplit(tags[0]), + termTags: tags.length > 1 ? dictFieldSplit(tags[1]) : [], rules: dictFieldSplit(row.rules), glossary: row.glossary, score: row.score, diff --git a/ext/bg/js/dictionary.js b/ext/bg/js/dictionary.js index b6ca6fd5..ee4f5946 100644 --- a/ext/bg/js/dictionary.js +++ b/ext/bg/js/dictionary.js @@ -136,6 +136,7 @@ function dictTermsGroup(definitions, dictionaries) { expression: firstDef.expression, reading: firstDef.reading, reasons: firstDef.reasons, + termTags: groupDefs[0].termTags, score: groupDefs.reduce((p, v) => v.score > p ? v.score : p, Number.MIN_SAFE_INTEGER), source: firstDef.source }); @@ -226,14 +227,16 @@ function dictTermsMergeByGloss(result, definitions, appendTo, mergedIndices) { } for (const tag of definition.tags) { - if (dictIsJmdictTermTag(tag)) { - result.expressions.get(definition.expression).get(definition.reading).add(tag); - } else if (typeof tag === 'string') { + if (typeof tag === 'string') { definitionsByGloss[gloss].tags.add(tag); } else if (tag.category && tag.category !== 'dictionary') { definitionsByGloss[gloss].tags.add(tag.name); } } + + for (const tag of definition.termTags) { + result.expressions.get(definition.expression).get(definition.reading).add(tag); + } } for (const gloss in definitionsByGloss) { @@ -288,34 +291,12 @@ function dictTagsSort(tags) { }); } -function dictIsJmdictTermTag(tag) { - return [ - 'P', - 'news', - 'ichi', - 'spec', - 'gai', - 'ik', - 'iK', - 'ok', - 'oK', - 'ek', - 'eK', - 'io', - 'oik', - 'ateji', - 'gikun' - ].includes(tag); -} - function dictJmdictTermTagsRare(tags) { const rareTags = [ 'ik', 'iK', 'ok', 'oK', - 'ek', - 'eK', 'io', 'oik' ]; diff --git a/ext/bg/js/templates.js b/ext/bg/js/templates.js index 9a576479..19c49337 100644 --- a/ext/bg/js/templates.js +++ b/ext/bg/js/templates.js @@ -276,11 +276,13 @@ templates['terms.html'] = template({"1":function(container,depth0,helpers,partia + "\n" + ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.reasons : depth0),{"name":"if","hash":{},"fn":container.program(39, data, 0, blockParams, depths),"inverse":container.noop,"data":data})) != null ? stack1 : "") + "\n" - + ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.frequencies : depth0),{"name":"if","hash":{},"fn":container.program(43, data, 0, blockParams, depths),"inverse":container.noop,"data":data})) != null ? stack1 : "") + + ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.termTags : depth0),{"name":"if","hash":{},"fn":container.program(43, data, 0, blockParams, depths),"inverse":container.noop,"data":data})) != null ? stack1 : "") + + "\n" + + ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.frequencies : depth0),{"name":"if","hash":{},"fn":container.program(46, data, 0, blockParams, depths),"inverse":container.noop,"data":data})) != null ? stack1 : "") + "\n
    \n" - + ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.grouped : depth0),{"name":"if","hash":{},"fn":container.program(46, data, 0, blockParams, depths),"inverse":container.program(52, data, 0, blockParams, depths),"data":data})) != null ? stack1 : "") + + ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.grouped : depth0),{"name":"if","hash":{},"fn":container.program(49, data, 0, blockParams, depths),"inverse":container.program(55, data, 0, blockParams, depths),"data":data})) != null ? stack1 : "") + "
    \n\n" - + ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.debug : depth0),{"name":"if","hash":{},"fn":container.program(55, data, 0, blockParams, depths),"inverse":container.noop,"data":data})) != null ? stack1 : "") + + ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.debug : depth0),{"name":"if","hash":{},"fn":container.program(58, data, 0, blockParams, depths),"inverse":container.noop,"data":data})) != null ? stack1 : "") + "\n"; },"17":function(container,depth0,helpers,partials,data) { return " \n \n \n"; @@ -381,71 +383,87 @@ templates['terms.html'] = template({"1":function(container,depth0,helpers,partia var stack1; return "
    \n" - + ((stack1 = helpers.each.call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? depth0.frequencies : depth0),{"name":"each","hash":{},"fn":container.program(44, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") + + ((stack1 = helpers.each.call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? depth0.termTags : depth0),{"name":"each","hash":{},"fn":container.program(44, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") + "
    \n"; },"44":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.name || (depth0 != null ? depth0.name : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"name","hash":{},"data":data}) : helper))) + + "\n"; +},"46":function(container,depth0,helpers,partials,data) { + var stack1; + + return "
    \n" + + ((stack1 = helpers.each.call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? depth0.frequencies : depth0),{"name":"each","hash":{},"fn":container.program(47, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") + + "
    \n"; +},"47":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.dictionary || (depth0 != null ? depth0.dictionary : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"dictionary","hash":{},"data":data}) : helper))) + ":" + alias4(((helper = (helper = helpers.frequency || (depth0 != null ? depth0.frequency : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"frequency","hash":{},"data":data}) : helper))) + "\n"; -},"46":function(container,depth0,helpers,partials,data) { +},"49":function(container,depth0,helpers,partials,data) { var stack1; - return ((stack1 = helpers["if"].call(depth0 != null ? depth0 : (container.nullContext || {}),((stack1 = (depth0 != null ? depth0.definitions : depth0)) != null ? stack1["1"] : stack1),{"name":"if","hash":{},"fn":container.program(47, data, 0),"inverse":container.program(50, data, 0),"data":data})) != null ? stack1 : ""); -},"47":function(container,depth0,helpers,partials,data) { + return ((stack1 = helpers["if"].call(depth0 != null ? depth0 : (container.nullContext || {}),((stack1 = (depth0 != null ? depth0.definitions : depth0)) != null ? stack1["1"] : stack1),{"name":"if","hash":{},"fn":container.program(50, data, 0),"inverse":container.program(53, data, 0),"data":data})) != null ? stack1 : ""); +},"50":function(container,depth0,helpers,partials,data) { var stack1; return "
      \n" - + ((stack1 = helpers.each.call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? depth0.definitions : depth0),{"name":"each","hash":{},"fn":container.program(48, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") + + ((stack1 = helpers.each.call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? depth0.definitions : depth0),{"name":"each","hash":{},"fn":container.program(51, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") + "
    \n"; -},"48":function(container,depth0,helpers,partials,data) { +},"51":function(container,depth0,helpers,partials,data) { var stack1; return "
  • " + ((stack1 = container.invokePartial(partials.definition,depth0,{"name":"definition","data":data,"helpers":helpers,"partials":partials,"decorators":container.decorators})) != null ? stack1 : "") + "
  • \n"; -},"50":function(container,depth0,helpers,partials,data) { +},"53":function(container,depth0,helpers,partials,data) { var stack1; return ((stack1 = container.invokePartial(partials.definition,((stack1 = (depth0 != null ? depth0.definitions : depth0)) != null ? stack1["0"] : stack1),{"name":"definition","data":data,"indent":" ","helpers":helpers,"partials":partials,"decorators":container.decorators})) != null ? stack1 : ""); -},"52":function(container,depth0,helpers,partials,data,blockParams,depths) { +},"55":function(container,depth0,helpers,partials,data,blockParams,depths) { var stack1; - return ((stack1 = helpers["if"].call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? depth0.merged : depth0),{"name":"if","hash":{},"fn":container.program(46, data, 0, blockParams, depths),"inverse":container.program(53, data, 0, blockParams, depths),"data":data})) != null ? stack1 : ""); -},"53":function(container,depth0,helpers,partials,data) { + return ((stack1 = helpers["if"].call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? depth0.merged : depth0),{"name":"if","hash":{},"fn":container.program(49, data, 0, blockParams, depths),"inverse":container.program(56, data, 0, blockParams, depths),"data":data})) != null ? stack1 : ""); +},"56":function(container,depth0,helpers,partials,data) { var stack1; return ((stack1 = container.invokePartial(partials.definition,depth0,{"name":"definition","data":data,"indent":" ","helpers":helpers,"partials":partials,"decorators":container.decorators})) != null ? stack1 : "") + " "; -},"55":function(container,depth0,helpers,partials,data) { +},"58":function(container,depth0,helpers,partials,data) { var stack1, helper, options, buffer = "
    ";
       stack1 = ((helper = (helper = helpers.dumpObject || (depth0 != null ? depth0.dumpObject : depth0)) != null ? helper : helpers.helperMissing),(options={"name":"dumpObject","hash":{},"fn":container.program(25, data, 0),"inverse":container.noop,"data":data}),(typeof helper === "function" ? helper.call(depth0 != null ? depth0 : (container.nullContext || {}),options) : helper));
       if (!helpers.dumpObject) { stack1 = helpers.blockHelperMissing.call(depth0,stack1,options)}
       if (stack1 != null) { buffer += stack1; }
       return buffer + "
    \n"; -},"57":function(container,depth0,helpers,partials,data,blockParams,depths) { +},"60":function(container,depth0,helpers,partials,data,blockParams,depths) { var stack1; - return ((stack1 = helpers.each.call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? depth0.definitions : depth0),{"name":"each","hash":{},"fn":container.program(58, data, 0, blockParams, depths),"inverse":container.noop,"data":data})) != null ? stack1 : ""); -},"58":function(container,depth0,helpers,partials,data,blockParams,depths) { + return ((stack1 = helpers.each.call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? depth0.definitions : depth0),{"name":"each","hash":{},"fn":container.program(61, data, 0, blockParams, depths),"inverse":container.noop,"data":data})) != null ? stack1 : ""); +},"61":function(container,depth0,helpers,partials,data,blockParams,depths) { var stack1; - return ((stack1 = helpers.unless.call(depth0 != null ? depth0 : (container.nullContext || {}),(data && data.first),{"name":"unless","hash":{},"fn":container.program(59, data, 0, blockParams, depths),"inverse":container.noop,"data":data})) != null ? stack1 : "") + return ((stack1 = helpers.unless.call(depth0 != null ? depth0 : (container.nullContext || {}),(data && data.first),{"name":"unless","hash":{},"fn":container.program(62, data, 0, blockParams, depths),"inverse":container.noop,"data":data})) != null ? stack1 : "") + "\n" + ((stack1 = container.invokePartial(partials.term,depth0,{"name":"term","hash":{"playback":(depths[1] != null ? depths[1].playback : depths[1]),"addable":(depths[1] != null ? depths[1].addable : depths[1]),"merged":(depths[1] != null ? depths[1].merged : depths[1]),"grouped":(depths[1] != null ? depths[1].grouped : depths[1]),"debug":(depths[1] != null ? depths[1].debug : depths[1])},"data":data,"helpers":helpers,"partials":partials,"decorators":container.decorators})) != null ? stack1 : ""); -},"59":function(container,depth0,helpers,partials,data) { +},"62":function(container,depth0,helpers,partials,data) { return "
    "; -},"61":function(container,depth0,helpers,partials,data) { +},"64":function(container,depth0,helpers,partials,data) { return "

    No results found.

    \n"; },"compiler":[7,">= 4.0.0"],"main":function(container,depth0,helpers,partials,data,blockParams,depths) { var stack1; return "\n\n" - + ((stack1 = helpers["if"].call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? depth0.definitions : depth0),{"name":"if","hash":{},"fn":container.program(57, data, 0, blockParams, depths),"inverse":container.program(61, data, 0, blockParams, depths),"data":data})) != null ? stack1 : ""); + + ((stack1 = helpers["if"].call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? depth0.definitions : depth0),{"name":"if","hash":{},"fn":container.program(60, data, 0, blockParams, depths),"inverse":container.program(64, data, 0, blockParams, depths),"data":data})) != null ? stack1 : ""); },"main_d": function(fn, props, container, depth0, data, blockParams, depths) { var decorators = container.decorators; diff --git a/ext/bg/js/translator.js b/ext/bg/js/translator.js index 678bc613..737abd08 100644 --- a/ext/bg/js/translator.js +++ b/ext/bg/js/translator.js @@ -154,6 +154,7 @@ class Translator { for (const definition of deinflection.definitions) { const tags = await this.expandTags(definition.tags, definition.dictionary); tags.push(dictTagBuildSource(definition.dictionary)); + const termTags = await this.expandTags(definition.termTags, definition.dictionary); definitions.push({ source: deinflection.source, @@ -165,6 +166,7 @@ class Translator { reading: definition.reading, glossary: definition.glossary, tags: dictTagsSort(tags), + termTags: dictTagsSort(termTags), sequence: definition.sequence }); } diff --git a/tmpl/terms.html b/tmpl/terms.html index cc0f600e..72bf9824 100644 --- a/tmpl/terms.html +++ b/tmpl/terms.html @@ -80,6 +80,14 @@ {{/if}} + {{#if termTags}} +
    + {{#each termTags}} + {{name}} + {{/each}} +
    + {{/if}} + {{#if frequencies}}
    {{#each frequencies}} From 7783aa4c1a36784b709aba768c17d9476a16a43d Mon Sep 17 00:00:00 2001 From: siikamiika Date: Wed, 11 Oct 2017 19:58:57 +0300 Subject: [PATCH 18/64] reset main dictionary on purge --- ext/bg/js/settings.js | 1 + 1 file changed, 1 insertion(+) diff --git a/ext/bg/js/settings.js b/ext/bg/js/settings.js index 4d248304..cab9c056 100644 --- a/ext/bg/js/settings.js +++ b/ext/bg/js/settings.js @@ -302,6 +302,7 @@ async function onDictionaryPurge(e) { await utilDatabasePurge(); const options = await optionsLoad(); options.dictionaries = {}; + options.dictionary.main = ''; await optionsSave(options); await dictionaryGroupsPopulate(options); From 4e57fa1ad1cd85e18b2ae2c1d43480832533f9a7 Mon Sep 17 00:00:00 2001 From: siikamiika Date: Thu, 12 Oct 2017 01:10:05 +0300 Subject: [PATCH 19/64] merged mode: remove options.dictionary.main --- ext/bg/js/options.js | 4 ---- ext/bg/js/settings.js | 4 ---- ext/bg/js/translator.js | 5 +++-- 3 files changed, 3 insertions(+), 10 deletions(-) diff --git a/ext/bg/js/options.js b/ext/bg/js/options.js index 0aa6d7c6..b49c32da 100644 --- a/ext/bg/js/options.js +++ b/ext/bg/js/options.js @@ -154,10 +154,6 @@ function optionsSetDefaults(options) { dictionaries: {}, - dictionary: { - main: '' - }, - anki: { enable: false, server: 'http://127.0.0.1:8765', diff --git a/ext/bg/js/settings.js b/ext/bg/js/settings.js index cab9c056..6016b38a 100644 --- a/ext/bg/js/settings.js +++ b/ext/bg/js/settings.js @@ -61,9 +61,6 @@ async function formRead() { const priority = parseInt(dictionary.find('.dict-priority').val(), 10); const enabled = dictionary.find('.dict-enabled').prop('checked'); const main = dictionary.find('.dict-main').prop('checked'); - if (main) { - optionsNew.dictionary.main = title; - } optionsNew.dictionaries[title] = {priority, enabled, main}; }); @@ -302,7 +299,6 @@ async function onDictionaryPurge(e) { await utilDatabasePurge(); const options = await optionsLoad(); options.dictionaries = {}; - options.dictionary.main = ''; await optionsSave(options); await dictionaryGroupsPopulate(options); diff --git a/ext/bg/js/translator.js b/ext/bg/js/translator.js index 737abd08..99344b95 100644 --- a/ext/bg/js/translator.js +++ b/ext/bg/js/translator.js @@ -50,10 +50,11 @@ class Translator { async findTermsMerged(text, dictionaries, alphanumeric) { const options = await apiOptionsGet(); + const mainDictionary = Object.keys(options.dictionaries).filter(dict => options.dictionaries[dict].main).concat([''])[0]; const titles = Object.keys(dictionaries); const {length, definitions} = await this.findTerms(text, dictionaries, alphanumeric); - const definitionsBySequence = dictTermsMergeBySequence(definitions, options.dictionary.main); + const definitionsBySequence = dictTermsMergeBySequence(definitions, mainDictionary); const definitionsMerged = []; const mergedByTermIndices = new Set(); @@ -64,7 +65,7 @@ class Translator { const result = definitionsBySequence[sequence]; - const rawDefinitionsBySequence = await this.database.findTermsBySequence(Number(sequence), options.dictionary.main); + const rawDefinitionsBySequence = await this.database.findTermsBySequence(Number(sequence), mainDictionary); const definitionsByGloss = dictTermsMergeByGloss(result, rawDefinitionsBySequence); dictTermsMergeByGloss(result, definitionsBySequence['-1'], definitionsByGloss, mergedByTermIndices); From 6523b77ca13ebbc02cc9a4586a83a9d0ec29807d Mon Sep 17 00:00:00 2001 From: siikamiika Date: Thu, 12 Oct 2017 08:23:28 +0300 Subject: [PATCH 20/64] pos tag color --- ext/mixed/css/display.css | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ext/mixed/css/display.css b/ext/mixed/css/display.css index 3c0539bd..65cfd7ac 100644 --- a/ext/mixed/css/display.css +++ b/ext/mixed/css/display.css @@ -92,6 +92,10 @@ hr { background-color: #5cb85c; } +.tag-pos { + background-color: #565656; +} + .actions .disabled { pointer-events: none; cursor: default; From 8d660e282911ffb5d7b504784a3c09f13b164953 Mon Sep 17 00:00:00 2001 From: siikamiika Date: Thu, 12 Oct 2017 09:59:09 +0300 Subject: [PATCH 21/64] add compact tags --- ext/bg/js/dictionary.js | 26 ++++++++++++++++++++++++++ ext/bg/js/options.js | 3 ++- ext/bg/js/settings.js | 2 ++ ext/bg/js/templates.js | 36 ++++++++++++++++++------------------ ext/bg/js/translator.js | 13 +++++++++++++ ext/bg/settings.html | 4 ++++ tmpl/terms.html | 14 +++++++------- 7 files changed, 72 insertions(+), 26 deletions(-) diff --git a/ext/bg/js/dictionary.js b/ext/bg/js/dictionary.js index ee4f5946..14f90d29 100644 --- a/ext/bg/js/dictionary.js +++ b/ext/bg/js/dictionary.js @@ -110,6 +110,32 @@ function dictTermsUndupe(definitions) { return definitionsUnique; } +function dictTermsCompressTags(definitions) { + let lastDictionary = ''; + let lastPos = ''; + + for (const definition of definitions) { + const dictionary = JSON.stringify(definition.tags.filter(tag => tag.category === 'dictionary').map(tag => tag.name).sort()); + const pos = JSON.stringify(definition.tags.filter(tag => tag.category === 'pos').map(tag => tag.name).sort()); + + const filterOutCategories = []; + + if (lastDictionary === dictionary) { + filterOutCategories.push('dictionary'); + } else { + lastDictionary = dictionary; + } + + if (lastPos === pos) { + filterOutCategories.push('pos'); + } else { + lastPos = pos; + } + + definition.tags = definition.tags.filter(tag => !filterOutCategories.includes(tag.category)); + } +} + function dictTermsGroup(definitions, dictionaries) { const groups = {}; for (const definition of definitions) { diff --git a/ext/bg/js/options.js b/ext/bg/js/options.js index b49c32da..eef893c7 100644 --- a/ext/bg/js/options.js +++ b/ext/bg/js/options.js @@ -139,7 +139,8 @@ function optionsSetDefaults(options) { popupWidth: 400, popupHeight: 250, popupOffset: 10, - showGuide: true + showGuide: true, + compactTags: false }, scanning: { diff --git a/ext/bg/js/settings.js b/ext/bg/js/settings.js index 6016b38a..f59c3ad0 100644 --- a/ext/bg/js/settings.js +++ b/ext/bg/js/settings.js @@ -22,6 +22,7 @@ async function formRead() { const optionsNew = $.extend(true, {}, optionsOld); optionsNew.general.showGuide = $('#show-usage-guide').prop('checked'); + optionsNew.general.compactTags = $('#compact-tags').prop('checked'); optionsNew.general.resultOutputMode = $('#result-output-mode').val(); optionsNew.general.audioSource = $('#audio-playback-source').val(); optionsNew.general.audioVolume = parseFloat($('#audio-playback-volume').val()); @@ -125,6 +126,7 @@ async function onReady() { const options = await optionsLoad(); $('#show-usage-guide').prop('checked', options.general.showGuide); + $('#compact-tags').prop('checked', options.general.compactTags); $('#result-output-mode').val(options.general.resultOutputMode); $('#audio-playback-source').val(options.general.audioSource); $('#audio-playback-volume').val(options.general.audioVolume); diff --git a/ext/bg/js/templates.js b/ext/bg/js/templates.js index 19c49337..e8bd43e9 100644 --- a/ext/bg/js/templates.js +++ b/ext/bg/js/templates.js @@ -206,30 +206,16 @@ templates['model.html'] = template({"1":function(container,depth0,helpers,partia templates['terms.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.only : depth0),{"name":"if","hash":{},"fn":container.program(2, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") - + ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.tags : depth0),{"name":"if","hash":{},"fn":container.program(6, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") + return ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.tags : depth0),{"name":"if","hash":{},"fn":container.program(2, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") + + ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.only : depth0),{"name":"if","hash":{},"fn":container.program(5, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") + ((stack1 = helpers["if"].call(alias1,((stack1 = (depth0 != null ? depth0.glossary : depth0)) != null ? stack1["1"] : stack1),{"name":"if","hash":{},"fn":container.program(9, data, 0),"inverse":container.program(13, data, 0),"data":data})) != null ? stack1 : ""); },"2":function(container,depth0,helpers,partials,data) { var stack1; - return "
    \n (" - + ((stack1 = helpers.each.call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? depth0.only : depth0),{"name":"each","hash":{},"fn":container.program(3, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") - + " only)\n
    \n"; -},"3":function(container,depth0,helpers,partials,data) { - var stack1; - - return ((stack1 = container.lambda(depth0, depth0)) != null ? stack1 : "") - + ((stack1 = helpers.unless.call(depth0 != null ? depth0 : (container.nullContext || {}),(data && data.last),{"name":"unless","hash":{},"fn":container.program(4, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") - + "\n"; -},"4":function(container,depth0,helpers,partials,data) { - return ", "; -},"6":function(container,depth0,helpers,partials,data) { - var stack1; - return "
    \n" - + ((stack1 = helpers.each.call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? depth0.tags : depth0),{"name":"each","hash":{},"fn":container.program(7, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") + + ((stack1 = helpers.each.call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? depth0.tags : depth0),{"name":"each","hash":{},"fn":container.program(3, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") + "
    \n"; -},"7":function(container,depth0,helpers,partials,data) { +},"3":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.name || (depth0 != null ? depth0.name : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"name","hash":{},"data":data}) : helper))) + "\n"; +},"5":function(container,depth0,helpers,partials,data) { + var stack1; + + return "
    \n (" + + ((stack1 = helpers.each.call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? depth0.only : depth0),{"name":"each","hash":{},"fn":container.program(6, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") + + " only)\n
    \n"; +},"6":function(container,depth0,helpers,partials,data) { + var stack1; + + return ((stack1 = container.lambda(depth0, depth0)) != null ? stack1 : "") + + ((stack1 = helpers.unless.call(depth0 != null ? depth0 : (container.nullContext || {}),(data && data.last),{"name":"unless","hash":{},"fn":container.program(7, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") + + "\n"; +},"7":function(container,depth0,helpers,partials,data) { + return ", "; },"9":function(container,depth0,helpers,partials,data) { var stack1; diff --git a/ext/bg/js/translator.js b/ext/bg/js/translator.js index 99344b95..e307efc0 100644 --- a/ext/bg/js/translator.js +++ b/ext/bg/js/translator.js @@ -37,6 +37,7 @@ class Translator { } async findTermsGrouped(text, dictionaries, alphanumeric) { + const options = await apiOptionsGet(); const titles = Object.keys(dictionaries); const {length, definitions} = await this.findTerms(text, dictionaries, alphanumeric); @@ -45,6 +46,12 @@ class Translator { await this.buildTermFrequencies(definition, titles); } + if (options.general.compactTags) { + for (const definition of definitionsGrouped) { + dictTermsCompressTags(definition.definitions); + } + } + return {length, definitions: definitionsGrouped}; } @@ -120,6 +127,12 @@ class Translator { await this.buildTermFrequencies(definition, titles); } + if (options.general.compactTags) { + for (const definition of definitionsMerged) { + dictTermsCompressTags(definition.definitions); + } + } + return {length, definitions: dictTermsSort(definitionsMerged)}; } diff --git a/ext/bg/settings.html b/ext/bg/settings.html index 6274f3cb..d4b71932 100644 --- a/ext/bg/settings.html +++ b/ext/bg/settings.html @@ -35,6 +35,10 @@
    +
    + +
    +
    diff --git a/tmpl/terms.html b/tmpl/terms.html index 72bf9824..e037c544 100644 --- a/tmpl/terms.html +++ b/tmpl/terms.html @@ -1,4 +1,11 @@ {{#*inline "definition"}} +{{#if tags}} +
    + {{#each tags}} + {{name}} + {{/each}} +
    +{{/if}} {{#if only}}
    ( @@ -8,13 +15,6 @@ only)
    {{/if}} -{{#if tags}} -
    - {{#each tags}} - {{name}} - {{/each}} -
    -{{/if}} {{#if glossary.[1]}}
      {{#each glossary}} From c0f56480bb34b8811835b8d545443bd9ea87c997 Mon Sep 17 00:00:00 2001 From: siikamiika Date: Thu, 12 Oct 2017 11:28:32 +0300 Subject: [PATCH 22/64] compact tags: reset PoS on new dictionary --- ext/bg/js/dictionary.js | 1 + 1 file changed, 1 insertion(+) diff --git a/ext/bg/js/dictionary.js b/ext/bg/js/dictionary.js index 14f90d29..d057ae83 100644 --- a/ext/bg/js/dictionary.js +++ b/ext/bg/js/dictionary.js @@ -124,6 +124,7 @@ function dictTermsCompressTags(definitions) { filterOutCategories.push('dictionary'); } else { lastDictionary = dictionary; + lastPos = ''; } if (lastPos === pos) { From 7ec28bea5422cda4304b660eccdb39d690f74fad Mon Sep 17 00:00:00 2001 From: siikamiika Date: Fri, 13 Oct 2017 02:40:20 +0300 Subject: [PATCH 23/64] change db format, rename tags to definitionTags --- ext/bg/js/database.js | 19 +++++++++---------- ext/bg/js/dictionary.js | 14 +++++++------- ext/bg/js/templates.js | 4 ++-- ext/bg/js/translator.js | 10 +++++----- tmpl/terms.html | 4 ++-- 5 files changed, 25 insertions(+), 26 deletions(-) diff --git a/ext/bg/js/database.js b/ext/bg/js/database.js index 1c2194df..8350e214 100644 --- a/ext/bg/js/database.js +++ b/ext/bg/js/database.js @@ -68,12 +68,11 @@ class Database { const results = []; await this.db.terms.where('expression').equals(term).or('reading').equals(term).each(row => { if (titles.includes(row.dictionary)) { - const tags = row.tags.split('\t'); results.push({ expression: row.expression, reading: row.reading, - tags: dictFieldSplit(tags[0]), - termTags: tags.length > 1 ? dictFieldSplit(tags[1]) : [], + definitionTags: dictFieldSplit(row.definitionTags), + termTags: dictFieldSplit(row.termTags || ''), rules: dictFieldSplit(row.rules), glossary: row.glossary, score: row.score, @@ -95,12 +94,11 @@ class Database { const results = []; await this.db.terms.where('sequence').equals(sequence).each(row => { if (row.dictionary === mainDictionary) { - const tags = row.tags.split('\t'); results.push({ expression: row.expression, reading: row.reading, - tags: dictFieldSplit(tags[0]), - termTags: tags.length > 1 ? dictFieldSplit(tags[1]) : [], + definitionTags: dictFieldSplit(row.definitionTags), + termTags: dictFieldSplit(row.termTags || ''), rules: dictFieldSplit(row.rules), glossary: row.glossary, score: row.score, @@ -229,11 +227,11 @@ class Database { const rows = []; if (summary.version === 1) { - for (const [expression, reading, tags, rules, score, ...glossary] of entries) { + for (const [expression, reading, definitionTags, rules, score, ...glossary] of entries) { rows.push({ expression, reading, - tags, + definitionTags, rules, score, glossary, @@ -241,15 +239,16 @@ class Database { }); } } else { - for (const [expression, reading, tags, rules, score, glossary, sequence] of entries) { + for (const [expression, reading, definitionTags, rules, score, glossary, sequence, termTags] of entries) { rows.push({ expression, reading, - tags, + definitionTags, rules, score, glossary, sequence, + termTags, dictionary: summary.title }); } diff --git a/ext/bg/js/dictionary.js b/ext/bg/js/dictionary.js index d057ae83..816e96c4 100644 --- a/ext/bg/js/dictionary.js +++ b/ext/bg/js/dictionary.js @@ -115,8 +115,8 @@ function dictTermsCompressTags(definitions) { let lastPos = ''; for (const definition of definitions) { - const dictionary = JSON.stringify(definition.tags.filter(tag => tag.category === 'dictionary').map(tag => tag.name).sort()); - const pos = JSON.stringify(definition.tags.filter(tag => tag.category === 'pos').map(tag => tag.name).sort()); + const dictionary = JSON.stringify(definition.definitionTags.filter(tag => tag.category === 'dictionary').map(tag => tag.name).sort()); + const pos = JSON.stringify(definition.definitionTags.filter(tag => tag.category === 'pos').map(tag => tag.name).sort()); const filterOutCategories = []; @@ -133,7 +133,7 @@ function dictTermsCompressTags(definitions) { lastPos = pos; } - definition.tags = definition.tags.filter(tag => !filterOutCategories.includes(tag.category)); + definition.definitionTags = definition.definitionTags.filter(tag => !filterOutCategories.includes(tag.category)); } } @@ -229,7 +229,7 @@ function dictTermsMergeByGloss(result, definitions, appendTo, mergedIndices) { definitionsByGloss[gloss] = { expression: new Set(), reading: new Set(), - tags: new Set(), + definitionTags: new Set(), glossary: definition.glossary, source: result.source, reasons: [], @@ -253,11 +253,11 @@ function dictTermsMergeByGloss(result, definitions, appendTo, mergedIndices) { result.expressions.get(definition.expression).set(definition.reading, new Set()); } - for (const tag of definition.tags) { + for (const tag of definition.definitionTags) { if (typeof tag === 'string') { - definitionsByGloss[gloss].tags.add(tag); + definitionsByGloss[gloss].definitionTags.add(tag); } else if (tag.category && tag.category !== 'dictionary') { - definitionsByGloss[gloss].tags.add(tag.name); + definitionsByGloss[gloss].definitionTags.add(tag.name); } } diff --git a/ext/bg/js/templates.js b/ext/bg/js/templates.js index e8bd43e9..b7b4721e 100644 --- a/ext/bg/js/templates.js +++ b/ext/bg/js/templates.js @@ -206,14 +206,14 @@ templates['model.html'] = template({"1":function(container,depth0,helpers,partia templates['terms.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.tags : depth0),{"name":"if","hash":{},"fn":container.program(2, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") + return ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.definitionTags : depth0),{"name":"if","hash":{},"fn":container.program(2, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") + ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.only : depth0),{"name":"if","hash":{},"fn":container.program(5, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") + ((stack1 = helpers["if"].call(alias1,((stack1 = (depth0 != null ? depth0.glossary : depth0)) != null ? stack1["1"] : stack1),{"name":"if","hash":{},"fn":container.program(9, data, 0),"inverse":container.program(13, data, 0),"data":data})) != null ? stack1 : ""); },"2":function(container,depth0,helpers,partials,data) { var stack1; return "
      \n" - + ((stack1 = helpers.each.call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? depth0.tags : depth0),{"name":"each","hash":{},"fn":container.program(3, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") + + ((stack1 = helpers.each.call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? depth0.definitionTags : depth0),{"name":"each","hash":{},"fn":container.program(3, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") + "
      \n"; },"3":function(container,depth0,helpers,partials,data) { var helper, alias1=depth0 != null ? depth0 : (container.nullContext || {}), alias2=helpers.helperMissing, alias3="function", alias4=container.escapeExpression; diff --git a/ext/bg/js/translator.js b/ext/bg/js/translator.js index e307efc0..c102f6a8 100644 --- a/ext/bg/js/translator.js +++ b/ext/bg/js/translator.js @@ -79,9 +79,9 @@ class Translator { for (const gloss in definitionsByGloss) { const definition = definitionsByGloss[gloss]; - const tags = await this.expandTags(definition.tags, definition.dictionary); + const tags = await this.expandTags(definition.definitionTags, definition.dictionary); tags.push(dictTagBuildSource(definition.dictionary)); - definition.tags = dictTagsSort(tags); + definition.definitionTags = dictTagsSort(tags); result.definitions.push(definition); } @@ -166,8 +166,8 @@ class Translator { let definitions = []; for (const deinflection of deinflections) { for (const definition of deinflection.definitions) { - const tags = await this.expandTags(definition.tags, definition.dictionary); - tags.push(dictTagBuildSource(definition.dictionary)); + const definitionTags = await this.expandTags(definition.definitionTags, definition.dictionary); + definitionTags.push(dictTagBuildSource(definition.dictionary)); const termTags = await this.expandTags(definition.termTags, definition.dictionary); definitions.push({ @@ -179,7 +179,7 @@ class Translator { expression: definition.expression, reading: definition.reading, glossary: definition.glossary, - tags: dictTagsSort(tags), + definitionTags: dictTagsSort(definitionTags), termTags: dictTagsSort(termTags), sequence: definition.sequence }); diff --git a/tmpl/terms.html b/tmpl/terms.html index e037c544..f35caed4 100644 --- a/tmpl/terms.html +++ b/tmpl/terms.html @@ -1,7 +1,7 @@ {{#*inline "definition"}} -{{#if tags}} +{{#if definitionTags}}
      - {{#each tags}} + {{#each definitionTags}} {{name}} {{/each}}
      From 4203fda906a1b4a104187e54d256e5952d8ae55c Mon Sep 17 00:00:00 2001 From: siikamiika Date: Fri, 13 Oct 2017 03:14:06 +0300 Subject: [PATCH 24/64] rename pos to partOfSpeech --- ext/bg/js/dictionary.js | 12 ++++++------ ext/mixed/css/display.css | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/ext/bg/js/dictionary.js b/ext/bg/js/dictionary.js index 816e96c4..843d05f1 100644 --- a/ext/bg/js/dictionary.js +++ b/ext/bg/js/dictionary.js @@ -112,11 +112,11 @@ function dictTermsUndupe(definitions) { function dictTermsCompressTags(definitions) { let lastDictionary = ''; - let lastPos = ''; + let lastPartOfSpeech = ''; for (const definition of definitions) { const dictionary = JSON.stringify(definition.definitionTags.filter(tag => tag.category === 'dictionary').map(tag => tag.name).sort()); - const pos = JSON.stringify(definition.definitionTags.filter(tag => tag.category === 'pos').map(tag => tag.name).sort()); + const partOfSpeech = JSON.stringify(definition.definitionTags.filter(tag => tag.category === 'partOfSpeech').map(tag => tag.name).sort()); const filterOutCategories = []; @@ -124,13 +124,13 @@ function dictTermsCompressTags(definitions) { filterOutCategories.push('dictionary'); } else { lastDictionary = dictionary; - lastPos = ''; + lastPartOfSpeech = ''; } - if (lastPos === pos) { - filterOutCategories.push('pos'); + if (lastPartOfSpeech === partOfSpeech) { + filterOutCategories.push('partOfSpeech'); } else { - lastPos = pos; + lastPartOfSpeech = partOfSpeech; } definition.definitionTags = definition.definitionTags.filter(tag => !filterOutCategories.includes(tag.category)); diff --git a/ext/mixed/css/display.css b/ext/mixed/css/display.css index 65cfd7ac..670930ae 100644 --- a/ext/mixed/css/display.css +++ b/ext/mixed/css/display.css @@ -92,7 +92,7 @@ hr { background-color: #5cb85c; } -.tag-pos { +.tag-partOfSpeech { background-color: #565656; } From 5502bf8aed8b9b4158cfe02ea5b042b03ef2f5cf Mon Sep 17 00:00:00 2001 From: Roderic Day Date: Fri, 13 Oct 2017 15:05:51 -0400 Subject: [PATCH 25/64] Place `nodeType` checks inside `caretRangeFromPoint` function Checked that it does not un-fix #80 Squelches alerts (but does not fix underlying issue) for #89 --- ext/fg/js/document.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ext/fg/js/document.js b/ext/fg/js/document.js index a1806d77..821a279f 100644 --- a/ext/fg/js/document.js +++ b/ext/fg/js/document.js @@ -76,7 +76,7 @@ function docRangeFromPoint(point) { if (!document.caretRangeFromPoint) { document.caretRangeFromPoint = (x, y) => { const position = document.caretPositionFromPoint(x,y); - if (position && position.offsetNode) { + if (position && position.offsetNode && position.offsetNode.nodeType === Node.TEXT_NODE) { const range = document.createRange(); range.setStart(position.offsetNode, position.offset); range.setEnd(position.offsetNode, position.offset); @@ -86,7 +86,7 @@ function docRangeFromPoint(point) { } const range = document.caretRangeFromPoint(point.x, point.y); - if (range && range.startContainer.nodeType === 3 && range.endContainer.nodeType === 3) { + if (range) { return new TextSourceRange(range); } } From 03f7ca23e118c5ca804eef35cea05070e69779c7 Mon Sep 17 00:00:00 2001 From: siikamiika Date: Sun, 15 Oct 2017 05:19:16 +0300 Subject: [PATCH 26/64] merged mode: add secondary searches --- ext/bg/js/database.js | 26 ++++++++++++++++++++++++++ ext/bg/js/settings.js | 12 +++++++----- ext/bg/js/templates.js | 4 +++- ext/bg/js/translator.js | 20 ++++++++++++++++++-- tmpl/dictionary.html | 5 +++++ 5 files changed, 59 insertions(+), 8 deletions(-) diff --git a/ext/bg/js/database.js b/ext/bg/js/database.js index 8350e214..dea78196 100644 --- a/ext/bg/js/database.js +++ b/ext/bg/js/database.js @@ -86,6 +86,32 @@ class Database { return results; } + async findTermsExact(term, reading, titles) { + if (!this.db) { + throw 'Database not initialized'; + } + + const results = []; + await this.db.terms.where('expression').equals(term).each(row => { + if (row.reading === reading && titles.includes(row.dictionary)) { + results.push({ + expression: row.expression, + reading: row.reading, + definitionTags: dictFieldSplit(row.definitionTags), + termTags: dictFieldSplit(row.termTags || ''), + rules: dictFieldSplit(row.rules), + glossary: row.glossary, + score: row.score, + dictionary: row.dictionary, + id: row.id, + sequence: typeof row.sequence === 'undefined' ? -1 : row.sequence + }); + } + }); + + return results; + } + async findTermsBySequence(sequence, mainDictionary) { if (!this.db) { throw 'Database not initialized'; diff --git a/ext/bg/js/settings.js b/ext/bg/js/settings.js index f59c3ad0..b9c59a4a 100644 --- a/ext/bg/js/settings.js +++ b/ext/bg/js/settings.js @@ -62,7 +62,8 @@ async function formRead() { const priority = parseInt(dictionary.find('.dict-priority').val(), 10); const enabled = dictionary.find('.dict-enabled').prop('checked'); const main = dictionary.find('.dict-main').prop('checked'); - optionsNew.dictionaries[title] = {priority, enabled, main}; + const allowSecondarySearches = dictionary.find('.dict-allow-secondary-searches').prop('checked'); + optionsNew.dictionaries[title] = {priority, enabled, main, allowSecondarySearches}; }); return {optionsNew, optionsOld}; @@ -262,14 +263,15 @@ async function dictionaryGroupsPopulate(options) { } for (const dictRow of dictRowsSort(dictRows, options)) { - const dictOptions = options.dictionaries[dictRow.title] || {enabled: false, priority: 0, main: false}; + const dictOptions = options.dictionaries[dictRow.title] || {enabled: false, priority: 0, main: false, allowSecondarySearches: false}; const dictHtml = await apiTemplateRender('dictionary.html', { title: dictRow.title, version: dictRow.version, revision: dictRow.revision, priority: dictOptions.priority, enabled: dictOptions.enabled, - main: dictOptions.main + main: dictOptions.main, + allowSecondarySearches: dictOptions.allowSecondarySearches }); dictGroups.append($(dictHtml)); @@ -277,7 +279,7 @@ async function dictionaryGroupsPopulate(options) { formUpdateVisibility(options); - $('.dict-enabled, .dict-priority').change(e => { + $('.dict-enabled, .dict-priority, .dict-allow-secondary-searches').change(e => { dictionaryGroupsSort(); onFormOptionsChanged(e); }); @@ -329,7 +331,7 @@ async function onDictionaryImport(e) { const options = await optionsLoad(); const summary = await utilDatabaseImport(e.target.files[0], updateProgress); - options.dictionaries[summary.title] = {enabled: true, priority: 0, main: false}; + options.dictionaries[summary.title] = {enabled: true, priority: 0, main: false, allowSecondarySearches: false}; await optionsSave(options); await dictionaryGroupsPopulate(options); diff --git a/ext/bg/js/templates.js b/ext/bg/js/templates.js index b7b4721e..2e13053b 100644 --- a/ext/bg/js/templates.js +++ b/ext/bg/js/templates.js @@ -13,7 +13,9 @@ templates['dictionary.html'] = template({"1":function(container,depth0,helpers,p + alias4(((helper = (helper = helpers.revision || (depth0 != null ? depth0.revision : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"revision","hash":{},"data":data}) : helper))) + "\n\n
      \n \n \n
      \n
      \n \n
      \n
      \n \n
      \n
      \n
    \n"; },"12":function(container,depth0,helpers,partials,data) { - return "class=\"compact\""; + return "class=\"compact-glossary\""; },"14":function(container,depth0,helpers,partials,data) { var stack1, helper, options, buffer = "
  • "; @@ -274,7 +274,7 @@ templates['terms.html'] = template({"1":function(container,depth0,helpers,partia if (stack1 != null) { buffer += stack1; } return buffer + "\n"; },"18":function(container,depth0,helpers,partials,data) { - return "compact"; + return "compact-glossary"; },"20":function(container,depth0,helpers,partials,data) { var stack1; diff --git a/ext/mixed/css/display.css b/ext/mixed/css/display.css index b31774f9..eadb9dae 100644 --- a/ext/mixed/css/display.css +++ b/ext/mixed/css/display.css @@ -177,21 +177,25 @@ hr { display: inline-block; } +.compact-info { + display: inline-block; +} + .glossary ol, .glossary ul { padding-left: 1.4em; } -.glossary ul.compact { +.glossary ul.compact-glossary { display: inline; list-style: none; padding-left: 0px; } -.glossary .compact li { +.glossary .compact-glossary li { display: inline; } -.glossary .compact li:not(:first-child):before { +.glossary .compact-glossary li:not(:first-child):before { content: " | "; } @@ -203,7 +207,7 @@ hr { color: #000; } -div.glossary-item.compact { +div.glossary-item.compact-glossary { display: inline; } diff --git a/tmpl/terms.html b/tmpl/terms.html index b5b1325d..09441e72 100644 --- a/tmpl/terms.html +++ b/tmpl/terms.html @@ -1,13 +1,13 @@ {{#*inline "definition"}} {{#if definitionTags}} -
    +
    {{#each definitionTags}} {{name}} {{/each}}
    {{/if}} {{#if only}} -
    +
    ( {{~#each only~}} {{{.}}}{{#unless @last}}, {{/unless}} @@ -16,13 +16,13 @@
    {{/if}} {{#if glossary.[1]}} -
      +
        {{#each glossary}}
      • {{#multiLine}}{{.}}{{/multiLine}}
      • {{/each}}
      {{else}} -
      {{#multiLine}}{{glossary.[0]}}{{/multiLine}}
      +
      {{#multiLine}}{{glossary.[0]}}{{/multiLine}}
      {{/if}} {{/inline}} From f828043838b52f8304f1a4b226b904d68f19b643 Mon Sep 17 00:00:00 2001 From: siikamiika Date: Tue, 24 Oct 2017 23:50:33 +0300 Subject: [PATCH 53/64] terms.html: fix whitespace issues in merged mode --- ext/bg/js/templates.js | 16 ++++++++-------- tmpl/terms.html | 20 ++++++++++---------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/ext/bg/js/templates.js b/ext/bg/js/templates.js index a0b518b2..6f9c39ec 100644 --- a/ext/bg/js/templates.js +++ b/ext/bg/js/templates.js @@ -310,7 +310,7 @@ templates['terms.html'] = template({"1":function(container,depth0,helpers,partia return ((stack1 = helpers.each.call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? depth0.expressions : depth0),{"name":"each","hash":{},"fn":container.program(29, data, 0, blockParams, depths),"inverse":container.noop,"data":data})) != null ? stack1 : ""); },"29":function(container,depth0,helpers,partials,data,blockParams,depths) { var stack1, helper, options, alias1=depth0 != null ? depth0 : (container.nullContext || {}), alias2=helpers.helperMissing, alias3="function", buffer = - "
      \n "; stack1 = ((helper = (helper = helpers.kanjiLinks || (depth0 != null ? depth0.kanjiLinks : depth0)) != null ? helper : alias2),(options={"name":"kanjiLinks","hash":{},"fn":container.program(30, data, 0, blockParams, depths),"inverse":container.noop,"data":data}),(typeof helper === alias3 ? helper.call(alias1,options) : helper)); @@ -320,9 +320,9 @@ templates['terms.html'] = template({"1":function(container,depth0,helpers,partia + ((stack1 = helpers["if"].call(alias1,(depths[1] != null ? depths[1].playback : depths[1]),{"name":"if","hash":{},"fn":container.program(33, data, 0, blockParams, depths),"inverse":container.noop,"data":data})) != null ? stack1 : "") + ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.termTags : depth0),{"name":"if","hash":{},"fn":container.program(35, data, 0, blockParams, depths),"inverse":container.noop,"data":data})) != null ? stack1 : "") + ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.frequencies : depth0),{"name":"if","hash":{},"fn":container.program(38, data, 0, blockParams, depths),"inverse":container.noop,"data":data})) != null ? stack1 : "") - + "
    \n"; + + "\">、
    "; },"30":function(container,depth0,helpers,partials,data) { var stack1, helper, options; @@ -335,13 +335,13 @@ templates['terms.html'] = template({"1":function(container,depth0,helpers,partia return ((stack1 = container.lambda(depth0, depth0)) != null ? stack1 : ""); },"33":function(container,depth0,helpers,partials,data) { - return "\n"; + return ""; },"35":function(container,depth0,helpers,partials,data) { var stack1; return "
    " + ((stack1 = helpers.each.call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? depth0.termTags : depth0),{"name":"each","hash":{},"fn":container.program(36, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") - + "
    \n"; + + ""; },"36":function(container,depth0,helpers,partials,data) { var helper, alias1=depth0 != null ? depth0 : (container.nullContext || {}), alias2=helpers.helperMissing, alias3="function", alias4=container.escapeExpression; @@ -351,13 +351,13 @@ templates['terms.html'] = template({"1":function(container,depth0,helpers,partia + alias4(((helper = (helper = helpers.notes || (depth0 != null ? depth0.notes : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"notes","hash":{},"data":data}) : helper))) + "\">" + alias4(((helper = (helper = helpers.name || (depth0 != null ? depth0.name : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"name","hash":{},"data":data}) : helper))) - + "
    \n"; + + ""; },"38":function(container,depth0,helpers,partials,data) { var stack1; return "
    " + ((stack1 = helpers.each.call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? depth0.frequencies : depth0),{"name":"each","hash":{},"fn":container.program(39, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") - + "
    \n "; + + ""; },"39":function(container,depth0,helpers,partials,data) { var helper, alias1=depth0 != null ? depth0 : (container.nullContext || {}), alias2=helpers.helperMissing, alias3="function", alias4=container.escapeExpression; @@ -365,7 +365,7 @@ templates['terms.html'] = template({"1":function(container,depth0,helpers,partia + alias4(((helper = (helper = helpers.dictionary || (depth0 != null ? depth0.dictionary : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"dictionary","hash":{},"data":data}) : helper))) + ":" + alias4(((helper = (helper = helpers.frequency || (depth0 != null ? depth0.frequency : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"frequency","hash":{},"data":data}) : helper))) - + "\n"; + + ""; },"41":function(container,depth0,helpers,partials,data) { return "invisible"; },"43":function(container,depth0,helpers,partials,data) { diff --git a/tmpl/terms.html b/tmpl/terms.html index 09441e72..eb114b5f 100644 --- a/tmpl/terms.html +++ b/tmpl/terms.html @@ -43,31 +43,31 @@ {{#if merged}} - {{#each expressions}} -
    - {{#kanjiLinks}}{{#furigana}}{{{.}}}{{/furigana}}{{/kanjiLinks}}{{#kanjiLinks}}{{#furigana}}{{{.}}}{{/furigana}}{{/kanjiLinks}}
    {{~#if ../playback~}} - {{/if}} + {{~/if~}} {{~#if termTags~}}
    {{~#each termTags~}} {{name}} - {{/each}} + {{~/each~}}
    - {{/if}} + {{~/if~}} {{~#if frequencies~}}
    {{~#each frequencies~}} {{dictionary}}:{{frequency}} - {{/each}} + {{~/each~}}
    - {{/if}}
    - {{/each}} + {{~/each~}} {{else}}
    {{#kanjiLinks}}{{#furigana}}{{{.}}}{{/furigana}}{{/kanjiLinks}}
    {{#if termTags}} From ee80fa5331d594907c9fce382dcc981d2cf8682f Mon Sep 17 00:00:00 2001 From: siikamiika Date: Wed, 25 Oct 2017 00:58:11 +0300 Subject: [PATCH 54/64] merged mode: restore whitespace between termTags --- ext/bg/js/templates.js | 4 ++-- tmpl/terms.html | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ext/bg/js/templates.js b/ext/bg/js/templates.js index 6f9c39ec..236e7583 100644 --- a/ext/bg/js/templates.js +++ b/ext/bg/js/templates.js @@ -345,13 +345,13 @@ templates['terms.html'] = template({"1":function(container,depth0,helpers,partia },"36":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.name || (depth0 != null ? depth0.name : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"name","hash":{},"data":data}) : helper))) - + ""; + + "\n"; },"38":function(container,depth0,helpers,partials,data) { var stack1; diff --git a/tmpl/terms.html b/tmpl/terms.html index eb114b5f..a9b260c1 100644 --- a/tmpl/terms.html +++ b/tmpl/terms.html @@ -52,9 +52,9 @@ {{~/if~}} {{~#if termTags~}}
    - {{~#each termTags~}} + {{~#each termTags}} {{name}} - {{~/each~}} + {{/each~}}
    {{~/if~}} {{~#if frequencies~}} From de28190f5a1a80665ac95ef561148e684eae8ae1 Mon Sep 17 00:00:00 2001 From: siikamiika Date: Thu, 26 Oct 2017 10:18:28 +0300 Subject: [PATCH 55/64] merged mode: restore whitespace between frequencies --- ext/bg/js/templates.js | 4 ++-- tmpl/terms.html | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ext/bg/js/templates.js b/ext/bg/js/templates.js index 236e7583..f3f680d5 100644 --- a/ext/bg/js/templates.js +++ b/ext/bg/js/templates.js @@ -361,11 +361,11 @@ templates['terms.html'] = template({"1":function(container,depth0,helpers,partia },"39":function(container,depth0,helpers,partials,data) { var helper, alias1=depth0 != null ? depth0 : (container.nullContext || {}), alias2=helpers.helperMissing, alias3="function", alias4=container.escapeExpression; - return "" + return " " + alias4(((helper = (helper = helpers.dictionary || (depth0 != null ? depth0.dictionary : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"dictionary","hash":{},"data":data}) : helper))) + ":" + alias4(((helper = (helper = helpers.frequency || (depth0 != null ? depth0.frequency : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"frequency","hash":{},"data":data}) : helper))) - + ""; + + "\n"; },"41":function(container,depth0,helpers,partials,data) { return "invisible"; },"43":function(container,depth0,helpers,partials,data) { diff --git a/tmpl/terms.html b/tmpl/terms.html index a9b260c1..245a0ea1 100644 --- a/tmpl/terms.html +++ b/tmpl/terms.html @@ -59,9 +59,9 @@ {{~/if~}} {{~#if frequencies~}}
    - {{~#each frequencies~}} + {{~#each frequencies}} {{dictionary}}:{{frequency}} - {{~/each~}} + {{/each~}}
    {{~/if~}} {{#kanjiLinks}}{{#furigana}}{{{.}}}{{/furigana}}{{/kanjiLinks}}
    +
    + {{#kanjiLinks}}{{#furigana}}{{{.}}}{{/furigana}}{{/kanjiLinks}} +
    {{~#if ../playback~}} {{~/if~}} @@ -64,9 +64,9 @@ {{/each~}}
    {{~/if~}} -
    + + + {{~/each~}} {{else}}
    {{#kanjiLinks}}{{#furigana}}{{{.}}}{{/furigana}}{{/kanjiLinks}}
    From 7d29e5b533a4607d1580cb6982de3870605805af Mon Sep 17 00:00:00 2001 From: Alex Yatskov Date: Sun, 29 Oct 2017 10:18:15 -0700 Subject: [PATCH 59/64] cleanup of settings page --- ext/bg/js/settings.js | 58 ++++++++++++++++++------------------------- ext/bg/settings.html | 17 +++++++------ 2 files changed, 34 insertions(+), 41 deletions(-) diff --git a/ext/bg/js/settings.js b/ext/bg/js/settings.js index 7a9ba4f9..d608a81b 100644 --- a/ext/bg/js/settings.js +++ b/ext/bg/js/settings.js @@ -25,7 +25,6 @@ async function formRead() { optionsNew.general.compactTags = $('#compact-tags').prop('checked'); optionsNew.general.compactGlossaries = $('#compact-glossaries').prop('checked'); optionsNew.general.resultOutputMode = $('#result-output-mode').val(); - optionsNew.general.mainDictionary = $('#main-dictionary').val(); optionsNew.general.audioSource = $('#audio-playback-source').val(); optionsNew.general.audioVolume = parseFloat($('#audio-playback-volume').val()); optionsNew.general.debugInfo = $('#show-debug-info').prop('checked'); @@ -58,6 +57,7 @@ async function formRead() { optionsNew.anki.kanji.fields = ankiFieldsToDict($('#kanji .anki-field-value')); } + optionsNew.general.mainDictionary = $('#dict-main').val(); $('.dict-group').each((index, element) => { const dictionary = $(element); const title = dictionary.data('title'); @@ -85,11 +85,11 @@ function formUpdateVisibility(options) { advanced.hide(); } - const merge = $('.options-merge'); + const mainGroup = $('#dict-main-group'); if (options.general.resultOutputMode === 'merge') { - merge.show(); + mainGroup.show(); } else { - merge.hide(); + mainGroup.hide(); } const debug = $('#debug'); @@ -105,40 +105,32 @@ function formUpdateVisibility(options) { } async function formMainDictionaryOptionsPopulate(options) { - const select = $('#main-dictionary').empty(); + const select = $('#dict-main').empty(); + select.append($('')); - let titles = await utilDatabaseGetTitlesWithSequences(); - titles = titles.filter(title => options.dictionaries[title].enabled); - const formOptionsHtml = []; - let mainDictionarySelected = false; + let mainDictionary = ''; + const formOptions = [$]; + const titles = await utilDatabaseGetTitlesWithSequences(); for (const title of titles) { - if (options.general.mainDictionary === title) { - mainDictionarySelected = true; + select.append($(``)); + if (title === options.general.mainDictionary) { + mainDictionary = title; } - formOptionsHtml.push(``); } - if (!mainDictionarySelected) { - options.general.mainDictionary = ''; - } - - const notSelectedOptionHtml = ``; - - select.append($([notSelectedOptionHtml].concat(formOptionsHtml).join(''))); + select.val(mainDictionary); } async function onFormOptionsChanged(e) { + if (!e.originalEvent && !e.isTrigger) { + return; + } + + const {optionsNew, optionsOld} = await formRead(); + await optionsSave(optionsNew); + formUpdateVisibility(optionsNew); + try { - if (!e.originalEvent && !e.isTrigger) { - return; - } - - const {optionsNew, optionsOld} = await formRead(); - await formMainDictionaryOptionsPopulate(optionsNew); - await optionsSave(optionsNew); - - formUpdateVisibility(optionsNew); - const ankiUpdated = optionsNew.anki.enable !== optionsOld.anki.enable || optionsNew.anki.server !== optionsOld.anki.server; @@ -162,7 +154,6 @@ async function onReady() { $('#compact-tags').prop('checked', options.general.compactTags); $('#compact-glossaries').prop('checked', options.general.compactGlossaries); $('#result-output-mode').val(options.general.resultOutputMode); - $('#main-dictionary').val(options.general.mainDictionary); $('#audio-playback-source').val(options.general.audioSource); $('#audio-playback-volume').val(options.general.audioVolume); $('#show-debug-info').prop('checked', options.general.debugInfo); @@ -194,6 +185,7 @@ async function onReady() { try { await dictionaryGroupsPopulate(options); + await formMainDictionaryOptionsPopulate(options); } catch (e) { dictionaryErrorShow(e); } @@ -204,8 +196,6 @@ async function onReady() { ankiErrorShow(e); } - await formMainDictionaryOptionsPopulate(options); - formUpdateVisibility(options); } @@ -311,7 +301,7 @@ async function dictionaryGroupsPopulate(options) { async function onDictionaryPurge(e) { e.preventDefault(); - const dictControls = $('#dict-importer, #dict-groups').hide(); + const dictControls = $('#dict-importer, #dict-groups, #dict-main-group').hide(); const dictProgress = $('#dict-purge').show(); try { @@ -352,7 +342,7 @@ async function onDictionaryImport(e) { const options = await optionsLoad(); const summary = await utilDatabaseImport(e.target.files[0], updateProgress); options.dictionaries[summary.title] = {enabled: true, priority: 0, allowSecondarySearches: false}; - if (summary.hasSequences && !options.general.mainDictionary) { + if (summary.hasSequences && options.general.mainDictionary === '') { options.general.mainDictionary = summary.title; } await optionsSave(options); diff --git a/ext/bg/settings.html b/ext/bg/settings.html index 12556065..1565ed52 100644 --- a/ext/bg/settings.html +++ b/ext/bg/settings.html @@ -145,21 +145,20 @@ or you can simply purge the database to delete everything.

    - Please visit the Yomichan homepage to download free - dictionaries that you can use with this extension. + Deleting individual dictionaries is not currently feasible due to limitations of browser database technology.

    +
    + + +
    +
    Dictionary data is being purged, please be patient...
    No dictionaries have been installed
    -
    - - -
    -
    Dictionary data is being imported, please be patient...
    @@ -168,6 +167,10 @@
    +

    + Select a dictionary to import for use below. Please visit the Yomichan + homepage to download free dictionaries to use with this extension and to learn about importing proprietary EPWING dictionaries. +

    From c62cc01642b29c13a38f3bcc08f2fa144107c158 Mon Sep 17 00:00:00 2001 From: Alex Yatskov Date: Sun, 29 Oct 2017 10:42:39 -0700 Subject: [PATCH 60/64] simplify database interface --- ext/bg/js/database.js | 17 +---------------- ext/bg/js/settings.js | 14 +++++++------- ext/bg/js/util.js | 12 ++++-------- 3 files changed, 12 insertions(+), 31 deletions(-) diff --git a/ext/bg/js/database.js b/ext/bg/js/database.js index fcf8ef3f..14b3243a 100644 --- a/ext/bg/js/database.js +++ b/ext/bg/js/database.js @@ -220,7 +220,7 @@ class Database { return result; } - async getTitles() { + async summarize() { if (this.db) { return this.db.dictionaries.toArray(); } else { @@ -228,21 +228,6 @@ class Database { } } - async getTitlesWithSequences() { - if (!this.db) { - throw 'Database not initialized'; - } - - const titles = []; - await this.db.dictionaries.each(row => { - if (row.hasSequences) { - titles.push(row.title); - } - }); - - return titles; - } - async importDictionary(archive, callback) { if (!this.db) { throw 'Database not initialized'; diff --git a/ext/bg/js/settings.js b/ext/bg/js/settings.js index d608a81b..9d47f33c 100644 --- a/ext/bg/js/settings.js +++ b/ext/bg/js/settings.js @@ -109,12 +109,12 @@ async function formMainDictionaryOptionsPopulate(options) { select.append($('')); let mainDictionary = ''; - const formOptions = [$]; - const titles = await utilDatabaseGetTitlesWithSequences(); - for (const title of titles) { - select.append($(``)); - if (title === options.general.mainDictionary) { - mainDictionary = title; + for (const dictRow of await utilDatabaseSummarize()) { + if (dictRow.hasSequences) { + select.append($(``)); + if (dictRow.title === options.general.mainDictionary) { + mainDictionary = dictRow.title; + } } } @@ -271,7 +271,7 @@ async function dictionaryGroupsPopulate(options) { const dictGroups = $('#dict-groups').empty(); const dictWarning = $('#dict-warning').hide(); - const dictRows = await utilDatabaseGetTitles(); + const dictRows = await utilDatabaseSummarize(); if (dictRows.length === 0) { dictWarning.show(); } diff --git a/ext/bg/js/util.js b/ext/bg/js/util.js index 091137ed..216cef3f 100644 --- a/ext/bg/js/util.js +++ b/ext/bg/js/util.js @@ -75,18 +75,14 @@ function utilAnkiGetDeckNames() { return utilBackend().anki.getDeckNames(); } +function utilDatabaseSummarize() { + return utilBackend().translator.database.summarize(); +} + function utilAnkiGetModelFieldNames(modelName) { return utilBackend().anki.getModelFieldNames(modelName); } -function utilDatabaseGetTitles() { - return utilBackend().translator.database.getTitles(); -} - -function utilDatabaseGetTitlesWithSequences() { - return utilBackend().translator.database.getTitlesWithSequences(); -} - function utilDatabasePurge() { return utilBackend().translator.database.purge(); } From d6603fd03155939ba98e8e74f98d1c5ce7ca9b0f Mon Sep 17 00:00:00 2001 From: Alex Yatskov Date: Sun, 29 Oct 2017 10:59:50 -0700 Subject: [PATCH 61/64] include sequence property in header data --- ext/bg/js/database.js | 15 +++------------ ext/bg/js/settings.js | 4 ++-- 2 files changed, 5 insertions(+), 14 deletions(-) diff --git a/ext/bg/js/database.js b/ext/bg/js/database.js index 14b3243a..e63d95de 100644 --- a/ext/bg/js/database.js +++ b/ext/bg/js/database.js @@ -233,7 +233,7 @@ class Database { throw 'Database not initialized'; } - const indexDataValid = async summary => { + const indexDataLoaded = async summary => { if (summary.version > 2) { throw 'Unsupported dictionary version'; } @@ -242,9 +242,7 @@ class Database { if (count > 0) { throw 'Dictionary is already imported'; } - }; - const indexDataLoaded = async summary => { await this.db.dictionaries.add(summary); }; @@ -282,8 +280,6 @@ class Database { } } - summary.hasSequences = rows.every(row => row.sequence >= 0); - await this.db.terms.bulkAdd(rows); }; @@ -381,7 +377,6 @@ class Database { return await Database.importDictionaryZip( archive, - indexDataValid, indexDataLoaded, termDataLoaded, termMetaDataLoaded, @@ -393,7 +388,6 @@ class Database { static async importDictionaryZip( archive, - indexDataValid, indexDataLoaded, termDataLoaded, termMetaDataLoaded, @@ -416,10 +410,11 @@ class Database { const summary = { title: index.title, revision: index.revision, + sequenced: index.sequenced, version: index.format || index.version }; - await indexDataValid(summary); + await indexDataLoaded(summary); const buildTermBankName = index => `term_bank_${index + 1}.json`; const buildTermMetaBankName = index => `term_meta_bank_${index + 1}.json`; @@ -476,10 +471,6 @@ class Database { await loadBank(summary, buildKanjiMetaBankName, kanjiMetaBankCount, kanjiMetaDataLoaded); await loadBank(summary, buildTagBankName, tagBankCount, tagDataLoaded); - if (indexDataLoaded) { - await indexDataLoaded(summary); - } - return summary; } } diff --git a/ext/bg/js/settings.js b/ext/bg/js/settings.js index 9d47f33c..9a7b20b6 100644 --- a/ext/bg/js/settings.js +++ b/ext/bg/js/settings.js @@ -110,7 +110,7 @@ async function formMainDictionaryOptionsPopulate(options) { let mainDictionary = ''; for (const dictRow of await utilDatabaseSummarize()) { - if (dictRow.hasSequences) { + if (dictRow.sequenced) { select.append($(``)); if (dictRow.title === options.general.mainDictionary) { mainDictionary = dictRow.title; @@ -342,7 +342,7 @@ async function onDictionaryImport(e) { const options = await optionsLoad(); const summary = await utilDatabaseImport(e.target.files[0], updateProgress); options.dictionaries[summary.title] = {enabled: true, priority: 0, allowSecondarySearches: false}; - if (summary.hasSequences && options.general.mainDictionary === '') { + if (summary.sequenced && options.general.mainDictionary === '') { options.general.mainDictionary = summary.title; } await optionsSave(options); From c08dc6e00a0786438d785d3c7f62ce86205386fd Mon Sep 17 00:00:00 2001 From: Alex Yatskov Date: Sun, 29 Oct 2017 12:20:56 -0700 Subject: [PATCH 62/64] add dictionary update nag screen --- ext/bg/js/database.js | 2 +- ext/bg/js/settings.js | 24 +++++++++++++++--------- ext/bg/js/templates.js | 18 +++++++++++------- tmpl/dictionary.html | 3 +++ 4 files changed, 30 insertions(+), 17 deletions(-) diff --git a/ext/bg/js/database.js b/ext/bg/js/database.js index e63d95de..3c7f6aab 100644 --- a/ext/bg/js/database.js +++ b/ext/bg/js/database.js @@ -234,7 +234,7 @@ class Database { } const indexDataLoaded = async summary => { - if (summary.version > 2) { + if (summary.version > 3) { throw 'Unsupported dictionary version'; } diff --git a/ext/bg/js/settings.js b/ext/bg/js/settings.js index 9a7b20b6..dcc9c43d 100644 --- a/ext/bg/js/settings.js +++ b/ext/bg/js/settings.js @@ -60,11 +60,11 @@ async function formRead() { optionsNew.general.mainDictionary = $('#dict-main').val(); $('.dict-group').each((index, element) => { const dictionary = $(element); - const title = dictionary.data('title'); - const priority = parseInt(dictionary.find('.dict-priority').val(), 10); - const enabled = dictionary.find('.dict-enabled').prop('checked'); - const allowSecondarySearches = dictionary.find('.dict-allow-secondary-searches').prop('checked'); - optionsNew.dictionaries[title] = {priority, enabled, allowSecondarySearches}; + optionsNew.dictionaries[dictionary.data('title')] = { + priority: parseInt(dictionary.find('.dict-priority').val(), 10), + enabled: dictionary.find('.dict-enabled').prop('checked'), + allowSecondarySearches: dictionary.find('.dict-allow-secondary-searches').prop('checked') + }; }); return {optionsNew, optionsOld}; @@ -277,14 +277,20 @@ async function dictionaryGroupsPopulate(options) { } for (const dictRow of dictRowsSort(dictRows, options)) { - const dictOptions = options.dictionaries[dictRow.title] || {enabled: false, priority: 0, allowSecondarySearches: false}; + const dictOptions = options.dictionaries[dictRow.title] || { + enabled: false, + priority: 0, + allowSecondarySearches: false + }; + const dictHtml = await apiTemplateRender('dictionary.html', { + enabled: dictOptions.enabled, + priority: dictOptions.priority, + allowSecondarySearches: dictOptions.allowSecondarySearches, title: dictRow.title, version: dictRow.version, revision: dictRow.revision, - priority: dictOptions.priority, - enabled: dictOptions.enabled, - allowSecondarySearches: dictOptions.allowSecondarySearches + outdated: dictRow.version < 3 }); dictGroups.append($(dictHtml)); diff --git a/ext/bg/js/templates.js b/ext/bg/js/templates.js index f3f680d5..680ec742 100644 --- a/ext/bg/js/templates.js +++ b/ext/bg/js/templates.js @@ -1,6 +1,8 @@ (function() { var template = Handlebars.template, templates = Handlebars.templates = Handlebars.templates || {}; templates['dictionary.html'] = template({"1":function(container,depth0,helpers,partials,data) { + return "

    This dictionary is outdated and may not support new extension features; please import the latest version.

    \n"; +},"3":function(container,depth0,helpers,partials,data) { return "checked"; },"compiler":[7,">= 4.0.0"],"main":function(container,depth0,helpers,partials,data) { var stack1, helper, alias1=depth0 != null ? depth0 : (container.nullContext || {}), alias2=helpers.helperMissing, alias3="function", alias4=container.escapeExpression; @@ -11,10 +13,12 @@ templates['dictionary.html'] = template({"1":function(container,depth0,helpers,p + alias4(((helper = (helper = helpers.title || (depth0 != null ? depth0.title : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"title","hash":{},"data":data}) : helper))) + " rev." + alias4(((helper = (helper = helpers.revision || (depth0 != null ? depth0.revision : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"revision","hash":{},"data":data}) : helper))) - + "\n\n
    \n