* fix(lyrics): correct TTML background-vocal cue timing and whitespace
Two parsing defects surfaced by Apple Music TTML files that mix a main
vocal with an x-bg (background) span group within the same line:
- Cue end-time normalization ran over the whole line's cue list in
document order. Background cues are stored after the main cues but
interleave earlier on the timeline, so the next-cue clamp collapsed the
last main cue's end down to its own start (start == end). End times are
now normalized per agent group, matching how the Subsonic serializer
already groups cues, so parallel layers no longer corrupt each other.
- Whitespace between elements was treated as significant: pretty-printed
(indented) TTML injected spurious newlines into the line text, turning
one line into many. Per TTML2 default xml:space handling (linefeeds
treat-as-space, whitespace-collapse), formatting whitespace now collapses
to a single space and hard line breaks come only from <br/>.
The line-level value and per-agent cueLine.value remain the full line text,
as required by the OpenSubsonic songLyrics v2 contract; the per-agent text
is carried in each cueLine's cue[] array.
Two existing tests that encoded the buggy newline-as-break behavior are
corrected; new tests cover whitespace collapse, <br/> preservation, and
interleaved background cue timing.
* fix(lyrics): only collapse XML whitespace, preserve other Unicode spaces
Whitespace collapsing used unicode.IsSpace, which matches more than the XML
S production (space, tab, CR, LF): it also folds characters like NBSP and
U+3000 into a regular space, silently altering content. Restrict collapsing
to the four XML whitespace characters so other Unicode spaces pass through
unchanged, and add a regression test. Also clarify the doc comment that
collapsing is applied unconditionally (xml:space="preserve" is not supported).