nodebb-plugin-ezoic-infinite 1.2.3 → 1.2.5

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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/public/client.js +50 -2
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nodebb-plugin-ezoic-infinite",
3
- "version": "1.2.3",
3
+ "version": "1.2.5",
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
@@ -93,11 +93,57 @@
93
93
  return 'category';
94
94
  }
95
95
 
96
+
97
+ function getTopicItems() {
98
+ return Array.from(document.querySelectorAll(SELECTORS.topicItem));
99
+ }
100
+
101
+ function getPostContainers() {
102
+ // Harmony can include multiple [component="post"] blocks (e.g. parent previews, nested structures).
103
+ // We only want top-level post containers that actually contain post content.
104
+ const nodes = Array.from(document.querySelectorAll(SELECTORS.postItem));
105
+ return nodes.filter((el) => {
106
+ if (!el || !el.isConnected) return false;
107
+
108
+ // Must contain post content
109
+ if (!el.querySelector('[component="post/content"]')) return false;
110
+
111
+ // Must not be nested within another post container
112
+ const parentPost = el.parentElement && el.parentElement.closest('[component="post"][data-pid]');
113
+ if (parentPost && parentPost !== el) return false;
114
+
115
+ // Avoid "parent/quote" blocks that use component="post/parent"
116
+ if (el.getAttribute('component') === 'post/parent') return false;
117
+
118
+ return true;
119
+ });
120
+ }
121
+
96
122
  function hasAdImmediatelyAfter(el) {
97
123
  const n = el && el.nextElementSibling;
98
124
  return !!(n && n.classList && n.classList.contains(WRAP_CLASS));
99
125
  }
100
126
 
127
+ function enforceNoAdjacentAds() {
128
+ // NodeBB can virtualize (remove) topics/posts from the DOM while keeping our ad wrappers,
129
+ // which can temporarily make two ad wrappers adjacent. Hide the later one to avoid back-to-back ads.
130
+ const ads = Array.from(document.querySelectorAll(`.${WRAP_CLASS}`));
131
+ for (let i = 0; i < ads.length; i++) {
132
+ const ad = ads[i];
133
+ const prev = ad.previousElementSibling;
134
+ if (prev && prev.classList && prev.classList.contains(WRAP_CLASS)) {
135
+ ad.style.display = 'none';
136
+ } else {
137
+ ad.style.display = '';
138
+ }
139
+ }
140
+ }
141
+
142
+
143
+ const n = el && el.nextElementSibling;
144
+ return !!(n && n.classList && n.classList.contains(WRAP_CLASS));
145
+ }
146
+
101
147
  function buildWrap(id, kind, afterPos) {
102
148
  const wrap = document.createElement('div');
103
149
  wrap.className = `${WRAP_CLASS} ${kind}`;
@@ -248,7 +294,7 @@
248
294
  const interval = Math.max(1, parseInt(cfg.intervalPosts, 10) || 6);
249
295
  const first = normalizeBool(cfg.showFirstTopicAd);
250
296
 
251
- const items = Array.from(document.querySelectorAll(SELECTORS.topicItem));
297
+ const items = getTopicItems();
252
298
  if (!items.length) return 0;
253
299
 
254
300
  let inserted = 0;
@@ -288,7 +334,7 @@
288
334
  const interval = Math.max(1, parseInt(cfg.messageIntervalPosts, 10) || 3);
289
335
  const first = normalizeBool(cfg.showFirstMessageAd);
290
336
 
291
- const posts = Array.from(document.querySelectorAll(SELECTORS.postItem));
337
+ const posts = getPostContainers();
292
338
  if (!posts.length) return 0;
293
339
 
294
340
  let inserted = 0;
@@ -366,6 +412,8 @@
366
412
  if (kind === 'topic') inserted = injectPosts(cfg);
367
413
  else inserted = injectTopics(cfg);
368
414
 
415
+ enforceNoAdjacentAds();
416
+
369
417
  // If we inserted max per run, schedule another pass to gradually fill (avoids “burst”)
370
418
  if (inserted >= MAX_INSERTS_PER_RUN) {
371
419
  setTimeout(() => scheduleRun('continue-fill'), 120);