From ff3bb782d38ae61fcd148e8b295c9424d17a0add Mon Sep 17 00:00:00 2001 From: Honey Date: Fri, 5 Jun 2026 00:26:39 +0200 Subject: [PATCH] fix: romaji override delete button (JSON.stringify breaks HTML attr); fix file stem search for en-dash track prefixes Co-Authored-By: Claude Sonnet 4.6 --- backend/novasonic-server.js | 22 +++++++++++++++++----- src/ui.js | 2 +- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/backend/novasonic-server.js b/backend/novasonic-server.js index 85f53cb..84d03aa 100644 --- a/backend/novasonic-server.js +++ b/backend/novasonic-server.js @@ -95,19 +95,31 @@ function _findFileInDir(dir, basename) { // Convention: MusicRoot/AlbumArtist/Album/{01 - }Artist - Title.ext // The title stem is everything after the optional "NN - Artist - " prefix. // We match any audio file whose stem ends with the same title words. +// Normalize a file stem for loose matching: +// 1. Strip compound track prefixes like "01-15 – " or "01 - " (handles en-dash, em-dash, hyphen) +// 2. Normalize all dash variants (en-dash, em-dash) to " - " +function _normStem(s) { + return s + .replace(/^\d[\d\-–—]*\s*[-–—]\s*/, '') // strip leading "01-15 – " or "01 - " + .replace(/\s*[–—]\s*/g, ' - '); // normalize remaining en/em-dash to " - " +} + function _findFileByStem(dir, titleStem, depth = 0) { if (depth > 4) return null; + const normTitle = _normStem(titleStem); try { for (const entry of fs.readdirSync(dir, { withFileTypes: true })) { if (entry.isDirectory()) { const found = _findFileByStem(path.join(dir, entry.name), titleStem, depth + 1); if (found) return found; } else if (AUDIO_EXT_RE.test(entry.name)) { - // Strip extension, strip leading "NN - ", then strip optional "Artist - " prefix - const bare = entry.name.replace(AUDIO_EXT_RE, '').replace(/^\d+\s*-\s*/, ''); - // bare may be "Artist - Title" or just "Title" — match from the end - const bareStem = bare.toLowerCase(); - if (bareStem === titleStem || bareStem.endsWith(' - ' + titleStem) || bareStem.endsWith(titleStem)) { + // Strip extension + leading track prefix, then normalize dashes + const bare = entry.name.replace(AUDIO_EXT_RE, '').replace(/^\d+\s*-\s*/, ''); + const bareStem = _normStem(bare.toLowerCase()); + // Match: exact, or "Artist - Title" ending with our title stem + if (bareStem === normTitle || + bareStem.endsWith(' - ' + normTitle) || + bareStem.endsWith(normTitle)) { return path.join(dir, entry.name); } } diff --git a/src/ui.js b/src/ui.js index 5c4c9fb..155d61f 100644 --- a/src/ui.js +++ b/src/ui.js @@ -84,7 +84,7 @@ function _renderRomajiOverrides() { ${esc(k)} → ${esc(v)} - + ` ).join(''); }