Preserve and display bilingual and phonetic lyric cues
This commit is contained in:
@@ -56,6 +56,11 @@
|
||||
return String(s).split(/[,|·]/).map((x) => x.trim()).filter(Boolean);
|
||||
}
|
||||
|
||||
function display(line) {
|
||||
const text = String(line?.text || ''), divider = text.indexOf(' / ');
|
||||
return { text: divider < 0 ? text : text.slice(0, divider).trim(), secondary: line?.secondary || (divider < 0 ? '' : text.slice(divider + 3).trim()), phonetic: line?.phonetic || '' };
|
||||
}
|
||||
|
||||
// Editor text → { lines, tags, offset }.
|
||||
function fromText(text) {
|
||||
const lines = [];
|
||||
@@ -65,8 +70,14 @@
|
||||
for (const rawLine of String(text || '').replace(/\r/g, '').split('\n')) {
|
||||
let rest = rawLine.trim();
|
||||
if (!rest) continue;
|
||||
if (/^!pinyin:\s*/i.test(rest) && group.some(l => l.kind === 'line')) {
|
||||
const value = rest.replace(/^!pinyin:\s*/i, '').trim();
|
||||
for (const line of group) if (value) line.phonetic = line.phonetic ? line.phonetic + '\n' + value : value;
|
||||
continue;
|
||||
}
|
||||
if (rest.startsWith('| ') && group.length) {
|
||||
for (const line of group) line.text += '\n' + rest.slice(2).trim();
|
||||
const extra = display({ text: rest.slice(2).trim() });
|
||||
for (const line of group) { line.text += '\n' + extra.text; if (extra.secondary) line.secondary = line.secondary ? line.secondary + '\n' + extra.secondary : extra.secondary; }
|
||||
continue;
|
||||
}
|
||||
group = [];
|
||||
@@ -92,6 +103,7 @@
|
||||
if (!rest) continue;
|
||||
group = stamps.length ? stamps.map(t => ({ t: Math.round(t * 100) / 100, text: rest, kind }))
|
||||
: [{ t: null, text: rest, kind }];
|
||||
if (kind === 'line') for (const line of group) { const parts = display(line); line.text = parts.text; if (parts.secondary) line.secondary = parts.secondary; }
|
||||
lines.push(...group);
|
||||
}
|
||||
// A fully timed sheet (typical .lrc with repeated-chorus stamps) is put in
|
||||
@@ -108,8 +120,11 @@
|
||||
for (const l of (doc && doc.lines) || []) {
|
||||
const stamp = l.t === null || l.t === undefined ? '' : `[${fmtStamp(l.t)}] `;
|
||||
const mark = l.kind === 'section' ? '# ' : l.kind === 'cue' ? '! ' : '';
|
||||
const parts = String(l.text || '').split('\n');
|
||||
out.push(stamp + mark + parts[0], ...parts.slice(1).map(part => '| ' + part));
|
||||
const parts = (l.kind === 'line' ? display(l) : { text: l.text || '', secondary: '' });
|
||||
const primary = parts.text.split('\n'), secondary = parts.secondary.split('\n');
|
||||
const combined = primary.map((part, i) => part + (secondary[i] ? ' / ' + secondary[i] : ''));
|
||||
out.push(stamp + mark + combined[0], ...combined.slice(1).map(part => '| ' + part));
|
||||
if (l.phonetic) out.push(...String(l.phonetic).split('\n').map(part => '!pinyin: ' + part));
|
||||
}
|
||||
return out.join('\n');
|
||||
}
|
||||
@@ -162,7 +177,7 @@
|
||||
}
|
||||
|
||||
const LyricsCore = {
|
||||
parseStamp, fmtStamp, fmtClock, fromText, toText,
|
||||
parseStamp, fmtStamp, fmtClock, fromText, toText, display,
|
||||
activeIndex, activeSection, timedCount, activeMarker, toYouTubeTimestamps,
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user