mirror of
https://github.com/shadoll/sLogos.git
synced 2026-02-04 02:53:22 +00:00
feat: add script and workflow step for generating SVG variants from logos
This commit is contained in:
3
.github/workflows/gh-pages.yml
vendored
3
.github/workflows/gh-pages.yml
vendored
@@ -34,6 +34,9 @@ jobs:
|
|||||||
- name: Generate logos.json
|
- name: Generate logos.json
|
||||||
run: node scripts/scanLogos.js
|
run: node scripts/scanLogos.js
|
||||||
|
|
||||||
|
- name: Generate SVG variants
|
||||||
|
run: node scripts/generate-svg-variants.js
|
||||||
|
|
||||||
- name: Prepare Pages artifact
|
- name: Prepare Pages artifact
|
||||||
run: |
|
run: |
|
||||||
mkdir -p ./gh-pages-artifact/build
|
mkdir -p ./gh-pages-artifact/build
|
||||||
|
|||||||
8
Makefile
8
Makefile
@@ -6,7 +6,7 @@ CONTAINER_NAME = slogos-dev
|
|||||||
DEV_PORT = 5006
|
DEV_PORT = 5006
|
||||||
|
|
||||||
# Main targets
|
# Main targets
|
||||||
.PHONY: all build start stop restart logs clean scan-logos dev rebuild favicon deps-favicon build-with-favicons sync-packages convert-colors
|
.PHONY: all build start stop restart logs clean scan-logos dev rebuild favicon deps-favicon build-with-favicons sync-packages convert-colors generate-svg-variants
|
||||||
|
|
||||||
all: build start
|
all: build start
|
||||||
|
|
||||||
@@ -75,3 +75,9 @@ update-lock:
|
|||||||
@echo "Updating package-lock.json to match package.json..."
|
@echo "Updating package-lock.json to match package.json..."
|
||||||
$(DOCKER_COMPOSE) -f compose.dev.yml run --rm $(CONTAINER_NAME) npm install
|
$(DOCKER_COMPOSE) -f compose.dev.yml run --rm $(CONTAINER_NAME) npm install
|
||||||
@echo "Package lock file has been updated"
|
@echo "Package lock file has been updated"
|
||||||
|
|
||||||
|
# Generate SVG variants with color sets
|
||||||
|
generate-svg-variants:
|
||||||
|
@echo "Generating SVG variants with color sets..."
|
||||||
|
$(DOCKER_COMPOSE) -f compose.dev.yml run --rm $(CONTAINER_NAME) node scripts/generate-svg-variants.js
|
||||||
|
@echo "SVG variants have been generated"
|
||||||
|
|||||||
@@ -7,7 +7,9 @@
|
|||||||
"dev": "rollup -c -w",
|
"dev": "rollup -c -w",
|
||||||
"start": "sirv public --host 0.0.0.0 --dev --single",
|
"start": "sirv public --host 0.0.0.0 --dev --single",
|
||||||
"scan-logos": "node scripts/scanLogos.js",
|
"scan-logos": "node scripts/scanLogos.js",
|
||||||
"generate-favicons": "node scripts/generateFavicons.js"
|
"generate-favicons": "node scripts/generateFavicons.js",
|
||||||
|
"generate-variants": "node scripts/generate-svg-variants.js",
|
||||||
|
"variants": "npm run generate-variants"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@rollup/plugin-commonjs": "^17.0.0",
|
"@rollup/plugin-commonjs": "^17.0.0",
|
||||||
|
|||||||
@@ -2361,4 +2361,4 @@
|
|||||||
],
|
],
|
||||||
"brand": "Bvr"
|
"brand": "Bvr"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
190
scripts/generate-svg-variants.js
Normal file
190
scripts/generate-svg-variants.js
Normal file
@@ -0,0 +1,190 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
|
|
||||||
|
const fs = require('fs');
|
||||||
|
const path = require('path');
|
||||||
|
|
||||||
|
const LOGOS_DIR = path.join(__dirname, '..', 'public', 'logos');
|
||||||
|
const LOGOS_GEN_DIR = path.join(__dirname, '..', 'public', 'logos_gen');
|
||||||
|
|
||||||
|
// Try multiple possible locations for logos.json
|
||||||
|
const POSSIBLE_LOGOS_JSON_PATHS = [
|
||||||
|
path.join(process.cwd(), 'public', 'data', 'logos.json'), // Correct location after scan-logos
|
||||||
|
path.join(__dirname, '..', 'public', 'data', 'logos.json'),
|
||||||
|
path.join(process.cwd(), 'public', 'logos.json'),
|
||||||
|
path.join(__dirname, '..', 'public', 'logos.json'),
|
||||||
|
path.join(__dirname, '..', 'src', 'data', 'logos.json')
|
||||||
|
];
|
||||||
|
|
||||||
|
function findLogosJsonPath() {
|
||||||
|
for (const possiblePath of POSSIBLE_LOGOS_JSON_PATHS) {
|
||||||
|
if (fs.existsSync(possiblePath)) {
|
||||||
|
console.log(`📁 Found logos.json at: ${possiblePath}`);
|
||||||
|
return possiblePath;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
console.error('❌ Could not find logos.json in any of these locations:');
|
||||||
|
POSSIBLE_LOGOS_JSON_PATHS.forEach(p => console.error(` ${p}`));
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load logos data from logos.json
|
||||||
|
*/
|
||||||
|
function loadLogosData() {
|
||||||
|
const LOGOS_JSON_PATH = findLogosJsonPath();
|
||||||
|
|
||||||
|
if (!LOGOS_JSON_PATH) {
|
||||||
|
console.error('❌ logos.json file not found');
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const data = fs.readFileSync(LOGOS_JSON_PATH, 'utf8');
|
||||||
|
return JSON.parse(data);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error loading logos.json:', error.message);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Apply color set to SVG content
|
||||||
|
*/
|
||||||
|
function applySvgColors(svgContent, colorSet, targets) {
|
||||||
|
let modifiedSvg = svgContent;
|
||||||
|
|
||||||
|
if (!targets || !colorSet) {
|
||||||
|
return modifiedSvg;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply colors based on targets mapping
|
||||||
|
Object.entries(targets).forEach(([targetKey, selector]) => {
|
||||||
|
if (colorSet[targetKey]) {
|
||||||
|
const color = colorSet[targetKey];
|
||||||
|
|
||||||
|
// Handle different types of selectors
|
||||||
|
if (selector.startsWith('#')) {
|
||||||
|
// ID selector - replace fill/stroke for specific element
|
||||||
|
const elementId = selector.substring(1);
|
||||||
|
const idRegex = new RegExp(`(id="${elementId}"[^>]*?)fill="[^"]*"`, 'g');
|
||||||
|
modifiedSvg = modifiedSvg.replace(idRegex, `$1fill="${color}"`);
|
||||||
|
|
||||||
|
// If no fill attribute, add it
|
||||||
|
const addFillRegex = new RegExp(`(id="${elementId}"[^>]*?)(?!.*fill=)([^>]*>)`, 'g');
|
||||||
|
modifiedSvg = modifiedSvg.replace(addFillRegex, `$1 fill="${color}"$2`);
|
||||||
|
} else {
|
||||||
|
// Default: replace all fill attributes (fallback)
|
||||||
|
modifiedSvg = modifiedSvg.replace(
|
||||||
|
/fill="[^"]*"/g,
|
||||||
|
`fill="${color}"`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return modifiedSvg;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate SVG variants with color sets
|
||||||
|
*/
|
||||||
|
function generateSvgVariants() {
|
||||||
|
console.log('🎨 Generating SVG variants with color sets...');
|
||||||
|
|
||||||
|
// Ensure the logos_gen directory exists
|
||||||
|
if (!fs.existsSync(LOGOS_GEN_DIR)) {
|
||||||
|
fs.mkdirSync(LOGOS_GEN_DIR, { recursive: true });
|
||||||
|
console.log(`📁 Created directory: ${LOGOS_GEN_DIR}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const logos = loadLogosData();
|
||||||
|
let generatedCount = 0;
|
||||||
|
let skippedCount = 0;
|
||||||
|
|
||||||
|
if (!Array.isArray(logos)) {
|
||||||
|
console.error('❌ Expected logos.json to contain an array, got:', typeof logos);
|
||||||
|
process.exit(1);
|
||||||
|
} console.log(`📊 Processing ${logos.length} logos...`);
|
||||||
|
|
||||||
|
logos.forEach((logo, index) => {
|
||||||
|
// Check if logo has required properties
|
||||||
|
if (!logo || typeof logo !== 'object') {
|
||||||
|
console.warn(`⚠️ Logo at index ${index} is not a valid object`);
|
||||||
|
skippedCount++;
|
||||||
|
return;
|
||||||
|
}// Handle different possible filename properties
|
||||||
|
const pathOrFilename = logo.path || logo.filename || logo.file || logo.name;
|
||||||
|
|
||||||
|
if (!pathOrFilename) {
|
||||||
|
console.warn(`⚠️ Logo at index ${index} has no path/filename property`);
|
||||||
|
skippedCount++;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract just the filename from path if needed
|
||||||
|
const actualFilename = pathOrFilename.includes('/') ? path.basename(pathOrFilename) : pathOrFilename;
|
||||||
|
|
||||||
|
// Skip if no sets or not an SVG
|
||||||
|
if (!logo.sets || !actualFilename.endsWith('.svg')) {
|
||||||
|
skippedCount++;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const basePath = path.join(LOGOS_DIR, actualFilename);
|
||||||
|
const baseNameWithoutExt = path.basename(actualFilename, '.svg'); // Check if base SVG exists
|
||||||
|
if (!fs.existsSync(basePath)) {
|
||||||
|
console.warn(`⚠️ Base SVG not found: ${actualFilename}`);
|
||||||
|
skippedCount++;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read the base SVG content
|
||||||
|
const baseSvgContent = fs.readFileSync(basePath, 'utf8');
|
||||||
|
|
||||||
|
// Generate variants for each color set
|
||||||
|
// Handle sets as object (not array)
|
||||||
|
Object.entries(logo.sets).forEach(([setName, setConfig]) => {
|
||||||
|
if (!setName || !setConfig) {
|
||||||
|
console.warn(`⚠️ Invalid set in ${actualFilename}: missing name or config`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert set config to colors object
|
||||||
|
const colors = {};
|
||||||
|
if (logo.colors && logo.targets) {
|
||||||
|
Object.entries(setConfig).forEach(([targetKey, colorKey]) => {
|
||||||
|
if (logo.colors[colorKey]) {
|
||||||
|
colors[targetKey] = logo.colors[colorKey];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Object.keys(colors).length === 0) {
|
||||||
|
console.warn(`⚠️ No valid colors found for set ${setName} in ${actualFilename}`);
|
||||||
|
return;
|
||||||
|
} const variantFilename = `${baseNameWithoutExt}__${setName}.svg`;
|
||||||
|
const variantPath = path.join(LOGOS_GEN_DIR, variantFilename);
|
||||||
|
|
||||||
|
// Apply colors to SVG
|
||||||
|
const modifiedSvg = applySvgColors(baseSvgContent, colors, logo.targets);
|
||||||
|
|
||||||
|
// Write the variant SVG
|
||||||
|
fs.writeFileSync(variantPath, modifiedSvg, 'utf8');
|
||||||
|
|
||||||
|
console.log(`✅ Generated: ${variantFilename}`);
|
||||||
|
generatedCount++;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(`\n🎨 SVG variant generation complete!`);
|
||||||
|
console.log(` Generated: ${generatedCount} variants`);
|
||||||
|
console.log(` Skipped: ${skippedCount} logos (no sets or not SVG)`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run the script
|
||||||
|
if (require.main === module) {
|
||||||
|
generateSvgVariants();
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = { generateSvgVariants };
|
||||||
Reference in New Issue
Block a user