diff options
| -rw-r--r-- | ext/bg/js/api.js | 29 | ||||
| -rw-r--r-- | ext/bg/js/backend.js | 2 | ||||
| -rw-r--r-- | ext/bg/js/database.js | 9 | ||||
| -rw-r--r-- | ext/bg/js/dictionary.js | 40 | ||||
| -rw-r--r-- | ext/bg/js/search.js | 9 | ||||
| -rw-r--r-- | ext/bg/js/translator.js | 96 | ||||
| -rw-r--r-- | ext/fg/js/api.js | 4 | ||||
| -rw-r--r-- | ext/fg/js/frontend.js | 2 | ||||
| -rw-r--r-- | ext/mixed/js/display.js | 2 | 
9 files changed, 103 insertions, 90 deletions
| diff --git a/ext/bg/js/api.js b/ext/bg/js/api.js index 9fed99a1..df73aa2a 100644 --- a/ext/bg/js/api.js +++ b/ext/bg/js/api.js @@ -72,33 +72,18 @@ async function apiOptionsSave(source) {      backend.onOptionsUpdated(source);  } -async function apiTermsFind(text, optionsContext) { +async function apiTermsFind(text, details, optionsContext) {      const options = await apiOptionsGet(optionsContext); -    const translator = utilBackend().translator; - -    const searcher = { -        'merge': translator.findTermsMerged, -        'split': translator.findTermsSplit, -        'group': translator.findTermsGrouped -    }[options.general.resultOutputMode].bind(translator); - -    const {definitions, length} = await searcher( -        text, -        dictEnabledSet(options), -        options.scanning.alphanumeric, -        options -    ); - -    return { -        length, -        definitions: definitions.slice(0, options.general.maxResults) -    }; +    const [definitions, length] = await utilBackend().translator.findTerms(text, details, options); +    definitions.splice(options.general.maxResults); +    return {length, definitions};  }  async function apiKanjiFind(text, optionsContext) {      const options = await apiOptionsGet(optionsContext); -    const definitions = await utilBackend().translator.findKanji(text, dictEnabledSet(options)); -    return definitions.slice(0, options.general.maxResults); +    const definitions = await utilBackend().translator.findKanji(text, options); +    definitions.splice(options.general.maxResults); +    return definitions;  }  async function apiDefinitionAdd(definition, mode, context, optionsContext) { diff --git a/ext/bg/js/backend.js b/ext/bg/js/backend.js index 71393467..efad153a 100644 --- a/ext/bg/js/backend.js +++ b/ext/bg/js/backend.js @@ -179,7 +179,7 @@ Backend.messageHandlers = {      optionsGet: ({optionsContext}) => apiOptionsGet(optionsContext),      optionsSet: ({changedOptions, optionsContext, source}) => apiOptionsSet(changedOptions, optionsContext, source),      kanjiFind: ({text, optionsContext}) => apiKanjiFind(text, optionsContext), -    termsFind: ({text, optionsContext}) => apiTermsFind(text, optionsContext), +    termsFind: ({text, details, optionsContext}) => apiTermsFind(text, details, optionsContext),      definitionAdd: ({definition, mode, context, optionsContext}) => apiDefinitionAdd(definition, mode, context, optionsContext),      definitionsAddable: ({definitions, modes, optionsContext}) => apiDefinitionsAddable(definitions, modes, optionsContext),      noteView: ({noteId}) => apiNoteView(noteId), diff --git a/ext/bg/js/database.js b/ext/bg/js/database.js index b6cf9063..9b560f78 100644 --- a/ext/bg/js/database.js +++ b/ext/bg/js/database.js @@ -130,7 +130,7 @@ class Database {          await Promise.all(promises);      } -    async findTermsBulk(termList, titles) { +    async findTermsBulk(termList, titles, wildcard) {          this.validate();          const promises = []; @@ -149,10 +149,11 @@ class Database {          const dbIndex2 = dbTerms.index('reading');          for (let i = 0; i < termList.length; ++i) { -            const only = IDBKeyRange.only(termList[i]); +            const term = termList[i]; +            const query = wildcard ? IDBKeyRange.bound(term, `${term}\uffff`, false, false) : IDBKeyRange.only(term);              promises.push( -                Database.getAll(dbIndex1, only, i, processRow), -                Database.getAll(dbIndex2, only, i, processRow) +                Database.getAll(dbIndex1, query, i, processRow), +                Database.getAll(dbIndex2, query, i, processRow)              );          } diff --git a/ext/bg/js/dictionary.js b/ext/bg/js/dictionary.js index a4cf34ed..9aa0af9c 100644 --- a/ext/bg/js/dictionary.js +++ b/ext/bg/js/dictionary.js @@ -55,39 +55,23 @@ function dictRowsSort(rows, options) {  function dictTermsSort(definitions, dictionaries=null) {      return definitions.sort((v1, v2) => { +        let i;          if (dictionaries !== null) { -            const p1 = (dictionaries[v1.dictionary] || {}).priority || 0; -            const p2 = (dictionaries[v2.dictionary] || {}).priority || 0; -            if (p1 > p2) { -                return -1; -            } else if (p1 < p2) { -                return 1; -            } +            i = ( +                ((dictionaries[v2.dictionary] || {}).priority || 0) - +                ((dictionaries[v1.dictionary] || {}).priority || 0) +            ); +            if (i !== 0) { return i; }          } -        const sl1 = v1.source.length; -        const sl2 = v2.source.length; -        if (sl1 > sl2) { -            return -1; -        } else if (sl1 < sl2) { -            return 1; -        } +        i = v2.source.length - v1.source.length; +        if (i !== 0) { return i; } -        const rl1 = v1.reasons.length; -        const rl2 = v2.reasons.length; -        if (rl1 < rl2) { -            return -1; -        } else if (rl1 > rl2) { -            return 1; -        } +        i = v2.reasons.length - v1.reasons.length; +        if (i !== 0) { return i; } -        const s1 = v1.score; -        const s2 = v2.score; -        if (s1 > s2) { -            return -1; -        } else if (s1 < s2) { -            return 1; -        } +        i = v2.score - v1.score; +        if (i !== 0) { return i; }          return v2.expression.toString().localeCompare(v1.expression.toString());      }); diff --git a/ext/bg/js/search.js b/ext/bg/js/search.js index dccc7da7..56316217 100644 --- a/ext/bg/js/search.js +++ b/ext/bg/js/search.js @@ -203,11 +203,18 @@ class DisplaySearch extends Display {      async onSearchQueryUpdated(query, animate) {          try { +            const details = {}; +            const match = /[\*\uff0a]+$/.exec(query); +            if (match !== null) { +                details.wildcard = true; +                query = query.substr(0, query.length - match[0].length); +            } +              const valid = (query.length > 0);              this.setIntroVisible(!valid, animate);              this.updateSearchButton();              if (valid) { -                const {definitions} = await apiTermsFind(query, this.optionsContext); +                const {definitions} = await apiTermsFind(query, details, this.optionsContext);                  this.setContentTerms(definitions, {                      focus: false,                      sentence: null, diff --git a/ext/bg/js/translator.js b/ext/bg/js/translator.js index ff1d24f3..583d6e31 100644 --- a/ext/bg/js/translator.js +++ b/ext/bg/js/translator.js @@ -47,22 +47,6 @@ class Translator {          await this.database.deleteDictionary(dictionaryName);      } -    async findTermsGrouped(text, dictionaries, alphanumeric, options) { -        const titles = Object.keys(dictionaries); -        const {length, definitions} = await this.findTerms(text, dictionaries, alphanumeric); - -        const definitionsGrouped = dictTermsGroup(definitions, dictionaries); -        await this.buildTermFrequencies(definitionsGrouped, titles); - -        if (options.general.compactTags) { -            for (const definition of definitionsGrouped) { -                dictTermsCompressTags(definition.definitions); -            } -        } - -        return {length, definitions: definitionsGrouped}; -    } -      async getSequencedDefinitions(definitions, mainDictionary) {          const definitionsBySequence = dictTermsMergeBySequence(definitions, mainDictionary);          const defaultDefinitions = definitionsBySequence['-1']; @@ -157,10 +141,41 @@ class Translator {          return result;      } -    async findTermsMerged(text, dictionaries, alphanumeric, options) { +    async findTerms(text, details, options) { +        switch (options.general.resultOutputMode) { +            case 'group': +                return await this.findTermsGrouped(text, details, options); +            case 'merge': +                return await this.findTermsMerged(text, details, options); +            case 'split': +                return await this.findTermsSplit(text, details, options); +            default: +                return [[], 0]; +        } +    } + +    async findTermsGrouped(text, details, options) { +        const dictionaries = dictEnabledSet(options); +        const titles = Object.keys(dictionaries); +        const [definitions, length] = await this.findTermsInternal(text, dictionaries, options.scanning.alphanumeric, details); + +        const definitionsGrouped = dictTermsGroup(definitions, dictionaries); +        await this.buildTermFrequencies(definitionsGrouped, titles); + +        if (options.general.compactTags) { +            for (const definition of definitionsGrouped) { +                dictTermsCompressTags(definition.definitions); +            } +        } + +        return [definitionsGrouped, length]; +    } + +    async findTermsMerged(text, details, options) { +        const dictionaries = dictEnabledSet(options);          const secondarySearchTitles = Object.keys(options.dictionaries).filter(dict => options.dictionaries[dict].allowSecondarySearches);          const titles = Object.keys(dictionaries); -        const {length, definitions} = await this.findTerms(text, dictionaries, alphanumeric); +        const [definitions, length] = await this.findTermsInternal(text, dictionaries, options.scanning.alphanumeric, details);          const {sequencedDefinitions, defaultDefinitions} = await this.getSequencedDefinitions(definitions, options.general.mainDictionary);          const definitionsMerged = [];          const mergedByTermIndices = new Set(); @@ -191,29 +206,33 @@ class Translator {              }          } -        return {length, definitions: dictTermsSort(definitionsMerged)}; +        return [dictTermsSort(definitionsMerged), length];      } -    async findTermsSplit(text, dictionaries, alphanumeric) { +    async findTermsSplit(text, details, options) { +        const dictionaries = dictEnabledSet(options);          const titles = Object.keys(dictionaries); -        const {length, definitions} = await this.findTerms(text, dictionaries, alphanumeric); +        const [definitions, length] = await this.findTermsInternal(text, dictionaries, options.scanning.alphanumeric, details);          await this.buildTermFrequencies(definitions, titles); -        return {length, definitions}; +        return [definitions, length];      } -    async findTerms(text, dictionaries, alphanumeric) { +    async findTermsInternal(text, dictionaries, alphanumeric, details) {          if (!alphanumeric && text.length > 0) {              const c = text[0];              if (!jpIsKana(c) && !jpIsKanji(c)) { -                return {length: 0, definitions: []}; +                return [[], 0];              }          } -        const textHiragana = jpKatakanaToHiragana(text);          const titles = Object.keys(dictionaries); -        const deinflections = await this.findTermDeinflections(text, textHiragana, titles); +        const deinflections = ( +            details.wildcard ? +            await this.findTermWildcard(text, titles) : +            await this.findTermDeinflections(text, titles) +        );          let definitions = [];          for (const deinflection of deinflections) { @@ -246,10 +265,26 @@ class Translator {              length = Math.max(length, definition.source.length);          } -        return {length, definitions}; +        return [definitions, length]; +    } + +    async findTermWildcard(text, titles) { +        const definitions = await this.database.findTermsBulk([text], titles, true); +        if (definitions.length === 0) { +            return []; +        } + +        return [{ +            source: text, +            term: text, +            rules: 0, +            definitions, +            reasons: [] +        }];      } -    async findTermDeinflections(text, text2, titles) { +    async findTermDeinflections(text, titles) { +        const text2 = jpKatakanaToHiragana(text);          const deinflections = (text === text2 ? this.getDeinflections(text) : this.getDeinflections2(text, text2));          if (deinflections.length === 0) { @@ -273,7 +308,7 @@ class Translator {              deinflectionArray.push(deinflection);          } -        const definitions = await this.database.findTermsBulk(uniqueDeinflectionTerms, titles); +        const definitions = await this.database.findTermsBulk(uniqueDeinflectionTerms, titles, false);          for (const definition of definitions) {              const definitionRules = Deinflector.rulesToRuleFlags(definition.rules); @@ -314,7 +349,8 @@ class Translator {          return deinflections;      } -    async findKanji(text, dictionaries) { +    async findKanji(text, options) { +        const dictionaries = dictEnabledSet(options);          const titles = Object.keys(dictionaries);          const kanjiUnique = {};          const kanjiList = []; diff --git a/ext/fg/js/api.js b/ext/fg/js/api.js index 54818702..945ba076 100644 --- a/ext/fg/js/api.js +++ b/ext/fg/js/api.js @@ -25,8 +25,8 @@ function apiOptionsSet(changedOptions, optionsContext, source) {      return utilInvoke('optionsSet', {changedOptions, optionsContext, source});  } -function apiTermsFind(text, optionsContext) { -    return utilInvoke('termsFind', {text, optionsContext}); +function apiTermsFind(text, details, optionsContext) { +    return utilInvoke('termsFind', {text, details, optionsContext});  }  function apiKanjiFind(text, optionsContext) { diff --git a/ext/fg/js/frontend.js b/ext/fg/js/frontend.js index 7c62b51b..6002dfcb 100644 --- a/ext/fg/js/frontend.js +++ b/ext/fg/js/frontend.js @@ -413,7 +413,7 @@ class Frontend {          const searchText = textSource.text();          if (searchText.length === 0) { return null; } -        const {definitions, length} = await apiTermsFind(searchText, this.getOptionsContext()); +        const {definitions, length} = await apiTermsFind(searchText, {}, this.getOptionsContext());          if (definitions.length === 0) { return null; }          textSource.setEndOffset(length); diff --git a/ext/mixed/js/display.js b/ext/mixed/js/display.js index 801011df..8ad3ee1b 100644 --- a/ext/mixed/js/display.js +++ b/ext/mixed/js/display.js @@ -112,7 +112,7 @@ class Display {              try {                  textSource.setEndOffset(this.options.scanning.length); -                ({definitions, length} = await apiTermsFind(textSource.text(), this.getOptionsContext())); +                ({definitions, length} = await apiTermsFind(textSource.text(), {}, this.getOptionsContext()));                  if (definitions.length === 0) {                      return false;                  } |