From 3f57e2ae26ee0184ebfba5d8e51b299f9f1347fc Mon Sep 17 00:00:00 2001 From: Honey Date: Fri, 24 Jul 2026 22:41:53 +0200 Subject: [PATCH] fix(web): metadata autofill normalizes trailing " & " in multi-artist lists MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Apple Music / MusicBrainz render multi-artist credits as "A, B, C & D" — the last artist is joined with " & " instead of the list separator, so it stayed glued to the previous one (e.g. "REI AMI & KPop Demon Hunters Cast" became a single artist that Navidrome's ";" split could not break apart). _fmtArtists now also rewrites " & " to the list separator, but only when the string is already a list (contains ; , • ·), so real band names like "Simon & Garfunkel" stay intact. The iTunes and MusicBrainz autofill results are now run through _fmtArtists too (previously set raw), so the artist field comes out ";"-separated and matches the Navidrome Tags.artist.Split config. Co-Authored-By: Claude Opus 4.8 --- src/ui/metadata.js | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/ui/metadata.js b/src/ui/metadata.js index a4f3d31..ce74e38 100644 --- a/src/ui/metadata.js +++ b/src/ui/metadata.js @@ -8,7 +8,14 @@ import { showConfirm } from './modals.js'; // ─── SONG INFO MODAL ─── function _fmtArtists(str, sep) { if (!str) return ''; - return str.split(/\s*[•·;,]\s*/).map(s => s.trim()).filter(Boolean).join(sep); + let s = str.trim(); + // Apple Music / MusicBrainz render multi-artist lists as "A, B, C & D" — the LAST artist is + // joined with " & " instead of the list separator, which would otherwise stay glued together as + // one artist. Only rewrite the " & " when the string is already a list (contains ; , • ·), so + // genuine band names like "Simon & Garfunkel" or "Earth, Wind & Fire" without a leading list are + // left intact. (Manual editor — the user can still fix the rare false positive before saving.) + if (/[;,•·]/.test(s)) s = s.replace(/\s+&\s+/g, '; '); + return s.split(/\s*[•·;,]\s*/).map(x => x.trim()).filter(Boolean).join(sep); } function _renderInfoModal(s) { @@ -178,8 +185,8 @@ export async function autofillMusicBrainz() { const d = await r.json(); if (!d.found) { status.textContent = '❌ Kein Treffer auf MusicBrainz'; return; } if (d.title) document.getElementById('ie-title').value = d.title; - if (d.artist) document.getElementById('ie-artist').value = d.artist; - if (d.albumArtist) document.getElementById('ie-albumartist').value = d.albumArtist; + if (d.artist) document.getElementById('ie-artist').value = _fmtArtists(d.artist, '; '); + if (d.albumArtist) document.getElementById('ie-albumartist').value = _fmtArtists(d.albumArtist, ', '); if (d.album) document.getElementById('ie-album').value = d.album; if (d.genre) document.getElementById('ie-genre').value = d.genre; if (d.year) document.getElementById('ie-year').value = d.year; @@ -213,8 +220,8 @@ export async function autofillItunes() { const d = await r.json(); if (!d.found) { status.textContent = '❌ Kein Treffer auf iTunes'; return; } if (d.title) document.getElementById('ie-title').value = d.title; - if (d.artist) document.getElementById('ie-artist').value = d.artist; - if (d.albumArtist) document.getElementById('ie-albumartist').value = d.albumArtist; + if (d.artist) document.getElementById('ie-artist').value = _fmtArtists(d.artist, '; '); + if (d.albumArtist) document.getElementById('ie-albumartist').value = _fmtArtists(d.albumArtist, ', '); if (d.album) document.getElementById('ie-album').value = d.album; if (d.genre) document.getElementById('ie-genre').value = d.genre; if (d.year) document.getElementById('ie-year').value = d.year;