mirror of
https://github.com/DominikDoom/a1111-sd-webui-tagcomplete.git
synced 2026-01-26 11:09:54 +00:00
Some refactoring, WIP translation search
Translation are still a bit buggy, e.g. listing duplicates & no english tag shown yet.
This commit is contained in:
@@ -20,6 +20,15 @@ var lycos = [];
|
||||
var modelKeywordDict = new Map();
|
||||
var chants = [];
|
||||
var styleNames = [];
|
||||
// uFuzzy haystacks
|
||||
var tacHaystacks = {
|
||||
"tag": [],
|
||||
"extra": [],
|
||||
"tagAlias": [],
|
||||
"extraAlias": [],
|
||||
"translationKeys": [],
|
||||
"translationValues": []
|
||||
}
|
||||
|
||||
// Selected model info for black/whitelisting
|
||||
var currentModelHash = "";
|
||||
|
||||
@@ -201,4 +201,50 @@ class TacFuzzy {
|
||||
|
||||
return highlightedString;
|
||||
}
|
||||
|
||||
// Utility to construct results for a given haystack
|
||||
/**
|
||||
*
|
||||
* @param {int[][]} pairs - Size two array of [index, orderIndex] for the fuzzy results
|
||||
* @param {"base"|"alias"} sourceName - Whether the match matches the base text or an alias
|
||||
* @param {"tag"|"extra"} targetName - The type of the target (i.e. which haystack to use for the result data)
|
||||
* @param {Set<Number>} indexSet - Set of indices to avoid duplicates for cases where tag and alias would both match
|
||||
* @param {AutocompleteResult[]} output - The list to append the results to
|
||||
*/
|
||||
static assignResults = (pairs, sourceName, targetName, indexSet, output) => {
|
||||
pairs.forEach(pair => {
|
||||
const idx = pair[0];
|
||||
const orderIdx = pair[1];
|
||||
if (!indexSet.has(idx)) {
|
||||
let target, resultType;
|
||||
switch (targetName) {
|
||||
case "tag":
|
||||
target = allTags[idx];
|
||||
resultType = ResultType.tag;
|
||||
break;
|
||||
case "extra":
|
||||
target = extras[idx];
|
||||
resultType = ResultType.extra;
|
||||
break;
|
||||
default:
|
||||
target = allTags[idx];
|
||||
resultType = ResultType.tag;
|
||||
}
|
||||
const result = new AutocompleteResult(target[0], resultType);
|
||||
result.highlightedText = TacFuzzy.toStr(orderIdx);
|
||||
result.matchSource = sourceName;
|
||||
|
||||
result.category = target[1];
|
||||
|
||||
if (targetName === "tag")
|
||||
result.count = target[2];
|
||||
else if (targetName === "extra")
|
||||
result.meta = target[2] || "Custom tag";
|
||||
|
||||
result.aliases = target[3];
|
||||
output.push(result);
|
||||
indexSet.add(idx);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -162,6 +162,14 @@ async function loadTags(c) {
|
||||
}
|
||||
}
|
||||
await loadExtraTags(c);
|
||||
|
||||
// Assign uFuzzy haystacks
|
||||
tacHaystacks.tag = allTags.map(x => x[0]);
|
||||
tacHaystacks.extra = extras.map(x => x[0]);
|
||||
tacHaystacks.tagAlias = allTags.map(x => x[3] || "");
|
||||
tacHaystacks.extraAlias = extras.map(e => e[3] || "");
|
||||
tacHaystacks.translationKeys = Array.from(translations.keys());
|
||||
tacHaystacks.translationValues = Array.from(translations.values());
|
||||
}
|
||||
|
||||
async function loadExtraTags(c) {
|
||||
@@ -1159,144 +1167,70 @@ async function autocomplete(textArea, prompt, fixedTag = null) {
|
||||
});
|
||||
*/
|
||||
|
||||
//const fuzResult = TacFuzzy.search(haystack, tagword)
|
||||
let fuzMatchSet = new Set();
|
||||
let extraFuzMatchSet = new Set();
|
||||
let tagIndexSet = new Set()
|
||||
let extraIndexSet = new Set();
|
||||
let translationIndexSet = new Set();
|
||||
let tagOut = [];
|
||||
let extraOut = [];
|
||||
let transFuzMatchSet = new Set();
|
||||
// Base text search
|
||||
TacFuzzy.assignResults(TacFuzzy.search(tacHaystacks.tag, tagword),"base", "tag", tagIndexSet, tagOut)
|
||||
TacFuzzy.assignResults(TacFuzzy.search(tacHaystacks.extra, tagword), "base", "extra", extraIndexSet, extraOut)
|
||||
// Alias search
|
||||
if (TAC_CFG.alias.searchByAlias) {
|
||||
TacFuzzy.assignResults(TacFuzzy.search(tacHaystacks.tagAlias, tagword), "alias", "tag", tagIndexSet, tagOut)
|
||||
TacFuzzy.assignResults(TacFuzzy.search(tacHaystacks.extraAlias, tagword), "alias", "extra", extraIndexSet, extraOut)
|
||||
}
|
||||
// Translation search
|
||||
if (TAC_CFG.translation.searchByTranslation) {
|
||||
// Translations need special treatment as they can belong to both tags and extras and need lookup based on their keys.
|
||||
// We also use unicode search here, slower but needed for non-latin translations.
|
||||
TacFuzzy.search(tacHaystacks.translationValues, tagword, true).forEach(pair => {
|
||||
const idx = pair[0];
|
||||
const orderIdx = pair[1];
|
||||
if (!translationIndexSet.has(idx)) {
|
||||
const translationKey = tacHaystacks.translationKeys[idx];
|
||||
|
||||
const tagBaseFuzResult = TacFuzzy.search(allTags.map(t => t[0] || ""), tagword)
|
||||
tagBaseFuzResult.forEach(pair => {
|
||||
const idx = pair[0];
|
||||
const orderIdx = pair[1];
|
||||
if (!fuzMatchSet.has(idx)) {
|
||||
const result = new AutocompleteResult(allTags[idx][0], ResultType.tag);
|
||||
result.highlightedText = TacFuzzy.toStr(orderIdx);
|
||||
result.matchSource = "base"
|
||||
// Placeholder to make sure we never access an index of null if no matching key was found
|
||||
const notFound = [null, null, null, null];
|
||||
|
||||
// Check if the translation belongs to a tag or its alias. Only search alias if no base text found.
|
||||
const translatedTagBase = allTags.find(t => t[0] === translationKey);
|
||||
const translatedTagAlias = !translatedTagBase
|
||||
? allTags.find(t => t[3]?.split(",").some(a => a === translationKey))
|
||||
: null;
|
||||
const translatedTag = translatedTagBase || translatedTagAlias || notFound; // Combined result for easier checks later
|
||||
// Check if the translation belongs to an extra or its alias. Only search alias if no base text found.
|
||||
const translatedExtraBase = extras.find(e => e[0] === translationKey);
|
||||
const translatedExtraAlias = !translatedExtraBase
|
||||
? extras.find(e => e[3]?.split(",").some(a => a === translationKey))
|
||||
: null;
|
||||
const translatedExtra = translatedExtraBase || translatedExtraAlias || notFound; // Combined result for easier checks later
|
||||
|
||||
result.category = allTags[idx][1];
|
||||
result.count = allTags[idx][2];
|
||||
result.aliases = allTags[idx][3];
|
||||
tagOut.push(result);
|
||||
fuzMatchSet.add(idx);
|
||||
}
|
||||
});
|
||||
const tagAliasFuzResult = TacFuzzy.search(allTags.map(t => t[3] || ""), tagword)
|
||||
tagAliasFuzResult.forEach(pair => {
|
||||
const idx = pair[0];
|
||||
const orderIdx = pair[1];
|
||||
if (!fuzMatchSet.has(idx)) {
|
||||
const result = new AutocompleteResult(allTags[idx][0], ResultType.tag)
|
||||
result.highlightedText = TacFuzzy.toStr(orderIdx);
|
||||
result.matchSource = "alias"
|
||||
const result = new AutocompleteResult(translatedTag[0] || translatedExtra[0], ResultType.tag)
|
||||
result.highlightedText = TacFuzzy.toStr(orderIdx);
|
||||
|
||||
result.category = allTags[idx][1];
|
||||
result.count = allTags[idx][2];
|
||||
result.aliases = allTags[idx][3];
|
||||
tagOut.push(result);
|
||||
fuzMatchSet.add(idx);
|
||||
}
|
||||
});
|
||||
const extraBaseFuzResult = TacFuzzy.search(extras.map(e => e[0] || ""), tagword)
|
||||
extraBaseFuzResult.forEach(pair => {
|
||||
const idx = pair[0];
|
||||
const orderIdx = pair[1];
|
||||
if (!extraFuzMatchSet.has(idx)) {
|
||||
const result = new AutocompleteResult(extras[idx][0], ResultType.extra)
|
||||
result.highlightedText = TacFuzzy.toStr(orderIdx);
|
||||
result.matchSource = "base"
|
||||
result.matchSource = (translatedTagBase || translatedExtraBase) ? "base" : "alias";
|
||||
result.category = translatedTag[1] || translatedExtra[1] || 0;
|
||||
|
||||
if (translatedTag[0])
|
||||
result.count = translatedTag[2] || 0;
|
||||
else if (translatedExtra[0])
|
||||
result.meta = translatedExtra[2] || "Custom tag";
|
||||
|
||||
result.category = extras[idx][1] || 0; // If no category is given, use 0 as the default
|
||||
result.meta = extras[idx][2] || "Custom tag";
|
||||
result.aliases = extras[idx][3] || "";
|
||||
extraOut.push(result);
|
||||
extraFuzMatchSet.add(idx);
|
||||
}
|
||||
});
|
||||
const extraAliasFuzResult = TacFuzzy.search(extras.map(e => e[3] || ""), tagword)
|
||||
extraAliasFuzResult.forEach(pair => {
|
||||
const idx = pair[0];
|
||||
const orderIdx = pair[1];
|
||||
if (!extraFuzMatchSet.has(idx)) {
|
||||
const result = new AutocompleteResult(extras[idx][0], ResultType.extra)
|
||||
result.highlightedText = TacFuzzy.toStr(orderIdx);
|
||||
result.matchSource = "alias"
|
||||
result.aliases = translatedTag[3] || translatedExtra[3] || "";
|
||||
|
||||
result.category = extras[idx][1] || 0; // If no category is given, use 0 as the default
|
||||
result.meta = extras[idx][2] || "Custom tag";
|
||||
result.aliases = extras[idx][3] || "";
|
||||
extraOut.push(result);
|
||||
extraFuzMatchSet.add(idx);
|
||||
}
|
||||
});
|
||||
const transFuzResult = TacFuzzy.search([...translations.keys()].filter(x => !!x), tagword, true) // Unicode search here, slower but needed for non-latin translations
|
||||
transFuzResult.forEach(pair => {
|
||||
const idx = pair[0];
|
||||
const orderIdx = pair[1];
|
||||
if (!transFuzMatchSet.has(idx)) {
|
||||
const translationKey = [...translations.keys()][idx];
|
||||
const tagForTranslation = allTags.find(t => t[0] === translationKey || t[3]?.split(",").some(a => a === translationKey));
|
||||
const extraForTranslation = extras.find(e => e[0] === translationKey || e[3]?.split(",").some(a => a === translationKey));
|
||||
|
||||
const result = new AutocompleteResult(tagForTranslation[0] || extraForTranslation[0], ResultType.tag)
|
||||
result.highlightedText = TacFuzzy.toStr(orderIdx);
|
||||
// TODO: translations can't differentiate between tag and alias here yet
|
||||
result.matchSource = "translation";
|
||||
|
||||
result.category = tagForTranslation[1] || extraForTranslation[1] || 0;
|
||||
|
||||
if (tagForTranslation)
|
||||
result.count = tagForTranslation[2] || 0;
|
||||
else if (extraForTranslation)
|
||||
result.meta = extraForTranslation[2] || "Custom tag";
|
||||
|
||||
result.aliases = tagForTranslation[3] || extraForTranslation[3] || "";
|
||||
|
||||
if (tagForTranslation) {
|
||||
tagOut.push(result);
|
||||
} else if (extraForTranslation) {
|
||||
extraOut.push(result);
|
||||
if (translatedTag[0]) {
|
||||
tagOut.push(result);
|
||||
} else if (translatedExtra[0]) {
|
||||
extraOut.push(result);
|
||||
}
|
||||
translationIndexSet.add(idx);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Append results for each set
|
||||
results = results.concat([...extraOut]).concat([...tagOut]);
|
||||
|
||||
/*
|
||||
for (let i = 0; i < fuzResult.haystackIndices.length; i++) {
|
||||
const idx = fuzResult.haystackIndices[i];
|
||||
const orderIdx = fuzResult.orderIndices[i];
|
||||
const tag = allTags[idx];
|
||||
|
||||
let result = new AutocompleteResult(tag[0], ResultType.tag)
|
||||
result.highlightedText = TacFuzzy.toStr(orderIdx)
|
||||
result.category = tag[1];
|
||||
result.count = tag[2];
|
||||
result.aliases = tag[3];
|
||||
results.push(result);
|
||||
}
|
||||
|
||||
// Add extras
|
||||
if (TAC_CFG.extra.extraFile) {
|
||||
let extraResults = [];
|
||||
|
||||
extras.filter(fil).forEach(e => {
|
||||
let result = new AutocompleteResult(e[0].trim(), ResultType.extra)
|
||||
result.category = e[1] || 0; // If no category is given, use 0 as the default
|
||||
result.meta = e[2] || "Custom tag";
|
||||
result.aliases = e[3] || "";
|
||||
extraResults.push(result);
|
||||
});
|
||||
|
||||
if (TAC_CFG.extra.addMode === "Insert before") {
|
||||
results = extraResults.concat(results);
|
||||
} else {
|
||||
results = results.concat(extraResults);
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
// Guard for empty results
|
||||
|
||||
Reference in New Issue
Block a user