nodebb-plugin-ezoic-infinite 1.5.27 → 1.5.29

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.5.27",
3
+ "version": "1.5.29",
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
@@ -259,10 +259,70 @@ function withInternalDomChange(fn) {
259
259
  return false;
260
260
  }
261
261
 
262
- function buildWrap(id, kindClass, afterPos) {
262
+
263
+ function getWrapIdFromWrap(wrap) {
264
+ try {
265
+ const v = wrap.getAttribute('data-ezoic-wrapid');
266
+ if (v) return String(v);
267
+ const ph = wrap.querySelector(`[id^="${PLACEHOLDER_PREFIX}"]`);
268
+ if (ph && ph.id) return ph.id.replace(PLACEHOLDER_PREFIX, '');
269
+ } catch (e) {}
270
+ return null;
271
+ }
272
+
273
+ function safeDestroyById(id) {
274
+ try {
275
+ const ez = window.ezstandalone;
276
+ if (ez && typeof ez.destroyPlaceholders === 'function') {
277
+ ez.destroyPlaceholders([`${PLACEHOLDER_PREFIX}${id}`]);
278
+ }
279
+ } catch (e) {}
280
+ }
281
+
282
+ function pruneOrphanWraps(kindClass, items) {
283
+ if (!items || !items.length) return 0;
284
+ const itemSet = new Set(items);
285
+ const wraps = document.querySelectorAll(`.${WRAP_CLASS}.${kindClass}`);
286
+ let removed = 0;
287
+
288
+ wraps.forEach((wrap) => {
289
+ const prev = wrap.previousElementSibling;
290
+ if (!prev || !itemSet.has(prev)) {
291
+ const id = getWrapIdFromWrap(wrap);
292
+ withInternalDomChange(() => {
293
+ try {
294
+ if (id) safeDestroyById(id);
295
+ wrap.remove();
296
+ } catch (e) {}
297
+ });
298
+ removed++;
299
+ }
300
+ });
301
+
302
+ if (removed) dbg('prune-orphan', kindClass, { removed });
303
+ return removed;
304
+ }
305
+
306
+ function refreshEmptyState(id) {
307
+ // After Ezoic has had a moment to fill the placeholder, toggle the CSS class.
308
+ window.setTimeout(() => {
309
+ try {
310
+ const ph = document.getElementById(`${PLACEHOLDER_PREFIX}${id}`);
311
+ if (!ph || !ph.isConnected) return;
312
+ const wrap = ph.closest(`.${WRAP_CLASS}`);
313
+ if (!wrap) return;
314
+ const hasContent = ph.childElementCount > 0 || ph.offsetHeight > 0;
315
+ if (hasContent) wrap.classList.remove('is-empty');
316
+ else wrap.classList.add('is-empty');
317
+ } catch (e) {}
318
+ }, 1800);
319
+ }
320
+
321
+ function buildWrap(id, kindClass, afterPos) {
263
322
  const wrap = document.createElement('div');
264
- wrap.className = `${WRAP_CLASS} ${kindClass}`;
323
+ wrap.className = `${WRAP_CLASS} ${kindClass} is-empty`;
265
324
  wrap.setAttribute('data-ezoic-after', String(afterPos));
325
+ wrap.setAttribute('data-ezoic-wrapid', String(id));
266
326
  wrap.style.width = '100%';
267
327
 
268
328
  const ph = document.createElement('div');
@@ -569,9 +629,11 @@ function withInternalDomChange(fn) {
569
629
 
570
630
  if (kind === 'topic') {
571
631
  if (normalizeBool(cfg.enableMessageAds)) {
632
+ const __items = getPostContainers();
633
+ pruneOrphanWraps('ezoic-ad-message', __items);
572
634
  injectBetween(
573
635
  'ezoic-ad-message',
574
- getPostContainers(),
636
+ __items,
575
637
  Math.max(1, parseInt(cfg.messageIntervalPosts, 10) || 3),
576
638
  normalizeBool(cfg.showFirstMessageAd),
577
639
  state.allPosts,
@@ -580,9 +642,11 @@ function withInternalDomChange(fn) {
580
642
  }
581
643
  } else if (kind === 'categoryTopics') {
582
644
  if (normalizeBool(cfg.enableBetweenAds)) {
645
+ const __items = getTopicItems();
646
+ pruneOrphanWraps('ezoic-ad-between', __items);
583
647
  injectBetween(
584
648
  'ezoic-ad-between',
585
- getTopicItems(),
649
+ __items,
586
650
  Math.max(1, parseInt(cfg.intervalPosts, 10) || 6),
587
651
  normalizeBool(cfg.showFirstTopicAd),
588
652
  state.allTopics,
@@ -591,9 +655,11 @@ function withInternalDomChange(fn) {
591
655
  }
592
656
  } else if (kind === 'categories') {
593
657
  if (normalizeBool(cfg.enableCategoryAds)) {
658
+ const __items = getCategoryItems();
659
+ pruneOrphanWraps('ezoic-ad-categories', __items);
594
660
  injectBetween(
595
661
  'ezoic-ad-categories',
596
- getCategoryItems(),
662
+ __items,
597
663
  Math.max(1, parseInt(cfg.intervalCategories, 10) || 4),
598
664
  normalizeBool(cfg.showFirstCategoryAd),
599
665
  state.allCategories,
package/public/style.css CHANGED
@@ -19,3 +19,21 @@
19
19
  margin: 0 !important;
20
20
  padding: 0 !important;
21
21
  }
22
+
23
+
24
+ /* Collapse empty ad blocks (prevents "holes" when an ad doesn't fill or gets destroyed) */
25
+ .ezoic-ad.is-empty {
26
+ display: none !important;
27
+ margin: 0 !important;
28
+ padding: 0 !important;
29
+ height: 0 !important;
30
+ min-height: 0 !important;
31
+ }
32
+
33
+ .ezoic-ad {
34
+ min-height: 0 !important;
35
+ }
36
+
37
+ .ezoic-ad > [id^="ezoic-pub-ad-placeholder-"] {
38
+ min-height: 0 !important;
39
+ }