diff options
author | toasted-nutbread <toasted-nutbread@users.noreply.github.com> | 2020-11-12 20:34:11 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-11-12 20:34:11 -0500 |
commit | ec021964b7311d02fdbc5531564074f145043b91 (patch) | |
tree | 7d82366ed48e64c3dbad00e37a5f717134c59439 /ext/bg/js | |
parent | f2ad94e54f2a110bf93aebfae33c808c497005be (diff) |
Compact tags refactor (#1021)
* Update translator to flag redundant tags instead of remove
* Update how compact tags are shown in the popup
* Pass compactTags option to note builder
* Update options templates
* Add options upgrade
* Add options upgrade test
Diffstat (limited to 'ext/bg/js')
-rw-r--r-- | ext/bg/js/anki-note-builder.js | 6 | ||||
-rw-r--r-- | ext/bg/js/backend.js | 3 | ||||
-rw-r--r-- | ext/bg/js/options.js | 28 | ||||
-rw-r--r-- | ext/bg/js/settings/anki-templates-controller.js | 3 | ||||
-rw-r--r-- | ext/bg/js/translator.js | 46 |
5 files changed, 55 insertions, 31 deletions
diff --git a/ext/bg/js/anki-note-builder.js b/ext/bg/js/anki-note-builder.js index 4ac597da..d1e918c9 100644 --- a/ext/bg/js/anki-note-builder.js +++ b/ext/bg/js/anki-note-builder.js @@ -35,6 +35,7 @@ class AnkiNoteBuilder { duplicateScope='collection', resultOutputMode='split', compactGlossaries=false, + compactTags=false, modeOptions: {fields, deck, model}, audioDetails=null, screenshotDetails=null, @@ -70,7 +71,7 @@ class AnkiNoteBuilder { } }; - const data = this._createNoteData(definition, mode, context, resultOutputMode, compactGlossaries); + const data = this._createNoteData(definition, mode, context, resultOutputMode, compactGlossaries, compactTags); const formattedFieldValuePromises = []; for (const [, fieldValue] of fieldEntries) { const formattedFieldValuePromise = this._formatField(fieldValue, data, templates, errors); @@ -104,7 +105,7 @@ class AnkiNoteBuilder { // Private - _createNoteData(definition, mode, context, resultOutputMode, compactGlossaries) { + _createNoteData(definition, mode, context, resultOutputMode, compactGlossaries, compactTags) { const pitches = DictionaryDataUtil.getPitchAccentInfos(definition); const pitchCount = pitches.reduce((i, v) => i + v.pitches.length, 0); return { @@ -118,6 +119,7 @@ class AnkiNoteBuilder { modeTermKana: mode === 'term-kana', modeKanji: mode === 'kanji', compactGlossaries, + compactTags, context }; } diff --git a/ext/bg/js/backend.js b/ext/bg/js/backend.js index d1d25153..c3e3339c 100644 --- a/ext/bg/js/backend.js +++ b/ext/bg/js/backend.js @@ -1650,7 +1650,7 @@ class Backend { const {wildcard} = details; const enabledDictionaryMap = this._getTranslatorEnabledDictionaryMap(options); const { - general: {compactTags, mainDictionary}, + general: {mainDictionary}, scanning: {alphanumeric}, translation: { convertHalfWidthCharacters, @@ -1663,7 +1663,6 @@ class Backend { } = options; return { wildcard, - compactTags, mainDictionary, alphanumeric, convertHalfWidthCharacters, diff --git a/ext/bg/js/options.js b/ext/bg/js/options.js index bb90e655..e4f6c8e4 100644 --- a/ext/bg/js/options.js +++ b/ext/bg/js/options.js @@ -618,7 +618,35 @@ class OptionsUtil { options.global.showPopupPreview = false; for (const profile of options.profiles) { profile.options.anki.checkForDuplicates = true; + const fieldTemplates = profile.options.anki.fieldTemplates; + if (typeof fieldTemplates === 'string') { + profile.options.anki.fieldTemplates = this._updateVersion6AnkiTemplatesCompactTags(fieldTemplates); + } } return options; } + + _updateVersion6AnkiTemplatesCompactTags(templates) { + const rawPattern1 = '{{~#if definitionTags~}}<i>({{#each definitionTags}}{{name}}{{#unless @last}}, {{/unless}}{{/each}})</i> {{/if~}}'; + const pattern1 = new RegExp(`((\r?\n)?[ \t]*)${escapeRegExp(rawPattern1)}`, 'g'); + const replacement1 = ( + // eslint-disable-next-line indent +`{{~#scope~}} + {{~#set "any" false}}{{/set~}} + {{~#if definitionTags~}}{{#each definitionTags~}} + {{~#if (op "||" (op "!" ../data.compactTags) (op "!" redundant))~}} + {{~#if (get "any")}}, {{else}}<i>({{/if~}} + {{name}} + {{~#set "any" true}}{{/set~}} + {{~/if~}} + {{~/each~}} + {{~#if (get "any")}})</i> {{/if~}} + {{~/if~}} +{{~/scope~}}` + ); + const simpleNewline = /\n/g; + templates = templates.replace(pattern1, (g0, space) => (space + replacement1.replace(simpleNewline, space))); + templates = templates.replace(/\bcompactGlossaries=((?:\.*\/)*)compactGlossaries\b/g, (g0, g1) => `${g0} data=${g1}.`); + return templates; + } } diff --git a/ext/bg/js/settings/anki-templates-controller.js b/ext/bg/js/settings/anki-templates-controller.js index e6bab256..e1e01627 100644 --- a/ext/bg/js/settings/anki-templates-controller.js +++ b/ext/bg/js/settings/anki-templates-controller.js @@ -183,7 +183,7 @@ class AnkiTemplatesController { const ankiNoteBuilder = new AnkiNoteBuilder({ renderTemplate: this._renderTemplate.bind(this) }); - const {general: {resultOutputMode, compactGlossaries}} = options; + const {general: {resultOutputMode, compactGlossaries, compactTags}} = options; const note = await ankiNoteBuilder.createNote({ definition, mode, @@ -191,6 +191,7 @@ class AnkiTemplatesController { templates, resultOutputMode, compactGlossaries, + compactTags, modeOptions: { fields: {field}, deck: '', diff --git a/ext/bg/js/translator.js b/ext/bg/js/translator.js index 6e29aeae..2c4d7d3a 100644 --- a/ext/bg/js/translator.js +++ b/ext/bg/js/translator.js @@ -59,7 +59,6 @@ class Translator { * @param options An object using the following structure: * { * wildcard: (null or string), - * compactTags: (boolean), * mainDictionary: (string), * alphanumeric: (boolean), * convertHalfWidthCharacters: (enum: 'false', 'true', 'variant'), @@ -156,24 +155,22 @@ class Translator { } async _findTermsGrouped(text, options) { - const {compactTags, enabledDictionaryMap} = options; + const {enabledDictionaryMap} = options; const [definitions, length] = await this._findTermsInternal(text, enabledDictionaryMap, options); const groupedDefinitions = this._groupTerms(definitions, enabledDictionaryMap); await this._buildTermMeta(groupedDefinitions, enabledDictionaryMap); this._sortDefinitions(groupedDefinitions, false); - if (compactTags) { - for (const definition of groupedDefinitions) { - this._compressDefinitionTags(definition.definitions); - } + for (const definition of groupedDefinitions) { + this._flagRedundantDefinitionTags(definition.definitions); } return [groupedDefinitions, length]; } async _findTermsMerged(text, options) { - const {compactTags, mainDictionary, enabledDictionaryMap} = options; + const {mainDictionary, enabledDictionaryMap} = options; const secondarySearchDictionaryMap = this._getSecondarySearchDictionaryMap(enabledDictionaryMap); const [definitions, length] = await this._findTermsInternal(text, enabledDictionaryMap, options); @@ -212,10 +209,8 @@ class Translator { await this._buildTermMeta(definitionsMerged, enabledDictionaryMap); this._sortDefinitions(definitionsMerged, false); - if (compactTags) { - for (const definition of definitionsMerged) { - this._compressDefinitionTags(definition.definitions); - } + for (const definition of definitionsMerged) { + this._flagRedundantDefinitionTags(definition.definitions); } return [definitionsMerged, length]; @@ -541,7 +536,7 @@ class Translator { } } - _compressDefinitionTags(definitions) { + _flagRedundantDefinitionTags(definitions) { let lastDictionary = ''; let lastPartOfSpeech = ''; const removeCategoriesSet = new Set(); @@ -564,7 +559,7 @@ class Translator { } if (removeCategoriesSet.size > 0) { - this._removeTagsWithCategory(definitionTags, removeCategoriesSet); + this._flagTagsWithCategoryAsRedundant(definitionTags, removeCategoriesSet); removeCategoriesSet.clear(); } } @@ -749,7 +744,7 @@ class Translator { const meta = tagMetaList[i]; const name = names[i]; const {category, notes, order, score} = (meta !== null ? meta : {}); - const tag = this._createTag(name, category, notes, order, score, dictionary); + const tag = this._createTag(name, category, notes, order, score, dictionary, false); results.push(tag); } return results; @@ -893,13 +888,11 @@ class Translator { return results; } - _removeTagsWithCategory(tags, removeCategoriesSet) { - for (let i = 0, ii = tags.length; i < ii; ++i) { - const {category} = tags[i]; - if (!removeCategoriesSet.has(category)) { continue; } - tags.splice(i, 1); - --i; - --ii; + _flagTagsWithCategoryAsRedundant(tags, removeCategoriesSet) { + for (const tag of tags) { + if (removeCategoriesSet.has(tag.category)) { + tag.redundant = true; + } } } @@ -970,8 +963,8 @@ class Translator { // Common data creation and cloning functions _cloneTag(tag) { - const {name, category, notes, order, score, dictionary} = tag; - return this._createTag(name, category, notes, order, score, dictionary); + const {name, category, notes, order, score, dictionary, redundant} = tag; + return this._createTag(name, category, notes, order, score, dictionary, redundant); } _cloneTags(tags) { @@ -987,17 +980,18 @@ class Translator { } _createDictionaryTag(name) { - return this._createTag(name, 'dictionary', '', 100, 0, name); + return this._createTag(name, 'dictionary', '', 100, 0, name, false); } - _createTag(name, category, notes, order, score, dictionary) { + _createTag(name, category, notes, order, score, dictionary, redundant) { return { name, category: (typeof category === 'string' && category.length > 0 ? category : 'default'), notes: (typeof notes === 'string' ? notes : ''), order: (typeof order === 'number' ? order : 0), score: (typeof score === 'number' ? score : 0), - dictionary: (typeof dictionary === 'string' ? dictionary : null) + dictionary: (typeof dictionary === 'string' ? dictionary : null), + redundant }; } |