| | const styleColors = { |
| | "--results-bg": ["#0b0f19", "#ffffff"], |
| | "--results-border-color": ["#4b5563", "#e5e7eb"], |
| | "--results-border-width": ["1px", "1.5px"], |
| | "--results-bg-odd": ["#111827", "#f9fafb"], |
| | "--results-hover": ["#1f2937", "#f5f6f8"], |
| | "--results-selected": ["#374151", "#e5e7eb"], |
| | "--meta-text-color": ["#6b6f7b", "#a2a9b4"], |
| | "--embedding-v1-color": ["lightsteelblue", "#2b5797"], |
| | "--embedding-v2-color": ["skyblue", "#2d89ef"], |
| | } |
| | const browserVars = { |
| | "--results-overflow-y": { |
| | "firefox": "scroll", |
| | "other": "auto" |
| | } |
| | } |
| | |
| | const autocompleteCSS = ` |
| | #quicksettings [id^=setting_tac] { |
| | background-color: transparent; |
| | min-width: fit-content; |
| | align-self: center; |
| | } |
| | #quicksettings [id^=setting_tac] > label > span { |
| | margin-bottom: 0px; |
| | } |
| | .autocompleteResults { |
| | position: absolute; |
| | z-index: 999; |
| | max-width: calc(100% - 1.5rem); |
| | margin: 5px 0 0 0; |
| | background-color: var(--results-bg) !important; |
| | border: var(--results-border-width) solid var(--results-border-color) !important; |
| | border-radius: 12px !important; |
| | overflow-y: var(--results-overflow-y); |
| | overflow-x: hidden; |
| | word-break: break-word; |
| | } |
| | .autocompleteResultsList > li:nth-child(odd) { |
| | background-color: var(--results-bg-odd); |
| | } |
| | .autocompleteResultsList > li { |
| | list-style-type: none; |
| | padding: 10px; |
| | cursor: pointer; |
| | } |
| | .autocompleteResultsList > li:hover { |
| | background-color: var(--results-hover); |
| | } |
| | .autocompleteResultsList > li.selected { |
| | background-color: var(--results-selected); |
| | } |
| | .resultsFlexContainer { |
| | display: flex; |
| | } |
| | .acListItem { |
| | white-space: break-spaces; |
| | } |
| | .acMetaText { |
| | position: relative; |
| | flex-grow: 1; |
| | text-align: end; |
| | padding: 0 0 0 15px; |
| | white-space: nowrap; |
| | color: var(--meta-text-color); |
| | } |
| | .acWikiLink { |
| | padding: 0.5rem; |
| | margin: -0.5rem 0 -0.5rem -0.5rem; |
| | } |
| | .acWikiLink:hover { |
| | text-decoration: underline; |
| | } |
| | .acListItem.acEmbeddingV1 { |
| | color: var(--embedding-v1-color); |
| | } |
| | .acListItem.acEmbeddingV2 { |
| | color: var(--embedding-v2-color); |
| | } |
| | `; |
| |
|
| | async function loadTags(c) { |
| | |
| | if (allTags.length === 0 && c.tagFile && c.tagFile !== "None") { |
| | try { |
| | allTags = await loadCSV(`${tagBasePath}/${c.tagFile}`); |
| | } catch (e) { |
| | console.error("Error loading tags file: " + e); |
| | return; |
| | } |
| | } |
| | if (c.extra.extraFile && c.extra.extraFile !== "None") { |
| | try { |
| | extras = await loadCSV(`${tagBasePath}/${c.extra.extraFile}`); |
| | } catch (e) { |
| | console.error("Error loading extra file: " + e); |
| | return; |
| | } |
| | } |
| | } |
| |
|
| | async function loadTranslations(c) { |
| | if (c.translation.translationFile && c.translation.translationFile !== "None") { |
| | try { |
| | let tArray = await loadCSV(`${tagBasePath}/${c.translation.translationFile}`); |
| | tArray.forEach(t => { |
| | if (c.translation.oldFormat) |
| | translations.set(t[0], t[2]); |
| | else |
| | translations.set(t[0], t[1]); |
| | }); |
| | } catch (e) { |
| | console.error("Error loading translations file: " + e); |
| | return; |
| | } |
| | } |
| | } |
| |
|
| | async function syncOptions() { |
| | let newCFG = { |
| | |
| | tagFile: opts["tac_tagFile"], |
| | |
| | activeIn: { |
| | global: opts["tac_active"], |
| | txt2img: opts["tac_activeIn.txt2img"], |
| | img2img: opts["tac_activeIn.img2img"], |
| | negativePrompts: opts["tac_activeIn.negativePrompts"], |
| | thirdParty: opts["tac_activeIn.thirdParty"], |
| | modelList: opts["tac_activeIn.modelList"], |
| | modelListMode: opts["tac_activeIn.modelListMode"] |
| | }, |
| | |
| | slidingPopup: opts["tac_slidingPopup"], |
| | maxResults: opts["tac_maxResults"], |
| | showAllResults: opts["tac_showAllResults"], |
| | resultStepLength: opts["tac_resultStepLength"], |
| | delayTime: opts["tac_delayTime"], |
| | useWildcards: opts["tac_useWildcards"], |
| | useEmbeddings: opts["tac_useEmbeddings"], |
| | useHypernetworks: opts["tac_useHypernetworks"], |
| | useLoras: opts["tac_useLoras"], |
| | useLycos: opts["tac_useLycos"], |
| | showWikiLinks: opts["tac_showWikiLinks"], |
| | |
| | replaceUnderscores: opts["tac_replaceUnderscores"], |
| | escapeParentheses: opts["tac_escapeParentheses"], |
| | appendComma: opts["tac_appendComma"], |
| | |
| | alias: { |
| | searchByAlias: opts["tac_alias.searchByAlias"], |
| | onlyShowAlias: opts["tac_alias.onlyShowAlias"] |
| | }, |
| | |
| | translation: { |
| | translationFile: opts["tac_translation.translationFile"], |
| | oldFormat: opts["tac_translation.oldFormat"], |
| | searchByTranslation: opts["tac_translation.searchByTranslation"], |
| | }, |
| | |
| | extra: { |
| | extraFile: opts["tac_extra.extraFile"], |
| | addMode: opts["tac_extra.addMode"] |
| | }, |
| | |
| | extraNetworksDefaultMultiplier: opts["extra_networks_default_multiplier"], |
| | extraNetworksSeparator: opts["extra_networks_add_text_separator"], |
| | |
| | keymap: JSON.parse(opts["tac_keymap"]), |
| | colorMap: JSON.parse(opts["tac_colormap"]) |
| | } |
| | if (newCFG.alias.onlyShowAlias) { |
| | newCFG.alias.searchByAlias = true; |
| | } |
| |
|
| | |
| | if (!CFG || newCFG.tagFile !== CFG.tagFile || newCFG.extra.extraFile !== CFG.extra.extraFile) { |
| | allTags = []; |
| | await loadTags(newCFG); |
| | } |
| | |
| | if (!CFG || newCFG.translation.translationFile !== CFG.translation.translationFile) { |
| | translations.clear(); |
| | await loadTranslations(newCFG); |
| | } |
| |
|
| | |
| | if (CFG && newCFG.maxResults !== CFG.maxResults) { |
| | gradioApp().querySelectorAll(".autocompleteResults").forEach(r => { |
| | r.style.maxHeight = `${newCFG.maxResults * 50}px`; |
| | }); |
| | } |
| |
|
| | |
| | CFG = newCFG; |
| |
|
| | |
| | await processQueue(QUEUE_AFTER_CONFIG_CHANGE, null); |
| | } |
| |
|
| | |
| | function createResultsDiv(textArea) { |
| | let resultsDiv = document.createElement("div"); |
| | let resultsList = document.createElement("ul"); |
| |
|
| | let textAreaId = getTextAreaIdentifier(textArea); |
| | let typeClass = textAreaId.replaceAll(".", " "); |
| |
|
| | resultsDiv.style.maxHeight = `${CFG.maxResults * 50}px`; |
| | resultsDiv.setAttribute("class", `autocompleteResults ${typeClass} notranslate`); |
| | resultsDiv.setAttribute("translate", "no"); |
| | resultsList.setAttribute("class", "autocompleteResultsList"); |
| | resultsDiv.appendChild(resultsList); |
| |
|
| | return resultsDiv; |
| | } |
| |
|
| | |
| | function isVisible(textArea) { |
| | let textAreaId = getTextAreaIdentifier(textArea); |
| | let resultsDiv = gradioApp().querySelector('.autocompleteResults' + textAreaId); |
| | return resultsDiv.style.display === "block"; |
| | } |
| | function showResults(textArea) { |
| | let textAreaId = getTextAreaIdentifier(textArea); |
| | let resultsDiv = gradioApp().querySelector('.autocompleteResults' + textAreaId); |
| | resultsDiv.style.display = "block"; |
| |
|
| | if (CFG.slidingPopup) { |
| | let caretPosition = getCaretCoordinates(textArea, textArea.selectionEnd).left; |
| | let offset = Math.min(textArea.offsetLeft - textArea.scrollLeft + caretPosition, textArea.offsetWidth - resultsDiv.offsetWidth); |
| | |
| | resultsDiv.style.left = `${offset}px`; |
| | } else { |
| | if (resultsDiv.style.left) |
| | resultsDiv.style.removeProperty("left"); |
| | } |
| | } |
| | function hideResults(textArea) { |
| | let textAreaId = getTextAreaIdentifier(textArea); |
| | let resultsDiv = gradioApp().querySelector('.autocompleteResults' + textAreaId); |
| | |
| | if (!resultsDiv) return; |
| | |
| | resultsDiv.style.display = "none"; |
| | selectedTag = null; |
| | } |
| |
|
| | |
| | function isEnabled() { |
| | if (CFG.activeIn.global) { |
| | |
| | if (!currentModelName || !currentModelHash) return true; |
| | |
| | let modelList = CFG.activeIn.modelList |
| | .split(",") |
| | .map(x => x.trim()) |
| | .filter(x => x.length > 0); |
| | |
| | let shortHash = currentModelHash.substring(0, 10); |
| | let modelNameWithoutHash = currentModelName.replace(/\[.*\]$/g, "").trim(); |
| | if (CFG.activeIn.modelListMode.toLowerCase() === "blacklist") { |
| | |
| | return modelList.filter(x => x === currentModelName || x === modelNameWithoutHash || x === currentModelHash || x === shortHash).length === 0; |
| | } else { |
| | |
| | |
| | return modelList.length === 0 || modelList.filter(x => x === currentModelName || x === modelNameWithoutHash || x === currentModelHash || x === shortHash).length > 0; |
| | } |
| | } else { |
| | return false; |
| | } |
| | } |
| |
|
| | const WEIGHT_REGEX = /[([]([^()[\]:|]+)(?::(?:\d+(?:\.\d+)?|\.\d+))?[)\]]/g; |
| | const POINTY_REGEX = /<[^\s,<](?:[^\t\n\r,<>]*>|[^\t\n\r,> ]*)/g; |
| | const COMPLETED_WILDCARD_REGEX = /__[^\s,_][^\t\n\r,_]*[^\s,_]__[^\s,_]*/g; |
| | const NORMAL_TAG_REGEX = /[^\s,|<>)\]]+|</g; |
| | const TAG_REGEX = new RegExp(`${POINTY_REGEX.source}|${COMPLETED_WILDCARD_REGEX.source}|${NORMAL_TAG_REGEX.source}`, "g"); |
| |
|
| | |
| | async function insertTextAtCursor(textArea, result, tagword) { |
| | let text = result.text; |
| | let tagType = result.type; |
| |
|
| | let cursorPos = textArea.selectionStart; |
| | var sanitizedText = text |
| |
|
| | |
| | sanitizeResults = await processQueueReturn(QUEUE_SANITIZE, null, tagType, text); |
| |
|
| | if (sanitizeResults && sanitizeResults.length > 0) { |
| | sanitizedText = sanitizeResults[0]; |
| | } else { |
| | sanitizedText = CFG.replaceUnderscores ? text.replaceAll("_", " ") : text; |
| |
|
| | if (CFG.escapeParentheses && tagType === ResultType.tag) { |
| | sanitizedText = sanitizedText |
| | .replaceAll("(", "\\(") |
| | .replaceAll(")", "\\)") |
| | .replaceAll("[", "\\[") |
| | .replaceAll("]", "\\]"); |
| | } |
| | } |
| |
|
| | var prompt = textArea.value; |
| |
|
| | |
| | let editStart = Math.max(cursorPos - tagword.length, 0); |
| | let editEnd = Math.min(cursorPos + tagword.length, prompt.length); |
| | let surrounding = prompt.substring(editStart, editEnd); |
| | let match = surrounding.match(new RegExp(escapeRegExp(`${tagword}`), "i")); |
| | let afterInsertCursorPos = editStart + match.index + sanitizedText.length; |
| |
|
| | var optionalSeparator = ""; |
| | let extraNetworkTypes = [ResultType.hypernetwork, ResultType.lora]; |
| | let noCommaTypes = [ResultType.wildcardFile, ResultType.yamlWildcard].concat(extraNetworkTypes); |
| | if (CFG.appendComma && !noCommaTypes.includes(tagType)) { |
| | optionalSeparator = surrounding.match(new RegExp(`${escapeRegExp(tagword)}[,:]`, "i")) !== null ? "" : ", "; |
| | } else if (extraNetworkTypes.includes(tagType)) { |
| | |
| | optionalSeparator = CFG.extraNetworksSeparator || " "; |
| | } |
| |
|
| | |
| | let insert = surrounding.replace(match, sanitizedText + optionalSeparator); |
| |
|
| | |
| | var newPrompt = prompt.substring(0, editStart) + insert + prompt.substring(editEnd); |
| | textArea.value = newPrompt; |
| | textArea.selectionStart = afterInsertCursorPos + optionalSeparator.length; |
| | textArea.selectionEnd = textArea.selectionStart |
| |
|
| | |
| | |
| | updateInput(textArea); |
| |
|
| | |
| | let weightedTags = [...newPrompt.matchAll(WEIGHT_REGEX)] |
| | .map(match => match[1]); |
| | let tags = newPrompt.match(TAG_REGEX) |
| | if (weightedTags !== null) { |
| | tags = tags.filter(tag => !weightedTags.some(weighted => tag.includes(weighted))) |
| | .concat(weightedTags); |
| | } |
| | previousTags = tags; |
| |
|
| | |
| | let returns = await processQueueReturn(QUEUE_AFTER_INSERT, null, tagType, sanitizedText, newPrompt, textArea); |
| | |
| | if (returns.some(x => x === true)) |
| | return; |
| |
|
| | |
| | if (!hideBlocked && isVisible(textArea)) { |
| | hideResults(textArea); |
| | } |
| | } |
| |
|
| | function addResultsToList(textArea, results, tagword, resetList) { |
| | let textAreaId = getTextAreaIdentifier(textArea); |
| | let resultDiv = gradioApp().querySelector('.autocompleteResults' + textAreaId); |
| | let resultsList = resultDiv.querySelector('ul'); |
| |
|
| | |
| | if (resetList) { |
| | resultsList.innerHTML = ""; |
| | selectedTag = null; |
| | resultDiv.scrollTop = 0; |
| | resultCount = 0; |
| | } |
| |
|
| | |
| | let tagFileName = CFG.tagFile.split(".")[0]; |
| | let tagColors = CFG.colorMap; |
| | let mode = gradioApp().querySelector('.dark') ? 0 : 1; |
| | let nextLength = Math.min(results.length, resultCount + CFG.resultStepLength); |
| |
|
| | for (let i = resultCount; i < nextLength; i++) { |
| | let result = results[i]; |
| |
|
| | |
| | if (!result) |
| | continue; |
| |
|
| | let li = document.createElement("li"); |
| |
|
| | let flexDiv = document.createElement("div"); |
| | flexDiv.classList.add("resultsFlexContainer"); |
| | li.appendChild(flexDiv); |
| |
|
| | let itemText = document.createElement("div"); |
| | itemText.classList.add("acListItem"); |
| |
|
| | let displayText = ""; |
| | |
| | if (result.aliases && !result.text.includes(tagword)) { |
| | let splitAliases = result.aliases.split(","); |
| | let bestAlias = splitAliases.find(a => a.toLowerCase().includes(tagword)); |
| |
|
| | |
| | if (!bestAlias) { |
| | let tagOrAlias = pair => pair[0] === result.text || splitAliases.includes(pair[0]); |
| | var tArray = [...translations]; |
| | if (tArray) { |
| | var translationKey = [...translations].find(pair => tagOrAlias(pair) && pair[1].includes(tagword)); |
| | if (translationKey) |
| | bestAlias = translationKey[0]; |
| | } |
| | } |
| |
|
| | displayText = escapeHTML(bestAlias); |
| |
|
| | |
| | if (translations.has(bestAlias) && translations.get(bestAlias) !== bestAlias && bestAlias !== result.text) |
| | displayText += `[${translations.get(bestAlias)}]`; |
| |
|
| | if (!CFG.alias.onlyShowAlias && result.text !== bestAlias) |
| | displayText += " ➝ " + result.text; |
| | } else { |
| | displayText = escapeHTML(result.text); |
| | } |
| |
|
| | |
| | if (translations.has(result.text)) |
| | displayText += `[${translations.get(result.text)}]`; |
| |
|
| | |
| | itemText.innerHTML = displayText.replace(tagword, `<b>${tagword}</b>`); |
| |
|
| | |
| | if (CFG.showWikiLinks |
| | && (result.type === ResultType.tag) |
| | && (tagFileName.toLowerCase().startsWith("danbooru") || tagFileName.toLowerCase().startsWith("e621"))) { |
| | let wikiLink = document.createElement("a"); |
| | wikiLink.classList.add("acWikiLink"); |
| | wikiLink.innerText = "?"; |
| |
|
| | let linkPart = displayText; |
| | |
| | if (displayText.includes("➝")) |
| | linkPart = displayText.split(" ➝ ")[1]; |
| | |
| | |
| | let tagFileNameLower = tagFileName.toLowerCase(); |
| | if (tagFileNameLower.startsWith("danbooru")) { |
| | wikiLink.href = `https://danbooru.donmai.us/wiki_pages/${linkPart}`; |
| | } else if (tagFileNameLower.startsWith("e621")) { |
| | wikiLink.href = `https://e621.net/wiki_pages/${linkPart}`; |
| | } |
| | |
| | wikiLink.target = "_blank"; |
| | flexDiv.appendChild(wikiLink); |
| | } |
| |
|
| | flexDiv.appendChild(itemText); |
| |
|
| | |
| | |
| | if (result.category) { |
| | |
| | let cat = result.category; |
| | let colorGroup = tagColors[tagFileName]; |
| | |
| | if (!colorGroup) |
| | colorGroup = tagColors["danbooru"]; |
| |
|
| | |
| | if (!colorGroup[cat]) |
| | cat = "-1"; |
| |
|
| | flexDiv.style = `color: ${colorGroup[cat][mode]};`; |
| | } |
| |
|
| | |
| | if (result.count && !isNaN(result.count)) { |
| | let postCount = result.count; |
| | let formatter; |
| |
|
| | |
| | if (postCount >= 1000000 || (postCount >= 1000 && postCount < 10000)) |
| | formatter = Intl.NumberFormat("en", { notation: "compact", minimumFractionDigits: 1, maximumFractionDigits: 1 }); |
| | else |
| | formatter = Intl.NumberFormat("en", {notation: "compact"}); |
| |
|
| | let formattedCount = formatter.format(postCount); |
| |
|
| | let countDiv = document.createElement("div"); |
| | countDiv.textContent = formattedCount; |
| | countDiv.classList.add("acMetaText"); |
| | flexDiv.appendChild(countDiv); |
| | } else if (result.meta) { |
| | let metaDiv = document.createElement("div"); |
| | metaDiv.textContent = result.meta; |
| | metaDiv.classList.add("acMetaText"); |
| |
|
| | |
| | if (result.type === ResultType.embedding) { |
| | if (result.meta.startsWith("v1")) |
| | itemText.classList.add("acEmbeddingV1"); |
| | else if (result.meta.startsWith("v2")) |
| | itemText.classList.add("acEmbeddingV2"); |
| | } |
| | |
| | flexDiv.appendChild(metaDiv); |
| | } |
| |
|
| | |
| | li.addEventListener("click", function () { insertTextAtCursor(textArea, result, tagword); }); |
| | |
| | resultsList.appendChild(li); |
| | } |
| | resultCount = nextLength; |
| |
|
| | if (resetList) |
| | resultDiv.scrollTop = 0; |
| | } |
| |
|
| | function updateSelectionStyle(textArea, newIndex, oldIndex) { |
| | let textAreaId = getTextAreaIdentifier(textArea); |
| | let resultDiv = gradioApp().querySelector('.autocompleteResults' + textAreaId); |
| | let resultsList = resultDiv.querySelector('ul'); |
| | let items = resultsList.getElementsByTagName('li'); |
| |
|
| | if (oldIndex != null) { |
| | items[oldIndex].classList.remove('selected'); |
| | } |
| |
|
| | |
| | if (newIndex !== null) { |
| | items[newIndex].classList.add('selected'); |
| | } |
| |
|
| | |
| | if (items.length > CFG.maxResults) { |
| | let selected = items[newIndex]; |
| | resultDiv.scrollTop = selected.offsetTop - resultDiv.offsetTop; |
| | } |
| | } |
| |
|
| | async function autocomplete(textArea, prompt, fixedTag = null) { |
| | |
| | if (!isEnabled()) return; |
| |
|
| | |
| | if (prompt.length === 0) { |
| | hideResults(textArea); |
| | previousTags = []; |
| | tagword = ""; |
| | return; |
| | } |
| |
|
| | if (fixedTag === null) { |
| | |
| | |
| | let weightedTags = [...prompt.matchAll(WEIGHT_REGEX)] |
| | .map(match => match[1]); |
| | let tags = prompt.match(TAG_REGEX) |
| | if (weightedTags !== null && tags !== null) { |
| | tags = tags.filter(tag => !weightedTags.some(weighted => tag.includes(weighted) && !tag.startsWith("<["))) |
| | .concat(weightedTags); |
| | } |
| |
|
| | |
| | if (!tags || tags.length === 0) { |
| | previousTags = []; |
| | tagword = ""; |
| | hideResults(textArea); |
| | return; |
| | } |
| |
|
| | let tagCountChange = tags.length - previousTags.length; |
| | let diff = difference(tags, previousTags); |
| | previousTags = tags; |
| |
|
| | |
| | if (diff === null || diff.length === 0 || (diff.length === 1 && tagCountChange < 0)) { |
| | if (!hideBlocked) hideResults(textArea); |
| | return; |
| | } |
| |
|
| | tagword = diff[0] |
| |
|
| | |
| | if (tagword === null || tagword.length === 0) { |
| | hideResults(textArea); |
| | return; |
| | } |
| | } else { |
| | tagword = fixedTag; |
| | } |
| |
|
| | results = []; |
| | tagword = tagword.toLowerCase().replace(/[\n\r]/g, ""); |
| |
|
| | |
| | let resultCandidates = await processParsers(textArea, prompt); |
| | |
| | if (resultCandidates && resultCandidates.length > 0) { |
| | |
| | results = resultCandidates.flat(); |
| | |
| | |
| | let shouldSort = resultCandidates.length > 1; |
| | if (shouldSort) { |
| | results = results.sort((a, b) => a.text.localeCompare(b.text)); |
| |
|
| | |
| | if (tagword.startsWith("<") || tagword.startsWith("*<")) { |
| | |
| | let searchRegex; |
| | if (tagword.startsWith("*")) { |
| | tagword = tagword.slice(1); |
| | searchRegex = new RegExp(`${escapeRegExp(tagword)}`, 'i'); |
| | } else { |
| | searchRegex = new RegExp(`(^|[^a-zA-Z])${escapeRegExp(tagword)}`, 'i'); |
| | } |
| | let genericResults = allTags.filter(x => x[0].toLowerCase().search(searchRegex) > -1).slice(0, CFG.maxResults); |
| |
|
| | genericResults.forEach(g => { |
| | let result = new AutocompleteResult(g[0].trim(), ResultType.tag) |
| | result.category = g[1]; |
| | result.count = g[2]; |
| | result.aliases = g[3]; |
| | results.push(result); |
| | }); |
| | } |
| | } |
| | } else { |
| | |
| | let searchRegex; |
| | if (tagword.startsWith("*")) { |
| | tagword = tagword.slice(1); |
| | searchRegex = new RegExp(`${escapeRegExp(tagword)}`, 'i'); |
| | } else { |
| | searchRegex = new RegExp(`(^|[^a-zA-Z])${escapeRegExp(tagword)}`, 'i'); |
| | } |
| |
|
| | |
| | let baseFilter = (x) => x[0].toLowerCase().search(searchRegex) > -1; |
| | let aliasFilter = (x) => x[3] && x[3].toLowerCase().search(searchRegex) > -1; |
| | let translationFilter = (x) => (translations.has(x[0]) && translations.get(x[0]).toLowerCase().search(searchRegex) > -1) |
| | || x[3] && x[3].split(",").some(y => translations.has(y) && translations.get(y).toLowerCase().search(searchRegex) > -1); |
| | |
| | let fil; |
| | if (CFG.alias.searchByAlias && CFG.translation.searchByTranslation) |
| | fil = (x) => baseFilter(x) || aliasFilter(x) || translationFilter(x); |
| | else if (CFG.alias.searchByAlias && !CFG.translation.searchByTranslation) |
| | fil = (x) => baseFilter(x) || aliasFilter(x); |
| | else if (CFG.translation.searchByTranslation && !CFG.alias.searchByAlias) |
| | fil = (x) => baseFilter(x) || translationFilter(x); |
| | else |
| | fil = (x) => baseFilter(x); |
| |
|
| | |
| | allTags.filter(fil).forEach(t => { |
| | let result = new AutocompleteResult(t[0].trim(), ResultType.tag) |
| | result.category = t[1]; |
| | result.count = t[2]; |
| | result.aliases = t[3]; |
| | results.push(result); |
| | }); |
| |
|
| | |
| | if (CFG.extra.extraFile) { |
| | let extraResults = []; |
| |
|
| | extras.filter(fil).forEach(e => { |
| | let result = new AutocompleteResult(e[0].trim(), ResultType.extra) |
| | result.category = e[1] || 0; |
| | result.meta = e[2] || "Custom tag"; |
| | result.aliases = e[3] || ""; |
| | extraResults.push(result); |
| | }); |
| |
|
| | if (CFG.extra.addMode === "Insert before") { |
| | results = extraResults.concat(results); |
| | } else { |
| | results = results.concat(extraResults); |
| | } |
| | } |
| | |
| | |
| | if (!CFG.showAllResults) { |
| | results = results.slice(0, CFG.maxResults); |
| | } |
| | } |
| |
|
| | |
| | if (!results || results.length === 0) { |
| | |
| | hideResults(textArea); |
| | return; |
| | } |
| |
|
| | addResultsToList(textArea, results, tagword, true); |
| | showResults(textArea); |
| | } |
| |
|
| | function navigateInList(textArea, event) { |
| | |
| | if (!isEnabled()) return; |
| | |
| | let keys = CFG.keymap; |
| |
|
| | |
| | if ((event.key === "Home" || event.key === "End") && !Object.values(keys).includes(event.key)) { |
| | hideResults(textArea); |
| | return; |
| | } |
| |
|
| | |
| | |
| | validKeys = Object.values(keys).filter(x => x !== "None" && x !== ""); |
| |
|
| | if (!validKeys.includes(event.key)) return; |
| | if (!isVisible(textArea)) return |
| | |
| | if (event.ctrlKey || event.altKey) return; |
| |
|
| | oldSelectedTag = selectedTag; |
| |
|
| | switch (event.key) { |
| | case keys["MoveUp"]: |
| | if (selectedTag === null) { |
| | selectedTag = resultCount - 1; |
| | } else { |
| | selectedTag = (selectedTag - 1 + resultCount) % resultCount; |
| | } |
| | break; |
| | case keys["MoveDown"]: |
| | if (selectedTag === null) { |
| | selectedTag = 0; |
| | } else { |
| | selectedTag = (selectedTag + 1) % resultCount; |
| | } |
| | break; |
| | case keys["JumpUp"]: |
| | if (selectedTag === null || selectedTag === 0) { |
| | selectedTag = resultCount - 1; |
| | } else { |
| | selectedTag = (Math.max(selectedTag - 5, 0) + resultCount) % resultCount; |
| | } |
| | break; |
| | case keys["JumpDown"]: |
| | if (selectedTag === null || selectedTag === resultCount - 1) { |
| | selectedTag = 0; |
| | } else { |
| | selectedTag = Math.min(selectedTag + 5, resultCount - 1) % resultCount; |
| | } |
| | break; |
| | case keys["JumpToStart"]: |
| | selectedTag = 0; |
| | break; |
| | case keys["JumpToEnd"]: |
| | selectedTag = resultCount - 1; |
| | break; |
| | case keys["ChooseSelected"]: |
| | if (selectedTag !== null) { |
| | insertTextAtCursor(textArea, results[selectedTag], tagword); |
| | } else { |
| | hideResults(textArea); |
| | return; |
| | } |
| | break; |
| | case keys["ChooseFirstOrSelected"]: |
| | if (selectedTag === null) { |
| | selectedTag = 0; |
| | } |
| | insertTextAtCursor(textArea, results[selectedTag], tagword); |
| | break; |
| | case keys["Close"]: |
| | hideResults(textArea); |
| | break; |
| | } |
| | if (selectedTag === resultCount - 1 |
| | && (event.key === keys["MoveUp"] || event.key === keys["MoveDown"] || event.key === keys["JumpToStart"] || event.key === keys["JumpToEnd"])) { |
| | addResultsToList(textArea, results, tagword, false); |
| | } |
| | |
| | if (selectedTag !== null) |
| | updateSelectionStyle(textArea, selectedTag, oldSelectedTag); |
| |
|
| | |
| | event.preventDefault(); |
| | event.stopPropagation(); |
| | } |
| |
|
| | |
| | async function setup() { |
| | |
| | await processQueue(QUEUE_FILE_LOAD, null); |
| |
|
| | |
| | let textAreas = getTextAreas(); |
| |
|
| | |
| | let applySettingsButton = gradioApp().querySelector("#tab_settings #settings_submit") || gradioApp().querySelector("#tab_settings > div > .gr-button-primary"); |
| | applySettingsButton?.addEventListener("click", () => { |
| | |
| | setTimeout(async () => { |
| | await syncOptions(); |
| | }, 500); |
| | }); |
| | |
| | let quicksettings = gradioApp().querySelector('#quicksettings'); |
| | let commonQueryPart = "[id^=setting_tac] > label >"; |
| | quicksettings?.querySelectorAll(`${commonQueryPart} input, ${commonQueryPart} textarea, ${commonQueryPart} select`).forEach(e => { |
| | e.addEventListener("change", () => { |
| | setTimeout(async () => { |
| | await syncOptions(); |
| | }, 500); |
| | }); |
| | }); |
| |
|
| | |
| | let modelHashText = gradioApp().querySelector("#sd_checkpoint_hash"); |
| | if (modelHashText) { |
| | currentModelHash = modelHashText.title |
| | let modelHashObserver = new MutationObserver((mutationList, observer) => { |
| | for (const mutation of mutationList) { |
| | if (mutation.type === "attributes" && mutation.attributeName === "title") { |
| | currentModelHash = mutation.target.title; |
| | let modelDropdown = gradioApp().querySelector("#setting_sd_model_checkpoint span.single-select") |
| | if (modelDropdown) { |
| | currentModelName = modelDropdown.textContent; |
| | } else { |
| | |
| | modelDropdown = gradioApp().querySelector("#setting_sd_model_checkpoint select"); |
| | currentModelName = modelDropdown.value; |
| | } |
| | } |
| | } |
| | }); |
| | modelHashObserver.observe(modelHashText, { attributes: true }); |
| | } |
| |
|
| | |
| | if (textAreas.every(v => v === null || v === undefined)) return; |
| | |
| | if (gradioApp().querySelector('.autocompleteResults.p')) { |
| | if (gradioApp().querySelector('.autocompleteResults.n') || !CFG.activeIn.negativePrompts) { |
| | return; |
| | } |
| | } else if (!CFG.activeIn.txt2img && !CFG.activeIn.img2img) { |
| | return; |
| | } |
| |
|
| | textAreas.forEach(area => { |
| | |
| | let textAreaId = getTextAreaIdentifier(area); |
| | if ((!CFG.activeIn.img2img && textAreaId.includes("img2img")) |
| | || (!CFG.activeIn.txt2img && textAreaId.includes("txt2img")) |
| | || (!CFG.activeIn.negativePrompts && textAreaId.includes("n")) |
| | || (!CFG.activeIn.thirdParty && textAreaId.includes("thirdParty"))) { |
| | return; |
| | } |
| |
|
| | |
| | if (!area.classList.contains('autocomplete')) { |
| | |
| | var resultsDiv = createResultsDiv(area); |
| | area.parentNode.insertBefore(resultsDiv, area.nextSibling); |
| | |
| | hideResults(area); |
| |
|
| | |
| | area.addEventListener('input', debounce(() => autocomplete(area, area.value), CFG.delayTime)); |
| | |
| | area.addEventListener('focusout', debounce(() => hideResults(area), 400)); |
| | |
| | area.addEventListener('keydown', (e) => navigateInList(area, e)); |
| | |
| | |
| | area.addEventListener('compositionend', () => { |
| | hideBlocked = true; |
| | setTimeout(() => { hideBlocked = false; }, 100); |
| | }); |
| |
|
| | |
| | area.classList.add('autocomplete'); |
| | } |
| | }); |
| |
|
| | |
| | let acStyle = document.createElement('style'); |
| | |
| | let mode = gradioApp().querySelector('.dark') ? 0 : 1; |
| | |
| | let browser = navigator.userAgent.toLowerCase().indexOf('firefox') > -1 ? "firefox" : "other"; |
| | |
| | let css = autocompleteCSS; |
| | |
| | Object.keys(styleColors).forEach((key) => { |
| | css = css.replace(`var(${key})`, styleColors[key][mode]); |
| | }) |
| | Object.keys(browserVars).forEach((key) => { |
| | css = css.replace(`var(${key})`, browserVars[key][browser]); |
| | }) |
| | |
| | if (acStyle.styleSheet) { |
| | acStyle.styleSheet.cssText = css; |
| | } else { |
| | acStyle.appendChild(document.createTextNode(css)); |
| | } |
| | gradioApp().appendChild(acStyle); |
| |
|
| | |
| | await processQueue(QUEUE_AFTER_SETUP, null); |
| | } |
| | let loading = false; |
| | onUiUpdate(async () => { |
| | if (loading) return; |
| | if (Object.keys(opts).length === 0) return; |
| | if (CFG) return; |
| | loading = true; |
| | |
| | tagBasePath = await readFile(`tmp/tagAutocompletePath.txt`); |
| | |
| | await syncOptions(); |
| | |
| | setup(); |
| | loading = false; |
| | }); |
| |
|