nodebb-plugin-ezoic-infinite 1.4.4 → 1.4.6
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 +1 -1
- package/public/client.js +86 -11
package/package.json
CHANGED
package/public/client.js
CHANGED
|
@@ -40,6 +40,8 @@
|
|
|
40
40
|
retryQueue: [],
|
|
41
41
|
retryQueueSet: new Set(),
|
|
42
42
|
retryQueueRunning: false,
|
|
43
|
+
badIds: new Set(),
|
|
44
|
+
definedIds: new Set(),
|
|
43
45
|
|
|
44
46
|
scheduled: false,
|
|
45
47
|
timer: null,
|
|
@@ -121,10 +123,16 @@
|
|
|
121
123
|
|
|
122
124
|
function destroyPlaceholderIds(ids) {
|
|
123
125
|
if (!ids || !ids.length) return;
|
|
126
|
+
// Only destroy ids that were actually "defined" (filled at least once) to avoid Ezoic warnings.
|
|
127
|
+
const filtered = ids.filter((id) => {
|
|
128
|
+
try { return state.definedIds && state.definedIds.has(id); } catch (e) { return true; }
|
|
129
|
+
});
|
|
130
|
+
if (!filtered.length) return;
|
|
131
|
+
|
|
124
132
|
const call = () => {
|
|
125
133
|
try {
|
|
126
134
|
if (window.ezstandalone && typeof window.ezstandalone.destroyPlaceholders === 'function') {
|
|
127
|
-
window.ezstandalone.destroyPlaceholders(
|
|
135
|
+
window.ezstandalone.destroyPlaceholders(filtered);
|
|
128
136
|
}
|
|
129
137
|
} catch (e) {}
|
|
130
138
|
};
|
|
@@ -135,6 +143,15 @@
|
|
|
135
143
|
else window.ezstandalone.cmd.push(call);
|
|
136
144
|
} catch (e) {}
|
|
137
145
|
}
|
|
146
|
+
} catch (e) {}
|
|
147
|
+
};
|
|
148
|
+
try {
|
|
149
|
+
window.ezstandalone = window.ezstandalone || {};
|
|
150
|
+
window.ezstandalone.cmd = window.ezstandalone.cmd || [];
|
|
151
|
+
if (window.ezstandalone && typeof window.ezstandalone.destroyPlaceholders === 'function') call();
|
|
152
|
+
else window.ezstandalone.cmd.push(call);
|
|
153
|
+
} catch (e) {}
|
|
154
|
+
}
|
|
138
155
|
|
|
139
156
|
function getRecyclable(liveArr) {
|
|
140
157
|
const margin = 1800;
|
|
@@ -168,6 +185,34 @@
|
|
|
168
185
|
return { id: null, recycled: null };
|
|
169
186
|
}
|
|
170
187
|
|
|
188
|
+
|
|
189
|
+
function resetPlaceholderInWrap(wrap, id) {
|
|
190
|
+
try {
|
|
191
|
+
if (!wrap) return;
|
|
192
|
+
const old = wrap.querySelector && wrap.querySelector(`#${PLACEHOLDER_PREFIX}${id}`);
|
|
193
|
+
if (old) old.remove();
|
|
194
|
+
// Remove any leftover markup inside wrapper
|
|
195
|
+
wrap.querySelectorAll && wrap.querySelectorAll('iframe, ins').forEach(n => n.remove());
|
|
196
|
+
const ph = document.createElement('div');
|
|
197
|
+
ph.id = `${PLACEHOLDER_PREFIX}${id}`;
|
|
198
|
+
wrap.appendChild(ph);
|
|
199
|
+
} catch (e) {}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
function isAdjacentAd(target) {
|
|
203
|
+
if (!target || !target.nextElementSibling) return false;
|
|
204
|
+
const next = target.nextElementSibling;
|
|
205
|
+
if (next && next.classList && next.classList.contains(WRAP_CLASS)) return true;
|
|
206
|
+
return false;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
function isPrevAd(target) {
|
|
210
|
+
if (!target || !target.previousElementSibling) return false;
|
|
211
|
+
const prev = target.previousElementSibling;
|
|
212
|
+
if (prev && prev.classList && prev.classList.contains(WRAP_CLASS)) return true;
|
|
213
|
+
return false;
|
|
214
|
+
}
|
|
215
|
+
|
|
171
216
|
function buildWrap(id, kindClass, afterPos) {
|
|
172
217
|
const wrap = document.createElement('div');
|
|
173
218
|
wrap.className = `${WRAP_CLASS} ${kindClass}`;
|
|
@@ -243,10 +288,13 @@
|
|
|
243
288
|
function isPlaceholderFilled(id) {
|
|
244
289
|
const ph = document.getElementById(`${PLACEHOLDER_PREFIX}${id}`);
|
|
245
290
|
if (!ph || !ph.isConnected) return false;
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
291
|
+
|
|
292
|
+
// Ezoic typically injects content inside the placeholder node.
|
|
293
|
+
const filled = !!(ph.childNodes && ph.childNodes.length > 0);
|
|
294
|
+
if (filled) {
|
|
295
|
+
try { state.definedIds && state.definedIds.add(id); } catch (e) {}
|
|
296
|
+
}
|
|
297
|
+
return filled;
|
|
250
298
|
}
|
|
251
299
|
|
|
252
300
|
function scheduleRefill(delay = 350) {
|
|
@@ -256,6 +304,7 @@
|
|
|
256
304
|
|
|
257
305
|
function enqueueRetry(id) {
|
|
258
306
|
if (!id) return;
|
|
307
|
+
if (state.badIds && state.badIds.has(id)) return;
|
|
259
308
|
if (state.retryQueueSet.has(id)) return;
|
|
260
309
|
state.retryQueueSet.add(id);
|
|
261
310
|
state.retryQueue.push(id);
|
|
@@ -270,11 +319,23 @@
|
|
|
270
319
|
const id = state.retryQueue.shift();
|
|
271
320
|
if (!id) {
|
|
272
321
|
state.retryQueueRunning = false;
|
|
322
|
+
state.badIds = new Set();
|
|
323
|
+
state.definedIds = new Set();
|
|
273
324
|
return;
|
|
274
325
|
}
|
|
275
326
|
state.retryQueueSet.delete(id);
|
|
327
|
+
// If this id was previously attempted and still empty, force a full reset before re-requesting.
|
|
328
|
+
const attempts = (state.retryById.get(id) || 0);
|
|
329
|
+
const phNow = document.getElementById(`${PLACEHOLDER_PREFIX}${id}`);
|
|
330
|
+
const wrapNow = phNow && phNow.parentElement;
|
|
331
|
+
if (attempts > 0 && wrapNow && wrapNow.isConnected && !isPlaceholderFilled(id)) {
|
|
332
|
+
if (state.definedIds && state.definedIds.has(id)) {
|
|
333
|
+
destroyPlaceholderIds([id]);
|
|
334
|
+
}
|
|
335
|
+
resetPlaceholderInWrap(wrapNow, id);
|
|
336
|
+
}
|
|
276
337
|
callShowAdsWhenReady(id);
|
|
277
|
-
setTimeout(step,
|
|
338
|
+
setTimeout(step, 1100);
|
|
278
339
|
};
|
|
279
340
|
|
|
280
341
|
step();
|
|
@@ -297,7 +358,7 @@
|
|
|
297
358
|
}
|
|
298
359
|
|
|
299
360
|
const tries = (state.retryById.get(id) || 0);
|
|
300
|
-
if (tries >= 8) continue;
|
|
361
|
+
if (tries >= 8) { state.badIds && state.badIds.add(id); continue; }
|
|
301
362
|
|
|
302
363
|
const r = safeRect(wrap);
|
|
303
364
|
if (r && (r.top > window.innerHeight + 1200 || r.bottom < -1200)) continue;
|
|
@@ -423,8 +484,7 @@
|
|
|
423
484
|
if (!el || !el.isConnected) continue;
|
|
424
485
|
|
|
425
486
|
// Prevent adjacent ads (DOM-based, robust against virtualization)
|
|
426
|
-
|
|
427
|
-
if (nextSibling && nextSibling.classList && nextSibling.classList.contains(WRAP_CLASS)) {
|
|
487
|
+
if (isAdjacentAd(el) || isPrevAd(el)) {
|
|
428
488
|
continue;
|
|
429
489
|
}
|
|
430
490
|
|
|
@@ -444,10 +504,14 @@
|
|
|
444
504
|
|
|
445
505
|
let wrap = null;
|
|
446
506
|
if (pick.recycled && pick.recycled.wrap) {
|
|
447
|
-
|
|
507
|
+
// Only destroy if Ezoic has actually defined this placeholder before
|
|
508
|
+
if (state.definedIds && state.definedIds.has(id)) {
|
|
509
|
+
destroyPlaceholderIds([id]);
|
|
510
|
+
}
|
|
448
511
|
wrap = pick.recycled.wrap;
|
|
449
512
|
if (!moveWrapAfter(wrap, el, kindClass, afterPos)) continue;
|
|
450
|
-
|
|
513
|
+
resetPlaceholderInWrap(wrap, id);
|
|
514
|
+
setTimeout(() => { enqueueRetry(id); }, 450);
|
|
451
515
|
} else {
|
|
452
516
|
usedSet.add(id);
|
|
453
517
|
wrap = insertAfter(el, id, kindClass, afterPos);
|
|
@@ -455,6 +519,17 @@
|
|
|
455
519
|
}
|
|
456
520
|
|
|
457
521
|
liveArr.push({ id, wrap });
|
|
522
|
+
// If adjacency ended up happening (e.g. DOM shifts), rollback this placement.
|
|
523
|
+
if (wrap && (wrap.previousElementSibling && wrap.previousElementSibling.classList && wrap.previousElementSibling.classList.contains(WRAP_CLASS)) || (wrap.nextElementSibling && wrap.nextElementSibling.classList && wrap.nextElementSibling.classList.contains(WRAP_CLASS))) {
|
|
524
|
+
try { wrap.remove(); } catch (e) {}
|
|
525
|
+
// Put id back if it was newly consumed (not recycled)
|
|
526
|
+
if (!(pick.recycled && pick.recycled.wrap)) {
|
|
527
|
+
try { kindPool.unshift(id); } catch (e) {}
|
|
528
|
+
try { usedSet.delete(id); } catch (e) {}
|
|
529
|
+
}
|
|
530
|
+
inserted -= 0; // no-op
|
|
531
|
+
continue;
|
|
532
|
+
}
|
|
458
533
|
if (!(pick.recycled && pick.recycled.wrap)) {
|
|
459
534
|
callShowAdsWhenReady(id);
|
|
460
535
|
}
|