@linkitbe/sdk 1.0.8 → 1.0.12

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.
@@ -22,7 +22,9 @@
22
22
  feedObserverRootSelector: null,
23
23
  // true = перед POST integration-viewable запросить GET /v1/events/integration-viewable-token (нужен секрет на markup-api).
24
24
  fetchImpressionTokenForViewable: true,
25
- sdkVersion: '1.0.8',
25
+ // null — mini-offer в конец contentBlock; CSS-селектор — вставить перед первым совпадением внутри блока.
26
+ miniOfferInsertBeforeSelector: null,
27
+ sdkVersion: '1.0.12',
26
28
  styles: {
27
29
  link_color: '#e2187b',
28
30
  link_weight: '700',
@@ -300,6 +302,14 @@
300
302
  preview.style.top = Math.max(margin, top) + 'px';
301
303
  }
302
304
 
305
+ function buildPreviewLabelingEl(integration) {
306
+ const erid = integration && integration.erid != null ? String(integration.erid).trim() : '';
307
+ const label = document.createElement('div');
308
+ label.style.cssText = 'font-size:10px;line-height:1.35;color:#aaa;margin-bottom:6px;font-weight:400;';
309
+ label.textContent = erid ? `#реклама · erid: ${erid}` : '#реклама';
310
+ return label;
311
+ }
312
+
303
313
  function showPreview(preview, integration, x, y, styles_config) {
304
314
  if (!integration.preview || !integration.preview.img) {
305
315
  preview.style.display = 'none';
@@ -308,6 +318,8 @@
308
318
 
309
319
  preview.replaceChildren();
310
320
 
321
+ preview.appendChild(buildPreviewLabelingEl(integration));
322
+
311
323
  const image = document.createElement('img');
312
324
  image.src = String(integration.preview.img);
313
325
  image.style.cssText = 'width:100%;border-radius:8px;display:block;';
@@ -332,6 +344,26 @@
332
344
  positionMarkupPreview(preview, x, y);
333
345
  }
334
346
 
347
+ function hidePreview(preview) {
348
+ if (preview) {
349
+ preview.style.display = 'none';
350
+ }
351
+ }
352
+
353
+ function attachPreviewDismissHandlers(preview) {
354
+ if (!preview || preview.dataset.lbDismissBound === '1') {
355
+ return;
356
+ }
357
+ preview.dataset.lbDismissBound = '1';
358
+
359
+ const dismiss = () => hidePreview(preview);
360
+
361
+ document.addEventListener('visibilitychange', dismiss);
362
+ window.addEventListener('blur', dismiss);
363
+ window.addEventListener('pagehide', dismiss);
364
+ window.addEventListener('pageshow', dismiss);
365
+ }
366
+
335
367
 
336
368
  // ============================================================
337
369
  // 5. KEYWORD: plain, матчи, Range
@@ -657,6 +689,96 @@
657
689
  }
658
690
 
659
691
  const MINI_OFFER_PLACEHOLDER = '{anchor_text}';
