@linkitbe/sdk 1.0.2 → 1.0.10
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/dist/linkitbe_sdk.js +321 -28
- package/dist/linkitbe_sdk.min.js +1 -1
- package/package.json +1 -1
package/dist/linkitbe_sdk.js
CHANGED
|
@@ -20,7 +20,9 @@
|
|
|
20
20
|
enableFeedAutoProcess: false,
|
|
21
21
|
// Корень наблюдения для фида (обязателен при enableFeedAutoProcess=true).
|
|
22
22
|
feedObserverRootSelector: null,
|
|
23
|
-
|
|
23
|
+
// true = перед POST integration-viewable запросить GET /v1/events/integration-viewable-token (нужен секрет на markup-api).
|
|
24
|
+
fetchImpressionTokenForViewable: true,
|
|
25
|
+
sdkVersion: '1.0.10',
|
|
24
26
|
styles: {
|
|
25
27
|
link_color: '#e2187b',
|
|
26
28
|
link_weight: '700',
|
|
@@ -113,6 +115,32 @@
|
|
|
113
115
|
return null;
|
|
114
116
|
}
|
|
115
117
|
|
|
118
|
+
async function fetchIntegrationViewableImpressionToken(articleId, processingId) {
|
|
119
|
+
const partnerKey = config.partnerApiKey ? String(config.partnerApiKey).trim() : '';
|
|
120
|
+
if (!partnerKey || !processingId) return null;
|
|
121
|
+
try {
|
|
122
|
+
const base = String(config.apiBaseUrl || 'https://api.linkitbe.com').replace(/\/$/, '');
|
|
123
|
+
const u = new URL(base + '/v1/events/integration-viewable-token');
|
|
124
|
+
u.searchParams.set('article_id', articleId);
|
|
125
|
+
u.searchParams.set('domain', String(config.domain || ''));
|
|
126
|
+
u.searchParams.set('processing_id', String(processingId));
|
|
127
|
+
const res = await fetch(u.toString(), {
|
|
128
|
+
method: 'GET',
|
|
129
|
+
headers: {
|
|
130
|
+
'Accept': 'application/json',
|
|
131
|
+
'X-Partner-Api-Key': partnerKey,
|
|
132
|
+
},
|
|
133
|
+
credentials: 'omit',
|
|
134
|
+
});
|
|
135
|
+
if (!res.ok) return null;
|
|
136
|
+
const j = await res.json();
|
|
137
|
+
return j && j.impression_token ? String(j.impression_token) : null;
|
|
138
|
+
} catch (e) {
|
|
139
|
+
console.warn('[LinkItBe] impression token fetch failed', e);
|
|
140
|
+
return null;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
116
144
|
async function emitSdkEvent(eventType, path, articleId, integration, extra) {
|
|
117
145
|
const processingId = extractProcessingIdFromIntegrations([integration]);
|
|
118
146
|
if (!processingId) return;
|
|
@@ -136,6 +164,11 @@
|
|
|
136
164
|
referrer: document.referrer || null,
|
|
137
165
|
}, extra || {});
|
|
138
166
|
|
|
167
|
+
if (eventType === 'integration_viewable' && config.fetchImpressionTokenForViewable) {
|
|
168
|
+
const tok = await fetchIntegrationViewableImpressionToken(articleId, processingId);
|
|
169
|
+
if (tok) payload.impression_token = tok;
|
|
170
|
+
}
|
|
171
|
+
|
|
139
172
|
try {
|
|
140
173
|
const base = String(config.apiBaseUrl || 'https://api.linkitbe.com').replace(/\/$/, '');
|
|
141
174
|
await fetch(`${base}${path}`, {
|
|
@@ -163,22 +196,52 @@
|
|
|
163
196
|
|
|
164
197
|
function attachIntegrationViewableObserver(articleId, contentBlock) {
|
|
165
198
|
if (!articleId) return;
|
|
199
|
+
const clearTimer = (linkEl) => {
|
|
200
|
+
const t = linkEl._lbViewDwellTimer;
|
|
201
|
+
if (t) {
|
|
202
|
+
clearTimeout(t);
|
|
203
|
+
linkEl._lbViewDwellTimer = null;
|
|
204
|
+
}
|
|
205
|
+
};
|
|
166
206
|
const io = new IntersectionObserver((entries) => {
|
|
167
207
|
for (let i = 0; i < entries.length; i++) {
|
|
168
208
|
const en = entries[i];
|
|
169
|
-
if (!en.isIntersecting || en.intersectionRatio < 0.5) continue;
|
|
170
209
|
const linkEl = en.target;
|
|
171
210
|
if (linkEl.dataset.lbViewableSent === '1') continue;
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
io.unobserve(linkEl);
|
|
211
|
+
if (!en.isIntersecting || en.intersectionRatio < 0.5) {
|
|
212
|
+
clearTimer(linkEl);
|
|
213
|
+
linkEl._lbViewVisibleSince = null;
|
|
214
|
+
linkEl._lbViewLastIr = null;
|
|
177
215
|
continue;
|
|
178
216
|
}
|
|
179
|
-
linkEl.
|
|
180
|
-
|
|
181
|
-
|
|
217
|
+
linkEl._lbViewLastIr = String(Math.min(1, Math.max(0, en.intersectionRatio)));
|
|
218
|
+
if (!linkEl._lbViewVisibleSince) {
|
|
219
|
+
linkEl._lbViewVisibleSince = Date.now();
|
|
220
|
+
}
|
|
221
|
+
clearTimer(linkEl);
|
|
222
|
+
linkEl._lbViewDwellTimer = setTimeout(() => {
|
|
223
|
+
linkEl._lbViewDwellTimer = null;
|
|
224
|
+
if (linkEl.dataset.lbViewableSent === '1') return;
|
|
225
|
+
if (document.visibilityState !== 'visible') return;
|
|
226
|
+
let integration;
|
|
227
|
+
try {
|
|
228
|
+
integration = JSON.parse(decodeURIComponent(linkEl.dataset.lbIntegration || ''));
|
|
229
|
+
} catch (e) {
|
|
230
|
+
io.unobserve(linkEl);
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
linkEl.dataset.lbViewableSent = '1';
|
|
234
|
+
const start = linkEl._lbViewVisibleSince || Date.now();
|
|
235
|
+
const dwell = Math.max(0, Date.now() - start);
|
|
236
|
+
const ir = parseFloat(linkEl._lbViewLastIr || '0.5');
|
|
237
|
+
emitSdkEvent('integration_viewable', '/v1/events/integration-viewable', articleId, integration, {
|
|
238
|
+
tab_visible: document.visibilityState === 'visible',
|
|
239
|
+
dwell_ms: Math.max(1000, dwell),
|
|
240
|
+
intersection_ratio: ir,
|
|
241
|
+
viewability_rule_version: 'elitesdk-1',
|
|
242
|
+
});
|
|
243
|
+
io.unobserve(linkEl);
|
|
244
|
+
}, 1000);
|
|
182
245
|
}
|
|
183
246
|
}, { threshold: [0.5] });
|
|
184
247
|
contentBlock.querySelectorAll('.__lb_link').forEach((linkEl) => io.observe(linkEl));
|
|
@@ -214,6 +277,37 @@
|
|
|
214
277
|
return preview;
|
|
215
278
|
}
|
|
216
279
|
|
|
280
|
+
function positionMarkupPreview(preview, clientX, clientY) {
|
|
281
|
+
const margin = 12;
|
|
282
|
+
const offsetX = 16;
|
|
283
|
+
const cursorAnchor = 60;
|
|
284
|
+
|
|
285
|
+
const previewHeight = preview.offsetHeight || 0;
|
|
286
|
+
const previewWidth = preview.offsetWidth || 0;
|
|
287
|
+
|
|
288
|
+
let left = clientX + offsetX;
|
|
289
|
+
let top = clientY - previewHeight + cursorAnchor;
|
|
290
|
+
|
|
291
|
+
const maxLeft = window.innerWidth - previewWidth - margin;
|
|
292
|
+
left = Math.min(Math.max(left, margin), Math.max(margin, maxLeft));
|
|
293
|
+
|
|
294
|
+
const viewportBottom = window.innerHeight - margin;
|
|
295
|
+
if (top + previewHeight > viewportBottom) {
|
|
296
|
+
top = clientY - previewHeight - margin;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
preview.style.left = left + 'px';
|
|
300
|
+
preview.style.top = Math.max(margin, top) + 'px';
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
function buildPreviewLabelingEl(integration) {
|
|
304
|
+
const erid = integration && integration.erid != null ? String(integration.erid).trim() : '';
|
|
305
|
+
const label = document.createElement('div');
|
|
306
|
+
label.style.cssText = 'font-size:10px;line-height:1.35;color:#aaa;margin-bottom:6px;font-weight:400;';
|
|
307
|
+
label.textContent = erid ? `#реклама · erid: ${erid}` : '#реклама';
|
|
308
|
+
return label;
|
|
309
|
+
}
|
|
310
|
+
|
|
217
311
|
function showPreview(preview, integration, x, y, styles_config) {
|
|
218
312
|
if (!integration.preview || !integration.preview.img) {
|
|
219
313
|
preview.style.display = 'none';
|
|
@@ -222,6 +316,8 @@
|
|
|
222
316
|
|
|
223
317
|
preview.replaceChildren();
|
|
224
318
|
|
|
319
|
+
preview.appendChild(buildPreviewLabelingEl(integration));
|
|
320
|
+
|
|
225
321
|
const image = document.createElement('img');
|
|
226
322
|
image.src = String(integration.preview.img);
|
|
227
323
|
image.style.cssText = 'width:100%;border-radius:8px;display:block;';
|
|
@@ -242,9 +338,28 @@
|
|
|
242
338
|
cta.textContent = integration.preview.cta ? String(integration.preview.cta) : '';
|
|
243
339
|
preview.appendChild(cta);
|
|
244
340
|
|
|
245
|
-
preview.style.left = (x + 16) + 'px';
|
|
246
|
-
preview.style.top = (y - 60) + 'px';
|
|
247
341
|
preview.style.display = 'block';
|
|
342
|
+
positionMarkupPreview(preview, x, y);
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
function hidePreview(preview) {
|
|
346
|
+
if (preview) {
|
|
347
|
+
preview.style.display = 'none';
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
function attachPreviewDismissHandlers(preview) {
|
|
352
|
+
if (!preview || preview.dataset.lbDismissBound === '1') {
|
|
353
|
+
return;
|
|
354
|
+
}
|
|
355
|
+
preview.dataset.lbDismissBound = '1';
|
|
356
|
+
|
|
357
|
+
const dismiss = () => hidePreview(preview);
|
|
358
|
+
|
|
359
|
+
document.addEventListener('visibilitychange', dismiss);
|
|
360
|
+
window.addEventListener('blur', dismiss);
|
|
361
|
+
window.addEventListener('pagehide', dismiss);
|
|
362
|
+
window.addEventListener('pageshow', dismiss);
|
|
248
363
|
}
|
|
249
364
|
|
|
250
365
|
|
|
@@ -404,6 +519,113 @@
|
|
|
404
519
|
}
|
|
405
520
|
}
|
|
406
521
|
|
|
522
|
+
function normalizePlainMarkerText(markerText) {
|
|
523
|
+
const normalized = String(markerText || '#реклама').trim();
|
|
524
|
+
if (!normalized) {
|
|
525
|
+
return '#реклама';
|
|
526
|
+
}
|
|
527
|
+
if (normalized.endsWith(':')) {
|
|
528
|
+
return normalized;
|
|
529
|
+
}
|
|
530
|
+
return normalized.replace(/:+$/, '') + ':';
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
function appendEridToAdvertiserInfoUrl(rawUrl, erid) {
|
|
534
|
+
const sanitizedErid = erid != null ? String(erid).trim() : '';
|
|
535
|
+
if (!sanitizedErid || !rawUrl) {
|
|
536
|
+
return rawUrl;
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
try {
|
|
540
|
+
const url = new URL(String(rawUrl), window.location.origin);
|
|
541
|
+
url.searchParams.set('erid', sanitizedErid);
|
|
542
|
+
return url.toString();
|
|
543
|
+
} catch (e) {
|
|
544
|
+
return rawUrl;
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
function resolveAdvertiserInfoUrl(integration, pageConfig) {
|
|
549
|
+
const erid = integration && integration.erid != null
|
|
550
|
+
? String(integration.erid).trim()
|
|
551
|
+
: '';
|
|
552
|
+
|
|
553
|
+
const fromIntegration = sanitizeIntegrationLink(integration && integration.advertiser_info_url);
|
|
554
|
+
if (fromIntegration) {
|
|
555
|
+
return appendEridToAdvertiserInfoUrl(fromIntegration, erid);
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
const base = pageConfig && pageConfig.advertiser_info_base_url;
|
|
559
|
+
const advertiser = integration && integration.advertiser != null
|
|
560
|
+
? String(integration.advertiser).trim()
|
|
561
|
+
: '';
|
|
562
|
+
if (!base || !advertiser) {
|
|
563
|
+
return null;
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
try {
|
|
567
|
+
const url = new URL(String(base), window.location.origin);
|
|
568
|
+
url.searchParams.append('items[]', advertiser);
|
|
569
|
+
if (erid) {
|
|
570
|
+
url.searchParams.set('erid', erid);
|
|
571
|
+
}
|
|
572
|
+
return url.toString();
|
|
573
|
+
} catch (e) {
|
|
574
|
+
return null;
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
function createAdvertiserInfoLinkElement(integration, linkText, linkStyle, pageConfig) {
|
|
579
|
+
const sanitizedLink = resolveAdvertiserInfoUrl(integration, pageConfig);
|
|
580
|
+
if (!sanitizedLink) {
|
|
581
|
+
console.warn('[LinkItBe] advertiser info url is missing for marker', integration && integration.advertiser);
|
|
582
|
+
return null;
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
const a = document.createElement('a');
|
|
586
|
+
a.href = sanitizedLink;
|
|
587
|
+
a.target = '_blank';
|
|
588
|
+
a.rel = 'noopener noreferrer sponsored nofollow';
|
|
589
|
+
a.className = '__lb_link __lb_advertiser_info_link';
|
|
590
|
+
a.style.cssText = linkStyle.replace(/\s+/g, ' ').trim();
|
|
591
|
+
a.textContent = linkText;
|
|
592
|
+
return a;
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
function buildLabelingMarkerNode(labelingTemplate, integration, pageConfig) {
|
|
596
|
+
const template = labelingTemplate && typeof labelingTemplate === 'object' ? labelingTemplate : {};
|
|
597
|
+
const markerType = template.marker_type || 'plain_text';
|
|
598
|
+
const position = template.position || 'before_phrase';
|
|
599
|
+
const markerText = template.marker_text != null ? String(template.marker_text).trim() : '';
|
|
600
|
+
const labelStyle = 'font-size:11px;color:#999;display:block;margin-bottom:4px;';
|
|
601
|
+
const markerLinkStyle = 'font-size:11px;color:#999;font-weight:400;text-decoration:underline;cursor:pointer;';
|
|
602
|
+
|
|
603
|
+
if (markerType === 'marker_link') {
|
|
604
|
+
const text = markerText || '#реклама';
|
|
605
|
+
const linkEl = createAdvertiserInfoLinkElement(integration, text, markerLinkStyle, pageConfig);
|
|
606
|
+
if (linkEl) {
|
|
607
|
+
const wrapper = document.createElement('span');
|
|
608
|
+
wrapper.style.cssText = labelStyle.replace('margin-bottom:4px;', '');
|
|
609
|
+
wrapper.appendChild(linkEl);
|
|
610
|
+
return { node: wrapper, position: position };
|
|
611
|
+
}
|
|
612
|
+
console.warn('[LinkItBe] marker_link fallback to plain text:', text);
|
|
613
|
+
const span = document.createElement('span');
|
|
614
|
+
span.style.cssText = labelStyle;
|
|
615
|
+
span.textContent = text;
|
|
616
|
+
return { node: span, position: position };
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
if (markerType !== 'plain_text') {
|
|
620
|
+
console.warn('[LinkItBe] unsupported marker_type, fallback to plain_text:', markerType);
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
const span = document.createElement('span');
|
|
624
|
+
span.style.cssText = labelStyle;
|
|
625
|
+
span.textContent = normalizePlainMarkerText(markerText || '#реклама');
|
|
626
|
+
return { node: span, position: position };
|
|
627
|
+
}
|
|
628
|
+
|
|
407
629
|
function createLinkElement(integration, linkText, linkStyle) {
|
|
408
630
|
const sanitizedLink = sanitizeIntegrationLink(integration.link);
|
|
409
631
|
if (!sanitizedLink) {
|
|
@@ -465,24 +687,73 @@
|
|
|
465
687
|
}
|
|
466
688
|
|
|
467
689
|
const MINI_OFFER_PLACEHOLDER = '{anchor_text}';
|
|
690
|
+
const MOBILE_LAYOUT_MAX_WIDTH = 768;
|
|
691
|
+
const MOBILE_MIN_SIDE_INSET_PX = 8;
|
|
692
|
+
const MOBILE_FALLBACK_SIDE_PADDING_PX = 16;
|
|
693
|
+
|
|
694
|
+
function isMobileLayout() {
|
|
695
|
+
return window.matchMedia(`(max-width: ${MOBILE_LAYOUT_MAX_WIDTH}px)`).matches;
|
|
696
|
+
}
|
|
697
|
+
|
|
698
|
+
function getViewportSideInset(el) {
|
|
699
|
+
const rect = el.getBoundingClientRect();
|
|
700
|
+
return {
|
|
701
|
+
left: rect.left,
|
|
702
|
+
right: window.innerWidth - rect.right,
|
|
703
|
+
};
|
|
704
|
+
}
|
|
468
705
|
|
|
469
|
-
function
|
|
706
|
+
function findReferencePlainBlock(contentBlock, excludeEl) {
|
|
470
707
|
const sel = config.plainBlockSelector || 'p, blockquote, h1, h2, h3, h4, h5, h6';
|
|
471
708
|
const blocks = contentBlock.querySelectorAll(sel);
|
|
472
|
-
|
|
473
|
-
|
|
709
|
+
for (let i = 0; i < blocks.length; i++) {
|
|
710
|
+
const el = blocks[i];
|
|
711
|
+
if (el === excludeEl || el.classList.contains('__lb_mini_offer')) continue;
|
|
712
|
+
if (!(el.textContent || '').trim()) continue;
|
|
713
|
+
return el;
|
|
714
|
+
}
|
|
715
|
+
return null;
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
function applyMobileSideInsetIfNeeded(outro, contentBlock) {
|
|
719
|
+
if (!isMobileLayout()) return;
|
|
720
|
+
|
|
721
|
+
const currentInset = getViewportSideInset(outro);
|
|
722
|
+
if (currentInset.left >= MOBILE_MIN_SIDE_INSET_PX && currentInset.right >= MOBILE_MIN_SIDE_INSET_PX) {
|
|
723
|
+
return;
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
const ref = findReferencePlainBlock(contentBlock, outro);
|
|
727
|
+
const refInset = ref ? getViewportSideInset(ref) : null;
|
|
728
|
+
const targetLeft = refInset && refInset.left >= MOBILE_MIN_SIDE_INSET_PX
|
|
729
|
+
? refInset.left
|
|
730
|
+
: MOBILE_FALLBACK_SIDE_PADDING_PX;
|
|
731
|
+
const targetRight = refInset && refInset.right >= MOBILE_MIN_SIDE_INSET_PX
|
|
732
|
+
? refInset.right
|
|
733
|
+
: MOBILE_FALLBACK_SIDE_PADDING_PX;
|
|
734
|
+
|
|
735
|
+
const padLeft = currentInset.left < MOBILE_MIN_SIDE_INSET_PX
|
|
736
|
+
? Math.max(0, Math.round(targetLeft - currentInset.left))
|
|
737
|
+
: 0;
|
|
738
|
+
const padRight = currentInset.right < MOBILE_MIN_SIDE_INSET_PX
|
|
739
|
+
? Math.max(0, Math.round(targetRight - currentInset.right))
|
|
740
|
+
: 0;
|
|
741
|
+
|
|
742
|
+
if (padLeft > 0) outro.style.paddingLeft = `${padLeft}px`;
|
|
743
|
+
if (padRight > 0) outro.style.paddingRight = `${padRight}px`;
|
|
744
|
+
}
|
|
745
|
+
|
|
746
|
+
function applyMiniOffer(contentBlock, integration, linkStyle, labelingTemplate, pageConfig) {
|
|
747
|
+
if (!contentBlock) {
|
|
748
|
+
console.warn('[LinkItBe] mini-offer: no content block');
|
|
474
749
|
return false;
|
|
475
750
|
}
|
|
476
751
|
|
|
477
|
-
const lastBlock = blocks[blocks.length - 1];
|
|
478
752
|
const outro = document.createElement('p');
|
|
479
753
|
outro.className = '__lb_mini_offer';
|
|
480
754
|
outro.style.cssText = 'margin-top:16px;font-size:15px;font-family:Manrope, sans-serif;color:#343b4c;';
|
|
481
755
|
|
|
482
|
-
const
|
|
483
|
-
adLabel.style.cssText = 'font-size:11px;color:#999;display:block;margin-bottom:4px;';
|
|
484
|
-
adLabel.textContent = '#реклама';
|
|
485
|
-
outro.appendChild(adLabel);
|
|
756
|
+
const marker = buildLabelingMarkerNode(labelingTemplate, integration, pageConfig);
|
|
486
757
|
|
|
487
758
|
const body = document.createElement('span');
|
|
488
759
|
const template = integration.text != null ? String(integration.text) : '';
|
|
@@ -500,12 +771,21 @@
|
|
|
500
771
|
body.appendChild(anchor);
|
|
501
772
|
if (after) body.appendChild(document.createTextNode(after));
|
|
502
773
|
|
|
774
|
+
if (marker && marker.position === 'before_phrase') {
|
|
775
|
+
outro.appendChild(marker.node);
|
|
776
|
+
}
|
|
503
777
|
outro.appendChild(body);
|
|
504
|
-
|
|
778
|
+
if (marker && marker.position === 'after_phrase') {
|
|
779
|
+
outro.appendChild(document.createElement('br'));
|
|
780
|
+
outro.appendChild(marker.node);
|
|
781
|
+
}
|
|
782
|
+
|
|
783
|
+
contentBlock.appendChild(outro);
|
|
784
|
+
applyMobileSideInsetIfNeeded(outro, contentBlock);
|
|
505
785
|
return true;
|
|
506
786
|
}
|
|
507
787
|
|
|
508
|
-
function applyIntegrations(articleId, integrations, contentBlock, style_config) {
|
|
788
|
+
function applyIntegrations(articleId, integrations, contentBlock, style_config, labeling_template, page_config) {
|
|
509
789
|
if (!contentBlock) {
|
|
510
790
|
console.warn('[LinkItBe] Content block not provided');
|
|
511
791
|
const active = filterIntegrationsByAllowedFormats(integrations);
|
|
@@ -545,7 +825,7 @@
|
|
|
545
825
|
}
|
|
546
826
|
|
|
547
827
|
active.filter(i => i.type === 'mini-offer').forEach(integ => {
|
|
548
|
-
if (applyMiniOffer(contentBlock, integ, linkStyle)) {
|
|
828
|
+
if (applyMiniOffer(contentBlock, integ, linkStyle, labeling_template, page_config)) {
|
|
549
829
|
appliedCount += 1;
|
|
550
830
|
} else {
|
|
551
831
|
console.warn('[LinkItBe] mini-offer failed');
|
|
@@ -553,6 +833,8 @@
|
|
|
553
833
|
});
|
|
554
834
|
|
|
555
835
|
if (preview) {
|
|
836
|
+
attachPreviewDismissHandlers(preview);
|
|
837
|
+
|
|
556
838
|
contentBlock.querySelectorAll('.__lb_link').forEach((linkEl) => {
|
|
557
839
|
let integration;
|
|
558
840
|
try {
|
|
@@ -564,17 +846,26 @@
|
|
|
564
846
|
if (!integration.preview || !integration.preview.img) {
|
|
565
847
|
return;
|
|
566
848
|
}
|
|
849
|
+
const dismissPreview = () => hidePreview(preview);
|
|
850
|
+
|
|
567
851
|
linkEl.addEventListener('mouseenter', (e) => {
|
|
852
|
+
if (document.visibilityState !== 'visible') {
|
|
853
|
+
return;
|
|
854
|
+
}
|
|
568
855
|
showPreview(preview, integration, e.clientX, e.clientY, style_config);
|
|
569
856
|
if (linkEl.dataset.lbPreviewSent === '1' || !articleId) return;
|
|
570
857
|
linkEl.dataset.lbPreviewSent = '1';
|
|
571
858
|
emitSdkEvent('preview_viewed', '/v1/events/preview-viewed', articleId, integration);
|
|
572
859
|
});
|
|
573
860
|
linkEl.addEventListener('mousemove', (e) => {
|
|
574
|
-
preview.style.
|
|
575
|
-
|
|
861
|
+
if (preview.style.display === 'none') {
|
|
862
|
+
return;
|
|
863
|
+
}
|
|
864
|
+
positionMarkupPreview(preview, e.clientX, e.clientY);
|
|
576
865
|
});
|
|
577
|
-
linkEl.addEventListener('mouseleave',
|
|
866
|
+
linkEl.addEventListener('mouseleave', dismissPreview);
|
|
867
|
+
linkEl.addEventListener('click', dismissPreview);
|
|
868
|
+
linkEl.addEventListener('touchstart', dismissPreview, { passive: true });
|
|
578
869
|
});
|
|
579
870
|
}
|
|
580
871
|
|
|
@@ -594,8 +885,10 @@
|
|
|
594
885
|
|
|
595
886
|
const integrations = Array.isArray(data.integrations) ? data.integrations : [];
|
|
596
887
|
|
|
597
|
-
const
|
|
598
|
-
const
|
|
888
|
+
const page_config = data.config && typeof data.config === 'object' ? data.config : {};
|
|
889
|
+
const style_config = page_config.style || {};
|
|
890
|
+
const labeling_template = page_config.labeling_template || null;
|
|
891
|
+
const result = applyIntegrations(articleId, integrations, contentBlock, style_config, labeling_template, page_config);
|
|
599
892
|
|
|
600
893
|
await emitViewRendered(articleId, result.integrations, result.appliedCount);
|
|
601
894
|
}
|
package/dist/linkitbe_sdk.min.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
!function(){const e=Object.assign({domain:window.location.hostname,bootOnLoad:!0,contentSelector:null,showPreview:!0,plainBlockJoiner:"\n",plainBlockSelector:"p, blockquote, h1, h2, h3, h4, h5, h6",allowedFormats:["keyword","mini-offer"],apiBaseUrl:"https://api.linkitbe.com",partnerApiKey:null,articleIdResolver:null,enableFeedAutoProcess:!1,feedObserverRootSelector:null,sdkVersion:"1.0.2",styles:{link_color:"#e2187b",link_weight:"700",link_decoration:"underline"}},window.LinkItBeConfig||{});function n(n){if("function"==typeof e.articleIdResolver)try{const t=e.articleIdResolver(n),o=null!=t?String(t).trim():"";if(o)return o}catch(e){console.warn("[LinkItBe] articleIdResolver failed",e)}return null}function t(){const e="__lb_session_id";try{const n=window.localStorage.getItem(e);if(n&&n.trim())return n.trim();const t=window.crypto&&window.crypto.randomUUID?window.crypto.randomUUID():`${Date.now()}-${Math.random().toString(16).slice(2)}`;return window.localStorage.setItem(e,t),t}catch(e){return`${Date.now()}-${Math.random().toString(16).slice(2)}`}}function o(e){if(!Array.isArray(e))return null;for(const n of e){const e=n&&n.link?String(n.link):"";if(e)try{const n=new URL(e,window.location.origin).searchParams.get("processing_id"),t=Number(n);if(Number.isFinite(t)&&t>0)return t}catch(e){}}return null}async function r(n,r,i,l,s){const c=o([l]);if(!c)return;const a=e.partnerApiKey?String(e.partnerApiKey).trim():"";if(!a)return;const d=Object.assign({event_id:window.crypto&&window.crypto.randomUUID?window.crypto.randomUUID():`${Date.now()}-${Math.random().toString(16).slice(2)}`,event_type:n,event_time:(new Date).toISOString(),article_id:i,domain:e.domain,processing_id:c,placement_link:window.location.href,integration_type:l&&null!=l.type?l.type:null,sdk_version:String(e.sdkVersion||""),session_id:t(),referrer:document.referrer||null},s||{});try{const n=String(e.apiBaseUrl||"https://api.linkitbe.com").replace(/\/$/,"");await fetch(`${n}${r}`,{method:"POST",headers:{Accept:"application/json","Content-Type":"application/json","X-Partner-Api-Key":a},body:JSON.stringify(d),keepalive:!0,credentials:"omit"})}catch(e){console.warn("[LinkItBe] failed to send "+n,e)}}async function i(e,n,t){if(t<=0)return;const i=function(e){if(!Array.isArray(e))return null;for(let n=0;n<e.length;n++){const t=e[n];if(t&&o([t]))return t}return null}(n);i&&await r("view_rendered","/v1/events/view-rendered",e,i,{integrations_count:t})}function l(n){const t=e.allowedFormats;return null!=t&&Array.isArray(t)?n.filter(e=>t.includes(e.type)):n}function s(e){const n=[],t=document.createTreeWalker(e,NodeFilter.SHOW_TEXT,{acceptNode:e=>function(e){const n=e.nodeType===Node.TEXT_NODE?e.parentElement:e;return!!(n&&n.closest&&n.closest("a.__lb_link"))}(e)?NodeFilter.FILTER_REJECT:NodeFilter.FILTER_ACCEPT});let o;for(;o=t.nextNode();)n.push(o);return n}function c(e,n){if(!n)return[];const t=new RegExp(String(n).replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),"gi");const o=[];let r;for(;null!==(r=t.exec(e));)o.push({start:r.index,end:r.index+r[0].length}),0===r[0].length&&t.lastIndex===r.index&&t.lastIndex++;return o}function a(e,n,t){const o=function(e){if(null==e)return null;try{const n=new URL(String(e),window.location.origin);return"http:"!==n.protocol&&"https:"!==n.protocol?null:n.toString()}catch(e){return null}}(e.link);if(!o)return null;const r=document.createElement("a");return r.href=o,r.target="_blank",r.rel="noopener noreferrer sponsored nofollow",r.className="__lb_link",r.setAttribute("data-lb-integration",encodeURIComponent(JSON.stringify(e))),r.style.cssText=t.replace(/\s+/g," ").trim(),r.textContent=n,r}function d(n,t){const{plain:o,spans:r}=function(n){const t=null!=e.plainBlockJoiner?e.plainBlockJoiner:"\n",o=e.plainBlockSelector||"p, blockquote, h1, h2, h3, h4, h5, h6",r=n.querySelectorAll(o),i=[];let l="";return r.forEach((e,n)=>{n>0&&(l+=t);const o=s(e);for(const e of o){const n=e.textContent;if(!n.length)continue;const t=l.length;l+=n,i.push({g0:t,g1:l.length,node:e})}}),{plain:l,spans:i}}(n),i=function(e,n){if(!e.length)return null;if(1===e.length)return e[0];const t=n||{},o=t.match_index;if(null!=o&&Number.isFinite(Number(o))){const n=Number(o);if(n>=0&&n<e.length)return e[n];console.warn("[LinkItBe] match_index out of range:",o,"n=",e.length)}const r=t.offset_start,i=t.offset_end;if(null!=r&&Number.isFinite(Number(r))){const n=Number(r),t=null!=i&&Number.isFinite(Number(i))?Number(i):null;let o=e[0],l=1/0;for(const r of e){const e=1e9*Math.abs(r.start-n)+(null!=t?Math.abs(r.end-t):0);e<l&&(l=e,o=r)}return o}return console.warn("[LinkItBe] ambiguous matches, skipping (no match_index / offset_start):",e.length),null}(c(o,t.keyword),t.position);if(!i)return null;const l=o.slice(i.start,i.end);return{plain:o,spans:r,span:i,linkText:l}}function u(e,n,t){const o=d(e,n);if(!o)return console.warn("[LinkItBe] no span for keyword:",n.keyword),!1;const{plain:r,spans:i,span:l,linkText:s}=o,c=function(e,n,t){if(e<0||e>=t||!n.length)return null;const o=n.find(n=>e>=n.g0&&e<n.g1);return o?{node:o.node,offset:e-o.g0}:null}(l.start,i,r.length),u=function(e,n,t){if(!n.length)return null;if(e<=0)return{node:n[0].node,offset:0};if(e>=t){const e=n[n.length-1];return{node:e.node,offset:e.node.textContent.length}}for(let t=0;t<n.length;t++){const o=n[t];if(e>o.g0&&e<=o.g1)return{node:o.node,offset:e-o.g0};if(e===o.g0)return{node:o.node,offset:0}}for(let t=0;t<n.length;t++)if(e<n[t].g0)return{node:n[t].node,offset:0};return null}(l.end,i,r.length);if(!c||!u)return console.warn("[LinkItBe] could not map span to DOM"),!1;const p=r.slice(l.start,l.end);if(p.toLowerCase()!==s.toLowerCase())return console.warn("[LinkItBe] plain slice mismatch"),!1;const f=document.createRange();f.setStart(c.node,c.offset),f.setEnd(u.node,u.offset);const g=a(n,p,t);return g?(function(e,n){try{e.surroundContents(n)}catch(t){const o=e.extractContents();for(;o.firstChild;)n.appendChild(o.firstChild);e.insertNode(n)}}(f,g),!0):(console.warn("[LinkItBe] invalid integration link:",n.link),!1)}const p="{anchor_text}";function f(n,t,o,i){if(!o){console.warn("[LinkItBe] Content block not provided");return{appliedCount:0,integrations:l(t)}}const s=e.showPreview?function(){const e=document.createElement("div");return e.id="__lb_preview",e.style.cssText="\n position: fixed;\n display: none;\n background: white;\n border-radius: 12px;\n box-shadow: 0 4px 20px rgba(0,0,0,0.15);\n padding: 12px;\n z-index: 99999;\n width: 180px;\n font-family: Manrope, sans-serif;\n pointer-events: none;\n ",document.body.appendChild(e),e}():null,c=`\n color:${i.link_color};\n font-weight:${i.link_weight};\n text-decoration:${i.link_decoration};\n cursor:pointer;\n `,f=l(t);let g=0,h=f.filter(e=>"keyword"===e.type);for(;h.length;){const e=[];for(const n of h){const t=d(o,n);t&&e.push({integ:n,spanStart:t.span.start})}if(!e.length){h.forEach(e=>console.warn("[LinkItBe] unresolved keyword:",e.keyword));break}e.sort((e,n)=>n.spanStart-e.spanStart);const{integ:n}=e[0];u(o,n,c)&&(g+=1),h=h.filter(e=>e!==n)}return f.filter(e=>"mini-offer"===e.type).forEach(n=>{!function(n,t,o){const r=e.plainBlockSelector||"p, blockquote, h1, h2, h3, h4, h5, h6",i=n.querySelectorAll(r);if(!i.length)return console.warn("[LinkItBe] mini-offer: no content blocks"),!1;const l=i[i.length-1],s=document.createElement("p");s.className="__lb_mini_offer",s.style.cssText="margin-top:16px;font-size:15px;font-family:Manrope, sans-serif;color:#343b4c;";const c=document.createElement("span");c.style.cssText="font-size:11px;color:#999;display:block;margin-bottom:4px;",c.textContent="#реклама",s.appendChild(c);const d=document.createElement("span"),u=null!=t.text?String(t.text):"",f=null!=t.anchor_text?String(t.anchor_text):"",g=u.indexOf(p),h=g>=0?u.slice(0,g):u,w=g>=0?u.slice(g+13):"";h&&d.appendChild(document.createTextNode(h));const m=a(t,f,o);return m?(d.appendChild(m),w&&d.appendChild(document.createTextNode(w)),s.appendChild(d),l.after(s),!0):(console.warn("[LinkItBe] mini-offer invalid integration link:",t.link),!1)}(o,n,c)?console.warn("[LinkItBe] mini-offer failed"):g+=1}),s&&o.querySelectorAll(".__lb_link").forEach(e=>{let t;try{t=JSON.parse(decodeURIComponent(e.dataset.lbIntegration||""))}catch(e){return void console.warn("[LinkItBe] invalid integration payload for preview",e)}t.preview&&t.preview.img&&(e.addEventListener("mouseenter",o=>{!function(e,n,t,o,r){if(!n.preview||!n.preview.img)return void(e.style.display="none");e.replaceChildren();const i=document.createElement("img");i.src=String(n.preview.img),i.style.cssText="width:100%;border-radius:8px;display:block;",e.appendChild(i);const l=document.createElement("div");l.style.cssText="margin-top:8px;font-size:13px;color:#343b4c;font-weight:600;",l.textContent=n.preview.title?String(n.preview.title):"",e.appendChild(l);const s=document.createElement("div");s.style.cssText="font-size:12px;color:#777;margin-top:2px;",s.textContent=n.preview.price?String(n.preview.price):"",e.appendChild(s);const c=document.createElement("div");c.style.cssText=`font-size:12px;color:${r.link_color};margin-top:2px;`,c.textContent=n.preview.cta?String(n.preview.cta):"",e.appendChild(c),e.style.left=t+16+"px",e.style.top=o-60+"px",e.style.display="block"}(s,t,o.clientX,o.clientY,i),"1"!==e.dataset.lbPreviewSent&&n&&(e.dataset.lbPreviewSent="1",r("preview_viewed","/v1/events/preview-viewed",n,t))}),e.addEventListener("mousemove",e=>{s.style.left=e.clientX+16+"px",s.style.top=e.clientY-60+"px"}),e.addEventListener("mouseleave",()=>{s.style.display="none"}))}),function(e,n){if(!e)return;const t=new IntersectionObserver(n=>{for(let o=0;o<n.length;o++){const i=n[o];if(!i.isIntersecting||i.intersectionRatio<.5)continue;const l=i.target;if("1"===l.dataset.lbViewableSent)continue;let s;try{s=JSON.parse(decodeURIComponent(l.dataset.lbIntegration||""))}catch(e){t.unobserve(l);continue}l.dataset.lbViewableSent="1",r("integration_viewable","/v1/events/integration-viewable",e,s),t.unobserve(l)}},{threshold:[.5]});n.querySelectorAll(".__lb_link").forEach(e=>t.observe(e))}(n,o),{appliedCount:g,integrations:f}}async function g(n,t){if(!function(e,n){return e?!!n||(console.warn("[LinkItBe] Content block not found for article:",e),!1):(console.warn("[LinkItBe] Article ID not found"),!1)}(n,t))return;if("1"===t.dataset.lbProcessed)return;const o=await async function(n){const t=`${String(e.apiBaseUrl||"https://api.linkitbe.com").replace(/\/$/,"")}/v1/markup?article_id=${encodeURIComponent(n)}&domain=${encodeURIComponent(e.domain)}`,o={Accept:"application/json"},r=e.partnerApiKey?String(e.partnerApiKey).trim():"";r&&(o["X-Partner-Api-Key"]=r);const i=await fetch(t,{method:"GET",headers:o,credentials:"omit"});return i.ok?await i.json():null}(n);o&&await async function(e,n,t){if("1"===n.dataset.lbProcessed)return;n.dataset.lbProcessed="1";const o=f(e,Array.isArray(t.integrations)?t.integrations:[],n,t.config.style);await i(e,o.integrations,o.appliedCount)}(n,t,o)}function h(t){if(t.nodeType!==Node.ELEMENT_NODE)return;const o=t.querySelector(e.contentSelector);if(!o)return;g(n(o),o)}function w(e){if(!e)return void console.warn("[LinkItBe] feedRoot not provided for auto markup");new MutationObserver(e=>{for(const n of e)for(let e=0;e<n.addedNodes.length;e++)h(n.addedNodes[e])}).observe(e,{childList:!0,subtree:!0})}async function m(){const t=document.querySelector(e.contentSelector),o=n(t);if(await g(o,t),!0!==e.enableFeedAutoProcess)return;const r=document.querySelector(e.feedObserverRootSelector);r?w(r):console.warn("[LinkItBe] feedObserverRootSelector not found:",e.feedObserverRootSelector)}"loading"===document.readyState?document.addEventListener("DOMContentLoaded",m):!0===e.bootOnLoad&&m(),window.LinkItBe=Object.assign({},window.LinkItBe||{},{initArticle:g,startFeedAutoMarkup:w})}();
|
|
1
|
+
!function(){const e=Object.assign({domain:window.location.hostname,bootOnLoad:!0,contentSelector:null,showPreview:!0,plainBlockJoiner:"\n",plainBlockSelector:"p, blockquote, h1, h2, h3, h4, h5, h6",allowedFormats:["keyword","mini-offer"],apiBaseUrl:"https://api.linkitbe.com",partnerApiKey:null,articleIdResolver:null,enableFeedAutoProcess:!1,feedObserverRootSelector:null,fetchImpressionTokenForViewable:!0,sdkVersion:"1.0.10",styles:{link_color:"#e2187b",link_weight:"700",link_decoration:"underline"}},window.LinkItBeConfig||{});function t(t){if("function"==typeof e.articleIdResolver)try{const n=e.articleIdResolver(t),i=null!=n?String(n).trim():"";if(i)return i}catch(e){console.warn("[LinkItBe] articleIdResolver failed",e)}return null}function n(){const e="__lb_session_id";try{const t=window.localStorage.getItem(e);if(t&&t.trim())return t.trim();const n=window.crypto&&window.crypto.randomUUID?window.crypto.randomUUID():`${Date.now()}-${Math.random().toString(16).slice(2)}`;return window.localStorage.setItem(e,n),n}catch(e){return`${Date.now()}-${Math.random().toString(16).slice(2)}`}}function i(e){if(!Array.isArray(e))return null;for(const t of e){const e=t&&t.link?String(t.link):"";if(e)try{const t=new URL(e,window.location.origin).searchParams.get("processing_id"),n=Number(t);if(Number.isFinite(n)&&n>0)return n}catch(e){}}return null}async function o(t,o,r,l,s){const a=i([l]);if(!a)return;const c=e.partnerApiKey?String(e.partnerApiKey).trim():"";if(!c)return;const d=Object.assign({event_id:window.crypto&&window.crypto.randomUUID?window.crypto.randomUUID():`${Date.now()}-${Math.random().toString(16).slice(2)}`,event_type:t,event_time:(new Date).toISOString(),article_id:r,domain:e.domain,processing_id:a,placement_link:window.location.href,integration_type:l&&null!=l.type?l.type:null,sdk_version:String(e.sdkVersion||""),session_id:n(),referrer:document.referrer||null},s||{});if("integration_viewable"===t&&e.fetchImpressionTokenForViewable){const t=await async function(t,n){const i=e.partnerApiKey?String(e.partnerApiKey).trim():"";if(!i||!n)return null;try{const o=String(e.apiBaseUrl||"https://api.linkitbe.com").replace(/\/$/,""),r=new URL(o+"/v1/events/integration-viewable-token");r.searchParams.set("article_id",t),r.searchParams.set("domain",String(e.domain||"")),r.searchParams.set("processing_id",String(n));const l=await fetch(r.toString(),{method:"GET",headers:{Accept:"application/json","X-Partner-Api-Key":i},credentials:"omit"});if(!l.ok)return null;const s=await l.json();return s&&s.impression_token?String(s.impression_token):null}catch(e){return console.warn("[LinkItBe] impression token fetch failed",e),null}}(r,a);t&&(d.impression_token=t)}try{const t=String(e.apiBaseUrl||"https://api.linkitbe.com").replace(/\/$/,"");await fetch(`${t}${o}`,{method:"POST",headers:{Accept:"application/json","Content-Type":"application/json","X-Partner-Api-Key":c},body:JSON.stringify(d),keepalive:!0,credentials:"omit"})}catch(e){console.warn("[LinkItBe] failed to send "+t,e)}}async function r(e,t,n){if(n<=0)return;const r=function(e){if(!Array.isArray(e))return null;for(let t=0;t<e.length;t++){const n=e[t];if(n&&i([n]))return n}return null}(t);r&&await o("view_rendered","/v1/events/view-rendered",e,r,{integrations_count:n})}function l(t){const n=e.allowedFormats;return null!=n&&Array.isArray(n)?t.filter(e=>n.includes(e.type)):t}function s(e,t,n){const i=12,o=e.offsetHeight||0,r=e.offsetWidth||0;let l=t+16,s=n-o+60;const a=window.innerWidth-r-i;l=Math.min(Math.max(l,i),Math.max(i,a));s+o>window.innerHeight-i&&(s=n-o-i),e.style.left=l+"px",e.style.top=Math.max(i,s)+"px"}function a(e,t,n,i,o){if(!t.preview||!t.preview.img)return void(e.style.display="none");e.replaceChildren(),e.appendChild(function(e){const t=e&&null!=e.erid?String(e.erid).trim():"",n=document.createElement("div");return n.style.cssText="font-size:10px;line-height:1.35;color:#aaa;margin-bottom:6px;font-weight:400;",n.textContent=t?`#реклама · erid: ${t}`:"#реклама",n}(t));const r=document.createElement("img");r.src=String(t.preview.img),r.style.cssText="width:100%;border-radius:8px;display:block;",e.appendChild(r);const l=document.createElement("div");l.style.cssText="margin-top:8px;font-size:13px;color:#343b4c;font-weight:600;",l.textContent=t.preview.title?String(t.preview.title):"",e.appendChild(l);const a=document.createElement("div");a.style.cssText="font-size:12px;color:#777;margin-top:2px;",a.textContent=t.preview.price?String(t.preview.price):"",e.appendChild(a);const c=document.createElement("div");c.style.cssText=`font-size:12px;color:${o.link_color};margin-top:2px;`,c.textContent=t.preview.cta?String(t.preview.cta):"",e.appendChild(c),e.style.display="block",s(e,n,i)}function c(e){e&&(e.style.display="none")}function d(e){const t=[],n=document.createTreeWalker(e,NodeFilter.SHOW_TEXT,{acceptNode:e=>function(e){const t=e.nodeType===Node.TEXT_NODE?e.parentElement:e;return!!(t&&t.closest&&t.closest("a.__lb_link"))}(e)?NodeFilter.FILTER_REJECT:NodeFilter.FILTER_ACCEPT});let i;for(;i=n.nextNode();)t.push(i);return t}function u(e,t){if(!t)return[];const n=new RegExp(String(t).replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),"gi");const i=[];let o;for(;null!==(o=n.exec(e));)i.push({start:o.index,end:o.index+o[0].length}),0===o[0].length&&n.lastIndex===o.index&&n.lastIndex++;return i}function p(e){if(null==e)return null;try{const t=new URL(String(e),window.location.origin);return"http:"!==t.protocol&&"https:"!==t.protocol?null:t.toString()}catch(e){return null}}function f(e,t){const n=e&&null!=e.erid?String(e.erid).trim():"",i=p(e&&e.advertiser_info_url);if(i)return function(e,t){const n=null!=t?String(t).trim():"";if(!n||!e)return e;try{const t=new URL(String(e),window.location.origin);return t.searchParams.set("erid",n),t.toString()}catch(t){return e}}(i,n);const o=t&&t.advertiser_info_base_url,r=e&&null!=e.advertiser?String(e.advertiser).trim():"";if(!o||!r)return null;try{const e=new URL(String(o),window.location.origin);return e.searchParams.append("items[]",r),n&&e.searchParams.set("erid",n),e.toString()}catch(e){return null}}function m(e,t,n){const i=e&&"object"==typeof e?e:{},o=i.marker_type||"plain_text",r=i.position||"before_phrase",l=null!=i.marker_text?String(i.marker_text).trim():"",s="font-size:11px;color:#999;display:block;margin-bottom:4px;";if("marker_link"===o){const e=l||"#реклама",i=function(e,t,n,i){const o=f(e,i);if(!o)return console.warn("[LinkItBe] advertiser info url is missing for marker",e&&e.advertiser),null;const r=document.createElement("a");return r.href=o,r.target="_blank",r.rel="noopener noreferrer sponsored nofollow",r.className="__lb_link __lb_advertiser_info_link",r.style.cssText=n.replace(/\s+/g," ").trim(),r.textContent=t,r}(t,e,"font-size:11px;color:#999;font-weight:400;text-decoration:underline;cursor:pointer;",n);if(i){const e=document.createElement("span");return e.style.cssText=s.replace("margin-bottom:4px;",""),e.appendChild(i),{node:e,position:r}}console.warn("[LinkItBe] marker_link fallback to plain text:",e);const o=document.createElement("span");return o.style.cssText=s,o.textContent=e,{node:o,position:r}}"plain_text"!==o&&console.warn("[LinkItBe] unsupported marker_type, fallback to plain_text:",o);const a=document.createElement("span");return a.style.cssText=s,a.textContent=function(e){const t=String(e||"#реклама").trim();return t?t.endsWith(":")?t:t.replace(/:+$/,"")+":":"#реклама"}(l||"#реклама"),{node:a,position:r}}function h(e,t,n){const i=p(e.link);if(!i)return null;const o=document.createElement("a");return o.href=i,o.target="_blank",o.rel="noopener noreferrer sponsored nofollow",o.className="__lb_link",o.setAttribute("data-lb-integration",encodeURIComponent(JSON.stringify(e))),o.style.cssText=n.replace(/\s+/g," ").trim(),o.textContent=t,o}function w(t,n){const{plain:i,spans:o}=function(t){const n=null!=e.plainBlockJoiner?e.plainBlockJoiner:"\n",i=e.plainBlockSelector||"p, blockquote, h1, h2, h3, h4, h5, h6",o=t.querySelectorAll(i),r=[];let l="";return o.forEach((e,t)=>{t>0&&(l+=n);const i=d(e);for(const e of i){const t=e.textContent;if(!t.length)continue;const n=l.length;l+=t,r.push({g0:n,g1:l.length,node:e})}}),{plain:l,spans:r}}(t),r=function(e,t){if(!e.length)return null;if(1===e.length)return e[0];const n=t||{},i=n.match_index;if(null!=i&&Number.isFinite(Number(i))){const t=Number(i);if(t>=0&&t<e.length)return e[t];console.warn("[LinkItBe] match_index out of range:",i,"n=",e.length)}const o=n.offset_start,r=n.offset_end;if(null!=o&&Number.isFinite(Number(o))){const t=Number(o),n=null!=r&&Number.isFinite(Number(r))?Number(r):null;let i=e[0],l=1/0;for(const o of e){const e=1e9*Math.abs(o.start-t)+(null!=n?Math.abs(o.end-n):0);e<l&&(l=e,i=o)}return i}return console.warn("[LinkItBe] ambiguous matches, skipping (no match_index / offset_start):",e.length),null}(u(i,n.keyword),n.position);if(!r)return null;const l=i.slice(r.start,r.end);return{plain:i,spans:o,span:r,linkText:l}}function g(e,t,n){const i=w(e,t);if(!i)return console.warn("[LinkItBe] no span for keyword:",t.keyword),!1;const{plain:o,spans:r,span:l,linkText:s}=i,a=function(e,t,n){if(e<0||e>=n||!t.length)return null;const i=t.find(t=>e>=t.g0&&e<t.g1);return i?{node:i.node,offset:e-i.g0}:null}(l.start,r,o.length),c=function(e,t,n){if(!t.length)return null;if(e<=0)return{node:t[0].node,offset:0};if(e>=n){const e=t[t.length-1];return{node:e.node,offset:e.node.textContent.length}}for(let n=0;n<t.length;n++){const i=t[n];if(e>i.g0&&e<=i.g1)return{node:i.node,offset:e-i.g0};if(e===i.g0)return{node:i.node,offset:0}}for(let n=0;n<t.length;n++)if(e<t[n].g0)return{node:t[n].node,offset:0};return null}(l.end,r,o.length);if(!a||!c)return console.warn("[LinkItBe] could not map span to DOM"),!1;const d=o.slice(l.start,l.end);if(d.toLowerCase()!==s.toLowerCase())return console.warn("[LinkItBe] plain slice mismatch"),!1;const u=document.createRange();u.setStart(a.node,a.offset),u.setEnd(c.node,c.offset);const p=h(t,d,n);return p?(function(e,t){try{e.surroundContents(t)}catch(n){const i=e.extractContents();for(;i.firstChild;)t.appendChild(i.firstChild);e.insertNode(t)}}(u,p),!0):(console.warn("[LinkItBe] invalid integration link:",t.link),!1)}const b="{anchor_text}";function y(e){const t=e.getBoundingClientRect();return{left:t.left,right:window.innerWidth-t.right}}function _(t,n){if(!window.matchMedia("(max-width: 768px)").matches)return;const i=y(t);if(i.left>=8&&i.right>=8)return;const o=function(t,n){const i=e.plainBlockSelector||"p, blockquote, h1, h2, h3, h4, h5, h6",o=t.querySelectorAll(i);for(let e=0;e<o.length;e++){const t=o[e];if(t!==n&&!t.classList.contains("__lb_mini_offer")&&(t.textContent||"").trim())return t}return null}(n,t),r=o?y(o):null,l=r&&r.left>=8?r.left:16,s=r&&r.right>=8?r.right:16,a=i.left<8?Math.max(0,Math.round(l-i.left)):0,c=i.right<8?Math.max(0,Math.round(s-i.right)):0;a>0&&(t.style.paddingLeft=`${a}px`),c>0&&(t.style.paddingRight=`${c}px`)}function k(t,n,i,r,d,u){if(!i){console.warn("[LinkItBe] Content block not provided");return{appliedCount:0,integrations:l(n)}}const p=e.showPreview?function(){const e=document.createElement("div");return e.id="__lb_preview",e.style.cssText="\n position: fixed;\n display: none;\n background: white;\n border-radius: 12px;\n box-shadow: 0 4px 20px rgba(0,0,0,0.15);\n padding: 12px;\n z-index: 99999;\n width: 180px;\n font-family: Manrope, sans-serif;\n pointer-events: none;\n ",document.body.appendChild(e),e}():null,f=`\n color:${r.link_color};\n font-weight:${r.link_weight};\n text-decoration:${r.link_decoration};\n cursor:pointer;\n `,y=l(n);let k=0,v=y.filter(e=>"keyword"===e.type);for(;v.length;){const e=[];for(const t of v){const n=w(i,t);n&&e.push({integ:t,spanStart:n.span.start})}if(!e.length){v.forEach(e=>console.warn("[LinkItBe] unresolved keyword:",e.keyword));break}e.sort((e,t)=>t.spanStart-e.spanStart);const{integ:t}=e[0];g(i,t,f)&&(k+=1),v=v.filter(e=>e!==t)}return y.filter(e=>"mini-offer"===e.type).forEach(e=>{!function(e,t,n,i,o){if(!e)return console.warn("[LinkItBe] mini-offer: no content block"),!1;const r=document.createElement("p");r.className="__lb_mini_offer",r.style.cssText="margin-top:16px;font-size:15px;font-family:Manrope, sans-serif;color:#343b4c;";const l=m(i,t,o),s=document.createElement("span"),a=null!=t.text?String(t.text):"",c=null!=t.anchor_text?String(t.anchor_text):"",d=a.indexOf(b),u=d>=0?a.slice(0,d):a,p=d>=0?a.slice(d+13):"";u&&s.appendChild(document.createTextNode(u));const f=h(t,c,n);return f?(s.appendChild(f),p&&s.appendChild(document.createTextNode(p)),l&&"before_phrase"===l.position&&r.appendChild(l.node),r.appendChild(s),l&&"after_phrase"===l.position&&(r.appendChild(document.createElement("br")),r.appendChild(l.node)),e.appendChild(r),_(r,e),!0):(console.warn("[LinkItBe] mini-offer invalid integration link:",t.link),!1)}(i,e,f,d,u)?console.warn("[LinkItBe] mini-offer failed"):k+=1}),p&&(!function(e){if(!e||"1"===e.dataset.lbDismissBound)return;e.dataset.lbDismissBound="1";const t=()=>c(e);document.addEventListener("visibilitychange",t),window.addEventListener("blur",t),window.addEventListener("pagehide",t),window.addEventListener("pageshow",t)}(p),i.querySelectorAll(".__lb_link").forEach(e=>{let n;try{n=JSON.parse(decodeURIComponent(e.dataset.lbIntegration||""))}catch(e){return void console.warn("[LinkItBe] invalid integration payload for preview",e)}if(!n.preview||!n.preview.img)return;const i=()=>c(p);e.addEventListener("mouseenter",i=>{"visible"===document.visibilityState&&(a(p,n,i.clientX,i.clientY,r),"1"!==e.dataset.lbPreviewSent&&t&&(e.dataset.lbPreviewSent="1",o("preview_viewed","/v1/events/preview-viewed",t,n)))}),e.addEventListener("mousemove",e=>{"none"!==p.style.display&&s(p,e.clientX,e.clientY)}),e.addEventListener("mouseleave",i),e.addEventListener("click",i),e.addEventListener("touchstart",i,{passive:!0})})),function(e,t){if(!e)return;const n=e=>{const t=e._lbViewDwellTimer;t&&(clearTimeout(t),e._lbViewDwellTimer=null)},i=new IntersectionObserver(t=>{for(let r=0;r<t.length;r++){const l=t[r],s=l.target;"1"!==s.dataset.lbViewableSent&&(!l.isIntersecting||l.intersectionRatio<.5?(n(s),s._lbViewVisibleSince=null,s._lbViewLastIr=null):(s._lbViewLastIr=String(Math.min(1,Math.max(0,l.intersectionRatio))),s._lbViewVisibleSince||(s._lbViewVisibleSince=Date.now()),n(s),s._lbViewDwellTimer=setTimeout(()=>{if(s._lbViewDwellTimer=null,"1"===s.dataset.lbViewableSent)return;if("visible"!==document.visibilityState)return;let t;try{t=JSON.parse(decodeURIComponent(s.dataset.lbIntegration||""))}catch(e){return void i.unobserve(s)}s.dataset.lbViewableSent="1";const n=s._lbViewVisibleSince||Date.now(),r=Math.max(0,Date.now()-n),l=parseFloat(s._lbViewLastIr||"0.5");o("integration_viewable","/v1/events/integration-viewable",e,t,{tab_visible:"visible"===document.visibilityState,dwell_ms:Math.max(1e3,r),intersection_ratio:l,viewability_rule_version:"elitesdk-1"}),i.unobserve(s)},1e3)))}},{threshold:[.5]});t.querySelectorAll(".__lb_link").forEach(e=>i.observe(e))}(t,i),{appliedCount:k,integrations:y}}async function v(t,n){if(!function(e,t){return e?!!t||(console.warn("[LinkItBe] Content block not found for article:",e),!1):(console.warn("[LinkItBe] Article ID not found"),!1)}(t,n))return;if("1"===n.dataset.lbProcessed)return;const i=await async function(t){const n=`${String(e.apiBaseUrl||"https://api.linkitbe.com").replace(/\/$/,"")}/v1/markup?article_id=${encodeURIComponent(t)}&domain=${encodeURIComponent(e.domain)}`,i={Accept:"application/json"},o=e.partnerApiKey?String(e.partnerApiKey).trim():"";o&&(i["X-Partner-Api-Key"]=o);const r=await fetch(n,{method:"GET",headers:i,credentials:"omit"});return r.ok?await r.json():null}(t);i&&await async function(e,t,n){if("1"===t.dataset.lbProcessed)return;t.dataset.lbProcessed="1";const i=Array.isArray(n.integrations)?n.integrations:[],o=n.config&&"object"==typeof n.config?n.config:{},l=k(e,i,t,o.style||{},o.labeling_template||null,o);await r(e,l.integrations,l.appliedCount)}(t,n,i)}function x(n){if(n.nodeType!==Node.ELEMENT_NODE)return;const i=n.querySelector(e.contentSelector);if(!i)return;v(t(i),i)}function S(e){if(!e)return void console.warn("[LinkItBe] feedRoot not provided for auto markup");new MutationObserver(e=>{for(const t of e)for(let e=0;e<t.addedNodes.length;e++)x(t.addedNodes[e])}).observe(e,{childList:!0,subtree:!0})}async function I(){const n=document.querySelector(e.contentSelector),i=t(n);if(await v(i,n),!0!==e.enableFeedAutoProcess)return;const o=document.querySelector(e.feedObserverRootSelector);o?S(o):console.warn("[LinkItBe] feedObserverRootSelector not found:",e.feedObserverRootSelector)}"loading"===document.readyState?document.addEventListener("DOMContentLoaded",I):!0===e.bootOnLoad&&I(),window.LinkItBe=Object.assign({},window.LinkItBe||{},{initArticle:v,startFeedAutoMarkup:S})}();
|