UNPKG

native-lyrics-tools

Version:

A JavaScript library for parsing and generating various lyric formats.

140 lines (124 loc) 3.08 kB
function parseProperty(str) { const match = str.match(/^\[(\d+)]/); if (!match) throw new Error("Invalid property format"); const code = parseInt(match[1], 10); const remaining = str.slice(match[0].length); const map = { 0: [false, false], 1: [false, false], 2: [false, true], 3: [false, false], 4: [false, false], 5: [false, true], 6: [true, false], 7: [true, false], 8: [true, true], }; return { remaining, is_bg: map[code]?.[0] ?? false, is_duet: map[code]?.[1] ?? false, }; } function parseWordTime(segment) { const match = segment.match(/^\((\d+),(\d+)\)/); if (!match) throw new Error("Invalid word time format"); const start_time = parseInt(match[1], 10); const duration = parseInt(match[2], 10); const remaining = segment.slice(match[0].length); return { remaining, start_time, end_time: start_time + duration, }; } function parseWord(str) { for (let i = 0; i < str.length; i++) { if (str[i] === '(') { const before = str.slice(0, i); try { const { remaining, start_time, end_time } = parseWordTime(str.slice(i)); return { remaining, word: { word: before, start_time, end_time, } }; } catch { continue; } } } throw new Error("Failed to parse word"); } function parseWords(str) { const words = []; while (str.length > 0) { try { const { word, remaining } = parseWord(str); words.push(word); str = remaining.trimStart(); } catch { break; } } return words; } function parseLine(line) { const { remaining, is_bg, is_duet } = parseProperty(line); const words = parseWords(remaining); return { is_bg, is_duet, words, start_time: words[0]?.start_time ?? 0, end_time: words.at(-1)?.end_time ?? 0, }; } function parseLys(src) { const lines = []; for (const rawLine of src.split(/\r?\n/)) { if (!rawLine.trim()) continue; try { const line = parseLine(rawLine); if (line.words && line.words.length > 0) { lines.push(line); } } catch { continue; } } // You can call a processLyrics() function here if needed return lines; } function stringifyLys(lines) { let result = ''; for (const line of lines) { if (!line.words.length) continue; const prop = (() => { if (line.is_bg && line.is_duet) return '[8]'; if (line.is_bg) return '[6]'; if (line.is_duet) return '[2]'; return '[0]'; })(); result += prop; for (const word of line.words) { result += word.word; result += `(${word.start_time},${word.end_time - word.start_time})`; } result += '\n'; } return result; } // Export for ES Module usage export { parseProperty, parseWordTime, parseWord, parseWords, parseLine, parseLys, stringifyLys };