nodebb-plugin-ezoic-infinite 1.5.58 → 1.5.60
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 +52 -41
package/package.json
CHANGED
package/public/client.js
CHANGED
|
@@ -13,9 +13,24 @@
|
|
|
13
13
|
// and eliminates "HTML element with id ... does not exist" noise.
|
|
14
14
|
const POOL_ID = 'ezoic-placeholder-pool';
|
|
15
15
|
|
|
16
|
+
function isInPool(el) {
|
|
17
|
+
try { return !!(el && el.closest && el.closest('#' + POOL_ID)); } catch (e) { return false; }
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function isPlaceholderInUse(ph) {
|
|
21
|
+
// In use = connected AND not parked in our offscreen pool.
|
|
22
|
+
try { return !!(ph && ph.isConnected && !isInPool(ph)); } catch (e) { return false; }
|
|
23
|
+
}
|
|
24
|
+
|
|
16
25
|
function ensurePool() {
|
|
17
26
|
let pool = document.getElementById(POOL_ID);
|
|
18
|
-
if (pool)
|
|
27
|
+
if (pool) {
|
|
28
|
+
// In rare cases (aggressive SPA navigation), the pool may get detached.
|
|
29
|
+
if (!pool.isConnected) {
|
|
30
|
+
try { (document.documentElement || document.body).appendChild(pool); } catch (e) {}
|
|
31
|
+
}
|
|
32
|
+
return pool;
|
|
33
|
+
}
|
|
19
34
|
pool = document.createElement('div');
|
|
20
35
|
pool.id = POOL_ID;
|
|
21
36
|
pool.style.position = 'absolute';
|
|
@@ -44,24 +59,9 @@ function primePool(ids) {
|
|
|
44
59
|
try {
|
|
45
60
|
if (!ids || !ids.length) return;
|
|
46
61
|
const pool = ensurePool();
|
|
47
|
-
|
|
48
|
-
// Normalize and compute bounds
|
|
49
|
-
const arr = [];
|
|
50
62
|
for (const v of ids) {
|
|
51
|
-
const
|
|
52
|
-
if (Number.isFinite(
|
|
53
|
-
}
|
|
54
|
-
if (!arr.length) return;
|
|
55
|
-
|
|
56
|
-
let min = arr[0], max = arr[0];
|
|
57
|
-
for (const n of arr) { if (n < min) min = n; if (n > max) max = n; }
|
|
58
|
-
|
|
59
|
-
// Ezoic sometimes touches ids in a contiguous range. If the configured list
|
|
60
|
-
// looks like a range, pre-create all ids between min..max (bounded).
|
|
61
|
-
const RANGE_LIMIT = 2000;
|
|
62
|
-
const useRange = (max - min) <= RANGE_LIMIT;
|
|
63
|
-
|
|
64
|
-
const ensureOne = (id) => {
|
|
63
|
+
const id = parseInt(v, 10);
|
|
64
|
+
if (!Number.isFinite(id) || id <= 0) continue;
|
|
65
65
|
const domId = `${PLACEHOLDER_PREFIX}${id}`;
|
|
66
66
|
let ph = document.getElementById(domId);
|
|
67
67
|
if (!ph) {
|
|
@@ -72,12 +72,6 @@ function primePool(ids) {
|
|
|
72
72
|
} else if (!ph.isConnected) {
|
|
73
73
|
pool.appendChild(ph);
|
|
74
74
|
}
|
|
75
|
-
};
|
|
76
|
-
|
|
77
|
-
if (useRange) {
|
|
78
|
-
for (let id = min; id <= max; id++) ensureOne(id);
|
|
79
|
-
} else {
|
|
80
|
-
for (const id of arr) ensureOne(id);
|
|
81
75
|
}
|
|
82
76
|
} catch (e) {}
|
|
83
77
|
}
|
|
@@ -90,14 +84,14 @@ function acquirePlaceholder(id) {
|
|
|
90
84
|
ph.id = domId;
|
|
91
85
|
ph.setAttribute('data-ezoic-id', String(id));
|
|
92
86
|
ensurePool().appendChild(ph);
|
|
93
|
-
}
|
|
94
|
-
//
|
|
95
|
-
try { if (ph.parentNode) ph.parentNode.removeChild(ph); } catch (e) {}
|
|
87
|
+
}
|
|
88
|
+
// Note: appendChild will automatically move the node, no manual detach (avoids race gaps).
|
|
96
89
|
// Clear request/defined flags when reusing
|
|
97
90
|
try {
|
|
98
91
|
if (ph.dataset) {
|
|
99
92
|
ph.dataset.ezRequested = '0';
|
|
100
93
|
ph.dataset.ezDefined = '0';
|
|
94
|
+
ph.dataset.ezActive = '0';
|
|
101
95
|
}
|
|
102
96
|
} catch (e) {}
|
|
103
97
|
return ph;
|
|
@@ -108,6 +102,7 @@ function parkPlaceholderFromWrap(wrap) {
|
|
|
108
102
|
const ph = wrap && wrap.querySelector ? wrap.querySelector(`[id^="${PLACEHOLDER_PREFIX}"]`) : null;
|
|
109
103
|
if (!ph) return;
|
|
110
104
|
try { if (state && state.io) state.io.unobserve(ph); } catch (e) {}
|
|
105
|
+
try { if (ph.dataset) ph.dataset.ezActive = '0'; } catch (e) {}
|
|
111
106
|
ensurePool().appendChild(ph);
|
|
112
107
|
} catch (e) {}
|
|
113
108
|
}
|
|
@@ -246,10 +241,11 @@ function parkPlaceholderFromWrap(wrap) {
|
|
|
246
241
|
|
|
247
242
|
function parsePool(raw) {
|
|
248
243
|
if (!raw) return [];
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
244
|
+
const lines = String(raw)
|
|
245
|
+
.split(/\r?\n/)
|
|
246
|
+
.map(s => s.trim())
|
|
247
|
+
.filter(Boolean);
|
|
248
|
+
return uniqInts(lines);
|
|
253
249
|
}
|
|
254
250
|
|
|
255
251
|
function getPageKey() {
|
|
@@ -342,8 +338,24 @@ function parkPlaceholderFromWrap(wrap) {
|
|
|
342
338
|
if (!Number.isFinite(id) || id <= 0 || seen.has(id)) continue;
|
|
343
339
|
|
|
344
340
|
const domId = `${PLACEHOLDER_PREFIX}${id}`;
|
|
345
|
-
|
|
346
|
-
if (!ph || !ph.isConnected)
|
|
341
|
+
let ph = document.getElementById(domId);
|
|
342
|
+
if (!ph || !ph.isConnected) {
|
|
343
|
+
// If Ezoic (or another script) tries to show an id we haven't injected yet,
|
|
344
|
+
// create the placeholder in the offscreen pool so it exists, but don't load.
|
|
345
|
+
try {
|
|
346
|
+
ph = document.createElement('div');
|
|
347
|
+
ph.id = domId;
|
|
348
|
+
ph.setAttribute('data-ezoic-id', String(id));
|
|
349
|
+
if (ph.dataset) ph.dataset.ezActive = '0';
|
|
350
|
+
ensurePool().appendChild(ph);
|
|
351
|
+
} catch (e) {}
|
|
352
|
+
continue;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
// Only allow loads for placeholders actively injected into the page (not parked in the pool)
|
|
356
|
+
// and currently marked active.
|
|
357
|
+
if (!isPlaceholderInUse(ph)) continue;
|
|
358
|
+
if (ph.dataset && ph.dataset.ezActive !== '1') continue;
|
|
347
359
|
|
|
348
360
|
// Prevent repeated "define" attempts on the same placeholder while it remains in DOM.
|
|
349
361
|
if (ph.dataset && (ph.dataset.ezRequested === '1' || ph.dataset.ezDefined === '1')) continue;
|
|
@@ -566,6 +578,7 @@ function buildWrap(id, kindClass, afterPos) {
|
|
|
566
578
|
wrap.style.width = '100%';
|
|
567
579
|
|
|
568
580
|
const ph = acquirePlaceholder(id);
|
|
581
|
+
try { if (ph.dataset) ph.dataset.ezActive = '1'; } catch (e) {}
|
|
569
582
|
wrap.appendChild(ph);
|
|
570
583
|
|
|
571
584
|
return wrap;
|
|
@@ -581,7 +594,7 @@ function buildWrap(id, kindClass, afterPos) {
|
|
|
581
594
|
if (insertingIds.has(id)) return null;
|
|
582
595
|
|
|
583
596
|
const existingPh = document.getElementById(`${PLACEHOLDER_PREFIX}${id}`);
|
|
584
|
-
if (existingPh && existingPh
|
|
597
|
+
if (existingPh && isPlaceholderInUse(existingPh)) return null;
|
|
585
598
|
|
|
586
599
|
insertingIds.add(id);
|
|
587
600
|
try {
|
|
@@ -604,7 +617,7 @@ function buildWrap(id, kindClass, afterPos) {
|
|
|
604
617
|
|
|
605
618
|
const id = allIds[idx];
|
|
606
619
|
const ph = document.getElementById(`${PLACEHOLDER_PREFIX}${id}`);
|
|
607
|
-
if (ph && ph
|
|
620
|
+
if (ph && isPlaceholderInUse(ph)) continue;
|
|
608
621
|
|
|
609
622
|
return id;
|
|
610
623
|
}
|
|
@@ -709,16 +722,14 @@ function startShow(id) {
|
|
|
709
722
|
const ph = document.getElementById(domId);
|
|
710
723
|
if (!ph || !ph.isConnected) return;
|
|
711
724
|
|
|
712
|
-
// If this id was used before, destroy
|
|
713
|
-
// Then schedule showAds on the next tick (gives Ezoic time to clear state).
|
|
725
|
+
// If this id was used before, destroy safely using full DOM id.
|
|
714
726
|
if (state.usedOnce && state.usedOnce.has(id)) {
|
|
715
727
|
safeDestroyById(id);
|
|
716
|
-
setTimeout(() => { try { ez.showAds(id); } catch (e) {} }, 0);
|
|
717
|
-
} else {
|
|
718
|
-
// First time: show immediately
|
|
719
|
-
ez.showAds(id);
|
|
720
728
|
}
|
|
721
729
|
|
|
730
|
+
// showAds is patched to ignore missing placeholders and repeated defines.
|
|
731
|
+
ez.showAds(id);
|
|
732
|
+
|
|
722
733
|
try { state.usedOnce && state.usedOnce.add(id); } catch (e) {}
|
|
723
734
|
} catch (e) {}
|
|
724
735
|
finally {
|