692
+ const MOBILE_LAYOUT_MAX_WIDTH = 768;
693
+ const MOBILE_MIN_SIDE_INSET_PX = 8;
694
+ const MOBILE_FALLBACK_SIDE_PADDING_PX = 16;
695
+
696
+ function isMobileLayout() {
697
+ return window.matchMedia(`(max-width: ${MOBILE_LAYOUT_MAX_WIDTH}px)`).matches;
698
+ }
699
+
700
+ function getViewportSideInset(el) {
701
+ const rect = el.getBoundingClientRect();
702
+ return {
703
+ left: rect.left,
704
+ right: window.innerWidth - rect.right,
705
+ };
706
+ }
707
+
708
+ function findReferencePlainBlock(contentBlock, excludeEl) {
709
+ const sel = config.plainBlockSelector || 'p, blockquote, h1, h2, h3, h4, h5, h6';
710
+ const blocks = contentBlock.querySelectorAll(sel);
711
+ for (let i = 0; i < blocks.length; i++) {
712
+ const el = blocks[i];
713
+ if (el === excludeEl || el.classList.contains('__lb_mini_offer')) continue;
714
+ if (!(el.textContent || '').trim()) continue;
715
+ return el;
716
+ }
717
+ return null;
718
+ }
719
+
720
+ function applyMobileSideInsetIfNeeded(outro, contentBlock) {
721
+ if (!isMobileLayout()) return;
722
+
723
+ const currentInset = getViewportSideInset(outro);
724
+ if (currentInset.left >= MOBILE_MIN_SIDE_INSET_PX && currentInset.right >= MOBILE_MIN_SIDE_INSET_PX) {
725
+ return;
726
+ }
727
+
728
+ const ref = findReferencePlainBlock(contentBlock, outro);
729
+ const refInset = ref ? getViewportSideInset(ref) : null;
730
+ const targetLeft = refInset && refInset.left >= MOBILE_MIN_SIDE_INSET_PX
731
+ ? refInset.left
732
+ : MOBILE_FALLBACK_SIDE_PADDING_PX;
733
+ const targetRight = refInset && refInset.right >= MOBILE_MIN_SIDE_INSET_PX
734
+ ? refInset.right
735
+ : MOBILE_FALLBACK_SIDE_PADDING_PX;
736
+
737
+ const padLeft = currentInset.left < MOBILE_MIN_SIDE_INSET_PX
738
+ ? Math.max(0, Math.round(targetLeft - currentInset.left))
739
+ : 0;
740
+ const padRight = currentInset.right < MOBILE_MIN_SIDE_INSET_PX
741
+ ? Math.max(0, Math.round(targetRight - currentInset.right))
742
+ : 0;
743
+
744
+ if (padLeft > 0) outro.style.paddingLeft = `${padLeft}px`;
745
+ if (padRight > 0) outro.style.paddingRight = `${padRight}px`;
746
+ }
747
+
748
+ function findMiniOfferInsertAnchor(contentBlock) {
749
+ const raw = config.miniOfferInsertBeforeSelector;
750
+ const selector = raw != null ? String(raw).trim() : '';
751
+ if (!selector) {
752
+ return null;
753
+ }
754
+
755
+ try {
756
+ return contentBlock.querySelector(selector);
757
+ } catch (e) {
758
+ console.warn('[LinkItBe] miniOfferInsertBeforeSelector invalid:', selector, e);
759
+ return null;
760
+ }
761
+ }
762
+
763
+ function insertMiniOfferElement(contentBlock, outro) {
764
+ const anchor = findMiniOfferInsertAnchor(contentBlock);
765
+ if (!anchor || !contentBlock.contains(anchor) || anchor === outro) {
766
+ contentBlock.appendChild(outro);
767
+ return;
768
+ }
769
+
770
+ try {
771
+ const parent = anchor.parentNode;
772
+ if (!parent) {
773
+ contentBlock.appendChild(outro);
774
+ return;
775
+ }
776
+ parent.insertBefore(outro, anchor);
777
+ } catch (e) {
778
+ console.warn('[LinkItBe] mini-offer insertBefore failed, falling back to append', e);
779
+ contentBlock.appendChild(outro);
780
+ }
781
+ }
660
782
 
661
783
  function applyMiniOffer(contentBlock, integration, linkStyle, labelingTemplate, pageConfig) {
662
784
  if (!contentBlock) {
@@ -695,7 +817,8 @@
695
817
  outro.appendChild(marker.node);
696
818
  }
697
819
 
698
- contentBlock.appendChild(outro);
820
+ insertMiniOfferElement(contentBlock, outro);
821
+ applyMobileSideInsetIfNeeded(outro, contentBlock);
699
822
  return true;
700
823
  }
701
824
 
@@ -747,6 +870,8 @@
747
870
  });
748
871
 
