nodebb-plugin-ezoic-infinite 1.8.26 → 1.8.28
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 +101 -14
- package/public/style.css +16 -5
package/package.json
CHANGED
package/public/client.js
CHANGED
|
@@ -83,7 +83,7 @@
|
|
|
83
83
|
const MAX_INFLIGHT = 4; // max showAds() simultanés
|
|
84
84
|
const SHOW_THROTTLE_MS = 900; // anti-spam showAds() par id
|
|
85
85
|
const BURST_COOLDOWN_MS = 200; // délai min entre deux déclenchements de burst
|
|
86
|
-
const MIN_PLACEHOLDER_HEIGHT =
|
|
86
|
+
const MIN_PLACEHOLDER_HEIGHT = 1; // placeholder minimal (test stabilité scroll)
|
|
87
87
|
|
|
88
88
|
// Marges IO larges et fixes — observer créé une seule fois au boot
|
|
89
89
|
const IO_MARGIN_DESKTOP = '2500px 0px 2500px 0px';
|
|
@@ -144,13 +144,51 @@
|
|
|
144
144
|
const isBlocked = () => ts() < blockedUntil;
|
|
145
145
|
const isMobile = () => { try { return window.innerWidth < 768; } catch (_) { return false; } };
|
|
146
146
|
const normBool = v => v === true || v === 'true' || v === 1 || v === '1' || v === 'on';
|
|
147
|
-
const
|
|
147
|
+
const FILL_SEL = 'iframe, ins, img, video, [data-google-container-id], div[id$="__container__"]';
|
|
148
|
+
const isFilled = n => !!(n?.querySelector?.(FILL_SEL));
|
|
148
149
|
|
|
149
150
|
function mutate(fn) {
|
|
150
151
|
S.mutGuard++;
|
|
151
152
|
try { fn(); } finally { S.mutGuard--; }
|
|
152
153
|
}
|
|
153
154
|
|
|
155
|
+
function clearEmptyIfFilled(wrap) {
|
|
156
|
+
try {
|
|
157
|
+
if (!wrap?.isConnected) return false;
|
|
158
|
+
const ph = wrap.querySelector(`[id^="${PH_PREFIX}"]`);
|
|
159
|
+
if (!ph) return false;
|
|
160
|
+
if (!isFilled(ph)) return false;
|
|
161
|
+
wrap.classList.remove('is-empty');
|
|
162
|
+
return true;
|
|
163
|
+
} catch (_) { return false; }
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
function scheduleUncollapseChecksForWrap(wrap) {
|
|
167
|
+
if (!wrap) return;
|
|
168
|
+
for (const ms of [500, 1500, 3000, 7000, 15000]) {
|
|
169
|
+
setTimeout(() => { try { clearEmptyIfFilled(wrap); } catch (_) {} }, ms);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
function clearEmptyIfFilled(wrap) {
|
|
175
|
+
try {
|
|
176
|
+
if (!wrap?.isConnected) return false;
|
|
177
|
+
const ph = wrap.querySelector(`[id^="${PH_PREFIX}"]`);
|
|
178
|
+
if (!ph) return false;
|
|
179
|
+
if (!isFilled(ph)) return false;
|
|
180
|
+
wrap.classList.remove('is-empty');
|
|
181
|
+
return true;
|
|
182
|
+
} catch (_) { return false; }
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
function scheduleUncollapseChecksForWrap(wrap) {
|
|
186
|
+
if (!wrap) return;
|
|
187
|
+
for (const ms of [500, 1500, 3000, 7000, 15000]) {
|
|
188
|
+
setTimeout(() => { try { clearEmptyIfFilled(wrap); } catch (_) {} }, ms);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
154
192
|
// ── Config ─────────────────────────────────────────────────────────────────
|
|
155
193
|
|
|
156
194
|
async function fetchConfig() {
|
|
@@ -370,17 +408,30 @@
|
|
|
370
408
|
best.setAttribute(A_CREATED, String(ts()));
|
|
371
409
|
best.setAttribute(A_SHOWN, '0');
|
|
372
410
|
best.classList.remove('is-empty');
|
|
373
|
-
const
|
|
374
|
-
if (
|
|
411
|
+
const oldPh = best.querySelector(`#${PH_PREFIX}${id}`);
|
|
412
|
+
if (oldPh) {
|
|
413
|
+
const fresh = document.createElement('div');
|
|
414
|
+
fresh.id = `${PH_PREFIX}${id}`;
|
|
415
|
+
fresh.setAttribute('data-ezoic-id', String(id));
|
|
416
|
+
fresh.style.minHeight = `${MIN_PLACEHOLDER_HEIGHT}px`;
|
|
417
|
+
oldPh.replaceWith(fresh);
|
|
418
|
+
}
|
|
375
419
|
targetEl.insertAdjacentElement('afterend', best);
|
|
376
420
|
});
|
|
377
421
|
if (oldKey && S.wrapByKey.get(oldKey) === best) S.wrapByKey.delete(oldKey);
|
|
378
422
|
S.wrapByKey.set(newKey, best);
|
|
379
423
|
|
|
380
|
-
//
|
|
381
|
-
|
|
382
|
-
const
|
|
383
|
-
|
|
424
|
+
// Recyclage Ezoic : détruire l'ancien placeholder avant de réutiliser le même ID.
|
|
425
|
+
// Puis ré-observer + re-show (batché via patchShowAds) sur le placeholder recréé.
|
|
426
|
+
const doDestroy = () => {
|
|
427
|
+
try { ez.destroyPlaceholders(id); } catch (_) {
|
|
428
|
+
try { ez.destroyPlaceholders([id]); } catch (_) {}
|
|
429
|
+
}
|
|
430
|
+
setTimeout(() => {
|
|
431
|
+
try { observePh(id); } catch (_) {}
|
|
432
|
+
try { enqueueShow(id); } catch (_) {}
|
|
433
|
+
}, 450);
|
|
434
|
+
};
|
|
384
435
|
try { (typeof ez.cmd?.push === 'function') ? ez.cmd.push(doDestroy) : doDestroy(); } catch (_) {}
|
|
385
436
|
|
|
386
437
|
return { id, wrap: best };
|
|
@@ -585,7 +636,10 @@
|
|
|
585
636
|
window.ezstandalone = window.ezstandalone || {};
|
|
586
637
|
const ez = window.ezstandalone;
|
|
587
638
|
const doShow = () => {
|
|
639
|
+
let wrap = null;
|
|
640
|
+
try { wrap = ph.closest?.(`.${WRAP_CLASS}`) || null; } catch (_) {}
|
|
588
641
|
try { ez.showAds(id); } catch (_) {}
|
|
642
|
+
if (wrap) scheduleUncollapseChecksForWrap(wrap);
|
|
589
643
|
scheduleEmptyCheck(id, t);
|
|
590
644
|
setTimeout(() => { clearTimeout(timer); release(); }, 700);
|
|
591
645
|
};
|
|
@@ -601,7 +655,8 @@
|
|
|
601
655
|
const wrap = ph?.closest?.(`.${WRAP_CLASS}`);
|
|
602
656
|
if (!wrap || !ph?.isConnected) return;
|
|
603
657
|
if (parseInt(wrap.getAttribute(A_SHOWN) || '0', 10) > showTs) return;
|
|
604
|
-
|
|
658
|
+
if (clearEmptyIfFilled(wrap)) return;
|
|
659
|
+
wrap.classList.add('is-empty');
|
|
605
660
|
} catch (_) {}
|
|
606
661
|
}, EMPTY_CHECK_MS);
|
|
607
662
|
}
|
|
@@ -620,17 +675,34 @@
|
|
|
620
675
|
if (window.__nbbEzPatched || typeof ez.showAds !== 'function') return;
|
|
621
676
|
window.__nbbEzPatched = true;
|
|
622
677
|
const orig = ez.showAds.bind(ez);
|
|
678
|
+
const q = new Set();
|
|
679
|
+
let flushTimer = null;
|
|
680
|
+
const BATCH_SIZE = 3;
|
|
681
|
+
const FLUSH_MS = 80;
|
|
682
|
+
const flush = () => {
|
|
683
|
+
flushTimer = null;
|
|
684
|
+
if (isBlocked() || !q.size) return;
|
|
685
|
+
const ids = Array.from(q).sort((a, b) => a - b);
|
|
686
|
+
q.clear();
|
|
687
|
+
const valid = ids.filter(id => document.getElementById(`${PH_PREFIX}${id}`)?.isConnected);
|
|
688
|
+
for (let i = 0; i < valid.length; i += BATCH_SIZE) {
|
|
689
|
+
const chunk = valid.slice(i, i + BATCH_SIZE);
|
|
690
|
+
try { orig(...chunk); } catch (_) {
|
|
691
|
+
for (const id of chunk) { try { orig(id); } catch (_) {} }
|
|
692
|
+
}
|
|
693
|
+
}
|
|
694
|
+
};
|
|
623
695
|
ez.showAds = function (...args) {
|
|
624
696
|
if (isBlocked()) return;
|
|
625
|
-
const ids
|
|
626
|
-
const seen = new Set();
|
|
697
|
+
const ids = args.length === 1 && Array.isArray(args[0]) ? args[0] : args;
|
|
627
698
|
for (const v of ids) {
|
|
628
699
|
const id = parseInt(v, 10);
|
|
629
|
-
if (!Number.isFinite(id) || id <= 0
|
|
700
|
+
if (!Number.isFinite(id) || id <= 0) continue;
|
|
630
701
|
if (!document.getElementById(`${PH_PREFIX}${id}`)?.isConnected) continue;
|
|
631
|
-
|
|
632
|
-
try { orig(id); } catch (_) {}
|
|
702
|
+
q.add(id);
|
|
633
703
|
}
|
|
704
|
+
if (!q.size) return;
|
|
705
|
+
if (!flushTimer) flushTimer = setTimeout(flush, FLUSH_MS);
|
|
634
706
|
};
|
|
635
707
|
} catch (_) {}
|
|
636
708
|
};
|
|
@@ -746,6 +818,21 @@
|
|
|
746
818
|
if (S.domObs) return;
|
|
747
819
|
S.domObs = new MutationObserver(muts => {
|
|
748
820
|
if (S.mutGuard > 0 || isBlocked()) return;
|
|
821
|
+
for (const m of muts) {
|
|
822
|
+
if (m.type !== 'childList') continue;
|
|
823
|
+
for (const node of m.addedNodes) {
|
|
824
|
+
if (!(node instanceof Element)) continue;
|
|
825
|
+
let hasAd = false;
|
|
826
|
+
try {
|
|
827
|
+
hasAd = !!(node.matches?.(FILL_SEL) || node.querySelector?.(FILL_SEL));
|
|
828
|
+
} catch (_) {}
|
|
829
|
+
if (!hasAd) continue;
|
|
830
|
+
try {
|
|
831
|
+
const wrap = node.closest?.(`.${WRAP_CLASS}.is-empty`) || m.target?.closest?.(`.${WRAP_CLASS}.is-empty`);
|
|
832
|
+
if (wrap) clearEmptyIfFilled(wrap);
|
|
833
|
+
} catch (_) {}
|
|
834
|
+
}
|
|
835
|
+
}
|
|
749
836
|
const relevant = (() => {
|
|
750
837
|
const k = getKind();
|
|
751
838
|
if (k === 'topic') return [SEL.post];
|
package/public/style.css
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*
|
|
2
|
-
* NodeBB Ezoic Infinite Ads — style.css (v20
|
|
2
|
+
* NodeBB Ezoic Infinite Ads — style.css (v20)
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
/* ── Wrapper ──────────────────────────────────────────────────────────────── */
|
|
@@ -39,9 +39,9 @@
|
|
|
39
39
|
/* Ne pas écraser la hauteur réelle calculée par Ezoic */
|
|
40
40
|
.nodebb-ezoic-wrap .ezoic-ad,
|
|
41
41
|
.nodebb-ezoic-wrap span.ezoic-ad {
|
|
42
|
-
display: block !important;
|
|
43
42
|
margin: 0 !important;
|
|
44
43
|
padding: 0 !important;
|
|
44
|
+
display: block !important;
|
|
45
45
|
height: auto !important;
|
|
46
46
|
min-height: unset !important;
|
|
47
47
|
max-height: none !important;
|
|
@@ -60,8 +60,8 @@
|
|
|
60
60
|
|
|
61
61
|
/* ── État vide ────────────────────────────────────────────────────────────── */
|
|
62
62
|
/*
|
|
63
|
-
Ajouté après
|
|
64
|
-
Collapse à 1px : réserve minimale, reste observable par l'IO.
|
|
63
|
+
Ajouté 20s après showAds si aucun fill détecté.
|
|
64
|
+
Collapse à 1px : réserve minimale demandée, reste observable par l'IO.
|
|
65
65
|
*/
|
|
66
66
|
.nodebb-ezoic-wrap.is-empty {
|
|
67
67
|
display: block !important;
|
|
@@ -77,4 +77,15 @@
|
|
|
77
77
|
.ezoic-ad {
|
|
78
78
|
margin: 0 !important;
|
|
79
79
|
padding: 0 !important;
|
|
80
|
-
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
/* Anti-faux-empty : si une pub est présente, annule le collapse */
|
|
84
|
+
.nodebb-ezoic-wrap.is-empty:has(iframe),
|
|
85
|
+
.nodebb-ezoic-wrap.is-empty:has([data-google-container-id]),
|
|
86
|
+
.nodebb-ezoic-wrap.is-empty:has(div[id$="__container__"]) {
|
|
87
|
+
height: auto !important;
|
|
88
|
+
min-height: 0 !important;
|
|
89
|
+
max-height: none !important;
|
|
90
|
+
overflow: visible !important;
|
|
91
|
+
}
|