fix(artist pin): esc() crashed on numeric Deezer id; move pin button to banner top-right

- esc() now coerces to string first (String(s ?? '')), so passing a number (e.g. the
  Deezer artist id in the pin picker) no longer throws 'replace is not a function'.
- The '⚙ Falscher Künstler?' button moved from under the fan count to the top-right
  of the artist banner (absolute, on the hero). SW cache -> ns-v75.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
HoneyandClaude Opus 4.8 committed 2026-08-13 00:16:14 +02:00
1 parent 02960cf886
commit 5f251d555f
3 files changed
+14 -15

No files matched your search

+3 -1
View File
@@ -36,7 +36,9 @@ export function md5(input) {
}
export function esc(s) {
return (s||'').replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/"/g,'&quot;');
// Coerce to string first — callers sometimes pass numbers (e.g. a Deezer artist id), which
// would throw on .replace. null/undefined → ''.
return String(s ?? '').replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/"/g,'&quot;');
}
export function formatDur(s) {
+10 -13
View File
@@ -94,19 +94,16 @@ export async function loadArtistDetail(artist) {
const knownFans = _pin?.fanCount ?? artist.deezerFanCount ?? null;
if (knownFans) _showFans(knownFans); // from the global-search card / pin — show immediately
// "Falscher Künstler?" pin button (local artists only) — fix a wrong same-name Deezer match.
if (hasND) {
const infoEl = hero.querySelector('.artist-hero-info');
infoEl?.querySelector('.artist-pin-btn')?.remove();
if (infoEl) {
const pinBtn = document.createElement('button');
pinBtn.className = 'artist-pin-btn';
pinBtn.textContent = _pin ? '⚙ Künstler gepinnt' : '⚙ Falscher Künstler?';
pinBtn.title = 'Richtigen Deezer-Künstler wählen';
pinBtn.style.cssText = 'margin-top:8px;padding:5px 12px;border-radius:999px;border:1px solid var(--border2);background:rgba(0,0,0,.35);color:#fff;font-family:var(--font);font-size:12px;font-weight:600;cursor:pointer';
pinBtn.onclick = () => openArtistPin(artist.id, artist.name);
infoEl.appendChild(pinBtn);
}
// "Falscher Künstler?" pin button (local artists only) — top-right of the banner.
if (hasND && hero) {
hero.querySelector('.artist-pin-btn')?.remove();
const pinBtn = document.createElement('button');
pinBtn.className = 'artist-pin-btn';
pinBtn.textContent = _pin ? '⚙ Gepinnt' : '⚙ Falscher Künstler?';
pinBtn.title = 'Richtigen Deezer-Künstler wählen';
pinBtn.style.cssText = 'position:absolute;top:12px;right:12px;z-index:5;padding:5px 12px;border-radius:999px;border:1px solid rgba(255,255,255,.25);background:rgba(0,0,0,.45);color:#fff;font-family:var(--font);font-size:12px;font-weight:600;cursor:pointer;backdrop-filter:blur(4px)';
pinBtn.onclick = () => openArtistPin(artist.id, artist.name);
hero.appendChild(pinBtn);
}
// Fire all requests immediately so they run in parallel.