fix(overlay): deduplicate secondary subtitle rendering (#208)

This commit is contained in:
2026-08-18 00:44:02 -07:00
committed by GitHub
parent 7de73e16a1
commit e9778a945a
21 changed files with 749 additions and 71 deletions
+16 -3
View File
@@ -1424,10 +1424,11 @@ test('subtitle annotation CSS underlines JLPT tokens without changing token colo
);
});
test('prepareSecondarySubtitleLines drops layered duplicate lines in short stacks', () => {
// A word-level animation stacks one event per layer copy; the stack is too short for
// the karaoke heuristic but the duplicates are still never distinct content.
test('prepareSecondarySubtitleLines preserves short stacks without layer metadata', () => {
assert.deepEqual(prepareSecondarySubtitleLines('Your\\NYour\\NYour\\NYour\\Nmosaic'), [
'Your',
'Your',
'Your',
'Your',
'mosaic',
]);
@@ -1447,6 +1448,18 @@ test('prepareSecondarySubtitleLines collapses karaoke syllable spam into one ded
assert.deepEqual(prepareSecondarySubtitleLines(karaoke), ['ya This no ma ups']);
});
test('prepareSecondarySubtitleLines preserves repeated short dialogue without layer metadata', () => {
const dialogue = ['Wait', 'Wait', 'Wait'];
assert.deepEqual(prepareSecondarySubtitleLines(dialogue.join('\\N')), dialogue);
});
test('prepareSecondarySubtitleLines preserves short simultaneous dialogue without repeats', () => {
const dialogue = ['Wait', 'Go!', 'No!', 'Run!'];
assert.deepEqual(prepareSecondarySubtitleLines(dialogue.join('\\N')), dialogue);
});
test('prepareSecondarySubtitleLines keeps normal dialogue lines intact', () => {
const dialogue = ' I never expected this. \\N\\N But here we are. ';
+3 -9
View File
@@ -677,12 +677,10 @@ export function prepareSecondarySubtitleLines(text: string): string[] {
.split('\n')
.map((line) => line.trim())
.filter((line) => line.length > 0);
if (!isKaraokeLikeLineSet(lines)) {
return lines;
}
// Identical lines in one render are layered copies of the same event (animation
// scripts stack several per glyph), never distinct content -- always drop them, so a
// short stack like "Your ×4 / mosaic" collapses without needing the karaoke
// heuristic. Karaoke-likeness is still judged on the raw stack, where the layered
// repetition is the signal.
const seen = new Set<string>();
const unique: string[] = [];
for (const line of lines) {
@@ -690,10 +688,6 @@ export function prepareSecondarySubtitleLines(text: string): string[] {
seen.add(line);
unique.push(line);
}
if (!isKaraokeLikeLineSet(lines)) {
return unique;
}
return [unique.join(' ')];
}