Skip to content

Commit 50257d4

Browse files
committed
FEATURE: handle karaoke groups better
1 parent 666652f commit 50257d4

File tree

11 files changed

+198
-91
lines changed

11 files changed

+198
-91
lines changed

dist/editor/index.js

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/editor/index.js.map

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/script/index.js

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/script/index.js.map

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/web/index.js

+115-59
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/web/index.js.map

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/editor/tsconfig.json

-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
{
22
"extends": "../../tsconfig.base.json",
33
"compilerOptions": {
4-
"module": "esnext"
54
},
65
"include": [
76
"./**/*.ts",

src/web/caption-renderer.ts

+12-7
Original file line numberDiff line numberDiff line change
@@ -19,20 +19,25 @@ export class CaptionRenderer {
1919
}
2020

2121
private renderWord(word: Word, caption: Caption): HTMLSpanElement {
22+
const cssClasses = CaptionRenderer.wordSpanClasses(word);
2223
const wordSpan = document.createElement('span');
2324
wordSpan.textContent = word.rawWord;
25+
wordSpan.classList.add(...cssClasses);
26+
27+
return this.cssProcessor.applyDynamicClasses(wordSpan, caption.index, caption.startTimeMs, [ word.rawWord ]);
28+
}
29+
30+
public static wordSpanClasses(word: Word): Set<string> {
31+
const cssClasses = new Set([ 'word' ]);
2432

25-
let cssClass = 'word'
2633
if (word.isHighlighted) {
27-
cssClass += ' ' + (word.highlightClass || 'highlighted');
34+
cssClasses.add(word.highlightClass || 'highlighted');
2835
} if (word.isBeforeHighlighted) {
29-
cssClass += ' before-highlighted';
36+
cssClasses.add('before-highlighted');
3037
} if (word.isAfterHighlighted) {
31-
cssClass += ' after-highlighted';
38+
cssClasses.add('after-highlighted');
3239
}
3340

34-
wordSpan.setAttribute('class', cssClass);
35-
36-
return this.cssProcessor.applyDynamicClasses(wordSpan, caption.index, caption.startTimeMs, [ word.rawWord ]);
41+
return cssClasses;
3742
}
3843
}

src/web/css-processor.ts

+18-5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import {AbstractDynamicCssRule, createDynamicCssRule, Filter, FilterType} from '../script/dynamic-css-rules';
22

3+
const dynamicCssClassPrefix = 'pup-';
34
const dynamicCssClassPattern = /^\.pup-(\w+)((?:-[^-]+)+)$/;
45

56
export class CssProcessor {
@@ -38,16 +39,28 @@ export class CssProcessor {
3839

3940
public applyDynamicClasses<T extends HTMLElement>(target: T, captionIndex: number, timeMs: number, words: string[]): T {
4041
const dynamicCssClasses = this.dynamicCssClasses(target, captionIndex, timeMs, words);
41-
let cssClass = target.getAttribute('class') || '';
42-
dynamicCssClasses.forEach(dynamicClass => cssClass += ' ' + dynamicClass);
43-
target.setAttribute('class', cssClass);
42+
const existingDynamicClasses = CssProcessor.getDynamicCssClassesFromElem(target);
43+
44+
const classesToRemove = existingDynamicClasses.difference(dynamicCssClasses);
45+
const classesToAdd = dynamicCssClasses.difference(classesToRemove);
46+
47+
target.classList.remove(...classesToRemove);
48+
target.classList.add(...classesToAdd);
49+
4450
return target;
4551
}
4652

47-
private dynamicCssClasses(target: HTMLElement, captionIndex: number, timeMs: number, words: string[]): string[] {
48-
return this.dynamicCssRules
53+
private dynamicCssClasses(target: HTMLElement, captionIndex: number, timeMs: number, words: string[]): Set<string> {
54+
const cssClasses = this.dynamicCssRules
4955
.filter(rule => rule.isApplied(target, captionIndex, timeMs, words))
5056
.map(rule => rule.appliedCssClass);
57+
return new Set(cssClasses);
58+
}
59+
60+
public static getDynamicCssClassesFromElem(elem: HTMLElement): Set<string> {
61+
const dynamicCssClasses = [...elem.classList.values()]
62+
.filter(cssClass => cssClass.startsWith(dynamicCssClassPrefix));
63+
return new Set(dynamicCssClasses);
5164
}
5265

5366
static parseFilter(dynamicCssClass: string): Filter {

0 commit comments

Comments
 (0)