Skip to content

Commit

Permalink
feat: add cssColorPreview support for inline comments
Browse files Browse the repository at this point in the history
  • Loading branch information
devvaannsh committed Dec 6, 2024
1 parent a787195 commit 6ef80f6
Showing 1 changed file with 92 additions and 34 deletions.
126 changes: 92 additions & 34 deletions src/extensionsIntegrated/CSSColorPreview/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,25 @@ define(function (require, exports, module) {
description: Strings.DESCRIPTION_CSS_COLOR_PREVIEW
});


/**
* Helper function to find the nth occurrence of a substring in a string
* @param {String} str the line text
* @param {String} substr color
* @param {Number} nth the occurence count of the color
* @return {Number} the index of the nth occurence
*/
function findNthOccurrence(str, substr, nth) {
let pos = -1;
while (nth-- > 0) {
pos = str.indexOf(substr, pos + 1);
if (pos === -1) {
break; // Exit early if the substring isn't found
}
}
return pos;
}

/**
* Responsible to get all the colors and their respective line numbers.
*
Expand All @@ -65,26 +84,51 @@ define(function (require, exports, module) {
const nLen = editor.lineCount();
const aColors = [];

// match colors and push into an array
// Match colors and push into an array
for (let i = 0; i < nLen; i++) {
let lineText = editor.getLine(i);
let regx = /:[^;]*;/g;

// to skip commented lines
// The second parameter in the getToken() method, `true`, enables precise tokenization.
// Without setting `precise` to `true`, multi-line comments are not handled correctly.
const token = editor.getToken({line: i}, true);
if(token.type === "comment") {
continue;
}
let lineMatches = lineText.match(regx);
if (lineMatches) {
// Iterate through all matches to find valid colors
let validColors = [];

// We need to track the occurrence count for colors because in cases like this:
// /*color: linear-gradient(red, blue, green, yellow);*/ color: red;
// The color "red" appears twice: the first occurrence is inside a comment,
// but the second one is not. If we simply search for the index of "red"
// using `indexOf`, it will always return the first match, which belongs
// to the comment. This would incorrectly mark the second "red" (outside
// the comment) as invalid. By tracking occurrences, we ensure we check
// the correct instance of "red" and only ignore those inside comments.
let occurrenceCount = {}; // Track occurrences for each color

for (let lineMatch of lineMatches) {
let tempColors = lineMatch.match(COLOR_REGEX);

if (tempColors && tempColors.length > 0) {
let filteredColors = tempColors.filter(color => {
// Increment the occurrence count for this color
occurrenceCount[color] = (occurrenceCount[color] || 0) + 1;

// Find the nth occurrence index of the color
const colorIndex = findNthOccurrence(lineText, color, occurrenceCount[color]);

// Check if the color is within a comment
const token = editor.getToken({ line: i, ch: colorIndex }, true);

// If the token is not a comment, keep the color
return token.type !== "comment";
});

let regx = /:[^;]*;/g;
validColors.push(...filteredColors);
}
}

lineText = lineText.match(regx);
if (lineText) {
let tempColors = lineText[0].match(COLOR_REGEX);
// Support up to 4 colors
if (tempColors && tempColors.length > 0) {
let colors = tempColors.slice(0, 4);
if (validColors.length > 0) {
let colors = validColors.slice(0, 4);
aColors.push({
lineNumber: i,
colorValues: colors
Expand Down Expand Up @@ -341,35 +385,49 @@ define(function (require, exports, module) {
* the colors to be added on those lines
*/
function updateColorMarks(editor, fromLineNumber, toLineNumber) {
// const nLen = editor.lineCount();

const aColors = [];

// match colors and push into an array
// Match colors and push into an array
for (let i = fromLineNumber; i <= toLineNumber; i++) {
let lineText = editor.getLine(i);
let regx = /:[^;]*;/g;

// to skip commented lines
// The second parameter in the getToken() method, `true`, enables precise tokenization.
// Without setting `precise` to `true`, multi-line comments are not handled correctly.
const token = editor.getToken({line: i}, true);
if(token.type === "comment") {
editor.setGutterMarker(i, GUTTER_NAME, "");
continue;
}
let lineMatches = lineText.match(regx);
if (lineMatches) {
// Iterate through all matches to find valid colors
let validColors = [];
let occurrenceCount = {}; // Track occurrences for each color

let regx = /:[^;]*;/g;

lineText = lineText.match(regx);
if (lineText) {
let tempColors = lineText[0].match(COLOR_REGEX);
for (let lineMatch of lineMatches) {
let tempColors = lineMatch.match(COLOR_REGEX);

// to remove color if the line is modified and now the colors are not valid
if(!tempColors) {
editor.setGutterMarker(i, GUTTER_NAME, "");
if (tempColors && tempColors.length > 0) {
let filteredColors = tempColors.filter(color => {
// Increment the occurrence count for this color
occurrenceCount[color] = (occurrenceCount[color] || 0) + 1;

// Find the nth occurrence index of the color
const colorIndex = findNthOccurrence(lineText, color, occurrenceCount[color]);

// Check if the color is within a comment
const token = editor.getToken({ line: i, ch: colorIndex }, true);

// If the token is not a comment, keep the color
return token.type !== "comment";
});

validColors.push(...filteredColors);
}
}
// Support up to 4 colors
if (tempColors && tempColors.length > 0) {
let colors = tempColors.slice(0, 4);

// If no valid colors, clear the gutter marker
if (validColors.length === 0) {
editor.setGutterMarker(i, GUTTER_NAME, "");
} else {
// Take up to 4 valid colors
let colors = validColors.slice(0, 4);
aColors.push({
lineNumber: i,
colorValues: colors
Expand Down

0 comments on commit 6ef80f6

Please sign in to comment.