nodebb-plugin-ezoic-infinite 1.4.74 → 1.4.76

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.74",
3
+ "version": "1.4.76",
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
@@ -23,10 +23,6 @@
23
23
  usedPosts: new Set(),
24
24
  usedCategories: new Set(),
25
25
 
26
- liveTopics: [],
27
- livePosts: [],
28
- liveCategories: [],
29
-
30
26
  lastShowById: new Map(),
31
27
  pendingById: new Set(),
32
28
  definedIds: new Set(),
@@ -146,32 +142,22 @@
146
142
  const ph = wrapper.querySelector('[id^="ezoic-pub-ad-placeholder-"]');
147
143
  if (!ph) return;
148
144
 
149
- // Supprimer TOUS les éléments après le placeholder rempli
150
- // qui créent de l'espace vertical
151
- let found = false;
145
+ // SÉCURISÉ: Supprimer TOUT sauf le placeholder
146
+ // CRITIQUE: Ne JAMAIS toucher au placeholder ou ses enfants
152
147
  Array.from(wrapper.children).forEach(child => {
153
- if (child === ph || child.contains(ph)) {
154
- found = true;
155
- return;
156
- }
148
+ // Vérifier que ce n'est PAS le placeholder
149
+ if (child === ph) return;
150
+ if (child.contains(ph)) return;
151
+ if (child.id && child.id.startsWith('ezoic-pub-ad-placeholder-')) return;
157
152
 
158
- // Si élément APRÈS le placeholder
159
- if (found) {
160
- const rect = child.getBoundingClientRect();
161
- const computed = window.getComputedStyle(child);
162
-
163
- // Supprimer si:
164
- // 1. Height > 0 mais pas de texte/image visible
165
- // 2. Ou opacity: 0
166
- // 3. Ou visibility: hidden
167
- const hasContent = child.textContent.trim().length > 0 ||
168
- child.querySelector('img, iframe, video');
169
-
170
- if (!hasContent || computed.opacity === '0' || computed.visibility === 'hidden') {
153
+ // Supprimer le reste
171
154
  child.remove();
172
- }
173
- }
174
155
  });
156
+
157
+ // Forcer wrapper sans espace
158
+ wrapper.style.height = 'auto';
159
+ wrapper.style.overflow = 'hidden';
160
+ wrapper.style.lineHeight = '0';
175
161
  });
176
162
  } catch (e) {}
177
163
  }
@@ -247,7 +233,6 @@
247
233
  wrap.className = `${WRAP_CLASS} ${kindClass}`;
248
234
  wrap.setAttribute('data-ezoic-after', String(afterPos));
249
235
  wrap.style.width = '100%';
250
- wrap.style.display = 'none';
251
236
 
252
237
  const ph = document.createElement('div');
253
238
  ph.id = `${PLACEHOLDER_PREFIX}${id}`;
@@ -323,31 +308,11 @@
323
308
  }
324
309
  }
325
310
 
