@bebranded/bb-contents 1.0.28-beta → 1.0.30-beta
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 +158 -10
- 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.30-beta
|
|
5
5
|
* @author BeBranded
|
|
6
6
|
* @license MIT
|
|
7
7
|
* @website https://www.bebranded.xyz
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
|
|
18
18
|
// Configuration
|
|
19
19
|
const config = {
|
|
20
|
-
version: '1.0.
|
|
20
|
+
version: '1.0.30-beta',
|
|
21
21
|
debug: window.location.hostname === 'localhost' || window.location.hostname.includes('webflow.io'),
|
|
22
22
|
prefix: 'bb-', // utilisé pour générer les sélecteurs (data-bb-*)
|
|
23
23
|
i18n: {
|
|
@@ -526,11 +526,69 @@
|
|
|
526
526
|
|
|
527
527
|
// Module YouTube Feed
|
|
528
528
|
youtube: {
|
|
529
|
+
// Détection des bots pour éviter les appels API inutiles
|
|
530
|
+
isBot: function() {
|
|
531
|
+
const userAgent = navigator.userAgent.toLowerCase();
|
|
532
|
+
const botPatterns = [
|
|
533
|
+
'bot', 'crawler', 'spider', 'scraper', 'googlebot', 'bingbot', 'slurp',
|
|
534
|
+
'duckduckbot', 'baiduspider', 'yandexbot', 'facebookexternalhit', 'twitterbot',
|
|
535
|
+
'linkedinbot', 'whatsapp', 'telegrambot', 'discordbot', 'slackbot'
|
|
536
|
+
];
|
|
537
|
+
|
|
538
|
+
return botPatterns.some(pattern => userAgent.includes(pattern)) ||
|
|
539
|
+
navigator.webdriver ||
|
|
540
|
+
!navigator.userAgent;
|
|
541
|
+
},
|
|
542
|
+
|
|
543
|
+
// Gestion du cache localStorage
|
|
544
|
+
cache: {
|
|
545
|
+
get: function(key) {
|
|
546
|
+
try {
|
|
547
|
+
const cached = localStorage.getItem(key);
|
|
548
|
+
if (!cached) return null;
|
|
549
|
+
|
|
550
|
+
const data = JSON.parse(cached);
|
|
551
|
+
const now = Date.now();
|
|
552
|
+
|
|
553
|
+
// Cache expiré après 24h
|
|
554
|
+
if (now - data.timestamp > 24 * 60 * 60 * 1000) {
|
|
555
|
+
localStorage.removeItem(key);
|
|
556
|
+
return null;
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
return data.value;
|
|
560
|
+
} catch (e) {
|
|
561
|
+
return null;
|
|
562
|
+
}
|
|
563
|
+
},
|
|
564
|
+
|
|
565
|
+
set: function(key, value) {
|
|
566
|
+
try {
|
|
567
|
+
const data = {
|
|
568
|
+
value: value,
|
|
569
|
+
timestamp: Date.now()
|
|
570
|
+
};
|
|
571
|
+
localStorage.setItem(key, JSON.stringify(data));
|
|
572
|
+
} catch (e) {
|
|
573
|
+
// Ignorer les erreurs de localStorage
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
},
|
|
577
|
+
|
|
529
578
|
detect: function(scope) {
|
|
530
579
|
return scope.querySelector('[bb-youtube-channel]') !== null;
|
|
531
580
|
},
|
|
532
581
|
|
|
533
582
|
init: function(scope) {
|
|
583
|
+
// Vérifier si c'est un bot - pas d'appel API
|
|
584
|
+
if (this.isBot()) {
|
|
585
|
+
bbContents.utils.log('Bot détecté, pas de chargement YouTube (économie API)');
|
|
586
|
+
return;
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
// Nettoyer le cache expiré au démarrage
|
|
590
|
+
this.cleanCache();
|
|
591
|
+
|
|
534
592
|
const elements = scope.querySelectorAll('[bb-youtube-channel]');
|
|
535
593
|
if (elements.length === 0) return;
|
|
536
594
|
|
|
@@ -585,6 +643,16 @@
|
|
|
585
643
|
// Marquer l'élément comme traité par le module YouTube
|
|
586
644
|
element.setAttribute('data-bb-youtube-processed', 'true');
|
|
587
645
|
|
|
646
|
+
// Vérifier le cache d'abord
|
|
647
|
+
const cacheKey = `youtube_${channelId}_${videoCount}_${allowShorts}`;
|
|
648
|
+
const cachedData = this.cache.get(cacheKey);
|
|
649
|
+
|
|
650
|
+
if (cachedData) {
|
|
651
|
+
bbContents.utils.log('Données YouTube récupérées du cache (économie API)');
|
|
652
|
+
this.generateYouTubeFeed(container, template, cachedData, allowShorts);
|
|
653
|
+
return;
|
|
654
|
+
}
|
|
655
|
+
|
|
588
656
|
// Afficher un loader
|
|
589
657
|
container.innerHTML = '<div style="padding: 20px; text-align: center; color: #6b7280;">Chargement des vidéos YouTube...</div>';
|
|
590
658
|
|
|
@@ -600,10 +668,29 @@
|
|
|
600
668
|
if (data.error) {
|
|
601
669
|
throw new Error(data.error.message || 'Erreur API YouTube');
|
|
602
670
|
}
|
|
671
|
+
|
|
672
|
+
// Sauvegarder en cache pour 24h
|
|
673
|
+
this.cache.set(cacheKey, data);
|
|
674
|
+
bbContents.utils.log('Données YouTube mises en cache pour 24h (économie API)');
|
|
675
|
+
|
|
603
676
|
this.generateYouTubeFeed(container, template, data, allowShorts);
|
|
604
677
|
})
|
|
605
678
|
.catch(error => {
|
|
606
679
|
bbContents.utils.log('Erreur dans le module youtube:', error);
|
|
680
|
+
|
|
681
|
+
// En cas d'erreur, essayer de récupérer du cache même expiré
|
|
682
|
+
const expiredCache = localStorage.getItem(cacheKey);
|
|
683
|
+
if (expiredCache) {
|
|
684
|
+
try {
|
|
685
|
+
const cachedData = JSON.parse(expiredCache);
|
|
686
|
+
bbContents.utils.log('Utilisation du cache expiré en cas d\'erreur API');
|
|
687
|
+
this.generateYouTubeFeed(container, template, cachedData.value, allowShorts);
|
|
688
|
+
return;
|
|
689
|
+
} catch (e) {
|
|
690
|
+
// Ignorer les erreurs de parsing
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
|
|
607
694
|
container.innerHTML = `<div style="padding: 20px; background: #fef2f2; border: 1px solid #fecaca; border-radius: 8px; color: #dc2626;"><strong>Erreur de chargement</strong><br>${error.message}</div>`;
|
|
608
695
|
});
|
|
609
696
|
});
|
|
@@ -655,16 +742,46 @@
|
|
|
655
742
|
element.rel = 'noopener noreferrer';
|
|
656
743
|
}
|
|
657
744
|
|
|
658
|
-
// Remplir la thumbnail (
|
|
745
|
+
// Remplir la thumbnail (qualité optimisée)
|
|
659
746
|
const thumbnail = element.querySelector('[bb-youtube-thumbnail]');
|
|
660
747
|
if (thumbnail) {
|
|
661
|
-
//
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
748
|
+
// Logique optimisée pour la meilleure qualité disponible
|
|
749
|
+
let bestThumbnailUrl = null;
|
|
750
|
+
let bestQuality = 'unknown';
|
|
751
|
+
|
|
752
|
+
// Priorité 1: maxres (1280x720) - qualité maximale
|
|
753
|
+
if (snippet.thumbnails.maxres?.url) {
|
|
754
|
+
bestThumbnailUrl = snippet.thumbnails.maxres.url;
|
|
755
|
+
bestQuality = 'maxres (1280x720)';
|
|
756
|
+
}
|
|
757
|
+
// Priorité 2: high (480x360) - bonne qualité pour l'affichage
|
|
758
|
+
else if (snippet.thumbnails.high?.url) {
|
|
759
|
+
bestThumbnailUrl = snippet.thumbnails.high.url;
|
|
760
|
+
bestQuality = 'high (480x360)';
|
|
761
|
+
}
|
|
762
|
+
// Priorité 3: medium (320x180) - qualité acceptable en dernier recours
|
|
763
|
+
else if (snippet.thumbnails.medium?.url) {
|
|
764
|
+
bestThumbnailUrl = snippet.thumbnails.medium.url;
|
|
765
|
+
bestQuality = 'medium (320x180)';
|
|
766
|
+
}
|
|
767
|
+
// Fallback: default (120x90) - seulement si rien d'autre
|
|
768
|
+
else if (snippet.thumbnails.default?.url) {
|
|
769
|
+
bestThumbnailUrl = snippet.thumbnails.default.url;
|
|
770
|
+
bestQuality = 'default (120x90)';
|
|
771
|
+
}
|
|
772
|
+
|
|
773
|
+
// Appliquer la meilleure thumbnail trouvée
|
|
774
|
+
if (bestThumbnailUrl) {
|
|
775
|
+
thumbnail.src = bestThumbnailUrl;
|
|
776
|
+
thumbnail.alt = snippet.title;
|
|
777
|
+
|
|
778
|
+
// Debug: logger la qualité utilisée (en mode debug seulement)
|
|
779
|
+
if (bbContents.config.debug) {
|
|
780
|
+
bbContents.utils.log(`Thumbnail optimisée pour ${snippet.title}: ${bestQuality}`);
|
|
781
|
+
}
|
|
782
|
+
} else {
|
|
783
|
+
bbContents.utils.log('Aucune thumbnail disponible pour:', snippet.title);
|
|
784
|
+
}
|
|
668
785
|
}
|
|
669
786
|
|
|
670
787
|
// Remplir le titre (avec décodage HTML)
|
|
@@ -711,6 +828,37 @@
|
|
|
711
828
|
const textarea = document.createElement('textarea');
|
|
712
829
|
textarea.innerHTML = text;
|
|
713
830
|
return textarea.value;
|
|
831
|
+
},
|
|
832
|
+
|
|
833
|
+
// Nettoyer le cache expiré
|
|
834
|
+
cleanCache: function() {
|
|
835
|
+
try {
|
|
836
|
+
const keys = Object.keys(localStorage);
|
|
837
|
+
const now = Date.now();
|
|
838
|
+
let cleaned = 0;
|
|
839
|
+
|
|
840
|
+
keys.forEach(key => {
|
|
841
|
+
if (key.startsWith('youtube_')) {
|
|
842
|
+
try {
|
|
843
|
+
const cached = JSON.parse(localStorage.getItem(key));
|
|
844
|
+
if (now - cached.timestamp > 24 * 60 * 60 * 1000) {
|
|
845
|
+
localStorage.removeItem(key);
|
|
846
|
+
cleaned++;
|
|
847
|
+
}
|
|
848
|
+
} catch (e) {
|
|
849
|
+
// Supprimer les clés corrompues
|
|
850
|
+
localStorage.removeItem(key);
|
|
851
|
+
cleaned++;
|
|
852
|
+
}
|
|
853
|
+
}
|
|
854
|
+
});
|
|
855
|
+
|
|
856
|
+
if (cleaned > 0) {
|
|
857
|
+
bbContents.utils.log(`Cache YouTube nettoyé: ${cleaned} entrées supprimées`);
|
|
858
|
+
}
|
|
859
|
+
} catch (e) {
|
|
860
|
+
// Ignorer les erreurs de nettoyage
|
|
861
|
+
}
|
|
714
862
|
}
|
|
715
863
|
}
|
|
716
864
|
};
|