🚧 Colour picker
This commit is contained in:
parent
8bdc9f16d8
commit
6457bfa63d
5 changed files with 138 additions and 5 deletions
11
package-lock.json
generated
11
package-lock.json
generated
|
@ -1,14 +1,15 @@
|
|||
{
|
||||
"name": "mapcompletevscode",
|
||||
"version": "0.0.1",
|
||||
"version": "1.0.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "mapcompletevscode",
|
||||
"version": "0.0.1",
|
||||
"version": "1.0.0",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"colortranslator": "^4.1.0",
|
||||
"jsonc-parser": "^3.3.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
@ -673,6 +674,12 @@
|
|||
"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",
|
||||
|
|
|
@ -48,6 +48,7 @@
|
|||
"typescript-eslint": "^8.16.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"colortranslator": "^4.1.0",
|
||||
"jsonc-parser": "^3.3.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import * as vscode from "vscode";
|
||||
import { layerCompletionProvider, layerDefinitionProvider } from "./theme";
|
||||
import { iconDefinitionProvider } from "./generic";
|
||||
import { colorProvider, iconDefinitionProvider } from "./generic";
|
||||
import {
|
||||
filterCompletionProvider,
|
||||
filterDefinitionProvider,
|
||||
|
@ -25,5 +25,5 @@ export function activate(context: vscode.ExtensionContext) {
|
|||
context.subscriptions.push(pathDefinitionProvider);
|
||||
|
||||
// Activate all generic features
|
||||
context.subscriptions.push(iconDefinitionProvider);
|
||||
context.subscriptions.push(iconDefinitionProvider, colorProvider);
|
||||
}
|
||||
|
|
113
src/generic.ts
113
src/generic.ts
|
@ -8,7 +8,9 @@ import {
|
|||
getRawCursorPath,
|
||||
getStartEnd,
|
||||
getValueFromPath,
|
||||
pathToJSONPath,
|
||||
} from "./utils";
|
||||
import { ColorTranslator } from "colortranslator";
|
||||
import * as path from "path";
|
||||
|
||||
/**
|
||||
|
@ -78,3 +80,114 @@ export const iconDefinitionProvider =
|
|||
},
|
||||
}
|
||||
);
|
||||
|
||||
/**
|
||||
* Color provider
|
||||
*
|
||||
* Some fields in MapComplete actually represent colors, this provider will provide a color presentation for these fields
|
||||
* Colours can be represented in two ways:
|
||||
* - As a hex color, like #ff0000ff or #ff0000
|
||||
* - As a color name, like red
|
||||
*
|
||||
* JSON paths:
|
||||
* - (layers.{index}.)lineRendering.{index}.color
|
||||
* - (layers.{index}.)lineRendering.{index}.color.render
|
||||
* - (layers.{index}.)lineRendering.{index}.color.mappings.{index}.then
|
||||
* - (layers.{index}.)lineRendering.{index}.fillColor
|
||||
* - (layers.{index}.)lineRendering.{index}.fillColor.render
|
||||
* - (layers.{index}.)lineRendering.{index}.fillColor.mappings.{index}.then
|
||||
* - (layers.{index}.)pointRendering.{index}.marker.{index}.color
|
||||
* - (layers.{index}.)pointRendering.{index}.marker.{index}.color.render
|
||||
* - (layers.{index}.)pointRendering.{index}.marker.{index}.color.mappings.{index}.then
|
||||
*
|
||||
*/
|
||||
export const colorProvider = vscode.languages.registerColorProvider(
|
||||
{
|
||||
language: "json",
|
||||
scheme: "file",
|
||||
pattern: "**/assets/*/*/*.json",
|
||||
},
|
||||
{
|
||||
provideColorPresentations(color, _context, _token) {
|
||||
console.log("colorProvider.provideColorPresentations");
|
||||
|
||||
const colorHex = new ColorTranslator(
|
||||
`rgba(${color.red * 255}, ${color.green * 255}, ${color.blue * 255}, ${
|
||||
color.alpha
|
||||
})`
|
||||
).HEXA;
|
||||
|
||||
// If the color is fully opaque (AKA it ends with FF), we can remove the alpha channel
|
||||
const colorHexString = colorHex.endsWith("FF")
|
||||
? colorHex.substring(0, 7)
|
||||
: colorHex;
|
||||
|
||||
// TODO: Add color names, maybe convert to short-hand hex
|
||||
|
||||
return [
|
||||
{
|
||||
label: colorHexString,
|
||||
},
|
||||
];
|
||||
},
|
||||
provideDocumentColors(document, _token) {
|
||||
console.log("colorProvider.provideDocumentColors");
|
||||
|
||||
const text = document.getText();
|
||||
const colors: vscode.ColorInformation[] = [];
|
||||
const jsonParsed = JSON.parse(text);
|
||||
const allPaths: string[] = [];
|
||||
|
||||
// Find all paths in the JSON
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const findPaths = (obj: any, path = "") => {
|
||||
for (const key in obj) {
|
||||
if (typeof obj[key] === "object") {
|
||||
findPaths(obj[key], path + key + ".");
|
||||
} else {
|
||||
allPaths.push(path + key);
|
||||
}
|
||||
}
|
||||
};
|
||||
findPaths(jsonParsed);
|
||||
|
||||
const regexes = [
|
||||
/^(layers.\d+.)?lineRendering.\d+.color((.render)|(.mappings.\d+.then))?$/,
|
||||
/^(layers.\d+.)?lineRendering.\d+.fillColor((.render)|(.mappings.\d+.then))?$/,
|
||||
/^(layers.\d+.)?pointRendering.\d+.marker.\d+.color((.render)|(.mappings.\d+.then))?$/,
|
||||
];
|
||||
|
||||
regexes.forEach((regex) => {
|
||||
allPaths.forEach((path) => {
|
||||
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);
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(
|
||||
`Output color: ${colorRgba.R}, ${colorRgba.G}, ${colorRgba.B}, ${colorRgba.A}`
|
||||
);
|
||||
|
||||
colors.push({
|
||||
color: new vscode.Color(
|
||||
colorRgba.R / 255,
|
||||
colorRgba.G / 255,
|
||||
colorRgba.B / 255,
|
||||
colorRgba.A ?? 1
|
||||
),
|
||||
range: getStartEnd(text, pathToJSONPath(path)),
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
return colors;
|
||||
},
|
||||
}
|
||||
);
|
||||
|
|
12
src/utils.ts
12
src/utils.ts
|
@ -219,3 +219,15 @@ export async function getFilters(): Promise<vscode.CompletionItem[]> {
|
|||
|
||||
return filtersList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility function to convert a string path to a JSON path
|
||||
*
|
||||
* @param path String path, separated by dots
|
||||
* @returns JSON path
|
||||
*/
|
||||
export function pathToJSONPath(path: string): JSONPath {
|
||||
return path.split(".").map((str) => {
|
||||
return isNaN(parseInt(str)) ? str : parseInt(str);
|
||||
});
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue