mirror of
https://github.com/shadoll/sLogos.git
synced 2025-12-20 03:26:59 +00:00
feat: add color conversion and target/sets configuration for logos
- Updated Makefile to include a new target for converting logo colors format. - Added a new script `convertColorsFormat.js` to convert colors from array to object format in `logos.json`. - Modified `logos.json` structure to use an object for colors and added targets and sets for SVG logos. - Updated `scanLogos.js` to set default colorConfig, targets, and sets for SVG logos. - Enhanced Svelte components (`Grid.svelte`, `List.svelte`, `Preview.svelte`, `InlineSvg.svelte`) to support new targets, sets, and colors structure. - Updated color theme utility functions to handle the new colors object format. - Removed deprecated `mono_white.svg` logo file.
This commit is contained in:
8
Makefile
8
Makefile
@@ -6,7 +6,7 @@ CONTAINER_NAME = logo-gallery
|
||||
DEV_PORT = 5006
|
||||
|
||||
# Main targets
|
||||
.PHONY: all build start stop restart logs clean scan-logos dev rebuild favicon deps-favicon build-with-favicons sync-packages
|
||||
.PHONY: all build start stop restart logs clean scan-logos dev rebuild favicon deps-favicon build-with-favicons sync-packages convert-colors
|
||||
|
||||
all: build start
|
||||
|
||||
@@ -50,6 +50,12 @@ scan-logos:
|
||||
$(DOCKER_COMPOSE) -f compose.dev.yml run --rm slogos-dev npm run scan-logos
|
||||
@echo "Logos have been updated - refresh the browser to see changes"
|
||||
|
||||
# Convert logo colors format from array to object
|
||||
convert-colors:
|
||||
@echo "Converting logo colors format in logos.json..."
|
||||
$(DOCKER_COMPOSE) -f compose.dev.yml run --rm slogos-dev npm run convert-colors
|
||||
@echo "Color format conversion complete"
|
||||
|
||||
# Clean up build artifacts and temporary files
|
||||
clean:
|
||||
@echo "Cleaning up build artifacts and temporary files..."
|
||||
|
||||
@@ -7,7 +7,8 @@
|
||||
"dev": "rollup -c -w",
|
||||
"start": "sirv public --host 0.0.0.0 --dev --single",
|
||||
"scan-logos": "node scripts/scanLogos.js",
|
||||
"generate-favicons": "node scripts/generateFavicons.js"
|
||||
"generate-favicons": "node scripts/generateFavicons.js",
|
||||
"convert-colors": "node scripts/convertColorsFormat.js"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@rollup/plugin-commonjs": "^17.0.0",
|
||||
|
||||
@@ -30,18 +30,23 @@
|
||||
"tags": [
|
||||
"tech"
|
||||
],
|
||||
"colors": [
|
||||
{
|
||||
"label": "Silver",
|
||||
"value": "#999"
|
||||
},
|
||||
{
|
||||
"label": "Dark Grey",
|
||||
"value": "#666"
|
||||
}
|
||||
],
|
||||
"colors": {
|
||||
"silver": "#999",
|
||||
"dark_grey": "#666"
|
||||
},
|
||||
"colorConfig": {
|
||||
"target": "path"
|
||||
},
|
||||
"targets": {
|
||||
"main": "path"
|
||||
},
|
||||
"sets": {
|
||||
"set_1": {
|
||||
"main": "silver"
|
||||
},
|
||||
"set_2": {
|
||||
"main": "dark_grey"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -100,16 +105,21 @@
|
||||
"tags": [
|
||||
"tech"
|
||||
],
|
||||
"colors": [
|
||||
{
|
||||
"label": "Dark Blue",
|
||||
"value": "#080225"
|
||||
}
|
||||
],
|
||||
"colors": {
|
||||
"dark_blue": "#080225"
|
||||
},
|
||||
"colorConfig": {
|
||||
"target": "g"
|
||||
},
|
||||
"brand": "arm"
|
||||
"brand": "arm",
|
||||
"targets": {
|
||||
"main": "g"
|
||||
},
|
||||
"sets": {
|
||||
"set_1": {
|
||||
"main": "dark_blue"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "ATB",
|
||||
@@ -200,12 +210,9 @@
|
||||
"garage"
|
||||
],
|
||||
"brand": "Dalnoboy Service",
|
||||
"colors": [
|
||||
{
|
||||
"label": "Orange",
|
||||
"value": "#ee7800"
|
||||
}
|
||||
]
|
||||
"colors": {
|
||||
"orange": "#ee7800"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Debian",
|
||||
@@ -241,14 +248,19 @@
|
||||
"container"
|
||||
],
|
||||
"brand": "Docker",
|
||||
"colors": [
|
||||
{
|
||||
"label": "Blue",
|
||||
"value": "#1d63ed"
|
||||
}
|
||||
],
|
||||
"colors": {
|
||||
"blue": "#1d63ed"
|
||||
},
|
||||
"colorConfig": {
|
||||
"target": "path"
|
||||
},
|
||||
"targets": {
|
||||
"main": "path"
|
||||
},
|
||||
"sets": {
|
||||
"set_1": {
|
||||
"main": "blue"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -261,19 +273,23 @@
|
||||
"automobile",
|
||||
"transport"
|
||||
],
|
||||
"colors": [
|
||||
{
|
||||
"label": "Grey",
|
||||
"value": "#2b2a29",
|
||||
"theme": "light"
|
||||
},
|
||||
{
|
||||
"label": "Red",
|
||||
"value": "#e22b28"
|
||||
}
|
||||
],
|
||||
"colors": {
|
||||
"grey": "#2b2a29",
|
||||
"red": "#e22b28"
|
||||
},
|
||||
"colorConfig": {
|
||||
"selector": "#text"
|
||||
},
|
||||
"targets": {
|
||||
"selector_1": "#text"
|
||||
},
|
||||
"sets": {
|
||||
"set_1": {
|
||||
"selector_1": "grey"
|
||||
},
|
||||
"set_2": {
|
||||
"selector_1": "red"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -353,14 +369,19 @@
|
||||
"software"
|
||||
],
|
||||
"brand": "GitHub",
|
||||
"colors": [
|
||||
{
|
||||
"label": "Dark Grey",
|
||||
"value": "#24292f"
|
||||
}
|
||||
],
|
||||
"colors": {
|
||||
"dark_grey": "#24292f"
|
||||
},
|
||||
"colorConfig": {
|
||||
"target": "path"
|
||||
},
|
||||
"targets": {
|
||||
"main": "path"
|
||||
},
|
||||
"sets": {
|
||||
"set_1": {
|
||||
"main": "dark_grey"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -373,14 +394,19 @@
|
||||
"software"
|
||||
],
|
||||
"brand": "GitHub",
|
||||
"colors": [
|
||||
{
|
||||
"label": "Dark Grey",
|
||||
"value": "#24292f"
|
||||
}
|
||||
],
|
||||
"colors": {
|
||||
"dark_grey": "#24292f"
|
||||
},
|
||||
"colorConfig": {
|
||||
"target": "path"
|
||||
},
|
||||
"targets": {
|
||||
"main": "path"
|
||||
},
|
||||
"sets": {
|
||||
"set_1": {
|
||||
"main": "dark_grey"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -404,30 +430,35 @@
|
||||
"language"
|
||||
],
|
||||
"brand": "Go",
|
||||
"colors": [
|
||||
{
|
||||
"label": "Aqua",
|
||||
"value": "#2DBCAF"
|
||||
},
|
||||
{
|
||||
"label": "Blue",
|
||||
"value": "#00ACD7"
|
||||
},
|
||||
{
|
||||
"label": "Fuchsia",
|
||||
"value": "#CE3262"
|
||||
},
|
||||
{
|
||||
"label": "LightBlue",
|
||||
"value": "#5DC9E1"
|
||||
},
|
||||
{
|
||||
"label": "Yellow",
|
||||
"value": "#FDDD00"
|
||||
}
|
||||
],
|
||||
"colors": {
|
||||
"aqua": "#2DBCAF",
|
||||
"blue": "#00ACD7",
|
||||
"fuchsia": "#CE3262",
|
||||
"lightblue": "#5DC9E1",
|
||||
"yellow": "#FDDD00"
|
||||
},
|
||||
"colorConfig": {
|
||||
"target": "g"
|
||||
},
|
||||
"targets": {
|
||||
"main": "g"
|
||||
},
|
||||
"sets": {
|
||||
"set_1": {
|
||||
"main": "aqua"
|
||||
},
|
||||
"set_2": {
|
||||
"main": "blue"
|
||||
},
|
||||
"set_3": {
|
||||
"main": "fuchsia"
|
||||
},
|
||||
"set_4": {
|
||||
"main": "lightblue"
|
||||
},
|
||||
"set_5": {
|
||||
"main": "yellow"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -560,14 +591,19 @@
|
||||
"automobile",
|
||||
"transport"
|
||||
],
|
||||
"colors": [
|
||||
{
|
||||
"label": "Green",
|
||||
"value": "#424d07"
|
||||
}
|
||||
],
|
||||
"colors": {
|
||||
"green": "#424d07"
|
||||
},
|
||||
"colorConfig": {
|
||||
"target": "g"
|
||||
},
|
||||
"targets": {
|
||||
"main": "g"
|
||||
},
|
||||
"sets": {
|
||||
"set_1": {
|
||||
"main": "green"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -602,14 +638,19 @@
|
||||
"appliances"
|
||||
],
|
||||
"brand": "LG",
|
||||
"colors": [
|
||||
{
|
||||
"label": "Grey",
|
||||
"value": "#6b6c6b"
|
||||
}
|
||||
],
|
||||
"colors": {
|
||||
"grey": "#6b6c6b"
|
||||
},
|
||||
"colorConfig": {
|
||||
"target": "#text"
|
||||
},
|
||||
"targets": {
|
||||
"main": "#text"
|
||||
},
|
||||
"sets": {
|
||||
"set_1": {
|
||||
"main": "grey"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -644,16 +685,21 @@
|
||||
"software",
|
||||
"messaging"
|
||||
],
|
||||
"colors": [
|
||||
{
|
||||
"label": "Denim",
|
||||
"value": "#1e325c"
|
||||
}
|
||||
],
|
||||
"colors": {
|
||||
"denim": "#1e325c"
|
||||
},
|
||||
"colorConfig": {
|
||||
"target": "g"
|
||||
},
|
||||
"brand": "Mattermost"
|
||||
"brand": "Mattermost",
|
||||
"targets": {
|
||||
"main": "g"
|
||||
},
|
||||
"sets": {
|
||||
"set_1": {
|
||||
"main": "denim"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "McDonald's",
|
||||
@@ -739,31 +785,33 @@
|
||||
"bank",
|
||||
"finance"
|
||||
],
|
||||
"colors": [
|
||||
{
|
||||
"label": "Black",
|
||||
"value": "#000"
|
||||
},
|
||||
{
|
||||
"label": "Yellow",
|
||||
"value": "#f2bd2b"
|
||||
}
|
||||
],
|
||||
"colors": {
|
||||
"black": "#000",
|
||||
"yellow": "#f2bd2b",
|
||||
"white": "#fff"
|
||||
},
|
||||
"colorConfig": {
|
||||
"target": "#background"
|
||||
},
|
||||
"targets": {
|
||||
"background": "#background",
|
||||
"text": "#text"
|
||||
},
|
||||
"sets": {
|
||||
"black": {
|
||||
"background": "black",
|
||||
"text": "white"
|
||||
},
|
||||
"white": {
|
||||
"background": "white",
|
||||
"text": "black"
|
||||
},
|
||||
"yellow": {
|
||||
"background": "yellow",
|
||||
"text": "white"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Mono White",
|
||||
"path": "logos/mono_white.svg",
|
||||
"format": "SVG",
|
||||
"disable": false,
|
||||
"brand": "Monobank",
|
||||
"tags": [
|
||||
"bank",
|
||||
"finance"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Monobank paw",
|
||||
"path": "logos/monobank_paw.svg",
|
||||
@@ -1035,14 +1083,19 @@
|
||||
"database"
|
||||
],
|
||||
"brand": "Redis",
|
||||
"colors": [
|
||||
{
|
||||
"label": "Grey",
|
||||
"value": "#636466"
|
||||
}
|
||||
],
|
||||
"colors": {
|
||||
"grey": "#636466"
|
||||
},
|
||||
"colorConfig": {
|
||||
"selector": "#text"
|
||||
},
|
||||
"targets": {
|
||||
"selector_1": "#text"
|
||||
},
|
||||
"sets": {
|
||||
"set_1": {
|
||||
"selector_1": "grey"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -1089,21 +1142,25 @@
|
||||
"tags": [
|
||||
"furniture"
|
||||
],
|
||||
"colors": [
|
||||
{
|
||||
"label": "Brown",
|
||||
"value": "#2b1c13",
|
||||
"theme": "light"
|
||||
},
|
||||
{
|
||||
"label": "Green",
|
||||
"value": "#859310"
|
||||
}
|
||||
],
|
||||
"colors": {
|
||||
"brown": "#2b1c13",
|
||||
"green": "#859310"
|
||||
},
|
||||
"colorConfig": {
|
||||
"target": "#text"
|
||||
},
|
||||
"brand": "RoomerIN"
|
||||
"brand": "RoomerIN",
|
||||
"targets": {
|
||||
"main": "#text"
|
||||
},
|
||||
"sets": {
|
||||
"set_1": {
|
||||
"main": "brown"
|
||||
},
|
||||
"set_2": {
|
||||
"main": "green"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Sainsbury's",
|
||||
@@ -1200,14 +1257,19 @@
|
||||
"communication"
|
||||
],
|
||||
"brand": "Signal",
|
||||
"colors": [
|
||||
{
|
||||
"label": "Ultramarine",
|
||||
"value": "#3b45fd"
|
||||
}
|
||||
],
|
||||
"colors": {
|
||||
"ultramarine": "#3b45fd"
|
||||
},
|
||||
"colorConfig": {
|
||||
"target": "path"
|
||||
},
|
||||
"targets": {
|
||||
"main": "path"
|
||||
},
|
||||
"sets": {
|
||||
"set_1": {
|
||||
"main": "ultramarine"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -1220,14 +1282,19 @@
|
||||
"communication"
|
||||
],
|
||||
"brand": "Signal",
|
||||
"colors": [
|
||||
{
|
||||
"label": "Ultramarine",
|
||||
"value": "#3b45fd"
|
||||
}
|
||||
],
|
||||
"colors": {
|
||||
"ultramarine": "#3b45fd"
|
||||
},
|
||||
"colorConfig": {
|
||||
"target": "path"
|
||||
},
|
||||
"targets": {
|
||||
"main": "path"
|
||||
},
|
||||
"sets": {
|
||||
"set_1": {
|
||||
"main": "ultramarine"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -1252,14 +1319,21 @@
|
||||
"footwear"
|
||||
],
|
||||
"brand": "Skechers",
|
||||
"colors": [
|
||||
{
|
||||
"label": "Deep Blue",
|
||||
"value": "#062849"
|
||||
}
|
||||
],
|
||||
"colors": {
|
||||
"deep_blue": "#062849"
|
||||
},
|
||||
"colorConfig": {
|
||||
"selector": "#text, #logo_int"
|
||||
},
|
||||
"targets": {
|
||||
"selector_1": "#text",
|
||||
"selector_2": "#logo_int"
|
||||
},
|
||||
"sets": {
|
||||
"set_1": {
|
||||
"selector_1": "deep_blue",
|
||||
"selector_2": "deep_blue"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -1317,14 +1391,19 @@
|
||||
"transport"
|
||||
],
|
||||
"brand": "Tesla",
|
||||
"colors": [
|
||||
{
|
||||
"label": "Red",
|
||||
"value": "#e82127"
|
||||
}
|
||||
],
|
||||
"colors": {
|
||||
"red": "#e82127"
|
||||
},
|
||||
"colorConfig": {
|
||||
"target": "path"
|
||||
},
|
||||
"targets": {
|
||||
"main": "path"
|
||||
},
|
||||
"sets": {
|
||||
"set_1": {
|
||||
"main": "red"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -1348,14 +1427,19 @@
|
||||
"transport"
|
||||
],
|
||||
"brand": "Toyota",
|
||||
"colors": [
|
||||
{
|
||||
"label": "Red",
|
||||
"value": "#EB0A1E"
|
||||
}
|
||||
],
|
||||
"colors": {
|
||||
"red": "#EB0A1E"
|
||||
},
|
||||
"colorConfig": {
|
||||
"target": "path"
|
||||
},
|
||||
"targets": {
|
||||
"main": "path"
|
||||
},
|
||||
"sets": {
|
||||
"set_1": {
|
||||
"main": "red"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -1368,14 +1452,19 @@
|
||||
"transport"
|
||||
],
|
||||
"brand": "Toyota",
|
||||
"colors": [
|
||||
{
|
||||
"label": "Red",
|
||||
"value": "#EB0A1E"
|
||||
}
|
||||
],
|
||||
"colors": {
|
||||
"red": "#EB0A1E"
|
||||
},
|
||||
"colorConfig": {
|
||||
"target": "path"
|
||||
},
|
||||
"targets": {
|
||||
"main": "path"
|
||||
},
|
||||
"sets": {
|
||||
"set_1": {
|
||||
"main": "red"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
<svg width="500" height="500" viewBox="0 0 500 500" xmlns="http://www.w3.org/2000/svg">
|
||||
<path id="background" fill="#ffffff" fill-rule="evenodd" stroke="none"
|
||||
d="M 0 470 C -0 486.568542 13.431458 500 30 500 L 470 500 C 486.568542 500 500 486.568542 500 470 L 500 30 C 500 13.431458 486.568542 0 470 0 L 30 0 C 13.431458 0 0 13.431458 0 30 Z" />
|
||||
<g id="text" fill="#000000" stroke="none">
|
||||
<path
|
||||
d="M 165.832596 291.28302 L 165.832596 233.147736 C 165.832596 216.656921 156.9505 208.828003 142.036041 208.828003 C 129.634674 208.828003 118.909729 216.157349 114.21714 223.486694 C 111.200958 214.325195 103.65937 208.828003 91.761093 208.828003 C 79.359734 208.828003 68.634781 216.490143 65.282707 221.321045 L 65.282707 210.826935 L 43.999985 210.826935 L 43.999985 291.28302 L 65.282707 291.28302 L 65.282707 237.145599 C 68.466835 232.648193 74.667145 227.651276 82.040787 227.651276 C 90.755676 227.651276 94.107018 232.98172 94.107018 240.477112 L 94.107018 291.28302 L 115.557655 291.28302 L 115.557655 236.979553 C 118.573837 232.648193 124.774879 227.651276 132.315735 227.651276 C 141.030624 227.651276 144.381958 232.98172 144.381958 240.477112 L 144.381958 291.28302 L 165.832596 291.28302 Z" />
|
||||
<path
|
||||
d="M 220.610077 291.28302 C 247.422882 291.28302 263.511414 272.417511 263.511414 249.974457 C 263.511414 227.693481 247.422882 208.828003 220.610077 208.828003 C 193.963791 208.828003 177.875992 227.693481 177.875992 249.974457 C 177.875992 272.417511 193.963791 291.28302 220.610077 291.28302 Z M 220.610077 272.905243 C 207.37056 272.905243 199.996887 262.334595 199.996887 249.974457 C 199.996887 237.776398 207.37056 227.20578 220.610077 227.20578 C 233.848938 227.20578 241.38974 237.776398 241.38974 249.974457 C 241.38974 262.334595 233.848938 272.905243 220.610077 272.905243 Z" />
|
||||
<path
|
||||
d="M 356.887146 291.28302 L 356.887146 234.480347 C 356.887146 218.822571 348.340912 208.828003 330.576721 208.828003 C 317.33786 208.828003 307.450409 215.157532 302.255493 221.321045 L 302.255493 210.826935 L 280.972015 210.826935 L 280.972015 291.28302 L 302.255493 291.28302 L 302.255493 237.145599 C 305.77475 232.31543 312.310181 227.651276 320.689209 227.651276 C 329.738495 227.651276 335.604401 231.482361 335.604401 242.642761 L 335.604401 291.28302 L 356.887146 291.28302 Z" />
|
||||
<path
|
||||
d="M 412.862396 291.28302 C 439.675873 291.28302 455.762207 272.417511 455.762207 249.974457 C 455.762207 227.693481 439.675873 208.828003 412.862396 208.828003 C 386.21756 208.828003 370.128998 227.693481 370.128998 249.974457 C 370.128998 272.417511 386.21756 291.28302 412.862396 291.28302 Z M 412.862396 272.905243 C 399.624268 272.905243 392.249939 262.334595 392.249939 249.974457 C 392.249939 237.776398 399.624268 227.20578 412.862396 227.20578 C 426.103394 227.20578 433.643524 237.776398 433.643524 249.974457 C 433.643524 262.334595 426.103394 272.905243 412.862396 272.905243 Z" />
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 2.9 KiB |
93
scripts/convertColorsFormat.js
Normal file
93
scripts/convertColorsFormat.js
Normal file
@@ -0,0 +1,93 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
// Path to logos.json
|
||||
const logosJsonPath = path.join(__dirname, '../public/data/logos.json');
|
||||
|
||||
// Read the current logos.json file
|
||||
console.log('Reading logos.json...');
|
||||
const logosData = JSON.parse(fs.readFileSync(logosJsonPath, 'utf8'));
|
||||
|
||||
// Convert the colors format and create targets & sets
|
||||
console.log('Converting logos format...');
|
||||
let convertedColorsCount = 0;
|
||||
let convertedConfigCount = 0;
|
||||
|
||||
for (const logo of logosData) {
|
||||
// 1. Convert colors array to object if needed
|
||||
if (logo.colors && Array.isArray(logo.colors)) {
|
||||
// Convert array format to object format
|
||||
const newColors = {};
|
||||
for (const colorObj of logo.colors) {
|
||||
// Convert label to lowercase and replace spaces with underscores
|
||||
const key = colorObj.label.toLowerCase().replace(/\s+/g, '_');
|
||||
newColors[key] = colorObj.value;
|
||||
}
|
||||
logo.colors = newColors;
|
||||
convertedColorsCount++;
|
||||
}
|
||||
|
||||
// 2. Convert colorConfig to targets and sets
|
||||
if (logo.colorConfig && !logo.targets) {
|
||||
// Create targets object
|
||||
logo.targets = {};
|
||||
|
||||
// Handle selector or target from colorConfig
|
||||
if (logo.colorConfig.selector) {
|
||||
// Split multiple selectors (e.g., "#text, #logo_int")
|
||||
const selectors = logo.colorConfig.selector.split(',').map(s => s.trim());
|
||||
|
||||
// Create a target for each selector
|
||||
selectors.forEach((selector, index) => {
|
||||
logo.targets[`selector_${index + 1}`] = selector;
|
||||
});
|
||||
|
||||
// Create sets for each color
|
||||
if (logo.colors && Object.keys(logo.colors).length > 0) {
|
||||
logo.sets = {};
|
||||
let setIndex = 1;
|
||||
|
||||
// Create a set for each color
|
||||
for (const [colorName, colorValue] of Object.entries(logo.colors)) {
|
||||
const setName = `set_${setIndex}`;
|
||||
logo.sets[setName] = {};
|
||||
|
||||
// Apply this color to all targets in this set
|
||||
Object.keys(logo.targets).forEach(targetName => {
|
||||
logo.sets[setName][targetName] = colorName;
|
||||
});
|
||||
|
||||
setIndex++;
|
||||
}
|
||||
}
|
||||
} else if (logo.colorConfig.target) {
|
||||
logo.targets.main = logo.colorConfig.target;
|
||||
|
||||
// Create sets for each color
|
||||
if (logo.colors && Object.keys(logo.colors).length > 0) {
|
||||
logo.sets = {};
|
||||
let setIndex = 1;
|
||||
|
||||
// Create a set for each color
|
||||
for (const [colorName, colorValue] of Object.entries(logo.colors)) {
|
||||
const setName = `set_${setIndex}`;
|
||||
logo.sets[setName] = {
|
||||
main: colorName
|
||||
};
|
||||
setIndex++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
convertedConfigCount++;
|
||||
|
||||
// Keep the original colorConfig for backward compatibility
|
||||
}
|
||||
}
|
||||
|
||||
// Write the updated data back to logos.json
|
||||
console.log('Writing updated logos.json...');
|
||||
fs.writeFileSync(logosJsonPath, JSON.stringify(logosData, null, 2));
|
||||
console.log(`Conversion complete! Updated colors for ${convertedColorsCount} logos and created targets/sets for ${convertedConfigCount} logos.`);
|
||||
@@ -171,6 +171,52 @@ function scanLogos() {
|
||||
if (!logoObj.brand) logoObj.brand = logoObj.name;
|
||||
if (!Array.isArray(logoObj.tags)) logoObj.tags = [];
|
||||
if (typeof logoObj.disable !== 'boolean') logoObj.disable = false;
|
||||
|
||||
// Set default colorConfig, targets, and sets for SVGs
|
||||
if (logoObj.format.toLowerCase() === 'svg') {
|
||||
// Maintain backward compatibility
|
||||
if (!logoObj.colorConfig) {
|
||||
logoObj.colorConfig = { target: 'path', attribute: 'fill' };
|
||||
}
|
||||
|
||||
// Add new format targets if not already present
|
||||
if (!logoObj.targets && (logoObj.colorConfig.target || logoObj.colorConfig.selector)) {
|
||||
logoObj.targets = {};
|
||||
|
||||
if (logoObj.colorConfig.selector) {
|
||||
// Split multiple selectors (e.g., "#text, #logo_int")
|
||||
const selectors = logoObj.colorConfig.selector.split(',').map(s => s.trim());
|
||||
|
||||
// Create a target for each selector
|
||||
selectors.forEach((selector, index) => {
|
||||
logoObj.targets[`selector_${index + 1}`] = selector;
|
||||
});
|
||||
} else if (logoObj.colorConfig.target) {
|
||||
logoObj.targets.main = logoObj.colorConfig.target;
|
||||
} else {
|
||||
logoObj.targets.main = 'path';
|
||||
}
|
||||
}
|
||||
|
||||
// Create sets if there are colors but no sets
|
||||
if (logoObj.colors && !logoObj.sets) {
|
||||
logoObj.sets = {};
|
||||
let setIndex = 1;
|
||||
|
||||
// Create a set for each color
|
||||
for (const [colorName, colorValue] of Object.entries(logoObj.colors)) {
|
||||
const setName = `set_${setIndex}`;
|
||||
logoObj.sets[setName] = {};
|
||||
|
||||
// Apply this color to all targets
|
||||
Object.keys(logoObj.targets || {}).forEach(targetName => {
|
||||
logoObj.sets[setName][targetName] = colorName;
|
||||
});
|
||||
|
||||
setIndex++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return logos;
|
||||
|
||||
@@ -62,6 +62,10 @@ $: getLogoThemeColor = logo => getDefaultLogoColor(logo.colors, theme);
|
||||
path={logo.path}
|
||||
color={logo.colors ? (logo._activeColor || getLogoThemeColor(logo)) : undefined}
|
||||
colorConfig={logo.colors ? logo.colorConfig : undefined}
|
||||
targets={logo.targets}
|
||||
sets={logo.sets}
|
||||
colors={logo.colors}
|
||||
activeSet={logo._activeSet}
|
||||
alt={logo.name}
|
||||
/>
|
||||
{/key}
|
||||
@@ -105,17 +109,40 @@ $: getLogoThemeColor = logo => getDefaultLogoColor(logo.colors, theme);
|
||||
<path d="M682.843,117.843l-565.686,565.685c-156.209,-156.21 -156.209,-409.476 0,-565.685c156.21,-156.21 409.476,-156.21 565.686,-0Z" style="fill:#33363f;"/>
|
||||
</svg>
|
||||
</span>
|
||||
{#each logo.colors as colorObj}
|
||||
<span
|
||||
class="color-circle"
|
||||
title={colorObj.label}
|
||||
style="background:{colorObj.value}"
|
||||
tabindex="0"
|
||||
role="button"
|
||||
on:click|stopPropagation={() => logo._activeColor = colorObj.value}
|
||||
on:keydown|stopPropagation={(e) => (e.key === 'Enter' || e.key === ' ') && (logo._activeColor = colorObj.value)}
|
||||
></span>
|
||||
{/each}
|
||||
{#if logo.sets}
|
||||
{#each Object.entries(logo.sets) as [setName, setConfig], i}
|
||||
<span
|
||||
class="color-circle set-circle"
|
||||
title={`Color Set ${i + 1}`}
|
||||
tabindex="0"
|
||||
role="button"
|
||||
on:click|stopPropagation={() => {
|
||||
logo._activeColor = Object.values(logo.colors)[i % Object.keys(logo.colors).length];
|
||||
logo._activeSet = setName;
|
||||
}}
|
||||
on:keydown|stopPropagation={(e) => {
|
||||
if (e.key === 'Enter' || e.key === ' ') {
|
||||
logo._activeColor = Object.values(logo.colors)[i % Object.keys(logo.colors).length];
|
||||
logo._activeSet = setName;
|
||||
}
|
||||
}}
|
||||
>
|
||||
{i + 1}
|
||||
</span>
|
||||
{/each}
|
||||
{:else}
|
||||
{#each Object.entries(logo.colors) as [colorName, colorValue], i}
|
||||
<span
|
||||
class="color-circle"
|
||||
title={colorName.replace('_', ' ')}
|
||||
style="background:{colorValue}"
|
||||
tabindex="0"
|
||||
role="button"
|
||||
on:click|stopPropagation={() => logo._activeColor = colorValue}
|
||||
on:keydown|stopPropagation={(e) => (e.key === 'Enter' || e.key === ' ') && (logo._activeColor = colorValue)}
|
||||
></span>
|
||||
{/each}
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
@@ -189,4 +216,20 @@ $: getLogoThemeColor = logo => getDefaultLogoColor(logo.colors, theme);
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
.set-circle {
|
||||
background: var(--color-border);
|
||||
color: var(--color-text);
|
||||
font-size: 10px;
|
||||
font-weight: bold;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
/* Dark theme variation */
|
||||
:global(.dark-theme) .set-circle {
|
||||
background: #444;
|
||||
color: #eee;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -3,6 +3,10 @@
|
||||
export let path;
|
||||
export let color;
|
||||
export let colorConfig = { target: "path", attribute: "fill" };
|
||||
export let targets = null;
|
||||
export let sets = null;
|
||||
export let activeSet = null;
|
||||
export let colors = null; // Add colors object for access to all color values
|
||||
export const alt = "";
|
||||
|
||||
let svgHtml = "";
|
||||
@@ -54,36 +58,70 @@
|
||||
});
|
||||
// Remove all <style> elements
|
||||
styleEls.forEach((styleEl) => styleEl.remove());
|
||||
let targets;
|
||||
if (colorConfig.selector) {
|
||||
targets = doc.querySelectorAll(colorConfig.selector);
|
||||
} else if (colorConfig.target) {
|
||||
targets = doc.querySelectorAll(colorConfig.target);
|
||||
} else {
|
||||
targets = [];
|
||||
}
|
||||
targets.forEach((el) => {
|
||||
if (colorConfig.attribute) {
|
||||
// Legacy: force a single attribute
|
||||
el.setAttribute(colorConfig.attribute, color);
|
||||
} else {
|
||||
// Always override fill and stroke unless they are 'none'
|
||||
if (el.hasAttribute("fill") && el.getAttribute("fill") !== "none") {
|
||||
el.setAttribute("fill", color);
|
||||
}
|
||||
if (el.hasAttribute("stroke") && el.getAttribute("stroke") !== "none") {
|
||||
el.setAttribute("stroke", color);
|
||||
}
|
||||
if (!el.hasAttribute("fill") && !el.hasAttribute("stroke")) {
|
||||
// If neither, prefer fill
|
||||
el.setAttribute("fill", color);
|
||||
// Handle the new format with targets and sets if available
|
||||
if (targets && sets && activeSet && sets[activeSet]) {
|
||||
// Get the color assignments from the active set
|
||||
const colorAssignments = sets[activeSet];
|
||||
|
||||
// Apply each target-color pair
|
||||
for (const [targetName, colorName] of Object.entries(colorAssignments)) {
|
||||
if (targets[targetName] && colors && colors[colorName]) {
|
||||
// Get the selector for this target
|
||||
const selector = targets[targetName];
|
||||
const targetElements = doc.querySelectorAll(selector);
|
||||
// Get the actual color value for this target
|
||||
const targetColor = colors[colorName];
|
||||
|
||||
// Apply the color to all elements matching this selector
|
||||
targetElements.forEach(el => {
|
||||
// Always override fill and stroke unless they are 'none'
|
||||
if (el.hasAttribute("fill") && el.getAttribute("fill") !== "none") {
|
||||
el.setAttribute("fill", targetColor);
|
||||
}
|
||||
if (el.hasAttribute("stroke") && el.getAttribute("stroke") !== "none") {
|
||||
el.setAttribute("stroke", targetColor);
|
||||
}
|
||||
if (!el.hasAttribute("fill") && !el.hasAttribute("stroke")) {
|
||||
// If neither, prefer fill
|
||||
el.setAttribute("fill", targetColor);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
// Otherwise, use the legacy format for backward compatibility
|
||||
else {
|
||||
let targetElements;
|
||||
if (colorConfig.selector) {
|
||||
targetElements = doc.querySelectorAll(colorConfig.selector);
|
||||
} else if (colorConfig.target) {
|
||||
targetElements = doc.querySelectorAll(colorConfig.target);
|
||||
} else {
|
||||
targetElements = [];
|
||||
}
|
||||
targetElements.forEach((el) => {
|
||||
if (colorConfig.attribute) {
|
||||
// Legacy: force a single attribute
|
||||
el.setAttribute(colorConfig.attribute, color);
|
||||
} else {
|
||||
// Always override fill and stroke unless they are 'none'
|
||||
if (el.hasAttribute("fill") && el.getAttribute("fill") !== "none") {
|
||||
el.setAttribute("fill", color);
|
||||
}
|
||||
if (el.hasAttribute("stroke") && el.getAttribute("stroke") !== "none") {
|
||||
el.setAttribute("stroke", color);
|
||||
}
|
||||
if (!el.hasAttribute("fill") && !el.hasAttribute("stroke")) {
|
||||
// If neither, prefer fill
|
||||
el.setAttribute("fill", color);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
svgHtml = doc.documentElement.outerHTML;
|
||||
}
|
||||
|
||||
$: path, color, colorConfig, fetchAndColorSvg();
|
||||
$: path, color, colorConfig, targets, sets, activeSet, colors, fetchAndColorSvg();
|
||||
</script>
|
||||
|
||||
{@html svgHtml}
|
||||
|
||||
@@ -98,6 +98,10 @@
|
||||
? logo._activeColor || getLogoThemeColor(logo)
|
||||
: undefined}
|
||||
colorConfig={logo.colors ? logo.colorConfig : undefined}
|
||||
targets={logo.targets}
|
||||
sets={logo.sets}
|
||||
colors={logo.colors}
|
||||
activeSet={logo._activeSet}
|
||||
alt={logo.name}
|
||||
/>
|
||||
{:else}
|
||||
@@ -142,20 +146,43 @@
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
{#each logo.colors as colorObj}
|
||||
<span
|
||||
class="color-circle"
|
||||
title={colorObj.label}
|
||||
style={`background:${colorObj.value}`}
|
||||
tabindex="0"
|
||||
role="button"
|
||||
on:click|stopPropagation={() =>
|
||||
(logo._activeColor = colorObj.value)}
|
||||
on:keydown|stopPropagation={(e) =>
|
||||
(e.key === "Enter" || e.key === " ") &&
|
||||
(logo._activeColor = colorObj.value)}
|
||||
></span>
|
||||
{/each}
|
||||
{#if logo.sets}
|
||||
{#each Object.entries(logo.sets) as [setName, setConfig], i}
|
||||
<span
|
||||
class="color-circle set-circle"
|
||||
title={`Color Set ${i + 1}`}
|
||||
tabindex="0"
|
||||
role="button"
|
||||
on:click|stopPropagation={() => {
|
||||
logo._activeColor = Object.values(logo.colors)[i % Object.keys(logo.colors).length];
|
||||
logo._activeSet = setName;
|
||||
}}
|
||||
on:keydown|stopPropagation={(e) => {
|
||||
if (e.key === "Enter" || e.key === " ") {
|
||||
logo._activeColor = Object.values(logo.colors)[i % Object.keys(logo.colors).length];
|
||||
logo._activeSet = setName;
|
||||
}
|
||||
}}
|
||||
>
|
||||
{i + 1}
|
||||
</span>
|
||||
{/each}
|
||||
{:else}
|
||||
{#each Object.entries(logo.colors) as [colorName, colorValue]}
|
||||
<span
|
||||
class="color-circle"
|
||||
title={colorName.replace('_', ' ')}
|
||||
style={`background:${colorValue}`}
|
||||
tabindex="0"
|
||||
role="button"
|
||||
on:click|stopPropagation={() =>
|
||||
(logo._activeColor = colorValue)}
|
||||
on:keydown|stopPropagation={(e) =>
|
||||
(e.key === "Enter" || e.key === " ") &&
|
||||
(logo._activeColor = colorValue)}
|
||||
></span>
|
||||
{/each}
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
@@ -271,4 +298,19 @@
|
||||
justify-content: space-between;
|
||||
gap: 0.5em;
|
||||
}
|
||||
.set-circle {
|
||||
background: var(--color-border);
|
||||
color: var(--color-text);
|
||||
font-size: 10px;
|
||||
font-weight: bold;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
/* Dark theme variation */
|
||||
:global(.dark-theme) .set-circle {
|
||||
background: #444;
|
||||
color: #eee;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -141,6 +141,10 @@
|
||||
path={logo.path}
|
||||
color={logo.colors ? (logo._activeColor || getLogoThemeColor(logo)) : undefined}
|
||||
colorConfig={validColorConfig}
|
||||
targets={logo.targets}
|
||||
sets={logo.sets}
|
||||
colors={logo.colors}
|
||||
activeSet={logo._activeSet}
|
||||
alt={logo.name}
|
||||
/>
|
||||
{:else}
|
||||
@@ -166,17 +170,40 @@
|
||||
<path d="M682.843,117.843l-565.686,565.685c-156.209,-156.21 -156.209,-409.476 0,-565.685c156.21,-156.21 409.476,-156.21 565.686,-0Z" style="fill:#33363f;"/>
|
||||
</svg>
|
||||
</span>
|
||||
{#each logo.colors as colorObj}
|
||||
<span
|
||||
class="color-circle"
|
||||
title={colorObj.label}
|
||||
style={`background:${colorObj.value}`}
|
||||
tabindex="0"
|
||||
role="button"
|
||||
on:click|stopPropagation={() => logo._activeColor = colorObj.value}
|
||||
on:keydown|stopPropagation={(e) => (e.key === 'Enter' || e.key === ' ') && (logo._activeColor = colorObj.value)}
|
||||
></span>
|
||||
{/each}
|
||||
{#if logo.sets}
|
||||
{#each Object.entries(logo.sets) as [setName, setConfig], i}
|
||||
<span
|
||||
class="color-circle set-circle"
|
||||
title={`Color Set ${i + 1}`}
|
||||
tabindex="0"
|
||||
role="button"
|
||||
on:click|stopPropagation={() => {
|
||||
logo._activeColor = Object.values(logo.colors)[i % Object.keys(logo.colors).length];
|
||||
logo._activeSet = setName;
|
||||
}}
|
||||
on:keydown|stopPropagation={(e) => {
|
||||
if (e.key === 'Enter' || e.key === ' ') {
|
||||
logo._activeColor = Object.values(logo.colors)[i % Object.keys(logo.colors).length];
|
||||
logo._activeSet = setName;
|
||||
}
|
||||
}}
|
||||
>
|
||||
{i + 1}
|
||||
</span>
|
||||
{/each}
|
||||
{:else}
|
||||
{#each Object.entries(logo.colors) as [colorName, colorValue]}
|
||||
<span
|
||||
class="color-circle"
|
||||
title={colorName.replace('_', ' ')}
|
||||
style={`background:${colorValue}`}
|
||||
tabindex="0"
|
||||
role="button"
|
||||
on:click|stopPropagation={() => logo._activeColor = colorValue}
|
||||
on:keydown|stopPropagation={(e) => (e.key === 'Enter' || e.key === ' ') && (logo._activeColor = colorValue)}
|
||||
></span>
|
||||
{/each}
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
{#if logo.brand}
|
||||
@@ -198,6 +225,21 @@
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.set-circle {
|
||||
background: var(--color-border);
|
||||
color: var(--color-text);
|
||||
font-size: 10px;
|
||||
font-weight: bold;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
:global(.dark-theme) .set-circle {
|
||||
background: #444;
|
||||
color: #eee;
|
||||
}
|
||||
|
||||
.modal-backdrop.fullscreen {
|
||||
position: fixed;
|
||||
top: 0; left: 0; right: 0; bottom: 0;
|
||||
@@ -316,6 +358,22 @@
|
||||
flex-wrap: wrap;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
.set-circle {
|
||||
background: var(--color-border);
|
||||
color: var(--color-text);
|
||||
font-size: 10px;
|
||||
font-weight: bold;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
/* Dark theme variation */
|
||||
:global(.dark-theme) .set-circle {
|
||||
background: #444;
|
||||
color: #eee;
|
||||
}
|
||||
|
||||
@media (max-width: 900px) {
|
||||
.modal-body.fullscreen-body {
|
||||
flex-direction: column;
|
||||
|
||||
@@ -1,19 +1,31 @@
|
||||
// Utility to pick the logo color for the current theme using the "theme" key only
|
||||
export function getDefaultLogoColor(colors, theme = 'light') {
|
||||
if (!colors || colors.length === 0) return undefined;
|
||||
// Use the color with the matching theme key if present
|
||||
const match = colors.find(c => c.theme === theme);
|
||||
if (match) return match.value;
|
||||
if (!colors || Object.keys(colors).length === 0) return undefined;
|
||||
|
||||
// Look through all colors to find one with a theme property
|
||||
for (const [colorName, colorValue] of Object.entries(colors)) {
|
||||
// If color value is an object with theme property matching current theme
|
||||
if (typeof colorValue === 'object' && colorValue.theme === theme) {
|
||||
return colorValue.value;
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback: do not colorize (undefined)
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// Utility to select the color with the matching theme key from the colors array
|
||||
// Utility to select the color with the matching theme key from the colors object
|
||||
export function getThemeColor(colors, theme = 'light') {
|
||||
if (!colors || colors.length === 0) return undefined;
|
||||
// Try to find a color with the matching theme key
|
||||
const match = colors.find(c => c.theme === theme);
|
||||
if (match) return match.value;
|
||||
if (!colors || Object.keys(colors).length === 0) return undefined;
|
||||
|
||||
// Look through all colors to find one with a theme property
|
||||
for (const [colorName, colorValue] of Object.entries(colors)) {
|
||||
// If color value is an object with theme property matching current theme
|
||||
if (typeof colorValue === 'object' && colorValue.theme === theme) {
|
||||
return colorValue.value;
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback: pick the first color
|
||||
return colors[0].value;
|
||||
return Object.values(colors)[0];
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user