nodebb-plugin-ezoic-infinite 1.4.94 → 1.4.96

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nodebb-plugin-ezoic-infinite",
3
- "version": "1.4.94",
3
+ "version": "1.4.96",
4
4
  "description": "Production-ready Ezoic infinite ads integration for NodeBB 4.x",
5
5
  "main": "library.js",
6
6
  "license": "MIT",
package/public/client.js CHANGED
@@ -7,6 +7,11 @@
7
7
  categoryItem: 'li[component="categories/category"]',
8
8
  }, WRAP_CLASS = 'ezoic-ad';
9
9
  const PLACEHOLDER_PREFIX = 'ezoic-pub-ad-placeholder-', MAX_INSERTS_PER_RUN = 3;
10
+
11
+ // FLAG GLOBAL: Bloquer Ezoic pendant navigation
12
+ let EZOIC_BLOCKED = false;
13
+
14
+ // DEBUG: Vérifier que le plugin charge
10
15
 
11
16
  const sessionDefinedIds = new Set();
12
17
 
@@ -142,35 +147,48 @@
142
147
  const ph = wrapper.querySelector('[id^="ezoic-pub-ad-placeholder-"]');
143
148
  if (!ph) return;
144
149
 
145
- // Supprimer TOUS les éléments après le placeholder rempli
146
- // qui créent de l'espace vertical
147
- let found = false;
150
+ // ULTRA-AGRESSIF: Supprimer TOUT sauf placeholder
148
151
  Array.from(wrapper.children).forEach(child => {
149
- if (child === ph || child.contains(ph)) {
150
- found = true;
151
- return;
152
- }
152
+ if (child === ph || child.contains(ph)) return;
153
+ if (child.id && child.id.startsWith('ezoic-pub-ad-placeholder-')) return;
154
+ child.remove();
155
+ });
153
156
 
154
- // Si élément APRÈS le placeholder
155
- if (found) {
156
- const rect = child.getBoundingClientRect();
157
- const computed = window.getComputedStyle(child);
157
+ // Forcer wrapper collé
158
+ wrapper.style.height = 'auto';
159
+ wrapper.style.overflow = 'hidden';
160
+ wrapper.style.lineHeight = '0';
161
+ wrapper.style.fontSize = '0';
162
+ wrapper.style.margin = '0';
163
+ wrapper.style.padding = '0';
158
164
 
159
- // Supprimer si:
160
- // 1. Height > 0 mais pas de texte/image visible
161
- // 2. Ou opacity: 0
162
- // 3. Ou visibility: hidden
163
- const hasContent = child.textContent.trim().length > 0 ||
164
- child.querySelector('img, iframe, video');
165
+ // CRITIQUE: Forcer suppression margin sur TOUS les .ezoic-ad enfants
166
+ // Pour overrider les margin-top/bottom:15px !important d'Ezoic
167
+ wrapper.querySelectorAll('.ezoic-ad, span.ezoic-ad').forEach(ezSpan => {
168
+ ezSpan.style.setProperty('margin-top', '0', 'important');
169
+ ezSpan.style.setProperty('margin-bottom', '0', 'important');
170
+ ezSpan.style.setProperty('margin-left', '0', 'important');
171
+ ezSpan.style.setProperty('margin-right', '0', 'important');
172
+ });
165
173
 
166
- if (!hasContent || computed.opacity === '0' || computed.visibility === 'hidden') {
174
+ // Nettoyer aussi DANS le placeholder
175
+ if (ph) {
176
+ Array.from(ph.children).forEach(child => {
177
+ // Garder seulement iframe, ins, img
178
+ const tag = child.tagName;
179
+ if (tag !== 'IFRAME' && tag !== 'INS' && tag !== 'IMG' && tag !== 'DIV') {
167
180
  child.remove();
168
181
  }
169
- }
170
182
  });
183
+ }
171
184
  });
172
185
  } catch (e) {}
173
186
  }
187
+
188
+ // Lancer cleanup périodique toutes les 2s
189
+ setInterval(() => {
190
+ try { cleanupInvisibleEzoicElements(); } catch (e) {}
191
+ }, 2000);
174
192
 
