diff --git a/docs/anki-integration.md b/docs/anki-integration.md index 9582025149..3a87286411 100644 --- a/docs/anki-integration.md +++ b/docs/anki-integration.md @@ -34,7 +34,8 @@ Flashcard fields can be configured with the following steps: | `{cloze-prefix}` | Fragment of the containing `{sentence}` starting at the beginning of `{sentence}` until the beginning of `{cloze-body}`. | | `{cloze-suffix}` | Fragment of the containing `{sentence}` starting at the end of `{cloze-body}` until the end of `{sentence}`. | | `{conjugation}` | Conjugation path from the raw inflected term to the source term. | - | `{dictionary}` | Name of the dictionary from which the card is being created (unavailable in _grouped_ mode). | + | `{dictionary}` | Original name of the dictionary from which the card is being created (unavailable in _grouped_ mode). | + | `{dictionary-alias}` | Display name of the dictionary from which the card is being created (unavailable in _grouped_ mode). | | `{document-title}` | Title of the web page that the term appeared in. | | `{expression}` | Term expressed as kanji (will be displayed in kana if kanji is not available). | | `{frequencies}` | Frequency information for the term. | @@ -79,7 +80,8 @@ Flashcard fields can be configured with the following steps: | `{cloze-body}` | Raw, inflected parent term as it appeared before being reduced to dictionary form by Yomitan. | | `{cloze-prefix}` | Fragment of the containing `{sentence}` starting at the beginning of `{sentence}` until the beginning of `{cloze-body}`. | | `{cloze-suffix}` | Fragment of the containing `{sentence}` starting at the end of `{cloze-body}` until the end of `{sentence}`. | - | `{dictionary}` | Name of the dictionary from which the card is being created. | + | `{dictionary}` | Original name of the dictionary from which the card is being created. | + | `{dictionary-alias}` | Display name of the dictionary from which the card is being created. | | `{document-title}` | Title of the web page that the kanji appeared in. | | `{frequencies}` | Frequency information for the kanji. | | `{frequency-harmonic-rank}` | The harmonic mean of frequency data for the current kanji. Defaults to rank 9999999 when frequency data is not found, indicating extremely low rank-based kanji usage. | diff --git a/ext/css/settings.css b/ext/css/settings.css index 2e97a6d07d..7e6c4bc158 100644 --- a/ext/css/settings.css +++ b/ext/css/settings.css @@ -2404,6 +2404,10 @@ input[type=number].dictionary-priority { overflow: auto; } +#dictionary-alias-input { + width: 100%; +} + #dictionary-move-up>span.icon-button-inner, #dictionary-move-down>span.icon-button-inner { width: 26px; diff --git a/ext/data/schemas/options-schema.json b/ext/data/schemas/options-schema.json index fba2bc208f..50fb81806b 100644 --- a/ext/data/schemas/options-schema.json +++ b/ext/data/schemas/options-schema.json @@ -831,6 +831,7 @@ "type": "object", "required": [ "name", + "alias", "priority", "enabled", "allowSecondarySearches", @@ -843,6 +844,10 @@ "type": "string", "default": "" }, + "alias": { + "type": "string", + "default": "" + }, "priority": { "type": "number", "default": 0 diff --git a/ext/data/templates/anki-field-templates-upgrade-v49.handlebars b/ext/data/templates/anki-field-templates-upgrade-v49.handlebars new file mode 100644 index 0000000000..f95cdd4660 --- /dev/null +++ b/ext/data/templates/anki-field-templates-upgrade-v49.handlebars @@ -0,0 +1,115 @@ +{{<<<<<<<}} +{{#*inline "glossary-single"}} + {{~#unless brief~}} + {{~#scope~}} + {{~set "any" false~}} + {{~#each definitionTags~}} + {{~#if (op "||" (op "!" @root.compactTags) (op "!" redundant))~}} + {{~#if (get "any")}}, {{else}}({{/if~}} + {{name}} + {{~set "any" true~}} + {{~/if~}} + {{~/each~}} + {{~#unless noDictionaryTag~}} + {{~#if (op "||" (op "!" @root.compactTags) (op "!==" dictionary (get "previousDictionary")))~}} + {{~#if (get "any")}}, {{else}}({{/if~}} + {{dictionary}} + {{~set "any" true~}} + {{~/if~}} + {{~/unless~}} + {{~#if (get "any")}}) {{/if~}} + {{~/scope~}} + {{~#if only~}}({{#each only}}{{.}}{{#unless @last}}, {{/unless}}{{/each}} only) {{/if~}} + {{~/unless~}} + {{~#if (op "<=" glossary.length 1)~}} + {{#each glossary}}{{formatGlossary ../dictionary .}}{{/each}} + {{~else if @root.compactGlossaries~}} + {{#each glossary}}{{formatGlossary ../dictionary .}}{{#unless @last}} | {{/unless}}{{/each}} + {{~else~}} + + {{~/if~}} + {{~set "previousDictionary" dictionary~}} +{{/inline}} +{{=======}} +{{#*inline "glossary-single"}} + {{~#unless brief~}} + {{~#scope~}} + {{~set "any" false~}} + {{~#each definitionTags~}} + {{~#if (op "||" (op "!" @root.compactTags) (op "!" redundant))~}} + {{~#if (get "any")}}, {{else}}({{/if~}} + {{name}} + {{~set "any" true~}} + {{~/if~}} + {{~/each~}} + {{~#unless noDictionaryTag~}} + {{~#if (op "||" (op "!" @root.compactTags) (op "!==" dictionary (get "previousDictionary")))~}} + {{~#if (get "any")}}, {{else}}({{/if~}} + {{dictionaryAlias}} + {{~set "any" true~}} + {{~/if~}} + {{~/unless~}} + {{~#if (get "any")}}) {{/if~}} + {{~/scope~}} + {{~#if only~}}({{#each only}}{{.}}{{#unless @last}}, {{/unless}}{{/each}} only) {{/if~}} + {{~/unless~}} + {{~#if (op "<=" glossary.length 1)~}} + {{#each glossary}}{{formatGlossary ../dictionary .}}{{/each}} + {{~else if @root.compactGlossaries~}} + {{#each glossary}}{{formatGlossary ../dictionary .}}{{#unless @last}} | {{/unless}}{{/each}} + {{~else~}} + + {{~/if~}} + {{~set "previousDictionary" dictionary~}} +{{/inline}} +{{>>>>>>>}} + +{{<<<<<<<}} +{{#*inline "dictionary"}} + {{~definition.dictionary~}} +{{/inline}} +{{=======}} +{{#*inline "dictionary"}} + {{~definition.dictionary~}} +{{/inline}} + +{{#*inline "dictionary-alias"}} + {{~definition.dictionaryAlias~}} +{{/inline}} +{{>>>>>>>}} + +{{<<<<<<<}} +{{#*inline "frequencies"}} + {{~#if (op ">" definition.frequencies.length 0)~}} + + {{~/if~}} +{{/inline}} +{{=======}} +{{#*inline "frequencies"}} + {{~#if (op ">" definition.frequencies.length 0)~}} + + {{~/if~}} +{{/inline}} +{{>>>>>>>}} \ No newline at end of file diff --git a/ext/data/templates/default-anki-field-templates.handlebars b/ext/data/templates/default-anki-field-templates.handlebars index 2ccea7ba09..a065e3848c 100644 --- a/ext/data/templates/default-anki-field-templates.handlebars +++ b/ext/data/templates/default-anki-field-templates.handlebars @@ -12,7 +12,7 @@ {{~#unless noDictionaryTag~}} {{~#if (op "||" (op "!" @root.compactTags) (op "!==" dictionary (get "previousDictionary")))~}} {{~#if (get "any")}}, {{else}}({{/if~}} - {{dictionary}} + {{dictionaryAlias}} {{~set "any" true~}} {{~/if~}} {{~/unless~}} @@ -44,6 +44,10 @@ {{~definition.dictionary~}} {{/inline}} +{{#*inline "dictionary-alias"}} + {{~definition.dictionaryAlias~}} +{{/inline}} + {{#*inline "expression"}} {{~#if merge~}} {{~#if modeTermKana~}} @@ -365,7 +369,7 @@ {{~furigana expression reading~}} ) {{/if~}} {{~/if~}} - {{~dictionary}}: {{frequency~}} + {{~dictionaryAlias}}: {{frequency~}} {{~/each~}} diff --git a/ext/js/background/backend.js b/ext/js/background/backend.js index 5617941b62..b010cb38f2 100644 --- a/ext/js/background/backend.js +++ b/ext/js/background/backend.js @@ -2472,6 +2472,7 @@ export class Backend { if (mode === 'merge' && !enabledDictionaryMap.has(mainDictionary)) { enabledDictionaryMap.set(mainDictionary, { index: enabledDictionaryMap.size, + alias: mainDictionary, priority: 0, allowSecondarySearches: false, partsOfSpeechFilter: true, @@ -2516,9 +2517,10 @@ export class Backend { const enabledDictionaryMap = new Map(); for (const dictionary of options.dictionaries) { if (!dictionary.enabled) { continue; } - const {name, priority, allowSecondarySearches, partsOfSpeechFilter, useDeinflections} = dictionary; + const {name, alias, priority, allowSecondarySearches, partsOfSpeechFilter, useDeinflections} = dictionary; enabledDictionaryMap.set(name, { index: enabledDictionaryMap.size, + alias, priority, allowSecondarySearches, partsOfSpeechFilter, diff --git a/ext/js/data/anki-note-data-creator.js b/ext/js/data/anki-note-data-creator.js index 4c92926a32..4c6576322c 100644 --- a/ext/js/data/anki-note-data-creator.js +++ b/ext/js/data/anki-note-data-creator.js @@ -327,7 +327,7 @@ function getDefinition(dictionaryEntry, context, resultOutputMode, dictionarySty * @returns {import('anki-templates').KanjiDictionaryEntry} */ function getKanjiDefinition(dictionaryEntry, context) { - const {character, dictionary, onyomi, kunyomi, definitions} = dictionaryEntry; + const {character, dictionary, dictionaryAlias, onyomi, kunyomi, definitions} = dictionaryEntry; let {url} = context; if (typeof url !== 'string') { url = ''; } @@ -343,6 +343,7 @@ function getKanjiDefinition(dictionaryEntry, context) { type: 'kanji', character, dictionary, + dictionaryAlias, onyomi, kunyomi, glossary: definitions, @@ -392,10 +393,11 @@ function convertKanjiStat({name, category, content, order, score, dictionary, va function getKanjiFrequencies(dictionaryEntry) { /** @type {import('anki-templates').KanjiFrequency[]} */ const results = []; - for (const {index, dictionary, dictionaryIndex, dictionaryPriority, character, frequency, displayValue} of dictionaryEntry.frequencies) { + for (const {index, dictionary, dictionaryAlias, dictionaryIndex, dictionaryPriority, character, frequency, displayValue} of dictionaryEntry.frequencies) { results.push({ index, dictionary, + dictionaryAlias, dictionaryOrder: { index: dictionaryIndex, priority: dictionaryPriority, @@ -429,6 +431,7 @@ function getTermDefinition(dictionaryEntry, context, resultOutputMode, dictionar const primarySource = getPrimarySource(dictionaryEntry); + const dictionaryAliases = createCachedValue(getTermDictionaryAliases.bind(null, dictionaryEntry)); const dictionaryNames = createCachedValue(getTermDictionaryNames.bind(null, dictionaryEntry)); const commonInfo = createCachedValue(getTermDictionaryEntryCommonInfo.bind(null, dictionaryEntry, type, dictionaryStylesMap)); const termTags = createCachedValue(getTermTags.bind(null, dictionaryEntry, type)); @@ -455,6 +458,7 @@ function getTermDefinition(dictionaryEntry, context, resultOutputMode, dictionar isPrimary: (type === 'term' ? dictionaryEntry.isPrimary : void 0), get sequence() { return getCachedValue(sequence); }, get dictionary() { return getCachedValue(dictionaryNames)[0]; }, + get dictionaryAlias() { return getCachedValue(dictionaryAliases)[0]; }, dictionaryOrder: { index: dictionaryIndex, priority: dictionaryPriority, @@ -499,6 +503,18 @@ function getTermDictionaryNames(dictionaryEntry) { return [...dictionaryNames]; } +/** + * @param {import('dictionary').TermDictionaryEntry} dictionaryEntry + * @returns {string[]} + */ +function getTermDictionaryAliases(dictionaryEntry) { + const dictionaryAliases = new Set(); + for (const {dictionaryAlias} of dictionaryEntry.definitions) { + dictionaryAliases.add(dictionaryAlias); + } + return [...dictionaryAliases]; +} + /** * @param {import('dictionary').TermDictionaryEntry} dictionaryEntry * @param {import('anki-templates').TermDictionaryEntryType} type @@ -524,7 +540,7 @@ function getTermDictionaryEntryCommonInfo(dictionaryEntry, type, dictionaryStyle const definitions = []; /** @type {import('anki-templates').Tag[]} */ const definitionTags = []; - for (const {tags, headwordIndices, entries, dictionary, sequences} of dictionaryEntry.definitions) { + for (const {tags, headwordIndices, entries, dictionary, dictionaryAlias, sequences} of dictionaryEntry.definitions) { const dictionaryStyles = dictionaryStylesMap.get(dictionary); let glossaryScopedStyles = ''; let dictScopedStyles = ''; @@ -542,6 +558,7 @@ function getTermDictionaryEntryCommonInfo(dictionaryEntry, type, dictionaryStyle definitions.push({ sequence: sequences[0], dictionary, + dictionaryAlias, glossaryScopedStyles, dictScopedStyles, glossary: entries, @@ -598,12 +615,13 @@ function addScopeToCss(css, scopeSelector) { function getTermFrequencies(dictionaryEntry) { const results = []; const {headwords} = dictionaryEntry; - for (const {headwordIndex, dictionary, dictionaryIndex, dictionaryPriority, hasReading, frequency, displayValue} of dictionaryEntry.frequencies) { + for (const {headwordIndex, dictionary, dictionaryAlias, dictionaryIndex, dictionaryPriority, hasReading, frequency, displayValue} of dictionaryEntry.frequencies) { const {term, reading} = headwords[headwordIndex]; results.push({ index: results.length, expressionIndex: headwordIndex, dictionary, + dictionaryAlias, dictionaryOrder: { index: dictionaryIndex, priority: dictionaryPriority, @@ -624,7 +642,7 @@ function getTermFrequencies(dictionaryEntry) { function getTermPitches(dictionaryEntry) { const results = []; const {headwords} = dictionaryEntry; - for (const {headwordIndex, dictionary, dictionaryIndex, dictionaryPriority, pronunciations} of dictionaryEntry.pronunciations) { + for (const {headwordIndex, dictionary, dictionaryAlias, dictionaryIndex, dictionaryPriority, pronunciations} of dictionaryEntry.pronunciations) { const {term, reading} = headwords[headwordIndex]; const pitches = getPronunciationsOfType(pronunciations, 'pitch-accent'); const cachedPitches = createCachedValue(getTermPitchesInner.bind(null, pitches)); @@ -632,6 +650,7 @@ function getTermPitches(dictionaryEntry) { index: results.length, expressionIndex: headwordIndex, dictionary, + dictionaryAlias, dictionaryOrder: { index: dictionaryIndex, priority: dictionaryPriority, @@ -667,7 +686,7 @@ function getTermPitchesInner(pitches) { function getTermPhoneticTranscriptions(dictionaryEntry) { const results = []; const {headwords} = dictionaryEntry; - for (const {headwordIndex, dictionary, dictionaryIndex, dictionaryPriority, pronunciations} of dictionaryEntry.pronunciations) { + for (const {headwordIndex, dictionary, dictionaryAlias, dictionaryIndex, dictionaryPriority, pronunciations} of dictionaryEntry.pronunciations) { const {term, reading} = headwords[headwordIndex]; const phoneticTranscriptions = getPronunciationsOfType(pronunciations, 'phonetic-transcription'); const termPhoneticTranscriptions = getTermPhoneticTranscriptionsInner(phoneticTranscriptions); @@ -675,6 +694,7 @@ function getTermPhoneticTranscriptions(dictionaryEntry) { index: results.length, expressionIndex: headwordIndex, dictionary, + dictionaryAlias, dictionaryOrder: { index: dictionaryIndex, priority: dictionaryPriority, @@ -742,13 +762,14 @@ function getTermExpressions(dictionaryEntry) { function getTermExpressionFrequencies(dictionaryEntry, i) { const results = []; const {headwords, frequencies} = dictionaryEntry; - for (const {headwordIndex, dictionary, dictionaryIndex, dictionaryPriority, hasReading, frequency, displayValue} of frequencies) { + for (const {headwordIndex, dictionary, dictionaryAlias, dictionaryIndex, dictionaryPriority, hasReading, frequency, displayValue} of frequencies) { if (headwordIndex !== i) { continue; } const {term, reading} = headwords[headwordIndex]; results.push({ index: results.length, expressionIndex: headwordIndex, dictionary, + dictionaryAlias, dictionaryOrder: { index: dictionaryIndex, priority: dictionaryPriority, @@ -770,7 +791,7 @@ function getTermExpressionFrequencies(dictionaryEntry, i) { function getTermExpressionPitches(dictionaryEntry, i) { const results = []; const {headwords, pronunciations: termPronunciations} = dictionaryEntry; - for (const {headwordIndex, dictionary, dictionaryIndex, dictionaryPriority, pronunciations} of termPronunciations) { + for (const {headwordIndex, dictionary, dictionaryAlias, dictionaryIndex, dictionaryPriority, pronunciations} of termPronunciations) { if (headwordIndex !== i) { continue; } const {term, reading} = headwords[headwordIndex]; const pitches = getPronunciationsOfType(pronunciations, 'pitch-accent'); @@ -779,6 +800,7 @@ function getTermExpressionPitches(dictionaryEntry, i) { index: results.length, expressionIndex: headwordIndex, dictionary, + dictionaryAlias, dictionaryOrder: { index: dictionaryIndex, priority: dictionaryPriority, diff --git a/ext/js/data/anki-template-util.js b/ext/js/data/anki-template-util.js index 74589c5bcf..5e36b7e607 100644 --- a/ext/js/data/anki-template-util.js +++ b/ext/js/data/anki-template-util.js @@ -34,6 +34,7 @@ export function getStandardFieldMarkers(type) { 'cloze-suffix', 'conjugation', 'dictionary', + 'dictionary-alias', 'document-title', 'expression', 'frequencies', @@ -74,6 +75,7 @@ export function getStandardFieldMarkers(type) { 'cloze-prefix', 'cloze-suffix', 'dictionary', + 'dictionary-alias', 'document-title', 'frequencies', 'frequency-harmonic-rank', diff --git a/ext/js/data/options-util.js b/ext/js/data/options-util.js index a56dca458c..3ae48df717 100644 --- a/ext/js/data/options-util.js +++ b/ext/js/data/options-util.js @@ -560,6 +560,7 @@ export class OptionsUtil { this._updateVersion46, this._updateVersion47, this._updateVersion48, + this._updateVersion49, ]; /* eslint-enable @typescript-eslint/unbound-method */ if (typeof targetVersion === 'number' && targetVersion < result.length) { @@ -1445,6 +1446,21 @@ export class OptionsUtil { } } + /** + * - Added dictionary alias + * @type {import('options-util').UpdateFunction} + */ + async _updateVersion49(options) { + await this._applyAnkiFieldTemplatesPatch(options, '/data/templates/anki-field-templates-upgrade-v49.handlebars'); + for (const {options: profileOptions} of options.profiles) { + if (Array.isArray(profileOptions.dictionaries)) { + for (const dictionary of profileOptions.dictionaries) { + dictionary.alias = dictionary.name; + } + } + } + } + /** * @param {string} url * @returns {Promise} diff --git a/ext/js/dictionary/dictionary-data-util.js b/ext/js/dictionary/dictionary-data-util.js index 39b604c8c4..296f4ed95e 100644 --- a/ext/js/dictionary/dictionary-data-util.js +++ b/ext/js/dictionary/dictionary-data-util.js @@ -58,13 +58,16 @@ export function groupTermFrequencies(dictionaryEntry) { /** @type {import('dictionary-data-util').TermFrequenciesMap1} */ const map1 = new Map(); - for (const {headwordIndex, dictionary, hasReading, frequency, displayValue} of sourceFrequencies) { + /** @type {Map} */ + const aliasMap = new Map(); + for (const {headwordIndex, dictionary, dictionaryAlias, hasReading, frequency, displayValue} of sourceFrequencies) { const {term, reading} = headwords[headwordIndex]; let map2 = map1.get(dictionary); if (typeof map2 === 'undefined') { map2 = new Map(); map1.set(dictionary, map2); + aliasMap.set(dictionary, dictionaryAlias); } const readingKey = hasReading ? reading : null; @@ -81,6 +84,7 @@ export function groupTermFrequencies(dictionaryEntry) { const results = []; for (const [dictionary, map2] of map1.entries()) { const frequencies = []; + const dictionaryAlias = aliasMap.get(dictionary) ?? dictionary; for (const {term, reading, values} of map2.values()) { frequencies.push({ term, @@ -88,7 +92,7 @@ export function groupTermFrequencies(dictionaryEntry) { values: [...values.values()], }); } - results.push({dictionary, frequencies}); + results.push({dictionary, frequencies, dictionaryAlias}); } return results; } @@ -100,11 +104,14 @@ export function groupTermFrequencies(dictionaryEntry) { export function groupKanjiFrequencies(sourceFrequencies) { /** @type {import('dictionary-data-util').KanjiFrequenciesMap1} */ const map1 = new Map(); - for (const {dictionary, character, frequency, displayValue} of sourceFrequencies) { + /** @type {Map} */ + const aliasMap = new Map(); + for (const {dictionary, dictionaryAlias, character, frequency, displayValue} of sourceFrequencies) { let map2 = map1.get(dictionary); if (typeof map2 === 'undefined') { map2 = new Map(); map1.set(dictionary, map2); + aliasMap.set(dictionary, dictionaryAlias); } let frequencyData = map2.get(character); @@ -119,13 +126,14 @@ export function groupKanjiFrequencies(sourceFrequencies) { const results = []; for (const [dictionary, map2] of map1.entries()) { const frequencies = []; + const dictionaryAlias = aliasMap.get(dictionary) ?? dictionary; for (const {character, values} of map2.values()) { frequencies.push({ character, values: [...values.values()], }); } - results.push({dictionary, frequencies}); + results.push({dictionary, frequencies, dictionaryAlias}); } return results; } @@ -139,6 +147,8 @@ export function getGroupedPronunciations(dictionaryEntry) { const allTerms = new Set(); const allReadings = new Set(); + /** @type {Map} */ + const aliasMap = new Map(); for (const {term, reading} of headwords) { allTerms.add(term); allReadings.add(reading); @@ -146,12 +156,13 @@ export function getGroupedPronunciations(dictionaryEntry) { /** @type {Map} */ const groupedPronunciationsMap = new Map(); - for (const {headwordIndex, dictionary, pronunciations} of termPronunciations) { + for (const {headwordIndex, dictionary, dictionaryAlias, pronunciations} of termPronunciations) { const {term, reading} = headwords[headwordIndex]; let dictionaryGroupedPronunciationList = groupedPronunciationsMap.get(dictionary); if (typeof dictionaryGroupedPronunciationList === 'undefined') { dictionaryGroupedPronunciationList = []; groupedPronunciationsMap.set(dictionary, dictionaryGroupedPronunciationList); + aliasMap.set(dictionary, dictionaryAlias); } for (const pronunciation of pronunciations) { let groupedPronunciation = findExistingGroupedPronunciation(reading, pronunciation, dictionaryGroupedPronunciationList); @@ -173,6 +184,7 @@ export function getGroupedPronunciations(dictionaryEntry) { for (const [dictionary, dictionaryGroupedPronunciationList] of groupedPronunciationsMap.entries()) { /** @type {import('dictionary-data-util').GroupedPronunciation[]} */ const pronunciations2 = []; + const dictionaryAlias = aliasMap.get(dictionary) ?? dictionary; for (const groupedPronunciation of dictionaryGroupedPronunciationList) { const {pronunciation, terms, reading} = groupedPronunciation; const exclusiveTerms = !areSetsEqual(terms, allTerms) ? getSetIntersection(terms, allTerms) : []; @@ -189,7 +201,7 @@ export function getGroupedPronunciations(dictionaryEntry) { }); } - results2.push({dictionary, pronunciations: pronunciations2}); + results2.push({dictionary, dictionaryAlias, pronunciations: pronunciations2}); } return results2; } diff --git a/ext/js/display/display-generator.js b/ext/js/display/display-generator.js index be87761b27..4497e9f5a2 100644 --- a/ext/js/display/display-generator.js +++ b/ext/js/display/display-generator.js @@ -134,14 +134,15 @@ export class DisplayGenerator { const dictionaryTag = this._createDictionaryTag(''); for (let i = 0, ii = definitions.length; i < ii; ++i) { const definition = definitions[i]; - const {dictionary} = definition; + const {dictionary, dictionaryAlias} = definition; if (dictionaryTag.dictionaries.includes(dictionary)) { dictionaryTag.redundant = true; } else { dictionaryTag.redundant = false; dictionaryTag.dictionaries.push(dictionary); - dictionaryTag.name = dictionary; + dictionaryTag.name = dictionaryAlias; + dictionaryTag.content = [dictionary]; } const node2 = this._createTermDefinition(definition, dictionaryTag, headwords, uniqueTerms, uniqueReadings); @@ -175,7 +176,9 @@ export class DisplayGenerator { if (this._language === 'ja') { glyphContainer.style.fontFamily = 'kanji-stroke-orders, sans-serif'; } const groupedFrequencies = groupKanjiFrequencies(dictionaryEntry.frequencies); - const dictionaryTag = this._createDictionaryTag(dictionaryEntry.dictionary); + const dictionaryTag = this._createDictionaryTag(''); + dictionaryTag.name = dictionaryEntry.dictionaryAlias; + dictionaryTag.content = [dictionaryEntry.dictionary]; this._appendMultiple(frequencyGroupListContainer, this._createFrequencyGroup.bind(this), groupedFrequencies, true); this._appendMultiple(tagContainer, this._createTag.bind(this), [...dictionaryEntry.tags, dictionaryTag]); @@ -660,7 +663,7 @@ export class DisplayGenerator { * @returns {HTMLElement} */ _createGroupedPronunciation(details) { - const {dictionary, pronunciations} = details; + const {dictionary, dictionaryAlias, pronunciations} = details; const node = this._instantiate('pronunciation-group'); node.dataset.dictionary = dictionary; @@ -668,7 +671,8 @@ export class DisplayGenerator { node.dataset.pronunciationsCount = `${pronunciations.length}`; const n1 = this._querySelector(node, '.pronunciation-group-tag-list'); - const tag = this._createTag(this._createTagData(dictionary, 'pronunciation-dictionary')); + const tag = this._createTag(this._createTagData(dictionaryAlias, 'pronunciation-dictionary')); + tag.dataset.details = dictionary; n1.appendChild(tag); let hasTags = false; @@ -796,22 +800,23 @@ export class DisplayGenerator { * @returns {HTMLElement} */ _createFrequencyGroup(details, kanji) { - const {dictionary, frequencies} = details; + const {dictionary, dictionaryAlias, frequencies} = details; const node = this._instantiate('frequency-group-item'); const body = this._querySelector(node, '.tag-body-content'); const tagLabel = this._querySelector(node, '.tag-label-content'); - this._setTextContent(tagLabel, dictionary); - node.dataset.details = dictionary; + const tag = this._querySelector(node, '.tag'); + + this._setTextContent(tagLabel, dictionaryAlias); const ii = frequencies.length; for (let i = 0; i < ii; ++i) { const item = frequencies[i]; const itemNode = ( kanji ? - this._createKanjiFrequency(/** @type {import('dictionary-data-util').KanjiFrequency} */ (item), dictionary) : - this._createTermFrequency(/** @type {import('dictionary-data-util').TermFrequency} */ (item), dictionary) + this._createKanjiFrequency(/** @type {import('dictionary-data-util').KanjiFrequency} */ (item), dictionary, dictionaryAlias) : + this._createTermFrequency(/** @type {import('dictionary-data-util').TermFrequency} */ (item), dictionary, dictionaryAlias) ); itemNode.dataset.index = `${i}`; body.appendChild(itemNode); @@ -820,24 +825,26 @@ export class DisplayGenerator { body.dataset.count = `${ii}`; node.dataset.count = `${ii}`; node.dataset.details = dictionary; - + tag.dataset.details = dictionary; return node; } /** * @param {import('dictionary-data-util').TermFrequency} details * @param {string} dictionary + * @param {string} dictionaryAlias * @returns {HTMLElement} */ - _createTermFrequency(details, dictionary) { + _createTermFrequency(details, dictionary, dictionaryAlias) { const {term, reading, values} = details; const node = this._instantiate('term-frequency-item'); const tagLabel = this._querySelector(node, '.tag-label-content'); + const tag = this._querySelector(node, '.tag'); const disambiguationTerm = this._querySelector(node, '.frequency-disambiguation-term'); const disambiguationReading = this._querySelector(node, '.frequency-disambiguation-reading'); const frequencyValueList = this._querySelector(node, '.frequency-value-list'); - this._setTextContent(tagLabel, dictionary); + this._setTextContent(tagLabel, dictionaryAlias); this._setTextContent(disambiguationTerm, term, this._language); this._setTextContent(disambiguationReading, (reading !== null ? reading : ''), this._language); this._populateFrequencyValueList(frequencyValueList, values); @@ -850,27 +857,30 @@ export class DisplayGenerator { node.dataset.readingIsSame = `${reading === term}`; node.dataset.dictionary = dictionary; node.dataset.details = dictionary; - + tag.dataset.details = dictionary; return node; } /** * @param {import('dictionary-data-util').KanjiFrequency} details * @param {string} dictionary + * @param {string} dictionaryAlias * @returns {HTMLElement} */ - _createKanjiFrequency(details, dictionary) { + _createKanjiFrequency(details, dictionary, dictionaryAlias) { const {character, values} = details; const node = this._instantiate('kanji-frequency-item'); const tagLabel = this._querySelector(node, '.tag-label-content'); + const tag = this._querySelector(node, '.tag'); const frequencyValueList = this._querySelector(node, '.frequency-value-list'); - this._setTextContent(tagLabel, dictionary); + this._setTextContent(tagLabel, dictionaryAlias); this._populateFrequencyValueList(frequencyValueList, values); node.dataset.character = character; node.dataset.dictionary = dictionary; node.dataset.details = dictionary; + tag.dataset.details = dictionary; return node; } diff --git a/ext/js/dom/dom-data-binder.js b/ext/js/dom/dom-data-binder.js index 586e586911..4ca3aded97 100644 --- a/ext/js/dom/dom-data-binder.js +++ b/ext/js/dom/dom-data-binder.js @@ -174,18 +174,20 @@ export class DOMDataBinder { _createObserver(element) { const metadata = this._createElementMetadata(element); if (typeof metadata === 'undefined') { return void 0; } + const type = this._getNormalizedElementType(element); + const eventType = 'change'; /** @type {import('dom-data-binder').ElementObserver} */ const observer = { element, - type: this._getNormalizedElementType(element), + type, value: null, hasValue: false, + eventType, onChange: null, metadata, }; observer.onChange = this._onElementChange.bind(this, observer); - - element.addEventListener('change', observer.onChange, false); + element.addEventListener(eventType, observer.onChange, false); void this._updateTasks.enqueue(observer, {all: false}); @@ -198,7 +200,7 @@ export class DOMDataBinder { */ _removeObserver(element, observer) { if (observer.onChange === null) { return; } - element.removeEventListener('change', observer.onChange, false); + element.removeEventListener(observer.eventType, observer.onChange, false); observer.onChange = null; } @@ -207,9 +209,10 @@ export class DOMDataBinder { * @param {import('dom-data-binder').ElementObserver} observer */ _onObserverChildrenUpdated(element, observer) { - if (observer.hasValue) { - this._setElementValue(element, observer.value); + if (!observer.hasValue) { + return; } + this._setElementValue(element, observer.value); } /** @@ -239,6 +242,9 @@ export class DOMDataBinder { case 'select': /** @type {HTMLInputElement|HTMLTextAreaElement|HTMLSelectElement} */ (element).value = typeof value === 'string' ? value : `${value}`; break; + case 'element': + element.textContent = typeof value === 'string' ? value : `${value}`; + break; } /** @type {number|string|boolean} */ @@ -274,8 +280,9 @@ export class DOMDataBinder { return /** @type {HTMLTextAreaElement} */ (element).value; case 'select': return /** @type {HTMLSelectElement} */ (element).value; + case 'element': + return element.textContent; } - return null; } /** @@ -302,6 +309,6 @@ export class DOMDataBinder { case 'SELECT': return 'select'; } - return null; + return 'element'; } } diff --git a/ext/js/language/translator.js b/ext/js/language/translator.js index 6f641b80fd..21719da3d1 100644 --- a/ext/js/language/translator.js +++ b/ext/js/language/translator.js @@ -155,7 +155,8 @@ export class Translator { const tagAggregator = new TranslatorTagAggregator(); for (const {character, onyomi, kunyomi, tags, definitions, stats, dictionary} of databaseEntries) { const expandedStats = await this._expandKanjiStats(stats, dictionary); - const dictionaryEntry = this._createKanjiDictionaryEntry(character, dictionary, onyomi, kunyomi, expandedStats, definitions); + const dictionaryAlias = this._getDictionaryAlias(dictionary, enabledDictionaryMap); + const dictionaryEntry = this._createKanjiDictionaryEntry(character, dictionary, dictionaryAlias, onyomi, kunyomi, expandedStats, definitions); dictionaryEntries.push(dictionaryEntry); tagAggregator.addTags(dictionaryEntry.tags, dictionary, tags); } @@ -1199,6 +1200,7 @@ export class Translator { const metas = await this._database.findTermMetaBulk(headwordMapKeys, enabledDictionaryMap); for (const {mode, data, dictionary, index} of metas) { const {index: dictionaryIndex, priority: dictionaryPriority} = this._getDictionaryOrder(dictionary, enabledDictionaryMap); + const dictionaryAlias = this._getDictionaryAlias(dictionary, enabledDictionaryMap); const map2 = headwordReadingMaps[index]; for (const [reading, targets] of map2.entries()) { switch (mode) { @@ -1214,6 +1216,7 @@ export class Translator { headwordIndex, dictionary, dictionaryIndex, + dictionaryAlias, dictionaryPriority, hasReading, frequencyValue, @@ -1250,6 +1253,7 @@ export class Translator { headwordIndex, dictionary, dictionaryIndex, + dictionaryAlias, dictionaryPriority, pitches, )); @@ -1279,6 +1283,7 @@ export class Translator { headwordIndex, dictionary, dictionaryIndex, + dictionaryAlias, dictionaryPriority, phoneticTranscriptions, )); @@ -1302,6 +1307,7 @@ export class Translator { const metas = await this._database.findKanjiMetaBulk(kanjiList, enabledDictionaryMap); for (const {character, mode, data, dictionary, index} of metas) { const {index: dictionaryIndex, priority: dictionaryPriority} = this._getDictionaryOrder(dictionary, enabledDictionaryMap); + const dictionaryAlias = this._getDictionaryAlias(dictionary, enabledDictionaryMap); switch (mode) { case 'freq': { @@ -1311,6 +1317,7 @@ export class Translator { frequencies.length, dictionary, dictionaryIndex, + dictionaryAlias, dictionaryPriority, character, frequency, @@ -1449,6 +1456,16 @@ export class Translator { return {index, priority}; } + /** + * @param {string} dictionary + * @param {import('translation').TermEnabledDictionaryMap|import('translation').KanjiEnabledDictionaryMap} enabledDictionaryMap + * @returns {string} + */ + _getDictionaryAlias(dictionary, enabledDictionaryMap) { + const info = enabledDictionaryMap.get(dictionary); + return info?.alias || dictionary; + } + /** * @param {unknown[]} array * @returns {string} @@ -1491,6 +1508,7 @@ export class Translator { * @param {number} index * @param {string} dictionary * @param {number} dictionaryIndex + * @param {string} dictionaryAlias * @param {number} dictionaryPriority * @param {string} character * @param {number} frequency @@ -1498,24 +1516,26 @@ export class Translator { * @param {boolean} displayValueParsed * @returns {import('dictionary').KanjiFrequency} */ - _createKanjiFrequency(index, dictionary, dictionaryIndex, dictionaryPriority, character, frequency, displayValue, displayValueParsed) { - return {index, dictionary, dictionaryIndex, dictionaryPriority, character, frequency, displayValue, displayValueParsed}; + _createKanjiFrequency(index, dictionary, dictionaryIndex, dictionaryAlias, dictionaryPriority, character, frequency, displayValue, displayValueParsed) { + return {index, dictionary, dictionaryIndex, dictionaryAlias, dictionaryPriority, character, frequency, displayValue, displayValueParsed}; } /** * @param {string} character * @param {string} dictionary + * @param {string} dictionaryAlias * @param {string[]} onyomi * @param {string[]} kunyomi * @param {import('dictionary').KanjiStatGroups} stats * @param {string[]} definitions * @returns {import('dictionary').KanjiDictionaryEntry} */ - _createKanjiDictionaryEntry(character, dictionary, onyomi, kunyomi, stats, definitions) { + _createKanjiDictionaryEntry(character, dictionary, dictionaryAlias, onyomi, kunyomi, stats, definitions) { return { type: 'kanji', character, dictionary, + dictionaryAlias, onyomi, kunyomi, tags: [], @@ -1580,6 +1600,7 @@ export class Translator { * @param {number[]} headwordIndices * @param {string} dictionary * @param {number} dictionaryIndex + * @param {string} dictionaryAlias * @param {number} dictionaryPriority * @param {number} id * @param {number} score @@ -1589,12 +1610,13 @@ export class Translator { * @param {import('dictionary-data').TermGlossaryContent[]} entries * @returns {import('dictionary').TermDefinition} */ - _createTermDefinition(index, headwordIndices, dictionary, dictionaryIndex, dictionaryPriority, id, score, sequences, isPrimary, tags, entries) { + _createTermDefinition(index, headwordIndices, dictionary, dictionaryIndex, dictionaryAlias, dictionaryPriority, id, score, sequences, isPrimary, tags, entries) { return { index, headwordIndices, dictionary, dictionaryIndex, + dictionaryAlias, dictionaryPriority, id, score, @@ -1611,12 +1633,13 @@ export class Translator { * @param {number} headwordIndex * @param {string} dictionary * @param {number} dictionaryIndex + * @param {string} dictionaryAlias * @param {number} dictionaryPriority * @param {import('dictionary').Pronunciation[]} pronunciations * @returns {import('dictionary').TermPronunciation} */ - _createTermPronunciation(index, headwordIndex, dictionary, dictionaryIndex, dictionaryPriority, pronunciations) { - return {index, headwordIndex, dictionary, dictionaryIndex, dictionaryPriority, pronunciations}; + _createTermPronunciation(index, headwordIndex, dictionary, dictionaryIndex, dictionaryAlias, dictionaryPriority, pronunciations) { + return {index, headwordIndex, dictionary, dictionaryIndex, dictionaryAlias, dictionaryPriority, pronunciations}; } /** @@ -1624,6 +1647,7 @@ export class Translator { * @param {number} headwordIndex * @param {string} dictionary * @param {number} dictionaryIndex + * @param {string} dictionaryAlias * @param {number} dictionaryPriority * @param {boolean} hasReading * @param {number} frequency @@ -1631,8 +1655,8 @@ export class Translator { * @param {boolean} displayValueParsed * @returns {import('dictionary').TermFrequency} */ - _createTermFrequency(index, headwordIndex, dictionary, dictionaryIndex, dictionaryPriority, hasReading, frequency, displayValue, displayValueParsed) { - return {index, headwordIndex, dictionary, dictionaryIndex, dictionaryPriority, hasReading, frequency, displayValue, displayValueParsed}; + _createTermFrequency(index, headwordIndex, dictionary, dictionaryIndex, dictionaryAlias, dictionaryPriority, hasReading, frequency, displayValue, displayValueParsed) { + return {index, headwordIndex, dictionary, dictionaryIndex, dictionaryAlias, dictionaryPriority, hasReading, frequency, displayValue, displayValueParsed}; } /** @@ -1641,6 +1665,7 @@ export class Translator { * @param {import('translation-internal').InflectionRuleChainCandidate[]} inflectionRuleChainCandidates * @param {number} score * @param {number} dictionaryIndex + * @param {string} dictionaryAlias * @param {number} dictionaryPriority * @param {number} sourceTermExactMatchCount * @param {number} maxOriginalTextLength @@ -1648,7 +1673,7 @@ export class Translator { * @param {import('dictionary').TermDefinition[]} definitions * @returns {import('translation-internal').TermDictionaryEntry} */ - _createTermDictionaryEntry(isPrimary, textProcessorRuleChainCandidates, inflectionRuleChainCandidates, score, dictionaryIndex, dictionaryPriority, sourceTermExactMatchCount, maxOriginalTextLength, headwords, definitions) { + _createTermDictionaryEntry(isPrimary, textProcessorRuleChainCandidates, inflectionRuleChainCandidates, score, dictionaryIndex, dictionaryAlias, dictionaryPriority, sourceTermExactMatchCount, maxOriginalTextLength, headwords, definitions) { return { type: 'term', isPrimary, @@ -1657,6 +1682,7 @@ export class Translator { score, frequencyOrder: 0, dictionaryIndex, + dictionaryAlias, dictionaryPriority, sourceTermExactMatchCount, maxOriginalTextLength, @@ -1698,6 +1724,7 @@ export class Translator { const contentDefinitions = /** @type {import('dictionary-data').TermGlossaryContent[]} */ (definitions); const reading = (rawReading.length > 0 ? rawReading : term); const {index: dictionaryIndex, priority: dictionaryPriority} = this._getDictionaryOrder(dictionary, enabledDictionaryMap); + const dictionaryAlias = this._getDictionaryAlias(dictionary, enabledDictionaryMap); const sourceTermExactMatchCount = (isPrimary && deinflectedText === term ? 1 : 0); const source = this._createSource(originalText, transformedText, deinflectedText, matchType, matchSource, isPrimary); const maxOriginalTextLength = originalText.length; @@ -1717,11 +1744,12 @@ export class Translator { inflectionRuleChainCandidates, score, dictionaryIndex, + dictionaryAlias, dictionaryPriority, sourceTermExactMatchCount, maxOriginalTextLength, [this._createTermHeadword(0, term, reading, [source], headwordTagGroups, rules)], - [this._createTermDefinition(0, [0], dictionary, dictionaryIndex, dictionaryPriority, id, score, [sequence], isPrimary, definitionTagGroups, contentDefinitions)], + [this._createTermDefinition(0, [0], dictionary, dictionaryIndex, dictionaryAlias, dictionaryPriority, id, score, [sequence], isPrimary, definitionTagGroups, contentDefinitions)], ); } @@ -1751,6 +1779,7 @@ export class Translator { let score = Number.MIN_SAFE_INTEGER; let dictionaryIndex = Number.MAX_SAFE_INTEGER; let dictionaryPriority = Number.MIN_SAFE_INTEGER; + const dictionaryAlias = ''; let maxOriginalTextLength = 0; let isPrimary = false; /** @type {import('dictionary').TermDefinition[]} */ @@ -1806,6 +1835,7 @@ export class Translator { inflections !== null ? inflections : [], score, dictionaryIndex, + dictionaryAlias, dictionaryPriority, sourceTermExactMatchCount, maxOriginalTextLength, @@ -1921,12 +1951,12 @@ export class Translator { * @param {number[]} headwordIndexMap */ _addTermDefinitionsFast(definitions, newDefinitions, headwordIndexMap) { - for (const {headwordIndices, dictionary, dictionaryIndex, dictionaryPriority, sequences, id, score, isPrimary, tags, entries} of newDefinitions) { + for (const {headwordIndices, dictionary, dictionaryIndex, dictionaryAlias, dictionaryPriority, sequences, id, score, isPrimary, tags, entries} of newDefinitions) { const headwordIndicesNew = []; for (const headwordIndex of headwordIndices) { headwordIndicesNew.push(headwordIndexMap[headwordIndex]); } - definitions.push(this._createTermDefinition(definitions.length, headwordIndicesNew, dictionary, dictionaryIndex, dictionaryPriority, id, score, sequences, isPrimary, tags, entries)); + definitions.push(this._createTermDefinition(definitions.length, headwordIndicesNew, dictionary, dictionaryIndex, dictionaryAlias, dictionaryPriority, id, score, sequences, isPrimary, tags, entries)); } } @@ -1938,11 +1968,11 @@ export class Translator { * @param {TranslatorTagAggregator} tagAggregator */ _addTermDefinitions(definitions, definitionsMap, newDefinitions, headwordIndexMap, tagAggregator) { - for (const {headwordIndices, dictionary, dictionaryIndex, dictionaryPriority, sequences, id, score, isPrimary, tags, entries} of newDefinitions) { + for (const {headwordIndices, dictionary, dictionaryIndex, dictionaryAlias, dictionaryPriority, sequences, id, score, isPrimary, tags, entries} of newDefinitions) { const key = this._createMapKey([dictionary, ...entries]); let definition = definitionsMap.get(key); if (typeof definition === 'undefined') { - definition = this._createTermDefinition(definitions.length, [], dictionary, dictionaryIndex, dictionaryPriority, id, score, [...sequences], isPrimary, [], [...entries]); + definition = this._createTermDefinition(definitions.length, [], dictionary, dictionaryIndex, dictionaryAlias, dictionaryPriority, id, score, [...sequences], isPrimary, [], [...entries]); definitions.push(definition); definitionsMap.set(key, definition); } else { diff --git a/ext/js/pages/settings/dictionary-controller.js b/ext/js/pages/settings/dictionary-controller.js index 516bd9fe1d..5706caf37e 100644 --- a/ext/js/pages/settings/dictionary-controller.js +++ b/ext/js/pages/settings/dictionary-controller.js @@ -63,7 +63,7 @@ class DictionaryEntry { /** @type {HTMLButtonElement} */ this._updatesAvailable = querySelectorNotNull(fragment, '.dictionary-update-available'); /** @type {HTMLElement} */ - this._titleNode = querySelectorNotNull(fragment, '.dictionary-title'); + this._aliasNode = querySelectorNotNull(fragment, '.dictionary-alias'); /** @type {HTMLElement} */ this._versionNode = querySelectorNotNull(fragment, '.dictionary-revision'); /** @type {HTMLElement} */ @@ -79,9 +79,9 @@ class DictionaryEntry { prepare() { // const index = this._index; - const {title, revision, version} = this._dictionaryInfo; + const {revision, version} = this._dictionaryInfo; - this._titleNode.textContent = title; + this._aliasNode.dataset.setting = `dictionaries[${index}].alias`; this._versionNode.textContent = `rev.${revision}`; this._outdatedButton.hidden = (version >= 3); this._priorityInput.dataset.setting = `dictionaries[${index}].priority`; @@ -177,9 +177,20 @@ class DictionaryEntry { case 'moveTo': this._showMoveToModal(); break; + case 'rename': + this._showRenameModal(); + break; } } + /** + * @param {string} alias + */ + updateAliasSettings(alias) { + this._aliasNode.textContent = alias; + this._aliasNode.dispatchEvent(new CustomEvent('change', {bubbles: true})); + } + /** * @param {import('dom-data-binder').SettingChangedEvent} e */ @@ -344,6 +355,23 @@ class DictionaryEntry { modal.setVisible(true); } + + /** */ + _showRenameModal() { + const {title} = this._dictionaryInfo; + const modal = this._dictionaryController.modalController.getModal('dictionary-set-alias'); + if (modal === null) { return; } + /** @type {HTMLInputElement} */ + const input = querySelectorNotNull(modal.node, '#dictionary-alias-input'); + /** @type {HTMLElement} */ + const titleNode = querySelectorNotNull(modal.node, '.dictionary-title'); + + modal.node.dataset.index = `${this._index}`; + titleNode.textContent = title; + input.value = this._aliasNode.textContent || title; + + modal.setVisible(true); + } } class DictionaryExtraInfo { @@ -503,6 +531,11 @@ export class DictionaryController { /** @type {HTMLButtonElement} */ const dictionaryMoveButton = querySelectorNotNull(document, '#dictionary-move-button'); + /** @type {HTMLButtonElement} */ + const dictiontaryResetAliasButton = querySelectorNotNull(document, '#dictionary-reset-alias-button'); + /** @type {HTMLButtonElement} */ + const dictionarySetAliasButton = querySelectorNotNull(document, '#dictionary-set-alias-button'); + this._settingsController.application.on('databaseUpdated', this._onDatabaseUpdated.bind(this)); this._settingsController.on('optionsChanged', this._onOptionsChanged.bind(this)); this._allCheckbox.addEventListener('change', this._onAllCheckboxChange.bind(this), false); @@ -510,6 +543,10 @@ export class DictionaryController { dictionaryUpdateButton.addEventListener('click', this._onDictionaryConfirmUpdate.bind(this), false); dictionaryMoveButton.addEventListener('click', this._onDictionaryMoveButtonClick.bind(this), false); + + dictionarySetAliasButton.addEventListener('click', this._onDictionarySetAliasButtonClick.bind(this), false); + dictiontaryResetAliasButton.addEventListener('click', this._onDictionaryResetAliasButtonClick.bind(this), false); + if (this._checkUpdatesButton !== null) { this._checkUpdatesButton.addEventListener('click', this._onCheckUpdatesButtonClick.bind(this), false); } @@ -612,6 +649,7 @@ export class DictionaryController { static createDefaultDictionarySettings(name, enabled, styles) { return { name, + alias: name, priority: 0, enabled, allowSecondarySearches: false, @@ -864,6 +902,33 @@ export class DictionaryController { void this.moveDictionaryOptions(indexNumber, target); } + /** */ + _onDictionaryResetAliasButtonClick() { + const modal = /** @type {import('./modal.js').Modal} */ (this._modalController.getModal('dictionary-set-alias')); + const index = modal.node.dataset.index ?? ''; + const indexNumber = Number.parseInt(index, 10); + if (Number.isNaN(indexNumber)) { return; } + + /** @type {HTMLInputElement} */ + const input = querySelectorNotNull(modal.node, '#dictionary-alias-input'); + input.value = this._dictionaryEntries[indexNumber].dictionaryTitle; + } + + /** */ + _onDictionarySetAliasButtonClick() { + const modal = /** @type {import('./modal.js').Modal} */ (this._modalController.getModal('dictionary-set-alias')); + const index = modal.node.dataset.index ?? ''; + const indexNumber = Number.parseInt(index, 10); + if (Number.isNaN(indexNumber)) { return; } + + /** @type {HTMLInputElement} */ + const input = querySelectorNotNull(modal.node, '#dictionary-alias-input'); + const inputValue = input.value.trim(); + if (inputValue) { + this._dictionaryEntries[indexNumber].updateAliasSettings(inputValue); + } + } + /** * @param {import('dictionary-importer').Summary[]} dictionaries */ diff --git a/ext/settings.html b/ext/settings.html index 83f4d4874a..1774faad17 100644 --- a/ext/settings.html +++ b/ext/settings.html @@ -2820,6 +2820,20 @@
or click here to upload
+ + +