Primera versión del plugin

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

63
README.md Normal file
View 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**.
![FontAwesome Pro Plugin](https://img.shields.io/badge/Version-2.0.0-blue)
![FontAwesome 6 Pro](https://img.shields.io/badge/FontAwesome-6_Pro-528DD7)
![Logseq Plugin](https://img.shields.io/badge/Logseq-Plugin-green)
## ✨ 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
View 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

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

105
assets/icons.json Normal file
View 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
}
]
}

View 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"
}
}

File diff suppressed because it is too large Load Diff

View 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"
}
}
}
}

View 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"
}
}

View 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"
}
}
}
}

View 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

File diff suppressed because it is too large Load Diff

View 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"
}
}
}
}

View 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
View 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
View File

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

BIN
icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

2560
index.html Normal file

File diff suppressed because it is too large Load Diff

14
package-lock.json generated Normal file
View 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
View 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
View 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
View 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
View File

419
update-styles.js Normal file
View 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
View 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));