175
193
  function cleanupEmptyWrappers() {
176
194
  try {
@@ -293,16 +311,44 @@
293
311
  const orig = ez.showAds;
294
312
 
295
313
  ez.showAds = function (arg) {
314
+ // CRITIQUE: Bloquer TOUS appels si navigation en cours
315
+ if (EZOIC_BLOCKED) {
316
+ return; // Ignorer complètement
317
+ }
318
+
319
+ // Filtrer IDs dont placeholders n'existent pas
320
+ const filterValidIds = (ids) => {
321
+ return ids.filter(id => {
322
+ const phId = `ezoic-pub-ad-placeholder-${id}`;
323
+ const ph = document.getElementById(phId);
324
+ return ph && ph.isConnected;
325
+ });
326
+ };
327
+
296
328
  if (Array.isArray(arg)) {
297
329
  const seen = new Set();
298
330
  for (const v of arg) {
299
331
  const id = parseInt(v, 10);
300
332
  if (!Number.isFinite(id) || id <= 0 || seen.has(id)) continue;
333
+
334
+ // Vérifier existence avant appel
335
+ const phId = `ezoic-pub-ad-placeholder-${id}`;
336
+ const ph = document.getElementById(phId);
337
+ if (!ph || !ph.isConnected) continue;
338
+
301
339
  seen.add(id);
302
340
  try { orig.call(ez, id); } catch (e) {}
303
341
  }
304
342
  return;
305
343
  }
344
+
345
+ // Pour appels simples, vérifier aussi
346
+ if (typeof arg === 'number') {
347
+ const phId = `ezoic-pub-ad-placeholder-${arg}`;
348
+ const ph = document.getElementById(phId);
349
+ if (!ph || !ph.isConnected) return;
350
+ }
351
+
306
352
  return orig.apply(ez, arguments);
307
353
  };
308
354
  } catch (e) {}
@@ -389,21 +435,39 @@
389
435
 
390
436
  clearTimeout(batchShowAdsTimer);
391
437
  batchShowAdsTimer = setTimeout(() => {
438
+ // CRITIQUE: Vérifier que nous sommes toujours sur la même page
439
+ const currentPageKey = getPageKey();
440
+ if (state.pageKey && currentPageKey !== state.pageKey) {
441
+ pendingShowAdsIds.clear();
442
+ return; // Page a changé, annuler
443
+ }
444
+
392
445
  if (pendingShowAdsIds.size === 0) return;
393
446
 
394
447
  const idsArray = Array.from(pendingShowAdsIds);
395
448
  pendingShowAdsIds.clear();
396
449
 
450
+ // CRITIQUE: Vérifier que placeholders existent encore
451
+ const validIds = idsArray.filter(id => {
452
+ const ph = document.getElementById(`${PLACEHOLDER_PREFIX}${id}`);
453
+ return ph && ph.isConnected;
454
+ });
455
+
456
+ if (validIds.length === 0) return;
457
+
397
458
  // Appeler showAds avec TOUS les IDs en une fois
398
459
  try {
460
+ // CRITIQUE: Re-patcher AVANT chaque appel pour être sûr
461
+ patchShowAds();
462
+
399
463
  window.ezstandalone = window.ezstandalone || {};
400
464
  window.ezstandalone.cmd = window.ezstandalone.cmd || [];
401
465
  window.ezstandalone.cmd.push(function() {
402
466
  if (typeof window.ezstandalone.showAds === 'function') {
403
467
  // Appel batch: showAds(id1, id2, id3...)
404
- window.ezstandalone.showAds(...idsArray);
468
+ window.ezstandalone.showAds(...validIds);
405
469
  // Tracker tous les IDs
406
- idsArray.forEach(id => {
470
+ validIds.forEach(id => {
407
471
  state.lastShowById.set(id, Date.now());
408
472
  sessionDefinedIds.add(id);
409
473
  });
@@ -414,7 +478,7 @@
414
478
  // CRITIQUE: Nettoyer éléments invisibles APRÈS que pubs soient chargées
415
479
  setTimeout(() => {
416
480
  cleanupInvisibleEzoicElements();
417
- }, 800); // 1.5s pour laisser Ezoic charger
481
+ }, 1500); // 1.5s pour laisser Ezoic charger
418
482
  }, 100);
419
483
  }
420
484
 
@@ -590,9 +654,45 @@
590
654
  }
591
655
 
592
656
  function cleanup() {
593
- destroyUsedPlaceholders();
657
+ // DEBUG: Vérifier que cleanup est appelé
658
+ // CRITIQUE: BLOQUER Ezoic immédiatement
659
+ EZOIC_BLOCKED = true;
660
+
661
+ // Détruire TOUS les placeholders Ezoic AVANT de supprimer DOM
662
+ const allWrappers = document.querySelectorAll('.ezoic-ad');
663
+ const allIds = [];
664
+ allWrappers.forEach(wrapper => {
665
+ const ph = wrapper.querySelector('[id^="ezoic-pub-ad-placeholder-"]');
666
+ if (ph) {
667
+ const match = ph.id.match(/\d+/);
668
+ if (match) allIds.push(parseInt(match[0]));
669
+ }
670
+ });
671
+
672
+ // CRITIQUE: Vider COMPLÈTEMENT sessionDefinedIds
673
+ // Pour éviter que d'anciens IDs soient encore en mémoire
674
+
675
+ // CRITIQUE: Détruire AUSSI tous les IDs tracés dans state
676
+ // Pour annuler les anciens IDs qu'Ezoic a en mémoire
677
+ const trackedIds = [
678
+ ...Array.from(state.usedTopics),
679
+ ...Array.from(state.usedPosts),
680
+ ...Array.from(state.usedCategories)
681
+ ];
682
+
683
+ const allIdsToDestroy = [...new Set([...allIds, ...trackedIds, ...Array.from(sessionDefinedIds)])];
684
+ sessionDefinedIds.clear(); // ✅ VIDER TOUT
685
+
686
+ if (allIdsToDestroy.length > 0) {
687
+ destroyPlaceholderIds(allIdsToDestroy);
688
+ }
689
+
690
+ // Annuler batch showAds en attente
691
+ pendingShowAdsIds.clear();
692
+ clearTimeout(batchShowAdsTimer);
594
693
 
595
- document.querySelectorAll('.ezoic-ad').forEach(el => {
694
+ // Maintenant supprimer DOM
695
+ allWrappers.forEach(el => {
596
696
  try { el.remove(); } catch (e) {}
597
697
  });
598
698
 
@@ -631,6 +731,11 @@
631
731
  }
632
732
 
633
733
  async function runCore() {
734
+ // CRITIQUE: Ne rien insérer si navigation en cours
735
+ if (EZOIC_BLOCKED) {
736
+ return;
737
+ }
738
+
634
739
  if (!state.canShowAds) {
635
740
  return;
636
741
  }
@@ -718,9 +823,16 @@
718
823
 
719
824
  $(window).on('action:ajaxify.end.ezoicInfinite', () => {
720
825
  state.pageKey = getPageKey();
826
+
827
+ // Débloquer Ezoic IMMÉDIATEMENT pour la nouvelle page
828
+ EZOIC_BLOCKED = false;
829
+
721
830
  ensureObserver();
722
831
 
723
832
  state.canShowAds = true;
833
+
834
+ // CRITIQUE: Relancer insertion maintenant que navigation est terminée
835
+ scheduleRun();
724
836
  });
725
837
 
726
838
  $(window).on('action:category.loaded.ezoicInfinite', () => {
package/public/style.css CHANGED
@@ -1,10 +1,7 @@
1
- .ezoic-ad {
2
- height: auto !important;
3
- padding: 0 !important;
4
- margin: 0 !important;
5
- }
6
-
7
- .ezoic-ad * {
8
- margin: 0 !important;
9
- padding: 0 !important;
1
+ .ezoic-ad,
2
+ .ezoic-ad *,
3
+ span.ezoic-ad,
4
+ span[class*="ezoic"] {
5
+ min-height: 0 !important;
6
+ min-width: 0 !important;
10
7
  }