#!/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); // First, remove any existing fill attributes for this element // Updated regex to preserve the closing tag structure const removeExistingFillRegex = new RegExp(`(id="${elementId}"[^>]*?)\\s*fill="[^"]*"([^>]*>)`, 'g'); modifiedSvg = modifiedSvg.replace(removeExistingFillRegex, '$1$2'); // Then add the new fill attribute before the closing > const addFillRegex = new RegExp(`(id="${elementId}"[^>]*?)(\s*\/?>)`, '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 };