versacompiler 2.1.0 → 2.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/compiler/compile.js +2520 -25
- package/dist/compiler/error-reporter.js +467 -38
- package/dist/compiler/linter.js +72 -1
- package/dist/compiler/minify.js +272 -1
- package/dist/compiler/minifyTemplate.js +230 -1
- package/dist/compiler/module-resolution-optimizer.js +888 -1
- package/dist/compiler/parser.js +336 -1
- package/dist/compiler/performance-monitor.js +204 -56
- package/dist/compiler/tailwindcss.js +39 -1
- package/dist/compiler/transform-optimizer.js +392 -1
- package/dist/compiler/transformTStoJS.js +16 -1
- package/dist/compiler/transforms.js +554 -1
- package/dist/compiler/typescript-compiler.js +172 -2
- package/dist/compiler/typescript-error-parser.js +281 -10
- package/dist/compiler/typescript-manager.js +304 -2
- package/dist/compiler/typescript-sync-validator.js +295 -31
- package/dist/compiler/typescript-worker-pool.js +936 -1
- package/dist/compiler/typescript-worker-thread.cjs +466 -22
- package/dist/compiler/typescript-worker.js +339 -1
- package/dist/compiler/vuejs.js +396 -37
- package/dist/hrm/VueHRM.js +359 -1
- package/dist/hrm/errorScreen.js +83 -1
- package/dist/hrm/getInstanciaVue.js +313 -1
- package/dist/hrm/initHRM.js +586 -1
- package/dist/main.js +353 -7
- package/dist/servicios/browserSync.js +589 -2
- package/dist/servicios/file-watcher.js +425 -4
- package/dist/servicios/logger.js +63 -3
- package/dist/servicios/readConfig.js +399 -53
- package/dist/utils/excluded-modules.js +37 -1
- package/dist/utils/module-resolver.js +552 -1
- package/dist/utils/promptUser.js +48 -2
- package/dist/utils/proxyValidator.js +68 -1
- package/dist/utils/resolve-bin.js +58 -1
- package/dist/utils/utils.js +21 -1
- package/dist/utils/vue-types-setup.js +435 -241
- package/dist/wrappers/eslint-node.js +1 -1
- package/dist/wrappers/oxlint-node.js +122 -1
- package/dist/wrappers/tailwind-node.js +94 -1
- package/package.json +109 -104
package/dist/compiler/minify.js
CHANGED
|
@@ -1 +1,272 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { minify } from 'oxc-minify';
|
|
3
|
+
import { minifyTemplate } from './minifyTemplate.js';
|
|
4
|
+
class MinificationCache {
|
|
5
|
+
static instance;
|
|
6
|
+
cache = new Map();
|
|
7
|
+
MAX_CACHE_SIZE = 100; // Máximo archivos minificados en cache
|
|
8
|
+
MAX_CACHE_MEMORY = 20 * 1024 * 1024; // 20MB límite
|
|
9
|
+
CACHE_TTL = 30 * 60 * 1000; // 30 minutos
|
|
10
|
+
currentMemoryUsage = 0;
|
|
11
|
+
// Métricas
|
|
12
|
+
cacheHits = 0;
|
|
13
|
+
cacheMisses = 0;
|
|
14
|
+
totalMinifications = 0;
|
|
15
|
+
totalOriginalSize = 0;
|
|
16
|
+
totalMinifiedSize = 0;
|
|
17
|
+
static getInstance() {
|
|
18
|
+
if (!MinificationCache.instance) {
|
|
19
|
+
MinificationCache.instance = new MinificationCache();
|
|
20
|
+
}
|
|
21
|
+
return MinificationCache.instance;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Genera un hash del contenido y opciones de minificación
|
|
25
|
+
*/
|
|
26
|
+
generateCacheKey(data, options) {
|
|
27
|
+
const content = `${data}||${JSON.stringify(options)}`;
|
|
28
|
+
return createHash('sha256').update(content).digest('hex');
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Obtiene resultado de minificación desde cache o lo genera
|
|
32
|
+
*/
|
|
33
|
+
async getOrMinify(data, filename, options) {
|
|
34
|
+
this.totalMinifications++;
|
|
35
|
+
const cacheKey = this.generateCacheKey(data, options);
|
|
36
|
+
// Verificar cache
|
|
37
|
+
const cached = this.cache.get(cacheKey);
|
|
38
|
+
if (cached && Date.now() - cached.timestamp < this.CACHE_TTL) {
|
|
39
|
+
// Actualizar timestamp de uso (LRU)
|
|
40
|
+
cached.timestamp = Date.now();
|
|
41
|
+
this.cacheHits++;
|
|
42
|
+
return {
|
|
43
|
+
code: cached.minifiedCode,
|
|
44
|
+
error: null,
|
|
45
|
+
cached: true,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
// Cache miss - minificar código
|
|
49
|
+
this.cacheMisses++;
|
|
50
|
+
const originalSize = data.length;
|
|
51
|
+
try {
|
|
52
|
+
const result = await minify(filename, data, options);
|
|
53
|
+
// Si el código de entrada no estaba vacío pero el resultado sí,
|
|
54
|
+
// retornar código original sin minificar con advertencia
|
|
55
|
+
if (data.trim() && !result.code.trim()) {
|
|
56
|
+
console.warn(`⚠️ Minificación fallida para ${filename}, usando código original`);
|
|
57
|
+
return {
|
|
58
|
+
code: data, // Retornar código original
|
|
59
|
+
error: null, // No es un error crítico
|
|
60
|
+
cached: false,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
const minifiedSize = result.code.length;
|
|
64
|
+
// Cachear resultado exitoso
|
|
65
|
+
this.addToCache(cacheKey, {
|
|
66
|
+
contentHash: cacheKey,
|
|
67
|
+
options,
|
|
68
|
+
minifiedCode: result.code,
|
|
69
|
+
timestamp: Date.now(),
|
|
70
|
+
originalSize,
|
|
71
|
+
minifiedSize,
|
|
72
|
+
});
|
|
73
|
+
// Actualizar métricas globales
|
|
74
|
+
this.totalOriginalSize += originalSize;
|
|
75
|
+
this.totalMinifiedSize += minifiedSize;
|
|
76
|
+
return {
|
|
77
|
+
code: result.code,
|
|
78
|
+
error: null,
|
|
79
|
+
cached: false,
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
catch (error) {
|
|
83
|
+
// En caso de excepción, retornar código original con advertencia
|
|
84
|
+
console.warn(`⚠️ Error al minificar ${filename}: ${error instanceof Error ? error.message : String(error)}`);
|
|
85
|
+
console.warn(` Usando código original sin minificar`);
|
|
86
|
+
return {
|
|
87
|
+
code: data, // Retornar código original
|
|
88
|
+
error: null, // No propagar el error
|
|
89
|
+
cached: false,
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Añade resultado al cache con gestión de memoria
|
|
95
|
+
*/
|
|
96
|
+
addToCache(cacheKey, entry) {
|
|
97
|
+
try {
|
|
98
|
+
const entrySize = entry.originalSize + entry.minifiedSize;
|
|
99
|
+
// Aplicar políticas de eviction si es necesario
|
|
100
|
+
this.evictIfNeeded(entrySize);
|
|
101
|
+
this.cache.set(cacheKey, entry);
|
|
102
|
+
this.currentMemoryUsage += entrySize;
|
|
103
|
+
}
|
|
104
|
+
catch (error) {
|
|
105
|
+
console.warn('[MinificationCache] Error cacheando minificación:', error);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Aplica políticas de eviction LRU si es necesario
|
|
110
|
+
*/
|
|
111
|
+
evictIfNeeded(newEntrySize) {
|
|
112
|
+
// Verificar límite de entradas
|
|
113
|
+
while (this.cache.size >= this.MAX_CACHE_SIZE) {
|
|
114
|
+
this.evictLRU();
|
|
115
|
+
}
|
|
116
|
+
// Verificar límite de memoria
|
|
117
|
+
while (this.currentMemoryUsage + newEntrySize > this.MAX_CACHE_MEMORY &&
|
|
118
|
+
this.cache.size > 0) {
|
|
119
|
+
this.evictLRU();
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Elimina la entrada menos recientemente usada
|
|
124
|
+
*/
|
|
125
|
+
evictLRU() {
|
|
126
|
+
let oldestKey = '';
|
|
127
|
+
let oldestTime = Infinity;
|
|
128
|
+
for (const [key, entry] of this.cache) {
|
|
129
|
+
if (entry.timestamp < oldestTime) {
|
|
130
|
+
oldestTime = entry.timestamp;
|
|
131
|
+
oldestKey = key;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
if (oldestKey) {
|
|
135
|
+
const entry = this.cache.get(oldestKey);
|
|
136
|
+
if (entry) {
|
|
137
|
+
this.currentMemoryUsage -=
|
|
138
|
+
entry.originalSize + entry.minifiedSize;
|
|
139
|
+
this.cache.delete(oldestKey);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Limpia entradas expiradas
|
|
145
|
+
*/
|
|
146
|
+
cleanExpired() {
|
|
147
|
+
const now = Date.now();
|
|
148
|
+
for (const [key, entry] of this.cache.entries()) {
|
|
149
|
+
if (now - entry.timestamp > this.CACHE_TTL) {
|
|
150
|
+
this.currentMemoryUsage -=
|
|
151
|
+
entry.originalSize + entry.minifiedSize;
|
|
152
|
+
this.cache.delete(key);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Obtiene estadísticas del cache
|
|
158
|
+
*/
|
|
159
|
+
getStats() {
|
|
160
|
+
const hitRate = this.totalMinifications > 0
|
|
161
|
+
? Math.round((this.cacheHits / this.totalMinifications) * 100)
|
|
162
|
+
: 0;
|
|
163
|
+
const avgCompressionRatio = this.totalOriginalSize > 0
|
|
164
|
+
? Math.round(((this.totalOriginalSize - this.totalMinifiedSize) /
|
|
165
|
+
this.totalOriginalSize) *
|
|
166
|
+
100)
|
|
167
|
+
: 0;
|
|
168
|
+
return {
|
|
169
|
+
cacheHits: this.cacheHits,
|
|
170
|
+
cacheMisses: this.cacheMisses,
|
|
171
|
+
hitRate,
|
|
172
|
+
totalMinifications: this.totalMinifications,
|
|
173
|
+
cacheSize: this.cache.size,
|
|
174
|
+
maxCacheSize: this.MAX_CACHE_SIZE,
|
|
175
|
+
memoryUsage: this.currentMemoryUsage,
|
|
176
|
+
maxMemoryUsage: this.MAX_CACHE_MEMORY,
|
|
177
|
+
totalOriginalSize: this.totalOriginalSize,
|
|
178
|
+
totalMinifiedSize: this.totalMinifiedSize,
|
|
179
|
+
avgCompressionRatio,
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Limpia todo el cache
|
|
184
|
+
*/
|
|
185
|
+
clear() {
|
|
186
|
+
this.cache.clear();
|
|
187
|
+
this.currentMemoryUsage = 0;
|
|
188
|
+
this.cacheHits = 0;
|
|
189
|
+
this.cacheMisses = 0;
|
|
190
|
+
this.totalMinifications = 0;
|
|
191
|
+
this.totalOriginalSize = 0;
|
|
192
|
+
this.totalMinifiedSize = 0;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
// Instancia global del cache de minificación
|
|
196
|
+
const minificationCache = MinificationCache.getInstance();
|
|
197
|
+
/**
|
|
198
|
+
* Minifica el codigo JavaScript usando opciones especificas.
|
|
199
|
+
*
|
|
200
|
+
* @param {string} data - The JavaScript code to be minified.
|
|
201
|
+
* @param {string} filename - The name of the file containing the JavaScript code.
|
|
202
|
+
* @param {boolean} isProd - Indica si está en modo producción.
|
|
203
|
+
* @returns {Promise<Object>} The result of the minification process.
|
|
204
|
+
*/
|
|
205
|
+
export const minifyJS = async (data, filename, isProd = true) => {
|
|
206
|
+
try {
|
|
207
|
+
const options = {
|
|
208
|
+
compress: {
|
|
209
|
+
target: 'es2020',
|
|
210
|
+
},
|
|
211
|
+
mangle: {
|
|
212
|
+
toplevel: true,
|
|
213
|
+
debug: !isProd,
|
|
214
|
+
},
|
|
215
|
+
codegen: {
|
|
216
|
+
removeWhitespace: true,
|
|
217
|
+
},
|
|
218
|
+
sourcemap: !isProd,
|
|
219
|
+
};
|
|
220
|
+
const result = await minificationCache.getOrMinify(data, filename, options);
|
|
221
|
+
return { code: result.code, error: result.error };
|
|
222
|
+
}
|
|
223
|
+
catch (error) {
|
|
224
|
+
return { error, code: '' };
|
|
225
|
+
}
|
|
226
|
+
};
|
|
227
|
+
// ✨ NUEVAS FUNCIONES: Exportar funcionalidades del cache de minificación para uso externo
|
|
228
|
+
export const getMinificationCacheStats = () => {
|
|
229
|
+
return minificationCache.getStats();
|
|
230
|
+
};
|
|
231
|
+
export const clearMinificationCache = () => {
|
|
232
|
+
minificationCache.clear();
|
|
233
|
+
};
|
|
234
|
+
export const cleanExpiredMinificationCache = () => {
|
|
235
|
+
minificationCache.cleanExpired();
|
|
236
|
+
};
|
|
237
|
+
/**
|
|
238
|
+
* ✨ Minifica templates HTML/Vue ANTES de minificar JavaScript
|
|
239
|
+
* Esta función combina la minificación de templates con la minificación JS en el orden correcto:
|
|
240
|
+
* 1. Primero minifica templates HTML usando minify-html-literals
|
|
241
|
+
* 2. Luego minifica el JavaScript resultante usando oxc-minify
|
|
242
|
+
*
|
|
243
|
+
* @param {string} data - El código a minificar (puede contener templates HTML)
|
|
244
|
+
* @param {string} filename - El nombre del archivo
|
|
245
|
+
* @param {boolean} isProd - Indica si está en modo producción
|
|
246
|
+
* @returns {Promise<Object>} El resultado de la minificación combinada { code, error }
|
|
247
|
+
*/
|
|
248
|
+
export const minifyWithTemplates = async (data, filename, isProd = true) => {
|
|
249
|
+
try {
|
|
250
|
+
// PASO 1: Minificar templates HTML primero
|
|
251
|
+
const templateResult = minifyTemplate(data, filename);
|
|
252
|
+
// Si hay error en la minificación de templates, pero tenemos código, continuar
|
|
253
|
+
if (templateResult.error && !templateResult.code) {
|
|
254
|
+
const errorMsg = templateResult.error instanceof Error
|
|
255
|
+
? templateResult.error.message
|
|
256
|
+
: String(templateResult.error);
|
|
257
|
+
return {
|
|
258
|
+
code: '',
|
|
259
|
+
error: new Error(`Template minification failed: ${errorMsg}`),
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
// PASO 2: Minificar el JavaScript resultante
|
|
263
|
+
return await minifyJS(templateResult.code, filename, isProd);
|
|
264
|
+
}
|
|
265
|
+
catch (error) {
|
|
266
|
+
return {
|
|
267
|
+
error: error instanceof Error ? error : new Error(String(error)),
|
|
268
|
+
code: '',
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
};
|
|
272
|
+
//# sourceMappingURL=minify.js.map
|
|
@@ -1 +1,230 @@
|
|
|
1
|
-
import{minifyHTMLLiterals
|
|
1
|
+
import { minifyHTMLLiterals } from 'minify-html-literals';
|
|
2
|
+
const defaultMinifyOptions = {
|
|
3
|
+
// Opciones esenciales para componentes Vue
|
|
4
|
+
caseSensitive: true, // Preserva mayúsculas/minúsculas en nombres de componentes
|
|
5
|
+
keepClosingSlash: true, // ✅ MANTIENE el slash de cierre <component />
|
|
6
|
+
collapseWhitespace: true, // Elimina espacios en blanco
|
|
7
|
+
removeComments: true, // Elimina comentarios HTML
|
|
8
|
+
minifyCSS: true, // ✅ Minifica CSS inline (importante para estilos Vue)
|
|
9
|
+
minifyJS: true, // Minifica JS inline en atributos
|
|
10
|
+
// Configuración para frameworks (Vue/React)
|
|
11
|
+
conservativeCollapse: false, // Colapso más agresivo de espacios
|
|
12
|
+
preserveLineBreaks: false, // No preservar saltos de línea
|
|
13
|
+
// Importante: NO remover atributos necesarios de Vue
|
|
14
|
+
removeAttributeQuotes: false, // NO quitar comillas (Vue las necesita en :prop y @event)
|
|
15
|
+
removeEmptyAttributes: false, // NO quitar atributos vacíos (Vue los usa)
|
|
16
|
+
removeRedundantAttributes: false, // NO quitar atributos redundantes
|
|
17
|
+
// Optimizaciones seguras
|
|
18
|
+
removeScriptTypeAttributes: true, // Quitar type="text/javascript"
|
|
19
|
+
removeStyleLinkTypeAttributes: true, // Quitar type="text/css"
|
|
20
|
+
useShortDoctype: true, // Usar <!DOCTYPE html> corto
|
|
21
|
+
};
|
|
22
|
+
// Marcadores únicos para identificar tags temporales
|
|
23
|
+
const TEMP_TAG_MARKER = '__VERSA_TEMP__';
|
|
24
|
+
const TEMP_HTML_TAG = `${TEMP_TAG_MARKER}`;
|
|
25
|
+
const TEMP_CSS_TAG = `${TEMP_TAG_MARKER}css`;
|
|
26
|
+
/**
|
|
27
|
+
* Detecta el tipo de contenido dentro de un template string
|
|
28
|
+
* @param content - Contenido del template string
|
|
29
|
+
* @returns 'css' | 'html' | 'mixed' | 'unknown'
|
|
30
|
+
*/
|
|
31
|
+
const detectContentType = (content) => {
|
|
32
|
+
// Remover template expressions ${...} para análisis más preciso
|
|
33
|
+
const cleanContent = content.replace(/\$\{[^}]+\}/g, '');
|
|
34
|
+
// Detectar CSS: Buscar selectores y propiedades CSS
|
|
35
|
+
const hasCSSBraces = cleanContent.includes('{') && cleanContent.includes('}');
|
|
36
|
+
const hasCSSProperties = /[a-z-]+\s*:\s*[^;]+;/.test(cleanContent);
|
|
37
|
+
const hasMediaQueries = /@media|@keyframes|@import/.test(cleanContent);
|
|
38
|
+
const isCSSLike = hasCSSBraces && (hasCSSProperties || hasMediaQueries);
|
|
39
|
+
// Detectar código TypeScript (para evitar falsos positivos)
|
|
40
|
+
const hasTypeScriptSyntax = /\b(function|const|let|var|interface|type|declare|export|import)\b/.test(cleanContent);
|
|
41
|
+
const hasTypeScriptGenerics = /<[A-Z][^>]*>|<\{/.test(cleanContent); // <T>, <T extends Foo>, <{}>
|
|
42
|
+
// Si parece código TypeScript, no intentar minificar
|
|
43
|
+
if (hasTypeScriptSyntax && hasTypeScriptGenerics) {
|
|
44
|
+
return 'unknown';
|
|
45
|
+
}
|
|
46
|
+
// Detectar HTML: Buscar tags HTML REALES (no genéricos TypeScript)
|
|
47
|
+
// Tags HTML comunes para evitar falsos positivos
|
|
48
|
+
const hasHTMLElements = /<(div|span|p|a|button|input|form|table|ul|ol|li|h[1-6]|section|article|nav|header|footer|main|aside|style|script)[^>]*>/i.test(cleanContent);
|
|
49
|
+
const hasHTMLClosingTags = /<\/(div|span|p|a|button|input|form|table|ul|ol|li|h[1-6]|section|article|nav|header|footer|main|aside|style|script)>/i.test(cleanContent);
|
|
50
|
+
const isHTMLLike = hasHTMLElements || hasHTMLClosingTags;
|
|
51
|
+
// Detectar contenido mixto (CSS + HTML juntos)
|
|
52
|
+
if (isCSSLike && isHTMLLike) {
|
|
53
|
+
return 'mixed';
|
|
54
|
+
}
|
|
55
|
+
if (isCSSLike) {
|
|
56
|
+
return 'css';
|
|
57
|
+
}
|
|
58
|
+
if (isHTMLLike) {
|
|
59
|
+
return 'html';
|
|
60
|
+
}
|
|
61
|
+
return 'unknown';
|
|
62
|
+
};
|
|
63
|
+
/**
|
|
64
|
+
* Detecta template strings sin tags y les agrega tags temporales según su contenido
|
|
65
|
+
* @param code - Código fuente a procesar
|
|
66
|
+
* @returns Código con tags temporales agregados
|
|
67
|
+
*/
|
|
68
|
+
const detectAndTagTemplateStrings = (code) => {
|
|
69
|
+
try {
|
|
70
|
+
// Patrón para detectar template strings sin tag `` o css``
|
|
71
|
+
// Busca: = ` ... ` o : ` ... ` pero NO ` o css`
|
|
72
|
+
// Negative lookbehind: (?<!html|css|TEMP_TAG_MARKER)
|
|
73
|
+
const templateStringPattern = new RegExp(`(?<!html|css|${TEMP_TAG_MARKER.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')})\\\`([^\`]+?)\\\``, 'gs');
|
|
74
|
+
return code.replace(templateStringPattern, (match, content) => {
|
|
75
|
+
// No procesar si ya tiene un tag (doble verificación)
|
|
76
|
+
if (match.includes('`') ||
|
|
77
|
+
match.includes('css`') ||
|
|
78
|
+
match.includes(TEMP_TAG_MARKER)) {
|
|
79
|
+
return match;
|
|
80
|
+
}
|
|
81
|
+
// No procesar template strings vacíos o muy cortos (probablemente strings simples)
|
|
82
|
+
if (content.trim().length < 10) {
|
|
83
|
+
return match;
|
|
84
|
+
}
|
|
85
|
+
// Detectar tipo de contenido
|
|
86
|
+
const contentType = detectContentType(content);
|
|
87
|
+
// Solo agregar tag si es CSS o HTML (contenido minificable)
|
|
88
|
+
if (contentType === 'css') {
|
|
89
|
+
return `${TEMP_CSS_TAG}\`${content}\``;
|
|
90
|
+
}
|
|
91
|
+
else if (contentType === 'html' || contentType === 'mixed') {
|
|
92
|
+
return `${TEMP_HTML_TAG}\`${content}\``;
|
|
93
|
+
}
|
|
94
|
+
// Si es unknown o JavaScript, no agregar tag
|
|
95
|
+
return match;
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
catch (error) {
|
|
99
|
+
console.warn('[MinifyTemplate] Error detectando template strings:', error);
|
|
100
|
+
return code;
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
/**
|
|
104
|
+
* Remueve los tags temporales agregados por detectAndTagTemplateStrings
|
|
105
|
+
* @param code - Código con tags temporales
|
|
106
|
+
* @returns Código limpio sin tags temporales
|
|
107
|
+
*/
|
|
108
|
+
const removeTemporaryTags = (code) => {
|
|
109
|
+
try {
|
|
110
|
+
// Remover tags temporales: __VERSA_TEMP__` -> `
|
|
111
|
+
const tempHtmlPattern = new RegExp(`${TEMP_HTML_TAG}\\\``, 'g');
|
|
112
|
+
const tempCssPattern = new RegExp(`${TEMP_CSS_TAG}\\\``, 'g');
|
|
113
|
+
return code.replace(tempHtmlPattern, '`').replace(tempCssPattern, '`');
|
|
114
|
+
}
|
|
115
|
+
catch (error) {
|
|
116
|
+
console.warn('[MinifyTemplate] Error removiendo tags temporales:', error);
|
|
117
|
+
return code;
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
/**
|
|
121
|
+
* Minifica CSS dentro de tagged templates
|
|
122
|
+
* Ahora soporta múltiples formatos: =`...`, :`...`, =css`...`, etc.
|
|
123
|
+
*/
|
|
124
|
+
const minifyCSS = (code) => {
|
|
125
|
+
try {
|
|
126
|
+
// Patrón expandido para detectar diferentes contextos:
|
|
127
|
+
// - Asignaciones: =` o =css`
|
|
128
|
+
// - Propiedades de objeto: : ` o : css`
|
|
129
|
+
// - Template strings standalone: ` o css`
|
|
130
|
+
// - Tags temporales: __VERSA_TEMP__css` o __VERSA_TEMP__`
|
|
131
|
+
const cssPattern = /(?:=|:|\s)(html|css|__VERSA_TEMP__html|__VERSA_TEMP__css)?`([^`]+)`/g;
|
|
132
|
+
return code.replace(cssPattern, (match, tag, content) => {
|
|
133
|
+
const looksLikeCSS = content.includes('{') &&
|
|
134
|
+
content.includes('}') &&
|
|
135
|
+
/[a-z-]+\s*:\s*[^;]+;/.test(content);
|
|
136
|
+
// Si no tiene tag, no procesar aquí (se procesará en detectAndTagTemplateStrings)
|
|
137
|
+
if (!tag && !looksLikeCSS) {
|
|
138
|
+
return match;
|
|
139
|
+
}
|
|
140
|
+
// Solo minificar si parece ser CSS (contiene { y })
|
|
141
|
+
if (content.includes('{') && content.includes('}')) {
|
|
142
|
+
// Minificar CSS: remover espacios innecesarios
|
|
143
|
+
const minified = content
|
|
144
|
+
.replace(/\/\*[\s\S]*?\*\//g, '') // Remover comentarios CSS
|
|
145
|
+
.replace(/\s+/g, ' ') // Normalizar múltiples espacios a uno
|
|
146
|
+
.replace(/\s*{\s*/g, '{') // Remover espacios alrededor de {
|
|
147
|
+
.replace(/\s*}\s*/g, '}') // Remover espacios alrededor de }
|
|
148
|
+
.replace(/\s*:\s*/g, ':') // Remover espacios alrededor de :
|
|
149
|
+
.replace(/\s*;\s*/g, ';') // Remover espacios alrededor de ;
|
|
150
|
+
.replace(/;\s*}/g, '}') // Remover ; antes de }
|
|
151
|
+
.replace(/,\s*/g, ',') // Remover espacios después de ,
|
|
152
|
+
.replace(/\s*>\s*/g, '>') // Remover espacios en selectores >
|
|
153
|
+
.replace(/\s*\+\s*/g, '+') // Remover espacios en selectores +
|
|
154
|
+
.replace(/\s*~\s*/g, '~') // Remover espacios en selectores ~
|
|
155
|
+
.trim();
|
|
156
|
+
// Preservar el prefijo original (=, :, espacio)
|
|
157
|
+
const prefix = match.charAt(0);
|
|
158
|
+
const tagPart = tag || ''; // Si no hay tag, usar string vacío
|
|
159
|
+
return `${prefix}${tagPart}\`${minified}\``;
|
|
160
|
+
}
|
|
161
|
+
// Si no es CSS, devolver sin cambios
|
|
162
|
+
return match;
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
catch (error) {
|
|
166
|
+
console.warn('[MinifyTemplate] Error minificando CSS:', error);
|
|
167
|
+
return code;
|
|
168
|
+
}
|
|
169
|
+
};
|
|
170
|
+
const minifyTemplate = (data, fileName) => {
|
|
171
|
+
try {
|
|
172
|
+
// ⚠️ SKIP: Archivos de definiciones de tipos TypeScript
|
|
173
|
+
// Estos archivos NO contienen template strings HTML/CSS para minificar
|
|
174
|
+
if (fileName.endsWith('.d.ts') ||
|
|
175
|
+
fileName.includes('types') ||
|
|
176
|
+
fileName.includes('type-')) {
|
|
177
|
+
return { code: data, error: null };
|
|
178
|
+
}
|
|
179
|
+
// ⚠️ SKIP: Archivos sin backticks (no tienen template strings)
|
|
180
|
+
if (!data.includes('`')) {
|
|
181
|
+
return { code: data, error: null };
|
|
182
|
+
}
|
|
183
|
+
// ✨ NUEVO FLUJO DE TRES PASOS:
|
|
184
|
+
// PASO 1: Detectar y etiquetar template strings sin tags
|
|
185
|
+
// Esto agrega tags temporales (__VERSA_TEMP__` o __VERSA_TEMP__css`)
|
|
186
|
+
// a template strings que contienen HTML o CSS pero no tienen tag
|
|
187
|
+
let code = detectAndTagTemplateStrings(data);
|
|
188
|
+
// PASO 2: Minificar CSS en tagged templates (`...` y css`...`)
|
|
189
|
+
// Esto incluye los tags temporales agregados en el paso 1
|
|
190
|
+
code = minifyCSS(code);
|
|
191
|
+
// PASO 3: Minificar templates HTML con minify-html-literals
|
|
192
|
+
// Esta librería procesa todos los template strings con tags `` y css``
|
|
193
|
+
// Solo procesar si realmente hay tags `` o css`` en el código
|
|
194
|
+
let minifiedCode = code;
|
|
195
|
+
if (code.includes('`') ||
|
|
196
|
+
code.includes('css`') ||
|
|
197
|
+
code.includes(TEMP_HTML_TAG) ||
|
|
198
|
+
code.includes(TEMP_CSS_TAG)) {
|
|
199
|
+
try {
|
|
200
|
+
const minified = minifyHTMLLiterals(code, {
|
|
201
|
+
fileName,
|
|
202
|
+
...defaultMinifyOptions,
|
|
203
|
+
});
|
|
204
|
+
if (minified && minified.code) {
|
|
205
|
+
minifiedCode = minified.code;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
catch (parseError) {
|
|
209
|
+
// Si minifyHTMLLiterals falla (ej: encuentra código TypeScript en vez de HTML),
|
|
210
|
+
// devolver el código sin minificar en lugar de fallar completamente
|
|
211
|
+
console.warn(`[MinifyTemplate] minifyHTMLLiterals falló para ${fileName}, usando código sin minificar:`, parseError instanceof Error
|
|
212
|
+
? parseError.message
|
|
213
|
+
: String(parseError));
|
|
214
|
+
// minifiedCode ya tiene el valor de code
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
// PASO 4: Remover tags temporales agregados en el paso 1
|
|
218
|
+
// Esto convierte __VERSA_TEMP__` de vuelta a ` para que el código
|
|
219
|
+
// final no contenga los marcadores temporales
|
|
220
|
+
const finalCode = removeTemporaryTags(minifiedCode);
|
|
221
|
+
return { code: finalCode, error: null };
|
|
222
|
+
}
|
|
223
|
+
catch (error) {
|
|
224
|
+
console.warn(`[MinifyTemplate] Error minificando plantilla ${fileName}:`, error);
|
|
225
|
+
return { code: data, error };
|
|
226
|
+
}
|
|
227
|
+
};
|
|
228
|
+
// ✨ Exportar funciones y configuración
|
|
229
|
+
export { defaultMinifyOptions, detectAndTagTemplateStrings, detectContentType, minifyTemplate, removeTemporaryTags, };
|
|
230
|
+
//# sourceMappingURL=minifyTemplate.js.map
|