diff --git a/ext/bg/js/api.js b/ext/bg/js/api.js index 9f65bb07..de3ad64e 100644 --- a/ext/bg/js/api.js +++ b/ext/bg/js/api.js @@ -29,9 +29,11 @@ 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 = { + 'merge': translator.findTermsMerged, + 'split': translator.findTermsSplit, + 'group': translator.findTermsGrouped + }[options.general.resultOutputMode].bind(translator); const {definitions, length} = await searcher( text, diff --git a/ext/bg/js/audio.js b/ext/bg/js/audio.js index ce47490c..549288f5 100644 --- a/ext/bg/js/audio.js +++ b/ext/bg/js/audio.js @@ -140,8 +140,13 @@ async function audioInject(definition, fields, mode) { } try { - const url = await audioBuildUrl(definition, mode); - const filename = audioBuildFilename(definition); + let audioSourceDefinition = definition; + if (definition.hasOwnProperty('expressions')) { + audioSourceDefinition = definition.expressions[0]; + } + + const url = await audioBuildUrl(audioSourceDefinition, mode); + const filename = audioBuildFilename(audioSourceDefinition); if (url && filename) { definition.audio = {url, filename}; diff --git a/ext/bg/js/database.js b/ext/bg/js/database.js index 6ceb3ec8..fcf8ef3f 100644 --- a/ext/bg/js/database.js +++ b/ext/bg/js/database.js @@ -40,6 +40,9 @@ class Database { kanjiMeta: '++,dictionary,character', tagMeta: '++,dictionary,name' }); + this.db.version(4).stores({ + terms: '++id,dictionary,expression,reading,sequence' + }); await this.db.open(); } @@ -68,12 +71,66 @@ class Database { results.push({ expression: row.expression, reading: row.reading, - tags: dictFieldSplit(row.tags), + definitionTags: dictFieldSplit(row.definitionTags || row.tags || ''), + termTags: dictFieldSplit(row.termTags || ''), rules: dictFieldSplit(row.rules), glossary: row.glossary, score: row.score, dictionary: row.dictionary, - id: row.id + id: row.id, + sequence: typeof row.sequence === 'undefined' ? -1 : row.sequence + }); + } + }); + + 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 || row.tags || ''), + 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'; + } + + const results = []; + await this.db.terms.where('sequence').equals(sequence).each(row => { + if (row.dictionary === mainDictionary) { + results.push({ + expression: row.expression, + reading: row.reading, + definitionTags: dictFieldSplit(row.definitionTags || row.tags || ''), + 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 }); } }); @@ -171,12 +228,27 @@ 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'; } - const indexDataLoaded = async summary => { + const indexDataValid = async summary => { if (summary.version > 2) { throw 'Unsupported dictionary version'; } @@ -185,7 +257,9 @@ class Database { if (count > 0) { throw 'Dictionary is already imported'; } + }; + const indexDataLoaded = async summary => { await this.db.dictionaries.add(summary); }; @@ -196,11 +270,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, @@ -208,19 +282,23 @@ class Database { }); } } else { - for (const [expression, reading, tags, rules, score, glossary] 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 }); } } + summary.hasSequences = rows.every(row => row.sequence >= 0); + await this.db.terms.bulkAdd(rows); }; @@ -300,12 +378,13 @@ class Database { } const rows = []; - for (const [name, category, order, notes] of entries) { + for (const [name, category, order, notes, score] of entries) { const row = dictTagSanitize({ name, category, order, notes, + score, dictionary: summary.title }); @@ -317,6 +396,7 @@ class Database { return await Database.importDictionaryZip( archive, + indexDataValid, indexDataLoaded, termDataLoaded, termMetaDataLoaded, @@ -328,6 +408,7 @@ class Database { static async importDictionaryZip( archive, + indexDataValid, indexDataLoaded, termDataLoaded, termMetaDataLoaded, @@ -353,9 +434,7 @@ class Database { version: index.format || index.version }; - if (indexDataLoaded) { - await indexDataLoaded(summary); - } + await indexDataValid(summary); const buildTermBankName = index => `term_bank_${index + 1}.json`; const buildTermMetaBankName = index => `term_meta_bank_${index + 1}.json`; @@ -390,7 +469,7 @@ class Database { const bank = []; for (const name in index.tagMeta) { const tag = index.tagMeta[name]; - bank.push([name, tag.category, tag.order, tag.notes]); + bank.push([name, tag.category, tag.order, tag.notes, tag.score]); } tagDataLoaded(summary, bank, ++bankTotalCount, bankLoadedCount++); @@ -412,6 +491,10 @@ 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/dictionary.js b/ext/bg/js/dictionary.js index 57acbe5e..fea5f3e5 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()); }); } @@ -110,6 +110,33 @@ function dictTermsUndupe(definitions) { return definitionsUnique; } +function dictTermsCompressTags(definitions) { + let lastDictionary = ''; + let lastPartOfSpeech = ''; + + for (const definition of definitions) { + const dictionary = JSON.stringify(definition.definitionTags.filter(tag => tag.category === 'dictionary').map(tag => tag.name).sort()); + const partOfSpeech = JSON.stringify(definition.definitionTags.filter(tag => tag.category === 'partOfSpeech').map(tag => tag.name).sort()); + + const filterOutCategories = []; + + if (lastDictionary === dictionary) { + filterOutCategories.push('dictionary'); + } else { + lastDictionary = dictionary; + lastPartOfSpeech = ''; + } + + if (lastPartOfSpeech === partOfSpeech) { + filterOutCategories.push('partOfSpeech'); + } else { + lastPartOfSpeech = partOfSpeech; + } + + definition.definitionTags = definition.definitionTags.filter(tag => !filterOutCategories.includes(tag.category)); + } +} + function dictTermsGroup(definitions, dictionaries) { const groups = {}; for (const definition of definitions) { @@ -136,6 +163,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 }); @@ -144,6 +172,116 @@ function dictTermsGroup(definitions, dictionaries) { return dictTermsSort(results); } +function dictTermsMergeBySequence(definitions, mainDictionary) { + const definitionsBySequence = {'-1': []}; + for (const definition of definitions) { + if (mainDictionary === definition.dictionary && definition.sequence >= 0) { + if (!definitionsBySequence[definition.sequence]) { + definitionsBySequence[definition.sequence] = { + reasons: definition.reasons, + score: Number.MIN_SAFE_INTEGER, + expression: new Set(), + reading: new Set(), + expressions: new Map(), + source: definition.source, + dictionary: definition.dictionary, + definitions: [] + }; + } + const score = Math.max(definitionsBySequence[definition.sequence].score, definition.score); + definitionsBySequence[definition.sequence].score = score; + } else { + definitionsBySequence['-1'].push(definition); + } + } + + return definitionsBySequence; +} + +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.concat(definition.dictionary)); + if (!definitionsByGloss[gloss]) { + definitionsByGloss[gloss] = { + expression: new Set(), + reading: new Set(), + definitionTags: [], + glossary: definition.glossary, + source: result.source, + reasons: [], + score: definition.score, + id: definition.id, + dictionary: definition.dictionary + }; + } + + definitionsByGloss[gloss].expression.add(definition.expression); + definitionsByGloss[gloss].reading.add(definition.reading); + + result.expression.add(definition.expression); + result.reading.add(definition.reading); + + // result->expressions[ Expression1[ Reading1[ Tag1, Tag2 ] ], Expression2, ... ] + if (!result.expressions.has(definition.expression)) { + result.expressions.set(definition.expression, new Map()); + } + if (!result.expressions.get(definition.expression).has(definition.reading)) { + result.expressions.get(definition.expression).set(definition.reading, new Set()); + } + + for (const tag of definition.definitionTags) { + if (!definitionsByGloss[gloss].definitionTags.find(existingTag => existingTag.name === tag.name)) { + definitionsByGloss[gloss].definitionTags.push(tag); + } + } + + for (const tag of definition.termTags) { + result.expressions.get(definition.expression).get(definition.reading).add(tag); + } + } + + 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; +} + function dictTagBuildSource(name) { return dictTagSanitize({name, category: 'dictionary', order: 100}); } @@ -153,6 +291,7 @@ function dictTagSanitize(tag) { tag.category = tag.category || 'default'; tag.notes = tag.notes || ''; tag.order = tag.order || 0; + tag.score = tag.score || 0; return tag; } @@ -207,10 +346,12 @@ 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' + modeKanji: mode === 'kanji', + compactGlossaries: options.general.compactGlossaries }; const html = await apiTemplateRender(options.anki.fieldTemplates, data, true); diff --git a/ext/bg/js/options.js b/ext/bg/js/options.js index 36ab7694..9f1414ad 100644 --- a/ext/bg/js/options.js +++ b/ext/bg/js/options.js @@ -19,12 +19,26 @@ function optionsFieldTemplates() { return ` + {{#*inline "glossary-single"}} {{~#unless brief~}} - {{~#if tags~}}({{#each tags}}{{name}}{{#unless @last}}, {{/unless}}{{/each}}) {{/if~}} + {{~#if definitionTags~}}({{#each definitionTags}}{{name}}{{#unless @last}}, {{/unless}}{{/each}}) {{/if~}} + {{~#if only~}}({{#each only}}{{{.}}}{{#unless @last}}, {{/unless}}{{/each}} only) {{/if~}} {{~/unless~}} {{~#if glossary.[1]~}} - + {{~#if compactGlossaries~}} + {{#each glossary}}{{#multiLine}}{{.}}{{/multiLine}}{{#unless @last}} | {{/unless}}{{/each}} + {{~else~}} + + {{~/if~}} {{~else~}} {{~#multiLine}}{{glossary.[0]}}{{/multiLine~}} {{~/if~}} @@ -41,23 +55,56 @@ function optionsFieldTemplates() { {{/inline}} {{#*inline "expression"}} - {{~#if modeTermKana~}} - {{~#if definition.reading~}} - {{definition.reading}} + {{~#if merge~}} + {{~#if modeTermKana~}} + {{~#each definition.reading~}} + {{{.}}} + {{~#unless @last}}、{{/unless~}} + {{~else~}} + {{~#each definition.expression~}} + {{{.}}} + {{~#unless @last}}、{{/unless~}} + {{~/each~}} + {{~/each~}} + {{~else~}} + {{~#each definition.expression~}} + {{{.}}} + {{~#unless @last}}、{{/unless~}} + {{~/each~}} + {{~/if~}} + {{~else~}} + {{~#if modeTermKana~}} + {{~#if definition.reading~}} + {{definition.reading}} + {{~else~}} + {{definition.expression}} + {{~/if~}} {{~else~}} {{definition.expression}} {{~/if~}} - {{~else~}} - {{definition.expression}} {{~/if~}} {{/inline}} {{#*inline "furigana"}} - {{#furigana}}{{{definition}}}{{/furigana}} + {{~#if merge~}} + {{~#each definition.expressions~}} + {{~#furigana}}{{{.}}}{{/furigana~}} + {{~#unless @last}}、{{/unless~}} + {{~/each~}} + {{~else~}} + {{#furigana}}{{{definition}}}{{/furigana}} + {{~/if~}} {{/inline}} {{#*inline "furigana-plain"}} - {{#furiganaPlain}}{{{definition}}}{{/furiganaPlain}} + {{~#if merge~}} + {{~#each definition.expressions~}} + {{~#furiganaPlain}}{{{.}}}{{/furiganaPlain~}} + {{~#unless @last}}、{{/unless~}} + {{~/each~}} + {{~else~}} + {{#furiganaPlain}}{{{definition}}}{{/furiganaPlain}} + {{~/if~}} {{/inline}} {{#*inline "glossary"}} @@ -71,12 +118,18 @@ function optionsFieldTemplates() { {{~else~}} {{~#if group~}} {{~#if definition.definitions.[1]~}} -
    {{#each definition.definitions}}
  1. {{> glossary-single brief=../brief}}
  2. {{/each}}
+
    {{#each definition.definitions}}
  1. {{> glossary-single brief=../brief compactGlossaries=../compactGlossaries}}
  2. {{/each}}
{{~else~}} - {{~> glossary-single definition.definitions.[0] brief=brief~}} + {{~> glossary-single definition.definitions.[0] brief=brief compactGlossaries=compactGlossaries~}} + {{~/if~}} + {{~else if merge~}} + {{~#if definition.definitions.[1]~}} +
    {{#each definition.definitions}}
  1. {{> glossary-single brief=../brief compactGlossaries=../compactGlossaries}}
  2. {{/each}}
+ {{~else~}} + {{~> glossary-single definition.definitions.[0] brief=brief compactGlossaries=compactGlossaries~}} {{~/if~}} {{~else~}} - {{~> glossary-single definition brief=brief~}} + {{~> glossary-single definition brief=brief compactGlossaries=compactGlossaries~}} {{~/if~}} {{~/if~}} @@ -95,7 +148,16 @@ function optionsFieldTemplates() { {{/inline}} {{#*inline "reading"}} - {{~#unless modeTermKana}}{{definition.reading}}{{/unless~}} + {{~#unless modeTermKana~}} + {{~#if merge~}} + {{~#each definition.reading~}} + {{{.}}} + {{~#unless @last}}、{{/unless~}} + {{~/each~}} + {{~else~}} + {{~definition.reading~}} + {{~/if~}} + {{~/unless~}} {{/inline}} {{#*inline "sentence"}} @@ -115,7 +177,7 @@ function optionsFieldTemplates() { {{/inline}} {{#*inline "tags"}} - {{~#each definition.tags}}{{name}}{{#unless @last}}, {{/unless}}{{/each~}} + {{~#each definition.definitionTags}}{{name}}{{#unless @last}}, {{/unless}}{{/each~}} {{/inline}} {{#*inline "url"}} @@ -132,14 +194,17 @@ function optionsSetDefaults(options) { enable: true, audioSource: 'jpod101', audioVolume: 100, - groupResults: true, + resultOutputMode: 'group', debugInfo: false, maxResults: 32, showAdvanced: false, popupWidth: 400, popupHeight: 250, popupOffset: 10, - showGuide: true + showGuide: true, + compactTags: false, + compactGlossaries: false, + mainDictionary: '' }, scanning: { @@ -205,6 +270,24 @@ function optionsVersion(options) { } else { options.scanning.modifier = 'none'; } + }, + () => { + if (options.general.groupResults) { + options.general.resultOutputMode = 'group'; + } else { + options.general.resultOutputMode = 'split'; + } + if (utilStringHashCode(options.anki.fieldTemplates) !== -805327496) { // a3c8508031a1073629803d0616a2ee416cd3cccc + options.anki.fieldTemplates = ` +{{#if merge}} +${optionsFieldTemplates()} +{{else}} +${options.anki.fieldTemplates} +{{/if}} +`.trim(); + } else { + options.anki.fieldTemplates = optionsFieldTemplates(); + } } ]; diff --git a/ext/bg/js/settings.js b/ext/bg/js/settings.js index a2f22371..7a9ba4f9 100644 --- a/ext/bg/js/settings.js +++ b/ext/bg/js/settings.js @@ -22,9 +22,12 @@ 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.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.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); @@ -60,7 +63,8 @@ async function formRead() { const title = dictionary.data('title'); const priority = parseInt(dictionary.find('.dict-priority').val(), 10); const enabled = dictionary.find('.dict-enabled').prop('checked'); - optionsNew.dictionaries[title] = {priority, enabled}; + const allowSecondarySearches = dictionary.find('.dict-allow-secondary-searches').prop('checked'); + optionsNew.dictionaries[title] = {priority, enabled, allowSecondarySearches}; }); return {optionsNew, optionsOld}; @@ -81,6 +85,13 @@ function formUpdateVisibility(options) { advanced.hide(); } + const merge = $('.options-merge'); + if (options.general.resultOutputMode === 'merge') { + merge.show(); + } else { + merge.hide(); + } + const debug = $('#debug'); if (options.general.debugInfo) { const temp = utilIsolate(options); @@ -93,6 +104,29 @@ function formUpdateVisibility(options) { } } +async function formMainDictionaryOptionsPopulate(options) { + const select = $('#main-dictionary').empty(); + + let titles = await utilDatabaseGetTitlesWithSequences(); + titles = titles.filter(title => options.dictionaries[title].enabled); + const formOptionsHtml = []; + let mainDictionarySelected = false; + for (const title of titles) { + if (options.general.mainDictionary === title) { + mainDictionarySelected = true; + } + formOptionsHtml.push(``); + } + + if (!mainDictionarySelected) { + options.general.mainDictionary = ''; + } + + const notSelectedOptionHtml = ``; + + select.append($([notSelectedOptionHtml].concat(formOptionsHtml).join(''))); +} + async function onFormOptionsChanged(e) { try { if (!e.originalEvent && !e.isTrigger) { @@ -100,6 +134,7 @@ async function onFormOptionsChanged(e) { } const {optionsNew, optionsOld} = await formRead(); + await formMainDictionaryOptionsPopulate(optionsNew); await optionsSave(optionsNew); formUpdateVisibility(optionsNew); @@ -124,9 +159,12 @@ async function onReady() { const options = await optionsLoad(); $('#show-usage-guide').prop('checked', options.general.showGuide); + $('#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); - $('#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); @@ -166,6 +204,8 @@ async function onReady() { ankiErrorShow(e); } + await formMainDictionaryOptionsPopulate(options); + formUpdateVisibility(options); } @@ -247,13 +287,14 @@ async function dictionaryGroupsPopulate(options) { } for (const dictRow of dictRowsSort(dictRows, options)) { - const dictOptions = options.dictionaries[dictRow.title] || {enabled: false, priority: 0}; + const dictOptions = options.dictionaries[dictRow.title] || {enabled: false, priority: 0, allowSecondarySearches: false}; const dictHtml = await apiTemplateRender('dictionary.html', { title: dictRow.title, version: dictRow.version, revision: dictRow.revision, priority: dictOptions.priority, - enabled: dictOptions.enabled + enabled: dictOptions.enabled, + allowSecondarySearches: dictOptions.allowSecondarySearches }); dictGroups.append($(dictHtml)); @@ -261,7 +302,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); }); @@ -280,9 +321,11 @@ async function onDictionaryPurge(e) { await utilDatabasePurge(); const options = await optionsLoad(); options.dictionaries = {}; + options.general.mainDictionary = ''; await optionsSave(options); await dictionaryGroupsPopulate(options); + await formMainDictionaryOptionsPopulate(options); } catch (e) { dictionaryErrorShow(e); } finally { @@ -308,10 +351,14 @@ 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}; + options.dictionaries[summary.title] = {enabled: true, priority: 0, allowSecondarySearches: false}; + if (summary.hasSequences && !options.general.mainDictionary) { + options.general.mainDictionary = summary.title; + } await optionsSave(options); await dictionaryGroupsPopulate(options); + await formMainDictionaryOptionsPopulate(options); } catch (e) { dictionaryErrorShow(e); } finally { diff --git a/ext/bg/js/templates.js b/ext/bg/js/templates.js index b5d352fc..f3f680d5 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" - + ((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 : "") + return "
\n" + + ((stack1 = helpers.each.call(alias1,(depth0 != null ? depth0.definitionTags : depth0),{"name":"each","hash":{},"fn":container.program(5, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") + "
\n"; },"3":function(container,depth0,helpers,partials,data) { + return "class=\"compact-info\""; +},"5":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) { +},"7":function(container,depth0,helpers,partials,data) { + var stack1, alias1=depth0 != null ? depth0 : (container.nullContext || {}); + + return "
\n (" + + ((stack1 = helpers.each.call(alias1,(depth0 != null ? depth0.only : depth0),{"name":"each","hash":{},"fn":container.program(8, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") + + " only)\n
\n"; +},"8":function(container,depth0,helpers,partials,data) { var stack1; - return "