Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 10 additions & 10 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions src-node/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

255 changes: 255 additions & 0 deletions src/extensionsIntegrated/CSSColorPreview/main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,255 @@
/*
* GNU AGPL-3.0 License
*
* Copyright (c) 2021 - present core.ai . All rights reserved.
* Original work Copyright (c) 2024 [cmgddd](https://github.com/cmgddd/Brackets-css-color-preview). All rights reserved.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License
* for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see https://opensource.org/licenses/AGPL-3.0.
*
*/


/* Displays a color preview in the gutter for any file containing color values */
/* Styles on `styles/brackets.less` file */

define(function (require, exports, module) {

// Brackets modules.
const _ = require("thirdparty/lodash"),
EditorManager = require('editor/EditorManager'),
ColorUtils = require('utils/ColorUtils'),
AppInit = require("utils/AppInit"),
PreferencesManager = require("preferences/PreferencesManager"),
Strings = require("strings");

// Extension variables.
const COLOR_REGEX = ColorUtils.COLOR_REGEX, // used to match color
gutterName = "CodeMirror-colorGutter";


// For preferences settings, to toggle this feature on/off
const PREFERENCES_CSS_COLOR_PREVIEW = "CSSColorPreview";
let enabled = true; // by default:- on

PreferencesManager.definePreference(PREFERENCES_CSS_COLOR_PREVIEW, "boolean", enabled, {
description: Strings.DESCRIPTION_CSS_COLOR_PREVIEW
});

/**
* Gets all the colors that are to be displayed
*
* Makes sure that the feature is enabled and editor is active, if yes:
* Calls showGutter function to display the color marks on the gutter
*/
function showColorMarks() {
if (!enabled) {
removeColorMarks();
return;
}

const editor = EditorManager.getActiveEditor();
if (editor) {

const cm = editor._codeMirror;
const nLen = cm.lineCount();
const aColors = [];

// match colors and push into an array
for (let i = 0; i < nLen; i++) {
let lineText = cm.getLine(i);

if ((lineText.indexOf('/*') !== -1) || (lineText.indexOf('*/') !== -1)) {
continue;
} else {
let regx = /:[^;]*;/g;

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);
aColors.push({
lineNumber: i,
colorValues: colors
});
}
}
}
}

showGutters(editor, aColors);
}
}

/**
* To remove the color marks from the gutter
*/
function removeColorMarks() {
const editor = EditorManager.getActiveEditor();
if (editor) {
const cm = editor._codeMirror;
cm.clearGutter(gutterName);
}
}

/**
* To display the color marks on the gutter
* @param {activeEditor} editor
* @param {Array.<object>} _results An array of objects which stores
* all the line numbers and the colors to be displayed on that line.
*/
function showGutters(editor, _results) {
if (editor && enabled) {
initGutter(editor);
const cm = editor._codeMirror;
cm.clearGutter(gutterName); // clear color markers

// Only add markers if enabled
if (enabled) {
cm.colorGutters = _.sortBy(_results, "lineNumber");

cm.colorGutters.forEach(function (obj) {
let $marker;

if (obj.colorValues.length === 1) {
// Single color preview
$marker = $("<i>")
.addClass("ico-cssColorPreview")
.css('background-color', obj.colorValues[0]);

cm.setGutterMarker(obj.lineNumber, gutterName, $marker[0]);
} else {
// Multiple colors preview
$marker = $("<div>").addClass("ico-multiple-cssColorPreview");

// Positions for up to 4 colors in grid
const positions = [
{ top: 0, left: 0 },
{ top: 0, right: 0 },
{ bottom: 0, right: 0 },
{ bottom: 0, left: 0 }
];

obj.colorValues.forEach((color, index) => {
if (index < 4) {
const $colorBox = $("<div>")
.addClass("color-box")
.css({
'background-color': color,
...positions[index]
});
$marker.append($colorBox);
}
});

cm.setGutterMarker(obj.lineNumber, gutterName, $marker[0]);
}
});
}

}
}


