nodebb-plugin-ezoic-infinite 1.6.13 → 1.6.15

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 +64 -63
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nodebb-plugin-ezoic-infinite",
3
- "version": "1.6.13",
3
+ "version": "1.6.15",
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
@@ -1,61 +1,66 @@
1
1
  (function () {
2
2
  'use strict';
3
3
 
4
- function ezoicAnchorKeyFromEl(el) {
4
+ function ezoicTopicIdFromLi(li) {
5
5
  try {
6
- if (!el || !el.getAttribute) return '';
7
- var tid = el.getAttribute('data-tid') || el.getAttribute('data-topic-id');
8
- if (tid) return 'tid:' + String(tid);
9
- var pid = el.getAttribute('data-pid') || el.getAttribute('data-id');
10
- if (pid) return 'pid:' + String(pid);
11
- var uid = el.getAttribute('data-uid');
12
- if (uid) return 'uid:' + String(uid);
6
+ if (!li) return '';
7
+ // try explicit attrs first
8
+ var tid = li.getAttribute && (li.getAttribute('data-tid') || li.getAttribute('data-topic-id'));
9
+ if (tid) return String(tid);
10
+ // try finding a topic permalink like /topic/13789/...
11
+ var a = li.querySelector && li.querySelector('a[href*="/topic/"]');
12
+ if (!a) return '';
13
+ var href = a.getAttribute('href') || '';
14
+ var m = href.match(/\/topic\/(\d+)\b/);
15
+ if (m && m[1]) return m[1];
13
16
  } catch (e) {}
14
17
  return '';
15
18
  }
16
19
 
17
- function ezoicFindAnchorEl(anchorKey, scope) {
20
+ function ezoicAnchorKeyFromTarget(target) {
21
+ try {
22
+ if (!target) return '';
23
+ var li = target.closest ? target.closest('li') : null;
24
+ if (!li) li = target.tagName === 'LI' ? target : null;
25
+ if (!li) return '';
26
+ var tid = ezoicTopicIdFromLi(li);
27
+ if (tid) return 'topic:' + tid;
28
+ } catch (e) {}
29
+ return '';
30
+ }
31
+
32
+ function ezoicFindAnchorLiByKey(anchorKey, scope) {
18
33
  try {
19
34
  if (!anchorKey) return null;
35
+ if (anchorKey.indexOf('topic:') !== 0) return null;
36
+ var tid = anchorKey.slice(6);
20
37
  var root = scope || document;
21
- if (anchorKey.indexOf('tid:') === 0) {
22
- var v = anchorKey.slice(4);
23
- return root.querySelector('[data-tid="' + v + '"], [data-topic-id="' + v + '"]');
24
- }
25
- if (anchorKey.indexOf('pid:') === 0) {
26
- var p = anchorKey.slice(4);
27
- return root.querySelector('[data-pid="' + p + '"], [data-id="' + p + '"]');
28
- }
29
- if (anchorKey.indexOf('uid:') === 0) {
30
- var u = anchorKey.slice(4);
31
- return root.querySelector('[data-uid="' + u + '"]');
32
- }
38
+ // locate any link to this topic and climb to li
39
+ var link = root.querySelector('a[href^="/topic/' + tid + '"], a[href*="/topic/' + tid + '/"]');
40
+ if (!link) return null;
41
+ return link.closest ? link.closest('li') : null;
33
42
  } catch (e) {}
34
43
  return null;
35
44
  }
36
45
 
37
- function ezoicReconcileHosts(scope) {
38
- // Ensure each li.nodebb-ezoic-host stays directly after its anchor <li>.
39
- // Prevents "all hosts under first topic" after NodeBB re-render/virtualize.
46
+ function ezoicReconcileOrPurgeByTopic(scope) {
40
47
  try {
41
48
  var root = scope || document;
42
49
  var hosts = root.querySelectorAll('li.nodebb-ezoic-host[data-ezoic-anchor]');
43
50
  if (!hosts || !hosts.length) return;
44
51
 
45
- hosts.forEach(function (host) {
52
+ hosts.forEach(function(host){
46
53
  try {
47
- var anchorKey = host.getAttribute('data-ezoic-anchor') || '';
48
- if (!anchorKey) return;
49
- var ul = host.parentElement;
50
- if (!ul) return;
51
-
52
- var anchor = ezoicFindAnchorEl(anchorKey, ul) || ezoicFindAnchorEl(anchorKey, document);
53
- if (!anchor) return;
54
-
55
- // Anchor is often inside the <li> topic; normalize to list item
56
- var anchorLi = anchor.closest ? (anchor.closest('li') || anchor) : anchor;
57
- if (!anchorLi || !anchorLi.parentElement) return;
58
-
54
+ var listEl = host.parentElement;
55
+ if (!listEl) return;
56
+ var key = host.getAttribute('data-ezoic-anchor') || '';
57
+ if (!key) return;
58
+
59
+ var anchorLi = ezoicFindAnchorLiByKey(key, listEl) || ezoicFindAnchorLiByKey(key, document);
60
+ if (!anchorLi) {
61
+ host.remove();
62
+ return;
63
+ }
59
64
  if (host.previousElementSibling !== anchorLi) {
60
65
  anchorLi.insertAdjacentElement('afterend', host);
61
66
  }
@@ -64,8 +69,6 @@ function ezoicReconcileHosts(scope) {
64
69
  } catch (e) {}
65
70
  }
66
71
 
67
- ' + '';
68
-
69
72
 
70
73
  function ezoicInsertAfterWithUlGuard(target, wrap, kindClass) {
71
74
  try {
@@ -80,7 +83,7 @@ function ezoicInsertAfterWithUlGuard(target, wrap, kindClass) {
80
83
  host.setAttribute('role', 'listitem');
81
84
  host.style.listStyle = 'none';
82
85
  host.style.width = '100%';
83
- try { var ak = ezoicAnchorKeyFromEl(target); if (ak) host.setAttribute('data-ezoic-anchor', ak); } catch(e) {}
86
+ try { var ak = ezoicAnchorKeyFromTarget(target); if (ak) host.setAttribute('data-ezoic-anchor', ak); } catch(e) {}
84
87
 
85
88
  // Insert host after the target listitem, then move the wrap inside.
86
89
  if (target.insertAdjacentElement) {
@@ -115,7 +118,7 @@ function ezoicRepairInvalidBetweenWraps() {
115
118
  host.setAttribute('role', 'listitem');
116
119
  host.style.listStyle = 'none';
117
120
  host.style.width = '100%';
118
- try { var ak = ezoicAnchorKeyFromEl(target); if (ak) host.setAttribute('data-ezoic-anchor', ak); } catch(e) {}
121
+ try { var prevLi = wrap.previousElementSibling; var ak2 = ezoicAnchorKeyFromTarget(prevLi || wrap); if (ak2) host.setAttribute('data-ezoic-anchor', ak2); } catch(e) {}
119
122
  p.insertBefore(host, wrap);
120
123
  host.appendChild(wrap);
121
124
  try { wrap.style.width = '100%'; } catch (e) {}
@@ -1647,52 +1650,50 @@ if (window.jQuery) {
1647
1650
  // ===== /V12.2 =====
1648
1651
 
1649
1652
 
1650
- // ===== V12.3 reconcile scheduler =====
1651
- (function(){
1652
- var pending = false;
1653
- var last = 0;
1654
- var COOLDOWN = 180;
1655
1653
 
1654
+ // ===== V12.5 topic-anchor reconcile =====
1655
+ (function(){
1656
+ var pending=false, last=0, COOLDOWN=140;
1656
1657
  function schedule(scope){
1657
- var now = Date.now();
1658
- if (now - last < COOLDOWN) return;
1658
+ var now=Date.now();
1659
+ if (now-last<COOLDOWN) return;
1659
1660
  if (pending) return;
1660
- pending = true;
1661
+ pending=true;
1661
1662
  requestAnimationFrame(function(){
1662
- pending = false;
1663
- last = Date.now();
1664
- try { ezoicReconcileHosts(scope); } catch(e) {}
1663
+ pending=false; last=Date.now();
1664
+ try { ezoicReconcileOrPurgeByTopic(scope); } catch(e) {}
1665
1665
  });
1666
1666
  }
1667
1667
 
1668
- window.addEventListener('scroll', function(){ schedule(document); }, { passive: true });
1669
- window.addEventListener('resize', function(){ schedule(document); }, { passive: true });
1668
+ window.addEventListener('scroll', function(){ schedule(document); }, { passive:true });
1669
+ window.addEventListener('resize', function(){ schedule(document); }, { passive:true });
1670
1670
 
1671
1671
  if (window.jQuery) {
1672
1672
  window.jQuery(window).on('action:ajaxify.end action:infiniteScroll.loaded', function(){
1673
1673
  setTimeout(function(){ schedule(document); }, 0);
1674
1674
  setTimeout(function(){ schedule(document); }, 220);
1675
- setTimeout(function(){ schedule(document); }, 600);
1675
+ setTimeout(function(){ schedule(document); }, 700);
1676
1676
  });
1677
1677
  }
1678
1678
 
1679
- // MutationObserver lightweight: only watch ULs for child list changes
1680
1679
  try {
1681
1680
  if (typeof MutationObserver !== 'undefined') {
1682
1681
  var mo = new MutationObserver(function(muts){
1683
- // if any li hosts are moved/added, reconcile
1684
1682
  for (var i=0;i<muts.length;i++){
1685
- var m = muts[i];
1686
- if (m.addedNodes && m.addedNodes.length) { schedule(m.target); break; }
1687
- if (m.removedNodes && m.removedNodes.length) { schedule(m.target); break; }
1683
+ var m=muts[i];
1684
+ if ((m.addedNodes && m.addedNodes.length) || (m.removedNodes && m.removedNodes.length)) {
1685
+ schedule(m.target);
1686
+ break;
1687
+ }
1688
1688
  }
1689
1689
  });
1690
1690
  document.querySelectorAll('ul,ol').forEach(function(list){
1691
- try { mo.observe(list, {childList:true}); } catch(e) {}
1691
+ try { mo.observe(list, {childList:true, subtree:false}); } catch(e) {}
1692
1692
  });
1693
1693
  }
1694
1694
  } catch(e){}
1695
1695
 
1696
- setTimeout(function(){ try { schedule(document); } catch(e) {} }, 0);
1696
+ setTimeout(function(){ schedule(document); }, 0);
1697
1697
  })();
1698
- // ===== /V12.3 =====
1698
+ // ===== /V12.5 =====
1699
+