326
-
327
- function forcePlaceholderAutoHeight(wrap, id) {
328
- try {
329
- if (!wrap) return;
330
- const ph = id ? wrap.querySelector && wrap.querySelector(`#${PLACEHOLDER_PREFIX}${id}`) : (wrap.querySelector && wrap.querySelector(`[id^="${PLACEHOLDER_PREFIX}"]`));
331
- if (!ph) return;
332
- ph.style.setProperty('height', 'auto', 'important');
333
- ph.style.setProperty('min-height', '0px', 'important');
334
- requestAnimationFrame(() => {
335
- try {
336
- ph.style.setProperty('height', 'auto', 'important');
337
- ph.style.setProperty('min-height', '0px', 'important');
338
- } catch (e) {}
339
- });
340
- } catch (e) {}
341
- }
342
-
343
- function markFilled(wrap, id) {
311
+ function markFilled(wrap) {
344
312
  try {
345
313
  if (!wrap) return;
346
314
  if (wrap.__ezoicFillObs) { wrap.__ezoicFillObs.disconnect(); wrap.__ezoicFillObs = null; }
347
315
  wrap.setAttribute('data-ezoic-filled', '1');
348
- // show wrapper only when filled (avoid blank gaps if consent/CMP blocks)
349
- wrap.style.display = 'block';
350
- forcePlaceholderAutoHeight(wrap, id);
351
316
  } catch (e) {}
352
317
  }
353
318
 
@@ -361,13 +326,13 @@
361
326
  if (!ph) return;
362
327
  // Already filled?
363
328
  if (ph.childNodes && ph.childNodes.length > 0) {
364
- markFilled(wrap, id); // Afficher wrapper
329
+ markFilled(wrap); // Afficher wrapper
365
330
  sessionDefinedIds.add(id);
366
331
  return;
367
332
  }
368
333
  const obs = new MutationObserver(() => {
369
334
  if (ph.childNodes && ph.childNodes.length > 0) {
370
- markFilled(wrap, id); // CRITIQUE: Afficher wrapper maintenant
335
+ markFilled(wrap); // CRITIQUE: Afficher wrapper maintenant
371
336
  try { sessionDefinedIds.add(id); } catch (e) {}
372
337
  try { obs.disconnect(); } catch (e) {}
373
338
  }
@@ -387,7 +352,7 @@
387
352
  const filled = !!(ph.childNodes && ph.childNodes.length > 0);
388
353
  if (filled) {
389
354
  try { state.definedIds && state.definedIds.add(id); sessionDefinedIds.add(id); } catch (e) {}
390
- try { markFilled(wrap, id); } catch (e) {}
355
+ try { markFilled(wrap); } catch (e) {}
391
356
  }
392
357
  return filled;
393
358
  }
@@ -419,6 +384,14 @@
419
384
  const idsArray = Array.from(pendingShowAdsIds);
420
385
  pendingShowAdsIds.clear();
421
386
 
387
+ // CRITIQUE: Vérifier que placeholders existent encore
388
+ const validIds = idsArray.filter(id => {
389
+ const ph = document.getElementById(`${PLACEHOLDER_PREFIX}${id}`);
390
+ return ph && ph.isConnected;
391
+ });
392
+
393
+ if (validIds.length === 0) return;
394
+
422
395
  // Appeler showAds avec TOUS les IDs en une fois
423
396
  try {
424
397
  window.ezstandalone = window.ezstandalone || {};
@@ -426,9 +399,9 @@
426
399
  window.ezstandalone.cmd.push(function() {
427
400
  if (typeof window.ezstandalone.showAds === 'function') {
428
401
  // Appel batch: showAds(id1, id2, id3...)
429
- window.ezstandalone.showAds(...idsArray);
402
+ window.ezstandalone.showAds(...validIds);
430
403
  // Tracker tous les IDs
431
- idsArray.forEach(id => {
404
+ validIds.forEach(id => {
432
405
  state.lastShowById.set(id, Date.now());
433
406
  sessionDefinedIds.add(id);
434
407
  });
@@ -439,7 +412,7 @@
439
412
  // CRITIQUE: Nettoyer éléments invisibles APRÈS que pubs soient chargées
440
413
  setTimeout(() => {
441
414
  cleanupInvisibleEzoicElements();
442
- }, 800); // 1.5s pour laisser Ezoic charger
415
+ }, 1500); // 1.5s pour laisser Ezoic charger
443
416
  }, 100);
444
417
  }
445
418
 
@@ -454,8 +427,6 @@
454
427
  window.ezstandalone = window.ezstandalone || {};
455
428
  if (typeof window.ezstandalone.showAds === 'function') {
456
429
 
457
- const elNow = document.getElementById(phId);
458
- if (!elNow || !elNow.isConnected) return false;
459
430
  state.lastShowById.set(id, Date.now());
460
431
  window.ezstandalone.showAds(id);
461
432
  sessionDefinedIds.add(id);
@@ -531,7 +502,7 @@
531
502
  return Array.from(new Set(out)).sort((a, b) => a - b);
532
503
  }
533
504
 
534
- function injectBetween(kindClass, items, interval, showFirst, kindPool, usedSet, liveArr) {
505
+ function injectBetween(kindClass, items, interval, showFirst, kindPool, usedSet) {
535
506
  if (!items.length) return 0;
536
507
  const targets = computeTargets(items.length, interval, showFirst);
537
508
 
@@ -552,7 +523,7 @@
552
523
 
553
524
  if (findWrap(kindClass, afterPos)) continue;
554
525
 
555
- const pick = pickId(kindPool, liveArr || []);
526
+ const pick = pickId(kindPool, []);
556
527
  const id = pick.id;
557
528
  if (!id) break;
558
529
 
@@ -578,7 +549,7 @@
578
549
  callShowAdsWhenReady(id);
579
550
  }
580
551
 
581
- if (liveArr) liveArr.push({ id, wrap });
552
+ liveArr.push({ id, wrap });
582
553
  if (wrap && (
583
554
  (wrap.previousElementSibling && wrap.previousElementSibling.classList && wrap.previousElementSibling.classList.contains(WRAP_CLASS)) || (wrap.nextElementSibling && wrap.nextElementSibling.classList && wrap.nextElementSibling.classList.contains(WRAP_CLASS))
584
555
  )) {
@@ -678,7 +649,7 @@
678
649
  Math.max(1, parseInt(cfg.messageIntervalPosts, 10) || 3),
679
650
  normalizeBool(cfg.showFirstMessageAd),
680
651
  state.poolPosts,
681
- state.usedPosts, state.livePosts);
652
+ state.usedPosts);
682
653
  }
683
654
  } else if (kind === 'categoryTopics') {
684
655
  if (normalizeBool(cfg.enableBetweenAds)) {
@@ -686,7 +657,7 @@
686
657
  Math.max(1, parseInt(cfg.intervalPosts, 10) || 6),
687
658
  normalizeBool(cfg.showFirstTopicAd),
688
659
  state.poolTopics,
689
- state.usedTopics, state.liveTopics);
660
+ state.usedTopics);
690
661
  }
