nodebb-plugin-ezoic-infinite 1.8.89 → 1.8.91

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 +42 -32
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nodebb-plugin-ezoic-infinite",
3
- "version": "1.8.89",
3
+ "version": "1.8.91",
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
@@ -81,7 +81,6 @@
81
81
  kind: null,
82
82
  cfg: null,
83
83
  poolsReady: false,
84
- ezEnabled: false,
85
84
  pools: { topics: [], posts: [], categories: [] },
86
85
  cursors: { topics: 0, posts: 0, categories: 0 },
87
86
  mountedIds: new Set(),
@@ -135,23 +134,6 @@
135
134
  S.poolsReady = true;
136
135
  }
137
136
 
138
- function enableEzoic(cfg) {
139
- if (S.ezEnabled) return;
140
- const ids = [
141
- ...parseIds(cfg.placeholderIds),
142
- ...parseIds(cfg.messagePlaceholderIds),
143
- ...parseIds(cfg.categoryPlaceholderIds),
144
- ];
145
- if (!ids.length) return;
146
- S.ezEnabled = true; // set synchronously to block concurrent calls before the callback runs
147
- window.ezstandalone = window.ezstandalone || {};
148
- const ez = window.ezstandalone;
149
- const doEnable = () => {
150
- try { ez.define(...ids); ez.enable(); } catch (_) {}
151
- };
152
- typeof ez.cmd?.push === 'function' ? ez.cmd.push(doEnable) : doEnable();
153
- }
154
-
155
137
  // ── Page identity ──────────────────────────────────────────────────────────
156
138
 
157
139
  function pageKey() {
@@ -642,7 +624,6 @@
642
624
  const cfg = await fetchConfig();
643
625
  if (!cfg || cfg.excluded) return 0;
644
626
  initPools(cfg);
645
- enableEzoic(cfg);
646
627
 
647
628
  const kind = getKind();
648
629
  if (kind === 'other') return 0;
@@ -722,8 +703,6 @@
722
703
  S.wrapByKey.clear();
723
704
  S.wrapsByClass.clear();
724
705
  S.kind = null;
725
- // S.ezEnabled intentionally NOT reset: ez.define()+ez.enable() must be called
726
- // only once per full page load, not on every SPA navigation.
727
706
  S.inflight = 0;
728
707
  S.pending.clear();
729
708
  S.burstActive = false;
@@ -907,25 +886,56 @@
907
886
 
908
887
  // Retry boot: sa.min.js async + Cloudflare Rocket Loader + NodeBB SPA
909
888
  // can cause client.js to boot before DOM/Ezoic are ready.
910
- // Retries stop once ads are mounted or after ~10s.
911
- // If Ezoic defineScript failed (CMP race on first load), reload sa.min.js once.
889
+ //
890
+ // Two reload cases:
891
+ // 1. sa.min.js never injected (Rocket Loader stripped it) — reload immediately.
892
+ // 2. Cold-start crash: first visit with no Ezoic cookies causes sa.min.js to set
893
+ // loadingStatus='LOADING' but never reach 'complete' (_ezaq.ab_test_id undefined
894
+ // in ez-standalone.js → onStandaloneLoadEvent crash). After ~6s, remove and reload
895
+ // sa.min.js; Ezoic's partial first-run state may let the second run succeed.
896
+ // Once recovered, re-enqueue all mounted placeholders so showAds() fires.
912
897
  let _retries = 0;
913
898
  let _scriptReloaded = false;
899
+ let _postReloadShown = false;
914
900
  function retryBoot() {
915
- if (_retries >= 12 || S.mountedIds.size > 0) return;
901
+ if (_retries >= 12) return;
916
902
  _retries++;
917
903
  patchShowAds();
918
904
 
919
- // Reload sa.min.js only if Ezoic never initialized at all (no loadingStatus)
920
- // AND sa.min.js is not already present in the DOM (to avoid duplicates on first load
921
- // when the script is injected server-side but loadingStatus hasn't been set yet).
922
- // Do NOT reload when loadingStatus === 'complete' (post-defineScript-failure):
923
- // that would trigger a second defineScript failed error.
924
- if (!_scriptReloaded && _retries <= 3) {
925
- const ez = window.ezstandalone;
926
- if (!ez?.loadingStatus && !document.querySelector('script[src*="sa.min.js"]')) {
905
+ const ez = window.ezstandalone;
906
+ const status = ez?.loadingStatus;
907
+
908
+ // After reload: once Ezoic reaches 'complete', re-call showAds for all mounted placeholders
909
+ if (_scriptReloaded && !_postReloadShown && status === 'complete') {
910
+ _postReloadShown = true;
911
+ for (const id of S.mountedIds) { try { enqueueShow(id); } catch (_) {} }
912
+ return;
913
+ }
914
+
915
+ // Normal exit: placeholders mounted, no reload triggered (healthy load)
916
+ if (S.mountedIds.size > 0 && !_scriptReloaded) return;
917
+ // Exit once reload is done and re-show has been triggered
918
+ if (_scriptReloaded && _postReloadShown) return;
919
+
920
+ if (!_scriptReloaded) {
921
+ // Case 1: sa.min.js never injected (Rocket Loader stripped it, etc.)
922
+ const neverInjected = !status && !document.querySelector('script[src*="sa.min.js"]') && _retries <= 3;
923
+ // Case 2: cold-start crash — loadingStatus stuck before 'complete' after enough wait.
924
+ // Do NOT reload when status==='complete' (post-defineScript-failure would re-trigger).
925
+ const anyFilled = !!document.querySelector(`.${WRAP_CLASS} ${FILL_SEL}`);
926
+ const crashed = _retries >= 8 && !anyFilled && status && status !== 'complete';
927
+ if (neverInjected || crashed) {
927
928
  _scriptReloaded = true;
928
929
  try {
930
+ if (crashed) {
931
+ // Remove the broken script before re-adding to avoid a duplicate
932
+ const old = document.querySelector('script[src*="sa.min.js"]');
933
+ if (old) old.remove();
934
+ // Reset ezstandalone to initial state, preserving queued cmd items
935
+ const savedCmd = Array.isArray(ez?.cmd) ? [...ez.cmd] : [];
936
+ window.ezstandalone = { cmd: savedCmd };
937
+ window.__nbbEzPatched = false;
938
+ }
929
939
  const s = document.createElement('script');
930
940
  s.setAttribute('data-cfasync', 'false');
931
941
  s.src = '//www.ezojs.com/ezoic/sa.min.js';