refactor(lyrics): strip BOM once at ParseLyrics entry for all paths

Previously only the content-sniff path stripped the BOM; the suffix path
relied on its callers (fromExternalFile via UTF8Reader) having already
stripped it. That implicit contract was fragile — a caller passing raw
BOM-prefixed bytes with a suffix would reach the parsers with the BOM intact
(SanitizeText does not strip it). Strip once at entry so every path and
parser sees clean bytes regardless of caller. No-op for already-stripped
input.
This commit is contained in:
Deluan 2026-06-19 16:13:11 -04:00
commit 9622b23ed4

View file

@ -39,12 +39,16 @@ var lyricFormats = []struct {
// structured parser that does not match falls back to the LRC/plain-text floor —
// never to another structured format.
func ParseLyrics(suffix, lang string, contents []byte) (LyricList, error) {
// Strip a leading BOM once here so every parser sees clean bytes, regardless
// of which caller (file read, embedded tag, plugin, DB string) supplied them.
contents = stripBOM(contents)
if suffix == "" || strings.EqualFold(suffix, "auto") {
candidates := make([]lyricParser, len(lyricFormats))
for i, f := range lyricFormats {
candidates[i] = f.parse
}
return parseFirstMatch(lang, stripBOM(contents), candidates...)
return parseFirstMatch(lang, contents, candidates...)
}
for _, f := range lyricFormats {
if slices.ContainsFunc(f.suffixes, func(s string) bool { return strings.EqualFold(s, suffix) }) {