691
662
  } else if (kind === 'categories') {
692
663
  if (normalizeBool(cfg.enableCategoryAds)) {
@@ -694,7 +665,7 @@
694
665
  Math.max(1, parseInt(cfg.intervalCategories, 10) || 4),
695
666
  normalizeBool(cfg.showFirstCategoryAd),
696
667
  state.poolCategories,
697
- state.usedCategories, state.liveCategories);
668
+ state.usedCategories);
698
669
  }
699
670
  }
700
671
 
package/public/style.css CHANGED
@@ -1,40 +1,21 @@
1
- /* Ezoic Infinite Ads (NodeBB) - production safe */
2
- /* Hide wrappers until ad actually fills to avoid blank gaps (e.g., CMP/consent issues) */
3
- .ezoic-ad{
4
- display:none;
5
- height:auto !important;
6
- min-height:0 !important;
7
- padding:0 !important;
8
- margin:0 !important;
9
- width:100%;
1
+ .ezoic-ad {
2
+ height: auto !important;
3
+ padding: 0 !important;
4
+ margin: 0 !important;
5
+ border: 0 !important;
6
+ overflow: hidden !important;
7
+ line-height: 0 !important;
10
8
  }
11
9
 
12
- /* Marked filled => show */
13
- .ezoic-ad[data-ezoic-filled="1"]{
14
- display:block;
10
+ .ezoic-ad * {
11
+ margin: 0 !important;
12
+ padding: 0 !important;
13
+ border: 0 !important;
15
14
  }
16
15
 
17
- /* Placeholder must not reserve fixed height */
18
- .ezoic-ad > [id^="ezoic-pub-ad-placeholder-"]{
19
- height:auto !important;
20
- min-height:0 !important;
21
- margin:0 !important;
22
- padding:0 !important;
23
- }
24
-
25
- /* Prevent baseline gaps under iframes/ins */
26
- .ezoic-ad iframe,
27
- .ezoic-ad ins{
28
- display:block !important;
29
- }
30
-
31
- /* Remove empty spacer divs if any */
32
- .ezoic-ad > div:empty{
33
- display:none !important;
34
- }
35
-
36
- /* Defensive: wipe margins/paddings inside wrapper */
37
- .ezoic-ad *{
38
- margin:0 !important;
39
- padding:0 !important;
40
- }
16
+ .ezoic-ad::after {
17
+ content: '';
18
+ display: block;
19
+ height: 0 !important;
20
+ margin: 0 !important;
21
+ }