refactor(lyrics): trim verbose comments to essential why

This commit is contained in:
Deluan 2026-06-19 16:17:31 -04:00
commit 8190e3a535
4 changed files with 13 additions and 28 deletions

View file

@ -414,9 +414,7 @@ func parseTime(line string, match []int) (int64, error) {
type LyricList []Lyrics
// MarshalJSON owns the lyrics column invariant: an empty or nil list serializes
// to [], never null. This keeps every writer consistent without each one having
// to pre-initialize or nil-guard the slice.
// MarshalJSON keeps the lyrics column invariant: empty/nil serializes to [], never null.
func (ll LyricList) MarshalJSON() ([]byte, error) {
if len(ll) == 0 {
return []byte("[]"), nil

View file

@ -9,21 +9,17 @@ import (
"github.com/navidrome/navidrome/log"
)
// lyricParser parses a single lyrics format. It returns an empty list (not an
// error) when the input is well-formed but not its format, so candidates can be
// tried in order. The lang argument is the default language for formats that do
// not carry their own.
// lyricParser returns an empty list (not an error) when the input is not its
// format, so parsers can be tried in order. lang is the default for formats that
// do not carry their own.
type lyricParser func(lang string, contents []byte) (LyricList, error)
func parseLyricsfileBytes(_ string, contents []byte) (LyricList, error) {
return parseLyricsfile(string(contents))
}
// lyricFormats lists the structured formats. Each parser is self-skipping: it
// returns an empty list (not an error) when the content is not its format, so it
// is safe to try in order. Slice order is the content-sniff probe order
// (TTML → SRT → YAML); each row's suffixes drive sidecar dispatch. LRC/plain is
// not listed — it is the fallback floor for both paths.
// lyricFormats is the structured formats in content-sniff probe order; each
// row's suffixes drive sidecar dispatch. LRC/plain is the unlisted fallback floor.
var lyricFormats = []struct {
suffixes []string
parse lyricParser
@ -33,14 +29,10 @@ var lyricFormats = []struct {
{[]string{".yaml", ".yml"}, parseLyricsfileBytes},
}
// ParseLyrics is the single entry point for parsing lyrics. A known suffix
// (.ttml/.srt/.yaml/.yml/.lrc) routes to that format's parser; an empty or
// "auto" suffix content-sniffs by trying each format in order. In both modes a
// structured parser that does not match falls back to the LRC/plain-text floor —
// never to another structured format.
// ParseLyrics is the single entry point for parsing lyrics. A known suffix routes
// to that format's parser; an empty or "auto" suffix content-sniffs. Either way,
// a structured parser that does not match falls back to the LRC/plain-text floor.
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") {
@ -55,11 +47,9 @@ func ParseLyrics(suffix, lang string, contents []byte) (LyricList, error) {
return parseFirstMatch(lang, contents, f.parse)
}
}
return plainLRC(lang, contents) // .lrc and any unknown suffix
return plainLRC(lang, contents)
}
// parseFirstMatch tries each candidate in order, returning the first non-empty
// result. When every candidate misses, it falls to the LRC/plain-text floor.
func parseFirstMatch(lang string, contents []byte, candidates ...lyricParser) (LyricList, error) {
for _, parse := range candidates {
list, err := parse(lang, contents)

View file

@ -109,10 +109,8 @@ func parseTTML(contents []byte) (LyricList, error) {
func parseTTMLWithDefaultLang(defaultLang string, contents []byte) (LyricList, error) {
contents = xmlEncodingRegex.ReplaceAll(contents, []byte(`<?xml$1encoding="UTF-8"$2?>`))
// Self-skip non-TTML content (returns nil, nil) so content-sniffing does not
// run the XML decoder on plain text or LRC. Checked after the encoding fixup
// above so a UTF-16-declared document is still recognized. Content that is a
// <tt> document but malformed still parses below and surfaces its error.
// Skip non-TTML content so sniffing doesn't run the XML decoder on plain text.
// Checked after the encoding fixup so UTF-16-declared documents are recognized.
if !isTTMLDocument(string(contents)) {
return nil, nil
}

View file

@ -20,8 +20,7 @@ func (t *testLyrics) GetLyrics(input lyrics.GetLyricsRequest) (lyrics.GetLyricsR
return lyrics.GetLyricsResponse{}, fmt.Errorf("%s", errMsg)
}
// Config-selected formats let integration tests prove the adapter's content-sniffing
// detects each format; plain-text parsing would silently mangle the rich ones.
// Config-selected format lets tests exercise the adapter's content-sniffing per format.
format, hasFormat := pdk.GetConfig("format")
if hasFormat {
var text string