@bebranded/bb-contents 1.0.84 → 1.0.86
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/bb-contents.js +72 -30
- package/package.json +1 -1
package/bb-contents.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* BeBranded Contents
|
|
3
3
|
* Contenus additionnels français pour Webflow
|
|
4
|
-
* @version 1.0.
|
|
4
|
+
* @version 1.0.86
|
|
5
5
|
* @author BeBranded
|
|
6
6
|
* @license MIT
|
|
7
7
|
* @website https://www.bebranded.xyz
|
|
@@ -32,11 +32,11 @@
|
|
|
32
32
|
window._bbContentsInitialized = true;
|
|
33
33
|
|
|
34
34
|
// Log de démarrage simple (une seule fois)
|
|
35
|
-
console.log('bb-contents | v1.0.
|
|
35
|
+
console.log('bb-contents | v1.0.86');
|
|
36
36
|
|
|
37
37
|
// Configuration
|
|
38
38
|
const config = {
|
|
39
|
-
version: '1.0.
|
|
39
|
+
version: '1.0.86',
|
|
40
40
|
debug: false, // Debug désactivé pour rendu propre
|
|
41
41
|
prefix: 'bb-', // utilisé pour générer les sélecteurs (data-bb-*)
|
|
42
42
|
youtubeEndpoint: null, // URL du worker YouTube (à définir par l'utilisateur)
|
|
@@ -385,13 +385,25 @@
|
|
|
385
385
|
const totalImages = images.length;
|
|
386
386
|
|
|
387
387
|
|
|
388
|
-
//
|
|
388
|
+
// OPTIMISATION: Charger les images sans forcer les dimensions
|
|
389
389
|
images.forEach(img => {
|
|
390
390
|
if (img.dataset.src && !img.src) {
|
|
391
391
|
img.src = img.dataset.src;
|
|
392
392
|
img.loading = 'eager';
|
|
393
393
|
}
|
|
394
|
+
|
|
395
|
+
// OPTIMISATION: Préserver les styles CSS existants (object-fit, etc.)
|
|
396
|
+
const originalObjectFit = img.style.objectFit || getComputedStyle(img).objectFit;
|
|
397
|
+
const originalObjectPosition = img.style.objectPosition || getComputedStyle(img).objectPosition;
|
|
398
|
+
|
|
394
399
|
img.onload = () => {
|
|
400
|
+
// OPTIMISATION: Restaurer les styles CSS après chargement
|
|
401
|
+
if (originalObjectFit && originalObjectFit !== 'none') {
|
|
402
|
+
img.style.objectFit = originalObjectFit;
|
|
403
|
+
}
|
|
404
|
+
if (originalObjectPosition && originalObjectPosition !== 'initial') {
|
|
405
|
+
img.style.objectPosition = originalObjectPosition;
|
|
406
|
+
}
|
|
395
407
|
imagesLoaded++;
|
|
396
408
|
};
|
|
397
409
|
img.onerror = () => {
|
|
@@ -973,21 +985,36 @@
|
|
|
973
985
|
|
|
974
986
|
// Module YouTube Feed
|
|
975
987
|
youtube: {
|
|
976
|
-
// Détection des bots pour éviter les appels API inutiles
|
|
988
|
+
// OPTIMISATION: Détection améliorée des bots pour éviter les appels API inutiles
|
|
977
989
|
isBot: function() {
|
|
978
990
|
const userAgent = navigator.userAgent.toLowerCase();
|
|
979
991
|
const botPatterns = [
|
|
980
992
|
'bot', 'crawler', 'spider', 'scraper', 'googlebot', 'bingbot', 'slurp',
|
|
981
993
|
'duckduckbot', 'baiduspider', 'yandexbot', 'facebookexternalhit', 'twitterbot',
|
|
982
|
-
'linkedinbot', 'whatsapp', 'telegrambot', 'discordbot', 'slackbot'
|
|
994
|
+
'linkedinbot', 'whatsapp', 'telegrambot', 'discordbot', 'slackbot', 'headless',
|
|
995
|
+
'phantom', 'selenium', 'puppeteer', 'playwright', 'lighthouse', 'gtmetrix',
|
|
996
|
+
'pagespeed', 'pingdom', 'uptime', 'monitor', 'check', 'test'
|
|
983
997
|
];
|
|
984
998
|
|
|
985
|
-
|
|
999
|
+
// Vérifications supplémentaires pour détecter plus de bots
|
|
1000
|
+
const isBot = botPatterns.some(pattern => userAgent.includes(pattern)) ||
|
|
986
1001
|
navigator.webdriver ||
|
|
987
|
-
!navigator.userAgent
|
|
1002
|
+
!navigator.userAgent ||
|
|
1003
|
+
!window.chrome || // Détecte les navigateurs headless
|
|
1004
|
+
navigator.userAgent.includes('HeadlessChrome') ||
|
|
1005
|
+
window.navigator.plugins.length === 0; // Bots n'ont souvent pas de plugins
|
|
1006
|
+
|
|
1007
|
+
if (isBot) {
|
|
1008
|
+
// Log pour debug (en mode debug seulement)
|
|
1009
|
+
if (bbContents.config.debug) {
|
|
1010
|
+
bbContents.utils.log('Bot détecté, pas d\'appel API YouTube');
|
|
1011
|
+
}
|
|
1012
|
+
}
|
|
1013
|
+
|
|
1014
|
+
return isBot;
|
|
988
1015
|
},
|
|
989
1016
|
|
|
990
|
-
//
|
|
1017
|
+
// OPTIMISATION: Cache amélioré avec protection contre les appels multiples
|
|
991
1018
|
cache: {
|
|
992
1019
|
get: function(key) {
|
|
993
1020
|
try {
|
|
@@ -997,7 +1024,7 @@
|
|
|
997
1024
|
const data = JSON.parse(cached);
|
|
998
1025
|
const now = Date.now();
|
|
999
1026
|
|
|
1000
|
-
// Cache
|
|
1027
|
+
// OPTIMISATION: Cache plus long (24h maintenu)
|
|
1001
1028
|
if (now - data.timestamp > 24 * 60 * 60 * 1000) {
|
|
1002
1029
|
localStorage.removeItem(key);
|
|
1003
1030
|
return null;
|
|
@@ -1022,6 +1049,21 @@
|
|
|
1022
1049
|
}
|
|
1023
1050
|
},
|
|
1024
1051
|
|
|
1052
|
+
// OPTIMISATION: Protection globale contre les appels multiples
|
|
1053
|
+
_activeRequests: new Set(),
|
|
1054
|
+
|
|
1055
|
+
isRequestActive: function(cacheKey) {
|
|
1056
|
+
return this._activeRequests.has(cacheKey);
|
|
1057
|
+
},
|
|
1058
|
+
|
|
1059
|
+
markRequestActive: function(cacheKey) {
|
|
1060
|
+
this._activeRequests.add(cacheKey);
|
|
1061
|
+
},
|
|
1062
|
+
|
|
1063
|
+
markRequestComplete: function(cacheKey) {
|
|
1064
|
+
this._activeRequests.delete(cacheKey);
|
|
1065
|
+
},
|
|
1066
|
+
|
|
1025
1067
|
detect: function(scope) {
|
|
1026
1068
|
return scope.querySelector('[bb-youtube-channel]') !== null;
|
|
1027
1069
|
},
|
|
@@ -1075,18 +1117,18 @@
|
|
|
1075
1117
|
}
|
|
1076
1118
|
|
|
1077
1119
|
if (!endpoint) {
|
|
1078
|
-
//
|
|
1120
|
+
// OPTIMISATION: Réduire drastiquement les retries (de 50 à 10)
|
|
1079
1121
|
const retryCount = element.getAttribute('data-youtube-retry-count') || '0';
|
|
1080
1122
|
const retries = parseInt(retryCount);
|
|
1081
1123
|
|
|
1082
|
-
if (retries <
|
|
1124
|
+
if (retries < 10) { // 10 * 500ms = 5 secondes max (plus espacé)
|
|
1083
1125
|
element.innerHTML = '<div style="padding: 20px; text-align: center; color: #6b7280;">Configuration YouTube en cours...</div>';
|
|
1084
1126
|
element.setAttribute('data-youtube-retry-count', (retries + 1).toString());
|
|
1085
1127
|
|
|
1086
|
-
//
|
|
1128
|
+
// OPTIMISATION: Espacer les retries (500ms au lieu de 100ms)
|
|
1087
1129
|
setTimeout(() => {
|
|
1088
1130
|
this.initElement(element);
|
|
1089
|
-
},
|
|
1131
|
+
}, 500);
|
|
1090
1132
|
return;
|
|
1091
1133
|
} else {
|
|
1092
1134
|
// Timeout après 5 secondes
|
|
@@ -1129,29 +1171,28 @@
|
|
|
1129
1171
|
return;
|
|
1130
1172
|
}
|
|
1131
1173
|
|
|
1132
|
-
//
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
if (!window[loadingKey]) {
|
|
1174
|
+
// OPTIMISATION: Protection globale contre les appels multiples
|
|
1175
|
+
if (this.isRequestActive(cacheKey)) {
|
|
1176
|
+
// Un appel est déjà en cours pour cette clé, attendre
|
|
1177
|
+
const checkActive = () => {
|
|
1178
|
+
if (!this.isRequestActive(cacheKey)) {
|
|
1138
1179
|
// L'autre appel est terminé, vérifier le cache
|
|
1139
1180
|
const newCachedData = this.cache.get(cacheKey);
|
|
1140
1181
|
if (newCachedData && newCachedData.value) {
|
|
1141
1182
|
this.generateYouTubeFeed(container, template, newCachedData.value, allowShorts, language);
|
|
1142
|
-
|
|
1183
|
+
} else {
|
|
1143
1184
|
container.innerHTML = '<div style="padding: 20px; text-align: center; color: #6b7280;">Erreur de chargement</div>';
|
|
1144
1185
|
}
|
|
1145
1186
|
} else {
|
|
1146
|
-
setTimeout(
|
|
1187
|
+
setTimeout(checkActive, 200); // Vérifier moins souvent
|
|
1147
1188
|
}
|
|
1148
1189
|
};
|
|
1149
|
-
|
|
1190
|
+
checkActive();
|
|
1150
1191
|
return;
|
|
1151
1192
|
}
|
|
1152
1193
|
|
|
1153
1194
|
// Marquer qu'un appel API est en cours
|
|
1154
|
-
|
|
1195
|
+
this.markRequestActive(cacheKey);
|
|
1155
1196
|
|
|
1156
1197
|
// Afficher un loader
|
|
1157
1198
|
container.innerHTML = '<div style="padding: 20px; text-align: center; color: #6b7280;">Chargement des vidéos YouTube...</div>';
|
|
@@ -1169,20 +1210,20 @@
|
|
|
1169
1210
|
throw new Error(data.error.message || 'Erreur API YouTube');
|
|
1170
1211
|
}
|
|
1171
1212
|
|
|
1172
|
-
// Sauvegarder en cache pour 24h
|
|
1213
|
+
// OPTIMISATION: Sauvegarder en cache pour 24h
|
|
1173
1214
|
this.cache.set(cacheKey, data);
|
|
1174
1215
|
// Données YouTube mises en cache pour 24h (économie API)
|
|
1175
1216
|
|
|
1176
1217
|
this.generateYouTubeFeed(container, template, data, allowShorts, language);
|
|
1177
1218
|
|
|
1178
|
-
// Libérer le verrou
|
|
1179
|
-
|
|
1219
|
+
// OPTIMISATION: Libérer le verrou avec la nouvelle méthode
|
|
1220
|
+
this.markRequestComplete(cacheKey);
|
|
1180
1221
|
})
|
|
1181
1222
|
.catch(error => {
|
|
1182
1223
|
// Erreur dans le module youtube
|
|
1183
1224
|
|
|
1184
|
-
// Libérer le verrou en cas d'erreur
|
|
1185
|
-
|
|
1225
|
+
// OPTIMISATION: Libérer le verrou en cas d'erreur
|
|
1226
|
+
this.markRequestComplete(cacheKey);
|
|
1186
1227
|
|
|
1187
1228
|
// En cas d'erreur, essayer de récupérer du cache même expiré
|
|
1188
1229
|
const expiredCache = localStorage.getItem(cacheKey);
|
|
@@ -1372,7 +1413,7 @@
|
|
|
1372
1413
|
return textarea.value;
|
|
1373
1414
|
},
|
|
1374
1415
|
|
|
1375
|
-
// Nettoyer le cache expiré
|
|
1416
|
+
// OPTIMISATION: Nettoyer le cache expiré (48h)
|
|
1376
1417
|
cleanCache: function() {
|
|
1377
1418
|
try {
|
|
1378
1419
|
const keys = Object.keys(localStorage);
|
|
@@ -1383,6 +1424,7 @@
|
|
|
1383
1424
|
if (key.startsWith('youtube_')) {
|
|
1384
1425
|
try {
|
|
1385
1426
|
const cached = JSON.parse(localStorage.getItem(key));
|
|
1427
|
+
// OPTIMISATION: Cache 24h maintenu
|
|
1386
1428
|
if (now - cached.timestamp > 24 * 60 * 60 * 1000) {
|
|
1387
1429
|
localStorage.removeItem(key);
|
|
1388
1430
|
cleaned++;
|