749
872
  if (preview) {
873
+ attachPreviewDismissHandlers(preview);
874
+
750
875
  contentBlock.querySelectorAll('.__lb_link').forEach((linkEl) => {
751
876
  let integration;
752
877
  try {
@@ -758,16 +883,26 @@
758
883
  if (!integration.preview || !integration.preview.img) {
759
884
  return;
760
885
  }
886
+ const dismissPreview = () => hidePreview(preview);
887
+
761
888
  linkEl.addEventListener('mouseenter', (e) => {
889
+ if (document.visibilityState !== 'visible') {
890
+ return;
891
+ }
762
892
  showPreview(preview, integration, e.clientX, e.clientY, style_config);
763
893
  if (linkEl.dataset.lbPreviewSent === '1' || !articleId) return;
764
894
  linkEl.dataset.lbPreviewSent = '1';
765
895
  emitSdkEvent('preview_viewed', '/v1/events/preview-viewed', articleId, integration);
766
896
  });
767
897
  linkEl.addEventListener('mousemove', (e) => {
898
+ if (preview.style.display === 'none') {
899
+ return;
900
+ }
768
901
  positionMarkupPreview(preview, e.clientX, e.clientY);
769
902
  });
770
- linkEl.addEventListener('mouseleave', () => { preview.style.display = 'none'; });
903
+ linkEl.addEventListener('mouseleave', dismissPreview);
904
+ linkEl.addEventListener('click', dismissPreview);
905
+ linkEl.addEventListener('touchstart', dismissPreview, { passive: true });
771
906
  });
772
907
  }
773
908
 
@@ -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,fetchImpressionTokenForViewable:!0,sdkVersion:"1.0.8",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 a=o([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:n,event_time:(new Date).toISOString(),article_id:i,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:t(),referrer:document.referrer||null},s||{});if("integration_viewable"===n&&e.fetchImpressionTokenForViewable){const n=await async function(n,t){const o=e.partnerApiKey?String(e.partnerApiKey).trim():"";if(!o||!t)return null;try{const r=String(e.apiBaseUrl||"https://api.linkitbe.com").replace(/\/$/,""),i=new URL(r+"/v1/events/integration-viewable-token");i.searchParams.set("article_id",n),i.searchParams.set("domain",String(e.domain||"")),i.searchParams.set("processing_id",String(t));const l=await fetch(i.toString(),{method:"GET",headers:{Accept:"application/json","X-Partner-Api-Key":o},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}}(i,a);n&&(d.impression_token=n)}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":c},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,n,t){const o=12,r=e.offsetHeight||0,i=e.offsetWidth||0;let l=n+16,s=t-r+60;const a=window.innerWidth-i-o;l=Math.min(Math.max(l,o),Math.max(o,a));s+r>window.innerHeight-o&&(s=t-r-o),e.style.left=l+"px",e.style.top=Math.max(o,s)+"px"}function a(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 d(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}}function u(e,n){const t=e&&null!=e.erid?String(e.erid).trim():"",o=d(e&&e.advertiser_info_url);if(o)return function(e,n){const t=null!=n?String(n).trim():"";if(!t||!e)return e;try{const n=new URL(String(e),window.location.origin);return n.searchParams.set("erid",t),n.toString()}catch(n){return e}}(o,t);const r=n&&n.advertiser_info_base_url,i=e&&null!=e.advertiser?String(e.advertiser).trim():"";if(!r||!i)return null;try{const e=new URL(String(r),window.location.origin);return e.searchParams.append("items[]",i),t&&e.searchParams.set("erid",t),e.toString()}catch(e){return null}}function p(e,n,t){const o=e&&"object"==typeof e?e:{},r=o.marker_type||"plain_text",i=o.position||"before_phrase",l=null!=o.marker_text?String(o.marker_text).trim():"",s="font-size:11px;color:#999;display:block;margin-bottom:4px;";if("marker_link"===r){const e=l||"#реклама",o=function(e,n,t,o){const r=u(e,o);if(!r)return console.warn("[LinkItBe] advertiser info url is missing for marker",e&&e.advertiser),null;const i=document.createElement("a");return i.href=r,i.target="_blank",i.rel="noopener noreferrer sponsored nofollow",i.className="__lb_link __lb_advertiser_info_link",i.style.cssText=t.replace(/\s+/g," ").trim(),i.textContent=n,i}(n,e,"font-size:11px;color:#999;font-weight:400;text-decoration:underline;cursor:pointer;",t);if(o){const e=document.createElement("span");return e.style.cssText=s.replace("margin-bottom:4px;",""),e.appendChild(o),{node:e,position:i}}console.warn("[LinkItBe] marker_link fallback to plain text:",e);const r=document.createElement("span");return r.style.cssText=s,r.textContent=e,{node:r,position:i}}"plain_text"!==r&&console.warn("[LinkItBe] unsupported marker_type, fallback to plain_text:",r);const a=document.createElement("span");return a.style.cssText=s,a.textContent=function(e){const n=String(e||"#реклама").trim();return n?n.endsWith(":")?n:n.replace(/:+$/,"")+":":"#реклама"}(l||"#реклама"),{node:a,position:i}}function f(e,n,t){const o=d(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 m(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=a(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 w(e,n,t){const o=m(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,a=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),c=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(!a||!c)return console.warn("[LinkItBe] could not map span to DOM"),!1;const d=r.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=f(n,d,t);return p?(function(e,n){try{e.surroundContents(n)}catch(t){const o=e.extractContents();for(;o.firstChild;)n.appendChild(o.firstChild);e.insertNode(n)}}(u,p),!0):(console.warn("[LinkItBe] invalid integration link:",n.link),!1)}const h="{anchor_text}";function g(n,t,o,i,a,c){if(!o){console.warn("[LinkItBe] Content block not provided");return{appliedCount:0,integrations:l(t)}}const d=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,u=`\n color:${i.link_color};\n font-weight:${i.link_weight};\n text-decoration:${i.link_decoration};\n cursor:pointer;\n `,g=l(t);let b=0,_=g.filter(e=>"keyword"===e.type);for(;_.length;){const e=[];for(const n of _){const t=m(o,n);t&&e.push({integ:n,spanStart:t.span.start})}if(!e.length){_.forEach(e=>console.warn("[LinkItBe] unresolved keyword:",e.keyword));break}e.sort((e,n)=>n.spanStart-e.spanStart);const{integ:n}=e[0];w(o,n,u)&&(b+=1),_=_.filter(e=>e!==n)}return g.filter(e=>"mini-offer"===e.type).forEach(e=>{!function(e,n,t,o,r){if(!e)return console.warn("[LinkItBe] mini-offer: no content block"),!1;const i=document.createElement("p");i.className="__lb_mini_offer",i.style.cssText="margin-top:16px;font-size:15px;font-family:Manrope, sans-serif;color:#343b4c;";const l=p(o,n,r),s=document.createElement("span"),a=null!=n.text?String(n.text):"",c=null!=n.anchor_text?String(n.anchor_text):"",d=a.indexOf(h),u=d>=0?a.slice(0,d):a,m=d>=0?a.slice(d+13):"";u&&s.appendChild(document.createTextNode(u));const w=f(n,c,t);return w?(s.appendChild(w),m&&s.appendChild(document.createTextNode(m)),l&&"before_phrase"===l.position&&i.appendChild(l.node),i.appendChild(s),l&&"after_phrase"===l.position&&(i.appendChild(document.createElement("br")),i.appendChild(l.node)),e.appendChild(i),!0):(console.warn("[LinkItBe] mini-offer invalid integration link:",n.link),!1)}(o,e,u,a,c)?console.warn("[LinkItBe] mini-offer failed"):b+=1}),d&&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 a=document.createElement("div");a.style.cssText="font-size:12px;color:#777;margin-top:2px;",a.textContent=n.preview.price?String(n.preview.price):"",e.appendChild(a);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.display="block",s(e,t,o)}(d,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(d,e.clientX,e.clientY)}),e.addEventListener("mouseleave",()=>{d.style.display="none"}))}),function(e,n){if(!e)return;const t=e=>{const n=e._lbViewDwellTimer;n&&(clearTimeout(n),e._lbViewDwellTimer=null)},o=new IntersectionObserver(n=>{for(let i=0;i<n.length;i++){const l=n[i],s=l.target;"1"!==s.dataset.lbViewableSent&&(!l.isIntersecting||l.intersectionRatio<.5?(t(s),s._lbViewVisibleSince=null,s._lbViewLastIr=null):(s._lbViewLastIr=String(Math.min(1,Math.max(0,l.intersectionRatio))),s._lbViewVisibleSince||(s._lbViewVisibleSince=Date.now()),t(s),s._lbViewDwellTimer=setTimeout(()=>{if(s._lbViewDwellTimer=null,"1"===s.dataset.lbViewableSent)return;if("visible"!==document.visibilityState)return;let n;try{n=JSON.parse(decodeURIComponent(s.dataset.lbIntegration||""))}catch(e){return void o.unobserve(s)}s.dataset.lbViewableSent="1";const t=s._lbViewVisibleSince||Date.now(),i=Math.max(0,Date.now()-t),l=parseFloat(s._lbViewLastIr||"0.5");r("integration_viewable","/v1/events/integration-viewable",e,n,{tab_visible:"visible"===document.visibilityState,dwell_ms:Math.max(1e3,i),intersection_ratio:l,viewability_rule_version:"elitesdk-1"}),o.unobserve(s)},1e3)))}},{threshold:[.5]});n.querySelectorAll(".__lb_link").forEach(e=>o.observe(e))}(n,o),{appliedCount:b,integrations:g}}async function b(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=Array.isArray(t.integrations)?t.integrations:[],r=t.config&&"object"==typeof t.config?t.config:{},l=g(e,o,n,r.style||{},r.labeling_template||null,r);await i(e,l.integrations,l.appliedCount)}(n,t,o)}function _(t){if(t.nodeType!==Node.ELEMENT_NODE)return;const o=t.querySelector(e.contentSelector);if(!o)return;b(n(o),o)}function k(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++)_(n.addedNodes[e])}).observe(e,{childList:!0,subtree:!0})}async function y(){const t=document.querySelector(e.contentSelector),o=n(t);if(await b(o,t),!0!==e.enableFeedAutoProcess)return;const r=document.querySelector(e.feedObserverRootSelector);r?k(r):console.warn("[LinkItBe] feedObserverRootSelector not found:",e.feedObserverRootSelector)}"loading"===document.readyState?document.addEventListener("DOMContentLoaded",y):!0===e.bootOnLoad&&y(),window.LinkItBe=Object.assign({},window.LinkItBe||{},{initArticle:b,startFeedAutoMarkup:k})}();
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,miniOfferInsertBeforeSelector:null,sdkVersion:"1.0.12",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 r(t,r,o,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:o,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 r=String(e.apiBaseUrl||"https://api.linkitbe.com").replace(/\/$/,""),o=new URL(r+"/v1/events/integration-viewable-token");o.searchParams.set("article_id",t),o.searchParams.set("domain",String(e.domain||"")),o.searchParams.set("processing_id",String(n));const l=await fetch(o.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}}(o,a);t&&(d.impression_token=t)}try{const t=String(e.apiBaseUrl||"https://api.linkitbe.com").replace(/\/$/,"");await fetch(`${t}${r}`,{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 o(e,t,n){if(n<=0)return;const o=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);o&&await r("view_rendered","/v1/events/view-rendered",e,o,{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,r=e.offsetHeight||0,o=e.offsetWidth||0;let l=t+16,s=n-r+60;const a=window.innerWidth-o-i;l=Math.min(Math.max(l,i),Math.max(i,a));s+r>window.innerHeight-i&&(s=n-r-i),e.style.left=l+"px",e.style.top=Math.max(i,s)+"px"}function a(e,t,n,i,r){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 o=document.createElement("img");o.src=String(t.preview.img),o.style.cssText="width:100%;border-radius:8px;display:block;",e.appendChild(o);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:${r.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 r;for(;null!==(r=n.exec(e));)i.push({start:r.index,end:r.index+r[0].length}),0===r[0].length&&n.lastIndex===r.index&&n.lastIndex++;return i}function f(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 p(e,t){const n=e&&null!=e.erid?String(e.erid).trim():"",i=f(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 r=t&&t.advertiser_info_base_url,o=e&&null!=e.advertiser?String(e.advertiser).trim():"";if(!r||!o)return null;try{const e=new URL(String(r),window.location.origin);return e.searchParams.append("items[]",o),n&&e.searchParams.set("erid",n),e.toString()}catch(e){return null}}function m(e,t,n){const i=e&&"object"==typeof e?e:{},r=i.marker_type||"plain_text",o=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"===r){const e=l||"#реклама",i=function(e,t,n,i){const r=p(e,i);if(!r)return console.warn("[LinkItBe] advertiser info url is missing for marker",e&&e.advertiser),null;const o=document.createElement("a");return o.href=r,o.target="_blank",o.rel="noopener noreferrer sponsored nofollow",o.className="__lb_link __lb_advertiser_info_link",o.style.cssText=n.replace(/\s+/g," ").trim(),o.textContent=t,o}(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:o}}console.warn("[LinkItBe] marker_link fallback to plain text:",e);const r=document.createElement("span");return r.style.cssText=s,r.textContent=e,{node:r,position:o}}"plain_text"!==r&&console.warn("[LinkItBe] unsupported marker_type, fallback to plain_text:",r);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:o}}function h(e,t,n){const i=f(e.link);if(!i)return null;const r=document.createElement("a");return r.href=i,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=n.replace(/\s+/g," ").trim(),r.textContent=t,r}function w(t,n){const{plain:i,spans:r}=function(t){const n=null!=e.plainBlockJoiner?e.plainBlockJoiner:"\n",i=e.plainBlockSelector||"p, blockquote, h1, h2, h3, h4, h5, h6",r=t.querySelectorAll(i),o=[];let l="";return r.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,o.push({g0:n,g1:l.length,node:e})}}),{plain:l,spans:o}}(t),o=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 r=n.offset_start,o=n.offset_end;if(null!=r&&Number.isFinite(Number(r))){const t=Number(r),n=null!=o&&Number.isFinite(Number(o))?Number(o):null;let i=e[0],l=1/0;for(const r of e){const e=1e9*Math.abs(r.start-t)+(null!=n?Math.abs(r.end-n):0);e<l&&(l=e,i=r)}return i}return console.warn("[LinkItBe] ambiguous matches, skipping (no match_index / offset_start):",e.length),null}(u(i,n.keyword),n.position);if(!o)return null;const l=i.slice(o.start,o.end);return{plain:i,spans:r,span:o,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:r,spans:o,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,o,r.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,o,r.length);if(!a||!c)return console.warn("[LinkItBe] could not map span to DOM"),!1;const d=r.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 f=h(t,d,n);return f?(function(e,t){try{e.surroundContents(t)}catch(n){const i=e.extractContents();for(;i.firstChild;)t.appendChild(i.firstChild);e.insertNode(t)}}(u,f),!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 r=function(t,n){const i=e.plainBlockSelector||"p, blockquote, h1, h2, h3, h4, h5, h6",r=t.querySelectorAll(i);for(let e=0;e<r.length;e++){const t=r[e];if(t!==n&&!t.classList.contains("__lb_mini_offer")&&(t.textContent||"").trim())return t}return null}(n,t),o=r?y(r):null,l=o&&o.left>=8?o.left:16,s=o&&o.right>=8?o.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){const i=function(t){const n=e.miniOfferInsertBeforeSelector,i=null!=n?String(n).trim():"";if(!i)return null;try{return t.querySelector(i)}catch(e){return console.warn("[LinkItBe] miniOfferInsertBeforeSelector invalid:",i,e),null}}(t);if(i&&t.contains(i)&&i!==n)try{const e=i.parentNode;if(!e)return void t.appendChild(n);e.insertBefore(n,i)}catch(e){console.warn("[LinkItBe] mini-offer insertBefore failed, falling back to append",e),t.appendChild(n)}else t.appendChild(n)}function v(t,n,i,o,d,u){if(!i){console.warn("[LinkItBe] Content block not provided");return{appliedCount:0,integrations:l(n)}}const f=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,p=`\n color:${o.link_color};\n font-weight:${o.link_weight};\n text-decoration:${o.link_decoration};\n cursor:pointer;\n `,y=l(n);let v=0,x=y.filter(e=>"keyword"===e.type);for(;x.length;){const e=[];for(const t of x){const n=w(i,t);n&&e.push({integ:t,spanStart:n.span.start})}if(!e.length){x.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,p)&&(v+=1),x=x.filter(e=>e!==t)}return y.filter(e=>"mini-offer"===e.type).forEach(e=>{!function(e,t,n,i,r){if(!e)return console.warn("[LinkItBe] mini-offer: no content block"),!1;const o=document.createElement("p");o.className="__lb_mini_offer",o.style.cssText="margin-top:16px;font-size:15px;font-family:Manrope, sans-serif;color:#343b4c;";const l=m(i,t,r),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,f=d>=0?a.slice(d+13):"";u&&s.appendChild(document.createTextNode(u));const p=h(t,c,n);return p?(s.appendChild(p),f&&s.appendChild(document.createTextNode(f)),l&&"before_phrase"===l.position&&o.appendChild(l.node),o.appendChild(s),l&&"after_phrase"===l.position&&(o.appendChild(document.createElement("br")),o.appendChild(l.node)),k(e,o),_(o,e),!0):(console.warn("[LinkItBe] mini-offer invalid integration link:",t.link),!1)}(i,e,p,d,u)?console.warn("[LinkItBe] mini-offer failed"):v+=1}),f&&(!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)}(f),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(f);e.addEventListener("mouseenter",i=>{"visible"===document.visibilityState&&(a(f,n,i.clientX,i.clientY,o),"1"!==e.dataset.lbPreviewSent&&t&&(e.dataset.lbPreviewSent="1",r("preview_viewed","/v1/events/preview-viewed",t,n)))}),e.addEventListener("mousemove",e=>{"none"!==f.style.display&&s(f,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 o=0;o<t.length;o++){const l=t[o],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(),o=Math.max(0,Date.now()-n),l=parseFloat(s._lbViewLastIr||"0.5");r("integration_viewable","/v1/events/integration-viewable",e,t,{tab_visible:"visible"===document.visibilityState,dwell_ms:Math.max(1e3,o),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:v,integrations:y}}async function x(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"},r=e.partnerApiKey?String(e.partnerApiKey).trim():"";r&&(i["X-Partner-Api-Key"]=r);const o=await fetch(n,{method:"GET",headers:i,credentials:"omit"});return o.ok?await o.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:[],r=n.config&&"object"==typeof n.config?n.config:{},l=v(e,i,t,r.style||{},r.labeling_template||null,r);await o(e,l.integrations,l.appliedCount)}(t,n,i)}function S(n){if(n.nodeType!==Node.ELEMENT_NODE)return;const i=n.querySelector(e.contentSelector);if(!i)return;x(t(i),i)}function I(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++)S(t.addedNodes[e])}).observe(e,{childList:!0,subtree:!0})}async function L(){const n=document.querySelector(e.contentSelector),i=t(n);if(await x(i,n),!0!==e.enableFeedAutoProcess)return;const r=document.querySelector(e.feedObserverRootSelector);r?I(r):console.warn("[LinkItBe] feedObserverRootSelector not found:",e.feedObserverRootSelector)}"loading"===document.readyState?document.addEventListener("DOMContentLoaded",L):!0===e.bootOnLoad&&L(),window.LinkItBe=Object.assign({},window.LinkItBe||{},{initArticle:x,startFeedAutoMarkup:I})}();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@linkitbe/sdk",
3
- "version": "1.0.8",
3
+ "version": "1.0.12",
4
4
  "description": "LinkItBe browser SDK",
5
5
  "license": "UNLICENSED",
6
6
  "publishConfig": {