Skip to content

Commit 6ef80f6

Browse files
committed
feat: add cssColorPreview support for inline comments
1 parent a787195 commit 6ef80f6

File tree

1 file changed

+92
-34
lines changed
  • src/extensionsIntegrated/CSSColorPreview

1 file changed

+92
-34
lines changed

src/extensionsIntegrated/CSSColorPreview/main.js

Lines changed: 92 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)