@@ -3,29 +3,54 @@ const trackInitializer = {
33 if ( ! lyricsElement ) return ;
44
55 const track = document . querySelector ( `[id^="trackDetails${ trackIndex } "]` ) ;
6- const ignoredWordsStr = track ?. dataset . ignoredWords || '' ;
7- const ignoredWords = ignoredWordsStr . split ( ',' ) . map ( w => w . trim ( ) . toLowerCase ( ) ) . filter ( Boolean ) ;
8- const ignoredWordsSet = new Set ( ignoredWords ) ;
9-
10- const words = lyricsElement . innerHTML
11- . split ( / \n / )
12- . map ( line => line . trim ( )
13- . split ( / ( \s + ) / )
14- . map ( word => {
15- const cleanedWord = cleanWord ( word ) ;
16- if ( cleanedWord . length > 0 && ignoredWordsSet . has ( cleanedWord ) ) {
17- return word ;
18- }
19- if ( cleanedWord . length > 0 ) {
20- return this . createWordSpan ( word , cleanedWord , trackIndex ) ;
21- }
22- return word ;
23- } )
24- . join ( '' )
25- )
26- . join ( '\n' ) ;
27-
28- lyricsElement . innerHTML = words ;
6+
7+ const ignoredWords = ( track ?. dataset . ignoredWords || '' ) . split ( ',' ) . map ( w => w . trim ( ) ) . filter ( Boolean ) ;
8+ const patterns = new Set ( ignoredWords . filter ( w => / [ ( ) [ \] { } : ] / . test ( w ) ) ) ;
9+ const exactWords = new Set ( ignoredWords . filter ( w => ! / [ ( ) [ \] { } : ] / . test ( w ) ) ) ;
10+
11+ const expandedIgnoredSet = new Set ( exactWords ) ;
12+ exactWords . forEach ( word => {
13+ const cleaned = cleanWord ( word ) ;
14+ if ( cleaned ) expandedIgnoredSet . add ( cleaned ) ;
15+ } ) ;
16+
17+ const lines = lyricsElement . innerHTML . split ( / \n / ) ;
18+ const processedLines = lines . map ( line => {
19+ let result = line ;
20+
21+ patterns . forEach ( ignored => {
22+ const escapedIgnored = ignored . replace ( / [ . * + ? ^ $ { } ( ) | [ \] \\ ] / g, '\\$&' ) ;
23+ const regex = new RegExp ( `(${ escapedIgnored } )` , 'g' ) ;
24+ result = result . replace ( regex , ( match ) => match ) ;
25+ } ) ;
26+
27+ const words = result . split ( / ( \s + ) / ) ;
28+ return words . map ( segment => {
29+ if ( ! segment . trim ( ) ) return segment ;
30+
31+ if ( patterns . has ( segment ) ) return segment ;
32+
33+ const cleanedWord = cleanWord ( segment ) ;
34+ if ( ! cleanedWord ) return segment ;
35+
36+ if ( expandedIgnoredSet . has ( cleanedWord ) ) return segment ;
37+
38+ return this . createWordSpan ( segment , cleanedWord , trackIndex ) ;
39+ } ) . join ( '' ) ;
40+ } ) ;
41+
42+ lyricsElement . innerHTML = processedLines . join ( '\n' ) ;
43+
44+ const wordCountContainer = track . querySelector ( '.word-counts' ) ;
45+ if ( wordCountContainer ) {
46+ const wordCountElements = wordCountContainer . querySelectorAll ( '[id^="wordCount"]' ) ;
47+ wordCountElements . forEach ( element => {
48+ const word = element . getAttribute ( 'data-word' ) ;
49+ if ( expandedIgnoredSet . has ( word ) ) {
50+ element . remove ( ) ;
51+ }
52+ } ) ;
53+ }
2954 } ,
3055
3156 createWordSpan ( originalWord , cleanedWord , trackIndex ) {
@@ -158,4 +183,35 @@ function copyDebugInfo(trackIndex) {
158183 } ) ;
159184}
160185window . copyDebugInfo = copyDebugInfo ;
161- window . trackInitializer = trackInitializer ;
186+ window . trackInitializer = trackInitializer ;
187+
188+ function copyIgnoredWordsInfo ( trackIndex ) {
189+ const trackElement = document . querySelector ( `[id^="trackDetails${ trackIndex } "]` ) ;
190+ const ignoredWordsStr = trackElement ?. dataset . ignoredWords || '' ;
191+ const lyrics = document . getElementById ( `lyrics${ trackIndex } ` ) . innerHTML ;
192+
193+ const info = {
194+ trackIndex,
195+ ignoredWords : ignoredWordsStr ,
196+ ignoredWordsList : ignoredWordsStr . split ( ',' ) . map ( w => w . trim ( ) ) . filter ( Boolean ) ,
197+ trackHTML : lyrics ,
198+ wordElements : Array . from ( document . querySelectorAll ( `.word[data-track="${ trackIndex } "]` ) )
199+ . map ( el => ( {
200+ word : el . getAttribute ( 'data-word' ) ,
201+ isInteractive : true
202+ } ) ) ,
203+ textNodes : Array . from ( document . getElementById ( `lyrics${ trackIndex } ` ) . childNodes )
204+ . filter ( node => node . nodeType === 3 )
205+ . map ( node => node . textContent . trim ( ) )
206+ . filter ( text => text . length > 0 )
207+ } ;
208+
209+ navigator . clipboard . writeText ( JSON . stringify ( info , null , 2 ) ) . then ( ( ) => {
210+ const button = document . querySelector ( `button[onclick="copyIgnoredWordsInfo(${ trackIndex } )"]` ) ;
211+ button . textContent = 'Copied!' ;
212+ setTimeout ( ( ) => {
213+ button . textContent = 'Debug Ignored Words' ;
214+ } , 2000 ) ;
215+ } ) ;
216+ }
217+ window . copyIgnoredWordsInfo = copyIgnoredWordsInfo ;
0 commit comments