@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.
@@ -20,7 +20,9 @@
20
20
  enableFeedAutoProcess: false,
21
21
  // Корень наблюдения для фида (обязателен при enableFeedAutoProcess=true).
22
22
  feedObserverRootSelector: null,
23
- sdkVersion: '1.0.2',
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
- let integration;
173
- try {
174
- integration = JSON.parse(decodeURIComponent(linkEl.dataset.lbIntegration || ''));
175
- } catch (e) {
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.dataset.lbViewableSent = '1';
180
- emitSdkEvent('integration_viewable', '/v1/events/integration-viewable', articleId, integration);
181
- io.unobserve(linkEl);
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 applyMiniOffer(contentBlock, integration, linkStyle) {
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
- if (!blocks.length) {
473
- console.warn('[LinkItBe] mini-offer: no content blocks');
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 adLabel = document.createElement('span');
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
- lastBlock.after(outro);
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.left = (e.clientX + 16) + 'px';
575
- preview.style.top = (e.clientY - 60) + 'px';
861
+ if (preview.style.display === 'none') {
862
+ return;
863
+ }
864
+ positionMarkupPreview(preview, e.clientX, e.clientY);
576
865
  });
577
- linkEl.addEventListener('mouseleave', () => { preview.style.display = 'none'; });
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 style_config = data.config.style;
598
- const result = applyIntegrations(articleId, integrations, contentBlock, style_config);
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
  }
@@ -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})}();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@linkitbe/sdk",
3
- "version": "1.0.2",
3
+ "version": "1.0.10",
4
4
  "description": "LinkItBe browser SDK",
5
5
  "license": "UNLICENSED",
6
6
  "publishConfig": {