♻️ Rework color conversion

This commit is contained in:
Robin van der Linde 2025-01-04 15:08:37 +01:00 committed by Robin van der Linde
parent 0f01b73c22
commit 185ba23520
4 changed files with 105 additions and 38 deletions

7
package-lock.json generated
View file

@ -9,7 +9,6 @@
"version": "1.0.0",
"license": "MIT",
"dependencies": {
"colortranslator": "^4.1.0",
"jsonc-parser": "^3.3.1"
},
"devDependencies": {
@ -674,12 +673,6 @@
"dev": true,
"license": "MIT"
},
"node_modules/colortranslator": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/colortranslator/-/colortranslator-4.1.0.tgz",
"integrity": "sha512-bwa5awaMnQ6dpm9D3nbsFwUr6x6FrTKmxPdolNtSYfxCNR7ZM93GG1OF5Y3Sy1LvYdalb3riKC9uTn0X5NB36g==",
"license": "Apache-2.0"
},
"node_modules/concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",

View file

@ -48,7 +48,6 @@
"typescript-eslint": "^8.16.0"
},
"dependencies": {
"colortranslator": "^4.1.0",
"jsonc-parser": "^3.3.1"
}
}

View file

@ -5,9 +5,12 @@
import * as vscode from "vscode";
import { getCursorPath, getRawCursorPath, getStartEnd } from "./utils/cursor";
import { getValueFromPath, pathToJSONPath } from "./utils/json";
import { ColorTranslator } from "colortranslator";
import * as path from "path";
import { findHexColor } from "./utils/color";
import {
findHexColorName,
mapCompleteToVScode,
vsCodeToHex,
} from "./utils/color";
/**
* Icon definition provider
@ -110,29 +113,18 @@ export const colorProvider = vscode.languages.registerColorProvider(
let outputColor: string;
// Convert the color to a hex string
outputColor = new ColorTranslator(
`rgba(${color.red * 255}, ${color.green * 255}, ${color.blue * 255}, ${
color.alpha
})`
).HEXA;
console.log(`First output color: ${outputColor}`);
outputColor = vsCodeToHex(color);
// If the color is fully opaque (AKA it ends with FF), we can remove the alpha channel
outputColor = outputColor.endsWith("FF")
outputColor = outputColor.endsWith("ff")
? outputColor.substring(0, 7)
: outputColor;
console.log(`Output color after alpha check: ${outputColor}`);
// See if we can find a color name
const colorName = findHexColor(outputColor);
const colorName = findHexColorName(outputColor);
if (colorName) {
outputColor = colorName.name;
}
console.log(`Output color after color name check: ${outputColor}`);
// If we have a pair like #AABBCC, we can shorten that to #ABC
if (
outputColor[1] === outputColor[2] &&
@ -142,7 +134,7 @@ export const colorProvider = vscode.languages.registerColorProvider(
outputColor = `#${outputColor[1]}${outputColor[3]}${outputColor[5]}`;
}
console.log(`Color after shortening: ${outputColor}`);
console.log("Output color from picker:", outputColor);
return [
{
@ -182,25 +174,18 @@ export const colorProvider = vscode.languages.registerColorProvider(
if (regex.exec(path)) {
const colorValue = getValueFromPath(text, pathToJSONPath(path));
let colorRgba;
try {
colorRgba = new ColorTranslator(colorValue).RGBAObject;
} catch (error) {
console.error("Error translating color value:", error);
const colorOuput = mapCompleteToVScode(colorValue);
if (!colorOuput) {
return;
}
console.log(
`Output color: ${colorRgba.R}, ${colorRgba.G}, ${colorRgba.B}, ${colorRgba.A}`
`Output color: ${colorOuput.red}, ${colorOuput.green}, ${colorOuput.blue}, ${colorOuput.alpha}`
);
colors.push({
color: new vscode.Color(
colorRgba.R / 255,
colorRgba.G / 255,
colorRgba.B / 255,
colorRgba.A ?? 1
),
color: colorOuput,
range: getStartEnd(text, pathToJSONPath(path)),
});
}

View file

@ -2,6 +2,8 @@
* Some utilities to works with colors, mainly color names
*/
import { Color as vscodeColor } from "vscode";
/**
* Representation of a color, contains hex and rgb values
*/
@ -34,11 +36,99 @@ interface Color {
/**
* Find a color by its hex value
*
* @param hex Hex color
* @returns Color object, if found
*/
export function findHexColor(hex: string): Color | undefined {
export function findHexColorName(hex: string): Color | undefined {
return colors.find((color) => color.hex === hex.toLowerCase());
}
/**
* Find a color by its name
*
* @param name Color name
* @returns Color object, if found
*/
export function findHexColor(name: string): Color | undefined {
return colors.find((color) => color.name === name.toLowerCase());
}
/**
* Convert a VSCode color to a hex string
*
* @param color VSCode color
* @returns Hex representation of the color
*/
export function vsCodeToHex(color: vscodeColor): string {
const red = Math.round(color.red * 255)
.toString(16)
.padStart(2, "0");
const green = Math.round(color.green * 255)
.toString(16)
.padStart(2, "0");
const blue = Math.round(color.blue * 255)
.toString(16)
.padStart(2, "0");
const alpha = Math.round(color.alpha * 255)
.toString(16)
.padStart(2, "0");
return `#${red}${green}${blue}${alpha}`;
}
/**
* Convert a color from a MapComplete JSON to a VSCode color
*
* Supports HEX (3, 6 or 8 characters) and color names
*
* @param color Color from MapComplete JSON
*/
export function mapCompleteToVScode(color: string): vscodeColor | undefined {
// First check if we have a hex color
if (color.startsWith("#")) {
// Check if we have 3, 6 or 8 defined characters
switch (color.length) {
case 4:
return new vscodeColor(
parseInt(color[1] + color[1], 16) / 255,
parseInt(color[2] + color[2], 16) / 255,
parseInt(color[3] + color[3], 16) / 255,
1
);
case 7:
return new vscodeColor(
parseInt(color.substring(1, 2), 16) / 255,
parseInt(color.substring(3, 2), 16) / 255,
parseInt(color.substring(5, 2), 16) / 255,
1
);
case 9:
return new vscodeColor(
parseInt(color.substring(1, 2), 16) / 255,
parseInt(color.substring(3, 2), 16) / 255,
parseInt(color.substring(5, 2), 16) / 255,
parseInt(color.substring(7, 2), 16) / 255
);
default:
return undefined;
}
} else {
// Look for a color name
const namedColor = findHexColor(color);
if (namedColor) {
return new vscodeColor(
namedColor.r / 255,
namedColor.g / 255,
namedColor.b / 255,
1
);
} else {
return undefined;
}
}
}
/**
* List of all named colors
*/