nodebb-plugin-ezoic-infinite 1.4.95 → 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.95",
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,8 +7,12 @@
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
- // Nécessaire pour savoir si on doit appeler destroyPlaceholders avant recyclage.
12
16
  const sessionDefinedIds = new Set();
13
17
 
14
18
  const insertingIds = new Set(), state = {
@@ -106,9 +110,7 @@
106
110
 
107
111
  function destroyPlaceholderIds(ids) {
108
112
  if (!ids || !ids.length) return;
109
- // Only destroy ids that were actually "defined" (filled at least once) to avoid Ezoic warnings.
110
113
  const filtered = ids.filter((id) => {
111
- // Utiliser sessionDefinedIds (survit aux navigations) plutôt que state.definedIds
112
114
  try { return sessionDefinedIds.has(id); } catch (e) { return true; }
113
115
  });
114
116
  if (!filtered.length) return;
@@ -119,6 +121,11 @@
119
121
  window.ezstandalone.destroyPlaceholders(filtered);
120
122
  }
121
123
  } catch (e) {}
124
+
125
+ // Recyclage: libérer IDs après 100ms
126
+ setTimeout(() => {
127
+ filtered.forEach(id => sessionDefinedIds.delete(id));
128
+ }, 100);
122
129
  };
123
130
  try {
124
131
  window.ezstandalone = window.ezstandalone || {};
@@ -126,10 +133,63 @@
126
133
  if (window.ezstandalone && typeof window.ezstandalone.destroyPlaceholders === 'function') call();
127
134
  else window.ezstandalone.cmd.push(call);
128
135
  } catch (e) {}
136
+
137
+ // Recyclage: libérer IDs après 100ms
138
+ setTimeout(() => {
139
+ filtered.forEach(id => sessionDefinedIds.delete(id));
140
+ }, 100);
129
141
  }
130
142
 
143
+ // Nettoyer éléments Ezoic invisibles qui créent espace vertical
144
+ function cleanupInvisibleEzoicElements() {
145
+ try {
146
+ document.querySelectorAll('.ezoic-ad').forEach(wrapper => {
147
+ const ph = wrapper.querySelector('[id^="ezoic-pub-ad-placeholder-"]');
148
+ if (!ph) return;
149
+
150
+ // ULTRA-AGRESSIF: Supprimer TOUT sauf placeholder
151
+ Array.from(wrapper.children).forEach(child => {
152
+ if (child === ph || child.contains(ph)) return;
153
+ if (child.id && child.id.startsWith('ezoic-pub-ad-placeholder-')) return;
154
+ child.remove();
155
+ });
131
156
 
132
- // Nettoyer les wrappers vides (sans pub) pour éviter espaces verticaux
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';
164
+
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
+ });
173
+
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') {
180
+ child.remove();
181
+ }
182
+ });
183
+ }
184
+ });
185
+ } catch (e) {}
186
+ }
187
+
188
+ // Lancer cleanup périodique toutes les 2s
189
+ setInterval(() => {
190
+ try { cleanupInvisibleEzoicElements(); } catch (e) {}
191
+ }, 2000);
192
+
133
193
  function cleanupEmptyWrappers() {
134
194
  try {
135
195
  document.querySelectorAll('.ezoic-ad').forEach(wrapper => {
@@ -140,7 +200,7 @@
140
200
  if (ph.children.length === 0) {
141
201
  wrapper.remove();
142
202
  }
143
- }, 3000);
203
+ }, 1500);
144
204
  }
145
205
  });
146
206
  } catch (e) {}
@@ -217,10 +277,8 @@
217
277
  if (findWrap(kindClass, afterPos)) return null;
218
278
 
219
279
  // CRITICAL: Double-lock pour éviter race conditions sur les doublons
220
- // 1. Vérifier qu'aucun autre thread n'est en train d'insérer cet ID
221
280
  if (insertingIds.has(id)) return null;
222
281
 
223
- // 2. Vérifier qu'aucun placeholder avec cet ID n'existe déjà dans le DOM
224
282
  const existingPh = document.getElementById(`${PLACEHOLDER_PREFIX}${id}`);
