@widergy/energy-ui 3.98.0 → 3.98.2
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/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
## [3.98.2](https://github.com/widergy/energy-ui/compare/v3.98.1...v3.98.2) (2025-08-12)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* [SFPE-483] UTDataCategory empty data ([#664](https://github.com/widergy/energy-ui/issues/664)) ([be73350](https://github.com/widergy/energy-ui/commit/be7335017612682e9b44a7950c6d9e0999427867))
|
|
7
|
+
|
|
8
|
+
## [3.98.1](https://github.com/widergy/energy-ui/compare/v3.98.0...v3.98.1) (2025-08-12)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Bug Fixes
|
|
12
|
+
|
|
13
|
+
* [PDI-149] fix on utils ([#663](https://github.com/widergy/energy-ui/issues/663)) ([a642070](https://github.com/widergy/energy-ui/commit/a642070e196b634ea54113c2140cf306b0cf8011))
|
|
14
|
+
|
|
1
15
|
# [3.98.0](https://github.com/widergy/energy-ui/compare/v3.97.0...v3.98.0) (2025-08-12)
|
|
2
16
|
|
|
3
17
|
|
|
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
6
6
|
exports.default = void 0;
|
|
7
7
|
var _propTypes = require("prop-types");
|
|
8
8
|
var _react = _interopRequireWildcard(require("react"));
|
|
9
|
+
var _isEmpty = _interopRequireDefault(require("lodash/isEmpty"));
|
|
9
10
|
var _WithTheme = _interopRequireDefault(require("../WithTheme"));
|
|
10
11
|
var _UTDataElement = _interopRequireDefault(require("../UTDataElement"));
|
|
11
12
|
var _UTLabel = _interopRequireDefault(require("../UTLabel"));
|
|
@@ -14,6 +15,7 @@ var _classesUtils = require("../../utils/classesUtils");
|
|
|
14
15
|
var _testIds = require("../../constants/testIds");
|
|
15
16
|
var _stylesModule = _interopRequireDefault(require("./styles.module.scss"));
|
|
16
17
|
var _theme = require("./theme");
|
|
18
|
+
var _constants = require("./constants");
|
|
17
19
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
18
20
|
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
|
|
19
21
|
function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
|
|
@@ -65,7 +67,10 @@ const UTDataCategory = _ref => {
|
|
|
65
67
|
}, /*#__PURE__*/_react.default.createElement("div", {
|
|
66
68
|
ref: childrenRef,
|
|
67
69
|
className: _stylesModule.default.childrenContent
|
|
68
|
-
},
|
|
70
|
+
}, (0, _isEmpty.default)(elements) ? /*#__PURE__*/_react.default.createElement(_UTLabel.default, {
|
|
71
|
+
align: "center",
|
|
72
|
+
colorTheme: "gray"
|
|
73
|
+
}, _constants.WITHOUT_DATA_TEXT) : elements.map((element, index) => {
|
|
69
74
|
const {
|
|
70
75
|
key,
|
|
71
76
|
...dataElementProps
|
package/dist/index.js
CHANGED
|
@@ -480,7 +480,7 @@ Object.defineProperty(exports, "keyboardUtils", {
|
|
|
480
480
|
Object.defineProperty(exports, "stylesDeduplicationUtils", {
|
|
481
481
|
enumerable: true,
|
|
482
482
|
get: function () {
|
|
483
|
-
return
|
|
483
|
+
return _stylesDeduplicationUtils.default;
|
|
484
484
|
}
|
|
485
485
|
});
|
|
486
486
|
var _AlertHandler = _interopRequireDefault(require("./components/UTAlert/AlertHandler"));
|
|
@@ -562,5 +562,5 @@ var _UTVirtualKeyboard = _interopRequireDefault(require("./components/UTVirtualK
|
|
|
562
562
|
var _UTWorkflowContainer = _interopRequireDefault(require("./components/UTWorkflowContainer"));
|
|
563
563
|
var _WithLoading = _interopRequireDefault(require("./components/WithLoading"));
|
|
564
564
|
var _WithTouch = _interopRequireDefault(require("./components/WithTouch"));
|
|
565
|
-
var
|
|
565
|
+
var _stylesDeduplicationUtils = _interopRequireDefault(require("./utils/stylesDeduplicationUtils"));
|
|
566
566
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
@@ -0,0 +1,453 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = void 0;
|
|
7
|
+
var _react = require("react");
|
|
8
|
+
/**
|
|
9
|
+
* Sistema de deduplicación de estilos para Energy UI
|
|
10
|
+
* Evita que los estilos se carguen múltiples veces cuando la librería se importa desde diferentes proyectos
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
// Cache global para estilos ya cargados
|
|
14
|
+
const loadedStyles = new Set(); // Set de hashes de contenido CSS ya procesados
|
|
15
|
+
const styleElementsByHash = new Map(); // Map de hash -> elemento DOM para estilos ya cargados
|
|
16
|
+
|
|
17
|
+
// Cache global para URLs de hojas de estilos externas ya cargadas
|
|
18
|
+
const loadedStylesheets = new Set(); // Set de URLs normalizadas de hojas externas ya cargadas
|
|
19
|
+
|
|
20
|
+
// Referencias globales para cleanup
|
|
21
|
+
let globalObserver = null;
|
|
22
|
+
let isConfigured = false;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Normaliza el contenido CSS para comparaciones consistentes
|
|
26
|
+
*/
|
|
27
|
+
const normalizeCSSContent = content => {
|
|
28
|
+
if (!content || typeof content !== 'string') {
|
|
29
|
+
return '';
|
|
30
|
+
}
|
|
31
|
+
return content
|
|
32
|
+
// Remover comentarios CSS (pero preservar source maps)
|
|
33
|
+
.replace(/\/\*[^*]*\*+(?:[^/*][^*]*\*+)*\//g, match => {
|
|
34
|
+
// Preservar source maps que pueden contener información importante
|
|
35
|
+
if (match.includes('sourceMappingURL')) {
|
|
36
|
+
return match;
|
|
37
|
+
}
|
|
38
|
+
return '';
|
|
39
|
+
})
|
|
40
|
+
// Remover espacios en blanco extra
|
|
41
|
+
.replace(/\s+/g, ' ')
|
|
42
|
+
// Remover espacios al inicio y final
|
|
43
|
+
.trim()
|
|
44
|
+
// Normalizar saltos de línea
|
|
45
|
+
.replace(/\r\n/g, '\n').replace(/\r/g, '\n')
|
|
46
|
+
// Remover espacios alrededor de caracteres especiales
|
|
47
|
+
.replace(/\s*([{}:;,])\s*/g, '$1')
|
|
48
|
+
// Normalizar valores de colores
|
|
49
|
+
.replace(/#([0-9a-fA-F]{3})\b/g, (match, hex) => // Expandir colores de 3 dígitos a 6 dígitos
|
|
50
|
+
"#".concat(hex.split('').map(char => char + char).join('')))
|
|
51
|
+
// Normalizar valores de unidades
|
|
52
|
+
.replace(/(\d+)px/g, '$1px').replace(/(\d+)em/g, '$1em').replace(/(\d+)rem/g, '$1rem')
|
|
53
|
+
// Remover espacios extra entre reglas
|
|
54
|
+
.replace(/}\s*{/g, '}{')
|
|
55
|
+
// Normalizar selectores
|
|
56
|
+
.replace(/\s*,\s*/g, ',').replace(/\s*>\s*/g, '>').replace(/\s*\+\s*/g, '+').replace(/\s*~\s*/g, '~');
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Normaliza URLs para comparaciones consistentes
|
|
61
|
+
*/
|
|
62
|
+
const normalizeURL = url => {
|
|
63
|
+
if (!url || typeof url !== 'string') {
|
|
64
|
+
return '';
|
|
65
|
+
}
|
|
66
|
+
try {
|
|
67
|
+
const urlObj = new URL(url, window.location.href);
|
|
68
|
+
|
|
69
|
+
// Remover parámetros de query que no afectan el contenido
|
|
70
|
+
const paramsToRemove = ['v', 'version', 't', 'timestamp', 'cache', 'cb'];
|
|
71
|
+
paramsToRemove.forEach(param => {
|
|
72
|
+
urlObj.searchParams.delete(param);
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
// Normalizar el path
|
|
76
|
+
let path = urlObj.pathname;
|
|
77
|
+
|
|
78
|
+
// Remover extensiones de archivo para comparación
|
|
79
|
+
path = path.replace(/\.(css|scss|sass|less)$/i, '');
|
|
80
|
+
|
|
81
|
+
// Remover hashes de build (ej: main.abc123.css -> main)
|
|
82
|
+
path = path.replace(/\.([a-f0-9]{8,})\./i, '.');
|
|
83
|
+
|
|
84
|
+
// Construir URL normalizada
|
|
85
|
+
const normalizedURL = "".concat(urlObj.origin).concat(path);
|
|
86
|
+
return normalizedURL.toLowerCase();
|
|
87
|
+
} catch (e) {
|
|
88
|
+
// Si no es una URL válida, normalizar como string
|
|
89
|
+
return url.toLowerCase().replace(/[?#].*$/, '') // Remover query params y hash
|
|
90
|
+
.replace(/\.(css|scss|sass|less)$/i, '') // Remover extensiones
|
|
91
|
+
.replace(/\.([a-f0-9]{8,})\./i, '.') // Remover hashes de build
|
|
92
|
+
.trim();
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Genera un hash único para un conjunto de estilos normalizado
|
|
98
|
+
*/
|
|
99
|
+
const generateStyleHash = content => {
|
|
100
|
+
const normalizedContent = normalizeCSSContent(content);
|
|
101
|
+
|
|
102
|
+
// Usar un algoritmo de hash más robusto
|
|
103
|
+
let hash = 0;
|
|
104
|
+
const prime = 31;
|
|
105
|
+
for (let i = 0; i < normalizedContent.length; i++) {
|
|
106
|
+
const char = normalizedContent.charCodeAt(i);
|
|
107
|
+
hash = hash * prime + char >>> 0; // Mantener como entero de 32 bits sin signo
|
|
108
|
+
}
|
|
109
|
+
return hash.toString(36);
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Verifica si el contenido es un estilo de Energy UI
|
|
114
|
+
*/
|
|
115
|
+
const isEnergyUIStyle = content => {
|
|
116
|
+
if (!content || typeof content !== 'string') {
|
|
117
|
+
return false;
|
|
118
|
+
}
|
|
119
|
+
const normalizedContent = normalizeCSSContent(content);
|
|
120
|
+
|
|
121
|
+
// Patrones específicos de Energy UI - MÁS SEGUROS
|
|
122
|
+
const energyUIPatterns = [
|
|
123
|
+
// Clases de componentes UT (muy específicas)
|
|
124
|
+
/\.[a-z]*UT[A-Z][a-zA-Z]*/g,
|
|
125
|
+
// Clases CSS Modules con hash de UT (muy específicas)
|
|
126
|
+
/\.UT[A-Z][a-zA-Z]*__[a-zA-Z0-9_-]+/g,
|
|
127
|
+
// Variables CSS de Energy UI (muy específicas)
|
|
128
|
+
/--energy-ui-/g, /--ut-/g,
|
|
129
|
+
// Selectores específicos de Energy UI (muy específicos)
|
|
130
|
+
/\[data-energy-ui\]/g, /\[data-ut-/g,
|
|
131
|
+
// Comentarios específicos de Energy UI (muy específicos)
|
|
132
|
+
/\/\*.*energy.*ui.*\*\//gi, /\/\*.*ut.*\*\//gi,
|
|
133
|
+
// CSS Modules internos de Energy UI (patrón específico .styles_[name]_[hash])
|
|
134
|
+
/\.styles_[a-zA-Z0-9_-]+_[a-zA-Z0-9_-]+/g,
|
|
135
|
+
// Source maps específicos de Energy UI
|
|
136
|
+
/sourceMappingURL.*energy/i, /sourceMappingURL.*ut/i];
|
|
137
|
+
|
|
138
|
+
// Verificación adicional de seguridad: debe contener al menos 2 patrones específicos
|
|
139
|
+
const matches = energyUIPatterns.filter(pattern => pattern.test(normalizedContent));
|
|
140
|
+
|
|
141
|
+
// Solo considerar Energy UI si hay al menos 2 coincidencias (más seguro)
|
|
142
|
+
if (matches.length >= 2) {
|
|
143
|
+
return true;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// Caso especial: si contiene el patrón .styles_[name]_[hash] Y algún otro patrón específico
|
|
147
|
+
const stylesPattern = /\.styles_[a-zA-Z0-9_-]+_[a-zA-Z0-9_-]+/g;
|
|
148
|
+
const hasStylesPattern = stylesPattern.test(normalizedContent);
|
|
149
|
+
const hasOtherPattern = energyUIPatterns.some(pattern => pattern !== stylesPattern && pattern.test(normalizedContent));
|
|
150
|
+
const isEnergyUI = hasStylesPattern && hasOtherPattern;
|
|
151
|
+
return isEnergyUI;
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Verifica si una URL es de Energy UI
|
|
156
|
+
*/
|
|
157
|
+
const isEnergyUIURL = url => {
|
|
158
|
+
if (!url || typeof url !== 'string') {
|
|
159
|
+
return false;
|
|
160
|
+
}
|
|
161
|
+
const normalizedURL = normalizeURL(url);
|
|
162
|
+
|
|
163
|
+
// Patrones de URL de Energy UI - MÁS SEGUROS
|
|
164
|
+
const energyUIPatterns = [
|
|
165
|
+
// URLs específicas de Energy UI
|
|
166
|
+
/energy-ui/i, /energyui/i, /ut-components/i, /energy.*ui/i,
|
|
167
|
+
// URLs locales específicas de Energy UI (más restrictivas)
|
|
168
|
+
/localhost.*\/energy/i, /localhost.*\/ut/i, /localhost.*energy-ui/i, /localhost.*ut-components/i];
|
|
169
|
+
return energyUIPatterns.some(pattern => pattern.test(normalizedURL));
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Verifica si un estilo ya está cargado
|
|
174
|
+
*/
|
|
175
|
+
const isStyleAlreadyLoaded = content => {
|
|
176
|
+
const hash = generateStyleHash(content);
|
|
177
|
+
return loadedStyles.has(hash);
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Marca un estilo como cargado
|
|
182
|
+
*/
|
|
183
|
+
const markStyleAsLoaded = (content, element) => {
|
|
184
|
+
const hash = generateStyleHash(content);
|
|
185
|
+
loadedStyles.add(hash);
|
|
186
|
+
styleElementsByHash.set(hash, element);
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Verifica si una hoja de estilos externa ya está cargada
|
|
191
|
+
*/
|
|
192
|
+
const isStylesheetAlreadyLoaded = href => {
|
|
193
|
+
const normalizedHref = normalizeURL(href);
|
|
194
|
+
return loadedStylesheets.has(normalizedHref);
|
|
195
|
+
};
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Marca una hoja de estilos externa como cargada
|
|
199
|
+
*/
|
|
200
|
+
const markStylesheetAsLoaded = href => {
|
|
201
|
+
const normalizedHref = normalizeURL(href);
|
|
202
|
+
loadedStylesheets.add(normalizedHref);
|
|
203
|
+
};
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Verifica si estamos en un entorno compatible
|
|
207
|
+
*/
|
|
208
|
+
const isCompatibleEnvironment = () => typeof window !== 'undefined' && typeof document !== 'undefined' && typeof document.head !== 'undefined';
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* Intercepta la creación de elementos <style> para evitar duplicados
|
|
212
|
+
*/
|
|
213
|
+
const interceptStyleCreation = () => {
|
|
214
|
+
// Verificar si estamos en un entorno con DOM disponible
|
|
215
|
+
if (!isCompatibleEnvironment()) {
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
218
|
+
if (isConfigured) {
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// Usar el punto de inserción existente (meta tag)
|
|
223
|
+
const insertionPoint = document.getElementById('energyui-insertion-point');
|
|
224
|
+
if (!insertionPoint) {
|
|
225
|
+
console.warn('Energy UI: No se encontró el punto de inserción <meta id="energyui-insertion-point"/>');
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
// Observer específico que solo procesa elementos después del meta tag
|
|
230
|
+
|
|
231
|
+
// Observer que solo observa los cambios DESPUÉS del meta tag (más seguro)
|
|
232
|
+
const observeAfterMetaTag = () => {
|
|
233
|
+
// Observar solo los nodos que se insertan después del meta tag
|
|
234
|
+
const observer = new MutationObserver(mutations => {
|
|
235
|
+
mutations.forEach(mutation => {
|
|
236
|
+
if (mutation.type === 'childList') {
|
|
237
|
+
mutation.addedNodes.forEach(node => {
|
|
238
|
+
if (node.nodeType === Node.ELEMENT_NODE) {
|
|
239
|
+
// Solo procesar elementos que están después del meta tag
|
|
240
|
+
if (insertionPoint.compareDocumentPosition(node) & Node.DOCUMENT_POSITION_FOLLOWING) {
|
|
241
|
+
// Procesar elementos <style>
|
|
242
|
+
if (node.tagName === 'STYLE') {
|
|
243
|
+
const content = node.textContent || '';
|
|
244
|
+
|
|
245
|
+
// Usar detección mejorada de Energy UI
|
|
246
|
+
if (content && isEnergyUIStyle(content)) {
|
|
247
|
+
if (isStyleAlreadyLoaded(content)) {
|
|
248
|
+
node.remove();
|
|
249
|
+
} else {
|
|
250
|
+
markStyleAsLoaded(content, node);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// Procesar elementos <link> con hojas de estilos
|
|
256
|
+
if (node.tagName === 'LINK' && node.rel === 'stylesheet') {
|
|
257
|
+
const href = node.href || '';
|
|
258
|
+
|
|
259
|
+
// Usar detección mejorada de URLs de Energy UI
|
|
260
|
+
if (href && isEnergyUIURL(href)) {
|
|
261
|
+
// Detección silenciosa de hojas de estilos externas
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
});
|
|
267
|
+
}
|
|
268
|
+
});
|
|
269
|
+
});
|
|
270
|
+
|
|
271
|
+
// Observar solo el head, pero filtrar por posición relativa al meta tag
|
|
272
|
+
observer.observe(document.head, {
|
|
273
|
+
childList: true,
|
|
274
|
+
subtree: false // No observar subtree, solo nodos directos
|
|
275
|
+
});
|
|
276
|
+
return observer;
|
|
277
|
+
};
|
|
278
|
+
|
|
279
|
+
// Usar el observer específico
|
|
280
|
+
globalObserver = observeAfterMetaTag();
|
|
281
|
+
|
|
282
|
+
// Marcar como configurado
|
|
283
|
+
isConfigured = true;
|
|
284
|
+
};
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* Función para limpiar estilos duplicados existentes
|
|
288
|
+
*/
|
|
289
|
+
const cleanupDuplicateStyles = () => {
|
|
290
|
+
// Limpiar elementos <style> duplicados
|
|
291
|
+
const existingStyleElements = document.querySelectorAll('style');
|
|
292
|
+
const seenContents = new Set();
|
|
293
|
+
existingStyleElements.forEach(style => {
|
|
294
|
+
const content = style.textContent || '';
|
|
295
|
+
|
|
296
|
+
// Usar detección mejorada de Energy UI
|
|
297
|
+
if (content && isEnergyUIStyle(content)) {
|
|
298
|
+
const hash = generateStyleHash(content);
|
|
299
|
+
if (seenContents.has(hash)) {
|
|
300
|
+
style.remove();
|
|
301
|
+
} else {
|
|
302
|
+
seenContents.add(hash);
|
|
303
|
+
markStyleAsLoaded(content, style);
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
// Limpiar hojas de estilos externas duplicadas
|
|
309
|
+
const linkElements = document.querySelectorAll('link[rel="stylesheet"]');
|
|
310
|
+
linkElements.forEach(link => {
|
|
311
|
+
const href = link.href || '';
|
|
312
|
+
|
|
313
|
+
// Usar detección mejorada de URLs de Energy UI
|
|
314
|
+
if (href && isEnergyUIURL(href)) {
|
|
315
|
+
if (isStylesheetAlreadyLoaded(href)) {
|
|
316
|
+
link.remove();
|
|
317
|
+
} else {
|
|
318
|
+
markStylesheetAsLoaded(href);
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
});
|
|
322
|
+
};
|
|
323
|
+
|
|
324
|
+
/**
|
|
325
|
+
* Función para limpiar recursos y desconectar observers
|
|
326
|
+
*/
|
|
327
|
+
const cleanupStyleDeduplication = () => {
|
|
328
|
+
if (globalObserver) {
|
|
329
|
+
globalObserver.disconnect();
|
|
330
|
+
globalObserver = null;
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
// Limpiar caches
|
|
334
|
+
loadedStyles.clear();
|
|
335
|
+
styleElementsByHash.clear();
|
|
336
|
+
loadedStylesheets.clear();
|
|
337
|
+
|
|
338
|
+
// Resetear estado
|
|
339
|
+
isConfigured = false;
|
|
340
|
+
};
|
|
341
|
+
|
|
342
|
+
/**
|
|
343
|
+
* Hook para React
|
|
344
|
+
*/
|
|
345
|
+
const useStyleDeduplication = function () {
|
|
346
|
+
let enableStyleDeduplication = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
|
|
347
|
+
(0, _react.useEffect)(() => {
|
|
348
|
+
if (enableStyleDeduplication) {
|
|
349
|
+
interceptStyleCreation();
|
|
350
|
+
cleanupDuplicateStyles();
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
// Cleanup automático cuando el componente se desmonta
|
|
354
|
+
return () => {
|
|
355
|
+
if (enableStyleDeduplication) {
|
|
356
|
+
cleanupStyleDeduplication();
|
|
357
|
+
}
|
|
358
|
+
};
|
|
359
|
+
}, [enableStyleDeduplication]);
|
|
360
|
+
};
|
|
361
|
+
|
|
362
|
+
/**
|
|
363
|
+
* Función para configuración manual
|
|
364
|
+
*/
|
|
365
|
+
const setupStyleDeduplication = () => {
|
|
366
|
+
interceptStyleCreation();
|
|
367
|
+
cleanupDuplicateStyles();
|
|
368
|
+
};
|
|
369
|
+
|
|
370
|
+
/**
|
|
371
|
+
* Función para verificar si está configurado
|
|
372
|
+
*/
|
|
373
|
+
const isStyleDeduplicationConfigured = () => isConfigured && globalObserver !== null;
|
|
374
|
+
|
|
375
|
+
/**
|
|
376
|
+
* Función para obtener estadísticas de deduplicación
|
|
377
|
+
*/
|
|
378
|
+
const getDeduplicationStats = () => ({
|
|
379
|
+
loadedStylesCount: loadedStyles.size,
|
|
380
|
+
styleElementsByHashCount: styleElementsByHash.size,
|
|
381
|
+
loadedStylesheetsCount: loadedStylesheets.size,
|
|
382
|
+
isConfigured: isStyleDeduplicationConfigured()
|
|
383
|
+
});
|
|
384
|
+
|
|
385
|
+
/**
|
|
386
|
+
* Función para testing: verificar si un contenido sería detectado como Energy UI
|
|
387
|
+
*/
|
|
388
|
+
const testEnergyUIDetection = content => ({
|
|
389
|
+
isEnergyUI: isEnergyUIStyle(content),
|
|
390
|
+
normalizedContent: normalizeCSSContent(content),
|
|
391
|
+
hash: generateStyleHash(content)
|
|
392
|
+
});
|
|
393
|
+
|
|
394
|
+
/**
|
|
395
|
+
* Función para testing: verificar si una URL sería detectada como Energy UI
|
|
396
|
+
*/
|
|
397
|
+
const testEnergyUIURLDetection = url => ({
|
|
398
|
+
isEnergyUI: isEnergyUIURL(url),
|
|
399
|
+
normalizedURL: normalizeURL(url)
|
|
400
|
+
});
|
|
401
|
+
|
|
402
|
+
/**
|
|
403
|
+
* Función para debugging: obtener información detallada de estilos cargados
|
|
404
|
+
*/
|
|
405
|
+
const getDetailedStats = () => {
|
|
406
|
+
const currentStyleElements = document.querySelectorAll('style');
|
|
407
|
+
const currentLinkElements = document.querySelectorAll('link[rel="stylesheet"]');
|
|
408
|
+
const energyUIStyles = [];
|
|
409
|
+
const energyUILinks = [];
|
|
410
|
+
currentStyleElements.forEach((style, index) => {
|
|
411
|
+
const content = style.textContent || '';
|
|
412
|
+
if (isEnergyUIStyle(content)) {
|
|
413
|
+
energyUIStyles.push({
|
|
414
|
+
index,
|
|
415
|
+
hash: generateStyleHash(content),
|
|
416
|
+
isDuplicate: isStyleAlreadyLoaded(content),
|
|
417
|
+
normalizedContent: "".concat(normalizeCSSContent(content).substring(0, 100), "...")
|
|
418
|
+
});
|
|
419
|
+
}
|
|
420
|
+
});
|
|
421
|
+
currentLinkElements.forEach((link, index) => {
|
|
422
|
+
const href = link.href || '';
|
|
423
|
+
if (isEnergyUIURL(href)) {
|
|
424
|
+
energyUILinks.push({
|
|
425
|
+
index,
|
|
426
|
+
href,
|
|
427
|
+
normalizedURL: normalizeURL(href),
|
|
428
|
+
isDuplicate: isStylesheetAlreadyLoaded(href)
|
|
429
|
+
});
|
|
430
|
+
}
|
|
431
|
+
});
|
|
432
|
+
return {
|
|
433
|
+
totalStyles: currentStyleElements.length,
|
|
434
|
+
totalLinks: currentLinkElements.length,
|
|
435
|
+
energyUIStyles,
|
|
436
|
+
energyUILinks,
|
|
437
|
+
loadedStylesCount: loadedStyles.size,
|
|
438
|
+
styleElementsByHashCount: styleElementsByHash.size,
|
|
439
|
+
isConfigured: isStyleDeduplicationConfigured()
|
|
440
|
+
};
|
|
441
|
+
};
|
|
442
|
+
var _default = exports.default = {
|
|
443
|
+
getDeduplicationStats,
|
|
444
|
+
isStyleDeduplicationConfigured,
|
|
445
|
+
setupStyleDeduplication,
|
|
446
|
+
cleanupStyleDeduplication,
|
|
447
|
+
useStyleDeduplication,
|
|
448
|
+
isCompatibleEnvironment,
|
|
449
|
+
isStylesheetAlreadyLoaded,
|
|
450
|
+
testEnergyUIDetection,
|
|
451
|
+
testEnergyUIURLDetection,
|
|
452
|
+
getDetailedStats
|
|
453
|
+
};
|
package/package.json
CHANGED
|
@@ -1,183 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.useStyleDeduplication = exports.setupStyleDeduplication = exports.isStyleDeduplicationConfigured = exports.getDeduplicationStats = exports.default = void 0;
|
|
7
|
-
var _react = require("react");
|
|
8
|
-
/**
|
|
9
|
-
* Sistema de deduplicación de estilos para Energy UI
|
|
10
|
-
* Evita que los estilos se carguen múltiples veces cuando la librería se importa desde diferentes proyectos
|
|
11
|
-
*/
|
|
12
|
-
|
|
13
|
-
// Cache global para estilos ya cargados
|
|
14
|
-
const loadedStyles = new Set();
|
|
15
|
-
const styleElements = new Map();
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Genera un hash único para un conjunto de estilos
|
|
19
|
-
*/
|
|
20
|
-
const generateStyleHash = content => {
|
|
21
|
-
let hash = 0;
|
|
22
|
-
for (let i = 0; i < content.length; i++) {
|
|
23
|
-
const char = content.charCodeAt(i);
|
|
24
|
-
hash = (hash << 5) - hash + char;
|
|
25
|
-
hash = hash & hash; // Convertir a entero de 32 bits
|
|
26
|
-
}
|
|
27
|
-
return hash.toString(36);
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Verifica si un estilo ya está cargado
|
|
32
|
-
*/
|
|
33
|
-
const isStyleAlreadyLoaded = content => {
|
|
34
|
-
const hash = generateStyleHash(content);
|
|
35
|
-
return loadedStyles.has(hash);
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* Marca un estilo como cargado
|
|
40
|
-
*/
|
|
41
|
-
const markStyleAsLoaded = (content, element) => {
|
|
42
|
-
const hash = generateStyleHash(content);
|
|
43
|
-
loadedStyles.add(hash);
|
|
44
|
-
styleElements.set(hash, element);
|
|
45
|
-
};
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Intercepta la creación de elementos <style> para evitar duplicados
|
|
49
|
-
*/
|
|
50
|
-
const interceptStyleCreation = () => {
|
|
51
|
-
if (window.__energyUI_styleDeduplicationConfigured) {
|
|
52
|
-
return;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
// Crear el punto de inserción si no existe
|
|
56
|
-
let insertionPoint = document.getElementById('energyui-insertion-point');
|
|
57
|
-
if (!insertionPoint) {
|
|
58
|
-
insertionPoint = document.createElement('div');
|
|
59
|
-
insertionPoint.id = 'energyui-insertion-point';
|
|
60
|
-
insertionPoint.setAttribute('data-energy-ui', 'deduplication-insertion-point');
|
|
61
|
-
document.head.appendChild(insertionPoint);
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
// Usar un enfoque más simple: solo observar el DOM
|
|
65
|
-
const observer = new MutationObserver(mutations => {
|
|
66
|
-
mutations.forEach(mutation => {
|
|
67
|
-
mutation.addedNodes.forEach(node => {
|
|
68
|
-
if (node.nodeType === Node.ELEMENT_NODE && node.tagName === 'STYLE') {
|
|
69
|
-
const content = node.textContent || '';
|
|
70
|
-
if (content && (content.includes('UT') || content.includes('energy-ui') || content.includes('energyui') || content.includes('__'))) {
|
|
71
|
-
if (isStyleAlreadyLoaded(content)) {
|
|
72
|
-
console.log('Energy UI: Estilo duplicado detectado en DOM, removiendo...');
|
|
73
|
-
node.remove();
|
|
74
|
-
} else {
|
|
75
|
-
markStyleAsLoaded(content, node);
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
});
|
|
80
|
-
});
|
|
81
|
-
});
|
|
82
|
-
observer.observe(document.head, {
|
|
83
|
-
childList: true,
|
|
84
|
-
subtree: true
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
// Interceptar la inserción de reglas CSS para JSS
|
|
88
|
-
const originalInsertRule = CSSStyleSheet.prototype.insertRule;
|
|
89
|
-
CSSStyleSheet.prototype.insertRule = function (rule, index) {
|
|
90
|
-
// Verificar si la regla ya existe en otra hoja de estilos
|
|
91
|
-
if (rule && typeof rule === 'string') {
|
|
92
|
-
const existingSheets = Array.from(document.styleSheets);
|
|
93
|
-
for (const sheet of existingSheets) {
|
|
94
|
-
try {
|
|
95
|
-
const rules = Array.from(sheet.cssRules || []);
|
|
96
|
-
for (const existingRule of rules) {
|
|
97
|
-
if (existingRule.cssText === rule) {
|
|
98
|
-
console.log('Energy UI: Regla CSS duplicada detectada y evitada');
|
|
99
|
-
return 0; // Retornar índice 0 para evitar errores
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
} catch (e) {
|
|
103
|
-
// Ignorar errores de CORS
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
return originalInsertRule.call(this, rule, index);
|
|
108
|
-
};
|
|
109
|
-
|
|
110
|
-
// Marcar como configurado
|
|
111
|
-
window.__energyUI_styleDeduplicationConfigured = true;
|
|
112
|
-
console.log('Energy UI: Sistema de deduplicación de estilos configurado');
|
|
113
|
-
};
|
|
114
|
-
|
|
115
|
-
/**
|
|
116
|
-
* Función para limpiar estilos duplicados existentes
|
|
117
|
-
*/
|
|
118
|
-
const cleanupDuplicateStyles = () => {
|
|
119
|
-
const styleElements = document.querySelectorAll('style');
|
|
120
|
-
const seenContents = new Set();
|
|
121
|
-
styleElements.forEach(style => {
|
|
122
|
-
const content = style.textContent || '';
|
|
123
|
-
if (content && (content.includes('UT') || content.includes('energy-ui') || content.includes('energyui') || content.includes('__'))) {
|
|
124
|
-
const hash = generateStyleHash(content);
|
|
125
|
-
if (seenContents.has(hash)) {
|
|
126
|
-
console.log('Energy UI: Removiendo estilo duplicado existente');
|
|
127
|
-
style.remove();
|
|
128
|
-
} else {
|
|
129
|
-
seenContents.add(hash);
|
|
130
|
-
markStyleAsLoaded(content, style);
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
});
|
|
134
|
-
};
|
|
135
|
-
|
|
136
|
-
/**
|
|
137
|
-
* Hook para React
|
|
138
|
-
*/
|
|
139
|
-
const useStyleDeduplication = function () {
|
|
140
|
-
let enableStyleDeduplication = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
|
|
141
|
-
(0, _react.useEffect)(() => {
|
|
142
|
-
if (enableStyleDeduplication) {
|
|
143
|
-
interceptStyleCreation();
|
|
144
|
-
cleanupDuplicateStyles();
|
|
145
|
-
}
|
|
146
|
-
}, [enableStyleDeduplication]);
|
|
147
|
-
};
|
|
148
|
-
|
|
149
|
-
/**
|
|
150
|
-
* Función para configuración manual
|
|
151
|
-
*/
|
|
152
|
-
exports.useStyleDeduplication = useStyleDeduplication;
|
|
153
|
-
const setupStyleDeduplication = () => {
|
|
154
|
-
interceptStyleCreation();
|
|
155
|
-
cleanupDuplicateStyles();
|
|
156
|
-
};
|
|
157
|
-
|
|
158
|
-
/**
|
|
159
|
-
* Función para verificar si está configurado
|
|
160
|
-
*/
|
|
161
|
-
exports.setupStyleDeduplication = setupStyleDeduplication;
|
|
162
|
-
const isStyleDeduplicationConfigured = () => {
|
|
163
|
-
return window.__energyUI_styleDeduplicationConfigured === true;
|
|
164
|
-
};
|
|
165
|
-
|
|
166
|
-
/**
|
|
167
|
-
* Función para obtener estadísticas de deduplicación
|
|
168
|
-
*/
|
|
169
|
-
exports.isStyleDeduplicationConfigured = isStyleDeduplicationConfigured;
|
|
170
|
-
const getDeduplicationStats = () => {
|
|
171
|
-
return {
|
|
172
|
-
loadedStylesCount: loadedStyles.size,
|
|
173
|
-
styleElementsCount: styleElements.size,
|
|
174
|
-
isConfigured: isStyleDeduplicationConfigured()
|
|
175
|
-
};
|
|
176
|
-
};
|
|
177
|
-
exports.getDeduplicationStats = getDeduplicationStats;
|
|
178
|
-
var _default = exports.default = {
|
|
179
|
-
getDeduplicationStats,
|
|
180
|
-
isStyleDeduplicationConfigured,
|
|
181
|
-
setupStyleDeduplication,
|
|
182
|
-
useStyleDeduplication
|
|
183
|
-
};
|