Primera versión del plugin
This commit is contained in:
886
scripts/extract-metadata.js
Normal file
886
scripts/extract-metadata.js
Normal file
@@ -0,0 +1,886 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
// Configuración
|
||||
const CONFIG = {
|
||||
// Rutas de entrada (FontAwesome Pro)
|
||||
FA_METADATA: path.join(__dirname, '..', 'assets', 'fontawesome', 'metadata', 'icons.json'),
|
||||
FA_CATEGORIES: path.join(__dirname, '..', 'assets', 'fontawesome', 'metadata', 'categories.yml'),
|
||||
|
||||
// Rutas de salida
|
||||
OUTPUT_DIR: path.join(__dirname, '..', 'assets', 'processed'),
|
||||
OUTPUT_METADATA: path.join(__dirname, '..', 'assets', 'processed', 'metadata.json'),
|
||||
OUTPUT_STYLES: path.join(__dirname, '..', 'assets', 'processed', 'styles.json'),
|
||||
OUTPUT_CATEGORIES: path.join(__dirname, '..', 'assets', 'processed', 'categories.json'),
|
||||
|
||||
// Configuración de procesamiento
|
||||
MIN_ICONS_TO_PROCESS: 100,
|
||||
VERSION: '2.0.0'
|
||||
};
|
||||
|
||||
// Colores para consola
|
||||
const colors = {
|
||||
reset: '\x1b[0m',
|
||||
green: '\x1b[32m',
|
||||
yellow: '\x1b[33m',
|
||||
blue: '\x1b[34m',
|
||||
red: '\x1b[31m',
|
||||
magenta: '\x1b[35m',
|
||||
cyan: '\x1b[36m'
|
||||
};
|
||||
|
||||
// Banner
|
||||
console.log(colors.cyan + '='.repeat(70));
|
||||
console.log(' EXTRACTOR DE METADATA FONTAWESOME PRO');
|
||||
console.log(' Versión: ' + CONFIG.VERSION);
|
||||
console.log('='.repeat(70) + colors.reset + '\n');
|
||||
|
||||
/**
|
||||
* Crear directorios necesarios
|
||||
*/
|
||||
function createDirectories() {
|
||||
console.log(colors.blue + '📁 Creando directorios...' + colors.reset);
|
||||
|
||||
const dirs = [
|
||||
CONFIG.OUTPUT_DIR,
|
||||
path.join(CONFIG.OUTPUT_DIR, 'backup'),
|
||||
path.join(CONFIG.OUTPUT_DIR, 'logs')
|
||||
];
|
||||
|
||||
dirs.forEach(dir => {
|
||||
if (!fs.existsSync(dir)) {
|
||||
fs.mkdirSync(dir, { recursive: true });
|
||||
console.log(` ✅ Creado: ${path.relative(process.cwd(), dir)}`);
|
||||
} else {
|
||||
console.log(` 📁 Existe: ${path.relative(process.cwd(), dir)}`);
|
||||
}
|
||||
});
|
||||
|
||||
console.log('');
|
||||
}
|
||||
|
||||
/**
|
||||
* Verificar archivos de entrada
|
||||
*/
|
||||
function checkInputFiles() {
|
||||
console.log(colors.blue + '🔍 Verificando archivos de entrada...' + colors.reset);
|
||||
|
||||
const files = [
|
||||
{ path: CONFIG.FA_METADATA, name: 'icons.json', required: true },
|
||||
{ path: CONFIG.FA_CATEGORIES, name: 'categories.yml', required: false }
|
||||
];
|
||||
|
||||
let allFound = true;
|
||||
|
||||
files.forEach(file => {
|
||||
if (fs.existsSync(file.path)) {
|
||||
const stats = fs.statSync(file.path);
|
||||
console.log(` ✅ ${file.name}: ${(stats.size / 1024).toFixed(2)} KB`);
|
||||
|
||||
if (file.name === 'icons.json') {
|
||||
try {
|
||||
const content = fs.readFileSync(file.path, 'utf8');
|
||||
const data = JSON.parse(content);
|
||||
console.log(` Íconos en metadata: ${Object.keys(data).length}`);
|
||||
} catch (error) {
|
||||
console.log(` ❌ ${file.name}: Error de formato - ${error.message}`);
|
||||
allFound = false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (file.required) {
|
||||
console.log(` ❌ ${file.name}: NO ENCONTRADO (requerido)`);
|
||||
allFound = false;
|
||||
} else {
|
||||
console.log(` ⚠️ ${file.name}: No encontrado (opcional)`);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
console.log('');
|
||||
return allFound;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hacer backup de archivos existentes
|
||||
*/
|
||||
function backupExistingFiles() {
|
||||
console.log(colors.blue + '💾 Creando respaldo de archivos existentes...' + colors.reset);
|
||||
|
||||
const filesToBackup = [
|
||||
CONFIG.OUTPUT_METADATA,
|
||||
CONFIG.OUTPUT_STYLES,
|
||||
CONFIG.OUTPUT_CATEGORIES
|
||||
];
|
||||
|
||||
const backupDir = path.join(CONFIG.OUTPUT_DIR, 'backup', new Date().toISOString().replace(/[:.]/g, '-'));
|
||||
|
||||
if (!fs.existsSync(backupDir)) {
|
||||
fs.mkdirSync(backupDir, { recursive: true });
|
||||
}
|
||||
|
||||
let backedUpCount = 0;
|
||||
|
||||
filesToBackup.forEach(file => {
|
||||
if (fs.existsSync(file)) {
|
||||
const fileName = path.basename(file);
|
||||
const backupPath = path.join(backupDir, fileName);
|
||||
|
||||
try {
|
||||
fs.copyFileSync(file, backupPath);
|
||||
console.log(` ✅ Respaldo: ${fileName}`);
|
||||
backedUpCount++;
|
||||
} catch (error) {
|
||||
console.log(` ❌ Error respaldando ${fileName}: ${error.message}`);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (backedUpCount > 0) {
|
||||
console.log(` 📊 Total respaldados: ${backedUpCount} archivos`);
|
||||
console.log(` 📍 Ubicación: ${path.relative(process.cwd(), backupDir)}`);
|
||||
} else {
|
||||
console.log(' ⚠️ No hay archivos existentes para respaldar');
|
||||
}
|
||||
|
||||
console.log('');
|
||||
return backupDir;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extraer y procesar metadata de íconos
|
||||
*/
|
||||
function extractIconMetadata() {
|
||||
console.log(colors.blue + '📊 Extrayendo metadata de íconos...' + colors.reset);
|
||||
|
||||
try {
|
||||
// Leer archivo original
|
||||
const content = fs.readFileSync(CONFIG.FA_METADATA, 'utf8');
|
||||
const rawMetadata = JSON.parse(content);
|
||||
|
||||
const totalIcons = Object.keys(rawMetadata).length;
|
||||
console.log(` 📈 Total íconos encontrados: ${totalIcons}`);
|
||||
|
||||
if (totalIcons < CONFIG.MIN_ICONS_TO_PROCESS) {
|
||||
throw new Error(`Muy pocos íconos (${totalIcons}). ¿Metadata corrupto?`);
|
||||
}
|
||||
|
||||
// Procesar cada ícono
|
||||
const processedIcons = {};
|
||||
let processedCount = 0;
|
||||
let stylesFound = new Set();
|
||||
let categoriesFound = new Set();
|
||||
|
||||
Object.entries(rawMetadata).forEach(([iconName, iconData]) => {
|
||||
processedCount++;
|
||||
|
||||
// Mostrar progreso cada 1000 íconos
|
||||
if (processedCount % 1000 === 0) {
|
||||
console.log(` ⏳ Procesados: ${processedCount}/${totalIcons} íconos...`);
|
||||
}
|
||||
|
||||
// Extraer información básica
|
||||
const processedIcon = {
|
||||
id: iconName,
|
||||
name: iconName,
|
||||
label: iconData.label || formatIconName(iconName),
|
||||
unicode: iconData.unicode || '',
|
||||
version: iconData.version || '6.0.0',
|
||||
search: iconData.search || {}
|
||||
};
|
||||
|
||||
// Estilos disponibles
|
||||
if (iconData.styles && Array.isArray(iconData.styles)) {
|
||||
processedIcon.styles = iconData.styles.map(style => style.toLowerCase());
|
||||
iconData.styles.forEach(style => stylesFound.add(style.toLowerCase()));
|
||||
} else {
|
||||
processedIcon.styles = [];
|
||||
}
|
||||
|
||||
// Categorías
|
||||
if (iconData.categories && Array.isArray(iconData.categories)) {
|
||||
processedIcon.categories = iconData.categories;
|
||||
iconData.categories.forEach(cat => categoriesFound.add(cat));
|
||||
} else {
|
||||
processedIcon.categories = ['uncategorized'];
|
||||
categoriesFound.add('uncategorized');
|
||||
}
|
||||
|
||||
// Información adicional
|
||||
if (iconData.svg) {
|
||||
processedIcon.svg = {
|
||||
width: iconData.svg.width,
|
||||
height: iconData.svg.height,
|
||||
path: iconData.svg.path
|
||||
};
|
||||
}
|
||||
|
||||
// Términos de búsqueda mejorados
|
||||
const searchTerms = new Set();
|
||||
|
||||
// Términos originales
|
||||
if (iconData.search && iconData.search.terms) {
|
||||
iconData.search.terms.forEach(term => {
|
||||
if (term && typeof term === 'string') {
|
||||
searchTerms.add(term.toLowerCase());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Agregar nombre y label
|
||||
searchTerms.add(iconName.toLowerCase());
|
||||
if (iconData.label) {
|
||||
searchTerms.add(iconData.label.toLowerCase());
|
||||
// Variantes sin espacios
|
||||
searchTerms.add(iconData.label.toLowerCase().replace(/\s+/g, '-'));
|
||||
}
|
||||
|
||||
// Agregar sinónimos comunes
|
||||
addCommonSynonyms(iconName, searchTerms);
|
||||
|
||||
processedIcon.searchTerms = Array.from(searchTerms);
|
||||
processedIcon.searchCount = searchTerms.size;
|
||||
|
||||
// Agregar a resultados
|
||||
processedIcons[iconName] = processedIcon;
|
||||
});
|
||||
|
||||
console.log(`\n ✅ Procesados: ${processedCount} íconos`);
|
||||
console.log(` 🎨 Estilos encontrados: ${stylesFound.size}`);
|
||||
console.log(` 📁 Categorías encontradas: ${categoriesFound.size}`);
|
||||
|
||||
// Guardar metadata procesado
|
||||
const metadataOutput = {
|
||||
meta: {
|
||||
generated: new Date().toISOString(),
|
||||
source: 'FontAwesome Pro',
|
||||
version: CONFIG.VERSION,
|
||||
totalIcons: processedCount,
|
||||
totalStyles: stylesFound.size,
|
||||
totalCategories: categoriesFound.size
|
||||
},
|
||||
icons: processedIcons,
|
||||
statistics: {
|
||||
styles: Array.from(stylesFound).sort(),
|
||||
categories: Array.from(categoriesFound).sort(),
|
||||
iconsPerStyle: countIconsPerStyle(processedIcons),
|
||||
iconsPerCategory: countIconsPerCategory(processedIcons)
|
||||
}
|
||||
};
|
||||
|
||||
fs.writeFileSync(CONFIG.OUTPUT_METADATA, JSON.stringify(metadataOutput, null, 2), 'utf8');
|
||||
console.log(`\n 💾 Metadata guardado: ${CONFIG.OUTPUT_METADATA}`);
|
||||
console.log(` 📊 Tamaño: ${(fs.statSync(CONFIG.OUTPUT_METADATA).size / 1024 / 1024).toFixed(2)} MB`);
|
||||
|
||||
return metadataOutput;
|
||||
|
||||
} catch (error) {
|
||||
console.error(colors.red + ` ❌ Error procesando metadata: ${error.message}` + colors.reset);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Formatear nombre de ícono
|
||||
*/
|
||||
function formatIconName(iconName) {
|
||||
return iconName
|
||||
.split('-')
|
||||
.map(word => word.charAt(0).toUpperCase() + word.slice(1))
|
||||
.join(' ');
|
||||
}
|
||||
|
||||
/**
|
||||
* Agregar sinónimos comunes
|
||||
*/
|
||||
function addCommonSynonyms(iconName, searchTerms) {
|
||||
const synonyms = {
|
||||
'home': ['house', 'casa', 'hogar', 'dwelling', 'residence'],
|
||||
'user': ['person', 'profile', 'persona', 'perfil', 'account', 'human'],
|
||||
'heart': ['love', 'like', 'favorite', 'amor', 'favorito', 'affection'],
|
||||
'star': ['favorite', 'rating', 'estrella', 'calificación', 'rate', 'review'],
|
||||
'settings': ['cog', 'gear', 'preferences', 'configuración', 'ajustes', 'options'],
|
||||
'bell': ['notification', 'alert', 'notificación', 'alerta', 'ring', 'chime'],
|
||||
'envelope': ['email', 'mail', 'correo', 'message', 'letter'],
|
||||
'calendar': ['date', 'schedule', 'fecha', 'calendario', 'agenda', 'planner'],
|
||||
'clock': ['time', 'hour', 'tiempo', 'hora', 'watch', 'timer'],
|
||||
'search': ['find', 'lookup', 'buscar', 'encontrar', 'seek', 'locate'],
|
||||
'plus': ['add', 'new', 'create', 'agregar', 'añadir', 'insert'],
|
||||
'minus': ['remove', 'delete', 'subtract', 'quitar', 'eliminar', 'restar'],
|
||||
'check': ['verify', 'confirm', 'mark', 'verificar', 'confirmar', 'tick'],
|
||||
'times': ['close', 'exit', 'cancel', 'cerrar', 'salir', 'cancelar'],
|
||||
'trash': ['delete', 'remove', 'garbage', 'eliminar', 'basura', 'waste'],
|
||||
'edit': ['modify', 'change', 'update', 'modificar', 'cambiar', 'actualizar'],
|
||||
'download': ['save', 'get', 'fetch', 'descargar', 'guardar', 'obtener'],
|
||||
'upload': ['send', 'share', 'post', 'subir', 'enviar', 'compartir'],
|
||||
'print': ['printer', 'hardcopy', 'paper', 'imprimir', 'copiar', 'document']
|
||||
};
|
||||
|
||||
Object.entries(synonyms).forEach(([key, words]) => {
|
||||
if (iconName.includes(key)) {
|
||||
words.forEach(word => searchTerms.add(word));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Contar íconos por estilo
|
||||
*/
|
||||
function countIconsPerStyle(icons) {
|
||||
const counts = {};
|
||||
|
||||
Object.values(icons).forEach(icon => {
|
||||
if (icon.styles) {
|
||||
icon.styles.forEach(style => {
|
||||
counts[style] = (counts[style] || 0) + 1;
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return counts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Contar íconos por categoría
|
||||
*/
|
||||
function countIconsPerCategory(icons) {
|
||||
const counts = {};
|
||||
|
||||
Object.values(icons).forEach(icon => {
|
||||
if (icon.categories) {
|
||||
icon.categories.forEach(category => {
|
||||
counts[category] = (counts[category] || 0) + 1;
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return counts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extraer información de estilos
|
||||
*/
|
||||
function extractStyleInfo(metadata) {
|
||||
console.log(colors.blue + '\n🎨 Extrayendo información de estilos...' + colors.reset);
|
||||
|
||||
// Definición de todos los estilos posibles
|
||||
const allStyles = {
|
||||
'solid': {
|
||||
id: 'solid',
|
||||
name: 'Solid',
|
||||
prefix: 'fas',
|
||||
class: 'fas',
|
||||
weight: 900,
|
||||
pro: true,
|
||||
sharp: false,
|
||||
family: 'Font Awesome 6 Pro',
|
||||
file: 'fa-solid-900.woff2'
|
||||
},
|
||||
'regular': {
|
||||
id: 'regular',
|
||||
name: 'Regular',
|
||||
prefix: 'far',
|
||||
class: 'far',
|
||||
weight: 400,
|
||||
pro: true,
|
||||
sharp: false,
|
||||
family: 'Font Awesome 6 Pro',
|
||||
file: 'fa-regular-400.woff2'
|
||||
},
|
||||
'light': {
|
||||
id: 'light',
|
||||
name: 'Light',
|
||||
prefix: 'fal',
|
||||
class: 'fal',
|
||||
weight: 300,
|
||||
pro: true,
|
||||
sharp: false,
|
||||
family: 'Font Awesome 6 Pro',
|
||||
file: 'fa-light-300.woff2'
|
||||
},
|
||||
'thin': {
|
||||
id: 'thin',
|
||||
name: 'Thin',
|
||||
prefix: 'fat',
|
||||
class: 'fat',
|
||||
weight: 100,
|
||||
pro: true,
|
||||
sharp: false,
|
||||
family: 'Font Awesome 6 Pro',
|
||||
file: 'fa-thin-100.woff2'
|
||||
},
|
||||
'duotone': {
|
||||
id: 'duotone',
|
||||
name: 'Duotone',
|
||||
prefix: 'fad',
|
||||
class: 'fad',
|
||||
weight: 900,
|
||||
pro: true,
|
||||
sharp: false,
|
||||
family: 'Font Awesome 6 Duotone',
|
||||
file: 'fa-duotone-900.woff2'
|
||||
},
|
||||
'sharp-solid': {
|
||||
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'
|
||||
},
|
||||
'sharp-regular': {
|
||||
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'
|
||||
},
|
||||
'sharp-light': {
|
||||
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'
|
||||
},
|
||||
'sharp-thin': {
|
||||
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'
|
||||
},
|
||||
'sharp-duotone': {
|
||||
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'
|
||||
}
|
||||
};
|
||||
|
||||
// Contar íconos por estilo (desde metadata)
|
||||
const styleCounts = metadata.statistics.iconsPerStyle || {};
|
||||
|
||||
// Enriquecer información de estilos
|
||||
const stylesInfo = {};
|
||||
|
||||
Object.keys(allStyles).forEach(styleId => {
|
||||
const style = allStyles[styleId];
|
||||
const count = styleCounts[styleId] || 0;
|
||||
|
||||
stylesInfo[styleId] = {
|
||||
...style,
|
||||
count: count,
|
||||
availableInMetadata: count > 0,
|
||||
percentage: metadata.meta.totalIcons > 0
|
||||
? ((count / metadata.meta.totalIcons) * 100).toFixed(1)
|
||||
: '0.0'
|
||||
};
|
||||
});
|
||||
|
||||
// Guardar información de estilos
|
||||
const stylesOutput = {
|
||||
meta: {
|
||||
generated: new Date().toISOString(),
|
||||
totalStyles: Object.keys(stylesInfo).length,
|
||||
stylesWithIcons: Object.values(stylesInfo).filter(s => s.count > 0).length
|
||||
},
|
||||
styles: stylesInfo,
|
||||
statistics: {
|
||||
totalIconsByStyle: styleCounts,
|
||||
styleCoverage: calculateStyleCoverage(stylesInfo, metadata.meta.totalIcons)
|
||||
}
|
||||
};
|
||||
|
||||
fs.writeFileSync(CONFIG.OUTPUT_STYLES, JSON.stringify(stylesOutput, null, 2), 'utf8');
|
||||
console.log(` ✅ Información de estilos guardada: ${CONFIG.OUTPUT_STYLES}`);
|
||||
|
||||
// Mostrar resumen
|
||||
console.log('\n 📊 RESUMEN DE ESTILOS:');
|
||||
Object.values(stylesInfo)
|
||||
.filter(style => style.count > 0)
|
||||
.sort((a, b) => b.count - a.count)
|
||||
.forEach(style => {
|
||||
console.log(` ${style.name.padEnd(20)}: ${style.count.toString().padStart(5)} íconos (${style.percentage}%)`);
|
||||
});
|
||||
|
||||
return stylesOutput;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calcular cobertura de estilos
|
||||
*/
|
||||
function calculateStyleCoverage(stylesInfo, totalIcons) {
|
||||
const coverage = {};
|
||||
|
||||
Object.values(stylesInfo).forEach(style => {
|
||||
if (style.count > 0) {
|
||||
coverage[style.id] = {
|
||||
hasIcons: true,
|
||||
count: style.count,
|
||||
percentage: ((style.count / totalIcons) * 100).toFixed(1)
|
||||
};
|
||||
} else {
|
||||
coverage[style.id] = {
|
||||
hasIcons: false,
|
||||
count: 0,
|
||||
percentage: '0.0'
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
return coverage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extraer y procesar categorías
|
||||
*/
|
||||
function extractCategories(metadata) {
|
||||
console.log(colors.blue + '\n📁 Extrayendo información de categorías...' + colors.reset);
|
||||
|
||||
// Mapeo de categorías de FontAwesome a nombres en español
|
||||
const categoriesMap = {
|
||||
'accessibility': 'Accesibilidad',
|
||||
'alert': 'Alertas',
|
||||
'animals': 'Animales',
|
||||
'arrows': 'Flechas',
|
||||
'automotive': 'Automotriz',
|
||||
'buildings': 'Edificios',
|
||||
'business': 'Negocios',
|
||||
'camping': 'Camping',
|
||||
'charity': 'Caridad',
|
||||
'charts-diagrams': 'Gráficos',
|
||||
'childhood': 'Infancia',
|
||||
'clothing-fashion': 'Ropa & Moda',
|
||||
'coding': 'Programación',
|
||||
'communication': 'Comunicación',
|
||||
'connectivity': 'Conectividad',
|
||||
'construction': 'Construcción',
|
||||
'design': 'Diseño',
|
||||
'devices-hardware': 'Dispositivos',
|
||||
'document': 'Documentos',
|
||||
'editing': 'Edición',
|
||||
'education': 'Educación',
|
||||
'emoji': 'Emoji',
|
||||
'energy': 'Energía',
|
||||
'files': 'Archivos',
|
||||
'film-video': 'Video',
|
||||
'food-beverage': 'Comida',
|
||||
'fruits-vegetables': 'Frutas',
|
||||
'gaming': 'Juegos',
|
||||
'gender': 'Género',
|
||||
'halloween': 'Halloween',
|
||||
'hands': 'Manos',
|
||||
'holidays': 'Fiestas',
|
||||
'household': 'Hogar',
|
||||
'humanitarian': 'Humanitario',
|
||||
'logistics': 'Logística',
|
||||
'maps': 'Mapas',
|
||||
'maritime': 'Marítimo',
|
||||
'marketing': 'Marketing',
|
||||
'mathematics': 'Matemáticas',
|
||||
'medical-health': 'Salud',
|
||||
'money': 'Dinero',
|
||||
'moving': 'Mudanza',
|
||||
'music-audio': 'Música',
|
||||
'nature': 'Naturaleza',
|
||||
'numbers': 'Números',
|
||||
'photos-images': 'Fotos',
|
||||
'political': 'Política',
|
||||
'punctuation-symbols': 'Símbolos',
|
||||
'religion': 'Religión',
|
||||
'science': 'Ciencia',
|
||||
'science-fiction': 'Sci-Fi',
|
||||
'security': 'Seguridad',
|
||||
'shapes': 'Formas',
|
||||
'shopping': 'Compras',
|
||||
'social': 'Social',
|
||||
'spinners': 'Spinners',
|
||||
'sports-fitness': 'Deportes',
|
||||
'text-formatting': 'Texto',
|
||||
'time': 'Tiempo',
|
||||
'toggle': 'Toggle',
|
||||
'transportation': 'Transporte',
|
||||
'travel': 'Viajes',
|
||||
'users-people': 'Personas',
|
||||
'weather': 'Clima',
|
||||
'writing': 'Escritura',
|
||||
'uncategorized': 'Sin Categoría'
|
||||
};
|
||||
|
||||
// Obtener conteos de categorías desde metadata
|
||||
const categoryCounts = metadata.statistics.iconsPerCategory || {};
|
||||
|
||||
// Procesar categorías
|
||||
const categories = [];
|
||||
|
||||
// Categorías especiales
|
||||
categories.push({
|
||||
id: 'all',
|
||||
name: 'Todos los Íconos',
|
||||
icon: 'fas fa-th',
|
||||
count: metadata.meta.totalIcons,
|
||||
type: 'special'
|
||||
});
|
||||
|
||||
categories.push({
|
||||
id: 'favorites',
|
||||
name: 'Favoritos',
|
||||
icon: 'fas fa-star',
|
||||
count: 0,
|
||||
type: 'special'
|
||||
});
|
||||
|
||||
categories.push({
|
||||
id: 'recent',
|
||||
name: 'Recientes',
|
||||
icon: 'fas fa-history',
|
||||
count: 0,
|
||||
type: 'special'
|
||||
});
|
||||
|
||||
// Categorías de FontAwesome
|
||||
Object.entries(categoryCounts).forEach(([categoryId, count]) => {
|
||||
const categoryName = categoriesMap[categoryId] || formatCategoryName(categoryId);
|
||||
|
||||
categories.push({
|
||||
id: categoryId,
|
||||
name: categoryName,
|
||||
icon: getCategoryIcon(categoryId),
|
||||
count: count,
|
||||
type: 'fontawesome'
|
||||
});
|
||||
});
|
||||
|
||||
// Ordenar categorías
|
||||
categories.sort((a, b) => {
|
||||
// Categorías especiales primero
|
||||
if (a.type === 'special' && b.type !== 'special') return -1;
|
||||
if (a.type !== 'special' && b.type === 'special') return 1;
|
||||
|
||||
// Luego por nombre
|
||||
return a.name.localeCompare(b.name);
|
||||
});
|
||||
|
||||
// Guardar categorías
|
||||
const categoriesOutput = {
|
||||
meta: {
|
||||
generated: new Date().toISOString(),
|
||||
totalCategories: categories.length,
|
||||
fontawesomeCategories: Object.keys(categoryCounts).length
|
||||
},
|
||||
categories: categories,
|
||||
mapping: categoriesMap
|
||||
};
|
||||
|
||||
fs.writeFileSync(CONFIG.OUTPUT_CATEGORIES, JSON.stringify(categoriesOutput, null, 2), 'utf8');
|
||||
console.log(` ✅ Categorías guardadas: ${CONFIG.OUTPUT_CATEGORIES}`);
|
||||
console.log(` 📊 Total categorías: ${categories.length}`);
|
||||
|
||||
// Mostrar top 10 categorías
|
||||
console.log('\n 🏆 TOP 10 CATEGORÍAS:');
|
||||
categories
|
||||
.filter(cat => cat.type === 'fontawesome')
|
||||
.sort((a, b) => b.count - a.count)
|
||||
.slice(0, 10)
|
||||
.forEach((cat, index) => {
|
||||
console.log(` ${index + 1}. ${cat.name.padEnd(25)}: ${cat.count} íconos`);
|
||||
});
|
||||
|
||||
return categoriesOutput;
|
||||
}
|
||||
|
||||
/**
|
||||
* Formatear nombre de categoría
|
||||
*/
|
||||
function formatCategoryName(categoryId) {
|
||||
return categoryId
|
||||
.split('-')
|
||||
.map(word => word.charAt(0).toUpperCase() + word.slice(1))
|
||||
.join(' ');
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtener ícono para categoría
|
||||
*/
|
||||
function getCategoryIcon(categoryId) {
|
||||
const iconMap = {
|
||||
'accessibility': 'fas fa-universal-access',
|
||||
'alert': 'fas fa-exclamation-triangle',
|
||||
'animals': 'fas fa-paw',
|
||||
'arrows': 'fas fa-arrow-right',
|
||||
'buildings': 'fas fa-building',
|
||||
'business': 'fas fa-briefcase',
|
||||
'coding': 'fas fa-code',
|
||||
'communication': 'fas fa-comments',
|
||||
'design': 'fas fa-palette',
|
||||
'devices-hardware': 'fas fa-laptop',
|
||||
'education': 'fas fa-graduation-cap',
|
||||
'files': 'fas fa-folder',
|
||||
'food-beverage': 'fas fa-utensils',
|
||||
'health': 'fas fa-heartbeat',
|
||||
'household': 'fas fa-home',
|
||||
'maps': 'fas fa-map',
|
||||
'music-audio': 'fas fa-music',
|
||||
'nature': 'fas fa-leaf',
|
||||
'shopping': 'fas fa-shopping-cart',
|
||||
'sports-fitness': 'fas fa-football-ball',
|
||||
'travel': 'fas fa-plane',
|
||||
'users-people': 'fas fa-user-friends',
|
||||
'weather': 'fas fa-cloud-sun',
|
||||
'writing': 'fas fa-pen-fancy'
|
||||
};
|
||||
|
||||
return iconMap[categoryId] || 'fas fa-folder';
|
||||
}
|
||||
|
||||
/**
|
||||
* Generar reporte de procesamiento
|
||||
*/
|
||||
function generateReport(metadata, styles, categories) {
|
||||
console.log(colors.blue + '\n📋 Generando reporte de procesamiento...' + colors.reset);
|
||||
|
||||
const reportPath = path.join(CONFIG.OUTPUT_DIR, 'logs', `report-${new Date().toISOString().replace(/[:.]/g, '-')}.json`);
|
||||
|
||||
const report = {
|
||||
meta: {
|
||||
generated: new Date().toISOString(),
|
||||
version: CONFIG.VERSION,
|
||||
duration: new Date() - startTime
|
||||
},
|
||||
summary: {
|
||||
totalIcons: metadata.meta.totalIcons,
|
||||
totalStyles: styles.meta.totalStyles,
|
||||
stylesWithIcons: styles.meta.stylesWithIcons,
|
||||
totalCategories: categories.meta.totalCategories
|
||||
},
|
||||
files: {
|
||||
metadata: CONFIG.OUTPUT_METADATA,
|
||||
styles: CONFIG.OUTPUT_STYLES,
|
||||
categories: CONFIG.OUTPUT_CATEGORIES
|
||||
},
|
||||
statistics: {
|
||||
iconsPerStyle: metadata.statistics.iconsPerStyle,
|
||||
iconsPerCategory: metadata.statistics.iconsPerCategory,
|
||||
styleCoverage: styles.statistics.styleCoverage
|
||||
}
|
||||
};
|
||||
|
||||
fs.writeFileSync(reportPath, JSON.stringify(report, null, 2), 'utf8');
|
||||
console.log(` ✅ Reporte guardado: ${reportPath}`);
|
||||
|
||||
return report;
|
||||
}
|
||||
|
||||
/**
|
||||
* Función principal
|
||||
*/
|
||||
async function main() {
|
||||
global.startTime = new Date();
|
||||
|
||||
try {
|
||||
console.log(colors.green + '🚀 Iniciando extracción de metadata...' + colors.reset);
|
||||
|
||||
// 1. Crear directorios
|
||||
createDirectories();
|
||||
|
||||
// 2. Verificar archivos de entrada
|
||||
if (!checkInputFiles()) {
|
||||
console.log(colors.red + '❌ Archivos requeridos no encontrados. Abortando.' + colors.reset);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// 3. Hacer backup
|
||||
backupExistingFiles();
|
||||
|
||||
// 4. Extraer metadata de íconos
|
||||
const metadata = extractIconMetadata();
|
||||
|
||||
// 5. Extraer información de estilos
|
||||
const styles = extractStyleInfo(metadata);
|
||||
|
||||
// 6. Extraer y procesar categorías
|
||||
const categories = extractCategories(metadata);
|
||||
|
||||
// 7. Generar reporte
|
||||
const report = generateReport(metadata, styles, categories);
|
||||
|
||||
// 8. Mostrar resumen final
|
||||
const duration = ((new Date() - startTime) / 1000).toFixed(2);
|
||||
|
||||
console.log(colors.green + '\n' + '='.repeat(70));
|
||||
console.log(' ✅ EXTRACCIÓN COMPLETADA EXITOSAMENTE');
|
||||
console.log('='.repeat(70) + colors.reset);
|
||||
|
||||
console.log(`\n📊 RESUMEN FINAL:`);
|
||||
console.log(` • Íconos procesados: ${metadata.meta.totalIcons}`);
|
||||
console.log(` • Estilos encontrados: ${styles.meta.stylesWithIcons}/${styles.meta.totalStyles}`);
|
||||
console.log(` • Categorías: ${categories.meta.totalCategories}`);
|
||||
console.log(` • Tiempo total: ${duration} segundos`);
|
||||
console.log(`\n📁 ARCHIVOS GENERADOS:`);
|
||||
console.log(` • ${path.relative(process.cwd(), CONFIG.OUTPUT_METADATA)}`);
|
||||
console.log(` • ${path.relative(process.cwd(), CONFIG.OUTPUT_STYLES)}`);
|
||||
console.log(` • ${path.relative(process.cwd(), CONFIG.OUTPUT_CATEGORIES)}`);
|
||||
console.log(`\n🚀 PRÓXIMOS PASOS:`);
|
||||
console.log(` • Ejecuta: npm run build`);
|
||||
console.log(` • Luego instala el plugin en Logseq`);
|
||||
|
||||
console.log(colors.green + '\n🎉 ¡Listo para construir la base de datos final!' + colors.reset);
|
||||
|
||||
} catch (error) {
|
||||
console.error(colors.red + '\n❌ ERROR CRÍTICO:' + colors.reset);
|
||||
console.error(` ${error.message}`);
|
||||
console.error(`\n🔧 Solución:`);
|
||||
console.error(` 1. Verifica que tengas FontAwesome 6 Pro instalado`);
|
||||
console.error(` 2. Asegúrate de que metadata/icons.json sea válido`);
|
||||
console.error(` 3. Intenta ejecutar 'npm run verify' primero`);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// Ejecutar
|
||||
if (require.main === module) {
|
||||
main();
|
||||
}
|
||||
|
||||
// Exportar funciones para uso en otros scripts
|
||||
module.exports = {
|
||||
extractIconMetadata,
|
||||
extractStyleInfo,
|
||||
extractCategories,
|
||||
createDirectories,
|
||||
checkInputFiles,
|
||||
CONFIG
|
||||
};
|
||||
331
scripts/validate-styles.js
Normal file
331
scripts/validate-styles.js
Normal file
@@ -0,0 +1,331 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const { execSync } = require('child_process');
|
||||
|
||||
// Configuración
|
||||
const CONFIG = {
|
||||
WEBFONTS_DIR: path.join(__dirname, '..', 'assets', 'fontawesome', 'webfonts'),
|
||||
PROCESSED_DIR: path.join(__dirname, '..', 'assets', 'processed'),
|
||||
OUTPUT_REPORT: path.join(__dirname, '..', 'assets', 'processed', 'validation-report.json'),
|
||||
VERSION: '2.0.0'
|
||||
};
|
||||
|
||||
console.log('🔍 Validando estilos FontAwesome Pro...\n');
|
||||
|
||||
/**
|
||||
* Validar archivos de fuentes
|
||||
*/
|
||||
function validateFontFiles() {
|
||||
console.log('🎨 Validando archivos de fuentes...');
|
||||
|
||||
const expectedFiles = [
|
||||
'fa-solid-900.woff2',
|
||||
'fa-regular-400.woff2',
|
||||
'fa-light-300.woff2',
|
||||
'fa-thin-100.woff2',
|
||||
'fa-duotone-900.woff2',
|
||||
'fa-sharp-solid-900.woff2',
|
||||
'fa-sharp-regular-400.woff2',
|
||||
'fa-sharp-light-300.woff2',
|
||||
'fa-sharp-thin-100.woff2',
|
||||
'fa-sharp-duotone-900.woff2',
|
||||
'fa-brands-400.woff2'
|
||||
];
|
||||
|
||||
const results = {
|
||||
total: expectedFiles.length,
|
||||
found: 0,
|
||||
missing: [],
|
||||
details: {}
|
||||
};
|
||||
|
||||
expectedFiles.forEach(file => {
|
||||
const filePath = path.join(CONFIG.WEBFONTS_DIR, file);
|
||||
const exists = fs.existsSync(filePath);
|
||||
|
||||
results.details[file] = {
|
||||
exists: exists,
|
||||
path: filePath,
|
||||
size: exists ? fs.statSync(filePath).size : 0
|
||||
};
|
||||
|
||||
if (exists) {
|
||||
results.found++;
|
||||
console.log(` ✅ ${file}`);
|
||||
} else {
|
||||
results.missing.push(file);
|
||||
console.log(` ❌ ${file} (FALTANTE)`);
|
||||
}
|
||||
});
|
||||
|
||||
console.log(`\n📊 Resumen: ${results.found}/${results.total} archivos encontrados`);
|
||||
|
||||
if (results.missing.length > 0) {
|
||||
console.log('\n⚠️ Archivos faltantes:');
|
||||
results.missing.forEach(file => {
|
||||
console.log(` • ${file}`);
|
||||
});
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validar metadata procesado
|
||||
*/
|
||||
function validateProcessedMetadata() {
|
||||
console.log('\n📊 Validando metadata procesado...');
|
||||
|
||||
const metadataPath = path.join(CONFIG.PROCESSED_DIR, 'metadata.json');
|
||||
const stylesPath = path.join(CONFIG.PROCESSED_DIR, 'styles.json');
|
||||
const categoriesPath = path.join(CONFIG.PROCESSED_DIR, 'categories.json');
|
||||
|
||||
const results = {
|
||||
metadata: { valid: false, error: null, data: null },
|
||||
styles: { valid: false, error: null, data: null },
|
||||
categories: { valid: false, error: null, data: null }
|
||||
};
|
||||
|
||||
// Validar metadata.json
|
||||
try {
|
||||
if (fs.existsSync(metadataPath)) {
|
||||
const content = fs.readFileSync(metadataPath, 'utf8');
|
||||
const data = JSON.parse(content);
|
||||
|
||||
if (data.meta && data.icons && data.statistics) {
|
||||
results.metadata = {
|
||||
valid: true,
|
||||
data: {
|
||||
totalIcons: data.meta.totalIcons || 0,
|
||||
totalStyles: data.statistics.styles?.length || 0,
|
||||
totalCategories: data.statistics.categories?.length || 0
|
||||
}
|
||||
};
|
||||
console.log(` ✅ metadata.json: ${results.metadata.data.totalIcons} íconos`);
|
||||
} else {
|
||||
results.metadata.error = 'Estructura inválida';
|
||||
console.log(` ❌ metadata.json: Estructura inválida`);
|
||||
}
|
||||
} else {
|
||||
results.metadata.error = 'Archivo no encontrado';
|
||||
console.log(` ❌ metadata.json: No encontrado`);
|
||||
}
|
||||
} catch (error) {
|
||||
results.metadata.error = error.message;
|
||||
console.log(` ❌ metadata.json: Error - ${error.message}`);
|
||||
}
|
||||
|
||||
// Validar styles.json
|
||||
try {
|
||||
if (fs.existsSync(stylesPath)) {
|
||||
const content = fs.readFileSync(stylesPath, 'utf8');
|
||||
const data = JSON.parse(content);
|
||||
|
||||
if (data.meta && data.styles) {
|
||||
const stylesWithIcons = Object.values(data.styles).filter(s => s.count > 0).length;
|
||||
results.styles = {
|
||||
valid: true,
|
||||
data: {
|
||||
totalStyles: data.meta.totalStyles || 0,
|
||||
stylesWithIcons: stylesWithIcons
|
||||
}
|
||||
};
|
||||
console.log(` ✅ styles.json: ${stylesWithIcons}/${data.meta.totalStyles} estilos con íconos`);
|
||||
} else {
|
||||
results.styles.error = 'Estructura inválida';
|
||||
console.log(` ❌ styles.json: Estructura inválida`);
|
||||
}
|
||||
} else {
|
||||
results.styles.error = 'Archivo no encontrado';
|
||||
console.log(` ❌ styles.json: No encontrado`);
|
||||
}
|
||||
} catch (error) {
|
||||
results.styles.error = error.message;
|
||||
console.log(` ❌ styles.json: Error - ${error.message}`);
|
||||
}
|
||||
|
||||
// Validar categories.json
|
||||
try {
|
||||
if (fs.existsSync(categoriesPath)) {
|
||||
const content = fs.readFileSync(categoriesPath, 'utf8');
|
||||
const data = JSON.parse(content);
|
||||
|
||||
if (data.meta && data.categories) {
|
||||
const fontawesomeCategories = data.categories.filter(c => c.type === 'fontawesome').length;
|
||||
results.categories = {
|
||||
valid: true,
|
||||
data: {
|
||||
totalCategories: data.meta.totalCategories || 0,
|
||||
fontawesomeCategories: fontawesomeCategories
|
||||
}
|
||||
};
|
||||
console.log(` ✅ categories.json: ${data.meta.totalCategories} categorías totales`);
|
||||
} else {
|
||||
results.categories.error = 'Estructura inválida';
|
||||
console.log(` ❌ categories.json: Estructura inválida`);
|
||||
}
|
||||
} else {
|
||||
results.categories.error = 'Archivo no encontrado';
|
||||
console.log(` ❌ categories.json: No encontrado`);
|
||||
}
|
||||
} catch (error) {
|
||||
results.categories.error = error.message;
|
||||
console.log(` ❌ categories.json: Error - ${error.message}`);
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validar compatibilidad
|
||||
*/
|
||||
function validateCompatibility(fontResults, metadataResults) {
|
||||
console.log('\n🔗 Validando compatibilidad...');
|
||||
|
||||
const issues = [];
|
||||
|
||||
// Verificar si hay estilos en metadata pero no en archivos
|
||||
if (metadataResults.styles.valid && metadataResults.styles.data) {
|
||||
const stylesWithIcons = metadataResults.styles.data.stylesWithIcons;
|
||||
|
||||
if (stylesWithIcons > fontResults.found) {
|
||||
issues.push({
|
||||
type: 'warning',
|
||||
message: `Hay ${stylesWithIcons} estilos en metadata pero solo ${fontResults.found} archivos de fuentes`
|
||||
});
|
||||
console.log(` ⚠️ Posible falta de archivos de fuentes`);
|
||||
}
|
||||
}
|
||||
|
||||
// Verificar si hay muchos archivos faltantes
|
||||
if (fontResults.missing.length > 5) {
|
||||
issues.push({
|
||||
type: 'error',
|
||||
message: `Faltan ${fontResults.missing.length} archivos de fuentes esenciales`
|
||||
});
|
||||
console.log(` ❌ Faltan muchos archivos de fuentes`);
|
||||
}
|
||||
|
||||
return issues;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generar reporte de validación
|
||||
*/
|
||||
function generateValidationReport(fontResults, metadataResults, compatibilityIssues) {
|
||||
const report = {
|
||||
meta: {
|
||||
generated: new Date().toISOString(),
|
||||
version: CONFIG.VERSION
|
||||
},
|
||||
fontFiles: fontResults,
|
||||
metadata: metadataResults,
|
||||
compatibility: {
|
||||
issues: compatibilityIssues,
|
||||
status: compatibilityIssues.length === 0 ? 'OK' : 'ISSUES'
|
||||
},
|
||||
recommendations: []
|
||||
};
|
||||
|
||||
// Generar recomendaciones
|
||||
if (fontResults.missing.length > 0) {
|
||||
report.recommendations.push({
|
||||
priority: 'high',
|
||||
action: 'download_missing_fonts',
|
||||
message: 'Descarga los archivos de fuentes faltantes de FontAwesome Pro'
|
||||
});
|
||||
}
|
||||
|
||||
if (!metadataResults.metadata.valid) {
|
||||
report.recommendations.push({
|
||||
priority: 'high',
|
||||
action: 'run_extract_metadata',
|
||||
message: 'Ejecuta scripts/extract-metadata.js primero'
|
||||
});
|
||||
}
|
||||
|
||||
if (compatibilityIssues.length > 0) {
|
||||
report.recommendations.push({
|
||||
priority: 'medium',
|
||||
action: 'verify_fontawesome_version',
|
||||
message: 'Verifica que tengas la versión correcta de FontAwesome Pro'
|
||||
});
|
||||
}
|
||||
|
||||
// Guardar reporte
|
||||
fs.writeFileSync(CONFIG.OUTPUT_REPORT, JSON.stringify(report, null, 2), 'utf8');
|
||||
console.log(`\n📋 Reporte de validación guardado: ${CONFIG.OUTPUT_REPORT}`);
|
||||
|
||||
return report;
|
||||
}
|
||||
|
||||
/**
|
||||
* Función principal
|
||||
*/
|
||||
function main() {
|
||||
try {
|
||||
console.log('='.repeat(60));
|
||||
console.log(' VALIDACIÓN DE ESTILOS FONTAWESOME PRO');
|
||||
console.log('='.repeat(60));
|
||||
|
||||
// 1. Validar archivos de fuentes
|
||||
const fontResults = validateFontFiles();
|
||||
|
||||
// 2. Validar metadata procesado
|
||||
const metadataResults = validateProcessedMetadata();
|
||||
|
||||
// 3. Validar compatibilidad
|
||||
const compatibilityIssues = validateCompatibility(fontResults, metadataResults);
|
||||
|
||||
// 4. Generar reporte
|
||||
const report = generateValidationReport(fontResults, metadataResults, compatibilityIssues);
|
||||
|
||||
// 5. Mostrar resumen
|
||||
console.log('\n' + '='.repeat(60));
|
||||
console.log(' RESUMEN DE VALIDACIÓN');
|
||||
console.log('='.repeat(60));
|
||||
|
||||
console.log(`\n🎨 Archivos de fuentes: ${fontResults.found}/${fontResults.total}`);
|
||||
console.log(`📊 Metadata procesado: ${metadataResults.metadata.valid ? '✅ Válido' : '❌ Inválido'}`);
|
||||
console.log(`🔗 Compatibilidad: ${compatibilityIssues.length === 0 ? '✅ OK' : '⚠️ Issues'}`);
|
||||
|
||||
if (report.recommendations.length > 0) {
|
||||
console.log('\n🚀 RECOMENDACIONES:');
|
||||
report.recommendations.forEach((rec, index) => {
|
||||
console.log(` ${index + 1}. [${rec.priority.toUpperCase()}] ${rec.message}`);
|
||||
});
|
||||
}
|
||||
|
||||
console.log('\n' + '='.repeat(60));
|
||||
|
||||
// Retornar código de salida apropiado
|
||||
if (fontResults.found === 0 || !metadataResults.metadata.valid) {
|
||||
console.log('\n❌ Validación fallida. Revisa las recomendaciones.');
|
||||
process.exit(1);
|
||||
} else if (compatibilityIssues.length > 0) {
|
||||
console.log('\n⚠️ Validación con advertencias. El plugin puede funcionar con limitaciones.');
|
||||
process.exit(0);
|
||||
} else {
|
||||
console.log('\n✅ Validación exitosa. Listo para construir la base de datos.');
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error(`\n❌ Error durante la validación: ${error.message}`);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// Ejecutar
|
||||
if (require.main === module) {
|
||||
main();
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
validateFontFiles,
|
||||
validateProcessedMetadata,
|
||||
validateCompatibility,
|
||||
generateValidationReport
|
||||
};
|
||||
Reference in New Issue
Block a user