From b6c03233ba8c60cf99e7a2675a1c1ac01d6bf1ca Mon Sep 17 00:00:00 2001 From: IceSandwich Date: Wed, 16 Jul 2025 14:20:51 +0800 Subject: [PATCH] fix the behavior of matching words --- web/js/autocomplete.js | 17 ++++++++++++----- web/js/data.js | 27 ++++++++++++++++----------- 2 files changed, 28 insertions(+), 16 deletions(-) diff --git a/web/js/autocomplete.js b/web/js/autocomplete.js index e989538..8b0817a 100644 --- a/web/js/autocomplete.js +++ b/web/js/autocomplete.js @@ -105,7 +105,7 @@ function searchCompletionCandidates(textareaElement) { for (const source of sources) { if (settingValues.useFastSearch && autoCompleteData[source].flexSearchIndex) { const searchResults = autoCompleteData[source].flexSearchIndex.search(partialTag, { - limit: settingValues.maxSuggestions, + limit: settingValues.maxSuggestions * 10, suggest: false, cache: true, }); @@ -114,8 +114,13 @@ function searchCompletionCandidates(textareaElement) { const duration = endTime - startTime; console.debug(`[Autocomplete-Plus] Fast Search for "${partialTag}" in ${source} took ${duration.toFixed(2)}ms. Found ${searchResults.length} candidates.`); } + let result = []; - searchResults.sort((a, b) => { + result = searchResults.map((index) => { + return autoCompleteData[source].flexSearchMapping[index]; + }); + result = [...new Set(result)]; + result = result.sort((a, b) => { const aTag = autoCompleteData[source].sortedTags[a]; const bTag = autoCompleteData[source].sortedTags[b]; if (matchWord(bTag.tag, queryVariations).isExactMatch || @@ -126,9 +131,11 @@ function searchCompletionCandidates(textareaElement) { (aTag.alias && aTag.alias.some(alias => matchWord(alias, queryVariations).isExactMatch))) { return -999999999999; } - return bTag.count - aTag.count; - }).forEach(seachResult => { - result.push(autoCompleteData[source].sortedTags[seachResult]); + return a - b; + }); + result = result.slice(0, Math.min(result.length, settingValues.maxSuggestions)); + result = result.map((index) => { + return autoCompleteData[source].sortedTags[index]; }); return result; } else { diff --git a/web/js/data.js b/web/js/data.js index 91b97ab..6f26a4d 100644 --- a/web/js/data.js +++ b/web/js/data.js @@ -67,6 +67,9 @@ class AutocompleteData { /** @type {Index} */ this.flexSearchIndex = null; + /** @type {number[]} */ + this.flexSearchMapping = []; + /** @type {TagData[]} */ this.sortedTags = []; @@ -197,9 +200,12 @@ async function loadTags(csvUrl, siteName) { */ async function buildFlexSearchIndex(siteName) { try { + if (autoCompleteData[siteName].sortedTags.length === 0) { + return; + } + const index = new Index({ - tokenize: "forward", - // encoder: Charset.CJK, // FIXME: English search doesn't work properly when using CJK + tokenize: "bidirectional", }); let startIdx = 0; @@ -209,15 +215,14 @@ async function buildFlexSearchIndex(siteName) { const end = Math.min(startIdx + chunkSize, autoCompleteData[siteName].sortedTags.length); for (; startIdx < end; startIdx++) { const tagData = autoCompleteData[siteName].sortedTags[startIdx]; - let allTags = []; - allTags.push(tagData.tag); - if (tagData.alias && Array.isArray(tagData.alias)) { - tagData.alias.forEach(alias => { - allTags.push(alias); - }); - } - allTags = [...new Set(allTags)]; - index.add(startIdx, allTags.join(',')); + + index.add(autoCompleteData[siteName].flexSearchMapping.length, tagData.tag); + autoCompleteData[siteName].flexSearchMapping.push(startIdx); + + tagData.alias.forEach(alias => { + index.add(autoCompleteData[siteName].flexSearchMapping.length, alias); + autoCompleteData[siteName].flexSearchMapping.push(startIdx); + }) } if (startIdx < autoCompleteData[siteName].sortedTags.length) {