refactor(js): tag-utils uses display_name and tag_id

getTagDisplayName is now a passthrough; post-refactor names are bare
and callers that need the character+fandom suffix pass tag.display_name
from the server. createTagChipHtml builds ?tag_id=<int> URLs and uses
display_name for the label. bulk-select.js callers pass display_name
directly.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-04-22 16:19:52 -04:00
parent c9fce48a39
commit 27609043e8
2 changed files with 33 additions and 33 deletions
+2 -2
View File
@@ -270,7 +270,7 @@
dom.commonTags.innerHTML = tags.map(t => { dom.commonTags.innerHTML = tags.map(t => {
const icon = getTagIcon(t.kind); const icon = getTagIcon(t.kind);
const display = getTagDisplayName(t.name, t.kind); const display = t.display_name || t.name;
const escapedName = escapeHtml(t.name); const escapedName = escapeHtml(t.name);
const escapedDisplay = escapeHtml(display); const escapedDisplay = escapeHtml(display);
return `<span class="tag-chip removable" data-name="${escapedName}"> return `<span class="tag-chip removable" data-name="${escapedName}">
@@ -605,7 +605,7 @@
dom.autocomplete.innerHTML = tags.map((t, i) => { dom.autocomplete.innerHTML = tags.map((t, i) => {
const icon = getTagIcon(t.kind); const icon = getTagIcon(t.kind);
const displayName = getTagDisplayName(t.name, t.kind); const displayName = t.display_name || t.name;
return `<div class="tag-autocomplete-item" data-index="${i}" data-name="${escapeHtml(t.name)}"> return `<div class="tag-autocomplete-item" data-index="${i}" data-name="${escapeHtml(t.name)}">
<span>${icon} ${escapeHtml(displayName)}</span> <span>${icon} ${escapeHtml(displayName)}</span>
<span class="tag-kind">${t.kind || 'user'}</span> <span class="tag-kind">${t.kind || 'user'}</span>
+31 -31
View File
@@ -24,35 +24,35 @@
} }
/** /**
* Get display name for a tag, stripping the prefix if present * Get display name for a tag.
* @param {string} name - Full tag name (e.g., "artist:Name") *
* @param {string} [kind] - Optional tag kind for context * Post-refactor tag names are stored bare (no kind: prefix), so this helper
* @returns {string} Display name without prefix * is now a near-passthrough. Callers that need character+fandom qualified
* names (e.g. "Ruby Rose (RWBY)") should pass `tag.display_name` from the
* server response directly.
*
* @param {string} name - Bare tag name
* @returns {string} The name unchanged
*/ */
function getTagDisplayName(name, kind) { function getTagDisplayName(name) {
// For prefixed kinds, strip the prefix
if (kind && ['artist', 'character', 'series', 'fandom', 'rating'].includes(kind)) {
return name.includes(':') ? name.split(':', 2)[1] : name;
}
// If no kind specified but has colon, assume it's prefixed
if (!kind && name.includes(':')) {
return name.split(':', 2)[1];
}
return name; return name;
} }
/** /**
* Get display name for tag overlay (used in gallery items) * Get overlay-formatted display name for a tag.
* Returns name with # prefix for unprefixed user tags *
* @param {string} name - Full tag name * User-kind (untyped) tags get a '#' hashtag prefix; every other kind
* gets the bare name (or whatever display form the caller passed).
*
* @param {string} name - Bare tag name or pre-rendered display_name
* @param {string} kind - Tag kind * @param {string} kind - Tag kind
* @returns {string} Display name for overlay * @returns {string} Overlay label
*/ */
function getTagDisplayNameForOverlay(name, kind) { function getTagDisplayNameForOverlay(name, kind) {
if (['artist', 'character', 'series', 'fandom', 'rating'].includes(kind)) { if (!kind || kind === 'user') {
return name.includes(':') ? name.split(':', 2)[1] : name; return '#' + name;
} }
return '#' + name; return name;
} }
/** /**
@@ -68,13 +68,13 @@
/** /**
* Format a tag for display with icon and name * Format a tag for display with icon and name
* @param {Object} tag - Tag object with name and kind * @param {Object} tag - Tag object with name, kind, and optional display_name
* @returns {string} Formatted HTML string * @returns {string} Formatted HTML string
*/ */
function formatTagHtml(tag) { function formatTagHtml(tag) {
const icon = getTagIcon(tag.kind); const icon = getTagIcon(tag.kind);
const displayName = getTagDisplayName(tag.name, tag.kind); const label = tag.display_name || tag.name;
const escaped = escapeHtml(displayName); const escaped = escapeHtml(label);
if (icon !== '#') { if (icon !== '#') {
return `${icon} ${escaped}`; return `${icon} ${escaped}`;
@@ -83,21 +83,21 @@
} }
/** /**
* Create tag chip HTML for gallery overlays * Create tag chip HTML for gallery overlays.
* @param {Object} tag - Tag object with name and kind *
* @param {Object} tag - Tag object with id, name, kind, and optional display_name
* @param {boolean} [stopPropagation=true] - Add onclick to stop propagation * @param {boolean} [stopPropagation=true] - Add onclick to stop propagation
* @returns {string} HTML string for tag chip link * @returns {string} HTML string for tag chip link
*/ */
function createTagChipHtml(tag, stopPropagation = true) { function createTagChipHtml(tag, stopPropagation = true) {
const icon = getTagIcon(tag.kind); const icon = getTagIcon(tag.kind);
const displayName = getTagDisplayNameForOverlay(tag.name, tag.kind); const label = tag.display_name || getTagDisplayNameForOverlay(tag.name, tag.kind);
const encodedName = encodeURIComponent(tag.name); const escapedLabel = escapeHtml(label);
const escapedTitle = escapeHtml(tag.name); const escapedTitle = escapeHtml(tag.display_name || tag.name);
const escapedDisplay = escapeHtml(displayName); const prefix = icon !== '#' ? icon + ' ' : '';
const prefix = icon !== '#' ? icon + ' ' : '#';
const onclick = stopPropagation ? ' onclick="event.stopPropagation()"' : ''; const onclick = stopPropagation ? ' onclick="event.stopPropagation()"' : '';
return `<a class="tag-chip" href="/gallery?tag=${encodedName}" title="Filter by ${escapedTitle}"${onclick}>${prefix}${escapedDisplay}</a>`; return `<a class="tag-chip tag-chip-${tag.kind || 'user'}" href="/gallery?tag_id=${tag.id}" title="Filter by ${escapedTitle}"${onclick}>${prefix}${escapedLabel}</a>`;
} }
// Export to window.TagUtils // Export to window.TagUtils