color-cleaner
Version:
A CLI tool to clean and consolidate colors in your project files.
96 lines (82 loc) • 4.38 kB
JavaScript
import fs from 'fs';
import path from 'path';
import { printUpdate } from './prettyConsoleService.js';
const cssNamedColors = [
'aliceblue', 'antiquewhite', 'aqua', 'aquamarine', 'azure', 'beige', 'bisque',
'black', 'blanchedalmond', 'blue', 'blueviolet', 'brown', 'burlywood', 'cadetblue',
'chartreuse', 'chocolate', 'coral', 'cornflowerblue', 'cornsilk', 'crimson', 'cyan',
'darkblue', 'darkcyan', 'darkgoldenrod', 'darkgray', 'darkgreen', 'darkgrey',
'darkkhaki', 'darkmagenta', 'darkolivegreen', 'darkorange', 'darkorchid', 'darkred',
'darksalmon', 'darkseagreen', 'darkslateblue', 'darkslategray', 'darkslategrey',
'darkturquoise', 'darkviolet', 'deeppink', 'deepskyblue', 'dimgray', 'dimgrey',
'dodgerblue', 'firebrick', 'floralwhite', 'forestgreen', 'fuchsia', 'gainsboro',
'ghostwhite', 'gold', 'goldenrod', 'gray', 'green', 'greenyellow', 'grey', 'honeydew',
'hotpink', 'indianred', 'indigo', 'ivory', 'khaki', 'lavender', 'lavenderblush',
'lawngreen', 'lemonchiffon', 'lightblue', 'lightcoral', 'lightcyan', 'lightgoldenrodyellow',
'lightgray', 'lightgreen', 'lightgrey', 'lightpink', 'lightsalmon', 'lightseagreen',
'lightskyblue', 'lightslategray', 'lightslategrey', 'lightsteelblue', 'lightyellow',
'lime', 'limegreen', 'linen', 'magenta', 'maroon', 'mediumaquamarine', 'mediumblue',
'mediumorchid', 'mediumpurple', 'mediumseagreen', 'mediumslateblue', 'mediumspringgreen',
'mediumturquoise', 'mediumvioletred', 'midnightblue', 'mintcream', 'mistyrose',
'moccasin', 'navajowhite', 'navy', 'oldlace', 'olive', 'olivedrab', 'orange',
'orangered', 'orchid', 'palegoldenrod', 'palegreen', 'paleturquoise', 'palevioletred',
'papayawhip', 'peachpuff', 'peru', 'pink', 'plum', 'powderblue', 'purple', 'rebeccapurple',
'red', 'rosybrown', 'royalblue', 'saddlebrown', 'salmon', 'sandybrown', 'seagreen',
'seashell', 'sienna', 'silver', 'skyblue', 'slateblue', 'slategray', 'slategrey',
'snow', 'springgreen', 'steelblue', 'tan', 'teal', 'thistle', 'tomato', 'transparent',
'turquoise', 'violet', 'wheat', 'white', 'whitesmoke', 'yellow', 'yellowgreen'
];
const COLOR_PATTERNS = [
/rgb\(\s*\d+\s*,\s*\d+\s*,\s*\d+\s*\)/gi,
/rgba\(\s*\d+\s*,\s*\d+\s*,\s*\d+\s*,\s*[\d.]+\s*\)/gi,
/#[0-9a-f]{3,8}/gi,
/hsl\(\s*\d+\s*,\s*\d+%\s*,\s*\d+%\s*\)/gi,
/hsla\(\s*\d+\s*,\s*\d+%\s*,\s*\d+%\s*,\s*[\d.]+\s*\)/gi,
new RegExp(`\\b(${cssNamedColors.join('|')})\\b`, 'gi')
];
export async function replaceColorsWithVariable(groups) {
const palette = new Map();
const fileContents = new Map();
// First pass: Map each CSS variable to its first encountered color
for (const group of groups) {
const cssVariable = group.cssVariable;
if (!palette.has(cssVariable)) {
const firstColor = group.items[0].color;
palette.set(cssVariable, firstColor);
}
}
// Second pass: Process files
for (const group of groups) {
const cssVariable = group.cssVariable;
for (const item of group.items) {
const { currentPath, lineNumber, color, originalColor } = item;
try {
const filePath = path.resolve(currentPath);
if (!fileContents.has(filePath)) {
const content = await fs.promises.readFile(filePath, 'utf8');
fileContents.set(filePath, content.split('\n'));
}
const lines = fileContents.get(filePath);
if (lines[lineNumber - 1]) {
const line = lines[lineNumber - 1];
let newLine = line;
for (const pattern of COLOR_PATTERNS) {
const matches = line.match(pattern) || [];
for (const match of matches) {
const colorToCompare = originalColor || color;
if (match.toLowerCase() === colorToCompare.toLowerCase()) {
newLine = newLine.replace(match, `var(${cssVariable})`);
}
}
}
lines[lineNumber - 1] = newLine;
}
await fs.promises.writeFile(filePath, lines.join('\n'), 'utf8');
printUpdate(currentPath, lineNumber);
} catch (error) {
console.error(`Error processing file ${currentPath}:`, error);
}
}
}
return palette;
}