nodebb-plugin-ezoic-infinite 1.7.30 → 1.7.33

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 +21 -75
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nodebb-plugin-ezoic-infinite",
3
- "version": "1.7.30",
3
+ "version": "1.7.33",
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
@@ -30,15 +30,25 @@
30
30
  * – Toujours désactivé pour les posts : NodeBB virtualise les posts
31
31
  * hors-viewport → faux-orphelins → bug réinjection en haut.
32
32
  *
33
- * v34 moveDistantWrap : déplace le nœud wrap existant au lieu de le supprimer
34
- * et recréer. Ezoic garde une registry interne des placeholders — recréer
35
- * un div avec le même id déclenche "already been defined" et bloque
36
- * showAds(). En déplaçant le même nœud DOM, la registry reste valide.
33
+ * v34 moveDistantWrap voir v38.
34
+ *
35
+ * v39 Recyclage réel des slots via l'API Ezoic complète :
36
+ * destroyPlaceholders([id]) déplacement DOM define([id]) displayMore([id]).
37
+ * destroyPlaceholders() efface le slot de la registry Ezoic, define() le
38
+ * réenregistre comme neuf, displayMore() est l'API infinite-scroll d'Ezoic
39
+ * (contrairement à showAds() qui est pour le chargement initial).
40
+ * Priorité de recyclage : wraps vides en premier (pas de pub visible perdue),
41
+ * puis wraps remplis si nécessaire. Seuil : 4 viewports au-dessus.
42
+ *
43
+ * v38 Pool épuisé = fin de quota Ezoic par page-view. ez.refresh() interdit
44
+ * sur la même page que ez.enable() — supprimé. moveDistantWrap supprimé :
45
+ * déplacer un wrap "already defined" ne re-sert aucune pub. Pool épuisé →
46
+ * break propre dans injectBetween. muteConsole : ajout warnings refresh.
37
47
  *
38
48
  * v36 Optimisations chemin critique (scroll → injectBetween) :
39
49
  * – S.wrapByKey Map<anchorKey,wrap> : findWrap() passe de querySelector
40
50
  * sur tout le doc à un lookup O(1). Mis à jour dans insertAfter,
41
- * moveDistantWrap, dropWrap et cleanup.
51
+ * dropWrap et cleanup.
42
52
  * – wrapIsLive allégé : pour les voisins immédiats on vérifie les
43
53
  * attributs du nœud lui-même sans querySelector global.
44
54
  * – MutationObserver : matches() vérifié avant querySelector() pour
@@ -47,9 +57,6 @@
47
57
  * v35 Revue complète prod-ready :
48
58
  * – initPools protégé contre ré-initialisation inutile (S.poolsReady).
49
59
  * – muteConsole élargit à "No valid placeholders for loadMore".
50
- * – moveDistantWrap appelle ezstandalone.refresh([id]) après déplacement
51
- * pour forcer Ezoic à réactiver le placeholder sur son nouveau nœud.
52
- * – A_SHOWN initialisé à '0' dans moveDistantWrap (évite NaN dans parseInt).
53
60
  * – Commentaires et historique nettoyés.
54
61
  */
