#!/usr/bin/env node const fs = require('fs'); const path = require('path'); const { execSync } = require('child_process'); // Configuración const CONFIG = { pluginDir: __dirname, assetsDir: path.join(__dirname, 'assets'), fontawesomeDir: path.join(__dirname, 'assets', 'fontawesome'), webfontsDir: path.join(__dirname, 'assets', 'fontawesome', 'webfonts'), metadataDir: path.join(__dirname, 'assets', 'fontawesome', 'metadata'), // URLs de referencia (no para descargar directamente por licencia) fontawesomeUrl: 'https://fontawesome.com/download', proDownloadUrl: 'https://fontawesome.com/account/download' }; // Colores para la consola const colors = { reset: '\x1b[0m', bright: '\x1b[1m', green: '\x1b[32m', yellow: '\x1b[33m', blue: '\x1b[34m', magenta: '\x1b[35m', cyan: '\x1b[36m', red: '\x1b[31m' }; // Función para imprimir con estilo function log(message, color = 'reset', type = 'info') { const prefix = type === 'success' ? '✅' : type === 'warning' ? '⚠️' : type === 'error' ? '❌' : type === 'info' ? 'ℹ️' : '📝'; console.log(`${colors[color] || colors.reset}${prefix} ${message}${colors.reset}`); } // Banner console.log(colors.cyan + '='.repeat(70)); console.log(' ACTUALIZADOR DE ESTILOS FONTAWESOME PRO PARA LOGSEQ'); console.log('='.repeat(70) + colors.reset + '\n'); /** * Verificar estructura de directorios */ function checkDirectoryStructure() { log('Verificando estructura de directorios...', 'blue'); const requiredDirs = [ CONFIG.assetsDir, CONFIG.fontawesomeDir, CONFIG.webfontsDir, CONFIG.metadataDir ]; let allExist = true; requiredDirs.forEach(dir => { if (fs.existsSync(dir)) { log(` ${path.basename(dir)}: Existe`, 'green'); } else { log(` ${path.basename(dir)}: No existe - Creando...`, 'yellow'); try { fs.mkdirSync(dir, { recursive: true }); log(` ${path.basename(dir)}: Creado`, 'green'); } catch (error) { log(` Error creando ${dir}: ${error.message}`, 'red', 'error'); allExist = false; } } }); return allExist; } /** * Verificar archivos actuales */ function checkCurrentFiles() { log('Analizando archivos actuales...', 'blue'); const files = { webfonts: [], metadata: [], css: [] }; // Verificar webfonts if (fs.existsSync(CONFIG.webfontsDir)) { files.webfonts = fs.readdirSync(CONFIG.webfontsDir) .filter(file => /\.(woff2|woff|ttf|eot)$/i.test(file)); } // Verificar metadata if (fs.existsSync(CONFIG.metadataDir)) { files.metadata = fs.readdirSync(CONFIG.metadataDir) .filter(file => /\.json$/i.test(file)); } // Verificar CSS const cssDir = path.join(CONFIG.fontawesomeDir, 'css'); if (fs.existsSync(cssDir)) { files.css = fs.readdirSync(cssDir) .filter(file => /\.css$/i.test(file)); } // Mostrar resumen log(` Webfonts: ${files.webfonts.length} archivos encontrados`, files.webfonts.length > 0 ? 'green' : 'yellow'); log(` Metadata: ${files.metadata.length} archivos encontrados`, files.metadata.length > 0 ? 'green' : 'yellow'); log(` CSS: ${files.css.length} archivos encontrados`, files.css.length > 0 ? 'green' : 'yellow'); return files; } /** * Mostrar instrucciones de actualización */ function showUpdateInstructions(currentFiles) { console.log('\n' + colors.yellow + '='.repeat(70)); console.log(' INSTRUCCIONES PARA ACTUALIZAR ESTILOS'); console.log('='.repeat(70) + colors.reset + '\n'); log('PASO 1: Descargar FontAwesome 6 Pro actualizado', 'magenta'); console.log(' • Visita: ' + colors.cyan + CONFIG.proDownloadUrl + colors.reset); console.log(' • Inicia sesión con tu cuenta Pro'); console.log(' • Descarga la versión más reciente\n'); log('PASO 2: Extraer archivos necesarios', 'magenta'); console.log('Del ZIP descargado, copia estos archivos:\n'); console.log(colors.bright + ' 📁 css/' + colors.reset); console.log(' ├── all.min.css'); console.log(' └── fontawesome.min.css\n'); console.log(colors.bright + ' 📁 webfonts/' + colors.reset); console.log(' ├── fa-solid-900.woff2'); console.log(' ├── fa-regular-400.woff2'); console.log(' ├── fa-light-300.woff2'); console.log(' ├── fa-thin-100.woff2'); console.log(' ├── fa-duotone-900.woff2'); console.log(' ├── fa-sharp-solid-900.woff2'); console.log(' ├── fa-sharp-regular-400.woff2'); console.log(' ├── fa-sharp-light-300.woff2'); console.log(' ├── fa-sharp-thin-100.woff2'); console.log(' ├── fa-sharp-duotone-900.woff2'); console.log(' └── fa-brands-400.woff2\n'); console.log(colors.bright + ' 📁 metadata/' + colors.reset); console.log(' └── icons.json\n'); log('PASO 3: Reemplazar archivos', 'magenta'); console.log(` • Copia los archivos a: ${colors.cyan}${CONFIG.fontawesomeDir}${colors.reset}`); log('PASO 4: Regenerar base de datos', 'magenta'); console.log(' • Ejecuta: ' + colors.green + 'npm run build' + colors.reset); console.log('\n' + colors.yellow + '='.repeat(70)); } /** * Detectar nuevos estilos disponibles */ function detectNewStyles() { log('Buscando nuevos estilos...', 'blue'); // Leer estilos actuales de la base de datos const dbPath = path.join(CONFIG.assetsDir, 'icons.json'); let currentStyles = []; if (fs.existsSync(dbPath)) { try { const db = JSON.parse(fs.readFileSync(dbPath, 'utf8')); currentStyles = db.meta?.stylesAvailable || []; log(` Estilos actuales en DB: ${currentStyles.length}`, 'green'); } catch (error) { log(` Error leyendo DB: ${error.message}`, 'yellow', 'warning'); } } // Detectar estilos en webfonts let detectedStyles = []; if (fs.existsSync(CONFIG.webfontsDir)) { const fontFiles = fs.readdirSync(CONFIG.webfontsDir); // Mapear archivos a estilos const styleMap = { 'fa-solid': 'solid', 'fa-regular': 'regular', 'fa-light': 'light', 'fa-thin': 'thin', 'fa-duotone': 'duotone', 'fa-sharp-solid': 'sharp-solid', 'fa-sharp-regular': 'sharp-regular', 'fa-sharp-light': 'sharp-light', 'fa-sharp-thin': 'sharp-thin', 'fa-sharp-duotone': 'sharp-duotone', 'fa-brands': 'brands' }; fontFiles.forEach(file => { Object.keys(styleMap).forEach(key => { if (file.includes(key)) { const style = styleMap[key]; if (!detectedStyles.includes(style)) { detectedStyles.push(style); } } }); }); } log(` Estilos detectados en archivos: ${detectedStyles.length}`, 'green'); // Encontrar nuevos estilos const newStyles = detectedStyles.filter(style => !currentStyles.includes(style)); if (newStyles.length > 0) { log(` ¡Nuevos estilos encontrados: ${newStyles.length}!`, 'magenta', 'success'); newStyles.forEach(style => { log(` • ${style}`, 'green'); }); } else { log(' No se encontraron nuevos estilos', 'yellow'); } return { currentStyles, detectedStyles, newStyles }; } /** * Verificar versiones */ function checkVersions() { log('Verificando versiones...', 'blue'); // Verificar metadata version const metadataPath = path.join(CONFIG.metadataDir, 'icons.json'); let metadataVersion = 'Desconocida'; if (fs.existsSync(metadataPath)) { try { const metadata = JSON.parse(fs.readFileSync(metadataPath, 'utf8')); const firstIcon = Object.values(metadata)[0]; metadataVersion = firstIcon?.version || 'Desconocida'; } catch (error) { // Ignorar error } } log(` Versión en metadata: ${metadataVersion}`, 'green'); // Verificar versión del plugin const packagePath = path.join(CONFIG.pluginDir, 'package.json'); let pluginVersion = 'Desconocida'; if (fs.existsSync(packagePath)) { try { const pkg = JSON.parse(fs.readFileSync(packagePath, 'utf8')); pluginVersion = pkg.version || 'Desconocida'; } catch (error) { // Ignorar error } } log(` Versión del plugin: ${pluginVersion}`, 'green'); return { metadataVersion, pluginVersion }; } /** * Realizar respaldo de archivos actuales */ function backupCurrentFiles() { log('Creando respaldo de archivos actuales...', 'blue'); const backupDir = path.join(CONFIG.pluginDir, 'backup', new Date().toISOString().split('T')[0]); try { if (!fs.existsSync(backupDir)) { fs.mkdirSync(backupDir, { recursive: true }); } // Archivos a respaldar const filesToBackup = [ path.join(CONFIG.assetsDir, 'icons.json'), path.join(CONFIG.assetsDir, 'dynamic-styles.css'), path.join(CONFIG.assetsDir, 'custom-styles.css') ]; let backedUpCount = 0; filesToBackup.forEach(file => { if (fs.existsSync(file)) { const fileName = path.basename(file); const backupPath = path.join(backupDir, fileName); fs.copyFileSync(file, backupPath); backedUpCount++; log(` Respaldo creado: ${fileName}`, 'green'); } }); if (backedUpCount > 0) { log(`✅ Respaldo completado (${backedUpCount} archivos)`, 'green', 'success'); log(` Ubicación: ${backupDir}`, 'cyan'); } else { log('⚠️ No se encontraron archivos para respaldar', 'yellow', 'warning'); } return backupDir; } catch (error) { log(`❌ Error creando respaldo: ${error.message}`, 'red', 'error'); return null; } } /** * Regenerar base de datos */ function regenerateDatabase() { log('Regenerando base de datos...', 'blue'); try { // Ejecutar el script de construcción log(' Ejecutando: npm run build', 'cyan'); const result = execSync('npm run build', { cwd: CONFIG.pluginDir, stdio: 'pipe', encoding: 'utf8' }); console.log(result); log('✅ Base de datos regenerada exitosamente', 'green', 'success'); return true; } catch (error) { log(`❌ Error regenerando base de datos: ${error.message}`, 'red', 'error'); if (error.stdout) console.log(error.stdout); if (error.stderr) console.log(error.stderr); return false; } } /** * Función principal */ async function main() { try { // 1. Verificar estructura if (!checkDirectoryStructure()) { log('Error en la estructura de directorios', 'red', 'error'); return; } // 2. Verificar archivos actuales const currentFiles = checkCurrentFiles(); // 3. Verificar versiones const versions = checkVersions(); // 4. Detectar nuevos estilos const styles = detectNewStyles(); // 5. Mostrar resumen console.log('\n' + colors.cyan + '='.repeat(70)); console.log(' RESUMEN DEL ANÁLISIS'); console.log('='.repeat(70) + colors.reset); console.log(`\n${colors.bright}📊 Estadísticas:${colors.reset}`); console.log(` • Webfonts: ${currentFiles.webfonts.length} archivos`); console.log(` • Estilos detectados: ${styles.detectedStyles.length}`); console.log(` • Estilos en DB: ${styles.currentStyles.length}`); console.log(` • Nuevos estilos: ${styles.newStyles.length}`); console.log(` • Versión metadata: ${versions.metadataVersion}`); console.log(` • Versión plugin: ${versions.pluginVersion}`); if (styles.newStyles.length > 0) { console.log(`\n${colors.bright}🎉 ¡Nuevos estilos disponibles!${colors.reset}`); console.log(` Ejecuta 'npm run build' para actualizar la base de datos.`); } // 6. Preguntar al usuario console.log(`\n${colors.bright}¿Qué deseas hacer?${colors.reset}`); console.log(' 1. Mostrar instrucciones de actualización'); console.log(' 2. Crear respaldo y regenerar base de datos'); console.log(' 3. Solo regenerar base de datos'); console.log(' 4. Salir'); // En un entorno real, aquí usarías readline para interactuar // Por ahora, mostramos las instrucciones automáticamente console.log('\n' + colors.yellow + 'Mostrando instrucciones...' + colors.reset); showUpdateInstructions(currentFiles); // 7. Opción para regenerar console.log(`\n${colors.bright}Para regenerar la base de datos con los nuevos estilos:${colors.reset}`); console.log(` Ejecuta: ${colors.green}npm run build${colors.reset}`); console.log('\n' + colors.cyan + '='.repeat(70)); console.log(' ACTUALIZACIÓN COMPLETADA'); console.log('='.repeat(70) + colors.reset); } catch (error) { log(`Error en el proceso de actualización: ${error.message}`, 'red', 'error'); process.exit(1); } } // Ejecutar main();