Primera versión del plugin
This commit is contained in:
63
README.md
Normal file
63
README.md
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
# 🎨 FontAwesome 6 Pro para Logseq
|
||||||
|
|
||||||
|
Plugin completo para integrar **FontAwesome 6 Pro** en Logseq con panel de íconos, slash commands, control de color y tamaño, y soporte para **todos los 11 estilos disponibles**.
|
||||||
|
|
||||||
|

|
||||||
|

|
||||||
|

|
||||||
|
|
||||||
|
## ✨ Características
|
||||||
|
|
||||||
|
### 🎨 **Todos los estilos FontAwesome 6 Pro**
|
||||||
|
- ✅ **Solid** (fas) - 900 weight
|
||||||
|
- ✅ **Regular** (far) - 400 weight
|
||||||
|
- ✅ **Light** (fal) - 300 weight
|
||||||
|
- ✅ **Thin** (fat) - 100 weight
|
||||||
|
- ✅ **Duotone** (fad) - 900 weight
|
||||||
|
- ✅ **Sharp Solid** (fass) - ⭐ Nuevo en FA6
|
||||||
|
- ✅ **Sharp Regular** (fasr) - ⭐ Nuevo en FA6
|
||||||
|
- ✅ **Sharp Light** (fasl) - ⭐ Nuevo en FA6
|
||||||
|
- ✅ **Sharp Thin** (fast) - ⭐ Nuevo en FA6
|
||||||
|
- ✅ **Sharp Duotone** (fasd) - ⭐ Nuevo en FA6
|
||||||
|
- ✅ **Brands** (fab) - 400 weight (gratis)
|
||||||
|
|
||||||
|
### 🎯 **Funcionalidades avanzadas**
|
||||||
|
- 🎨 **Control completo de color** - Predefinidos + personalizado (#hex, rgb(), nombres)
|
||||||
|
- 📏 **Control de tamaño** - XS (0.75em) a 4X (4em)
|
||||||
|
- 🌀 **8 animaciones** - Spin, Pulse, Beat, Fade, Bounce, Flip, Shake
|
||||||
|
- 🔄 **Transformaciones** - Rotación (0°, 90°, 180°, 270°) + Flip
|
||||||
|
- 🔍 **Buscador inteligente** - Por nombre, categoría, etiquetas en español/inglés
|
||||||
|
- 🗂️ **58 categorías** - Organizadas y traducidas
|
||||||
|
- ⭐ **Favoritos** - Guarda tus íconos más usados
|
||||||
|
- 🕒 **Recientes** - Acceso rápido a íconos usados
|
||||||
|
- 💾 **Presets guardados** - Configuraciones por ícono
|
||||||
|
- ⌨️ **Slash commands** - Integración nativa con Logseq
|
||||||
|
- 🌓 **Tema claro/oscuro** - Se adapta automáticamente
|
||||||
|
|
||||||
|
### ⚡ **Rendimiento y usabilidad**
|
||||||
|
- 🚀 **Detección automática** - Solo carga los estilos que tienes instalados
|
||||||
|
- 💾 **Archivos locales** - Funciona 100% offline
|
||||||
|
- 🔄 **Actualización fácil** - Scripts automáticos
|
||||||
|
- 📊 **Verificación** - Comprueba archivos faltantes
|
||||||
|
- 🛡️ **Degradación elegante** - No se rompe si faltan estilos
|
||||||
|
|
||||||
|
## 🚀 Instalación
|
||||||
|
|
||||||
|
### Requisitos previos
|
||||||
|
- **Logseq** v0.9.x o superior
|
||||||
|
- **FontAwesome 6 Pro** (licencia válida)
|
||||||
|
- **Node.js** (solo para generación de base de datos)
|
||||||
|
|
||||||
|
### Paso 1: Descargar FontAwesome 6 Pro
|
||||||
|
1. Visita [fontawesome.com](https://fontawesome.com)
|
||||||
|
2. Inicia sesión con tu cuenta Pro
|
||||||
|
3. Descarga "Font Awesome 6 Pro - Web"
|
||||||
|
|
||||||
|
### Paso 2: Preparar archivos del plugin
|
||||||
|
```bash
|
||||||
|
# Crear estructura de carpetas
|
||||||
|
mkdir logseq-fontawesome-pro
|
||||||
|
cd logseq-fontawesome-pro
|
||||||
|
|
||||||
|
# Crear directorios necesarios
|
||||||
|
mkdir -p assets/fontawesome/{css,webfonts,metadata}
|
||||||
139
assets/dynamic-styles.css
Normal file
139
assets/dynamic-styles.css
Normal file
@@ -0,0 +1,139 @@
|
|||||||
|
/* ============================================
|
||||||
|
FontAwesome Dynamic Styles
|
||||||
|
Generado: 2025-12-15T04:11:59.767Z
|
||||||
|
Estilos detectados: 10
|
||||||
|
============================================ */
|
||||||
|
|
||||||
|
/* Font Awesome 6 Pro */
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Font Awesome 6 Pro';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 900;
|
||||||
|
font-display: block;
|
||||||
|
src: url("../webfonts/fa-solid-900.woff2") format("woff2");
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Font Awesome 6 Pro';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400;
|
||||||
|
font-display: block;
|
||||||
|
src: url("../webfonts/fa-regular-400.woff2") format("woff2");
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Font Awesome 6 Pro';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 300;
|
||||||
|
font-display: block;
|
||||||
|
src: url("../webfonts/fa-light-300.woff2") format("woff2");
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Font Awesome 6 Pro';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 100;
|
||||||
|
font-display: block;
|
||||||
|
src: url("../webfonts/fa-thin-100.woff2") format("woff2");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Font Awesome 6 Duotone */
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Font Awesome 6 Duotone';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 900;
|
||||||
|
font-display: block;
|
||||||
|
src: url("../webfonts/fa-duotone-900.woff2") format("woff2");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Font Awesome 6 Sharp */
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Font Awesome 6 Sharp';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 900;
|
||||||
|
font-display: block;
|
||||||
|
src: url("../webfonts/fa-sharp-solid-900.woff2") format("woff2");
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Font Awesome 6 Sharp';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400;
|
||||||
|
font-display: block;
|
||||||
|
src: url("../webfonts/fa-sharp-regular-400.woff2") format("woff2");
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Font Awesome 6 Sharp';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 300;
|
||||||
|
font-display: block;
|
||||||
|
src: url("../webfonts/fa-sharp-light-300.woff2") format("woff2");
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Font Awesome 6 Sharp';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 100;
|
||||||
|
font-display: block;
|
||||||
|
src: url("../webfonts/fa-sharp-thin-100.woff2") format("woff2");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Font Awesome 6 Brands */
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Font Awesome 6 Brands';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400;
|
||||||
|
font-display: block;
|
||||||
|
src: url("../webfonts/fa-brands-400.woff2") format("woff2");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reglas de clase */
|
||||||
|
.fas {
|
||||||
|
font-family: 'Font Awesome 6 Pro';
|
||||||
|
font-weight: 900;
|
||||||
|
}
|
||||||
|
.far {
|
||||||
|
font-family: 'Font Awesome 6 Pro';
|
||||||
|
font-weight: 400;
|
||||||
|
}
|
||||||
|
.fal {
|
||||||
|
font-family: 'Font Awesome 6 Pro';
|
||||||
|
font-weight: 300;
|
||||||
|
}
|
||||||
|
.fat {
|
||||||
|
font-family: 'Font Awesome 6 Pro';
|
||||||
|
font-weight: 100;
|
||||||
|
}
|
||||||
|
.fad {
|
||||||
|
font-family: 'Font Awesome 6 Duotone';
|
||||||
|
font-weight: 900;
|
||||||
|
}
|
||||||
|
.fass {
|
||||||
|
font-family: 'Font Awesome 6 Sharp';
|
||||||
|
font-weight: 900;
|
||||||
|
}
|
||||||
|
.fasr {
|
||||||
|
font-family: 'Font Awesome 6 Sharp';
|
||||||
|
font-weight: 400;
|
||||||
|
}
|
||||||
|
.fasl {
|
||||||
|
font-family: 'Font Awesome 6 Sharp';
|
||||||
|
font-weight: 300;
|
||||||
|
}
|
||||||
|
.fast {
|
||||||
|
font-family: 'Font Awesome 6 Sharp';
|
||||||
|
font-weight: 100;
|
||||||
|
}
|
||||||
|
.fab {
|
||||||
|
font-family: 'Font Awesome 6 Brands';
|
||||||
|
font-weight: 400;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Variables para Duotone */
|
||||||
|
.fad, .fasd {
|
||||||
|
--fa-primary-color: currentColor;
|
||||||
|
--fa-secondary-color: rgba(0, 0, 0, 0.4);
|
||||||
|
--fa-primary-opacity: 1;
|
||||||
|
--fa-secondary-opacity: 0.4;
|
||||||
|
}
|
||||||
12
assets/fontawesome/css/all.min.css
vendored
Normal file
12
assets/fontawesome/css/all.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
9
assets/fontawesome/css/fontawesome.min.css
vendored
Normal file
9
assets/fontawesome/css/fontawesome.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
377398
assets/fontawesome/metadata/icons.json
Normal file
377398
assets/fontawesome/metadata/icons.json
Normal file
File diff suppressed because one or more lines are too long
BIN
assets/fontawesome/webfonts/fa-brands-400.woff2
Normal file
BIN
assets/fontawesome/webfonts/fa-brands-400.woff2
Normal file
Binary file not shown.
BIN
assets/fontawesome/webfonts/fa-duotone-900.woff2
Normal file
BIN
assets/fontawesome/webfonts/fa-duotone-900.woff2
Normal file
Binary file not shown.
BIN
assets/fontawesome/webfonts/fa-light-300.woff2
Normal file
BIN
assets/fontawesome/webfonts/fa-light-300.woff2
Normal file
Binary file not shown.
BIN
assets/fontawesome/webfonts/fa-regular-400.woff2
Normal file
BIN
assets/fontawesome/webfonts/fa-regular-400.woff2
Normal file
Binary file not shown.
BIN
assets/fontawesome/webfonts/fa-sharp-light-300.woff2
Normal file
BIN
assets/fontawesome/webfonts/fa-sharp-light-300.woff2
Normal file
Binary file not shown.
BIN
assets/fontawesome/webfonts/fa-sharp-regular-400.woff2
Normal file
BIN
assets/fontawesome/webfonts/fa-sharp-regular-400.woff2
Normal file
Binary file not shown.
BIN
assets/fontawesome/webfonts/fa-sharp-solid-900.woff2
Normal file
BIN
assets/fontawesome/webfonts/fa-sharp-solid-900.woff2
Normal file
Binary file not shown.
BIN
assets/fontawesome/webfonts/fa-sharp-thin-100.woff2
Normal file
BIN
assets/fontawesome/webfonts/fa-sharp-thin-100.woff2
Normal file
Binary file not shown.
BIN
assets/fontawesome/webfonts/fa-solid-900.woff2
Normal file
BIN
assets/fontawesome/webfonts/fa-solid-900.woff2
Normal file
Binary file not shown.
BIN
assets/fontawesome/webfonts/fa-thin-100.woff2
Normal file
BIN
assets/fontawesome/webfonts/fa-thin-100.woff2
Normal file
Binary file not shown.
BIN
assets/fontawesome/webfonts/fa-v4compatibility.woff2
Normal file
BIN
assets/fontawesome/webfonts/fa-v4compatibility.woff2
Normal file
Binary file not shown.
105
assets/icons.json
Normal file
105
assets/icons.json
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
{
|
||||||
|
"meta": {
|
||||||
|
"generated": "2025-12-15T04:11:59.773Z",
|
||||||
|
"fontawesomeVersion": "6.0.0",
|
||||||
|
"pluginVersion": "2.0.0",
|
||||||
|
"totalIcons": 2,
|
||||||
|
"totalCategories": 3,
|
||||||
|
"detectedStyles": 3,
|
||||||
|
"proIcons": 2,
|
||||||
|
"freeIcons": 0,
|
||||||
|
"note": "BASE DE DATOS DE EJEMPLO - Ejecuta 'npm run build' para generar la versión completa"
|
||||||
|
},
|
||||||
|
"icons": [
|
||||||
|
{
|
||||||
|
"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
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"categories": [
|
||||||
|
{
|
||||||
|
"id": "all",
|
||||||
|
"name": "Todos los Íconos",
|
||||||
|
"icon": "fas fa-th",
|
||||||
|
"count": 2,
|
||||||
|
"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": [
|
||||||
|
{
|
||||||
|
"id": "solid",
|
||||||
|
"name": "Solid",
|
||||||
|
"prefix": "fas",
|
||||||
|
"class": "fas",
|
||||||
|
"available": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "regular",
|
||||||
|
"name": "Regular",
|
||||||
|
"prefix": "far",
|
||||||
|
"class": "far",
|
||||||
|
"available": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "light",
|
||||||
|
"name": "Light",
|
||||||
|
"prefix": "fal",
|
||||||
|
"class": "fal",
|
||||||
|
"available": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
105
assets/processed/backup/2025-12-15T04-11-57-202Z/categories.json
Normal file
105
assets/processed/backup/2025-12-15T04-11-57-202Z/categories.json
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
{
|
||||||
|
"meta": {
|
||||||
|
"generated": "2025-12-15T04:03:05.442Z",
|
||||||
|
"totalCategories": 4,
|
||||||
|
"fontawesomeCategories": 1
|
||||||
|
},
|
||||||
|
"categories": [
|
||||||
|
{
|
||||||
|
"id": "favorites",
|
||||||
|
"name": "Favoritos",
|
||||||
|
"icon": "fas fa-star",
|
||||||
|
"count": 0,
|
||||||
|
"type": "special"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "recent",
|
||||||
|
"name": "Recientes",
|
||||||
|
"icon": "fas fa-history",
|
||||||
|
"count": 0,
|
||||||
|
"type": "special"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "all",
|
||||||
|
"name": "Todos los Íconos",
|
||||||
|
"icon": "fas fa-th",
|
||||||
|
"count": 3787,
|
||||||
|
"type": "special"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "uncategorized",
|
||||||
|
"name": "Sin Categoría",
|
||||||
|
"icon": "fas fa-folder",
|
||||||
|
"count": 3787,
|
||||||
|
"type": "fontawesome"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"mapping": {
|
||||||
|
"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"
|
||||||
|
}
|
||||||
|
}
|
||||||
143138
assets/processed/backup/2025-12-15T04-11-57-202Z/metadata.json
Normal file
143138
assets/processed/backup/2025-12-15T04-11-57-202Z/metadata.json
Normal file
File diff suppressed because it is too large
Load Diff
230
assets/processed/backup/2025-12-15T04-11-57-202Z/styles.json
Normal file
230
assets/processed/backup/2025-12-15T04-11-57-202Z/styles.json
Normal file
@@ -0,0 +1,230 @@
|
|||||||
|
{
|
||||||
|
"meta": {
|
||||||
|
"generated": "2025-12-15T04:03:05.375Z",
|
||||||
|
"totalStyles": 11,
|
||||||
|
"stylesWithIcons": 6
|
||||||
|
},
|
||||||
|
"styles": {
|
||||||
|
"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",
|
||||||
|
"count": 3301,
|
||||||
|
"availableInMetadata": true,
|
||||||
|
"percentage": "87.2"
|
||||||
|
},
|
||||||
|
"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",
|
||||||
|
"count": 3301,
|
||||||
|
"availableInMetadata": true,
|
||||||
|
"percentage": "87.2"
|
||||||
|
},
|
||||||
|
"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",
|
||||||
|
"count": 3301,
|
||||||
|
"availableInMetadata": true,
|
||||||
|
"percentage": "87.2"
|
||||||
|
},
|
||||||
|
"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",
|
||||||
|
"count": 3301,
|
||||||
|
"availableInMetadata": true,
|
||||||
|
"percentage": "87.2"
|
||||||
|
},
|
||||||
|
"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",
|
||||||
|
"count": 3301,
|
||||||
|
"availableInMetadata": true,
|
||||||
|
"percentage": "87.2"
|
||||||
|
},
|
||||||
|
"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",
|
||||||
|
"count": 0,
|
||||||
|
"availableInMetadata": false,
|
||||||
|
"percentage": "0.0"
|
||||||
|
},
|
||||||
|
"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",
|
||||||
|
"count": 0,
|
||||||
|
"availableInMetadata": false,
|
||||||
|
"percentage": "0.0"
|
||||||
|
},
|
||||||
|
"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",
|
||||||
|
"count": 0,
|
||||||
|
"availableInMetadata": false,
|
||||||
|
"percentage": "0.0"
|
||||||
|
},
|
||||||
|
"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",
|
||||||
|
"count": 0,
|
||||||
|
"availableInMetadata": false,
|
||||||
|
"percentage": "0.0"
|
||||||
|
},
|
||||||
|
"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",
|
||||||
|
"count": 0,
|
||||||
|
"availableInMetadata": false,
|
||||||
|
"percentage": "0.0"
|
||||||
|
},
|
||||||
|
"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",
|
||||||
|
"count": 490,
|
||||||
|
"availableInMetadata": true,
|
||||||
|
"percentage": "12.9"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"statistics": {
|
||||||
|
"totalIconsByStyle": {
|
||||||
|
"solid": 3301,
|
||||||
|
"regular": 3301,
|
||||||
|
"light": 3301,
|
||||||
|
"thin": 3301,
|
||||||
|
"duotone": 3301,
|
||||||
|
"brands": 490
|
||||||
|
},
|
||||||
|
"styleCoverage": {
|
||||||
|
"solid": {
|
||||||
|
"hasIcons": true,
|
||||||
|
"count": 3301,
|
||||||
|
"percentage": "87.2"
|
||||||
|
},
|
||||||
|
"regular": {
|
||||||
|
"hasIcons": true,
|
||||||
|
"count": 3301,
|
||||||
|
"percentage": "87.2"
|
||||||
|
},
|
||||||
|
"light": {
|
||||||
|
"hasIcons": true,
|
||||||
|
"count": 3301,
|
||||||
|
"percentage": "87.2"
|
||||||
|
},
|
||||||
|
"thin": {
|
||||||
|
"hasIcons": true,
|
||||||
|
"count": 3301,
|
||||||
|
"percentage": "87.2"
|
||||||
|
},
|
||||||
|
"duotone": {
|
||||||
|
"hasIcons": true,
|
||||||
|
"count": 3301,
|
||||||
|
"percentage": "87.2"
|
||||||
|
},
|
||||||
|
"sharp-solid": {
|
||||||
|
"hasIcons": false,
|
||||||
|
"count": 0,
|
||||||
|
"percentage": "0.0"
|
||||||
|
},
|
||||||
|
"sharp-regular": {
|
||||||
|
"hasIcons": false,
|
||||||
|
"count": 0,
|
||||||
|
"percentage": "0.0"
|
||||||
|
},
|
||||||
|
"sharp-light": {
|
||||||
|
"hasIcons": false,
|
||||||
|
"count": 0,
|
||||||
|
"percentage": "0.0"
|
||||||
|
},
|
||||||
|
"sharp-thin": {
|
||||||
|
"hasIcons": false,
|
||||||
|
"count": 0,
|
||||||
|
"percentage": "0.0"
|
||||||
|
},
|
||||||
|
"sharp-duotone": {
|
||||||
|
"hasIcons": false,
|
||||||
|
"count": 0,
|
||||||
|
"percentage": "0.0"
|
||||||
|
},
|
||||||
|
"brands": {
|
||||||
|
"hasIcons": true,
|
||||||
|
"count": 490,
|
||||||
|
"percentage": "12.9"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
105
assets/processed/categories.json
Normal file
105
assets/processed/categories.json
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
{
|
||||||
|
"meta": {
|
||||||
|
"generated": "2025-12-15T04:11:58.708Z",
|
||||||
|
"totalCategories": 4,
|
||||||
|
"fontawesomeCategories": 1
|
||||||
|
},
|
||||||
|
"categories": [
|
||||||
|
{
|
||||||
|
"id": "favorites",
|
||||||
|
"name": "Favoritos",
|
||||||
|
"icon": "fas fa-star",
|
||||||
|
"count": 0,
|
||||||
|
"type": "special"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "recent",
|
||||||
|
"name": "Recientes",
|
||||||
|
"icon": "fas fa-history",
|
||||||
|
"count": 0,
|
||||||
|
"type": "special"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "all",
|
||||||
|
"name": "Todos los Íconos",
|
||||||
|
"icon": "fas fa-th",
|
||||||
|
"count": 3787,
|
||||||
|
"type": "special"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "uncategorized",
|
||||||
|
"name": "Sin Categoría",
|
||||||
|
"icon": "fas fa-folder",
|
||||||
|
"count": 3787,
|
||||||
|
"type": "fontawesome"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"mapping": {
|
||||||
|
"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"
|
||||||
|
}
|
||||||
|
}
|
||||||
88
assets/processed/logs/report-2025-12-15T04-03-05-443Z.json
Normal file
88
assets/processed/logs/report-2025-12-15T04-03-05-443Z.json
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
{
|
||||||
|
"meta": {
|
||||||
|
"generated": "2025-12-15T04:03:05.444Z",
|
||||||
|
"version": "2.0.0",
|
||||||
|
"duration": 2744
|
||||||
|
},
|
||||||
|
"summary": {
|
||||||
|
"totalIcons": 3787,
|
||||||
|
"totalStyles": 11,
|
||||||
|
"stylesWithIcons": 6,
|
||||||
|
"totalCategories": 4
|
||||||
|
},
|
||||||
|
"files": {
|
||||||
|
"metadata": "/home/monitor/Documents/Development/logseq-fontawesome-pro/assets/processed/metadata.json",
|
||||||
|
"styles": "/home/monitor/Documents/Development/logseq-fontawesome-pro/assets/processed/styles.json",
|
||||||
|
"categories": "/home/monitor/Documents/Development/logseq-fontawesome-pro/assets/processed/categories.json"
|
||||||
|
},
|
||||||
|
"statistics": {
|
||||||
|
"iconsPerStyle": {
|
||||||
|
"solid": 3301,
|
||||||
|
"regular": 3301,
|
||||||
|
"light": 3301,
|
||||||
|
"thin": 3301,
|
||||||
|
"duotone": 3301,
|
||||||
|
"brands": 490
|
||||||
|
},
|
||||||
|
"iconsPerCategory": {
|
||||||
|
"uncategorized": 3787
|
||||||
|
},
|
||||||
|
"styleCoverage": {
|
||||||
|
"solid": {
|
||||||
|
"hasIcons": true,
|
||||||
|
"count": 3301,
|
||||||
|
"percentage": "87.2"
|
||||||
|
},
|
||||||
|
"regular": {
|
||||||
|
"hasIcons": true,
|
||||||
|
"count": 3301,
|
||||||
|
"percentage": "87.2"
|
||||||
|
},
|
||||||
|
"light": {
|
||||||
|
"hasIcons": true,
|
||||||
|
"count": 3301,
|
||||||
|
"percentage": "87.2"
|
||||||
|
},
|
||||||
|
"thin": {
|
||||||
|
"hasIcons": true,
|
||||||
|
"count": 3301,
|
||||||
|
"percentage": "87.2"
|
||||||
|
},
|
||||||
|
"duotone": {
|
||||||
|
"hasIcons": true,
|
||||||
|
"count": 3301,
|
||||||
|
"percentage": "87.2"
|
||||||
|
},
|
||||||
|
"sharp-solid": {
|
||||||
|
"hasIcons": false,
|
||||||
|
"count": 0,
|
||||||
|
"percentage": "0.0"
|
||||||
|
},
|
||||||
|
"sharp-regular": {
|
||||||
|
"hasIcons": false,
|
||||||
|
"count": 0,
|
||||||
|
"percentage": "0.0"
|
||||||
|
},
|
||||||
|
"sharp-light": {
|
||||||
|
"hasIcons": false,
|
||||||
|
"count": 0,
|
||||||
|
"percentage": "0.0"
|
||||||
|
},
|
||||||
|
"sharp-thin": {
|
||||||
|
"hasIcons": false,
|
||||||
|
"count": 0,
|
||||||
|
"percentage": "0.0"
|
||||||
|
},
|
||||||
|
"sharp-duotone": {
|
||||||
|
"hasIcons": false,
|
||||||
|
"count": 0,
|
||||||
|
"percentage": "0.0"
|
||||||
|
},
|
||||||
|
"brands": {
|
||||||
|
"hasIcons": true,
|
||||||
|
"count": 490,
|
||||||
|
"percentage": "12.9"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
88
assets/processed/logs/report-2025-12-15T04-11-58-710Z.json
Normal file
88
assets/processed/logs/report-2025-12-15T04-11-58-710Z.json
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
{
|
||||||
|
"meta": {
|
||||||
|
"generated": "2025-12-15T04:11:58.710Z",
|
||||||
|
"version": "2.0.0",
|
||||||
|
"duration": 2553
|
||||||
|
},
|
||||||
|
"summary": {
|
||||||
|
"totalIcons": 3787,
|
||||||
|
"totalStyles": 11,
|
||||||
|
"stylesWithIcons": 6,
|
||||||
|
"totalCategories": 4
|
||||||
|
},
|
||||||
|
"files": {
|
||||||
|
"metadata": "/home/monitor/Documents/Development/logseq-fontawesome-pro/assets/processed/metadata.json",
|
||||||
|
"styles": "/home/monitor/Documents/Development/logseq-fontawesome-pro/assets/processed/styles.json",
|
||||||
|
"categories": "/home/monitor/Documents/Development/logseq-fontawesome-pro/assets/processed/categories.json"
|
||||||
|
},
|
||||||
|
"statistics": {
|
||||||
|
"iconsPerStyle": {
|
||||||
|
"solid": 3301,
|
||||||
|
"regular": 3301,
|
||||||
|
"light": 3301,
|
||||||
|
"thin": 3301,
|
||||||
|
"duotone": 3301,
|
||||||
|
"brands": 490
|
||||||
|
},
|
||||||
|
"iconsPerCategory": {
|
||||||
|
"uncategorized": 3787
|
||||||
|
},
|
||||||
|
"styleCoverage": {
|
||||||
|
"solid": {
|
||||||
|
"hasIcons": true,
|
||||||
|
"count": 3301,
|
||||||
|
"percentage": "87.2"
|
||||||
|
},
|
||||||
|
"regular": {
|
||||||
|
"hasIcons": true,
|
||||||
|
"count": 3301,
|
||||||
|
"percentage": "87.2"
|
||||||
|
},
|
||||||
|
"light": {
|
||||||
|
"hasIcons": true,
|
||||||
|
"count": 3301,
|
||||||
|
"percentage": "87.2"
|
||||||
|
},
|
||||||
|
"thin": {
|
||||||
|
"hasIcons": true,
|
||||||
|
"count": 3301,
|
||||||
|
"percentage": "87.2"
|
||||||
|
},
|
||||||
|
"duotone": {
|
||||||
|
"hasIcons": true,
|
||||||
|
"count": 3301,
|
||||||
|
"percentage": "87.2"
|
||||||
|
},
|
||||||
|
"sharp-solid": {
|
||||||
|
"hasIcons": false,
|
||||||
|
"count": 0,
|
||||||
|
"percentage": "0.0"
|
||||||
|
},
|
||||||
|
"sharp-regular": {
|
||||||
|
"hasIcons": false,
|
||||||
|
"count": 0,
|
||||||
|
"percentage": "0.0"
|
||||||
|
},
|
||||||
|
"sharp-light": {
|
||||||
|
"hasIcons": false,
|
||||||
|
"count": 0,
|
||||||
|
"percentage": "0.0"
|
||||||
|
},
|
||||||
|
"sharp-thin": {
|
||||||
|
"hasIcons": false,
|
||||||
|
"count": 0,
|
||||||
|
"percentage": "0.0"
|
||||||
|
},
|
||||||
|
"sharp-duotone": {
|
||||||
|
"hasIcons": false,
|
||||||
|
"count": 0,
|
||||||
|
"percentage": "0.0"
|
||||||
|
},
|
||||||
|
"brands": {
|
||||||
|
"hasIcons": true,
|
||||||
|
"count": 490,
|
||||||
|
"percentage": "12.9"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
143138
assets/processed/metadata.json
Normal file
143138
assets/processed/metadata.json
Normal file
File diff suppressed because it is too large
Load Diff
230
assets/processed/styles.json
Normal file
230
assets/processed/styles.json
Normal file
@@ -0,0 +1,230 @@
|
|||||||
|
{
|
||||||
|
"meta": {
|
||||||
|
"generated": "2025-12-15T04:11:58.654Z",
|
||||||
|
"totalStyles": 11,
|
||||||
|
"stylesWithIcons": 6
|
||||||
|
},
|
||||||
|
"styles": {
|
||||||
|
"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",
|
||||||
|
"count": 3301,
|
||||||
|
"availableInMetadata": true,
|
||||||
|
"percentage": "87.2"
|
||||||
|
},
|
||||||
|
"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",
|
||||||
|
"count": 3301,
|
||||||
|
"availableInMetadata": true,
|
||||||
|
"percentage": "87.2"
|
||||||
|
},
|
||||||
|
"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",
|
||||||
|
"count": 3301,
|
||||||
|
"availableInMetadata": true,
|
||||||
|
"percentage": "87.2"
|
||||||
|
},
|
||||||
|
"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",
|
||||||
|
"count": 3301,
|
||||||
|
"availableInMetadata": true,
|
||||||
|
"percentage": "87.2"
|
||||||
|
},
|
||||||
|
"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",
|
||||||
|
"count": 3301,
|
||||||
|
"availableInMetadata": true,
|
||||||
|
"percentage": "87.2"
|
||||||
|
},
|
||||||
|
"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",
|
||||||
|
"count": 0,
|
||||||
|
"availableInMetadata": false,
|
||||||
|
"percentage": "0.0"
|
||||||
|
},
|
||||||
|
"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",
|
||||||
|
"count": 0,
|
||||||
|
"availableInMetadata": false,
|
||||||
|
"percentage": "0.0"
|
||||||
|
},
|
||||||
|
"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",
|
||||||
|
"count": 0,
|
||||||
|
"availableInMetadata": false,
|
||||||
|
"percentage": "0.0"
|
||||||
|
},
|
||||||
|
"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",
|
||||||
|
"count": 0,
|
||||||
|
"availableInMetadata": false,
|
||||||
|
"percentage": "0.0"
|
||||||
|
},
|
||||||
|
"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",
|
||||||
|
"count": 0,
|
||||||
|
"availableInMetadata": false,
|
||||||
|
"percentage": "0.0"
|
||||||
|
},
|
||||||
|
"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",
|
||||||
|
"count": 490,
|
||||||
|
"availableInMetadata": true,
|
||||||
|
"percentage": "12.9"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"statistics": {
|
||||||
|
"totalIconsByStyle": {
|
||||||
|
"solid": 3301,
|
||||||
|
"regular": 3301,
|
||||||
|
"light": 3301,
|
||||||
|
"thin": 3301,
|
||||||
|
"duotone": 3301,
|
||||||
|
"brands": 490
|
||||||
|
},
|
||||||
|
"styleCoverage": {
|
||||||
|
"solid": {
|
||||||
|
"hasIcons": true,
|
||||||
|
"count": 3301,
|
||||||
|
"percentage": "87.2"
|
||||||
|
},
|
||||||
|
"regular": {
|
||||||
|
"hasIcons": true,
|
||||||
|
"count": 3301,
|
||||||
|
"percentage": "87.2"
|
||||||
|
},
|
||||||
|
"light": {
|
||||||
|
"hasIcons": true,
|
||||||
|
"count": 3301,
|
||||||
|
"percentage": "87.2"
|
||||||
|
},
|
||||||
|
"thin": {
|
||||||
|
"hasIcons": true,
|
||||||
|
"count": 3301,
|
||||||
|
"percentage": "87.2"
|
||||||
|
},
|
||||||
|
"duotone": {
|
||||||
|
"hasIcons": true,
|
||||||
|
"count": 3301,
|
||||||
|
"percentage": "87.2"
|
||||||
|
},
|
||||||
|
"sharp-solid": {
|
||||||
|
"hasIcons": false,
|
||||||
|
"count": 0,
|
||||||
|
"percentage": "0.0"
|
||||||
|
},
|
||||||
|
"sharp-regular": {
|
||||||
|
"hasIcons": false,
|
||||||
|
"count": 0,
|
||||||
|
"percentage": "0.0"
|
||||||
|
},
|
||||||
|
"sharp-light": {
|
||||||
|
"hasIcons": false,
|
||||||
|
"count": 0,
|
||||||
|
"percentage": "0.0"
|
||||||
|
},
|
||||||
|
"sharp-thin": {
|
||||||
|
"hasIcons": false,
|
||||||
|
"count": 0,
|
||||||
|
"percentage": "0.0"
|
||||||
|
},
|
||||||
|
"sharp-duotone": {
|
||||||
|
"hasIcons": false,
|
||||||
|
"count": 0,
|
||||||
|
"percentage": "0.0"
|
||||||
|
},
|
||||||
|
"brands": {
|
||||||
|
"hasIcons": true,
|
||||||
|
"count": 490,
|
||||||
|
"percentage": "12.9"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
105
assets/processed/validation-report.json
Normal file
105
assets/processed/validation-report.json
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
{
|
||||||
|
"meta": {
|
||||||
|
"generated": "2025-12-15T04:11:59.617Z",
|
||||||
|
"version": "2.0.0"
|
||||||
|
},
|
||||||
|
"fontFiles": {
|
||||||
|
"total": 11,
|
||||||
|
"found": 10,
|
||||||
|
"missing": [
|
||||||
|
"fa-sharp-duotone-900.woff2"
|
||||||
|
],
|
||||||
|
"details": {
|
||||||
|
"fa-solid-900.woff2": {
|
||||||
|
"exists": true,
|
||||||
|
"path": "/home/monitor/Documents/Development/logseq-fontawesome-pro/assets/fontawesome/webfonts/fa-solid-900.woff2",
|
||||||
|
"size": 350540
|
||||||
|
},
|
||||||
|
"fa-regular-400.woff2": {
|
||||||
|
"exists": true,
|
||||||
|
"path": "/home/monitor/Documents/Development/logseq-fontawesome-pro/assets/fontawesome/webfonts/fa-regular-400.woff2",
|
||||||
|
"size": 421248
|
||||||
|
},
|
||||||
|
"fa-light-300.woff2": {
|
||||||
|
"exists": true,
|
||||||
|
"path": "/home/monitor/Documents/Development/logseq-fontawesome-pro/assets/fontawesome/webfonts/fa-light-300.woff2",
|
||||||
|
"size": 460556
|
||||||
|
},
|
||||||
|
"fa-thin-100.woff2": {
|
||||||
|
"exists": true,
|
||||||
|
"path": "/home/monitor/Documents/Development/logseq-fontawesome-pro/assets/fontawesome/webfonts/fa-thin-100.woff2",
|
||||||
|
"size": 498828
|
||||||
|
},
|
||||||
|
"fa-duotone-900.woff2": {
|
||||||
|
"exists": true,
|
||||||
|
"path": "/home/monitor/Documents/Development/logseq-fontawesome-pro/assets/fontawesome/webfonts/fa-duotone-900.woff2",
|
||||||
|
"size": 451084
|
||||||
|
},
|
||||||
|
"fa-sharp-solid-900.woff2": {
|
||||||
|
"exists": true,
|
||||||
|
"path": "/home/monitor/Documents/Development/logseq-fontawesome-pro/assets/fontawesome/webfonts/fa-sharp-solid-900.woff2",
|
||||||
|
"size": 283224
|
||||||
|
},
|
||||||
|
"fa-sharp-regular-400.woff2": {
|
||||||
|
"exists": true,
|
||||||
|
"path": "/home/monitor/Documents/Development/logseq-fontawesome-pro/assets/fontawesome/webfonts/fa-sharp-regular-400.woff2",
|
||||||
|
"size": 361060
|
||||||
|
},
|
||||||
|
"fa-sharp-light-300.woff2": {
|
||||||
|
"exists": true,
|
||||||
|
"path": "/home/monitor/Documents/Development/logseq-fontawesome-pro/assets/fontawesome/webfonts/fa-sharp-light-300.woff2",
|
||||||
|
"size": 399468
|
||||||
|
},
|
||||||
|
"fa-sharp-thin-100.woff2": {
|
||||||
|
"exists": true,
|
||||||
|
"path": "/home/monitor/Documents/Development/logseq-fontawesome-pro/assets/fontawesome/webfonts/fa-sharp-thin-100.woff2",
|
||||||
|
"size": 428956
|
||||||
|
},
|
||||||
|
"fa-sharp-duotone-900.woff2": {
|
||||||
|
"exists": false,
|
||||||
|
"path": "/home/monitor/Documents/Development/logseq-fontawesome-pro/assets/fontawesome/webfonts/fa-sharp-duotone-900.woff2",
|
||||||
|
"size": 0
|
||||||
|
},
|
||||||
|
"fa-brands-400.woff2": {
|
||||||
|
"exists": true,
|
||||||
|
"path": "/home/monitor/Documents/Development/logseq-fontawesome-pro/assets/fontawesome/webfonts/fa-brands-400.woff2",
|
||||||
|
"size": 118872
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"metadata": {
|
||||||
|
"metadata": {
|
||||||
|
"valid": true,
|
||||||
|
"data": {
|
||||||
|
"totalIcons": 3787,
|
||||||
|
"totalStyles": 6,
|
||||||
|
"totalCategories": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"styles": {
|
||||||
|
"valid": true,
|
||||||
|
"data": {
|
||||||
|
"totalStyles": 11,
|
||||||
|
"stylesWithIcons": 6
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"categories": {
|
||||||
|
"valid": true,
|
||||||
|
"data": {
|
||||||
|
"totalCategories": 4,
|
||||||
|
"fontawesomeCategories": 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"compatibility": {
|
||||||
|
"issues": [],
|
||||||
|
"status": "OK"
|
||||||
|
},
|
||||||
|
"recommendations": [
|
||||||
|
{
|
||||||
|
"priority": "high",
|
||||||
|
"action": "download_missing_fonts",
|
||||||
|
"message": "Descarga los archivos de fuentes faltantes de FontAwesome Pro"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
495
assets/styles.css
Normal file
495
assets/styles.css
Normal file
@@ -0,0 +1,495 @@
|
|||||||
|
/* ============================================
|
||||||
|
* FontAwesome Pro - Estilos Base para Logseq
|
||||||
|
* Versión: 2.0.0
|
||||||
|
* Generado automáticamente
|
||||||
|
= *=========================================== */
|
||||||
|
|
||||||
|
/* Variables CSS para temas */
|
||||||
|
:root {
|
||||||
|
--fa-primary-color: var(--ls-link-text-color, #0451a5);
|
||||||
|
--fa-secondary-color: var(--ls-secondary-text-color, #666666);
|
||||||
|
--fa-border-radius: 8px;
|
||||||
|
--fa-transition-speed: 0.2s;
|
||||||
|
|
||||||
|
/* Colores específicos para estilos FontAwesome */
|
||||||
|
--fa-solid-color: #000000;
|
||||||
|
--fa-regular-color: #666666;
|
||||||
|
--fa-light-color: #999999;
|
||||||
|
--fa-thin-color: #cccccc;
|
||||||
|
--fa-duotone-primary: #8b5cf6;
|
||||||
|
--fa-duotone-secondary: #ec4899;
|
||||||
|
--fa-sharp-solid-color: #7c3aed;
|
||||||
|
--fa-sharp-regular-color: #8b5cf6;
|
||||||
|
--fa-sharp-light-color: #a78bfa;
|
||||||
|
--fa-sharp-thin-color: #c4b5fd;
|
||||||
|
--fa-brands-color: #1877f2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Tema oscuro */
|
||||||
|
@media (prefers-color-scheme: dark) {
|
||||||
|
:root {
|
||||||
|
--fa-solid-color: #ffffff;
|
||||||
|
--fa-regular-color: #cccccc;
|
||||||
|
--fa-light-color: #aaaaaa;
|
||||||
|
--fa-thin-color: #888888;
|
||||||
|
--fa-duotone-primary: #a78bfa;
|
||||||
|
--fa-duotone-secondary: #f472b6;
|
||||||
|
--fa-sharp-solid-color: #a78bfa;
|
||||||
|
--fa-sharp-regular-color: #c4b5fd;
|
||||||
|
--fa-sharp-light-color: #ddd6fe;
|
||||||
|
--fa-sharp-thin-color: #ede9fe;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Clases utilitarias para íconos */
|
||||||
|
.fa-icon-xs { font-size: 0.75em !important; }
|
||||||
|
.fa-icon-sm { font-size: 0.875em !important; }
|
||||||
|
.fa-icon-md { font-size: 1em !important; }
|
||||||
|
.fa-icon-lg { font-size: 1.33em !important; }
|
||||||
|
.fa-icon-xl { font-size: 1.75em !important; }
|
||||||
|
.fa-icon-2x { font-size: 2em !important; }
|
||||||
|
.fa-icon-3x { font-size: 3em !important; }
|
||||||
|
.fa-icon-4x { font-size: 4em !important; }
|
||||||
|
.fa-icon-5x { font-size: 5em !important; }
|
||||||
|
|
||||||
|
/* Efectos hover para tarjetas de íconos */
|
||||||
|
.icon-card:hover .fa-icon {
|
||||||
|
transform: scale(1.1);
|
||||||
|
transition: transform var(--fa-transition-speed) ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Estilos para el buscador */
|
||||||
|
.fa-search-highlight {
|
||||||
|
background-color: rgba(var(--ls-link-text-color-rgb, 5, 81, 165), 0.1);
|
||||||
|
border-radius: 2px;
|
||||||
|
padding: 0 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Indicadores de estilo */
|
||||||
|
.style-indicator {
|
||||||
|
width: 8px;
|
||||||
|
height: 8px;
|
||||||
|
border-radius: 50%;
|
||||||
|
display: inline-block;
|
||||||
|
margin-right: 4px;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
.style-indicator.solid { background-color: var(--fa-solid-color); }
|
||||||
|
.style-indicator.regular { background-color: var(--fa-regular-color); }
|
||||||
|
.style-indicator.light { background-color: var(--fa-light-color); }
|
||||||
|
.style-indicator.thin { background-color: var(--fa-thin-color); }
|
||||||
|
.style-indicator.duotone {
|
||||||
|
background: linear-gradient(45deg, var(--fa-duotone-primary), var(--fa-duotone-secondary));
|
||||||
|
}
|
||||||
|
.style-indicator.sharp-solid { background-color: var(--fa-sharp-solid-color); }
|
||||||
|
.style-indicator.sharp-regular { background-color: var(--fa-sharp-regular-color); }
|
||||||
|
.style-indicator.sharp-light { background-color: var(--fa-sharp-light-color); }
|
||||||
|
.style-indicator.sharp-thin { background-color: var(--fa-sharp-thin-color); }
|
||||||
|
.style-indicator.sharp-duotone {
|
||||||
|
background: linear-gradient(45deg, var(--fa-sharp-solid-color), var(--fa-duotone-secondary));
|
||||||
|
}
|
||||||
|
.style-indicator.brands { background-color: var(--fa-brands-color); }
|
||||||
|
|
||||||
|
/* Badges para tarjetas */
|
||||||
|
.fa-badge {
|
||||||
|
position: absolute;
|
||||||
|
top: 6px;
|
||||||
|
right: 6px;
|
||||||
|
width: 18px;
|
||||||
|
height: 18px;
|
||||||
|
border-radius: 50%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-size: 10px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fa-badge.favorite {
|
||||||
|
background-color: #ef4444;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fa-badge.recent {
|
||||||
|
background-color: #f59e0b;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fa-badge.pro {
|
||||||
|
background-color: #8b5cf6;
|
||||||
|
color: white;
|
||||||
|
font-size: 9px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Estilos para categorías */
|
||||||
|
.category-progress {
|
||||||
|
height: 2px;
|
||||||
|
background: var(--ls-border-color);
|
||||||
|
border-radius: 1px;
|
||||||
|
margin-top: 4px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.category-progress-fill {
|
||||||
|
height: 100%;
|
||||||
|
background: var(--ls-link-text-color);
|
||||||
|
border-radius: 1px;
|
||||||
|
transition: width 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Selectores de color */
|
||||||
|
.color-swatch {
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
border-radius: 50%;
|
||||||
|
border: 2px solid var(--ls-border-color);
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all var(--fa-transition-speed);
|
||||||
|
display: inline-block;
|
||||||
|
margin: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.color-swatch:hover {
|
||||||
|
transform: scale(1.1);
|
||||||
|
border-color: var(--ls-link-text-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.color-swatch.active {
|
||||||
|
border-color: var(--ls-primary-text-color);
|
||||||
|
box-shadow: 0 0 0 2px var(--ls-link-text-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Previsualización de tamaño */
|
||||||
|
.size-preview {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
border: 1px solid var(--ls-border-color);
|
||||||
|
border-radius: var(--fa-border-radius);
|
||||||
|
background: var(--ls-secondary-background-color);
|
||||||
|
margin: 2px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all var(--fa-transition-speed);
|
||||||
|
}
|
||||||
|
|
||||||
|
.size-preview:hover {
|
||||||
|
border-color: var(--ls-link-text-color);
|
||||||
|
background: var(--ls-tertiary-background-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.size-preview.active {
|
||||||
|
border-color: var(--ls-link-text-color);
|
||||||
|
background: var(--ls-link-text-color);
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Animaciones de carga */
|
||||||
|
.fa-loading {
|
||||||
|
display: inline-block;
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
border: 2px solid var(--ls-border-color);
|
||||||
|
border-radius: 50%;
|
||||||
|
border-top-color: var(--ls-link-text-color);
|
||||||
|
animation: fa-spin 1s linear infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes fa-spin {
|
||||||
|
0% { transform: rotate(0deg); }
|
||||||
|
100% { transform: rotate(360deg); }
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Notificaciones */
|
||||||
|
.fa-notification {
|
||||||
|
position: fixed;
|
||||||
|
bottom: 20px;
|
||||||
|
right: 20px;
|
||||||
|
padding: 12px 16px;
|
||||||
|
background: var(--ls-success-color);
|
||||||
|
color: white;
|
||||||
|
border-radius: 6px;
|
||||||
|
font-size: 13px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
|
||||||
|
z-index: 1000;
|
||||||
|
animation: fa-slide-in 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes fa-slide-in {
|
||||||
|
from {
|
||||||
|
transform: translateX(100%);
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
transform: translateX(0);
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Tooltips */
|
||||||
|
.fa-tooltip {
|
||||||
|
position: relative;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fa-tooltip .fa-tooltip-text {
|
||||||
|
visibility: hidden;
|
||||||
|
width: 200px;
|
||||||
|
background-color: var(--ls-primary-background-color);
|
||||||
|
color: var(--ls-primary-text-color);
|
||||||
|
text-align: center;
|
||||||
|
border-radius: 6px;
|
||||||
|
padding: 8px;
|
||||||
|
border: 1px solid var(--ls-border-color);
|
||||||
|
position: absolute;
|
||||||
|
z-index: 1;
|
||||||
|
bottom: 125%;
|
||||||
|
left: 50%;
|
||||||
|
margin-left: -100px;
|
||||||
|
opacity: 0;
|
||||||
|
transition: opacity 0.3s;
|
||||||
|
font-size: 12px;
|
||||||
|
box-shadow: 0 4px 12px rgba(0,0,0,0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.fa-tooltip:hover .fa-tooltip-text {
|
||||||
|
visibility: visible;
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Estados de filtro */
|
||||||
|
.filter-active {
|
||||||
|
background: var(--ls-link-text-color) !important;
|
||||||
|
color: white !important;
|
||||||
|
border-color: var(--ls-link-text-color) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-disabled {
|
||||||
|
opacity: 0.5;
|
||||||
|
cursor: not-allowed !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Separadores */
|
||||||
|
.fa-separator {
|
||||||
|
height: 1px;
|
||||||
|
background: var(--ls-border-color);
|
||||||
|
margin: 12px 0;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Estilos para estadísticas */
|
||||||
|
.fa-stats {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
font-size: 11px;
|
||||||
|
color: var(--ls-secondary-text-color);
|
||||||
|
margin-top: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fa-stat-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Estilos para preview en tiempo real */
|
||||||
|
.fa-preview-container {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 20px;
|
||||||
|
background: var(--ls-secondary-background-color);
|
||||||
|
border-radius: var(--fa-border-radius);
|
||||||
|
min-height: 100px;
|
||||||
|
margin: 12px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fa-preview-icon {
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Estilos para código */
|
||||||
|
.fa-code-block {
|
||||||
|
background: var(--ls-tertiary-background-color);
|
||||||
|
padding: 12px;
|
||||||
|
border-radius: var(--fa-border-radius);
|
||||||
|
font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
|
||||||
|
font-size: 12px;
|
||||||
|
overflow-x: auto;
|
||||||
|
margin: 8px 0;
|
||||||
|
border: 1px solid var(--ls-border-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.fa-code-block pre {
|
||||||
|
margin: 0;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
word-break: break-all;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Botones de acción */
|
||||||
|
.fa-action-btn {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 6px;
|
||||||
|
padding: 8px 16px;
|
||||||
|
border: none;
|
||||||
|
border-radius: 6px;
|
||||||
|
background: var(--ls-link-text-color);
|
||||||
|
color: white;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: 500;
|
||||||
|
transition: all var(--fa-transition-speed);
|
||||||
|
}
|
||||||
|
|
||||||
|
.fa-action-btn:hover {
|
||||||
|
opacity: 0.9;
|
||||||
|
transform: translateY(-1px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.fa-action-btn.secondary {
|
||||||
|
background: var(--ls-secondary-background-color);
|
||||||
|
color: var(--ls-primary-text-color);
|
||||||
|
border: 1px solid var(--ls-border-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.fa-action-btn.success {
|
||||||
|
background: var(--ls-success-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.fa-action-btn.danger {
|
||||||
|
background: var(--ls-error-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Responsive */
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.fa-responsive-hide {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fa-responsive-stack {
|
||||||
|
flex-direction: column !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fa-responsive-grid {
|
||||||
|
grid-template-columns: repeat(auto-fill, minmax(70px, 1fr)) !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Utilidades de espaciado */
|
||||||
|
.fa-mt-1 { margin-top: 4px; }
|
||||||
|
.fa-mt-2 { margin-top: 8px; }
|
||||||
|
.fa-mt-3 { margin-top: 12px; }
|
||||||
|
.fa-mt-4 { margin-top: 16px; }
|
||||||
|
|
||||||
|
.fa-mb-1 { margin-bottom: 4px; }
|
||||||
|
.fa-mb-2 { margin-bottom: 8px; }
|
||||||
|
.fa-mb-3 { margin-bottom: 12px; }
|
||||||
|
.fa-mb-4 { margin-bottom: 16px; }
|
||||||
|
|
||||||
|
.fa-ml-1 { margin-left: 4px; }
|
||||||
|
.fa-ml-2 { margin-left: 8px; }
|
||||||
|
.fa-ml-3 { margin-left: 12px; }
|
||||||
|
.fa-ml-4 { margin-left: 16px; }
|
||||||
|
|
||||||
|
.fa-mr-1 { margin-right: 4px; }
|
||||||
|
.fa-mr-2 { margin-right: 8px; }
|
||||||
|
.fa-mr-3 { margin-right: 12px; }
|
||||||
|
.fa-mr-4 { margin-right: 16px; }
|
||||||
|
|
||||||
|
/* Utilidades de texto */
|
||||||
|
.fa-text-xs { font-size: 11px !important; }
|
||||||
|
.fa-text-sm { font-size: 12px !important; }
|
||||||
|
.fa-text-md { font-size: 13px !important; }
|
||||||
|
.fa-text-lg { font-size: 14px !important; }
|
||||||
|
.fa-text-xl { font-size: 16px !important; }
|
||||||
|
|
||||||
|
.fa-text-muted { color: var(--ls-secondary-text-color) !important; }
|
||||||
|
.fa-text-primary { color: var(--ls-link-text-color) !important; }
|
||||||
|
.fa-text-success { color: var(--ls-success-color) !important; }
|
||||||
|
.fa-text-danger { color: var(--ls-error-color) !important; }
|
||||||
|
.fa-text-warning { color: var(--ls-warning-color) !important; }
|
||||||
|
|
||||||
|
/* Utilidades de fondo */
|
||||||
|
.fa-bg-primary { background: var(--ls-link-text-color) !important; }
|
||||||
|
.fa-bg-secondary { background: var(--ls-secondary-background-color) !important; }
|
||||||
|
.fa-bg-tertiary { background: var(--ls-tertiary-background-color) !important; }
|
||||||
|
|
||||||
|
/* Utilidades de borde */
|
||||||
|
.fa-border { border: 1px solid var(--ls-border-color) !important; }
|
||||||
|
.fa-border-top { border-top: 1px solid var(--ls-border-color) !important; }
|
||||||
|
.fa-border-bottom { border-bottom: 1px solid var(--ls-border-color) !important; }
|
||||||
|
.fa-border-left { border-left: 1px solid var(--ls-border-color) !important; }
|
||||||
|
.fa-border-right { border-right: 1px solid var(--ls-border-color) !important; }
|
||||||
|
|
||||||
|
/* Utilidades de display */
|
||||||
|
.fa-d-block { display: block !important; }
|
||||||
|
.fa-d-inline { display: inline !important; }
|
||||||
|
.fa-d-inline-block { display: inline-block !important; }
|
||||||
|
.fa-d-flex { display: flex !important; }
|
||||||
|
.fa-d-none { display: none !important; }
|
||||||
|
|
||||||
|
/* Utilidades de flexbox */
|
||||||
|
.fa-flex-row { flex-direction: row !important; }
|
||||||
|
.fa-flex-column { flex-direction: column !important; }
|
||||||
|
.fa-align-items-center { align-items: center !important; }
|
||||||
|
.fa-justify-content-center { justify-content: center !important; }
|
||||||
|
.fa-justify-content-between { justify-content: space-between !important; }
|
||||||
|
.fa-flex-wrap { flex-wrap: wrap !important; }
|
||||||
|
.fa-gap-1 { gap: 4px !important; }
|
||||||
|
.fa-gap-2 { gap: 8px !important; }
|
||||||
|
.fa-gap-3 { gap: 12px !important; }
|
||||||
|
.fa-gap-4 { gap: 16px !important; }
|
||||||
|
|
||||||
|
/* Utilidades de grid */
|
||||||
|
.fa-grid { display: grid !important; }
|
||||||
|
.fa-grid-cols-2 { grid-template-columns: repeat(2, 1fr) !important; }
|
||||||
|
.fa-grid-cols-3 { grid-template-columns: repeat(3, 1fr) !important; }
|
||||||
|
.fa-grid-cols-4 { grid-template-columns: repeat(4, 1fr) !important; }
|
||||||
|
.fa-grid-cols-auto { grid-template-columns: repeat(auto-fill, minmax(100px, 1fr)) !important; }
|
||||||
|
|
||||||
|
/* Utilidades de posición */
|
||||||
|
.fa-position-relative { position: relative !important; }
|
||||||
|
.fa-position-absolute { position: absolute !important; }
|
||||||
|
.fa-position-fixed { position: fixed !important; }
|
||||||
|
.fa-position-sticky { position: sticky !important; }
|
||||||
|
|
||||||
|
/* Utilidades de overflow */
|
||||||
|
.fa-overflow-auto { overflow: auto !important; }
|
||||||
|
.fa-overflow-hidden { overflow: hidden !important; }
|
||||||
|
.fa-overflow-scroll { overflow: scroll !important; }
|
||||||
|
|
||||||
|
/* Utilidades de cursor */
|
||||||
|
.fa-cursor-pointer { cursor: pointer !important; }
|
||||||
|
.fa-cursor-default { cursor: default !important; }
|
||||||
|
.fa-cursor-not-allowed { cursor: not-allowed !important; }
|
||||||
|
|
||||||
|
/* Utilidades de transición */
|
||||||
|
.fa-transition-all { transition: all var(--fa-transition-speed) ease !important; }
|
||||||
|
.fa-transition-transform { transition: transform var(--fa-transition-speed) ease !important; }
|
||||||
|
.fa-transition-opacity { transition: opacity var(--fa-transition-speed) ease !important; }
|
||||||
|
|
||||||
|
/* Utilidades de transform */
|
||||||
|
.fa-transform-scale-1 { transform: scale(1) !important; }
|
||||||
|
.fa-transform-scale-1-1 { transform: scale(1.1) !important; }
|
||||||
|
.fa-transform-rotate-0 { transform: rotate(0deg) !important; }
|
||||||
|
.fa-transform-rotate-90 { transform: rotate(90deg) !important; }
|
||||||
|
.fa-transform-rotate-180 { transform: rotate(180deg) !important; }
|
||||||
|
.fa-transform-rotate-270 { transform: rotate(270deg) !important; }
|
||||||
|
|
||||||
|
/* Utilidades de animación */
|
||||||
|
.fa-animation-spin { animation: fa-spin 2s linear infinite !important; }
|
||||||
|
.fa-animation-pulse { animation: fa-spin 1s steps(8) infinite !important; }
|
||||||
|
.fa-animation-bounce { animation: fa-bounce 1s ease infinite !important; }
|
||||||
|
|
||||||
|
@keyframes fa-bounce {
|
||||||
|
0%, 100% { transform: translateY(0); }
|
||||||
|
50% { transform: translateY(-5px); }
|
||||||
|
}
|
||||||
863
build-icons-json.js
Normal file
863
build-icons-json.js
Normal 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
|
||||||
|
};
|
||||||
2560
index.html
Normal file
2560
index.html
Normal file
File diff suppressed because it is too large
Load Diff
14
package-lock.json
generated
Normal file
14
package-lock.json
generated
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"name": "logseq-fontawesome-pro",
|
||||||
|
"version": "2.6.2",
|
||||||
|
"lockfileVersion": 3,
|
||||||
|
"requires": true,
|
||||||
|
"packages": {
|
||||||
|
"": {
|
||||||
|
"name": "logseq-fontawesome-pro",
|
||||||
|
"version": "2.6.2",
|
||||||
|
"license": "MIT",
|
||||||
|
"devDependencies": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
27
package.json
Normal file
27
package.json
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
{
|
||||||
|
"name": "logseq-fontawesome-pro",
|
||||||
|
"version": "2.6.2",
|
||||||
|
"description": "FontAwesome 6 Pro completo con todos los estilos, color y tamaño para Logseq",
|
||||||
|
"main": "index.html",
|
||||||
|
"author": "MonitorDevs",
|
||||||
|
"license": "MIT",
|
||||||
|
"scripts": {
|
||||||
|
"extract": "node scripts/extract-metadata.js",
|
||||||
|
"validate": "node scripts/validate-styles.js",
|
||||||
|
"build": "npm run extract && npm run validate && node build-icons-json.js",
|
||||||
|
"update": "node update-styles.js",
|
||||||
|
"verify": "node verify-styles.js",
|
||||||
|
"build:sample": "node build-icons-json.js --sample",
|
||||||
|
"dev": "echo '✅ Plugin listo para Logseq'",
|
||||||
|
"clean": "rm -rf assets/processed assets/icons.json assets/dynamic-styles.css assets/custom-styles.css",
|
||||||
|
"reset": "npm run clean && npm run build"
|
||||||
|
},
|
||||||
|
"dependencies": {},
|
||||||
|
"devDependencies": {},
|
||||||
|
"logseq": {
|
||||||
|
"id": "logseq-fontawesome-pro",
|
||||||
|
"title": "FontAwesome Pro",
|
||||||
|
"icon": "./icon.png",
|
||||||
|
"description": "Íconos FontAwesome 6 Pro con todos los estilos, color y tamaño"
|
||||||
|
}
|
||||||
|
}
|
||||||
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
|
||||||
|
};
|
||||||
0
slash-commands.js
Normal file
0
slash-commands.js
Normal file
419
update-styles.js
Normal file
419
update-styles.js
Normal file
@@ -0,0 +1,419 @@
|
|||||||
|
#!/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();
|
||||||
148
verify-styles.js
Normal file
148
verify-styles.js
Normal file
@@ -0,0 +1,148 @@
|
|||||||
|
const fs = require('fs');
|
||||||
|
const path = require('path');
|
||||||
|
|
||||||
|
console.log('🔍 Verificador de Estilos FontAwesome Pro\n');
|
||||||
|
console.log('='.repeat(60));
|
||||||
|
|
||||||
|
// Configuración
|
||||||
|
const WEBFONTS_DIR = path.join(__dirname, 'assets', 'fontawesome', 'webfonts');
|
||||||
|
const METADATA_DIR = path.join(__dirname, 'assets', 'fontawesome', 'metadata');
|
||||||
|
const CSS_DIR = path.join(__dirname, 'assets', 'fontawesome', 'css');
|
||||||
|
|
||||||
|
// Archivos requeridos para cada estilo
|
||||||
|
const REQUIRED_FILES = {
|
||||||
|
'solid': ['fa-solid-900.woff2', 'fa-solid-900.ttf'],
|
||||||
|
'regular': ['fa-regular-400.woff2', 'fa-regular-400.ttf'],
|
||||||
|
'light': ['fa-light-300.woff2', 'fa-light-300.ttf'],
|
||||||
|
'thin': ['fa-thin-100.woff2', 'fa-thin-100.ttf'],
|
||||||
|
'duotone': ['fa-duotone-900.woff2', 'fa-duotone-900.ttf'],
|
||||||
|
'sharp-solid': ['fa-sharp-solid-900.woff2', 'fa-sharp-solid-900.ttf'],
|
||||||
|
'sharp-regular': ['fa-sharp-regular-400.woff2', 'fa-sharp-regular-400.ttf'],
|
||||||
|
'sharp-light': ['fa-sharp-light-300.woff2', 'fa-sharp-light-300.ttf'],
|
||||||
|
'sharp-thin': ['fa-sharp-thin-100.woff2', 'fa-sharp-thin-100.ttf'],
|
||||||
|
'sharp-duotone': ['fa-sharp-duotone-900.woff2', 'fa-sharp-duotone-900.ttf'],
|
||||||
|
'brands': ['fa-brands-400.woff2', 'fa-brands-400.ttf']
|
||||||
|
};
|
||||||
|
|
||||||
|
// Verificar directorios
|
||||||
|
console.log('\n📁 Verificando directorios...');
|
||||||
|
const directories = [
|
||||||
|
{ name: 'webfonts', path: WEBFONTS_DIR },
|
||||||
|
{ name: 'metadata', path: METADATA_DIR },
|
||||||
|
{ name: 'css', path: CSS_DIR }
|
||||||
|
];
|
||||||
|
|
||||||
|
directories.forEach(dir => {
|
||||||
|
if (fs.existsSync(dir.path)) {
|
||||||
|
console.log(` ✅ ${dir.name}: Existe`);
|
||||||
|
const files = fs.readdirSync(dir.path);
|
||||||
|
console.log(` Archivos: ${files.length}`);
|
||||||
|
} else {
|
||||||
|
console.log(` ❌ ${dir.name}: No existe`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Verificar archivos de fuentes
|
||||||
|
console.log('\n🎨 Verificando archivos de fuentes...');
|
||||||
|
let totalFound = 0;
|
||||||
|
let totalRequired = 0;
|
||||||
|
|
||||||
|
Object.entries(REQUIRED_FILES).forEach(([style, files]) => {
|
||||||
|
console.log(`\n ${style}:`);
|
||||||
|
|
||||||
|
let foundCount = 0;
|
||||||
|
files.forEach(file => {
|
||||||
|
const filePath = path.join(WEBFONTS_DIR, file);
|
||||||
|
if (fs.existsSync(filePath)) {
|
||||||
|
console.log(` ✅ ${file}`);
|
||||||
|
foundCount++;
|
||||||
|
totalFound++;
|
||||||
|
} else {
|
||||||
|
console.log(` ❌ ${file} (Faltante)`);
|
||||||
|
}
|
||||||
|
totalRequired++;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (foundCount === files.length) {
|
||||||
|
console.log(` 🎉 ${style} completo`);
|
||||||
|
} else if (foundCount > 0) {
|
||||||
|
console.log(` ⚠️ ${style} parcial (${foundCount}/${files.length})`);
|
||||||
|
} else {
|
||||||
|
console.log(` ❌ ${style} no disponible`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Verificar metadata
|
||||||
|
console.log('\n📊 Verificando metadata...');
|
||||||
|
const metadataPath = path.join(METADATA_DIR, 'icons.json');
|
||||||
|
if (fs.existsSync(metadataPath)) {
|
||||||
|
try {
|
||||||
|
const metadata = JSON.parse(fs.readFileSync(metadataPath, 'utf8'));
|
||||||
|
const iconCount = Object.keys(metadata).length;
|
||||||
|
console.log(` ✅ Metadata válido`);
|
||||||
|
console.log(` Íconos: ${iconCount}`);
|
||||||
|
|
||||||
|
// Verificar si hay estilos sharp en metadata
|
||||||
|
const sampleIcon = Object.values(metadata)[0];
|
||||||
|
if (sampleIcon && sampleIcon.styles) {
|
||||||
|
const hasSharp = sampleIcon.styles.some(s =>
|
||||||
|
s.toLowerCase().includes('sharp')
|
||||||
|
);
|
||||||
|
console.log(` Estilos Sharp: ${hasSharp ? 'Sí' : 'No'}`);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log(` ❌ Error en metadata: ${error.message}`);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.log(' ❌ Metadata no encontrado');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verificar archivos generados
|
||||||
|
console.log('\n🛠️ Verificando archivos generados...');
|
||||||
|
const generatedFiles = [
|
||||||
|
{ name: 'Base de datos', path: path.join(__dirname, 'assets', 'icons.json') },
|
||||||
|
{ name: 'CSS Dinámico', path: path.join(__dirname, 'assets', 'dynamic-styles.css') },
|
||||||
|
{ name: 'CSS Personalizado', path: path.join(__dirname, 'assets', 'custom-styles.css') }
|
||||||
|
];
|
||||||
|
|
||||||
|
generatedFiles.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 generado`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Resumen
|
||||||
|
console.log('\n' + '='.repeat(60));
|
||||||
|
console.log('📈 RESUMEN FINAL');
|
||||||
|
console.log('='.repeat(60));
|
||||||
|
|
||||||
|
const percentage = ((totalFound / totalRequired) * 100).toFixed(1);
|
||||||
|
console.log(`\nArchivos de fuentes: ${totalFound}/${totalRequired} (${percentage}%)`);
|
||||||
|
|
||||||
|
if (percentage >= 90) {
|
||||||
|
console.log('✅ Excelente! Tienes casi todos los estilos.');
|
||||||
|
} else if (percentage >= 50) {
|
||||||
|
console.log('⚠️ Tienes la mayoría de estilos básicos.');
|
||||||
|
} else {
|
||||||
|
console.log('❌ Faltan muchos estilos. Considera actualizar FontAwesome Pro.');
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('\n🎯 RECOMENDACIONES:');
|
||||||
|
if (totalFound < totalRequired) {
|
||||||
|
console.log(' 1. Descarga la versión completa de FontAwesome 6 Pro');
|
||||||
|
console.log(' 2. Copia todos los archivos de webfonts/');
|
||||||
|
console.log(' 3. Ejecuta: npm run build');
|
||||||
|
} else {
|
||||||
|
console.log(' 1. ¡Todo está listo!');
|
||||||
|
console.log(' 2. Ejecuta: npm run build (si no lo has hecho)');
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('\n🚀 COMANDOS DISPONIBLES:');
|
||||||
|
console.log(' • npm run build - Generar/actualizar base de datos');
|
||||||
|
console.log(' • npm run update - Verificar y actualizar estilos');
|
||||||
|
console.log(' • npm run verify - Verificar archivos (este comando)');
|
||||||
|
|
||||||
|
console.log('\n' + '='.repeat(60));
|
||||||
Reference in New Issue
Block a user