nodebb-plugin-ezoic-infinite 0.5.4 → 0.5.5
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
CHANGED
package/public/client.js
CHANGED
|
@@ -24,17 +24,10 @@ function parsePool(raw) {
|
|
|
24
24
|
));
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
/**
|
|
28
|
-
* Harmony: the real post wrapper is usually [component="post"][data-pid]
|
|
29
|
-
* We must avoid counting nested nodes like component="post/parent" or other elements
|
|
30
|
-
* that can also carry data-pid in some setups.
|
|
31
|
-
*/
|
|
32
27
|
function getTopicPosts() {
|
|
33
28
|
const $primary = $('[component="post"][data-pid]');
|
|
34
29
|
if ($primary.length) return $primary.not('.ezoic-ad-post');
|
|
35
30
|
|
|
36
|
-
// Fallback: top-level nodes with data-pid that contain the post content,
|
|
37
|
-
// excluding nodes nested inside another data-pid container.
|
|
38
31
|
const $top = $('[data-pid]').filter(function () {
|
|
39
32
|
const $el = $(this);
|
|
40
33
|
const hasContent = $el.find('[component="post/content"]').length > 0;
|
|
@@ -50,8 +43,9 @@ function tagName($el) {
|
|
|
50
43
|
return ($el && $el.length ? (($el.prop('tagName') || '').toUpperCase()) : '');
|
|
51
44
|
}
|
|
52
45
|
|
|
46
|
+
// Remove *all* nodes with a given id (duplicates are possible if misconfigured)
|
|
53
47
|
function removePlaceholdersByPool(pool) {
|
|
54
|
-
pool.forEach(id => $('
|
|
48
|
+
pool.forEach(id => $('[id="ezoic-pub-ad-placeholder-' + id + '"]').remove());
|
|
55
49
|
}
|
|
56
50
|
|
|
57
51
|
function removeAdWrappers() {
|
|
@@ -60,13 +54,8 @@ function removeAdWrappers() {
|
|
|
60
54
|
}
|
|
61
55
|
|
|
62
56
|
function computeWindowSlots(totalItems, interval, poolSize) {
|
|
63
|
-
// totalItems posts -> number of ad slots at positions interval, 2*interval, ...
|
|
64
57
|
const slots = Math.floor(totalItems / interval);
|
|
65
58
|
if (slots <= 0) return [];
|
|
66
|
-
|
|
67
|
-
// IMPORTANT:
|
|
68
|
-
// We cannot display more than poolSize ads at once because Ezoic placeholder IDs
|
|
69
|
-
// must be unique on the page. If slots > poolSize, we only render the latest poolSize slots.
|
|
70
59
|
const start = Math.max(1, slots - poolSize + 1);
|
|
71
60
|
const out = [];
|
|
72
61
|
for (let s = start; s <= slots; s++) out.push(s);
|
|
@@ -81,16 +70,16 @@ function makeWrapperLike($target, classes, innerHtml) {
|
|
|
81
70
|
return '<div class="' + classes + '" data-ezoic-ad="1">' + innerHtml + '</div>';
|
|
82
71
|
}
|
|
83
72
|
|
|
84
|
-
function insertBetweenPosts($posts,
|
|
73
|
+
function insertBetweenPosts($posts, ids, interval) {
|
|
85
74
|
const total = $posts.length;
|
|
86
|
-
const slotsToRender = computeWindowSlots(total, interval,
|
|
75
|
+
const slotsToRender = computeWindowSlots(total, interval, ids.length);
|
|
87
76
|
if (!slotsToRender.length) return [];
|
|
88
77
|
|
|
89
78
|
const activeIds = [];
|
|
90
79
|
for (let i = 0; i < slotsToRender.length; i++) {
|
|
91
80
|
const slotNumber = slotsToRender[i];
|
|
92
|
-
const id =
|
|
93
|
-
const index = slotNumber * interval - 1;
|
|
81
|
+
const id = ids[i];
|
|
82
|
+
const index = slotNumber * interval - 1;
|
|
94
83
|
const $target = $posts.eq(index);
|
|
95
84
|
if (!$target.length) continue;
|
|
96
85
|
|
|
@@ -101,15 +90,15 @@ function insertBetweenPosts($posts, pool, interval) {
|
|
|
101
90
|
return activeIds;
|
|
102
91
|
}
|
|
103
92
|
|
|
104
|
-
function insertAdMessagesBetweenReplies($posts,
|
|
93
|
+
function insertAdMessagesBetweenReplies($posts, ids, interval) {
|
|
105
94
|
const total = $posts.length;
|
|
106
|
-
const slotsToRender = computeWindowSlots(total, interval,
|
|
95
|
+
const slotsToRender = computeWindowSlots(total, interval, ids.length);
|
|
107
96
|
if (!slotsToRender.length) return [];
|
|
108
97
|
|
|
109
98
|
const activeIds = [];
|
|
110
99
|
for (let i = 0; i < slotsToRender.length; i++) {
|
|
111
100
|
const slotNumber = slotsToRender[i];
|
|
112
|
-
const id =
|
|
101
|
+
const id = ids[i];
|
|
113
102
|
const index = slotNumber * interval - 1;
|
|
114
103
|
const $target = $posts.eq(index);
|
|
115
104
|
if (!$target.length) continue;
|
|
@@ -122,6 +111,18 @@ function insertAdMessagesBetweenReplies($posts, pool, interval) {
|
|
|
122
111
|
return activeIds;
|
|
123
112
|
}
|
|
124
113
|
|
|
114
|
+
function uniqueConcat(a, b) {
|
|
115
|
+
const seen = new Set();
|
|
116
|
+
const out = [];
|
|
117
|
+
[...a, ...b].forEach((x) => {
|
|
118
|
+
if (!seen.has(x)) {
|
|
119
|
+
seen.add(x);
|
|
120
|
+
out.push(x);
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
return out;
|
|
124
|
+
}
|
|
125
|
+
|
|
125
126
|
async function refreshAds() {
|
|
126
127
|
let cfg;
|
|
127
128
|
try { cfg = await fetchConfig(); } catch (e) { return; }
|
|
@@ -136,19 +137,28 @@ async function refreshAds() {
|
|
|
136
137
|
const $posts = getTopicPosts();
|
|
137
138
|
if (!$posts.length) return;
|
|
138
139
|
|
|
139
|
-
// Clean first
|
|
140
|
+
// Clean first (remove wrappers + any placeholders, even duplicates)
|
|
140
141
|
removeAdWrappers();
|
|
141
|
-
removePlaceholdersByPool(betweenPool);
|
|
142
|
-
|
|
142
|
+
removePlaceholdersByPool(uniqueConcat(betweenPool, messagePool));
|
|
143
|
+
|
|
144
|
+
// IMPORTANT:
|
|
145
|
+
// IDs must be UNIQUE on the page. If admin reuses the same IDs for both pools,
|
|
146
|
+
// we allocate unique IDs across "between posts" and "message ads" to avoid duplicates.
|
|
147
|
+
const combinedUnique = uniqueConcat(betweenPool, messagePool);
|
|
143
148
|
|
|
144
149
|
const activeIds = [];
|
|
150
|
+
let cursor = 0;
|
|
145
151
|
|
|
146
152
|
if (cfg.enableBetweenAds && betweenPool.length) {
|
|
147
|
-
|
|
153
|
+
const idsForBetween = combinedUnique.slice(cursor, cursor + betweenPool.length);
|
|
154
|
+
cursor += idsForBetween.length;
|
|
155
|
+
activeIds.push(...insertBetweenPosts($posts, idsForBetween, betweenInterval));
|
|
148
156
|
}
|
|
149
157
|
|
|
150
158
|
if (cfg.enableMessageAds && messagePool.length) {
|
|
151
|
-
|
|
159
|
+
const idsForMessage = combinedUnique.slice(cursor, cursor + messagePool.length);
|
|
160
|
+
cursor += idsForMessage.length;
|
|
161
|
+
activeIds.push(...insertAdMessagesBetweenReplies($posts, idsForMessage, messageInterval));
|
|
152
162
|
}
|
|
153
163
|
|
|
154
164
|
// Ezoic render
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
<div class="mb-3">
|
|
34
34
|
<label class="form-label" for="messagePlaceholderIds">Pool d’IDs Ezoic (message)</label>
|
|
35
35
|
<textarea id="messagePlaceholderIds" name="messagePlaceholderIds" class="form-control" rows="4">{messagePlaceholderIds}</textarea>
|
|
36
|
-
<p class="form-text">Pool séparé recommandé pour éviter la réutilisation d’IDs.</p>
|
|
36
|
+
<p class="form-text">Pool séparé recommandé pour éviter la réutilisation d’IDs. IMPORTANT : ne réutilise pas les mêmes IDs dans les deux pools.</p>
|
|
37
37
|
</div>
|
|
38
38
|
|
|
39
39
|
<div class="mb-3">
|