nodebb-plugin-ezoic-infinite 1.8.12 → 1.8.13
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/library.js +18 -26
- package/package.json +2 -2
- package/public/client.js +56 -186
- package/public/style.css +8 -5
package/library.js
CHANGED
|
@@ -71,9 +71,8 @@ async function getSettings() {
|
|
|
71
71
|
|
|
72
72
|
async function isUserExcluded(uid, excludedGroups) {
|
|
73
73
|
if (!uid || !excludedGroups.length) return false;
|
|
74
|
-
const excluded = new Set((excludedGroups || []).map(String));
|
|
75
74
|
const userGroups = await groups.getUserGroups([uid]);
|
|
76
|
-
return (userGroups[0] || []).some(g =>
|
|
75
|
+
return (userGroups[0] || []).some(g => excludedGroups.includes(g.name));
|
|
77
76
|
}
|
|
78
77
|
|
|
79
78
|
// ── Scripts Ezoic ──────────────────────────────────────────────────────────
|
|
@@ -114,34 +113,13 @@ plugin.injectEzoicHead = async (data) => {
|
|
|
114
113
|
const uid = data.req?.uid ?? 0;
|
|
115
114
|
const excluded = await isUserExcluded(uid, settings.excludedGroups);
|
|
116
115
|
if (!excluded) {
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
data.templateData.customHTML = `<meta data-nbb-ezoic-head="1">` + EZOIC_SCRIPTS + html;
|
|
120
|
-
}
|
|
116
|
+
// Préfixer : nos scripts d'abord, puis le customHTML existant de l'admin
|
|
117
|
+
data.templateData.customHTML = EZOIC_SCRIPTS + (data.templateData.customHTML || '');
|
|
121
118
|
}
|
|
122
119
|
} catch (_) {}
|
|
123
120
|
return data;
|
|
124
121
|
};
|
|
125
122
|
|
|
126
|
-
|
|
127
|
-
function publicConfigPayload(settings, excluded) {
|
|
128
|
-
return {
|
|
129
|
-
excluded,
|
|
130
|
-
enableBetweenAds: settings.enableBetweenAds,
|
|
131
|
-
showFirstTopicAd: settings.showFirstTopicAd,
|
|
132
|
-
placeholderIds: settings.placeholderIds,
|
|
133
|
-
intervalPosts: settings.intervalPosts,
|
|
134
|
-
enableCategoryAds: settings.enableCategoryAds,
|
|
135
|
-
showFirstCategoryAd: settings.showFirstCategoryAd,
|
|
136
|
-
categoryPlaceholderIds: settings.categoryPlaceholderIds,
|
|
137
|
-
intervalCategories: settings.intervalCategories,
|
|
138
|
-
enableMessageAds: settings.enableMessageAds,
|
|
139
|
-
showFirstMessageAd: settings.showFirstMessageAd,
|
|
140
|
-
messagePlaceholderIds: settings.messagePlaceholderIds,
|
|
141
|
-
messageIntervalPosts: settings.messageIntervalPosts,
|
|
142
|
-
};
|
|
143
|
-
}
|
|
144
|
-
|
|
145
123
|
plugin.init = async ({ router, middleware }) => {
|
|
146
124
|
async function render(req, res) {
|
|
147
125
|
const settings = await getSettings();
|
|
@@ -161,7 +139,21 @@ plugin.init = async ({ router, middleware }) => {
|
|
|
161
139
|
router.get('/api/plugins/ezoic-infinite/config', async (req, res) => {
|
|
162
140
|
const settings = await getSettings();
|
|
163
141
|
const excluded = await isUserExcluded(req.uid, settings.excludedGroups);
|
|
164
|
-
res.json(
|
|
142
|
+
res.json({
|
|
143
|
+
excluded,
|
|
144
|
+
enableBetweenAds: settings.enableBetweenAds,
|
|
145
|
+
showFirstTopicAd: settings.showFirstTopicAd,
|
|
146
|
+
placeholderIds: settings.placeholderIds,
|
|
147
|
+
intervalPosts: settings.intervalPosts,
|
|
148
|
+
enableCategoryAds: settings.enableCategoryAds,
|
|
149
|
+
showFirstCategoryAd: settings.showFirstCategoryAd,
|
|
150
|
+
categoryPlaceholderIds: settings.categoryPlaceholderIds,
|
|
151
|
+
intervalCategories: settings.intervalCategories,
|
|
152
|
+
enableMessageAds: settings.enableMessageAds,
|
|
153
|
+
showFirstMessageAd: settings.showFirstMessageAd,
|
|
154
|
+
messagePlaceholderIds: settings.messagePlaceholderIds,
|
|
155
|
+
messageIntervalPosts: settings.messageIntervalPosts,
|
|
156
|
+
});
|
|
165
157
|
});
|
|
166
158
|
};
|
|
167
159
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nodebb-plugin-ezoic-infinite",
|
|
3
|
-
"version": "1.8.
|
|
3
|
+
"version": "1.8.13",
|
|
4
4
|
"description": "Production-ready Ezoic infinite ads integration for NodeBB 4.x",
|
|
5
5
|
"main": "library.js",
|
|
6
6
|
"license": "MIT",
|
|
@@ -18,4 +18,4 @@
|
|
|
18
18
|
"compatibility": "^4.0.0"
|
|
19
19
|
},
|
|
20
20
|
"private": false
|
|
21
|
-
}
|
|
21
|
+
}
|
package/public/client.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* NodeBB Ezoic Infinite Ads — client.js
|
|
2
|
+
* NodeBB Ezoic Infinite Ads — client.js v36
|
|
3
3
|
*
|
|
4
4
|
* Historique des corrections majeures
|
|
5
5
|
* ────────────────────────────────────
|
|
@@ -32,8 +32,6 @@
|
|
|
32
32
|
*
|
|
33
33
|
* v34 moveDistantWrap — voir v38.
|
|
34
34
|
*
|
|
35
|
-
* v52 Clean architecture interne (modules logiques, cache DOM, bridge Ezoic).
|
|
36
|
-
*
|
|
37
35
|
* v50 Suppression de bindLoginCheck() : NodeBB fait un rechargement complet
|
|
38
36
|
* après login — filter:middleware.renderHeader re-évalue l'exclusion au
|
|
39
37
|
* rechargement. Redondant depuis le fix normalizeExcludedGroups (v49).
|
|
@@ -151,10 +149,6 @@
|
|
|
151
149
|
burstDeadline: 0,
|
|
152
150
|
burstCount: 0,
|
|
153
151
|
lastBurstTs: 0,
|
|
154
|
-
ioViewportMode: isMobile() ? 'm' : 'd',
|
|
155
|
-
domRev: 0,
|
|
156
|
-
domCache: new Map(),
|
|
157
|
-
cacheFrameArmed: false,
|
|
158
152
|
};
|
|
159
153
|
|
|
160
154
|
let blockedUntil = 0;
|
|
@@ -163,81 +157,7 @@
|
|
|
163
157
|
const isBlocked = () => ts() < blockedUntil;
|
|
164
158
|
const isMobile = () => { try { return window.innerWidth < 768; } catch (_) { return false; } };
|
|
165
159
|
const normBool = v => v === true || v === 'true' || v === 1 || v === '1' || v === 'on';
|
|
166
|
-
const
|
|
167
|
-
const dbg = (...a) => { if (DEBUG) { try { console.debug('[nbb-ezoic]', ...a); } catch (_) {} } };
|
|
168
|
-
const isFilled = n => {
|
|
169
|
-
try {
|
|
170
|
-
if (!n?.querySelector) return false;
|
|
171
|
-
if (n.querySelector('iframe, ins, img, video, [data-google-container-id], .ezoic-ad, [id$="__container__"]')) return true;
|
|
172
|
-
const r = n.getBoundingClientRect?.();
|
|
173
|
-
return !!(r && r.height > 8);
|
|
174
|
-
} catch (_) { return false; }
|
|
175
|
-
};
|
|
176
|
-
|
|
177
|
-
const Arch = {
|
|
178
|
-
cache: {
|
|
179
|
-
// v53: frame-only micro-cache (safe for NodeBB progressive renders).
|
|
180
|
-
// We only cache DOM query results until the next animation frame, and any mutation invalidates immediately.
|
|
181
|
-
_armFrameClear() {
|
|
182
|
-
if (S.cacheFrameArmed) return;
|
|
183
|
-
S.cacheFrameArmed = true;
|
|
184
|
-
requestAnimationFrame(() => {
|
|
185
|
-
S.cacheFrameArmed = false;
|
|
186
|
-
try { S.domCache.clear(); } catch (_) {}
|
|
187
|
-
dbg('dom-cache.clear', 'raf');
|
|
188
|
-
});
|
|
189
|
-
},
|
|
190
|
-
invalidate(reason) {
|
|
191
|
-
try { S.domRev++; S.domCache.clear(); } catch (_) {}
|
|
192
|
-
dbg('dom-cache.invalidate', reason || '');
|
|
193
|
-
},
|
|
194
|
-
queryAll(key, selector, filterFn) {
|
|
195
|
-
const k = `q:${S.domRev}:${key}:${selector}`;
|
|
196
|
-
try {
|
|
197
|
-
if (S.domCache.has(k)) return S.domCache.get(k);
|
|
198
|
-
} catch (_) {}
|
|
199
|
-
const arr = Array.from(document.querySelectorAll(selector));
|
|
200
|
-
const out = typeof filterFn === 'function' ? arr.filter(Boolean).filter(filterFn) : arr;
|
|
201
|
-
try {
|
|
202
|
-
this._armFrameClear();
|
|
203
|
-
S.domCache.set(k, out);
|
|
204
|
-
} catch (_) {}
|
|
205
|
-
return out;
|
|
206
|
-
},
|
|
207
|
-
get(key, buildFn) {
|
|
208
|
-
const k = `g:${S.domRev}:${key}`;
|
|
209
|
-
try {
|
|
210
|
-
if (S.domCache.has(k)) return S.domCache.get(k);
|
|
211
|
-
} catch (_) {}
|
|
212
|
-
const out = buildFn();
|
|
213
|
-
try {
|
|
214
|
-
this._armFrameClear();
|
|
215
|
-
S.domCache.set(k, out);
|
|
216
|
-
} catch (_) {}
|
|
217
|
-
return out;
|
|
218
|
-
},
|
|
219
|
-
},
|
|
220
|
-
ezoic: {
|
|
221
|
-
ensure() {
|
|
222
|
-
window.ezstandalone = window.ezstandalone || {};
|
|
223
|
-
return window.ezstandalone;
|
|
224
|
-
},
|
|
225
|
-
run(fn) {
|
|
226
|
-
const ez = this.ensure();
|
|
227
|
-
try { return (typeof ez?.cmd?.push === 'function') ? ez.cmd.push(fn) : fn(); } catch (_) {}
|
|
228
|
-
},
|
|
229
|
-
call(method, ...args) {
|
|
230
|
-
const ez = this.ensure();
|
|
231
|
-
const fn = ez?.[method];
|
|
232
|
-
if (typeof fn !== 'function') return;
|
|
233
|
-
try { return fn.apply(ez, args); } catch (_) {}
|
|
234
|
-
},
|
|
235
|
-
},
|
|
236
|
-
page: {
|
|
237
|
-
kind() { return Arch.cache.get('kind', getKind); },
|
|
238
|
-
key() { return pageKey(); },
|
|
239
|
-
},
|
|
240
|
-
};
|
|
160
|
+
const isFilled = n => !!(n?.querySelector?.('iframe, ins, img, video, [data-google-container-id]'));
|
|
241
161
|
|
|
242
162
|
function healFalseEmpty(root = document) {
|
|
243
163
|
try {
|
|
@@ -295,8 +215,7 @@
|
|
|
295
215
|
|
|
296
216
|
function mutate(fn) {
|
|
297
217
|
S.mutGuard++;
|
|
298
|
-
try { fn(); }
|
|
299
|
-
finally { S.mutGuard--; Arch.cache.invalidate('mutate'); }
|
|
218
|
+
try { fn(); } finally { S.mutGuard--; }
|
|
300
219
|
}
|
|
301
220
|
function scheduleDestroyFlush() {
|
|
302
221
|
if (S.destroyBatchTimer) return;
|
|
@@ -316,7 +235,11 @@ function flushDestroyBatch() {
|
|
|
316
235
|
ids.push(id);
|
|
317
236
|
}
|
|
318
237
|
if (ids.length) {
|
|
319
|
-
try {
|
|
238
|
+
try {
|
|
239
|
+
const ez = window.ezstandalone;
|
|
240
|
+
const run = () => { try { ez?.destroyPlaceholders?.(ids); } catch (_) {} };
|
|
241
|
+
try { (typeof ez?.cmd?.push === 'function') ? ez.cmd.push(run) : run(); } catch (_) {}
|
|
242
|
+
} catch (_) {}
|
|
320
243
|
}
|
|
321
244
|
if (S.destroyPending.length) scheduleDestroyFlush();
|
|
322
245
|
}
|
|
@@ -332,28 +255,20 @@ function destroyEzoicId(id) {
|
|
|
332
255
|
scheduleDestroyFlush();
|
|
333
256
|
}
|
|
334
257
|
|
|
335
|
-
function
|
|
336
|
-
for (const raw of (ids || [])) {
|
|
337
|
-
const id = parseInt(raw, 10);
|
|
338
|
-
if (!Number.isFinite(id) || id <= 0) continue;
|
|
339
|
-
if (!S.ezActiveIds.has(id) && !S.ezShownSinceDestroy.has(id)) continue;
|
|
340
|
-
if (S.destroyPendingSet.has(id)) continue;
|
|
341
|
-
S.destroyPending.push(id);
|
|
342
|
-
S.destroyPendingSet.add(id);
|
|
343
|
-
S.ezActiveIds.delete(id);
|
|
344
|
-
S.ezShownSinceDestroy.delete(id);
|
|
345
|
-
}
|
|
346
|
-
if (S.destroyPending.length) scheduleDestroyFlush();
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
function prepareIdsForShow(ids) {
|
|
258
|
+
function destroyBeforeReuse(ids) {
|
|
350
259
|
const out = [];
|
|
260
|
+
const toDestroy = [];
|
|
351
261
|
const seen = new Set();
|
|
352
262
|
for (const raw of (ids || [])) {
|
|
353
263
|
const id = parseInt(raw, 10);
|
|
354
264
|
if (!Number.isFinite(id) || id <= 0 || seen.has(id)) continue;
|
|
355
265
|
seen.add(id);
|
|
356
266
|
out.push(id);
|
|
267
|
+
if (S.ezShownSinceDestroy.has(id)) toDestroy.push(id);
|
|
268
|
+
}
|
|
269
|
+
if (toDestroy.length) {
|
|
270
|
+
try { window.ezstandalone?.destroyPlaceholders?.(toDestroy); } catch (_) {}
|
|
271
|
+
for (const id of toDestroy) S.ezShownSinceDestroy.delete(id);
|
|
357
272
|
}
|
|
358
273
|
return out;
|
|
359
274
|
}
|
|
@@ -412,7 +327,7 @@ function prepareIdsForShow(ids) {
|
|
|
412
327
|
// ── Items DOM ──────────────────────────────────────────────────────────────
|
|
413
328
|
|
|
414
329
|
function getPosts() {
|
|
415
|
-
return
|
|
330
|
+
return Array.from(document.querySelectorAll(SEL.post)).filter(el => {
|
|
416
331
|
if (!el.isConnected) return false;
|
|
417
332
|
if (!el.querySelector('[component="post/content"]')) return false;
|
|
418
333
|
const p = el.parentElement?.closest(SEL.post);
|
|
@@ -421,8 +336,8 @@ function prepareIdsForShow(ids) {
|
|
|
421
336
|
});
|
|
422
337
|
}
|
|
423
338
|
|
|
424
|
-
const getTopics = () =>
|
|
425
|
-
const getCategories = () =>
|
|
339
|
+
const getTopics = () => Array.from(document.querySelectorAll(SEL.topic));
|
|
340
|
+
const getCategories = () => Array.from(document.querySelectorAll(SEL.category));
|
|
426
341
|
|
|
427
342
|
// ── Wraps — détection ──────────────────────────────────────────────────────
|
|
428
343
|
|
|
@@ -523,7 +438,6 @@ function prepareIdsForShow(ids) {
|
|
|
523
438
|
S.mountedIds.delete(id);
|
|
524
439
|
S.pendingSet.delete(id);
|
|
525
440
|
S.lastShow.delete(id);
|
|
526
|
-
queueDestroyIds([id]);
|
|
527
441
|
S.ezActiveIds.delete(id);
|
|
528
442
|
}
|
|
529
443
|
}
|
|
@@ -540,7 +454,7 @@ function prepareIdsForShow(ids) {
|
|
|
540
454
|
* Priorité : wraps vides d'abord, remplis si nécessaire.
|
|
541
455
|
*/
|
|
542
456
|
function recycleAndMove(klass, targetEl, newKey) {
|
|
543
|
-
const ez =
|
|
457
|
+
const ez = window.ezstandalone;
|
|
544
458
|
if (typeof ez?.destroyPlaceholders !== 'function' ||
|
|
545
459
|
typeof ez?.define !== 'function' ||
|
|
546
460
|
typeof ez?.displayMore !== 'function') return null;
|
|
@@ -612,7 +526,7 @@ function recycleAndMove(klass, targetEl, newKey) {
|
|
|
612
526
|
};
|
|
613
527
|
const doDefine = () => { try { ez.define([id]); } catch (_) {} setTimeout(doDisplay, 300); };
|
|
614
528
|
const doDisplay = () => { try { ez.displayMore([id]); S.ezActiveIds.add(id); S.ezShownSinceDestroy.add(id); } catch (_) {} };
|
|
615
|
-
try {
|
|
529
|
+
try { (typeof ez.cmd?.push === 'function') ? ez.cmd.push(doDestroy) : doDestroy(); } catch (_) {}
|
|
616
530
|
|
|
617
531
|
return { id, wrap: best };
|
|
618
532
|
}
|
|
@@ -652,7 +566,7 @@ function recycleAndMove(klass, targetEl, newKey) {
|
|
|
652
566
|
const ph = w.querySelector(`[id^="${PH_PREFIX}"]`);
|
|
653
567
|
if (ph instanceof Element) S.io?.unobserve(ph);
|
|
654
568
|
const id = parseInt(w.getAttribute(A_WRAPID), 10);
|
|
655
|
-
if (Number.isFinite(id)) {
|
|
569
|
+
if (Number.isFinite(id)) { S.ezActiveIds.delete(id); S.mountedIds.delete(id); }
|
|
656
570
|
const key = w.getAttribute(A_ANCHOR);
|
|
657
571
|
if (key && S.wrapByKey.get(key) === w) S.wrapByKey.delete(key);
|
|
658
572
|
w.remove();
|
|
@@ -675,18 +589,19 @@ function recycleAndMove(klass, targetEl, newKey) {
|
|
|
675
589
|
// supprimerait les wraps, et provoquerait une réinjection en haut.
|
|
676
590
|
|
|
677
591
|
function pruneOrphansBetween() {
|
|
678
|
-
if (S.burstActive || (S.scrollSpeed || 0) > 1800) return;
|
|
679
592
|
const klass = 'ezoic-ad-between';
|
|
680
593
|
const cfg = KIND[klass];
|
|
681
|
-
const liveAnchors = new Set(Arch.cache.queryAll('prune-between-anchors', cfg.sel).map(el => el.getAttribute(cfg.anchorAttr)).filter(Boolean));
|
|
682
594
|
|
|
683
595
|
document.querySelectorAll(`.${WRAP_CLASS}.${klass}`).forEach(w => {
|
|
684
596
|
const created = parseInt(w.getAttribute(A_CREATED) || '0', 10);
|
|
685
|
-
if (ts() - created < MIN_PRUNE_AGE_MS) return;
|
|
597
|
+
if (ts() - created < MIN_PRUNE_AGE_MS) return; // grâce post-création
|
|
598
|
+
|
|
686
599
|
const key = w.getAttribute(A_ANCHOR) ?? '';
|
|
687
|
-
const sid = key.slice(klass.length + 1);
|
|
600
|
+
const sid = key.slice(klass.length + 1); // après "ezoic-ad-between:"
|
|
688
601
|
if (!sid) { mutate(() => dropWrap(w)); return; }
|
|
689
|
-
|
|
602
|
+
|
|
603
|
+
const anchorEl = document.querySelector(`${cfg.baseTag}[${cfg.anchorAttr}="${sid}"]`);
|
|
604
|
+
if (!anchorEl?.isConnected) mutate(() => dropWrap(w));
|
|
690
605
|
});
|
|
691
606
|
}
|
|
692
607
|
|
|
@@ -732,8 +647,6 @@ function recycleAndMove(klass, targetEl, newKey) {
|
|
|
732
647
|
const w = insertAfter(el, id, klass, key);
|
|
733
648
|
if (w) { observePh(id); inserted++; }
|
|
734
649
|
} else {
|
|
735
|
-
// Recyclage agressif = source fréquente de churn visuel (surtout sticky/fixed)
|
|
736
|
-
if (klass === 'ezoic-ad-message') break;
|
|
737
650
|
const recycled = recycleAndMove(klass, el, key);
|
|
738
651
|
if (!recycled) break;
|
|
739
652
|
inserted++;
|
|
@@ -744,31 +657,15 @@ function recycleAndMove(klass, targetEl, newKey) {
|
|
|
744
657
|
|
|
745
658
|
// ── IntersectionObserver & Show ────────────────────────────────────────────
|
|
746
659
|
|
|
747
|
-
function ensureIOViewportMode() {
|
|
748
|
-
const mode = isMobile() ? 'm' : 'd';
|
|
749
|
-
if (S.io && S.ioViewportMode !== mode) {
|
|
750
|
-
try { S.io.disconnect(); } catch (_) {}
|
|
751
|
-
S.io = null;
|
|
752
|
-
}
|
|
753
|
-
S.ioViewportMode = mode;
|
|
754
|
-
}
|
|
755
|
-
|
|
756
660
|
function getIO() {
|
|
757
|
-
ensureIOViewportMode();
|
|
758
661
|
if (S.io) return S.io;
|
|
759
662
|
try {
|
|
760
663
|
S.io = new IntersectionObserver(entries => {
|
|
761
664
|
for (const e of entries) {
|
|
762
665
|
if (!e.isIntersecting) continue;
|
|
763
|
-
|
|
764
|
-
const id = parseInt(target
|
|
765
|
-
if (
|
|
766
|
-
const accepted = enqueueShow(id);
|
|
767
|
-
if (accepted) {
|
|
768
|
-
try { S.io?.unobserve(target); } catch (_) {}
|
|
769
|
-
} else if (target?.isConnected) {
|
|
770
|
-
setTimeout(() => { try { if (target.isConnected) S.io?.observe(target); } catch (_) {} }, 300);
|
|
771
|
-
}
|
|
666
|
+
if (e.target instanceof Element) S.io?.unobserve(e.target);
|
|
667
|
+
const id = parseInt(e.target.getAttribute('data-ezoic-id'), 10);
|
|
668
|
+
if (Number.isFinite(id) && id > 0) enqueueShow(id);
|
|
772
669
|
}
|
|
773
670
|
}, { root: null, rootMargin: isMobile() ? IO_MARGIN_MOBILE : IO_MARGIN_DESKTOP, threshold: 0 });
|
|
774
671
|
} catch (_) { S.io = null; }
|
|
@@ -789,15 +686,12 @@ function recycleAndMove(klass, targetEl, newKey) {
|
|
|
789
686
|
}
|
|
790
687
|
|
|
791
688
|
function enqueueShow(id) {
|
|
792
|
-
if (!id || isBlocked()) return
|
|
689
|
+
if (!id || isBlocked()) return;
|
|
793
690
|
const n = parseInt(id, 10);
|
|
794
|
-
if (!Number.isFinite(n) || n <= 0) return
|
|
795
|
-
if (ts() - (S.lastShow.get(n) ?? 0) < SHOW_THROTTLE_MS) return
|
|
796
|
-
const ph = phEl(n);
|
|
797
|
-
if (!ph?.isConnected || isFilled(ph) || !hasSinglePlaceholder(n)) return false;
|
|
691
|
+
if (!Number.isFinite(n) || n <= 0) return;
|
|
692
|
+
if (ts() - (S.lastShow.get(n) ?? 0) < SHOW_THROTTLE_MS) return;
|
|
798
693
|
if (!S.pendingSet.has(n)) { S.pending.push(n); S.pendingSet.add(n); }
|
|
799
694
|
scheduleDrainQueue();
|
|
800
|
-
return true;
|
|
801
695
|
}
|
|
802
696
|
|
|
803
697
|
function scheduleDrainQueue() {
|
|
@@ -863,18 +757,19 @@ function startShowBatch(ids) {
|
|
|
863
757
|
|
|
864
758
|
if (!valid.length) { clearTimeout(timer); return release(); }
|
|
865
759
|
|
|
866
|
-
|
|
760
|
+
window.ezstandalone = window.ezstandalone || {};
|
|
761
|
+
const ez = window.ezstandalone;
|
|
867
762
|
const doShow = () => {
|
|
868
|
-
const prepared =
|
|
763
|
+
const prepared = destroyBeforeReuse(valid);
|
|
869
764
|
if (!prepared.length) { setTimeout(() => { clearTimeout(timer); release(); }, SHOW_RELEASE_MS); return; }
|
|
870
|
-
try { ez.showAds(...prepared); } catch (_) {
|
|
765
|
+
try { ez.showAds(...prepared); } catch (_) {}
|
|
871
766
|
for (const id of prepared) {
|
|
872
767
|
S.ezActiveIds.add(id);
|
|
873
768
|
S.ezShownSinceDestroy.add(id);
|
|
874
769
|
}
|
|
875
770
|
setTimeout(() => { clearTimeout(timer); release(); }, SHOW_RELEASE_MS);
|
|
876
771
|
};
|
|
877
|
-
|
|
772
|
+
Array.isArray(ez.cmd) ? ez.cmd.push(doShow) : doShow();
|
|
878
773
|
} catch (_) { clearTimeout(timer); release(); }
|
|
879
774
|
});
|
|
880
775
|
}
|
|
@@ -889,7 +784,8 @@ function startShowBatch(ids) {
|
|
|
889
784
|
function patchShowAds() {
|
|
890
785
|
const apply = () => {
|
|
891
786
|
try {
|
|
892
|
-
|
|
787
|
+
window.ezstandalone = window.ezstandalone || {};
|
|
788
|
+
const ez = window.ezstandalone;
|
|
893
789
|
if (window.__nbbEzPatched || typeof ez.showAds !== 'function') return;
|
|
894
790
|
window.__nbbEzPatched = true;
|
|
895
791
|
const orig = ez.showAds.bind(ez);
|
|
@@ -916,7 +812,8 @@ function startShowBatch(ids) {
|
|
|
916
812
|
};
|
|
917
813
|
apply();
|
|
918
814
|
if (!window.__nbbEzPatched) {
|
|
919
|
-
|
|
815
|
+
window.ezstandalone = window.ezstandalone || {};
|
|
816
|
+
(window.ezstandalone.cmd = window.ezstandalone.cmd || []).push(apply);
|
|
920
817
|
}
|
|
921
818
|
}
|
|
922
819
|
|
|
@@ -1023,10 +920,8 @@ function startShowBatch(ids) {
|
|
|
1023
920
|
S.runQueued = false;
|
|
1024
921
|
S.sweepQueued = false;
|
|
1025
922
|
S.scrollSpeed = 0;
|
|
1026
|
-
S.cacheFrameArmed = false;
|
|
1027
923
|
S.lastScrollY = 0;
|
|
1028
924
|
S.lastScrollTs = 0;
|
|
1029
|
-
Arch.cache.invalidate('cleanup');
|
|
1030
925
|
}
|
|
1031
926
|
|
|
1032
927
|
// ── MutationObserver ───────────────────────────────────────────────────────
|
|
@@ -1044,14 +939,14 @@ function startShowBatch(ids) {
|
|
|
1044
939
|
sawWrapRemoval = true;
|
|
1045
940
|
}
|
|
1046
941
|
}
|
|
1047
|
-
if (sawWrapRemoval)
|
|
942
|
+
if (sawWrapRemoval) queueSweepDeadWraps();
|
|
1048
943
|
for (const n of m.addedNodes) {
|
|
1049
944
|
if (n.nodeType !== 1) continue;
|
|
1050
945
|
try { healFalseEmpty(n); } catch (_) {}
|
|
1051
946
|
// matches() d'abord (O(1)), querySelector() seulement si nécessaire
|
|
1052
947
|
if (allSel.some(s => { try { return n.matches(s); } catch(_){return false;} }) ||
|
|
1053
948
|
allSel.some(s => { try { return !!n.querySelector(s); } catch(_){return false;} })) {
|
|
1054
|
-
|
|
949
|
+
requestBurst(); return;
|
|
1055
950
|
}
|
|
1056
951
|
}
|
|
1057
952
|
}
|
|
@@ -1130,8 +1025,7 @@ function startShowBatch(ids) {
|
|
|
1130
1025
|
$(window).off('.nbbEzoic');
|
|
1131
1026
|
$(window).on('action:ajaxify.start.nbbEzoic', cleanup);
|
|
1132
1027
|
$(window).on('action:ajaxify.end.nbbEzoic', () => {
|
|
1133
|
-
S.pageKey =
|
|
1134
|
-
Arch.cache.invalidate('ajaxify.end');
|
|
1028
|
+
S.pageKey = pageKey();
|
|
1135
1029
|
blockedUntil = 0;
|
|
1136
1030
|
muteConsole(); ensureTcfLocator(); warmNetwork();
|
|
1137
1031
|
patchShowAds(); getIO(); ensureDomObserver(); sweepDeadWraps(); requestBurst();
|
|
@@ -1154,17 +1048,6 @@ function startShowBatch(ids) {
|
|
|
1154
1048
|
} catch (_) {}
|
|
1155
1049
|
}
|
|
1156
1050
|
|
|
1157
|
-
function bindResize() {
|
|
1158
|
-
let rT = 0;
|
|
1159
|
-
window.addEventListener('resize', () => {
|
|
1160
|
-
if (rT) clearTimeout(rT);
|
|
1161
|
-
rT = setTimeout(() => {
|
|
1162
|
-
ensureIOViewportMode();
|
|
1163
|
-
requestBurst();
|
|
1164
|
-
}, 120);
|
|
1165
|
-
}, { passive: true });
|
|
1166
|
-
}
|
|
1167
|
-
|
|
1168
1051
|
function bindScroll() {
|
|
1169
1052
|
let ticking = false;
|
|
1170
1053
|
try {
|
|
@@ -1191,29 +1074,16 @@ function startShowBatch(ids) {
|
|
|
1191
1074
|
|
|
1192
1075
|
// ── Boot ───────────────────────────────────────────────────────────────────
|
|
1193
1076
|
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
this.modules.infra.patchShowAds();
|
|
1206
|
-
this.modules.viewport.getIO();
|
|
1207
|
-
this.modules.lifecycle.ensureDomObserver();
|
|
1208
|
-
this.modules.lifecycle.bindNodeBB();
|
|
1209
|
-
this.modules.viewport.bindResize();
|
|
1210
|
-
this.modules.viewport.bindScroll();
|
|
1211
|
-
blockedUntil = 0;
|
|
1212
|
-
this.modules.scheduler.requestBurst();
|
|
1213
|
-
},
|
|
1214
|
-
};
|
|
1215
|
-
|
|
1216
|
-
S.pageKey = Arch.page.key();
|
|
1217
|
-
App.boot();
|
|
1077
|
+
S.pageKey = pageKey();
|
|
1078
|
+
muteConsole();
|
|
1079
|
+
ensureTcfLocator();
|
|
1080
|
+
warmNetwork();
|
|
1081
|
+
patchShowAds();
|
|
1082
|
+
getIO();
|
|
1083
|
+
ensureDomObserver();
|
|
1084
|
+
bindNodeBB();
|
|
1085
|
+
bindScroll();
|
|
1086
|
+
blockedUntil = 0;
|
|
1087
|
+
requestBurst();
|
|
1218
1088
|
|
|
1219
1089
|
})();
|
package/public/style.css
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*
|
|
2
|
-
* NodeBB Ezoic Infinite Ads — style.css (
|
|
2
|
+
* NodeBB Ezoic Infinite Ads — style.css (v20)
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
/* ── Wrapper ──────────────────────────────────────────────────────────────── */
|
|
@@ -8,9 +8,8 @@
|
|
|
8
8
|
width: 100%;
|
|
9
9
|
margin: 0 !important;
|
|
10
10
|
padding: 0 !important;
|
|
11
|
-
overflow:
|
|
12
|
-
contain:
|
|
13
|
-
position: relative;
|
|
11
|
+
overflow: hidden;
|
|
12
|
+
contain: layout style;
|
|
14
13
|
}
|
|
15
14
|
|
|
16
15
|
/* Placeholder : 1px minimum pour rester visible par l'IntersectionObserver */
|
|
@@ -51,7 +50,11 @@
|
|
|
51
50
|
position: absolute !important;
|
|
52
51
|
}
|
|
53
52
|
|
|
54
|
-
/*
|
|
53
|
+
/* Neutralise sticky dans nos wraps (évite l'effet "gliding") */
|
|
54
|
+
.nodebb-ezoic-wrap .ezads-sticky-intradiv {
|
|
55
|
+
position: static !important;
|
|
56
|
+
top: auto !important;
|
|
57
|
+
}
|
|
55
58
|
|
|
56
59
|
/* ── Ezoic global (hors de nos wraps) ────────────────────────────────────── */
|
|
57
60
|
.ezoic-ad {
|