Feed and profile cards now show one slim line (small artwork, title, artist, Open button) with the progress bar and reactions. The arrow opens the rest: album, your other services, Share, and lyrics. Lyrics come from LRCLIB (open source; LRCLIB_URL can point at a self-hosted copy, or be empty to turn lyrics off). The server looks each song up once and caches it, including misses (retried after a week). Timed lyrics follow along with the song; otherwise the first lines show with "All lyrics". Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
26 lines
974 B
TypeScript
26 lines
974 B
TypeScript
import { describe, expect, it } from 'vitest';
|
|
import { currentLyricIndex, parseLrc } from './lyrics';
|
|
|
|
describe('parseLrc', () => {
|
|
it('reads timestamps, skips tags, and sorts lines repeated by several tags', () => {
|
|
const lines = parseLrc('[ar:M83]\n[00:12.50] Waiting in a car\n[00:05.00][01:00.1]Chorus\n[00:20.00]\n\nnot a lyric');
|
|
expect(lines).toEqual([
|
|
{ timeMs: 5000, text: 'Chorus' },
|
|
{ timeMs: 12500, text: 'Waiting in a car' },
|
|
{ timeMs: 20000, text: '' },
|
|
{ timeMs: 60100, text: 'Chorus' },
|
|
]);
|
|
});
|
|
});
|
|
|
|
describe('currentLyricIndex', () => {
|
|
const lines = parseLrc('[00:05.00]a\n[00:10.00]b\n[00:15.00]c');
|
|
it('finds the line being sung', () => {
|
|
expect(currentLyricIndex(lines, 0)).toBe(-1);
|
|
expect(currentLyricIndex(lines, 5000)).toBe(0);
|
|
expect(currentLyricIndex(lines, 14_999)).toBe(1);
|
|
expect(currentLyricIndex(lines, 99_000)).toBe(2);
|
|
expect(currentLyricIndex([], 1000)).toBe(-1);
|
|
});
|
|
});
|