225
283
  if (existingPh && existingPh.isConnected) return null;
226
284
 
@@ -233,7 +291,6 @@
233
291
  attachFillObserver(wrap, id);
234
292
  return wrap;
235
293
  } finally {
236
- // Libérer le lock après 100ms (le temps que le DOM soit stable)
237
294
  setTimeout(() => insertingIds.delete(id), 50);
238
295
  }
239
296
  }
@@ -244,8 +301,6 @@
244
301
  }
245
302
 
246
303
  function patchShowAds() {
247
- // Minimal safety net: batch showAds can be triggered by other scripts; split into individual calls.
248
- // Also ensures the patch is applied even if Ezoic loads after our script.
249
304
  const applyPatch = () => {
250
305
  try {
251
306
  window.ezstandalone = window.ezstandalone || {}, ez = window.ezstandalone;
@@ -256,23 +311,50 @@
256
311
  const orig = ez.showAds;
257
312
 
258
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
+
259
328
  if (Array.isArray(arg)) {
260
329
  const seen = new Set();
261
330
  for (const v of arg) {
262
331
  const id = parseInt(v, 10);
263
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
+
264
339
  seen.add(id);
265
340
  try { orig.call(ez, id); } catch (e) {}
266
341
  }
267
342
  return;
268
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
+
269
352
  return orig.apply(ez, arguments);
270
353
  };
271
354
  } catch (e) {}
272
355
  };
273
356
 
274
357
  applyPatch();
275
- // Si Ezoic n'est pas encore chargé, appliquer le patch via sa cmd queue
276
358
  if (!window.__nodebbEzoicPatched) {
277
359
  try {
278
360
  window.ezstandalone = window.ezstandalone || {};
@@ -285,7 +367,6 @@
285
367
  function markFilled(wrap) {
286
368
  try {
287
369
  if (!wrap) return;
288
- // Disconnect the fill observer first (no need to remove+re-add the attribute)
289
370
  if (wrap.__ezoicFillObs) { wrap.__ezoicFillObs.disconnect(); wrap.__ezoicFillObs = null; }
290
371
  wrap.setAttribute('data-ezoic-filled', '1');
291
372
  } catch (e) {}
@@ -301,19 +382,18 @@
301
382
  if (!ph) return;
302
383
  // Already filled?
303
384
  if (ph.childNodes && ph.childNodes.length > 0) {
304
- markFilled(wrap);
305
- state.definedIds && state.definedIds.add(id); sessionDefinedIds.add(id);
385
+ markFilled(wrap); // Afficher wrapper
386
+ sessionDefinedIds.add(id);
306
387
  return;
307
388
  }
308
389
  const obs = new MutationObserver(() => {
309
390
  if (ph.childNodes && ph.childNodes.length > 0) {
310
- markFilled(wrap);
311
- try { state.definedIds && state.definedIds.add(id); sessionDefinedIds.add(id); } catch (e) {}
391
+ markFilled(wrap); // CRITIQUE: Afficher wrapper maintenant
392
+ try { sessionDefinedIds.add(id); } catch (e) {}
312
393
  try { obs.disconnect(); } catch (e) {}
313
394
  }
314
395
  });
315
396
  obs.observe(ph, { childList: true, subtree: true });
316
- // Keep a weak reference on the wrapper so we can disconnect on recycle/remove
317
397
  wrap.__ezoicFillObs = obs;
318
398
  } catch (e) {}
319
399
  }
@@ -333,15 +413,12 @@
333
413
  return filled;
334
414
  }
335
415
 
336
- // Appeler showAds() en batch selon recommandations Ezoic
337
- // Au lieu de showAds(id1), showAds(id2)... faire showAds(id1, id2, id3...)
338
416
  let batchShowAdsTimer = null;
339
417
  const pendingShowAdsIds = new Set();
340
418
 
341
419
  function scheduleShowAdsBatch(id) {
342
420
  if (!id) return;
343
421
 
344
- // CRITIQUE: Si cet ID a déjà été défini (sessionDefinedIds), le détruire d'abord
345
422
  if (sessionDefinedIds.has(id)) {
346
423
  try {
347
424
  destroyPlaceholderIds([id]);
@@ -356,30 +433,52 @@
356
433
  // Ajouter à la batch
357
434
  pendingShowAdsIds.add(id);
358
435
 
359
- // Debounce: attendre 100ms pour collecter tous les IDs
360
436
  clearTimeout(batchShowAdsTimer);
361
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
+
362
445
  if (pendingShowAdsIds.size === 0) return;
363
446
 
364
447
  const idsArray = Array.from(pendingShowAdsIds);
365
448
  pendingShowAdsIds.clear();
366
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
+
367
458
  // Appeler showAds avec TOUS les IDs en une fois
368
459
  try {
460
+ // CRITIQUE: Re-patcher AVANT chaque appel pour être sûr
461
+ patchShowAds();
462
+
369
463
  window.ezstandalone = window.ezstandalone || {};
370
464
  window.ezstandalone.cmd = window.ezstandalone.cmd || [];
371
465
  window.ezstandalone.cmd.push(function() {
372
466
  if (typeof window.ezstandalone.showAds === 'function') {
373
467
  // Appel batch: showAds(id1, id2, id3...)
374
- window.ezstandalone.showAds(...idsArray);
468
+ window.ezstandalone.showAds(...validIds);
375
469
  // Tracker tous les IDs
376
- idsArray.forEach(id => {
470
+ validIds.forEach(id => {
377
471
  state.lastShowById.set(id, Date.now());
378
472
  sessionDefinedIds.add(id);
379
473
  });
380
474
  }
381
475
  });
382
476
  } catch (e) {}
477
+
478
+ // CRITIQUE: Nettoyer éléments invisibles APRÈS que pubs soient chargées
479
+ setTimeout(() => {
480
+ cleanupInvisibleEzoicElements();
481
+ }, 1500); // 1.5s pour laisser Ezoic charger
383
482
  }, 100);
384
483
  }
385
484
 
@@ -406,19 +505,15 @@
406
505
  const startPageKey = state.pageKey;
407
506
  let attempts = 0;
408
507
  (function waitForPh() {
409
- // Abort if the user navigated away since this showAds was scheduled
410
508
  if (state.pageKey !== startPageKey) return;
411
- // Abort if another concurrent call is already handling this id
412
509
  if (state.pendingById.has(id)) return;
413
510
 
414
511
  attempts += 1;
415
512
  const el = document.getElementById(phId);
416
513
  if (el && el.isConnected) {
417
- // CRITIQUE: Vérifier que le placeholder est VISIBLE
418
514
 
419
515
  // Si on arrive ici, soit visible, soit timeout
420
516
 
421
- // Si doCall() réussit, Ezoic est chargé et showAds a été appelé → sortir
422
517
  if (doCall()) {
423
518
  state.pendingById.delete(id);
424
519
  return;
@@ -484,7 +579,6 @@
484
579
  const el = items[afterPos - 1];
485
580
  if (!el || !el.isConnected) continue;
486
581
 
487
- // Prevent adjacent ads (DOM-based, robust against virtualization)
488
582
  if (isAdjacentAd(el) || isPrevAd(el)) {
489
583
  continue;
490
584
  }
@@ -501,17 +595,14 @@
501
595
 
502
596
  let wrap = null;
503
597
  if (pick.recycled && pick.recycled.wrap) {
504
- // Only destroy if Ezoic has actually defined this placeholder before
505
598
  if (sessionDefinedIds.has(id)) {
506
599
  destroyPlaceholderIds([id]);
507
600
  }
508
- // Remove the old wrapper entirely, then create a fresh wrapper at the new position (same id)
509
601
  const oldWrap = pick.recycled.wrap;
510
602
  try { if (oldWrap && oldWrap.__ezoicFillObs) { oldWrap.__ezoicFillObs.disconnect(); } } catch (e) {}
511
603
  try { oldWrap && oldWrap.remove(); } catch (e) {}
512
604
  wrap = insertAfter(el, id, kindClass, afterPos);
513
605
  if (!wrap) continue;
514
- // Attendre que le wrapper soit dans le DOM puis appeler showAds
515
606
  setTimeout(() => {
516
607
  callShowAdsWhenReady(id);
517
608
  }, 50);
@@ -525,12 +616,10 @@
525
616
  }
526
617
 
527
618
  liveArr.push({ id, wrap });
528
- // If adjacency ended up happening (e.g. DOM shifts), rollback this placement.
529
619
  if (wrap && (
530
620
  (wrap.previousElementSibling && wrap.previousElementSibling.classList && wrap.previousElementSibling.classList.contains(WRAP_CLASS)) || (wrap.nextElementSibling && wrap.nextElementSibling.classList && wrap.nextElementSibling.classList.contains(WRAP_CLASS))
531
621
  )) {
532
622
  try { wrap.remove(); } catch (e) {}
533
- // Put id back if it was newly consumed (not recycled)
534
623
  if (!(pick.recycled && pick.recycled.wrap)) {
535
624
  try { kindPool.unshift(id); } catch (e) {}
536
625
  usedSet.delete(id);
@@ -547,7 +636,6 @@
547
636
  for (let i = 0; i < ads.length; i++) {
548
637
  const ad = ads[i], prev = ad.previousElementSibling;
549
638
  if (prev && prev.classList && prev.classList.contains(WRAP_CLASS)) {
550
- // Supprimer le wrapper adjacent au lieu de le cacher
551
639
  try {
552
640
  const ph = ad.querySelector && ad.querySelector(`[id^="${PLACEHOLDER_PREFIX}"]`);
553
641
  if (ph) {
@@ -566,11 +654,45 @@
566
654
  }
567
655
 
568
656
  function cleanup() {
569
- 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);
570
693
 
571
- // CRITIQUE: Supprimer TOUS les wrappers .ezoic-ad du DOM
572
- // Sinon ils restent et deviennent "unused" sur la nouvelle page
573
- document.querySelectorAll('.ezoic-ad').forEach(el => {
694
+ // Maintenant supprimer DOM
695
+ allWrappers.forEach(el => {
574
696
  try { el.remove(); } catch (e) {}
575
697
  });
576
698
 
@@ -585,23 +707,14 @@
585
707
  state.usedPosts.clear();
586
708
  state.usedCategories.clear();
587
709
  state.lastShowById.clear();
588
- // CRITIQUE: Vider pendingById pour annuler tous les showAds en cours
589
- // Sinon Ezoic essaie d'accéder aux placeholders pendant que NodeBB vide le DOM
590
710
  state.pendingById.clear();
591
711
  state.definedIds.clear();
592
712
 
593
- // NE PAS supprimer les wrappers Ezoic ici - ils seront supprimés naturellement
594
- // quand NodeBB vide le DOM lors de la navigation ajaxify
595
- // Les supprimer manuellement cause des problèmes avec l'état interne d'Ezoic
596
-
597
- // CRITIQUE: Annuler TOUS les timeouts en cours pour éviter que les anciens
598
- // showAds() continuent à s'exécuter après la navigation
599
713
  state.activeTimeouts.forEach(id => {
600
714
  try { clearTimeout(id); } catch (e) {}
601
715
  });
602
716
  state.activeTimeouts.clear();
603
717
 
604
- // Vider aussi pendingById pour annuler les showAds en attente
605
718
  state.pendingById.clear();
606
719
 
607
720
  if (state.obs) { state.obs.disconnect(); state.obs = null; }
@@ -618,7 +731,11 @@
618
731
  }
619
732
 
620
733
  async function runCore() {
621
- // Attendre que canInsert soit true (protection race condition navigation)
734
+ // CRITIQUE: Ne rien insérer si navigation en cours
735
+ if (EZOIC_BLOCKED) {
736
+ return;
737
+ }
738
+
622
739
  if (!state.canShowAds) {
623
740
  return;
624
741
  }
@@ -661,7 +778,6 @@
661
778
 
662
779
  enforceNoAdjacentAds();
663
780
 
664
- // If nothing inserted and list isn't in DOM yet (first click), retry a bit
665
781
  let count = 0;
666
782
  if (kind === 'topic') count = getPostContainers().length;
667
783
  else if (kind === 'categoryTopics') count = getTopicItems().length;
@@ -673,12 +789,9 @@
673
789
  }
674
790
 
675
791
  if (inserted >= MAX_INSERTS_PER_RUN) {
676
- // Plus d'insertions possibles ce cycle, continuer immédiatement
677
792
  setTimeout(arguments[0], 50);
678
793
  } else if (inserted === 0 && count > 0) {
679
794
  // Pool épuisé ou recyclage pas encore disponible.
680
- // Réessayer jusqu'à 8 fois (toutes les 400ms) pour laisser aux anciens wrappers
681
- // le temps de défiler hors écran et devenir recyclables.
682
795
  if (state.poolWaitAttempts < 8) {
683
796
  state.poolWaitAttempts += 1;
684
797
  setTimeout(arguments[0], 50);
@@ -710,17 +823,20 @@
710
823
 
711
824
  $(window).on('action:ajaxify.end.ezoicInfinite', () => {
712
825
  state.pageKey = getPageKey();
826
+
827
+ // Débloquer Ezoic IMMÉDIATEMENT pour la nouvelle page
828
+ EZOIC_BLOCKED = false;
829
+
713
830
  ensureObserver();
714
831
 
715
- // CRITIQUE: Attendre 300ms avant de permettre l'insertion de nouveaux placeholders
716
- // pour laisser les anciens showAds() (en cours) se terminer ou échouer proprement
717
- // Sinon race condition: NodeBB vide le DOM pendant que Ezoic essaie d'accéder aux placeholders
718
832
  state.canShowAds = true;
833
+
834
+ // CRITIQUE: Relancer insertion maintenant que navigation est terminée
835
+ scheduleRun();
719
836
  });
720
837
 
721
838
  $(window).on('action:category.loaded.ezoicInfinite', () => {
722
839
  ensureObserver();
723
- // category.loaded = infinite scroll, Ezoic déjà chargé normalement
724
840
  waitForContentThenRun();
725
841
  });
726
842
  $(window).on('action:topics.loaded.ezoicInfinite', () => {
@@ -750,7 +866,6 @@
750
866
  window.requestAnimationFrame(() => {
751
867
  ticking = false;
752
868
  enforceNoAdjacentAds();
753
- // Debounce scheduleRun - une fois toutes les 2 secondes max au scroll
754
869
  const now = Date.now();
755
870
  if (!state.lastScrollRun || now - state.lastScrollRun > 2000) {
756
871
  state.lastScrollRun = now;
@@ -760,7 +875,6 @@
760
875
  }, { passive: true });
761
876
  }
762
877
 
763
- // Fonction qui attend que la page ait assez de contenu avant d'insérer les pubs
764
878
  function waitForContentThenRun() {
765
879
  const MIN_WORDS = 250;
766
880
  let attempts = 0;
@@ -791,7 +905,6 @@
791
905
  })();
792
906
  }
793
907
 
794
- // Fonction qui attend que Ezoic soit vraiment chargé
795
908
  function waitForEzoicThenRun() {
796
909
  let attempts = 0;
797
910
  const maxAttempts = 50; // 50 × 200ms = 10s max
package/public/style.css CHANGED
@@ -1,3 +1,7 @@
1
- .ezoic-ad{height:auto !important; padding:0 !important; margin: 0.25rem 0;}
2
- .ezoic-ad .ezoic-ad-inner{padding:0;margin:0;}
3
- .ezoic-ad .ezoic-ad-inner > div{padding:0;margin:0;}
1
+ .ezoic-ad,
2
+ .ezoic-ad *,
3
+ span.ezoic-ad,
4
+ span[class*="ezoic"] {
5
+ min-height: 0 !important;
6
+ min-width: 0 !important;
7
+ }