Primera versión del plugin

This commit is contained in:
2025-12-14 23:23:56 -05:00
commit d215f498b9
37 changed files with 670696 additions and 0 deletions

863
build-icons-json.js Normal file
View File

@@ -0,0 +1,863 @@
const fs = require('fs');
const path = require('path');
// ================= CONFIGURACIÓN =================
const CONFIG = {
// Rutas de entrada (archivos procesados)
PROCESSED_METADATA: path.join(__dirname, 'assets', 'processed', 'metadata.json'),
PROCESSED_STYLES: path.join(__dirname, 'assets', 'processed', 'styles.json'),
PROCESSED_CATEGORIES: path.join(__dirname, 'assets', 'processed', 'categories.json'),
// Rutas de salida (plugin)
OUTPUT_ICONS: path.join(__dirname, 'assets', 'icons.json'),
OUTPUT_DYNAMIC_CSS: path.join(__dirname, 'assets', 'dynamic-styles.css'),
OUTPUT_CUSTOM_CSS: path.join(__dirname, 'assets', 'custom-styles.css'),
// Configuración del plugin
PLUGIN_NAME: 'FontAwesome Pro',
VERSION: '2.0.0'
};
// ================= ESTILOS POSIBLES =================
const ALL_STYLES = [
// Estilos clásicos
{
id: 'solid',
name: 'Solid',
prefix: 'fas',
class: 'fas',
weight: 900,
pro: true,
sharp: false,
family: 'Font Awesome 6 Pro',
file: 'fa-solid-900.woff2'
},
{
id: 'regular',
name: 'Regular',
prefix: 'far',
class: 'far',
weight: 400,
pro: true,
sharp: false,
family: 'Font Awesome 6 Pro',
file: 'fa-regular-400.woff2'
},
{
id: 'light',
name: 'Light',
prefix: 'fal',
class: 'fal',
weight: 300,
pro: true,
sharp: false,
family: 'Font Awesome 6 Pro',
file: 'fa-light-300.woff2'
},
{
id: 'thin',
name: 'Thin',
prefix: 'fat',
class: 'fat',
weight: 100,
pro: true,
sharp: false,
family: 'Font Awesome 6 Pro',
file: 'fa-thin-100.woff2'
},
{
id: 'duotone',
name: 'Duotone',
prefix: 'fad',
class: 'fad',
weight: 900,
pro: true,
sharp: false,
family: 'Font Awesome 6 Duotone',
file: 'fa-duotone-900.woff2'
},
// Estilos Sharp
{
id: 'sharp-solid',
name: 'Sharp Solid',
prefix: 'fass',
class: 'fass',
weight: 900,
pro: true,
sharp: true,
family: 'Font Awesome 6 Sharp',
file: 'fa-sharp-solid-900.woff2'
},
{
id: 'sharp-regular',
name: 'Sharp Regular',
prefix: 'fasr',
class: 'fasr',
weight: 400,
pro: true,
sharp: true,
family: 'Font Awesome 6 Sharp',
file: 'fa-sharp-regular-400.woff2'
},
{
id: 'sharp-light',
name: 'Sharp Light',
prefix: 'fasl',
class: 'fasl',
weight: 300,
pro: true,
sharp: true,
family: 'Font Awesome 6 Sharp',
file: 'fa-sharp-light-300.woff2'
},
{
id: 'sharp-thin',
name: 'Sharp Thin',
prefix: 'fast',
class: 'fast',
weight: 100,
pro: true,
sharp: true,
family: 'Font Awesome 6 Sharp',
file: 'fa-sharp-thin-100.woff2'
},
{
id: 'sharp-duotone',
name: 'Sharp Duotone',
prefix: 'fasd',
class: 'fasd',
weight: 900,
pro: true,
sharp: true,
family: 'Font Awesome 6 Sharp Duotone',
file: 'fa-sharp-duotone-900.woff2'
},
// Brands
{
id: 'brands',
name: 'Brands',
prefix: 'fab',
class: 'fab',
weight: 400,
pro: false,
sharp: false,
family: 'Font Awesome 6 Brands',
file: 'fa-brands-400.woff2'
}
];
// Estilos detectados (se llenará automáticamente)
let DETECTED_STYLES = [];
// ================= FUNCIONES PRINCIPALES =================
/**
* Verificar si los archivos procesados existen
*/
function checkProcessedFiles() {
console.log('🔍 Verificando archivos procesados...\n');
const requiredFiles = [
{ path: CONFIG.PROCESSED_METADATA, name: 'metadata.json' },
{ path: CONFIG.PROCESSED_STYLES, name: 'styles.json' },
{ path: CONFIG.PROCESSED_CATEGORIES, name: 'categories.json' }
];
let allExist = true;
requiredFiles.forEach(file => {
if (fs.existsSync(file.path)) {
const stats = fs.statSync(file.path);
console.log(`${file.name}: ${(stats.size / 1024).toFixed(2)} KB`);
} else {
console.log(`${file.name}: NO ENCONTRADO`);
allExist = false;
}
});
if (!allExist) {
console.log('\n⚠ Archivos procesados no encontrados.');
console.log(' Ejecuta primero: npm run extract');
console.log(' O: npm run build (que ejecuta extract automáticamente)');
}
console.log('');
return allExist;
}
/**
* Detectar estilos disponibles automáticamente
*/
function detectAvailableStyles() {
console.log('🔍 Detectando estilos disponibles...\n');
const webfontsDir = path.join(__dirname, 'assets', 'fontawesome', 'webfonts');
if (!fs.existsSync(webfontsDir)) {
console.error('❌ Carpeta de webfonts no encontrada:', webfontsDir);
console.log(' Asegúrate de copiar los archivos de FontAwesome Pro');
return [];
}
const availableStyles = [];
const fontFiles = fs.readdirSync(webfontsDir);
ALL_STYLES.forEach(style => {
const expectedFile = style.file;
const fontPath = path.join(webfontsDir, expectedFile);
// Verificar archivo principal (.woff2)
if (fs.existsSync(fontPath)) {
availableStyles.push(style);
console.log(`${style.name.padEnd(20)} ${expectedFile}`);
} else {
// Verificar variantes
const variants = ['.ttf', '.eot', '.woff'].map(ext =>
expectedFile.replace('.woff2', ext)
);
const foundVariant = variants.find(variant =>
fs.existsSync(path.join(webfontsDir, variant))
);
if (foundVariant) {
availableStyles.push(style);
console.log(`${style.name.padEnd(20)} ${foundVariant} (variante)`);
} else {
console.log(` ⚠️ ${style.name.padEnd(20)} No encontrado`);
}
}
});
console.log('\n' + '='.repeat(60));
console.log(`📊 RESUMEN: ${availableStyles.length} de ${ALL_STYLES.length} estilos detectados`);
// Estadísticas
const classicCount = availableStyles.filter(s => !s.sharp && s.id !== 'brands').length;
const sharpCount = availableStyles.filter(s => s.sharp).length;
const brandsCount = availableStyles.filter(s => s.id === 'brands').length;
console.log(` • Clásicos: ${classicCount}/5`);
console.log(` • Sharp: ${sharpCount}/5`);
console.log(` • Brands: ${brandsCount}/1`);
console.log('='.repeat(60) + '\n');
return availableStyles;
}
/**
* Cargar metadata procesado
*/
function loadProcessedMetadata() {
try {
console.log('📥 Cargando metadata procesado...');
if (!fs.existsSync(CONFIG.PROCESSED_METADATA)) {
throw new Error(`Archivo no encontrado: ${CONFIG.PROCESSED_METADATA}`);
}
const content = fs.readFileSync(CONFIG.PROCESSED_METADATA, 'utf8');
const data = JSON.parse(content);
if (!data.icons || typeof data.icons !== 'object') {
throw new Error('Estructura de metadata inválida');
}
console.log(`✅ Metadata cargado: ${Object.keys(data.icons).length} íconos`);
// Convertir objeto a array
const iconsArray = Object.values(data.icons);
// Filtrar íconos que tienen estilos disponibles
const filteredIcons = iconsArray.filter(icon => {
if (!icon.styles || !Array.isArray(icon.styles)) {
return false;
}
// Verificar si al menos un estilo está disponible
return icon.styles.some(style =>
DETECTED_STYLES.some(s => s.id === style)
);
});
console.log(`📊 Íconos con estilos disponibles: ${filteredIcons.length}/${iconsArray.length}`);
return filteredIcons;
} catch (error) {
console.error('❌ Error cargando metadata procesado:', error.message);
return null;
}
}
/**
* Cargar información de estilos procesada
*/
function loadProcessedStylesInfo() {
try {
if (!fs.existsSync(CONFIG.PROCESSED_STYLES)) {
console.log('⚠️ Archivo de estilos procesado no encontrado');
return null;
}
const content = fs.readFileSync(CONFIG.PROCESSED_STYLES, 'utf8');
const data = JSON.parse(content);
if (!data.styles || typeof data.styles !== 'object') {
console.log('⚠️ Estructura de estilos inválida');
return null;
}
console.log('✅ Información de estilos cargada');
return data.styles;
} catch (error) {
console.log('⚠️ Error cargando información de estilos:', error.message);
return null;
}
}
/**
* Cargar categorías procesadas
*/
function loadProcessedCategories() {
try {
if (!fs.existsSync(CONFIG.PROCESSED_CATEGORIES)) {
console.log('⚠️ Archivo de categorías procesado no encontrado');
return null;
}
const content = fs.readFileSync(CONFIG.PROCESSED_CATEGORIES, 'utf8');
const data = JSON.parse(content);
if (!data.categories || !Array.isArray(data.categories)) {
console.log('⚠️ Estructura de categorías inválida');
return null;
}
console.log(`✅ Categorías cargadas: ${data.categories.length}`);
return data.categories;
} catch (error) {
console.log('⚠️ Error cargando categorías:', error.message);
return null;
}
}
/**
* Generar CSS dinámico basado en estilos detectados
*/
function generateDynamicCSS(styles) {
console.log('🎨 Generando CSS dinámico...');
let cssContent = `/* ============================================\n`;
cssContent += ` FontAwesome Dynamic Styles\n`;
cssContent += ` Generado: ${new Date().toISOString()}\n`;
cssContent += ` Estilos detectados: ${styles.length}\n`;
cssContent += `============================================ */\n\n`;
// Agrupar por familia de fuentes
const families = {};
styles.forEach(style => {
if (!families[style.family]) {
families[style.family] = [];
}
families[style.family].push(style);
});
// Generar @font-face para cada familia
Object.entries(families).forEach(([familyName, familyStyles]) => {
cssContent += `/* ${familyName} */\n`;
familyStyles.forEach(style => {
const fontWeight = style.weight;
const fontFile = style.file;
const fontPath = `../webfonts/${fontFile}`;
cssContent += `@font-face {\n`;
cssContent += ` font-family: '${familyName}';\n`;
cssContent += ` font-style: normal;\n`;
cssContent += ` font-weight: ${fontWeight};\n`;
cssContent += ` font-display: block;\n`;
cssContent += ` src: url("${fontPath}") format("woff2");\n`;
cssContent += `}\n\n`;
});
});
// Reglas de clase para cada estilo
cssContent += `/* Reglas de clase */\n`;
styles.forEach(style => {
cssContent += `.${style.prefix} {\n`;
cssContent += ` font-family: '${style.family}';\n`;
cssContent += ` font-weight: ${style.weight};\n`;
cssContent += `}\n`;
});
// Variables CSS para Duotone
const hasDuotone = styles.some(s => s.id.includes('duotone'));
if (hasDuotone) {
cssContent += `\n/* Variables para Duotone */\n`;
cssContent += `.fad, .fasd {\n`;
cssContent += ` --fa-primary-color: currentColor;\n`;
cssContent += ` --fa-secondary-color: rgba(0, 0, 0, 0.4);\n`;
cssContent += ` --fa-primary-opacity: 1;\n`;
cssContent += ` --fa-secondary-opacity: 0.4;\n`;
cssContent += `}\n`;
}
// Guardar archivo
fs.writeFileSync(CONFIG.OUTPUT_DYNAMIC_CSS, cssContent, 'utf8');
console.log(`✅ CSS dinámico generado: ${CONFIG.OUTPUT_DYNAMIC_CSS}`);
}
/**
* Generar CSS personalizado para características avanzadas
*/
function generateCustomCSS() {
console.log('🎨 Generando CSS personalizado...');
const cssContent = `/* ============================================\n`;
cssContent += ` FontAwesome Custom Styles\n`;
cssContent += ` Características avanzadas: Color, Tamaño, Animaciones\n`;
cssContent += ` Generado: ${new Date().toISOString()}\n`;
cssContent += `============================================ */\n\n`;
// Tamaños personalizados
cssContent += `/* Tamaños */\n`;
const sizes = [
{ class: 'fa-xs', size: '0.75em' },
{ class: 'fa-sm', size: '0.875em' },
{ class: 'fa-lg', size: '1.33em' },
{ class: 'fa-xl', size: '1.75em' },
{ class: 'fa-2x', size: '2em' },
{ class: 'fa-3x', size: '3em' },
{ class: 'fa-4x', size: '4em' },
{ class: 'fa-5x', size: '5em' },
{ class: 'fa-6x', size: '6em' },
{ class: 'fa-7x', size: '7em' },
{ class: 'fa-8x', size: '8em' },
{ class: 'fa-9x', size: '9em' },
{ class: 'fa-10x', size: '10em' }
];
sizes.forEach(({ class: sizeClass, size }) => {
cssContent += `.${sizeClass} { font-size: ${size} !important; }\n`;
});
// Animaciones
cssContent += `\n/* Animaciones */\n`;
cssContent += `.fa-spin { animation: fa-spin 2s linear infinite; }\n`;
cssContent += `.fa-pulse { animation: fa-spin 1s steps(8) infinite; }\n`;
cssContent += `.fa-beat { animation: fa-beat 1s ease infinite; }\n`;
cssContent += `.fa-fade { animation: fa-fade 2s ease infinite; }\n`;
cssContent += `.fa-bounce { animation: fa-bounce 1s ease infinite; }\n`;
cssContent += `.fa-flip { animation: fa-flip 2s ease infinite; }\n`;
cssContent += `.fa-shake { animation: fa-shake 1s ease infinite; }\n`;
// Keyframes para animaciones
cssContent += `\n/* Keyframes */\n`;
cssContent += `@keyframes fa-beat {\n`;
cssContent += ` 0%, 90% { transform: scale(1); }\n`;
cssContent += ` 45% { transform: scale(1.1); }\n`;
cssContent += `}\n\n`;
cssContent += `@keyframes fa-fade {\n`;
cssContent += ` 0%, 100% { opacity: 1; }\n`;
cssContent += ` 50% { opacity: 0.5; }\n`;
cssContent += `}\n\n`;
cssContent += `@keyframes fa-bounce {\n`;
cssContent += ` 0%, 100% { transform: translateY(0); }\n`;
cssContent += ` 50% { transform: translateY(-5px); }\n`;
cssContent += `}\n\n`;
cssContent += `@keyframes fa-flip {\n`;
cssContent += ` 0% { transform: perspective(400px) rotateY(0); }\n`;
cssContent += ` 100% { transform: perspective(400px) rotateY(360deg); }\n`;
cssContent += `}\n\n`;
cssContent += `@keyframes fa-shake {\n`;
cssContent += ` 0%, 100% { transform: translateX(0); }\n`;
cssContent += ` 25% { transform: translateX(-3px); }\n`;
cssContent += ` 75% { transform: translateX(3px); }\n`;
cssContent += `}\n`;
// Colores temáticos
cssContent += `\n/* Colores temáticos */\n`;
const themeColors = [
{ class: 'fa-primary', color: 'var(--ls-link-text-color, #0451a5)' },
{ class: 'fa-success', color: '#10b981' },
{ class: 'fa-danger', color: '#ef4444' },
{ class: 'fa-warning', color: '#f59e0b' },
{ class: 'fa-info', color: '#3b82f6' },
{ class: 'fa-purple', color: '#8b5cf6' },
{ class: 'fa-pink', color: '#ec4899' },
{ class: 'fa-gray', color: '#6b7280' },
{ class: 'fa-black', color: '#000000' },
{ class: 'fa-white', color: '#ffffff' }
];
themeColors.forEach(({ class: colorClass, color }) => {
cssContent += `.${colorClass} { color: ${color} !important; }\n`;
});
// Efectos especiales
cssContent += `\n/* Efectos especiales */\n`;
cssContent += `.fa-shadow { filter: drop-shadow(0 2px 4px rgba(0,0,0,0.2)); }\n`;
cssContent += `.fa-shadow-lg { filter: drop-shadow(0 4px 8px rgba(0,0,0,0.3)); }\n`;
cssContent += `.fa-glow { filter: drop-shadow(0 0 8px currentColor); }\n`;
// Gradientes
cssContent += `.fa-gradient {\n`;
cssContent += ` background: linear-gradient(45deg, #8b5cf6, #3b82f6);\n`;
cssContent += ` -webkit-background-clip: text;\n`;
cssContent += ` -webkit-text-fill-color: transparent;\n`;
cssContent += ` background-clip: text;\n`;
cssContent += `}\n`;
// Guardar archivo
fs.writeFileSync(CONFIG.OUTPUT_CUSTOM_CSS, cssContent, 'utf8');
console.log(`✅ CSS personalizado generado: ${CONFIG.OUTPUT_CUSTOM_CSS}`);
}
/**
* Crear base de datos final
*/
function createDatabase(icons, categories, stylesInfo) {
console.log('📊 Creando base de datos final...');
// Preparar estilos para la base de datos
const dbStyles = DETECTED_STYLES.map(style => {
const styleInfoData = stylesInfo && stylesInfo[style.id] ? stylesInfo[style.id] : {};
return {
id: style.id,
name: style.name,
prefix: style.prefix,
class: style.class,
weight: style.weight,
pro: style.pro,
sharp: style.sharp,
available: true,
count: styleInfoData.count || 0,
percentage: styleInfoData.percentage || '0.0'
};
});
// Actualizar conteos en categorías
const updatedCategories = categories ? categories.map(category => {
if (category.id === 'all') {
return { ...category, count: icons.length };
} else if (category.type === 'fontawesome') {
// Contar íconos en esta categoría
const count = icons.filter(icon =>
icon.categories && icon.categories.includes(category.id)
).length;
return { ...category, count };
}
return category;
}) : getDefaultCategories(icons.length);
// Crear estructura final
const database = {
meta: {
generated: new Date().toISOString(),
fontawesomeVersion: '6.0.0',
pluginVersion: CONFIG.VERSION,
totalIcons: icons.length,
totalCategories: updatedCategories.length,
detectedStyles: DETECTED_STYLES.length,
stylesAvailable: DETECTED_STYLES.map(s => s.id),
proIcons: icons.filter(icon =>
icon.styles && icon.styles.some(style =>
['solid', 'regular', 'light', 'thin', 'duotone',
'sharp-solid', 'sharp-regular', 'sharp-light', 'sharp-thin', 'sharp-duotone']
.includes(style)
)
).length,
freeIcons: icons.filter(icon =>
icon.styles && icon.styles.includes('brands')
).length
},
icons: icons.map(icon => ({
id: icon.id,
name: icon.name,
label: icon.label,
categories: icon.categories || ['uncategorized'],
styles: icon.styles || [],
searchTerms: icon.searchTerms || [],
unicode: icon.unicode || '',
version: icon.version || '6.0.0',
free: (icon.styles && icon.styles.includes('brands')) || false,
pro: icon.styles && icon.styles.some(style =>
['solid', 'regular', 'light', 'thin', 'duotone',
'sharp-solid', 'sharp-regular', 'sharp-light', 'sharp-thin', 'sharp-duotone']
.includes(style)
)
})),
categories: updatedCategories,
styles: dbStyles,
search: {
languages: ['en', 'es'],
synonyms: true
},
features: {
colorCustomization: true,
sizeCustomization: true,
animations: true,
transformations: true,
presets: true
}
};
return database;
}
/**
* Obtener categorías por defecto
*/
function getDefaultCategories(totalIcons) {
return [
{
id: 'all',
name: 'Todos los Íconos',
icon: 'fas fa-th',
count: totalIcons,
type: 'special'
},
{
id: 'favorites',
name: 'Favoritos',
icon: 'fas fa-star',
count: 0,
type: 'special'
},
{
id: 'recent',
name: 'Recientes',
icon: 'fas fa-history',
count: 0,
type: 'special'
}
];
}
/**
* Guardar base de datos
*/
function saveDatabase(database) {
try {
// Asegurar directorio
const assetsDir = path.dirname(CONFIG.OUTPUT_ICONS);
if (!fs.existsSync(assetsDir)) {
fs.mkdirSync(assetsDir, { recursive: true });
}
// Guardar JSON
fs.writeFileSync(
CONFIG.OUTPUT_ICONS,
JSON.stringify(database, null, 2),
'utf8'
);
console.log(`✅ Base de datos guardada: ${CONFIG.OUTPUT_ICONS}`);
console.log(`📊 Tamaño: ${(fs.statSync(CONFIG.OUTPUT_ICONS).size / 1024 / 1024).toFixed(2)} MB`);
} catch (error) {
console.error('❌ Error guardando base de datos:', error.message);
throw error;
}
}
/**
* Generar base de datos de ejemplo
*/
function generateSampleDatabase() {
console.log('📝 Generando base de datos de ejemplo...');
const sampleIcons = [
{
id: "home",
name: "home",
label: "Home",
categories: ["household", "buildings"],
styles: ["solid", "regular", "light"],
searchTerms: ["casa", "hogar", "inicio"],
unicode: "f015",
version: "6.0.0",
free: true,
pro: true
},
{
id: "user",
name: "user",
label: "User",
categories: ["users-people"],
styles: ["solid", "regular"],
searchTerms: ["persona", "perfil", "cuenta"],
unicode: "f007",
version: "6.0.0",
free: true,
pro: true
}
];
const sampleStyles = DETECTED_STYLES.length > 0 ?
DETECTED_STYLES.slice(0, 3) :
ALL_STYLES.slice(0, 3);
const database = {
meta: {
generated: new Date().toISOString(),
fontawesomeVersion: "6.0.0",
pluginVersion: CONFIG.VERSION,
totalIcons: sampleIcons.length,
totalCategories: 3,
detectedStyles: sampleStyles.length,
proIcons: sampleIcons.length,
freeIcons: 0,
note: "BASE DE DATOS DE EJEMPLO - Ejecuta 'npm run build' para generar la versión completa"
},
icons: sampleIcons,
categories: [
{ id: "all", name: "Todos los Íconos", icon: "fas fa-th", count: sampleIcons.length, type: "special" },
{ id: "household", name: "Hogar", icon: "fas fa-home", count: 1, type: "fontawesome" },
{ id: "users-people", name: "Personas", icon: "fas fa-user", count: 1, type: "fontawesome" }
],
styles: sampleStyles.map(s => ({
id: s.id,
name: s.name,
prefix: s.prefix,
class: s.class,
available: true
}))
};
saveDatabase(database);
return database;
}
/**
* Función principal
*/
async function generateIconDatabase() {
console.log('🎨 ' + '='.repeat(60));
console.log(' GENERADOR DE BASE DE DATOS FONTAWESOME PRO');
console.log(' Versión: ' + CONFIG.VERSION);
console.log('='.repeat(60) + '\n');
try {
// 1. Verificar archivos procesados
const hasProcessedFiles = checkProcessedFiles();
if (!hasProcessedFiles) {
console.log('⚠️ Ejecutando en modo fallback (sin archivos procesados)...');
console.log(' Para mejor rendimiento, ejecuta: npm run extract');
}
// 2. Detectar estilos disponibles
DETECTED_STYLES = detectAvailableStyles();
if (DETECTED_STYLES.length === 0) {
console.warn('⚠️ No se detectaron estilos. Generando base de datos de ejemplo...');
return generateSampleDatabase();
}
// 3. Generar CSS
generateDynamicCSS(DETECTED_STYLES);
generateCustomCSS();
// 4. Cargar datos procesados
let icons, stylesInfo, categories;
if (hasProcessedFiles) {
icons = loadProcessedMetadata();
stylesInfo = loadProcessedStylesInfo();
categories = loadProcessedCategories();
if (!icons || icons.length === 0) {
throw new Error('No se pudieron cargar íconos del metadata procesado');
}
} else {
// Modo fallback: cargar metadata original
console.log('📥 Cargando metadata original (modo fallback)...');
const metadataPath = path.join(__dirname, 'assets', 'fontawesome', 'metadata', 'icons.json');
if (!fs.existsSync(metadataPath)) {
throw new Error('No se encontró metadata original. ¿Copiaste los archivos de FontAwesome?');
}
const content = fs.readFileSync(metadataPath, 'utf8');
const rawMetadata = JSON.parse(content);
// Procesar íconos básicamente
icons = Object.values(rawMetadata).map(icon => ({
id: icon.name || Object.keys(rawMetadata).find(key => rawMetadata[key] === icon),
name: icon.name || '',
label: icon.label || '',
categories: icon.categories || ['uncategorized'],
styles: icon.styles || [],
searchTerms: [],
unicode: icon.unicode || '',
version: icon.version || '6.0.0'
}));
categories = getDefaultCategories(icons.length);
}
// 5. Crear base de datos
console.log('\n📊 Creando estructura de datos...');
const database = createDatabase(icons, categories, stylesInfo);
// 6. Guardar
saveDatabase(database);
console.log('\n' + '='.repeat(60));
console.log('✅ ¡GENERACIÓN COMPLETADA EXITOSAMENTE!');
console.log('='.repeat(60));
console.log(`📊 Total íconos: ${database.icons.length}`);
console.log(`📁 Categorías: ${database.categories.length}`);
console.log(`🎨 Estilos: ${database.meta.detectedStyles}`);
console.log(`📍 Archivos generados:`);
console.log(`${CONFIG.OUTPUT_ICONS}`);
console.log(`${CONFIG.OUTPUT_DYNAMIC_CSS}`);
console.log(`${CONFIG.OUTPUT_CUSTOM_CSS}`);
console.log('='.repeat(60));
// Mostrar resumen de estilos
console.log('\n🎨 ESTILOS DISPONIBLES:');
database.styles.forEach(style => {
if (style.available) {
console.log(`${style.name.padEnd(15)}: ${style.count || 0} íconos`);
}
});
return database;
} catch (error) {
console.error('\n❌ ERROR CRÍTICO:', error.message);
console.log('\n🔄 Generando base de datos de ejemplo...');
return generateSampleDatabase();
}
}
// ================= EJECUCIÓN =================
const args = process.argv.slice(2);
const isSampleMode = args.includes('--sample');
if (require.main === module) {
if (isSampleMode) {
generateSampleDatabase();
} else {
generateIconDatabase();
}
}
// Exportar
module.exports = {
generateIconDatabase,
generateSampleDatabase,
CONFIG,
ALL_STYLES
};