nodebb-plugin-ezoic-infinite 1.8.99 → 1.9.1
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 +2 -0
- package/package.json +1 -1
- package/public/client.js +38 -47
package/library.js
CHANGED
|
@@ -243,6 +243,8 @@ plugin.injectEzoicHead = async (data) => {
|
|
|
243
243
|
};
|
|
244
244
|
|
|
245
245
|
plugin.init = async ({ router, middleware }) => {
|
|
246
|
+
getSettings().catch(() => {});
|
|
247
|
+
|
|
246
248
|
async function render(req, res) {
|
|
247
249
|
const settings = await getSettings();
|
|
248
250
|
const allGroups = await getAllGroups();
|
package/package.json
CHANGED
package/public/client.js
CHANGED
|
@@ -58,6 +58,7 @@
|
|
|
58
58
|
};
|
|
59
59
|
|
|
60
60
|
const FILL_SEL = 'iframe, ins, img, video, [data-google-container-id], div[id$="__container__"]';
|
|
61
|
+
const SUPPORTS_HAS = typeof CSS !== 'undefined' && !!CSS.supports?.('selector(:has(*))');
|
|
61
62
|
|
|
62
63
|
// ── Utility ────────────────────────────────────────────────────────────────
|
|
63
64
|
|
|
@@ -101,16 +102,15 @@
|
|
|
101
102
|
burstDeadline: 0,
|
|
102
103
|
burstCount: 0,
|
|
103
104
|
lastBurstTs: 0,
|
|
105
|
+
cleaningUp: false,
|
|
104
106
|
};
|
|
105
107
|
|
|
106
108
|
const isBlocked = () => now() < S.blockedUntil;
|
|
107
109
|
|
|
108
110
|
// ── DOM caches (burst-scoped) ──────────────────────────────────────────────
|
|
109
111
|
|
|
110
|
-
let _postsCache = null, _postsCacheTs = 0;
|
|
111
|
-
let _topicsCache = null, _topicsCacheTs = 0;
|
|
112
|
-
let _catsCache = null, _catsCacheTs = 0;
|
|
113
112
|
const POSTS_CACHE_MS = 200;
|
|
113
|
+
const _dc = { posts: null, postsAt: 0, topics: null, topicsAt: 0, cats: null, catsAt: 0 };
|
|
114
114
|
|
|
115
115
|
function mutate(fn) {
|
|
116
116
|
S.mutGuard++;
|
|
@@ -121,10 +121,8 @@
|
|
|
121
121
|
|
|
122
122
|
async function fetchConfig() {
|
|
123
123
|
if (S.cfg) return S.cfg;
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
if (inline && typeof inline === 'object') { S.cfg = inline; return S.cfg; }
|
|
127
|
-
} catch (_) {}
|
|
124
|
+
const inline = window.__nbbEzoicCfg;
|
|
125
|
+
if (inline && typeof inline === 'object') { S.cfg = inline; return S.cfg; }
|
|
128
126
|
try {
|
|
129
127
|
const ctrl = new AbortController();
|
|
130
128
|
const t = setTimeout(() => ctrl.abort(), 5_000);
|
|
@@ -184,37 +182,41 @@
|
|
|
184
182
|
|
|
185
183
|
function getPosts() {
|
|
186
184
|
const t = now();
|
|
187
|
-
if (
|
|
188
|
-
const all =
|
|
185
|
+
if (_dc.posts && t - _dc.postsAt < POSTS_CACHE_MS) return _dc.posts;
|
|
186
|
+
const all = SUPPORTS_HAS
|
|
187
|
+
? document.querySelectorAll('[component="post"][data-pid]:has([component="post/content"])')
|
|
188
|
+
: document.querySelectorAll(SEL.post);
|
|
189
189
|
const out = [];
|
|
190
190
|
for (let i = 0; i < all.length; i++) {
|
|
191
191
|
const el = all[i];
|
|
192
192
|
if (!el.isConnected) continue;
|
|
193
|
-
if (
|
|
194
|
-
|
|
193
|
+
if (!SUPPORTS_HAS) {
|
|
194
|
+
if (el.childElementCount === 0) continue;
|
|
195
|
+
if (!el.querySelector('[component="post/content"]')) continue;
|
|
196
|
+
}
|
|
195
197
|
const parent = el.parentElement?.closest(SEL.post);
|
|
196
198
|
if (parent && parent !== el) continue;
|
|
197
199
|
if (el.getAttribute('component') === 'post/parent') continue;
|
|
198
200
|
out.push(el);
|
|
199
201
|
}
|
|
200
|
-
|
|
201
|
-
|
|
202
|
+
_dc.posts = out;
|
|
203
|
+
_dc.postsAt = t;
|
|
202
204
|
return out;
|
|
203
205
|
}
|
|
204
206
|
|
|
205
207
|
function getTopics() {
|
|
206
208
|
const t = now();
|
|
207
|
-
if (
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
return
|
|
209
|
+
if (_dc.topics && t - _dc.topicsAt < POSTS_CACHE_MS) return _dc.topics;
|
|
210
|
+
_dc.topics = Array.from(document.querySelectorAll(SEL.topic));
|
|
211
|
+
_dc.topicsAt = t;
|
|
212
|
+
return _dc.topics;
|
|
211
213
|
}
|
|
212
214
|
function getCategories() {
|
|
213
215
|
const t = now();
|
|
214
|
-
if (
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
return
|
|
216
|
+
if (_dc.cats && t - _dc.catsAt < POSTS_CACHE_MS) return _dc.cats;
|
|
217
|
+
_dc.cats = Array.from(document.querySelectorAll(SEL.category));
|
|
218
|
+
_dc.catsAt = t;
|
|
219
|
+
return _dc.cats;
|
|
218
220
|
}
|
|
219
221
|
|
|
220
222
|
// ── Anchor keys & wrap registry ────────────────────────────────────────────
|
|
@@ -271,22 +273,7 @@
|
|
|
271
273
|
function wrapIsLive(wrap) {
|
|
272
274
|
if (!wrap?.classList?.contains(WRAP_CLASS)) return false;
|
|
273
275
|
const key = wrap.getAttribute(ATTR.ANCHOR);
|
|
274
|
-
|
|
275
|
-
if (S.wrapByKey.get(key) === wrap) return wrap.isConnected;
|
|
276
|
-
const colonIdx = key.indexOf(':');
|
|
277
|
-
const klass = key.slice(0, colonIdx);
|
|
278
|
-
const anchorId = key.slice(colonIdx + 1);
|
|
279
|
-
const cfg = KIND[klass];
|
|
280
|
-
if (!cfg) return false;
|
|
281
|
-
const parent = wrap.parentElement;
|
|
282
|
-
if (!parent) return false;
|
|
283
|
-
const sel = `${cfg.baseTag || ''}[${cfg.anchorAttr}="${anchorId}"]`;
|
|
284
|
-
for (const sib of parent.children) {
|
|
285
|
-
if (sib !== wrap) {
|
|
286
|
-
try { if (sib.matches(sel)) return sib.isConnected; } catch (_) {}
|
|
287
|
-
}
|
|
288
|
-
}
|
|
289
|
-
return false;
|
|
276
|
+
return !!key && S.wrapByKey.get(key) === wrap && wrap.isConnected;
|
|
290
277
|
}
|
|
291
278
|
|
|
292
279
|
const adjacentWrap = el => wrapIsLive(el.nextElementSibling) || wrapIsLive(el.previousElementSibling);
|
|
@@ -435,15 +422,16 @@
|
|
|
435
422
|
if (ph instanceof Element) S.io?.unobserve(ph);
|
|
436
423
|
const id = parseInt(w.getAttribute(ATTR.WRAPID), 10);
|
|
437
424
|
if (Number.isFinite(id)) {
|
|
438
|
-
S.mountedIds.delete(id);
|
|
439
|
-
S.lastShow.delete(id);
|
|
440
425
|
const timers = S.wrapTimers.get(id);
|
|
441
426
|
if (timers) { for (const t of timers) clearTimeout(t); S.wrapTimers.delete(id); }
|
|
442
427
|
}
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
428
|
+
if (!S.cleaningUp) {
|
|
429
|
+
if (Number.isFinite(id)) { S.mountedIds.delete(id); S.lastShow.delete(id); }
|
|
430
|
+
const key = w.getAttribute(ATTR.ANCHOR);
|
|
431
|
+
if (key && S.wrapByKey.get(key) === w) S.wrapByKey.delete(key);
|
|
432
|
+
const colonIdx = key?.indexOf(':') ?? -1;
|
|
433
|
+
if (colonIdx > 0) S.wrapsByClass.get(key.slice(0, colonIdx))?.delete(w);
|
|
434
|
+
}
|
|
447
435
|
w.remove();
|
|
448
436
|
} catch (_) {}
|
|
449
437
|
}
|
|
@@ -722,16 +710,19 @@
|
|
|
722
710
|
const ez = window.ezstandalone;
|
|
723
711
|
if (typeof ez?.destroyPlaceholders === 'function') ez.destroyPlaceholders();
|
|
724
712
|
} catch (_) {}
|
|
713
|
+
S.cleaningUp = true;
|
|
725
714
|
mutate(() => {
|
|
726
715
|
for (const w of document.querySelectorAll(`.${WRAP_CLASS}`)) dropWrap(w);
|
|
727
716
|
});
|
|
717
|
+
S.cleaningUp = false;
|
|
718
|
+
// Safety net: wrapTimers should be empty after dropWrap loop, but clear any orphans.
|
|
728
719
|
for (const timers of S.wrapTimers.values()) { for (const t of timers) clearTimeout(t); }
|
|
729
720
|
S.wrapTimers.clear();
|
|
730
721
|
S.domObs?.disconnect(); S.domObs = null;
|
|
731
722
|
S.io?.disconnect(); S.io = null; _ioMobile = null;
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
723
|
+
_dc.posts = null; _dc.postsAt = 0;
|
|
724
|
+
_dc.topics = null; _dc.topicsAt = 0;
|
|
725
|
+
_dc.cats = null; _dc.catsAt = 0;
|
|
735
726
|
// cfg/opts/pools are static for the session (window.__nbbEzoicCfg is set once
|
|
736
727
|
// by the server and never changes between SPA navigations) — preserve them.
|
|
737
728
|
S.cursors = { topics: 0, posts: 0, categories: 0 };
|
|
@@ -796,7 +787,7 @@
|
|
|
796
787
|
}
|
|
797
788
|
}
|
|
798
789
|
}
|
|
799
|
-
if (needsBurst) {
|
|
790
|
+
if (needsBurst) { _dc.postsAt = 0; _dc.topicsAt = 0; _dc.catsAt = 0; requestBurst(); }
|
|
800
791
|
});
|
|
801
792
|
try {
|
|
802
793
|
const target = document.getElementById('content') || document.body;
|