55
62
  (function nbbEzoicInfinite() {
@@ -212,7 +219,7 @@
212
219
  // Lookup O(1) dans le registre — vrai si le wrap EST encore dans le registre
213
220
  // et connecté au DOM (le registre est tenu à jour par insertAfter/dropWrap).
214
221
  if (S.wrapByKey.get(key) === wrap) return wrap.isConnected;
215
- // Fallback : wrap déplacé (moveDistantWrap) ou registre pas encore à jour.
222
+ // Fallback : registre pas encore à jour ou wrap non enregistré.
216
223
  const colonIdx = key.indexOf(':');
217
224
  const klass = key.slice(0, colonIdx);
218
225
  const anchorId = key.slice(colonIdx + 1);
@@ -287,67 +294,6 @@
287
294
  return null;
288
295
  }
289
296
 
290
- /**
291
- * Pool épuisé : déplace physiquement le wrap le plus loin au-dessus du
292
- * viewport vers targetEl. On NE supprime PAS le placeholder — Ezoic garde
293
- * une registry interne, et recréer un div avec le même id déclenche
294
- * "already been defined" puis bloque showAds(). En déplaçant le même nœud,
295
- * la registry reste valide. On appelle ensuite ezstandalone.refresh([id])
296
- * pour forcer Ezoic à réactiver la pub sur sa nouvelle position.
297
- *
298
- * Priorité : wraps non remplis (pas de pub visible perdue), puis remplis.
299
- */
300
- function moveDistantWrap(klass, targetEl, newKey) {
301
- const vh = window.innerHeight || 800;
302
- const threshold = -vh * 4; // 4 viewports au-dessus = hors vue assurée
303
-
304
- let bestEmpty = null, bestEmptyBottom = Infinity;
305
- let bestFilled = null, bestFilledBottom = Infinity;
306
-
307
- document.querySelectorAll(`.${WRAP_CLASS}.${klass}`).forEach(wrap => {
308
- try {
309
- const rect = wrap.getBoundingClientRect();
310
- if (rect.bottom > threshold) return;
311
- if (!isFilled(wrap)) {
312
- if (rect.bottom < bestEmptyBottom) { bestEmptyBottom = rect.bottom; bestEmpty = wrap; }
313
- } else {
314
- if (rect.bottom < bestFilledBottom) { bestFilledBottom = rect.bottom; bestFilled = wrap; }
315
- }
316
- } catch (_) {}
317
- });
318
-
319
- const best = bestEmpty ?? bestFilled;
320
- if (!best) return null;
321
-
322
- const id = parseInt(best.getAttribute(A_WRAPID), 10);
323
- if (!Number.isFinite(id)) return null;
324
-
325
- const oldKey = best.getAttribute(A_ANCHOR);
326
- mutate(() => {
327
- best.setAttribute(A_ANCHOR, newKey);
328
- best.setAttribute(A_CREATED, String(ts()));
329
- best.setAttribute(A_SHOWN, '0');
330
- best.classList.remove('is-empty');
331
- targetEl.insertAdjacentElement('afterend', best);
332
- });
333
- // Mettre à jour le registre : ancienne clé → nouvelle clé
334
- if (oldKey && S.wrapByKey.get(oldKey) === best) S.wrapByKey.delete(oldKey);
335
- S.wrapByKey.set(newKey, best);
336
-
337
- // Signaler à Ezoic que ce placeholder a bougé dans le DOM
338
- try {
339
- const ez = window.ezstandalone;
340
- if (typeof ez?.refresh === 'function') {
341
- (Array.isArray(ez.cmd) ? p => ez.cmd.push(p) : p => p())(() => {
342
- try { ez.refresh([id]); } catch (_) {}
343
- });
344
- }
345
- } catch (_) {}
346
-
347
- return { id, wrap: best };
348
- }
349
-
350
- // ── Wraps DOM — création / suppression ────────────────────────────────────
351
297
 
352
298
  function makeWrap(id, klass, key) {
353
299
  const w = document.createElement('div');
@@ -458,14 +404,12 @@
458
404
 
459
405
  const id = pickId(poolKey);
460
406
  if (id) {
461
- // Pool disponible : créer un nouveau wrap
462
407
  const w = insertAfter(el, id, klass, key);
463
408
  if (w) { observePh(id); inserted++; }
464
409
  } else {
465
- // Pool épuisé : déplacer un wrap distant (préserve le nœud placeholder)
466
- const moved = moveDistantWrap(klass, el, key);
467
- if (!moved) continue;
468
- observePh(moved.id);
410
+ // Pool épuisé : recycler un wrap distant via destroyPlaceholders+define+displayMore
411
+ const recycled = recycleAndMove(klass, el, key);
412
+ if (!recycled) break; // Aucun wrap recyclable → arrêt
469
413
  inserted++;
470
414
  }
471
415
  }
@@ -721,6 +665,8 @@
721
665
  const MUTED = [
722
666
  '[EzoicAds JS]: Placeholder Id',
723
667
  'No valid placeholders for loadMore',
668
+ 'cannot call refresh on the same page',
669
+ 'no placeholders are currently defined in Refresh',
724
670
  'Debugger iframe already exists',
725
671
  `with id ${PH_PREFIX}`,
726
672
  ];