feat: Refactor tag source handling and enhance UI with icon support for autocomplete suggestions
This commit is contained in:
+130
-61
@@ -1,39 +1,29 @@
|
||||
/* Light Theme */
|
||||
body {
|
||||
--autocomplete-plus-text-color-cat-general: var(--p-blue-600);
|
||||
--autocomplete-plus-text-color-cat-artist: var(--p-red-600);
|
||||
--autocomplete-plus-text-color-cat-copyright: var(--p-purple-600);
|
||||
--autocomplete-plus-text-color-cat-character: var(--p-green-600);
|
||||
--autocomplete-plus-text-color-cat-meta: var(--p-yellow-600);
|
||||
--autocomplete-plus-text-color-cat-unknown: var(--p-gray-600);
|
||||
--autocomplete-plus-text-color-cat-blue: var(--p-blue-600);
|
||||
--autocomplete-plus-text-color-cat-red: var(--p-red-600);
|
||||
--autocomplete-plus-text-color-cat-purple: var(--p-purple-600);
|
||||
--autocomplete-plus-text-color-cat-green: var(--p-green-600);
|
||||
--autocomplete-plus-text-color-cat-yellow: var(--p-yellow-600);
|
||||
--autocomplete-plus-text-color-cat-gray: var(--p-gray-600);
|
||||
--autocomplete-plus-text-color-cat-sky: var(--p-sky-500);
|
||||
--autocomplete-plus-text-color-cat-orange: var(--p-orange-600);
|
||||
--autocomplete-plus-text-color-cat-white: var(--p-neutral-700);
|
||||
--autocomplete-plus-text-color-disabled: var(--p-gray-400);
|
||||
|
||||
/* Selected color */
|
||||
--autocomplete-plus-text-color-cat-general-selected: var(--p-blue-200);
|
||||
--autocomplete-plus-text-color-cat-artist-selected: var(--p-red-200);
|
||||
--autocomplete-plus-text-color-cat-copyright-selected: var(--p-purple-200);
|
||||
--autocomplete-plus-text-color-cat-character-selected: var(--p-green-200);
|
||||
--autocomplete-plus-text-color-cat-meta-selected: var(--p-yellow-200);
|
||||
--autocomplete-plus-text-color-cat-unknown-selected: var(--p-gray-200);
|
||||
}
|
||||
|
||||
/* Dark Theme */
|
||||
body.dark-theme {
|
||||
--autocomplete-plus-text-color-cat-general: var(--p-blue-400);
|
||||
--autocomplete-plus-text-color-cat-artist: var(--p-red-400);
|
||||
--autocomplete-plus-text-color-cat-copyright: var(--p-purple-400);
|
||||
--autocomplete-plus-text-color-cat-character: var(--p-green-400);
|
||||
--autocomplete-plus-text-color-cat-meta: var(--p-yellow-400);
|
||||
--autocomplete-plus-text-color-cat-unknown: var(--p-gray-500);
|
||||
--autocomplete-plus-text-color-cat-blue: var(--p-blue-400);
|
||||
--autocomplete-plus-text-color-cat-red: var(--p-red-400);
|
||||
--autocomplete-plus-text-color-cat-purple: var(--p-purple-400);
|
||||
--autocomplete-plus-text-color-cat-green: var(--p-green-400);
|
||||
--autocomplete-plus-text-color-cat-yellow: var(--p-yellow-400);
|
||||
--autocomplete-plus-text-color-cat-gray: var(--p-gray-400);
|
||||
--autocomplete-plus-text-color-cat-sky: var(--p-sky-300);
|
||||
--autocomplete-plus-text-color-cat-orange: var(--p-orange-400);
|
||||
--autocomplete-plus-text-color-cat-white: var(--p-neutral-200);
|
||||
--autocomplete-plus-text-color-disabled: var(--p-gray-500);
|
||||
|
||||
/* Selected color */
|
||||
--autocomplete-plus-text-color-cat-general-selected: var(--p-blue-200);
|
||||
--autocomplete-plus-text-color-cat-artist-selected: var(--p-red-200);
|
||||
--autocomplete-plus-text-color-cat-copyright-selected: var(--p-purple-200);
|
||||
--autocomplete-plus-text-color-cat-character-selected: var(--p-green-200);
|
||||
--autocomplete-plus-text-color-cat-meta-selected: var(--p-yellow-200);
|
||||
--autocomplete-plus-text-color-cat-unknown-selected: var(--p-gray-200);
|
||||
}
|
||||
|
||||
#autocomplete-plus-root {
|
||||
@@ -62,28 +52,60 @@ body.dark-theme {
|
||||
grid-template-columns: subgrid;
|
||||
}
|
||||
|
||||
.autocomplete-plus-item[data-tag-category="general"] {
|
||||
color: var(--autocomplete-plus-text-color-cat-general);
|
||||
.autocomplete-plus-item.danbooru[data-tag-category="general"] {
|
||||
color: var(--autocomplete-plus-text-color-cat-blue);
|
||||
}
|
||||
|
||||
.autocomplete-plus-item[data-tag-category="artist"] {
|
||||
color: var(--autocomplete-plus-text-color-cat-artist);
|
||||
.autocomplete-plus-item.danbooru[data-tag-category="artist"] {
|
||||
color: var(--autocomplete-plus-text-color-cat-red);
|
||||
}
|
||||
|
||||
.autocomplete-plus-item[data-tag-category="copyright"] {
|
||||
color: var(--autocomplete-plus-text-color-cat-copyright);
|
||||
.autocomplete-plus-item.danbooru[data-tag-category="copyright"] {
|
||||
color: var(--autocomplete-plus-text-color-cat-purple);
|
||||
}
|
||||
|
||||
.autocomplete-plus-item[data-tag-category="character"] {
|
||||
color: var(--autocomplete-plus-text-color-cat-character);
|
||||
.autocomplete-plus-item.danbooru[data-tag-category="character"] {
|
||||
color: var(--autocomplete-plus-text-color-cat-green);
|
||||
}
|
||||
|
||||
.autocomplete-plus-item[data-tag-category="meta"] {
|
||||
color: var(--autocomplete-plus-text-color-cat-meta);
|
||||
.autocomplete-plus-item.danbooru[data-tag-category="meta"] {
|
||||
color: var(--autocomplete-plus-text-color-cat-yellow);
|
||||
}
|
||||
|
||||
.autocomplete-plus-item[data-tag-category="unknown"] {
|
||||
color: var(--autocomplete-plus-text-color-cat-unknown);
|
||||
.autocomplete-plus-item.danbooru[data-tag-category="unknown"] {
|
||||
color: var(--autocomplete-plus-text-color-cat-gray);
|
||||
}
|
||||
|
||||
.autocomplete-plus-item.e621[data-tag-category="general"] {
|
||||
color: var(--autocomplete-plus-text-color-cat-sky);
|
||||
}
|
||||
|
||||
.autocomplete-plus-item.e621[data-tag-category="artist"] {
|
||||
color: var(--autocomplete-plus-text-color-cat-orange);
|
||||
}
|
||||
|
||||
.autocomplete-plus-item.e621[data-tag-category="copyright"] {
|
||||
color: var(--autocomplete-plus-text-color-cat-purple);
|
||||
}
|
||||
|
||||
.autocomplete-plus-item.e621[data-tag-category="character"] {
|
||||
color: var(--autocomplete-plus-text-color-cat-green);
|
||||
}
|
||||
|
||||
.autocomplete-plus-item.e621[data-tag-category="species"] {
|
||||
color: var(--autocomplete-plus-text-color-cat-red);
|
||||
}
|
||||
|
||||
.autocomplete-plus-item.e621[data-tag-category="meta"] {
|
||||
color: var(--autocomplete-plus-text-color-cat-white);
|
||||
}
|
||||
|
||||
.autocomplete-plus-item.e621[data-tag-category="lore"] {
|
||||
color: var(--autocomplete-plus-text-color-cat-red);
|
||||
}
|
||||
|
||||
.autocomplete-plus-item.e621[data-tag-category="unknown"] {
|
||||
color: var(--autocomplete-plus-text-color-cat-purple);
|
||||
}
|
||||
|
||||
.autocomplete-plus-item span {
|
||||
@@ -113,22 +135,31 @@ body.dark-theme {
|
||||
background-color: var(--comfy-hover-bg);
|
||||
}
|
||||
|
||||
.autocomplete-plus-tag-name {
|
||||
padding: 8px;
|
||||
.autocomplete-plus-item .autocomplete-plus-tag-name {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.autocomplete-plus-item .autocomplete-plus-tag-icon-svg {
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.autocomplete-plus-tag-name.autocomplete-plus-already-exists {
|
||||
color: var(--autocomplete-plus-text-color-disabled);
|
||||
}
|
||||
|
||||
.autocomplete-plus-alias {
|
||||
.autocomplete-plus-item .autocomplete-plus-alias {
|
||||
overflow: hidden;
|
||||
color: var(--descrip-text);
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.autocomplete-plus-item .autocomplete-plus-tag-count {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
/* Related Tags UI Styles */
|
||||
#related-tags-root {
|
||||
position: absolute;
|
||||
@@ -163,9 +194,16 @@ body.dark-theme {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.related-tags-header-tag-name .autocomplete-plus-tag-icon-svg {
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.related-tags-header-controls {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-left: 16px;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
@@ -210,28 +248,60 @@ body.dark-theme {
|
||||
grid-template-columns: subgrid;
|
||||
}
|
||||
|
||||
.related-tag-item[data-tag-category="general"] {
|
||||
color: var(--autocomplete-plus-text-color-cat-general);
|
||||
.related-tag-item.danbooru[data-tag-category="general"] {
|
||||
color: var(--autocomplete-plus-text-color-cat-blue);
|
||||
}
|
||||
|
||||
.related-tag-item[data-tag-category="artist"] {
|
||||
color: var(--autocomplete-plus-text-color-cat-artist);
|
||||
.related-tag-item.danbooru[data-tag-category="artist"] {
|
||||
color: var(--autocomplete-plus-text-color-cat-red);
|
||||
}
|
||||
|
||||
.related-tag-item[data-tag-category="copyright"] {
|
||||
color: var(--autocomplete-plus-text-color-cat-copyright);
|
||||
.related-tag-item.danbooru[data-tag-category="copyright"] {
|
||||
color: var(--autocomplete-plus-text-color-cat-purple);
|
||||
}
|
||||
|
||||
.related-tag-item[data-tag-category="character"] {
|
||||
color: var(--autocomplete-plus-text-color-cat-character);
|
||||
.related-tag-item.danbooru[data-tag-category="character"] {
|
||||
color: var(--autocomplete-plus-text-color-cat-green);
|
||||
}
|
||||
|
||||
.related-tag-item[data-tag-category="meta"] {
|
||||
color: var(--autocomplete-plus-text-color-cat-meta);
|
||||
.related-tag-item.danbooru[data-tag-category="meta"] {
|
||||
color: var(--autocomplete-plus-text-color-cat-yellow);
|
||||
}
|
||||
|
||||
.related-tag-item[data-tag-category="unknown"] {
|
||||
color: var(--autocomplete-plus-text-color-cat-unknown);
|
||||
.related-tag-item.danbooru[data-tag-category="unknown"] {
|
||||
color: var(--autocomplete-plus-text-color-cat-gray);
|
||||
}
|
||||
|
||||
.related-tag-item.e621[data-tag-category="general"] {
|
||||
color: var(--autocomplete-plus-text-color-cat-sky);
|
||||
}
|
||||
|
||||
.related-tag-item.e621[data-tag-category="artist"] {
|
||||
color: var(--autocomplete-plus-text-color-cat-orange);
|
||||
}
|
||||
|
||||
.related-tag-item.e621[data-tag-category="copyright"] {
|
||||
color: var(--autocomplete-plus-text-color-cat-purple);
|
||||
}
|
||||
|
||||
.related-tag-item.e621[data-tag-category="character"] {
|
||||
color: var(--autocomplete-plus-text-color-cat-green);
|
||||
}
|
||||
|
||||
.related-tag-item.e621[data-tag-category="species"] {
|
||||
color: var(--autocomplete-plus-text-color-cat-red);
|
||||
}
|
||||
|
||||
.related-tag-item.e621[data-tag-category="meta"] {
|
||||
color: var(--autocomplete-plus-text-color-cat-white);
|
||||
}
|
||||
|
||||
.related-tag-item.e621[data-tag-category="lore"] {
|
||||
color: var(--autocomplete-plus-text-color-cat-red);
|
||||
}
|
||||
|
||||
.related-tag-item.e621[data-tag-category="unknown"] {
|
||||
color: var(--autocomplete-plus-text-color-cat-gray);
|
||||
}
|
||||
|
||||
/* stylelint-disable-next-line no-descending-specificity */
|
||||
@@ -261,23 +331,22 @@ body.dark-theme {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.related-tag-name {
|
||||
padding: 8px;
|
||||
.related-tag-item .related-tag-name {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.related-tag-name.related-tag-already-exists {
|
||||
.related-tag-item .related-tag-name.related-tag-already-exists {
|
||||
color: var(--autocomplete-plus-text-color-disabled);
|
||||
}
|
||||
|
||||
.related-tag-alias {
|
||||
.related-tag-item .related-tag-alias {
|
||||
overflow: hidden;
|
||||
color: var(--descrip-text);
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.related-tag-similarity {
|
||||
.related-tag-item .related-tag-similarity {
|
||||
color: var(--descrip-text);
|
||||
text-align: right;
|
||||
white-space: nowrap;
|
||||
@@ -294,4 +363,4 @@ body.dark-theme {
|
||||
color: var(--error-text);
|
||||
font-style: italic;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
+27
-12
@@ -1,8 +1,8 @@
|
||||
import {
|
||||
DanbooruTagCategory,
|
||||
TagCategory,
|
||||
TagData,
|
||||
autoCompleteData,
|
||||
getTagSourceInPriorityOrder
|
||||
getEnabledTagSourceInPriorityOrder
|
||||
} from './data.js';
|
||||
import {
|
||||
formatCountHumanReadable,
|
||||
@@ -13,7 +13,8 @@ import {
|
||||
normalizeTagToSearch,
|
||||
extractTagsFromTextArea,
|
||||
getCurrentTagRange,
|
||||
getViewportMargin
|
||||
getViewportMargin,
|
||||
IconSvgHtmlString
|
||||
} from './utils.js';
|
||||
import { settingValues } from './settings.js';
|
||||
|
||||
@@ -100,7 +101,7 @@ function searchCompletionCandidates(textareaElement) {
|
||||
queryVariations.add(hiraQuery);
|
||||
}
|
||||
|
||||
const sources = getTagSourceInPriorityOrder();
|
||||
const sources = getEnabledTagSourceInPriorityOrder();
|
||||
for (const source of sources) {
|
||||
// Search in sortedTags (already sorted by count)
|
||||
for (const tagData of autoCompleteData[source].sortedTags) {
|
||||
@@ -274,6 +275,13 @@ class AutocompleteUI {
|
||||
this.root = document.createElement('div'); // Use table instead of div
|
||||
this.root.id = 'autocomplete-plus-root';
|
||||
|
||||
// Create svg icon element as definition
|
||||
this.iconSvgDef = document.createElement('div');
|
||||
this.iconSvgDef.style.position = 'absolute';
|
||||
this.iconSvgDef.style.display = 'none';
|
||||
this.iconSvgDef.innerHTML = IconSvgHtmlString;
|
||||
this.root.appendChild(this.iconSvgDef);
|
||||
|
||||
this.tagsList = document.createElement('div');
|
||||
this.tagsList.id = 'autocomplete-plus-list';
|
||||
this.root.appendChild(this.tagsList);
|
||||
@@ -388,17 +396,24 @@ class AutocompleteUI {
|
||||
* @param {boolean} isExisting
|
||||
*/
|
||||
#createTagElement(tagData, isExisting) {
|
||||
const categoryText = DanbooruTagCategory[tagData.category] || "unknown";
|
||||
const categoryText = TagCategory[tagData.source][tagData.category] || "unknown";
|
||||
|
||||
const tagRow = document.createElement('div');
|
||||
tagRow.classList.add('autocomplete-plus-item');
|
||||
tagRow.classList.add('autocomplete-plus-item', tagData.source);
|
||||
tagRow.dataset.tag = tagData.tag;
|
||||
tagRow.dataset.tagCategory = categoryText;
|
||||
|
||||
// Tag name
|
||||
// Tag icon and name
|
||||
const tagSourceIconHtml = `<svg class="autocomplete-plus-tag-icon-svg"><use xlink:href="#autocomplete-plus-icon-${tagData.source}"></use></svg>`;
|
||||
const tagName = document.createElement('span');
|
||||
tagName.classList.add('autocomplete-plus-tag-name');
|
||||
tagName.textContent = `[${tagData.source[0]}] ${tagData.tag}`;
|
||||
tagName.className = 'autocomplete-plus-tag-name';
|
||||
if (settingValues.tagSourceIconPosition == 'hidden') {
|
||||
tagName.textContent = tagData.tag;
|
||||
} else {
|
||||
tagName.innerHTML = settingValues.tagSourceIconPosition == 'left'
|
||||
? `${tagSourceIconHtml} ${tagData.tag}`
|
||||
: `${tagData.tag} ${tagSourceIconHtml}`;
|
||||
}
|
||||
|
||||
// grayout tag name if it already exists
|
||||
if (isExisting) {
|
||||
@@ -407,7 +422,7 @@ class AutocompleteUI {
|
||||
|
||||
// Alias
|
||||
const alias = document.createElement('span');
|
||||
alias.classList.add('autocomplete-plus-alias');
|
||||
alias.className = 'autocomplete-plus-alias';
|
||||
|
||||
// Display alias if available
|
||||
if (tagData.alias && tagData.alias.length > 0) {
|
||||
@@ -420,10 +435,11 @@ class AutocompleteUI {
|
||||
const category = document.createElement('span');
|
||||
category.className = `autocomplete-plus-category`;
|
||||
category.textContent = `${categoryText.substring(0, 2)}`;
|
||||
category.title = categoryText; // Full category on hover
|
||||
|
||||
// Count
|
||||
const tagCount = document.createElement('span');
|
||||
category.className = `autocomplete-plus-tag-count`;
|
||||
tagCount.className = `autocomplete-plus-tag-count`;
|
||||
tagCount.textContent = formatCountHumanReadable(tagData.count);
|
||||
|
||||
tagRow.appendChild(tagName);
|
||||
@@ -458,7 +474,6 @@ class AutocompleteUI {
|
||||
const viewportHeight = window.innerHeight;
|
||||
const margin = getViewportMargin();
|
||||
|
||||
const targetRect = this.target.getBoundingClientRect();
|
||||
const targetElmOffset = this.#calculateElementOffset(this.target);
|
||||
|
||||
const { top: caretTop, left: caretLeft, lineHeight: caretLineHeight } = this.#getCaretCoordinates(this.target);
|
||||
|
||||
+31
-24
@@ -8,27 +8,27 @@ export const TagSource = {
|
||||
E621: 'e621',
|
||||
}
|
||||
|
||||
// Danbooru tag categories for display
|
||||
export const DanbooruTagCategory = [
|
||||
'general',
|
||||
'artist',
|
||||
'unused',
|
||||
'copyright',
|
||||
'character',
|
||||
'meta',
|
||||
]
|
||||
|
||||
export const E621TagCategory = [
|
||||
'general',
|
||||
'artist',
|
||||
'unused',
|
||||
'copyright',
|
||||
'character',
|
||||
'species',
|
||||
'invalid',
|
||||
'meta',
|
||||
'lore',
|
||||
]
|
||||
export const TagCategory = {
|
||||
'danbooru': [
|
||||
'general',
|
||||
'artist',
|
||||
'unused',
|
||||
'copyright',
|
||||
'character',
|
||||
'meta',
|
||||
],
|
||||
'e621': [
|
||||
'general',
|
||||
'artist',
|
||||
'unused',
|
||||
'copyright',
|
||||
'character',
|
||||
'species',
|
||||
'invalid',
|
||||
'meta',
|
||||
'lore',
|
||||
]
|
||||
}
|
||||
|
||||
// --- Data Structures ---
|
||||
|
||||
@@ -102,10 +102,17 @@ const COUNT_INDEX = TAGS_CSV_HEADER_COLUMNS.indexOf('count');
|
||||
// --- Helder Functions ---
|
||||
|
||||
/**
|
||||
*
|
||||
* Get the available tag sources in priority order based on the current settings.
|
||||
* @returns {string[]} Array of available tag sources in priority order
|
||||
*/
|
||||
export function getTagSourceInPriorityOrder() {
|
||||
return Object.values(TagSource).toSorted((a, b) => { return a === settingValues.priorityTagSource ? -1 : 1; });
|
||||
export function getEnabledTagSourceInPriorityOrder() {
|
||||
return Object.values(TagSource)
|
||||
.filter((s) => {
|
||||
return settingValues.tagSource === s || settingValues.tagSource === 'all';
|
||||
})
|
||||
.toSorted((a, b) => {
|
||||
return a === settingValues.primaryTagSource ? -1 : 1;
|
||||
});
|
||||
}
|
||||
|
||||
// --- Data Loading Functions ---
|
||||
|
||||
+25
-14
@@ -2,7 +2,7 @@ import { app } from "/scripts/app.js";
|
||||
import { ComfyWidgets } from "/scripts/widgets.js";
|
||||
import { settingValues } from "./settings.js";
|
||||
import { loadCSS } from "./utils.js";
|
||||
import { TagSource, fetchCsvList, getTagSourceInPriorityOrder, initializeData } from "./data.js";
|
||||
import { TagSource, fetchCsvList, initializeData } from "./data.js";
|
||||
import { AutocompleteEventHandler } from "./autocomplete.js";
|
||||
import { RelatedTagsEventHandler } from "./related-tags.js";
|
||||
|
||||
@@ -133,7 +133,7 @@ app.registerExtension({
|
||||
loadCSS(rootPath + "css/autocomplete-plus.css"); // Load CSS for autocomplete
|
||||
|
||||
fetchCsvList().then((csvList) => {
|
||||
getTagSourceInPriorityOrder().forEach((source) => {
|
||||
Object.values(TagSource).forEach((source) => {
|
||||
initializeData(csvList, source);
|
||||
});
|
||||
});
|
||||
@@ -141,29 +141,40 @@ app.registerExtension({
|
||||
|
||||
// One the Settings Screen, displays reverse order in same category
|
||||
settings: [
|
||||
// --- General Settings ---
|
||||
// --- Tag source Settings ---
|
||||
{
|
||||
id: id + ".priority_tag_source",
|
||||
name: "Priotized Tag Source",
|
||||
tooltip: "If all tag source are enabled, which tag source's tags should be displayed first.",
|
||||
id: id + ".tag_source_icon_position",
|
||||
name: "Tag Source Icon Position",
|
||||
type: "combo",
|
||||
options: ["left", "right", "hidden"],
|
||||
defaultValue: "left",
|
||||
category: [name, "Tag Source", "Tag Source Icon Position"],
|
||||
onChange: (newVal, oldVal) => {
|
||||
settingValues.tagSourceIconPosition = newVal;
|
||||
}
|
||||
},
|
||||
{
|
||||
id: id + ".primary_tag_source",
|
||||
name: "Primary source for 'all' Source",
|
||||
tooltip: "When 'Autocomplete Tag Source' is 'all', this determines which source's tags appear first in suggestions.",
|
||||
type: "combo",
|
||||
options: Object.values(TagSource),
|
||||
defaultValue: TagSource.Danbooru,
|
||||
category: [name, "General", "Priority Tag Source"],
|
||||
category: [name, "Tag Source", "Prioritize Tag Source"],
|
||||
onChange: (newVal, oldVal) => {
|
||||
settingValues.priorityTagSource = newVal;
|
||||
settingValues.primaryTagSource = newVal;
|
||||
}
|
||||
},
|
||||
{
|
||||
id: id + ".display_tag_source",
|
||||
name: "Display Tag Source",
|
||||
tooltip: "If multiple tag source are avirable, which tag source's tags should be displayed.",
|
||||
{
|
||||
id: id + ".tag_source",
|
||||
name: "Autocomplete Tag Source",
|
||||
tooltip: "Select the tag source for autocomplete suggestions. 'all' includes tags from all loaded sources.",
|
||||
type: "combo",
|
||||
options: [...Object.values(TagSource), "all"],
|
||||
defaultValue: "all",
|
||||
category: [name, "General", "Display Tag Source"],
|
||||
category: [name, "Tag Source", "Tag Source"],
|
||||
onChange: (newVal, oldVal) => {
|
||||
settingValues.displayTagSource = newVal;
|
||||
settingValues.tagSource = newVal;
|
||||
}
|
||||
},
|
||||
// --- Autocomplete Settings ---
|
||||
|
||||
+28
-11
@@ -1,4 +1,4 @@
|
||||
import { TagSource, DanbooruTagCategory, TagData, autoCompleteData, getTagSourceInPriorityOrder } from './data.js';
|
||||
import { TagSource, TagCategory, TagData, autoCompleteData } from './data.js';
|
||||
import { settingValues } from './settings.js';
|
||||
import {
|
||||
extractTagsFromTextArea,
|
||||
@@ -7,7 +7,7 @@ import {
|
||||
isValidTag,
|
||||
normalizeTagToInsert,
|
||||
normalizeTagToSearch,
|
||||
getCurrentTagRange
|
||||
getCurrentTagRange,
|
||||
} from './utils.js';
|
||||
|
||||
// --- RelatedTags Logic ---
|
||||
@@ -91,6 +91,7 @@ function searchRelatedTags(tag) {
|
||||
similarity: similarity,
|
||||
alias: tagData.alias,
|
||||
category: tagData.category,
|
||||
source: tagData.source,
|
||||
count: tagData.count,
|
||||
});
|
||||
});
|
||||
@@ -387,13 +388,29 @@ class RelatedTagsUI {
|
||||
* Updates header content
|
||||
*/
|
||||
#updateHeader() {
|
||||
// Find the tag data for the current tag
|
||||
const tagData = Object.values(TagSource)
|
||||
.map((source) => {
|
||||
if (source in autoCompleteData && autoCompleteData[source].tagMap.has(this.currentTag)) {
|
||||
return autoCompleteData[source].tagMap.get(this.currentTag);
|
||||
}
|
||||
})
|
||||
.find((tagData) => tagData !== undefined);
|
||||
|
||||
// Update header text with current tag
|
||||
this.headerText.innerHTML = ''; // Clear previous content
|
||||
this.headerText.textContent = 'Tags related to: ';
|
||||
const tagNameSpan = document.createElement('span');
|
||||
tagNameSpan.className = 'related-tags-header-tag-name';
|
||||
tagNameSpan.textContent = this.currentTag;
|
||||
this.headerText.appendChild(tagNameSpan);
|
||||
const tagName = document.createElement('span');
|
||||
tagName.className = 'related-tags-header-tag-name';
|
||||
tagName.textContent = this.currentTag;
|
||||
if (tagData && ['left', 'right'].includes(settingValues.tagSourceIconPosition)) {
|
||||
const tagSourceIconHtml = `<svg class="autocomplete-plus-tag-icon-svg"><use xlink:href="#autocomplete-plus-icon-${tagData.source}"></use></svg>`;
|
||||
tagName.innerHTML = settingValues.tagSourceIconPosition == 'left'
|
||||
? `${tagSourceIconHtml} ${tagData.tag}`
|
||||
: `${tagData.tag} ${tagSourceIconHtml}`;
|
||||
}
|
||||
|
||||
this.headerText.appendChild(tagName);
|
||||
|
||||
// Update pin button
|
||||
this.pinBtn.textContent = this.isPinned ? '🎯' : '📌';
|
||||
@@ -421,9 +438,9 @@ class RelatedTagsUI {
|
||||
|
||||
if (!this.relatedTags || this.relatedTags.length === 0) {
|
||||
// Show no related tags message
|
||||
const messageCell = document.createElement('div');
|
||||
messageCell.textContent = 'No related tags found';
|
||||
this.tagsContainer.appendChild(messageCell);
|
||||
const messageDiv = document.createElement('div');
|
||||
messageDiv.textContent = 'No related tags found';
|
||||
this.tagsContainer.appendChild(messageDiv);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -444,10 +461,10 @@ class RelatedTagsUI {
|
||||
* @returns {HTMLTableRowElement} The tag row element
|
||||
*/
|
||||
#createTagElement(tagData, isExisting) {
|
||||
const categoryText = DanbooruTagCategory[tagData.category] || "unknown";
|
||||
const categoryText = TagCategory[tagData.source][tagData.category] || "unknown";
|
||||
|
||||
const tagRow = document.createElement('div');
|
||||
tagRow.className = 'related-tag-item';
|
||||
tagRow.classList.add('related-tag-item', tagData.source);
|
||||
tagRow.dataset.tag = tagData.tag;
|
||||
tagRow.dataset.tagCategory = categoryText;
|
||||
|
||||
|
||||
+4
-3
@@ -1,7 +1,8 @@
|
||||
export const settingValues = {
|
||||
// General settings
|
||||
displayTagSource: 'danbooru', // 'danbooru', 'e621', 'all'
|
||||
priorityTagSource: 'danbooru', // 'danbooru', 'e621',
|
||||
// Tag source settings
|
||||
tagSource: 'all', // 'danbooru', 'e621', 'all'
|
||||
primaryTagSource: 'danbooru', // 'danbooru', 'e621'
|
||||
tagSourceIconPosition: 'left', // 'left', 'right', 'hidden'
|
||||
|
||||
// Autocomplete feature settings
|
||||
enabled: true,
|
||||
|
||||
+31
-2
@@ -1,3 +1,29 @@
|
||||
// --- Html String constants ---
|
||||
|
||||
/**
|
||||
* HTML string for the tag source icon.
|
||||
*/
|
||||
export const IconSvgHtmlString = `
|
||||
<svg>
|
||||
<defs>
|
||||
<symbol id="autocomplete-plus-icon-danbooru" viewBox="14 12 42 42">
|
||||
<polygon points="20,20 20,44 44,44 44,20" fill="#a67c52" stroke="#2d1400" stroke-width="2" stroke-linejoin="bevel"/>
|
||||
<polygon points="20,20 26,14 50,14 44,20" fill="#6e4b2c" stroke="#2d1400" stroke-width="2" stroke-linejoin="bevel"/>
|
||||
<polygon points="44,20 50,14 50,38 44,44" fill="#8b5e3c" stroke="#2d1400" stroke-width="2" stroke-linejoin="bevel"/>
|
||||
</symbol>
|
||||
<symbol id="autocomplete-plus-icon-e621" viewBox="-33 -38 66 76">
|
||||
<style>
|
||||
.e621-blue { fill: #0d2e69; }
|
||||
.e621-white { fill:rgb(230, 230, 230); }
|
||||
</style>
|
||||
<g>
|
||||
<path class="e621-blue" d="M0 -38 L32.909 -19 L32.909 19 L0 38 L-32.909 19 L-32.909 -19 Z"/>
|
||||
<text x="0" y="0" class="e621-white" font-family="Arial Black, Gadget, sans-serif" font-size="56" text-anchor="middle" dominant-baseline="middle">e</text>
|
||||
</g>
|
||||
</symbol>
|
||||
</defs>
|
||||
</svg>`;
|
||||
|
||||
// --- String Helper Functions ---
|
||||
|
||||
const MAX_PROMPT_WEIGHT_VALUE = 9.9;
|
||||
@@ -491,7 +517,10 @@ export function getCurrentTagRange(text, cursorPos) {
|
||||
|
||||
// --- End String Helper Functions ---
|
||||
|
||||
// Function to load a CSS file
|
||||
/**
|
||||
* Load a CSS file dynamically.
|
||||
* @param {string} href
|
||||
*/
|
||||
export function loadCSS(href) {
|
||||
const link = document.createElement('link');
|
||||
link.rel = 'stylesheet';
|
||||
@@ -500,7 +529,7 @@ export function loadCSS(href) {
|
||||
// Ensure the CSS is loaded before other scripts might rely on its styles
|
||||
// by adding it to the head.
|
||||
document.head.appendChild(link);
|
||||
console.debug(`Loaded CSS: ${href}`); // Optional: Log loading
|
||||
// console.debug(`[Autocomplete-Plus] Loaded CSS: ${href}`); // Optional: Log loading
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user