@@ -53,6 +53,25 @@ define(function (require, exports, module) {
5353 description : Strings . DESCRIPTION_CSS_COLOR_PREVIEW
5454 } ) ;
5555
56+
57+ /**
58+ * Helper function to find the nth occurrence of a substring in a string
59+ * @param {String } str the line text
60+ * @param {String } substr color
61+ * @param {Number } nth the occurence count of the color
62+ * @return {Number } the index of the nth occurence
63+ */
64+ function findNthOccurrence ( str , substr , nth ) {
65+ let pos = - 1 ;
66+ while ( nth -- > 0 ) {
67+ pos = str . indexOf ( substr , pos + 1 ) ;
68+ if ( pos === - 1 ) {
69+ break ; // Exit early if the substring isn't found
70+ }
71+ }
72+ return pos ;
73+ }
74+
5675 /**
5776 * Responsible to get all the colors and their respective line numbers.
5877 *
@@ -65,26 +84,51 @@ define(function (require, exports, module) {
6584 const nLen = editor . lineCount ( ) ;
6685 const aColors = [ ] ;
6786
68- // match colors and push into an array
87+ // Match colors and push into an array
6988 for ( let i = 0 ; i < nLen ; i ++ ) {
7089 let lineText = editor . getLine ( i ) ;
90+ let regx = / : [ ^ ; ] * ; / g;
7191
72- // to skip commented lines
73- // The second parameter in the getToken() method, `true`, enables precise tokenization.
74- // Without setting `precise` to `true`, multi-line comments are not handled correctly.
75- const token = editor . getToken ( { line : i } , true ) ;
76- if ( token . type === "comment" ) {
77- continue ;
78- }
92+ let lineMatches = lineText . match ( regx ) ;
93+ if ( lineMatches ) {
94+ // Iterate through all matches to find valid colors
95+ let validColors = [ ] ;
96+
97+ // We need to track the occurrence count for colors because in cases like this:
98+ // /*color: linear-gradient(red, blue, green, yellow);*/ color: red;
99+ // The color "red" appears twice: the first occurrence is inside a comment,
100+ // but the second one is not. If we simply search for the index of "red"
101+ // using `indexOf`, it will always return the first match, which belongs
102+ // to the comment. This would incorrectly mark the second "red" (outside
103+ // the comment) as invalid. By tracking occurrences, we ensure we check
104+ // the correct instance of "red" and only ignore those inside comments.
105+ let occurrenceCount = { } ; // Track occurrences for each color
106+
107+ for ( let lineMatch of lineMatches ) {
108+ let tempColors = lineMatch . match ( COLOR_REGEX ) ;
109+
110+ if ( tempColors && tempColors . length > 0 ) {
111+ let filteredColors = tempColors . filter ( color => {
112+ // Increment the occurrence count for this color
113+ occurrenceCount [ color ] = ( occurrenceCount [ color ] || 0 ) + 1 ;
114+
115+ // Find the nth occurrence index of the color
116+ const colorIndex = findNthOccurrence ( lineText , color , occurrenceCount [ color ] ) ;
117+
118+ // Check if the color is within a comment
119+ const token = editor . getToken ( { line : i , ch : colorIndex } , true ) ;
120+
121+ // If the token is not a comment, keep the color
122+ return token . type !== "comment" ;
123+ } ) ;
79124
80- let regx = / : [ ^ ; ] * ; / g;
125+ validColors . push ( ...filteredColors ) ;
126+ }
127+ }
81128
82- lineText = lineText . match ( regx ) ;
83- if ( lineText ) {
84- let tempColors = lineText [ 0 ] . match ( COLOR_REGEX ) ;
85129 // Support up to 4 colors
86- if ( tempColors && tempColors . length > 0 ) {
87- let colors = tempColors . slice ( 0 , 4 ) ;
130+ if ( validColors . length > 0 ) {
131+ let colors = validColors . slice ( 0 , 4 ) ;
88132 aColors . push ( {
89133 lineNumber : i ,
90134 colorValues : colors
@@ -341,35 +385,49 @@ define(function (require, exports, module) {
341385 * the colors to be added on those lines
342386 */
343387 function updateColorMarks ( editor , fromLineNumber , toLineNumber ) {
344- // const nLen = editor.lineCount();
388+
345389 const aColors = [ ] ;
346390
347- // match colors and push into an array
391+ // Match colors and push into an array
348392 for ( let i = fromLineNumber ; i <= toLineNumber ; i ++ ) {
349393 let lineText = editor . getLine ( i ) ;
394+ let regx = / : [ ^ ; ] * ; / g;
350395
351- // to skip commented lines
352- // The second parameter in the getToken() method, `true`, enables precise tokenization.
353- // Without setting `precise` to `true`, multi-line comments are not handled correctly.
354- const token = editor . getToken ( { line : i } , true ) ;
355- if ( token . type === "comment" ) {
356- editor . setGutterMarker ( i , GUTTER_NAME , "" ) ;
357- continue ;
358- }
396+ let lineMatches = lineText . match ( regx ) ;
397+ if ( lineMatches ) {
398+ // Iterate through all matches to find valid colors
399+ let validColors = [ ] ;
400+ let occurrenceCount = { } ; // Track occurrences for each color
359401
360- let regx = / : [ ^ ; ] * ; / g;
361402
362- lineText = lineText . match ( regx ) ;
363- if ( lineText ) {
364- let tempColors = lineText [ 0 ] . match ( COLOR_REGEX ) ;
403+ for ( let lineMatch of lineMatches ) {
404+ let tempColors = lineMatch . match ( COLOR_REGEX ) ;
365405
366- // to remove color if the line is modified and now the colors are not valid
367- if ( ! tempColors ) {
368- editor . setGutterMarker ( i , GUTTER_NAME , "" ) ;
406+ if ( tempColors && tempColors . length > 0 ) {
407+ let filteredColors = tempColors . filter ( color => {
408+ // Increment the occurrence count for this color
409+ occurrenceCount [ color ] = ( occurrenceCount [ color ] || 0 ) + 1 ;
410+
411+ // Find the nth occurrence index of the color
412+ const colorIndex = findNthOccurrence ( lineText , color , occurrenceCount [ color ] ) ;
413+
414+ // Check if the color is within a comment
415+ const token = editor . getToken ( { line : i , ch : colorIndex } , true ) ;
416+
417+ // If the token is not a comment, keep the color
418+ return token . type !== "comment" ;
419+ } ) ;
420+
421+ validColors . push ( ...filteredColors ) ;
422+ }
369423 }
370- // Support up to 4 colors
371- if ( tempColors && tempColors . length > 0 ) {
372- let colors = tempColors . slice ( 0 , 4 ) ;
424+
425+ // If no valid colors, clear the gutter marker
426+ if ( validColors . length === 0 ) {
427+ editor . setGutterMarker ( i , GUTTER_NAME , "" ) ;
428+ } else {
429+ // Take up to 4 valid colors
430+ let colors = validColors . slice ( 0 , 4 ) ;
373431 aColors . push ( {
374432 lineNumber : i ,
375433 colorValues : colors
0 commit comments