nodebb-plugin-ezoic-infinite 1.6.54 → 1.6.55
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/package.json +1 -1
- package/public/client.js +99 -60
package/package.json
CHANGED
package/public/client.js
CHANGED
|
@@ -1,32 +1,39 @@
|
|
|
1
1
|
(function () {
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
|
+
// --- 1. VARIABLES ET CONFIG ---
|
|
4
5
|
const WRAP_CLASS = 'nodebb-ezoic-wrap';
|
|
5
6
|
const PINNED_ATTR = 'data-ezoic-pinned';
|
|
6
|
-
const PROCESSED_ATTR = 'data-ezoic-seen'; // Nouveau : marqueur de sujet
|
|
7
7
|
const PLACEHOLDER_PREFIX = 'ezoic-pub-ad-placeholder-';
|
|
8
|
-
|
|
8
|
+
|
|
9
9
|
let config = null;
|
|
10
10
|
let usedIds = new Set();
|
|
11
11
|
let scheduleTimer = null;
|
|
12
12
|
|
|
13
|
+
// --- 2. SÉLECTEURS DE THÈMES ---
|
|
13
14
|
function getTopicList() {
|
|
14
|
-
return document.querySelector('[component="
|
|
15
|
+
return document.querySelector('.category [component="category"], .categories [component="categories"], [component="topic/list"], .topic-list');
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function getPostList() {
|
|
19
|
+
return document.querySelector('[component="topic"], [component="post/list"]');
|
|
15
20
|
}
|
|
16
21
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
22
|
+
// --- 3. LOGIQUE DES POOLS D'ID ---
|
|
23
|
+
function getNextId(poolStr) {
|
|
24
|
+
if (!poolStr) return null;
|
|
25
|
+
const ids = poolStr.split(/[\s,]+/).filter(Boolean);
|
|
20
26
|
for (const id of ids) {
|
|
21
|
-
const
|
|
22
|
-
if (
|
|
23
|
-
usedIds.add(
|
|
24
|
-
return
|
|
27
|
+
const num = id.replace(/[^\d]/g, '');
|
|
28
|
+
if (num && !usedIds.has(num)) {
|
|
29
|
+
usedIds.add(num);
|
|
30
|
+
return num;
|
|
25
31
|
}
|
|
26
32
|
}
|
|
27
33
|
return null;
|
|
28
34
|
}
|
|
29
35
|
|
|
36
|
+
// --- 4. APPEL EZOIC (REFRESH & SHOW) ---
|
|
30
37
|
function callEzoic(id) {
|
|
31
38
|
if (window.ezstandalone) {
|
|
32
39
|
try {
|
|
@@ -38,87 +45,119 @@
|
|
|
38
45
|
} else {
|
|
39
46
|
window.ezstandalone.refresh();
|
|
40
47
|
}
|
|
41
|
-
} catch (e) { console.warn('[ezoic]
|
|
48
|
+
} catch (e) { console.warn('[ezoic] refresh error', id, e); }
|
|
42
49
|
}
|
|
43
50
|
}
|
|
44
51
|
|
|
52
|
+
// --- 5. INJECTION SÉCURISÉE (ANTI-PILEUP) ---
|
|
45
53
|
function inject() {
|
|
46
54
|
if (!config || config.excluded) return;
|
|
47
|
-
const ul = getTopicList();
|
|
48
|
-
if (!ul) return;
|
|
49
55
|
|
|
50
|
-
//
|
|
51
|
-
const
|
|
52
|
-
if (
|
|
56
|
+
// A. LISTE DES SUJETS (Topics)
|
|
57
|
+
const ul = getTopicList();
|
|
58
|
+
if (ul && config.enableBetweenAds) {
|
|
59
|
+
// Nettoyage des pubs orphelines (celles qui n'ont plus de LI au dessus à cause du scroll up)
|
|
60
|
+
const wraps = ul.querySelectorAll('.' + WRAP_CLASS);
|
|
61
|
+
wraps.forEach(w => {
|
|
62
|
+
if (!w.previousElementSibling || w.previousElementSibling.tagName !== 'LI') w.remove();
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
const items = Array.from(ul.children).filter(c => c.tagName === 'LI' && !c.classList.contains(WRAP_CLASS));
|
|
66
|
+
if (items.length > 0) {
|
|
67
|
+
// Pub n°1 (Pinned)
|
|
68
|
+
if (config.showFirstTopicAd && !ul.querySelector(`[${PINNED_ATTR}="true"]`)) {
|
|
69
|
+
insertAd(items[0], getNextId(config.placeholderIds), true);
|
|
70
|
+
}
|
|
53
71
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
72
|
+
// Pubs d'intervalles
|
|
73
|
+
const interval = parseInt(config.intervalPosts, 10) || 5;
|
|
74
|
+
items.forEach((li, idx) => {
|
|
75
|
+
const pos = idx + 1;
|
|
76
|
+
if (pos > 1 && pos % interval === 0) {
|
|
77
|
+
// Vérifie si ce LI a déjà une pub juste après lui pour éviter les doublons
|
|
78
|
+
const next = li.nextElementSibling;
|
|
79
|
+
if (!next || !next.classList.contains(WRAP_CLASS)) {
|
|
80
|
+
insertAd(li, getNextId(config.placeholderIds), false);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
}
|
|
58
85
|
}
|
|
59
86
|
|
|
60
|
-
//
|
|
61
|
-
const
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
87
|
+
// B. LISTE DES MESSAGES (Posts)
|
|
88
|
+
const postList = getPostList();
|
|
89
|
+
if (postList && config.enableMessageAds) {
|
|
90
|
+
const posts = Array.from(postList.querySelectorAll('[component="post"]'));
|
|
91
|
+
if (config.showFirstMessageAd && posts.length > 0 && !postList.querySelector('.ezoic-msg-first')) {
|
|
92
|
+
insertAd(posts[0], getNextId(config.messagePlaceholderIds), false, 'ezoic-msg-first');
|
|
93
|
+
}
|
|
66
94
|
|
|
67
|
-
|
|
68
|
-
if (
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
95
|
+
const msgInterval = parseInt(config.messageIntervalPosts, 10) || 5;
|
|
96
|
+
if (msgInterval > 0) {
|
|
97
|
+
posts.forEach((post, idx) => {
|
|
98
|
+
const pPos = idx + 1;
|
|
99
|
+
if (pPos > 1 && pPos % msgInterval === 0) {
|
|
100
|
+
if (!post.nextElementSibling || !post.nextElementSibling.classList.contains(WRAP_CLASS)) {
|
|
101
|
+
insertAd(post, getNextId(config.messagePlaceholderIds), false);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
});
|
|
75
105
|
}
|
|
76
|
-
}
|
|
106
|
+
}
|
|
77
107
|
}
|
|
78
108
|
|
|
79
|
-
function insertAd(target, id, isPinned) {
|
|
80
|
-
if (!
|
|
81
|
-
|
|
109
|
+
function insertAd(target, id, isPinned, extraClass = '') {
|
|
110
|
+
if (!target || !id) return;
|
|
82
111
|
const wrap = document.createElement('div');
|
|
83
|
-
wrap.className = WRAP_CLASS
|
|
112
|
+
wrap.className = `${WRAP_CLASS} ezoic-ad-between ${extraClass}`;
|
|
84
113
|
if (isPinned) wrap.setAttribute(PINNED_ATTR, 'true');
|
|
85
114
|
|
|
86
115
|
const placeholder = document.createElement('div');
|
|
87
116
|
placeholder.id = PLACEHOLDER_PREFIX + id;
|
|
88
117
|
wrap.appendChild(placeholder);
|
|
89
118
|
|
|
90
|
-
// Insertion physique
|
|
91
119
|
target.after(wrap);
|
|
92
120
|
|
|
93
|
-
// On
|
|
121
|
+
// On laisse le DOM respirer 50ms avant d'appeler Ezoic
|
|
94
122
|
setTimeout(() => callEzoic(id), 50);
|
|
95
123
|
}
|
|
96
124
|
|
|
97
|
-
|
|
125
|
+
// --- 6. INITIALISATION ET HOOKS ---
|
|
126
|
+
async function fetchConfig() {
|
|
98
127
|
try {
|
|
99
128
|
const res = await fetch('/api/plugins/ezoic-infinite/config');
|
|
100
129
|
config = await res.json();
|
|
130
|
+
} catch (e) { console.error('[ezoic] config fetch failed'); }
|
|
131
|
+
}
|
|
101
132
|
|
|
102
|
-
|
|
103
|
-
|
|
133
|
+
function schedule() {
|
|
134
|
+
if (scheduleTimer) clearTimeout(scheduleTimer);
|
|
135
|
+
scheduleTimer = setTimeout(inject, 250);
|
|
136
|
+
}
|
|
104
137
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
138
|
+
function init() {
|
|
139
|
+
fetchConfig().then(() => {
|
|
140
|
+
schedule();
|
|
141
|
+
|
|
142
|
+
// MutationObserver pour le scroll infini
|
|
143
|
+
const body = document.body;
|
|
144
|
+
const mo = new MutationObserver((mutations) => {
|
|
145
|
+
for (let m of mutations) {
|
|
146
|
+
if (m.addedNodes.length > 0) {
|
|
147
|
+
schedule();
|
|
148
|
+
break;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
});
|
|
152
|
+
mo.observe(body, { childList: true, subtree: true });
|
|
153
|
+
});
|
|
114
154
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
} catch (e) { console.error('[ezoic] init fail', e); }
|
|
155
|
+
// Compatibilité jQuery/NodeBB Events
|
|
156
|
+
if (window.jQuery) {
|
|
157
|
+
window.jQuery(window).on('action:ajaxify.end action:infiniteScroll.loaded', () => {
|
|
158
|
+
setTimeout(schedule, 500);
|
|
159
|
+
});
|
|
160
|
+
}
|
|
122
161
|
}
|
|
123
162
|
|
|
124
163
|
if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', init);
|