/**
* Initialize the gutter
* @param {activeEditor} editor
*/
function initGutter(editor) {

const cm = editor._codeMirror;
const gutters = cm.getOption("gutters").slice(0);
let str = gutters.join('');
if (str.indexOf(gutterName) === -1) {
gutters.unshift(gutterName);
cm.setOption("gutters", gutters);
}
}

/**
* Register all the required handlers
*/
function registerHandlers() {
// Remove previous listeners to avoid multiple binding issue
EditorManager.off("activeEditorChange", onChanged);

// Add listener for all editor changes
EditorManager.on("activeEditorChange", function (event, newEditor, oldEditor) {
if (newEditor) {
// Unbind the previous editor's change event if it exists
if (oldEditor) {
const oldCM = oldEditor._codeMirror;
if (oldCM) {
oldCM.off("change", onChanged);
}
}

// Bind change event to the new editor
const cm = newEditor._codeMirror;
if (cm) {
cm.on("change", onChanged);
}

showColorMarks();
}
});

// Handle the currently active editor at initialization
const activeEditor = EditorManager.getActiveEditor();
if (activeEditor) {
const cm = activeEditor._codeMirror;
if (cm) {
cm.on("change", onChanged);
}
showColorMarks();
}

}

/**
* Checks for preference changes, to enable/disable the feature
*/
function preferenceChanged() {
const value = PreferencesManager.get(PREFERENCES_CSS_COLOR_PREVIEW);
Comment thread
devvaannsh marked this conversation as resolved.
enabled = value;
if (!value) {
removeColorMarks();
} else {
showColorMarks();
}
}

/**
* Function that gets triggered when any change occurs on the editor
*/
function onChanged() {
showColorMarks();
}

/**
* Driver function, runs at the start of the program
*/
function init() {
showColorMarks();
registerHandlers();
}

// init after appReady
AppInit.appReady(function () {
PreferencesManager.on("change", PREFERENCES_CSS_COLOR_PREVIEW, preferenceChanged);
init();
});
});

1 change: 1 addition & 0 deletions src/extensionsIntegrated/loader.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,5 @@ define(function (require, exports, module) {
require("./appUpdater/main");
require("./HtmlTagSyncEdit/main");
require("./indentGuides/main");
require("./CSSColorPreview/main");
});
3 changes: 2 additions & 1 deletion src/nls/root/strings.js
Original file line number Diff line number Diff line change
Expand Up @@ -1250,5 +1250,6 @@ define({
"BEAUTIFY_OPTION_PRINT_TRAILING_COMMAS": "Print trailing commas wherever possible in multi-line comma-separated syntactic structures",
// indent guides extension
"DESCRIPTION_INDENT_GUIDES_ENABLED": "true to show indent guide lines, else false.",
"DESCRIPTION_HIDE_FIRST": "true to show the first Indent Guide line else false."
"DESCRIPTION_HIDE_FIRST": "true to show the first Indent Guide line else false.",
"DESCRIPTION_CSS_COLOR_PREVIEW": "true to display color previews in the gutter, else false."
});
32 changes: 32 additions & 0 deletions src/styles/brackets.less
Original file line number Diff line number Diff line change
Expand Up @@ -3522,3 +3522,35 @@ label input {
}
}

// These styles are for CssColorPreview feature
// Check `extensionsIntegrated/CSSColorPreview for more reference
/* Single color preview */
.ico-cssColorPreview {
border: solid 1px rgba(0, 0, 0, 0.2);
display: inline-block;
height: 14px;
width: 14px;
margin-left: 6px;
position: absolute;
top: 8px;
z-index: 99999;
}

/* Multiple colors preview container (this is a div) */
.ico-multiple-cssColorPreview {
position: relative;
display: inline-block;
width: 14px;
height: 14px;
margin-left: 6px;
border: solid 1px rgba(0, 0, 0, 0.2);
z-index: 99999;
}

/* For individual color boxes, they will be added inside the main .ico-multiple-cssColorPreview div */
.ico-multiple-cssColorPreview .color-box {
position: absolute;
width: 6px;
height: 6px;
box-sizing: border-box;
}