diff --git a/assets/js/wpr-beacon.js b/assets/js/wpr-beacon.js index 0f056c5bd4..84899a86dc 100644 --- a/assets/js/wpr-beacon.js +++ b/assets/js/wpr-beacon.js @@ -379,13 +379,14 @@ var BeaconLrc_default = BeaconLrc; // src/BeaconPreloadFonts.js - var BeaconPreloadFonts = class _BeaconPreloadFonts { + var BeaconPreloadFonts = class { constructor(config, logger) { this.config = config; this.logger = logger; this.aboveTheFoldFonts = []; + const extensions = (Array.isArray(this.config.processed_extensions) && this.config.processed_extensions.length > 0 ? this.config.processed_extensions : ["woff", "woff2", "ttf"]).map((ext) => ext.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("|"); + this.FONT_FILE_REGEX = new RegExp(`\\.(${extensions})(\\?.*)?$`, "i"); } - static FONT_FILE_REGEX = /\.(woff2?|ttf|otf|eot)(\?.*)?$/i; /** * Checks if a given font family is a system font. * @@ -443,7 +444,7 @@ */ getNetworkLoadedFonts() { return new Map( - window.performance.getEntriesByType("resource").filter((resource) => _BeaconPreloadFonts.FONT_FILE_REGEX.test(resource.name)).map((resource) => [this.cleanUrl(resource.name), resource.name]) + window.performance.getEntriesByType("resource").filter((resource) => this.FONT_FILE_REGEX.test(resource.name)).map((resource) => [this.cleanUrl(resource.name), resource.name]) ); } /** diff --git a/assets/js/wpr-beacon.min.js b/assets/js/wpr-beacon.min.js index f0814fefa3..77e20d448f 100644 --- a/assets/js/wpr-beacon.min.js +++ b/assets/js/wpr-beacon.min.js @@ -1,2 +1,2 @@ -(()=>{var y=class{static getScreenWidth(){return window.innerWidth||document.documentElement.clientWidth}static getScreenHeight(){return window.innerHeight||document.documentElement.clientHeight}static isNotValidScreensize(e,t){const n=this.getScreenWidth(),i=this.getScreenHeight(),s=e&&(n>t.width||i>t.height),a=!e&&(n=0&&e.right>=0&&e.top<=(window.innerHeight||document.documentElement.clientHeight)&&e.left<=(window.innerWidth||document.documentElement.clientWidth)}static isPageScrolled(){return window.pageYOffset>0||document.documentElement.scrollTop>0}},d=y,w=class{constructor(e,t){this.config=e,this.performanceImages=[],this.logger=t}async run(){try{const e=this._generateLcpCandidates(1/0);e&&(this._initWithFirstElementWithInfo(e),this._fillATFWithoutDuplications(e))}catch(e){this.errorCode="script_error",this.logger.logMessage("Script Error: "+e)}}_generateLcpCandidates(e){const t=document.querySelectorAll(this.config.elements);return t.length<=0?[]:Array.from(t).map(s=>{if(s.nodeName.toLowerCase()==="img"&&s.parentElement.nodeName.toLowerCase()==="picture")return null;let a;if(s.nodeName.toLowerCase()==="picture"){const r=s.querySelector("img");if(r)a=r.getBoundingClientRect();else return null}else a=s.getBoundingClientRect();return{element:s,rect:a}}).filter(s=>s!==null).filter(s=>s.rect.width>0&&s.rect.height>0&&d.isIntersecting(s.rect)).map(s=>({item:s,area:this._getElementArea(s.rect),elementInfo:this._getElementInfo(s.element)})).sort((s,a)=>a.area-s.area).slice(0,e).map(s=>({element:s.item.element,elementInfo:s.elementInfo}))}_getElementArea(e){const t=Math.min(e.width,(window.innerWidth||document.documentElement.clientWidth)-e.left),n=Math.min(e.height,(window.innerHeight||document.documentElement.clientHeight)-e.top);return t*n}_getElementInfo(e){const t=e.nodeName.toLowerCase(),n={type:"",src:"",srcset:"",sizes:"",sources:[],bg_set:[],current_src:""},i=/url\(\s*?['"]?\s*?(.+?)\s*?["']?\s*?\)/ig;if(t==="img"&&e.srcset)n.type="img-srcset",n.src=e.src,n.srcset=e.srcset,n.sizes=e.sizes,n.current_src=e.currentSrc;else if(t==="img")n.type="img",n.src=e.src,n.current_src=e.currentSrc;else if(t==="video"){n.type="img";const s=e.querySelector("source");n.src=e.poster||(s?s.src:""),n.current_src=n.src}else if(t==="svg"){const s=e.querySelector("image");s&&(n.type="img",n.src=s.getAttribute("href")||"",n.current_src=n.src)}else if(t==="picture"){n.type="picture";const s=e.querySelector("img");n.src=s?s.src:"",n.sources=Array.from(e.querySelectorAll("source")).map(a=>({srcset:a.srcset||"",media:a.media||"",type:a.type||"",sizes:a.sizes||""}))}else{const a=[window.getComputedStyle(e,null).getPropertyValue("background-image"),getComputedStyle(e,":after").getPropertyValue("background-image"),getComputedStyle(e,":before").getPropertyValue("background-image")].filter(o=>o!=="none");if(a.length===0)return null;const r=a[0];if(n.type="bg-img",r.includes("image-set(")&&(n.type="bg-img-set"),!r||r===""||r.includes("data:image"))return null;const l=[...r.matchAll(i)];if(n.bg_set=l.map(o=>o[1]?{src:o[1].trim()+(o[2]?" "+o[2].trim():"")}:{}),n.bg_set.every(o=>o.src==="")&&(n.bg_set=l.map(o=>o[1]?{src:o[1].trim()}:{})),n.bg_set.length<=0)return null;n.bg_set.length>0&&(n.src=n.bg_set[0].src,n.type==="bg-img-set"&&(n.src=n.bg_set))}return n}_initWithFirstElementWithInfo(e){const t=e.find(n=>n.elementInfo!==null&&(n.elementInfo.src||n.elementInfo.srcset));if(!t){this.logger.logMessage("No LCP candidate found."),this.performanceImages=[];return}this.performanceImages=[{...t.elementInfo,label:"lcp"}]}_fillATFWithoutDuplications(e){e.forEach(({element:t,elementInfo:n})=>{this._isDuplicateImage(t)||!n||this.performanceImages.push({...n,label:"above-the-fold"})})}_isDuplicateImage(e){const t=this._getElementInfo(e);if(t===null)return!1;const n=t.type==="img"||t.type==="img-srcset"||t.type==="video",i=t.type==="bg-img"||t.type==="bg-img-set"||t.type==="picture";return(n||i)&&this.performanceImages.some(s=>s.src===t.src)}getResults(){return this.performanceImages}},E=w,_=class{constructor(e,t){this.config=e,this.logger=t,this.lazyRenderElements=[]}async run(){try{const e=this._getLazyRenderElements();e&&this._processElements(e)}catch(e){this.errorCode="script_error",this.logger.logMessage("Script Error: "+e)}}_getLazyRenderElements(){const e=document.querySelectorAll("[data-rocket-location-hash]"),t=this._getSvgUseTargets();return e.length<=0?[]:Array.from(e).filter(i=>this._skipElement(i)?!1:t.includes(i)?(this.logger.logColoredMessage(`Element skipped because of SVG: ${i.tagName}`,"orange"),!1):!0).map(i=>({element:i,depth:this._getElementDepth(i),distance:this._getElementDistance(i),hash:this._getLocationHash(i)}))}_getElementDepth(e){let t=0,n=e.parentElement;for(;n;)t++,n=n.parentElement;return t}_getElementDistance(e){const t=e.getBoundingClientRect(),n=window.pageYOffset||document.documentElement.scrollTop;return Math.max(0,t.top+n-d.getScreenHeight())}_skipElement(e){const t=this.config.skipStrings||["memex"];return!e||!e.id?!1:t.some(n=>e.id.toLowerCase().includes(n.toLowerCase()))}_shouldSkipElement(e,t){if(!e)return!1;for(let n=0;nparseFloat(n[r])<0);return(s||n.contentVisibility==="auto"||n.contentVisibility==="hidden")&&t.push({element:e,conflicts:[s&&"negative margin",n.contentVisibility==="auto"&&"content-visibility:auto",n.contentVisibility==="hidden"&&"content-visibility:hidden"].filter(Boolean)}),Array.from(e.children).forEach(r=>{const l=window.getComputedStyle(r),c=["marginTop","marginRight","marginBottom","marginLeft"].some(u=>parseFloat(l[u])<0);(c||l.position==="absolute"||l.position==="fixed")&&t.push({element:r,conflicts:[c&&"negative margin",l.position==="absolute"&&"position:absolute",l.position==="fixed"&&"position:fixed"].filter(Boolean)})}),t}_processElements(e){e.forEach(({element:t,depth:n,distance:i,hash:s})=>{if(this._shouldSkipElement(t,this.config.exclusions||[])||s==="No hash detected")return;const a=this._checkLcrConflict(t);if(a.length>0){this.logger.logMessage("Skipping element due to conflicts:",a);return}const r=t.parentElement&&this._getElementDistance(t.parentElement)=this.config.lrc_threshold,l=r?"green":i===0?"red":"";this.logger.logColoredMessage(`${" ".repeat(n)}${t.tagName} (Depth: ${n}, Distance from viewport bottom: ${i}px)`,l),this.logger.logColoredMessage(`${" ".repeat(n)}Location hash: ${s}`,l),this.logger.logColoredMessage(`${" ".repeat(n)}Dimensions Client Height: ${t.clientHeight}`,l),r&&(this.lazyRenderElements.push(s),this.logger.logMessage(`Element pushed with hash: ${s}`))})}_getXPath(e){return e&&e.id!==""?`//*[@id="${e.id}"]`:this._getElementXPath(e)}_getElementXPath(e){if(e===document.body)return"/html/body";const t=this._getElementPosition(e);return`${this._getElementXPath(e.parentNode)}/${e.nodeName.toLowerCase()}[${t}]`}_getElementPosition(e){let t=1,n=e.previousElementSibling;for(;n;)n.nodeName===e.nodeName&&t++,n=n.previousElementSibling;return t}_getLocationHash(e){return e.hasAttribute("data-rocket-location-hash")?e.getAttribute("data-rocket-location-hash"):"No hash detected"}_getSvgUseTargets(){const e=document.querySelectorAll("use"),t=new Set;return e.forEach(n=>{let i=n.parentElement;for(;i&&i!==document.body;)t.add(i),i=i.parentElement}),Array.from(t)}getResults(){return this.lazyRenderElements}},v=_,F=class b{constructor(t,n){this.config=t,this.logger=n,this.aboveTheFoldFonts=[]}static FONT_FILE_REGEX=/\.(woff2?|ttf|otf|eot)(\?.*)?$/i;isSystemFont(t){return new Set(this.config.system_fonts).has(t)}isElementVisible(t){const n=window.getComputedStyle(t),i=t.getBoundingClientRect();return!(n.display==="none"||n.visibility==="hidden"||n.opacity==="0"||i.width===0||i.height===0)}cleanUrl(t){try{return t=t.split("?")[0].split("#")[0],new URL(t,window.location.href).href}catch{return t}}getNetworkLoadedFonts(){return new Map(window.performance.getEntriesByType("resource").filter(t=>b.FONT_FILE_REGEX.test(t.name)).map(t=>[this.cleanUrl(t.name),t.name]))}getFontFaceRules(){const t={};return Array.from(document.styleSheets).forEach(n=>{try{Array.from(n.cssRules||[]).forEach(i=>{if(i instanceof CSSFontFaceRule){const s=i.style.getPropertyValue("src"),a=i.style.getPropertyValue("font-family").replace(/['"]+/g,"").trim(),r=i.style.getPropertyValue("font-weight")||"400",l=i.style.getPropertyValue("font-style")||"normal";t[a]||(t[a]={urls:[],variations:new Set}),(s.match(/url\(['"]?([^'"]+)['"]?\)/g)||[]).forEach(c=>{let g=c.match(/url\(['"]?([^'"]+)['"]?\)/)[1];n.href&&(g=new URL(g,n.href).href);const u=this.cleanUrl(g);t[a].urls.includes(u)||(t[a].urls.push(u),t[a].variations.add(JSON.stringify({weight:r,style:l})))})}})}catch(i){this.logger.logMessage(i)}}),Object.values(t).forEach(n=>{n.variations=Array.from(n.variations).map(i=>JSON.parse(i))}),t}isElementAboveFold(t){if(!this.isElementVisible(t))return!1;const n=t.getBoundingClientRect(),i=window.pageYOffset||document.documentElement.scrollTop,s=n.top+i,a=window.innerHeight||document.documentElement.clientHeight;return s<=a}async run(){await document.fonts.ready;const t=this.getNetworkLoadedFonts(),n=this.getFontFaceRules(),i=new Map,s=this.config.font_data,a=await this.processExternalFonts(s);Array.from(document.getElementsByTagName("*")).filter(o=>this.isElementAboveFold(o)).forEach(o=>{const c=(g,u=null)=>{if(!g||!this.isElementVisible(o))return;const h=g.fontFamily.split(",")[0].replace(/['"]+/g,"").trim();(u?g.content!=="none"&&g.content!=='""':o.textContent.trim())&&!this.isSystemFont(h)&&n[h]&&(i.has(h)||i.set(h,{elements:new Set,urls:n[h].urls,variations:n[h].variations}),i.get(h).elements.add(o))};try{c(window.getComputedStyle(o)),["::before","::after"].forEach(g=>{c(window.getComputedStyle(o,g),g)})}catch(g){this.logger.logMessage("Error processing element:",g)}});const l=this.summarizeMatches(a,i,t);if(!Object.keys(l.allFonts).length&&!Object.keys(l.externalFonts).length&&!Object.keys(l.hostedFonts).length){this.logger.logMessage("No fonts found above the fold.");return}this.logger.logMessage("Above the fold fonts:",l),this.aboveTheFoldFonts=[...new Set(Object.values(l.allFonts).flatMap(o=>o.variations.map(c=>c.url)))]}summarizeMatches(t,n,i){const s={},a={};return n.size>0&&n.forEach((r,l)=>{if(r.variations){const o=Array.from(r.elements),c=o.filter(u=>this.isElementAboveFold(u)),g=o.filter(u=>!this.isElementAboveFold(u));if(s[l]||(s[l]={type:"hosted",variations:[],elementCount:{aboveFold:c.length,belowFold:g.length,total:o.length},urlCount:{aboveFold:new Set,belowFold:new Set}}),r.variations.forEach(u=>{let h=null;for(const f of r.urls){const p=this.cleanUrl(f);if(i.has(p)){h=i.get(p);break}}s[l].variations.push({weight:u.weight,style:u.style,url:h||"File not found",elementCount:{aboveFold:c.length,belowFold:g.length,total:o.length}}),h&&(c.length>0&&s[l].urlCount.aboveFold.add(h),g.length>0&&s[l].urlCount.belowFold.add(h))}),!Object.prototype.hasOwnProperty.call(s,l))return;a[l]={variations:s[l].variations,elementCount:{...s[l].elementCount},urlCount:{...s[l].urlCount}}}}),Object.keys(t).length>0&&Object.entries(t).forEach(([r,l])=>{l.elementCount.aboveFold>0&&l.variations.forEach(o=>{s[o.family]||(s[o.family]={type:"external",variations:[],elementCount:{aboveFold:0,belowFold:0,total:0},urlCount:{aboveFold:new Set,belowFold:new Set}});const c=Array.from(l.elements).filter(u=>this.isElementAboveFold(u)),g=Array.from(l.elements).filter(u=>!this.isElementAboveFold(u));s[o.family].variations.push({weight:o.weight,style:o.style,url:r,elementCount:{aboveFold:c.length,belowFold:g.length,total:l.elements.length}}),s[o.family].elementCount.aboveFold+=c.length,s[o.family].elementCount.belowFold+=g.length,s[o.family].elementCount.total+=l.elements.length,c.length>0&&s[o.family].urlCount.aboveFold.add(r),g.length>0&&s[o.family].urlCount.belowFold.add(r)})}),Object.values(s).forEach(r=>{r.urlCount={aboveFold:r.urlCount.aboveFold.size,belowFold:r.urlCount.belowFold.size,total:new Set([...r.urlCount.aboveFold,...r.urlCount.belowFold]).size}}),Object.values(a).forEach(r=>{r.urlCount.aboveFold instanceof Set&&(r.urlCount={aboveFold:r.urlCount.aboveFold.size,belowFold:r.urlCount.belowFold.size,total:new Set([...r.urlCount.aboveFold,...r.urlCount.belowFold]).size})}),{externalFonts:Object.fromEntries(Object.entries(t).filter(r=>r[1].elementCount.aboveFold>0)),hostedFonts:a,allFonts:s}}async processExternalFonts(t){const n=new Map,i=Array.from(document.getElementsByTagName("*")).filter(r=>this.isElementAboveFold(r)),s=new Map;Object.entries(t).forEach(([r,l])=>{l.forEach(o=>{const c=`${o.family}|${o.weight}|${o.style}`;s.set(c,{url:r,...o})})});const a=r=>{const l=r.fontFamily.split(",")[0].replace(/['"]+/g,"").trim(),o=r.fontWeight,c=r.fontStyle,g=`${l}|${o}|${c}`;let u=s.get(g);if(!u&&o!=="400"){const h=`${l}|400|${c}`;u=s.get(h)}return u};return i.forEach(r=>{if(r.textContent.trim()){const l=window.getComputedStyle(r),o=a(l);o&&(n.has(o.url)||n.set(o.url,{elements:new Set,variations:new Set}),n.get(o.url).elements.add(r),n.get(o.url).variations.add(JSON.stringify({family:o.family,weight:o.weight,style:o.style})))}["::before","::after"].forEach(l=>{const o=window.getComputedStyle(r,l);if(o.content!=="none"&&o.content!=='""'){const c=a(o);c&&(n.has(c.url)||n.set(c.url,{elements:new Set,variations:new Set}),n.get(c.url).elements.add(r),n.get(c.url).variations.add(JSON.stringify({family:c.family,weight:c.weight,style:c.style})))}})}),Object.fromEntries(Array.from(n.entries()).map(([r,l])=>[r,{elementCount:{aboveFold:Array.from(l.elements).filter(o=>this.isElementAboveFold(o)).length,total:l.elements.size},variations:Array.from(l.variations).map(o=>JSON.parse(o)),elements:Array.from(l.elements)}]))}getResults(){return this.aboveTheFoldFonts}},C=F,S=class{constructor(e,t){this.logger=t,this.result=[],this.excludedPatterns=e.preconnect_external_domain_exclusions,this.eligibleElements=e.preconnect_external_domain_elements,this.matchedItems=new Set,this.excludedItems=new Set}async run(){document.querySelectorAll(`${this.eligibleElements.join(", ")}[src], ${this.eligibleElements.join(", ")}[href], ${this.eligibleElements.join(", ")}[rel], ${this.eligibleElements.join(", ")}[type]`).forEach(t=>this.processElement(t)),this.logger.logMessage({matchedItems:this.getMatchedItems(),excludedItems:Array.from(this.excludedItems)})}processElement(e){try{const t=new URL(e.src||e.href||"",location.href);if(this.isExcludedByAttribute(e)){this.excludedItems.add(this.createExclusionObject(t,e,"attribute"));return}if(this.isExcludedByDomain(t)){this.excludedItems.add(this.createExclusionObject(t,e,"domain"));return}this.isExternalDomain(t)&&(this.matchedItems.add(`${t.hostname}-${e.tagName.toLowerCase()}`),this.result=[...new Set(this.result.concat(t.hostname))])}catch(t){this.logger.logMessage(t)}}isExcludedByAttribute(e){return this.excludedPatterns.some(t=>t.type==="attribute"&&e.getAttribute(t.key)===t.value)}isExcludedByDomain(e){return this.excludedPatterns.some(t=>t.type==="domain"&&e.hostname.includes(t.value))}isExternalDomain(e){return e.hostname!==location.hostname&&e.hostname}createExclusionObject(e,t,n){const i=this.excludedPatterns.find(a=>n==="attribute"&&t.getAttribute(a.key)===a.value||n==="domain"&&e.hostname.includes(a.value));let s=n==="attribute"?`${i.key}=${i.value}`:`domain-partial=${i.value}`;return{domain:e.hostname,elementType:t.tagName.toLowerCase(),reason:s}}getMatchedItems(){return Array.from(this.matchedItems).map(e=>{const t=e.lastIndexOf("-");return[e.substring(0,t),e.substring(t+1)]})}getResults(){return this.result}},B=S,x=class{constructor(e){this.enabled=e}logMessage(e,t=""){if(this.enabled){if(t!==""){console.log(e,t);return}console.log(e)}}logColoredMessage(e,t="green"){this.enabled&&console.log(`%c${e}`,`color: ${t};`)}},I=x,M=class{constructor(e){this.config=e,this.lcpBeacon=null,this.lrcBeacon=null,this.preloadFontsBeacon=null,this.preconnectExternalDomainBeacon=null,this.infiniteLoopId=null,this.errorCode="",this.logger=new I(this.config.debug)}async init(){if(this.scriptTimer=new Date,!await this._isValidPreconditions()){this._finalize();return}if(d.isPageScrolled()){this.logger.logMessage("Bailing out because the page has been scrolled"),this._finalize();return}this.infiniteLoopId=setTimeout(()=>{this._handleInfiniteLoop()},1e4);const e=await this._getGeneratedBefore(),t=this.config.status.atf&&(e===!1||e.lcp===!1),n=this.config.status.lrc&&(e===!1||e.lrc===!1),i=this.config.status.preload_fonts&&(e===!1||e.preload_fonts===!1),s=this.config.status.preconnect_external_domain&&(e===!1||e.preconnect_external_domain===!1);t?(this.lcpBeacon=new E(this.config,this.logger),await this.lcpBeacon.run()):this.logger.logMessage("Not running BeaconLcp because data is already available or feature is disabled"),n?(this.lrcBeacon=new v(this.config,this.logger),await this.lrcBeacon.run()):this.logger.logMessage("Not running BeaconLrc because data is already available or feature is disabled"),i?(this.preloadFontsBeacon=new C(this.config,this.logger),await this.preloadFontsBeacon.run()):this.logger.logMessage("Not running BeaconPreloadFonts because data is already available or feature is disabled"),s?(this.preconnectExternalDomainBeacon=new B(this.config,this.logger),await this.preconnectExternalDomainBeacon.run()):this.logger.logMessage("Not running BeaconPreconnectExternalDomain because data is already available or feature is disabled"),t||n||i||s?this._saveFinalResultIntoDB():(this.logger.logMessage("Not saving results into DB as no beacon features ran."),this._finalize())}async _isValidPreconditions(){const e={width:this.config.width_threshold,height:this.config.height_threshold};return d.isNotValidScreensize(this.config.is_mobile,e)?(this.logger.logMessage("Bailing out because screen size is not acceptable"),!1):!0}async _getGeneratedBefore(){if(!d.isPageCached())return!1;let e=new FormData;return e.append("action","rocket_check_beacon"),e.append("rocket_beacon_nonce",this.config.nonce),e.append("url",this.config.url),e.append("is_mobile",this.config.is_mobile),(await fetch(this.config.ajax_url,{method:"POST",credentials:"same-origin",body:e}).then(n=>n.json())).data}_saveFinalResultIntoDB(){const e={lcp:this.lcpBeacon?this.lcpBeacon.getResults():null,lrc:this.lrcBeacon?this.lrcBeacon.getResults():null,preload_fonts:this.preloadFontsBeacon?this.preloadFontsBeacon.getResults():null,preconnect_external_domain:this.preconnectExternalDomainBeacon?this.preconnectExternalDomainBeacon.getResults():null},t=new FormData;t.append("action","rocket_beacon"),t.append("rocket_beacon_nonce",this.config.nonce),t.append("url",this.config.url),t.append("is_mobile",this.config.is_mobile),t.append("status",this._getFinalStatus()),t.append("results",JSON.stringify(e)),fetch(this.config.ajax_url,{method:"POST",credentials:"same-origin",body:t,headers:{"wpr-saas-no-intercept":!0}}).then(n=>n.json()).then(n=>{this.logger.logMessage(n.data.lcp)}).catch(n=>{this.logger.logMessage(n)}).finally(()=>{this._finalize()})}_getFinalStatus(){return this.errorCode!==""?this.errorCode:10<=(new Date-this.scriptTimer)/1e3?"timeout":"success"}_handleInfiniteLoop(){this._saveFinalResultIntoDB()}_finalize(){document.querySelector('[data-name="wpr-wpr-beacon"]').setAttribute("beacon-completed","true"),clearTimeout(this.infiniteLoopId)}},m=M;(e=>{if(!e)return;const t=new m(e);if(document.readyState!=="loading"){setTimeout(()=>{t.init()},e.delay);return}document.addEventListener("DOMContentLoaded",()=>{setTimeout(()=>{t.init()},e.delay)})})(window.rocket_beacon_data);var A=m})(); +(()=>{var p=class{static getScreenWidth(){return window.innerWidth||document.documentElement.clientWidth}static getScreenHeight(){return window.innerHeight||document.documentElement.clientHeight}static isNotValidScreensize(e,t){const n=this.getScreenWidth(),o=this.getScreenHeight(),i=e&&(n>t.width||o>t.height),s=!e&&(n=0&&e.right>=0&&e.top<=(window.innerHeight||document.documentElement.clientHeight)&&e.left<=(window.innerWidth||document.documentElement.clientWidth)}static isPageScrolled(){return window.pageYOffset>0||document.documentElement.scrollTop>0}},u=p,b=class{constructor(e,t){this.config=e,this.performanceImages=[],this.logger=t}async run(){try{const e=this._generateLcpCandidates(1/0);e&&(this._initWithFirstElementWithInfo(e),this._fillATFWithoutDuplications(e))}catch(e){this.errorCode="script_error",this.logger.logMessage("Script Error: "+e)}}_generateLcpCandidates(e){const t=document.querySelectorAll(this.config.elements);return t.length<=0?[]:Array.from(t).map(i=>{if(i.nodeName.toLowerCase()==="img"&&i.parentElement.nodeName.toLowerCase()==="picture")return null;let s;if(i.nodeName.toLowerCase()==="picture"){const l=i.querySelector("img");if(l)s=l.getBoundingClientRect();else return null}else s=i.getBoundingClientRect();return{element:i,rect:s}}).filter(i=>i!==null).filter(i=>i.rect.width>0&&i.rect.height>0&&u.isIntersecting(i.rect)).map(i=>({item:i,area:this._getElementArea(i.rect),elementInfo:this._getElementInfo(i.element)})).sort((i,s)=>s.area-i.area).slice(0,e).map(i=>({element:i.item.element,elementInfo:i.elementInfo}))}_getElementArea(e){const t=Math.min(e.width,(window.innerWidth||document.documentElement.clientWidth)-e.left),n=Math.min(e.height,(window.innerHeight||document.documentElement.clientHeight)-e.top);return t*n}_getElementInfo(e){const t=e.nodeName.toLowerCase(),n={type:"",src:"",srcset:"",sizes:"",sources:[],bg_set:[],current_src:""},o=/url\(\s*?['"]?\s*?(.+?)\s*?["']?\s*?\)/ig;if(t==="img"&&e.srcset)n.type="img-srcset",n.src=e.src,n.srcset=e.srcset,n.sizes=e.sizes,n.current_src=e.currentSrc;else if(t==="img")n.type="img",n.src=e.src,n.current_src=e.currentSrc;else if(t==="video"){n.type="img";const i=e.querySelector("source");n.src=e.poster||(i?i.src:""),n.current_src=n.src}else if(t==="svg"){const i=e.querySelector("image");i&&(n.type="img",n.src=i.getAttribute("href")||"",n.current_src=n.src)}else if(t==="picture"){n.type="picture";const i=e.querySelector("img");n.src=i?i.src:"",n.sources=Array.from(e.querySelectorAll("source")).map(s=>({srcset:s.srcset||"",media:s.media||"",type:s.type||"",sizes:s.sizes||""}))}else{const s=[window.getComputedStyle(e,null).getPropertyValue("background-image"),getComputedStyle(e,":after").getPropertyValue("background-image"),getComputedStyle(e,":before").getPropertyValue("background-image")].filter(a=>a!=="none");if(s.length===0)return null;const l=s[0];if(n.type="bg-img",l.includes("image-set(")&&(n.type="bg-img-set"),!l||l===""||l.includes("data:image"))return null;const r=[...l.matchAll(o)];if(n.bg_set=r.map(a=>a[1]?{src:a[1].trim()+(a[2]?" "+a[2].trim():"")}:{}),n.bg_set.every(a=>a.src==="")&&(n.bg_set=r.map(a=>a[1]?{src:a[1].trim()}:{})),n.bg_set.length<=0)return null;n.bg_set.length>0&&(n.src=n.bg_set[0].src,n.type==="bg-img-set"&&(n.src=n.bg_set))}return n}_initWithFirstElementWithInfo(e){const t=e.find(n=>n.elementInfo!==null&&(n.elementInfo.src||n.elementInfo.srcset));if(!t){this.logger.logMessage("No LCP candidate found."),this.performanceImages=[];return}this.performanceImages=[{...t.elementInfo,label:"lcp"}]}_fillATFWithoutDuplications(e){e.forEach(({element:t,elementInfo:n})=>{this._isDuplicateImage(t)||!n||this.performanceImages.push({...n,label:"above-the-fold"})})}_isDuplicateImage(e){const t=this._getElementInfo(e);if(t===null)return!1;const n=t.type==="img"||t.type==="img-srcset"||t.type==="video",o=t.type==="bg-img"||t.type==="bg-img-set"||t.type==="picture";return(n||o)&&this.performanceImages.some(i=>i.src===t.src)}getResults(){return this.performanceImages}},y=b,w=class{constructor(e,t){this.config=e,this.logger=t,this.lazyRenderElements=[]}async run(){try{const e=this._getLazyRenderElements();e&&this._processElements(e)}catch(e){this.errorCode="script_error",this.logger.logMessage("Script Error: "+e)}}_getLazyRenderElements(){const e=document.querySelectorAll("[data-rocket-location-hash]"),t=this._getSvgUseTargets();return e.length<=0?[]:Array.from(e).filter(o=>this._skipElement(o)?!1:t.includes(o)?(this.logger.logColoredMessage(`Element skipped because of SVG: ${o.tagName}`,"orange"),!1):!0).map(o=>({element:o,depth:this._getElementDepth(o),distance:this._getElementDistance(o),hash:this._getLocationHash(o)}))}_getElementDepth(e){let t=0,n=e.parentElement;for(;n;)t++,n=n.parentElement;return t}_getElementDistance(e){const t=e.getBoundingClientRect(),n=window.pageYOffset||document.documentElement.scrollTop;return Math.max(0,t.top+n-u.getScreenHeight())}_skipElement(e){const t=this.config.skipStrings||["memex"];return!e||!e.id?!1:t.some(n=>e.id.toLowerCase().includes(n.toLowerCase()))}_shouldSkipElement(e,t){if(!e)return!1;for(let n=0;nparseFloat(n[l])<0);return(i||n.contentVisibility==="auto"||n.contentVisibility==="hidden")&&t.push({element:e,conflicts:[i&&"negative margin",n.contentVisibility==="auto"&&"content-visibility:auto",n.contentVisibility==="hidden"&&"content-visibility:hidden"].filter(Boolean)}),Array.from(e.children).forEach(l=>{const r=window.getComputedStyle(l),c=["marginTop","marginRight","marginBottom","marginLeft"].some(h=>parseFloat(r[h])<0);(c||r.position==="absolute"||r.position==="fixed")&&t.push({element:l,conflicts:[c&&"negative margin",r.position==="absolute"&&"position:absolute",r.position==="fixed"&&"position:fixed"].filter(Boolean)})}),t}_processElements(e){e.forEach(({element:t,depth:n,distance:o,hash:i})=>{if(this._shouldSkipElement(t,this.config.exclusions||[])||i==="No hash detected")return;const s=this._checkLcrConflict(t);if(s.length>0){this.logger.logMessage("Skipping element due to conflicts:",s);return}const l=t.parentElement&&this._getElementDistance(t.parentElement)=this.config.lrc_threshold,r=l?"green":o===0?"red":"";this.logger.logColoredMessage(`${" ".repeat(n)}${t.tagName} (Depth: ${n}, Distance from viewport bottom: ${o}px)`,r),this.logger.logColoredMessage(`${" ".repeat(n)}Location hash: ${i}`,r),this.logger.logColoredMessage(`${" ".repeat(n)}Dimensions Client Height: ${t.clientHeight}`,r),l&&(this.lazyRenderElements.push(i),this.logger.logMessage(`Element pushed with hash: ${i}`))})}_getXPath(e){return e&&e.id!==""?`//*[@id="${e.id}"]`:this._getElementXPath(e)}_getElementXPath(e){if(e===document.body)return"/html/body";const t=this._getElementPosition(e);return`${this._getElementXPath(e.parentNode)}/${e.nodeName.toLowerCase()}[${t}]`}_getElementPosition(e){let t=1,n=e.previousElementSibling;for(;n;)n.nodeName===e.nodeName&&t++,n=n.previousElementSibling;return t}_getLocationHash(e){return e.hasAttribute("data-rocket-location-hash")?e.getAttribute("data-rocket-location-hash"):"No hash detected"}_getSvgUseTargets(){const e=document.querySelectorAll("use"),t=new Set;return e.forEach(n=>{let o=n.parentElement;for(;o&&o!==document.body;)t.add(o),o=o.parentElement}),Array.from(t)}getResults(){return this.lazyRenderElements}},E=w,_=class{constructor(e,t){this.config=e,this.logger=t,this.aboveTheFoldFonts=[];const n=(Array.isArray(this.config.processed_extensions)&&this.config.processed_extensions.length>0?this.config.processed_extensions:["woff","woff2","ttf"]).map(o=>o.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")).join("|");this.FONT_FILE_REGEX=new RegExp(`\\.(${n})(\\?.*)?$`,"i")}isSystemFont(e){return new Set(this.config.system_fonts).has(e)}isElementVisible(e){const t=window.getComputedStyle(e),n=e.getBoundingClientRect();return!(t.display==="none"||t.visibility==="hidden"||t.opacity==="0"||n.width===0||n.height===0)}cleanUrl(e){try{return e=e.split("?")[0].split("#")[0],new URL(e,window.location.href).href}catch{return e}}getNetworkLoadedFonts(){return new Map(window.performance.getEntriesByType("resource").filter(e=>this.FONT_FILE_REGEX.test(e.name)).map(e=>[this.cleanUrl(e.name),e.name]))}getFontFaceRules(){const e={};return Array.from(document.styleSheets).forEach(t=>{try{Array.from(t.cssRules||[]).forEach(n=>{if(n instanceof CSSFontFaceRule){const o=n.style.getPropertyValue("src"),i=n.style.getPropertyValue("font-family").replace(/['"]+/g,"").trim(),s=n.style.getPropertyValue("font-weight")||"400",l=n.style.getPropertyValue("font-style")||"normal";e[i]||(e[i]={urls:[],variations:new Set}),(o.match(/url\(['"]?([^'"]+)['"]?\)/g)||[]).forEach(a=>{let c=a.match(/url\(['"]?([^'"]+)['"]?\)/)[1];t.href&&(c=new URL(c,t.href).href);const g=this.cleanUrl(c);e[i].urls.includes(g)||(e[i].urls.push(g),e[i].variations.add(JSON.stringify({weight:s,style:l})))})}})}catch(n){this.logger.logMessage(n)}}),Object.values(e).forEach(t=>{t.variations=Array.from(t.variations).map(n=>JSON.parse(n))}),e}isElementAboveFold(e){if(!this.isElementVisible(e))return!1;const t=e.getBoundingClientRect(),n=window.pageYOffset||document.documentElement.scrollTop,o=t.top+n,i=window.innerHeight||document.documentElement.clientHeight;return o<=i}async run(){await document.fonts.ready;const e=this.getNetworkLoadedFonts(),t=this.getFontFaceRules(),n=new Map,o=this.config.font_data,i=await this.processExternalFonts(o);Array.from(document.getElementsByTagName("*")).filter(r=>this.isElementAboveFold(r)).forEach(r=>{const a=(c,g=null)=>{if(!c||!this.isElementVisible(r))return;const h=c.fontFamily.split(",")[0].replace(/['"]+/g,"").trim();(g?c.content!=="none"&&c.content!=='""':r.textContent.trim())&&!this.isSystemFont(h)&&t[h]&&(n.has(h)||n.set(h,{elements:new Set,urls:t[h].urls,variations:t[h].variations}),n.get(h).elements.add(r))};try{a(window.getComputedStyle(r)),["::before","::after"].forEach(c=>{a(window.getComputedStyle(r,c),c)})}catch(c){this.logger.logMessage("Error processing element:",c)}});const l=this.summarizeMatches(i,n,e);if(!Object.keys(l.allFonts).length&&!Object.keys(l.externalFonts).length&&!Object.keys(l.hostedFonts).length){this.logger.logMessage("No fonts found above the fold.");return}this.logger.logMessage("Above the fold fonts:",l),this.aboveTheFoldFonts=[...new Set(Object.values(l.allFonts).flatMap(r=>r.variations.map(a=>a.url)))]}summarizeMatches(e,t,n){const o={},i={};return t.size>0&&t.forEach((s,l)=>{if(s.variations){const r=Array.from(s.elements),a=r.filter(g=>this.isElementAboveFold(g)),c=r.filter(g=>!this.isElementAboveFold(g));if(o[l]||(o[l]={type:"hosted",variations:[],elementCount:{aboveFold:a.length,belowFold:c.length,total:r.length},urlCount:{aboveFold:new Set,belowFold:new Set}}),s.variations.forEach(g=>{let h=null;for(const m of s.urls){const f=this.cleanUrl(m);if(n.has(f)){h=n.get(f);break}}o[l].variations.push({weight:g.weight,style:g.style,url:h||"File not found",elementCount:{aboveFold:a.length,belowFold:c.length,total:r.length}}),h&&(a.length>0&&o[l].urlCount.aboveFold.add(h),c.length>0&&o[l].urlCount.belowFold.add(h))}),!Object.prototype.hasOwnProperty.call(o,l))return;i[l]={variations:o[l].variations,elementCount:{...o[l].elementCount},urlCount:{...o[l].urlCount}}}}),Object.keys(e).length>0&&Object.entries(e).forEach(([s,l])=>{l.elementCount.aboveFold>0&&l.variations.forEach(r=>{o[r.family]||(o[r.family]={type:"external",variations:[],elementCount:{aboveFold:0,belowFold:0,total:0},urlCount:{aboveFold:new Set,belowFold:new Set}});const a=Array.from(l.elements).filter(g=>this.isElementAboveFold(g)),c=Array.from(l.elements).filter(g=>!this.isElementAboveFold(g));o[r.family].variations.push({weight:r.weight,style:r.style,url:s,elementCount:{aboveFold:a.length,belowFold:c.length,total:l.elements.length}}),o[r.family].elementCount.aboveFold+=a.length,o[r.family].elementCount.belowFold+=c.length,o[r.family].elementCount.total+=l.elements.length,a.length>0&&o[r.family].urlCount.aboveFold.add(s),c.length>0&&o[r.family].urlCount.belowFold.add(s)})}),Object.values(o).forEach(s=>{s.urlCount={aboveFold:s.urlCount.aboveFold.size,belowFold:s.urlCount.belowFold.size,total:new Set([...s.urlCount.aboveFold,...s.urlCount.belowFold]).size}}),Object.values(i).forEach(s=>{s.urlCount.aboveFold instanceof Set&&(s.urlCount={aboveFold:s.urlCount.aboveFold.size,belowFold:s.urlCount.belowFold.size,total:new Set([...s.urlCount.aboveFold,...s.urlCount.belowFold]).size})}),{externalFonts:Object.fromEntries(Object.entries(e).filter(s=>s[1].elementCount.aboveFold>0)),hostedFonts:i,allFonts:o}}async processExternalFonts(e){const t=new Map,n=Array.from(document.getElementsByTagName("*")).filter(s=>this.isElementAboveFold(s)),o=new Map;Object.entries(e).forEach(([s,l])=>{l.forEach(r=>{const a=`${r.family}|${r.weight}|${r.style}`;o.set(a,{url:s,...r})})});const i=s=>{const l=s.fontFamily.split(",")[0].replace(/['"]+/g,"").trim(),r=s.fontWeight,a=s.fontStyle,c=`${l}|${r}|${a}`;let g=o.get(c);if(!g&&r!=="400"){const h=`${l}|400|${a}`;g=o.get(h)}return g};return n.forEach(s=>{if(s.textContent.trim()){const l=window.getComputedStyle(s),r=i(l);r&&(t.has(r.url)||t.set(r.url,{elements:new Set,variations:new Set}),t.get(r.url).elements.add(s),t.get(r.url).variations.add(JSON.stringify({family:r.family,weight:r.weight,style:r.style})))}["::before","::after"].forEach(l=>{const r=window.getComputedStyle(s,l);if(r.content!=="none"&&r.content!=='""'){const a=i(r);a&&(t.has(a.url)||t.set(a.url,{elements:new Set,variations:new Set}),t.get(a.url).elements.add(s),t.get(a.url).variations.add(JSON.stringify({family:a.family,weight:a.weight,style:a.style})))}})}),Object.fromEntries(Array.from(t.entries()).map(([s,l])=>[s,{elementCount:{aboveFold:Array.from(l.elements).filter(r=>this.isElementAboveFold(r)).length,total:l.elements.size},variations:Array.from(l.variations).map(r=>JSON.parse(r)),elements:Array.from(l.elements)}]))}getResults(){return this.aboveTheFoldFonts}},v=_,F=class{constructor(e,t){this.logger=t,this.result=[],this.excludedPatterns=e.preconnect_external_domain_exclusions,this.eligibleElements=e.preconnect_external_domain_elements,this.matchedItems=new Set,this.excludedItems=new Set}async run(){document.querySelectorAll(`${this.eligibleElements.join(", ")}[src], ${this.eligibleElements.join(", ")}[href], ${this.eligibleElements.join(", ")}[rel], ${this.eligibleElements.join(", ")}[type]`).forEach(t=>this.processElement(t)),this.logger.logMessage({matchedItems:this.getMatchedItems(),excludedItems:Array.from(this.excludedItems)})}processElement(e){try{const t=new URL(e.src||e.href||"",location.href);if(this.isExcludedByAttribute(e)){this.excludedItems.add(this.createExclusionObject(t,e,"attribute"));return}if(this.isExcludedByDomain(t)){this.excludedItems.add(this.createExclusionObject(t,e,"domain"));return}this.isExternalDomain(t)&&(this.matchedItems.add(`${t.hostname}-${e.tagName.toLowerCase()}`),this.result=[...new Set(this.result.concat(t.hostname))])}catch(t){this.logger.logMessage(t)}}isExcludedByAttribute(e){return this.excludedPatterns.some(t=>t.type==="attribute"&&e.getAttribute(t.key)===t.value)}isExcludedByDomain(e){return this.excludedPatterns.some(t=>t.type==="domain"&&e.hostname.includes(t.value))}isExternalDomain(e){return e.hostname!==location.hostname&&e.hostname}createExclusionObject(e,t,n){const o=this.excludedPatterns.find(s=>n==="attribute"&&t.getAttribute(s.key)===s.value||n==="domain"&&e.hostname.includes(s.value));let i=n==="attribute"?`${o.key}=${o.value}`:`domain-partial=${o.value}`;return{domain:e.hostname,elementType:t.tagName.toLowerCase(),reason:i}}getMatchedItems(){return Array.from(this.matchedItems).map(e=>{const t=e.lastIndexOf("-");return[e.substring(0,t),e.substring(t+1)]})}getResults(){return this.result}},C=F,S=class{constructor(e){this.enabled=e}logMessage(e,t=""){if(this.enabled){if(t!==""){console.log(e,t);return}console.log(e)}}logColoredMessage(e,t="green"){this.enabled&&console.log(`%c${e}`,`color: ${t};`)}},B=S,x=class{constructor(e){this.config=e,this.lcpBeacon=null,this.lrcBeacon=null,this.preloadFontsBeacon=null,this.preconnectExternalDomainBeacon=null,this.infiniteLoopId=null,this.errorCode="",this.logger=new B(this.config.debug)}async init(){if(this.scriptTimer=new Date,!await this._isValidPreconditions()){this._finalize();return}if(u.isPageScrolled()){this.logger.logMessage("Bailing out because the page has been scrolled"),this._finalize();return}this.infiniteLoopId=setTimeout(()=>{this._handleInfiniteLoop()},1e4);const e=await this._getGeneratedBefore(),t=this.config.status.atf&&(e===!1||e.lcp===!1),n=this.config.status.lrc&&(e===!1||e.lrc===!1),o=this.config.status.preload_fonts&&(e===!1||e.preload_fonts===!1),i=this.config.status.preconnect_external_domain&&(e===!1||e.preconnect_external_domain===!1);t?(this.lcpBeacon=new y(this.config,this.logger),await this.lcpBeacon.run()):this.logger.logMessage("Not running BeaconLcp because data is already available or feature is disabled"),n?(this.lrcBeacon=new E(this.config,this.logger),await this.lrcBeacon.run()):this.logger.logMessage("Not running BeaconLrc because data is already available or feature is disabled"),o?(this.preloadFontsBeacon=new v(this.config,this.logger),await this.preloadFontsBeacon.run()):this.logger.logMessage("Not running BeaconPreloadFonts because data is already available or feature is disabled"),i?(this.preconnectExternalDomainBeacon=new C(this.config,this.logger),await this.preconnectExternalDomainBeacon.run()):this.logger.logMessage("Not running BeaconPreconnectExternalDomain because data is already available or feature is disabled"),t||n||o||i?this._saveFinalResultIntoDB():(this.logger.logMessage("Not saving results into DB as no beacon features ran."),this._finalize())}async _isValidPreconditions(){const e={width:this.config.width_threshold,height:this.config.height_threshold};return u.isNotValidScreensize(this.config.is_mobile,e)?(this.logger.logMessage("Bailing out because screen size is not acceptable"),!1):!0}async _getGeneratedBefore(){if(!u.isPageCached())return!1;let e=new FormData;return e.append("action","rocket_check_beacon"),e.append("rocket_beacon_nonce",this.config.nonce),e.append("url",this.config.url),e.append("is_mobile",this.config.is_mobile),(await fetch(this.config.ajax_url,{method:"POST",credentials:"same-origin",body:e}).then(n=>n.json())).data}_saveFinalResultIntoDB(){const e={lcp:this.lcpBeacon?this.lcpBeacon.getResults():null,lrc:this.lrcBeacon?this.lrcBeacon.getResults():null,preload_fonts:this.preloadFontsBeacon?this.preloadFontsBeacon.getResults():null,preconnect_external_domain:this.preconnectExternalDomainBeacon?this.preconnectExternalDomainBeacon.getResults():null},t=new FormData;t.append("action","rocket_beacon"),t.append("rocket_beacon_nonce",this.config.nonce),t.append("url",this.config.url),t.append("is_mobile",this.config.is_mobile),t.append("status",this._getFinalStatus()),t.append("results",JSON.stringify(e)),fetch(this.config.ajax_url,{method:"POST",credentials:"same-origin",body:t,headers:{"wpr-saas-no-intercept":!0}}).then(n=>n.json()).then(n=>{this.logger.logMessage(n.data.lcp)}).catch(n=>{this.logger.logMessage(n)}).finally(()=>{this._finalize()})}_getFinalStatus(){return this.errorCode!==""?this.errorCode:10<=(new Date-this.scriptTimer)/1e3?"timeout":"success"}_handleInfiniteLoop(){this._saveFinalResultIntoDB()}_finalize(){document.querySelector('[data-name="wpr-wpr-beacon"]').setAttribute("beacon-completed","true"),clearTimeout(this.infiniteLoopId)}},d=x;(e=>{if(!e)return;const t=new d(e);if(document.readyState!=="loading"){setTimeout(()=>{t.init()},e.delay);return}document.addEventListener("DOMContentLoaded",()=>{setTimeout(()=>{t.init()},e.delay)})})(window.rocket_beacon_data);var I=d})(); //# sourceMappingURL=wpr-beacon.min.js.map diff --git a/assets/js/wpr-beacon.min.js.map b/assets/js/wpr-beacon.min.js.map index 3ca866231c..f87ee4d7fe 100644 --- a/assets/js/wpr-beacon.min.js.map +++ b/assets/js/wpr-beacon.min.js.map @@ -1,7 +1,7 @@ { "version": 3, "sources": ["wpr-beacon.js"], - "sourcesContent": ["(() => {\n // src/Utils.js\n var BeaconUtils = class {\n static getScreenWidth() {\n return window.innerWidth || document.documentElement.clientWidth;\n }\n static getScreenHeight() {\n return window.innerHeight || document.documentElement.clientHeight;\n }\n static isNotValidScreensize(is_mobile, threshold) {\n const screenWidth = this.getScreenWidth();\n const screenHeight = this.getScreenHeight();\n const isNotValidForMobile = is_mobile && (screenWidth > threshold.width || screenHeight > threshold.height);\n const isNotValidForDesktop = !is_mobile && (screenWidth < threshold.width || screenHeight < threshold.height);\n return isNotValidForMobile || isNotValidForDesktop;\n }\n static isPageCached() {\n const signature = document.documentElement.nextSibling && document.documentElement.nextSibling.data ? document.documentElement.nextSibling.data : \"\";\n return signature && signature.includes(\"Debug: cached\");\n }\n static isIntersecting(rect) {\n return rect.bottom >= 0 && rect.right >= 0 && rect.top <= (window.innerHeight || document.documentElement.clientHeight) && rect.left <= (window.innerWidth || document.documentElement.clientWidth);\n }\n static isPageScrolled() {\n return window.pageYOffset > 0 || document.documentElement.scrollTop > 0;\n }\n };\n var Utils_default = BeaconUtils;\n\n // src/BeaconLcp.js\n var BeaconLcp = class {\n constructor(config, logger) {\n this.config = config;\n this.performanceImages = [];\n this.logger = logger;\n }\n async run() {\n try {\n const above_the_fold_images = this._generateLcpCandidates(Infinity);\n if (above_the_fold_images) {\n this._initWithFirstElementWithInfo(above_the_fold_images);\n this._fillATFWithoutDuplications(above_the_fold_images);\n }\n } catch (err) {\n this.errorCode = \"script_error\";\n this.logger.logMessage(\"Script Error: \" + err);\n }\n }\n _generateLcpCandidates(count) {\n const lcpElements = document.querySelectorAll(this.config.elements);\n if (lcpElements.length <= 0) {\n return [];\n }\n const potentialCandidates = Array.from(lcpElements);\n const topCandidates = potentialCandidates.map((element) => {\n if (\"img\" === element.nodeName.toLowerCase() && \"picture\" === element.parentElement.nodeName.toLowerCase()) {\n return null;\n }\n let rect;\n if (\"picture\" === element.nodeName.toLowerCase()) {\n const imgElement = element.querySelector(\"img\");\n if (imgElement) {\n rect = imgElement.getBoundingClientRect();\n } else {\n return null;\n }\n } else {\n rect = element.getBoundingClientRect();\n }\n return {\n element,\n rect\n };\n }).filter((item) => item !== null).filter((item) => {\n return item.rect.width > 0 && item.rect.height > 0 && Utils_default.isIntersecting(item.rect);\n }).map((item) => ({\n item,\n area: this._getElementArea(item.rect),\n elementInfo: this._getElementInfo(item.element)\n })).sort((a, b) => b.area - a.area).slice(0, count);\n return topCandidates.map((candidate) => ({\n element: candidate.item.element,\n elementInfo: candidate.elementInfo\n }));\n }\n _getElementArea(rect) {\n const visibleWidth = Math.min(rect.width, (window.innerWidth || document.documentElement.clientWidth) - rect.left);\n const visibleHeight = Math.min(rect.height, (window.innerHeight || document.documentElement.clientHeight) - rect.top);\n return visibleWidth * visibleHeight;\n }\n _getElementInfo(element) {\n const nodeName = element.nodeName.toLowerCase();\n const element_info = {\n type: \"\",\n src: \"\",\n srcset: \"\",\n sizes: \"\",\n sources: [],\n bg_set: [],\n current_src: \"\"\n };\n const css_bg_url_rgx = /url\\(\\s*?['\"]?\\s*?(.+?)\\s*?[\"']?\\s*?\\)/ig;\n if (nodeName === \"img\" && element.srcset) {\n element_info.type = \"img-srcset\";\n element_info.src = element.src;\n element_info.srcset = element.srcset;\n element_info.sizes = element.sizes;\n element_info.current_src = element.currentSrc;\n } else if (nodeName === \"img\") {\n element_info.type = \"img\";\n element_info.src = element.src;\n element_info.current_src = element.currentSrc;\n } else if (nodeName === \"video\") {\n element_info.type = \"img\";\n const source = element.querySelector(\"source\");\n element_info.src = element.poster || (source ? source.src : \"\");\n element_info.current_src = element_info.src;\n } else if (nodeName === \"svg\") {\n const imageElement = element.querySelector(\"image\");\n if (imageElement) {\n element_info.type = \"img\";\n element_info.src = imageElement.getAttribute(\"href\") || \"\";\n element_info.current_src = element_info.src;\n }\n } else if (nodeName === \"picture\") {\n element_info.type = \"picture\";\n const img = element.querySelector(\"img\");\n element_info.src = img ? img.src : \"\";\n element_info.sources = Array.from(element.querySelectorAll(\"source\")).map((source) => ({\n srcset: source.srcset || \"\",\n media: source.media || \"\",\n type: source.type || \"\",\n sizes: source.sizes || \"\"\n }));\n } else {\n const computed_style = window.getComputedStyle(element, null);\n const bg_props = [\n computed_style.getPropertyValue(\"background-image\"),\n getComputedStyle(element, \":after\").getPropertyValue(\"background-image\"),\n getComputedStyle(element, \":before\").getPropertyValue(\"background-image\")\n ].filter((prop) => prop !== \"none\");\n if (bg_props.length === 0) {\n return null;\n }\n const full_bg_prop = bg_props[0];\n element_info.type = \"bg-img\";\n if (full_bg_prop.includes(\"image-set(\")) {\n element_info.type = \"bg-img-set\";\n }\n if (!full_bg_prop || full_bg_prop === \"\" || full_bg_prop.includes(\"data:image\")) {\n return null;\n }\n const matches = [...full_bg_prop.matchAll(css_bg_url_rgx)];\n element_info.bg_set = matches.map((m) => m[1] ? { src: m[1].trim() + (m[2] ? \" \" + m[2].trim() : \"\") } : {});\n if (element_info.bg_set.every((item) => item.src === \"\")) {\n element_info.bg_set = matches.map((m) => m[1] ? { src: m[1].trim() } : {});\n }\n if (element_info.bg_set.length <= 0) {\n return null;\n }\n if (element_info.bg_set.length > 0) {\n element_info.src = element_info.bg_set[0].src;\n if (element_info.type === \"bg-img-set\") {\n element_info.src = element_info.bg_set;\n }\n }\n }\n return element_info;\n }\n _initWithFirstElementWithInfo(elements) {\n const firstElementWithInfo = elements.find((item) => {\n return item.elementInfo !== null && (item.elementInfo.src || item.elementInfo.srcset);\n });\n if (!firstElementWithInfo) {\n this.logger.logMessage(\"No LCP candidate found.\");\n this.performanceImages = [];\n return;\n }\n this.performanceImages = [{\n ...firstElementWithInfo.elementInfo,\n label: \"lcp\"\n }];\n }\n _fillATFWithoutDuplications(elements) {\n elements.forEach(({ element, elementInfo }) => {\n if (this._isDuplicateImage(element) || !elementInfo) {\n return;\n }\n this.performanceImages.push({ ...elementInfo, label: \"above-the-fold\" });\n });\n }\n _isDuplicateImage(image) {\n const elementInfo = this._getElementInfo(image);\n if (elementInfo === null) {\n return false;\n }\n const isImageOrVideo = elementInfo.type === \"img\" || elementInfo.type === \"img-srcset\" || elementInfo.type === \"video\";\n const isBgImageOrPicture = elementInfo.type === \"bg-img\" || elementInfo.type === \"bg-img-set\" || elementInfo.type === \"picture\";\n return (isImageOrVideo || isBgImageOrPicture) && this.performanceImages.some((item) => item.src === elementInfo.src);\n }\n getResults() {\n return this.performanceImages;\n }\n };\n var BeaconLcp_default = BeaconLcp;\n\n // src/BeaconLrc.js\n var BeaconLrc = class {\n constructor(config, logger) {\n this.config = config;\n this.logger = logger;\n this.lazyRenderElements = [];\n }\n async run() {\n try {\n const elementsInView = this._getLazyRenderElements();\n if (elementsInView) {\n this._processElements(elementsInView);\n }\n } catch (err) {\n this.errorCode = \"script_error\";\n this.logger.logMessage(\"Script Error: \" + err);\n }\n }\n _getLazyRenderElements() {\n const elements = document.querySelectorAll(\"[data-rocket-location-hash]\");\n const svgUseTargets = this._getSvgUseTargets();\n if (elements.length <= 0) {\n return [];\n }\n const validElements = Array.from(elements).filter((element) => {\n if (this._skipElement(element)) {\n return false;\n }\n if (svgUseTargets.includes(element)) {\n this.logger.logColoredMessage(`Element skipped because of SVG: ${element.tagName}`, \"orange\");\n return false;\n }\n return true;\n });\n return validElements.map((element) => ({\n element,\n depth: this._getElementDepth(element),\n distance: this._getElementDistance(element),\n hash: this._getLocationHash(element)\n }));\n }\n _getElementDepth(element) {\n let depth = 0;\n let parent = element.parentElement;\n while (parent) {\n depth++;\n parent = parent.parentElement;\n }\n return depth;\n }\n _getElementDistance(element) {\n const rect = element.getBoundingClientRect();\n const scrollTop = window.pageYOffset || document.documentElement.scrollTop;\n return Math.max(0, rect.top + scrollTop - Utils_default.getScreenHeight());\n }\n _skipElement(element) {\n const skipStrings = this.config.skipStrings || [\"memex\"];\n if (!element || !element.id) return false;\n return skipStrings.some((str) => element.id.toLowerCase().includes(str.toLowerCase()));\n }\n _shouldSkipElement(element, exclusions) {\n if (!element) return false;\n for (let i = 0; i < exclusions.length; i++) {\n const [attribute, pattern] = exclusions[i];\n const attributeValue = element.getAttribute(attribute);\n if (attributeValue && new RegExp(pattern, \"i\").test(attributeValue)) {\n return true;\n }\n }\n return false;\n }\n _checkLcrConflict(element) {\n const conflictingElements = [];\n const computedStyle = window.getComputedStyle(element);\n const validMargins = [\"marginTop\", \"marginRight\", \"marginBottom\", \"marginLeft\"];\n const negativeMargins = validMargins.some((margin) => parseFloat(computedStyle[margin]) < 0);\n const currentElementConflicts = negativeMargins || computedStyle.contentVisibility === \"auto\" || computedStyle.contentVisibility === \"hidden\";\n if (currentElementConflicts) {\n conflictingElements.push({\n element,\n conflicts: [\n negativeMargins && \"negative margin\",\n computedStyle.contentVisibility === \"auto\" && \"content-visibility:auto\",\n computedStyle.contentVisibility === \"hidden\" && \"content-visibility:hidden\"\n ].filter(Boolean)\n });\n }\n Array.from(element.children).forEach((child) => {\n const childStyle = window.getComputedStyle(child);\n const validMargins2 = [\"marginTop\", \"marginRight\", \"marginBottom\", \"marginLeft\"];\n const childNegativeMargins = validMargins2.some((margin) => parseFloat(childStyle[margin]) < 0);\n const childConflicts = childNegativeMargins || childStyle.position === \"absolute\" || childStyle.position === \"fixed\";\n if (childConflicts) {\n conflictingElements.push({\n element: child,\n conflicts: [\n childNegativeMargins && \"negative margin\",\n childStyle.position === \"absolute\" && \"position:absolute\",\n childStyle.position === \"fixed\" && \"position:fixed\"\n ].filter(Boolean)\n });\n }\n });\n return conflictingElements;\n }\n _processElements(elements) {\n elements.forEach(({ element, depth, distance, hash }) => {\n if (this._shouldSkipElement(element, this.config.exclusions || [])) {\n return;\n }\n if (\"No hash detected\" === hash) {\n return;\n }\n const conflicts = this._checkLcrConflict(element);\n if (conflicts.length > 0) {\n this.logger.logMessage(\"Skipping element due to conflicts:\", conflicts);\n return;\n }\n const can_push_hash = element.parentElement && this._getElementDistance(element.parentElement) < this.config.lrc_threshold && distance >= this.config.lrc_threshold;\n const color = can_push_hash ? \"green\" : distance === 0 ? \"red\" : \"\";\n this.logger.logColoredMessage(`${\"\t\".repeat(depth)}${element.tagName} (Depth: ${depth}, Distance from viewport bottom: ${distance}px)`, color);\n this.logger.logColoredMessage(`${\"\t\".repeat(depth)}Location hash: ${hash}`, color);\n this.logger.logColoredMessage(`${\"\t\".repeat(depth)}Dimensions Client Height: ${element.clientHeight}`, color);\n if (can_push_hash) {\n this.lazyRenderElements.push(hash);\n this.logger.logMessage(`Element pushed with hash: ${hash}`);\n }\n });\n }\n _getXPath(element) {\n if (element && element.id !== \"\") {\n return `//*[@id=\"${element.id}\"]`;\n }\n return this._getElementXPath(element);\n }\n _getElementXPath(element) {\n if (element === document.body) {\n return \"/html/body\";\n }\n const position = this._getElementPosition(element);\n return `${this._getElementXPath(element.parentNode)}/${element.nodeName.toLowerCase()}[${position}]`;\n }\n _getElementPosition(element) {\n let pos = 1;\n let sibling = element.previousElementSibling;\n while (sibling) {\n if (sibling.nodeName === element.nodeName) {\n pos++;\n }\n sibling = sibling.previousElementSibling;\n }\n return pos;\n }\n _getLocationHash(element) {\n return element.hasAttribute(\"data-rocket-location-hash\") ? element.getAttribute(\"data-rocket-location-hash\") : \"No hash detected\";\n }\n _getSvgUseTargets() {\n const useElements = document.querySelectorAll(\"use\");\n const targets = /* @__PURE__ */ new Set();\n useElements.forEach((use) => {\n let parent = use.parentElement;\n while (parent && parent !== document.body) {\n targets.add(parent);\n parent = parent.parentElement;\n }\n });\n return Array.from(targets);\n }\n getResults() {\n return this.lazyRenderElements;\n }\n };\n var BeaconLrc_default = BeaconLrc;\n\n // src/BeaconPreloadFonts.js\n var BeaconPreloadFonts = class _BeaconPreloadFonts {\n constructor(config, logger) {\n this.config = config;\n this.logger = logger;\n this.aboveTheFoldFonts = [];\n }\n static FONT_FILE_REGEX = /\\.(woff2?|ttf|otf|eot)(\\?.*)?$/i;\n /**\n * Checks if a given font family is a system font.\n * \n * This method checks if the provided font family is part of the system fonts\n * defined in the configuration. It returns true if the font family is a system\n * font, and false otherwise.\n * \n * @param {string} fontFamily - The font family to check.\n * @returns {boolean} True if the font family is a system font, false otherwise.\n */\n isSystemFont(fontFamily) {\n const systemFonts = new Set(this.config.system_fonts);\n return systemFonts.has(fontFamily);\n }\n /**\n * Checks if an element is visible in the viewport.\n * \n * This method checks if the provided element is visible in the viewport by\n * considering its display, visibility, opacity, width, and height properties.\n * It returns true if the element is visible, and false otherwise.\n * \n * @param {Element} element - The element to check for visibility.\n * @returns {boolean} True if the element is visible, false otherwise.\n */\n isElementVisible(element) {\n const style = window.getComputedStyle(element);\n const rect = element.getBoundingClientRect();\n return !(style.display === \"none\" || style.visibility === \"hidden\" || style.opacity === \"0\" || rect.width === 0 || rect.height === 0);\n }\n /**\n * Cleans a URL by removing query parameters and fragments.\n * \n * This method takes a URL as input, removes any query parameters and fragments,\n * and returns the cleaned URL.\n * \n * @param {string} url - The URL to clean.\n * @returns {string} The cleaned URL.\n */\n cleanUrl(url) {\n try {\n url = url.split(\"?\")[0].split(\"#\")[0];\n return new URL(url, window.location.href).href;\n } catch (e) {\n return url;\n }\n }\n /**\n * Retrieves a map of network-loaded fonts.\n * \n * This method uses the Performance API to get all resource entries, filters out\n * the ones that match the font file regex, and maps them to their cleaned URLs.\n * \n * @returns {Map} A map where each key is a cleaned URL of a font file and\n * each value is the original URL of the font file.\n */\n getNetworkLoadedFonts() {\n return new Map(\n window.performance.getEntriesByType(\"resource\").filter((resource) => _BeaconPreloadFonts.FONT_FILE_REGEX.test(resource.name)).map((resource) => [this.cleanUrl(resource.name), resource.name])\n );\n }\n /**\n * Retrieves font-face rules from stylesheets.\n * \n * This method scans all stylesheets loaded on the page and collects\n * font-face rules, including their source URLs, font families, weights,\n * and styles. It returns an object containing the collected font data.\n * \n * @returns {Object} An object mapping font families to their respective\n * URLs and variations.\n */\n getFontFaceRules() {\n const stylesheetFonts = {};\n Array.from(document.styleSheets).forEach((sheet) => {\n try {\n Array.from(sheet.cssRules || []).forEach((rule) => {\n if (rule instanceof CSSFontFaceRule) {\n const src = rule.style.getPropertyValue(\"src\");\n const fontFamily = rule.style.getPropertyValue(\"font-family\").replace(/['\"]+/g, \"\").trim();\n const weight = rule.style.getPropertyValue(\"font-weight\") || \"400\";\n const style = rule.style.getPropertyValue(\"font-style\") || \"normal\";\n if (!stylesheetFonts[fontFamily]) {\n stylesheetFonts[fontFamily] = {\n urls: [],\n variations: /* @__PURE__ */ new Set()\n };\n }\n const urls = src.match(/url\\(['\"]?([^'\"]+)['\"]?\\)/g) || [];\n urls.forEach((urlMatch) => {\n let rawUrl = urlMatch.match(/url\\(['\"]?([^'\"]+)['\"]?\\)/)[1];\n if (sheet.href) {\n rawUrl = new URL(rawUrl, sheet.href).href;\n }\n const normalizedUrl = this.cleanUrl(rawUrl);\n if (!stylesheetFonts[fontFamily].urls.includes(normalizedUrl)) {\n stylesheetFonts[fontFamily].urls.push(normalizedUrl);\n stylesheetFonts[fontFamily].variations.add(JSON.stringify({\n weight,\n style\n }));\n }\n });\n }\n });\n } catch (e) {\n this.logger.logMessage(e);\n }\n });\n Object.values(stylesheetFonts).forEach((fontData) => {\n fontData.variations = Array.from(fontData.variations).map((v) => JSON.parse(v));\n });\n return stylesheetFonts;\n }\n /**\n * Checks if an element is above the fold (visible in the viewport without scrolling).\n * \n * @param {Element} element - The element to check.\n * @returns {boolean} True if the element is above the fold, false otherwise.\n */\n isElementAboveFold(element) {\n if (!this.isElementVisible(element)) return false;\n const rect = element.getBoundingClientRect();\n const scrollTop = window.pageYOffset || document.documentElement.scrollTop;\n const elementTop = rect.top + scrollTop;\n const foldPosition = window.innerHeight || document.documentElement.clientHeight;\n return elementTop <= foldPosition;\n }\n /**\n * Initiates the process of analyzing and summarizing font usage on the page.\n * This method fetches network-loaded fonts, stylesheet fonts, and external font pairs.\n * It then processes each element on the page to determine which fonts are used above the fold.\n * The results are summarized and logged.\n * \n * @returns {Promise} A promise that resolves when the analysis is complete.\n */\n async run() {\n await document.fonts.ready;\n const networkLoadedFonts = this.getNetworkLoadedFonts();\n const stylesheetFonts = this.getFontFaceRules();\n const hostedFonts = /* @__PURE__ */ new Map();\n const externalFontPairs = this.config.font_data;\n const externalFontsResults = await this.processExternalFonts(externalFontPairs);\n const elements = Array.from(document.getElementsByTagName(\"*\")).filter((el) => this.isElementAboveFold(el));\n elements.forEach((element) => {\n const processElementFont = (style, pseudoElement = null) => {\n if (!style || !this.isElementVisible(element)) return;\n const fontFamily = style.fontFamily.split(\",\")[0].replace(/['\"]+/g, \"\").trim();\n const hasContent = pseudoElement ? style.content !== \"none\" && style.content !== '\"\"' : element.textContent.trim();\n if (hasContent && !this.isSystemFont(fontFamily) && stylesheetFonts[fontFamily]) {\n if (!hostedFonts.has(fontFamily)) {\n hostedFonts.set(fontFamily, {\n elements: /* @__PURE__ */ new Set(),\n urls: stylesheetFonts[fontFamily].urls,\n variations: stylesheetFonts[fontFamily].variations\n });\n }\n hostedFonts.get(fontFamily).elements.add(element);\n }\n };\n try {\n processElementFont(window.getComputedStyle(element));\n [\"::before\", \"::after\"].forEach((pseudo) => {\n processElementFont(window.getComputedStyle(element, pseudo), pseudo);\n });\n } catch (e) {\n this.logger.logMessage(\"Error processing element:\", e);\n }\n });\n const aboveTheFoldFonts = this.summarizeMatches(externalFontsResults, hostedFonts, networkLoadedFonts);\n if (!Object.keys(aboveTheFoldFonts.allFonts).length && !Object.keys(aboveTheFoldFonts.externalFonts).length && !Object.keys(aboveTheFoldFonts.hostedFonts).length) {\n this.logger.logMessage(\"No fonts found above the fold.\");\n return;\n }\n this.logger.logMessage(\"Above the fold fonts:\", aboveTheFoldFonts);\n this.aboveTheFoldFonts = [...new Set(Object.values(aboveTheFoldFonts.allFonts).flatMap((font) => font.variations.map((variation) => variation.url)))];\n }\n /**\n * Summarizes all font matches found on the page\n * Creates a comprehensive object containing font usage data\n *\n * @param {Object} externalFontsResults - Results from External Fonts analysis\n * @param {Map} hostedFonts - Map of hosted (non-External) fonts found\n * @param {Map} networkLoadedFonts - Map of all font files loaded via network\n * @returns {Object} Complete analysis of font usage including locations and counts\n */\n summarizeMatches(externalFontsResults, hostedFonts, networkLoadedFonts) {\n const allFonts = {};\n const hostedFontsResults = {};\n if (hostedFonts.size > 0) {\n hostedFonts.forEach((data, fontFamily) => {\n if (data.variations) {\n const elements = Array.from(data.elements);\n const aboveElements = elements.filter((el) => this.isElementAboveFold(el));\n const belowElements = elements.filter((el) => !this.isElementAboveFold(el));\n if (!allFonts[fontFamily]) {\n allFonts[fontFamily] = {\n type: \"hosted\",\n variations: [],\n elementCount: {\n aboveFold: aboveElements.length,\n belowFold: belowElements.length,\n total: elements.length\n },\n urlCount: {\n aboveFold: /* @__PURE__ */ new Set(),\n belowFold: /* @__PURE__ */ new Set()\n }\n };\n }\n data.variations.forEach((variation) => {\n let matchingUrl = null;\n for (const styleUrl of data.urls) {\n const normalizedStyleUrl = this.cleanUrl(styleUrl);\n if (networkLoadedFonts.has(normalizedStyleUrl)) {\n matchingUrl = networkLoadedFonts.get(normalizedStyleUrl);\n break;\n }\n }\n allFonts[fontFamily].variations.push({\n weight: variation.weight,\n style: variation.style,\n url: matchingUrl || \"File not found\",\n elementCount: {\n aboveFold: aboveElements.length,\n belowFold: belowElements.length,\n total: elements.length\n }\n });\n if (matchingUrl) {\n if (aboveElements.length > 0) {\n allFonts[fontFamily].urlCount.aboveFold.add(matchingUrl);\n }\n if (belowElements.length > 0) {\n allFonts[fontFamily].urlCount.belowFold.add(matchingUrl);\n }\n }\n });\n if (!Object.prototype.hasOwnProperty.call(allFonts, fontFamily)) {\n return;\n }\n hostedFontsResults[fontFamily] = {\n variations: allFonts[fontFamily].variations,\n elementCount: { ...allFonts[fontFamily].elementCount },\n urlCount: { ...allFonts[fontFamily].urlCount }\n };\n }\n });\n }\n if (Object.keys(externalFontsResults).length > 0) {\n Object.entries(externalFontsResults).forEach(([url, data]) => {\n if (data.elementCount.aboveFold > 0) {\n data.variations.forEach((variation) => {\n if (!allFonts[variation.family]) {\n allFonts[variation.family] = {\n type: \"external\",\n variations: [],\n // Track element counts at font family level\n elementCount: {\n aboveFold: 0,\n belowFold: 0,\n total: 0\n },\n // Track unique URLs used in each fold location\n urlCount: {\n aboveFold: /* @__PURE__ */ new Set(),\n belowFold: /* @__PURE__ */ new Set()\n }\n };\n }\n const aboveElements = Array.from(data.elements).filter((el) => this.isElementAboveFold(el));\n const belowElements = Array.from(data.elements).filter((el) => !this.isElementAboveFold(el));\n allFonts[variation.family].variations.push({\n weight: variation.weight,\n style: variation.style,\n url,\n elementCount: {\n aboveFold: aboveElements.length,\n belowFold: belowElements.length,\n total: data.elements.length\n }\n });\n allFonts[variation.family].elementCount.aboveFold += aboveElements.length;\n allFonts[variation.family].elementCount.belowFold += belowElements.length;\n allFonts[variation.family].elementCount.total += data.elements.length;\n if (aboveElements.length > 0) {\n allFonts[variation.family].urlCount.aboveFold.add(url);\n }\n if (belowElements.length > 0) {\n allFonts[variation.family].urlCount.belowFold.add(url);\n }\n });\n }\n });\n }\n Object.values(allFonts).forEach((font) => {\n font.urlCount = {\n aboveFold: font.urlCount.aboveFold.size,\n belowFold: font.urlCount.belowFold.size,\n total: (/* @__PURE__ */ new Set([...font.urlCount.aboveFold, ...font.urlCount.belowFold])).size\n };\n });\n Object.values(hostedFontsResults).forEach((font) => {\n if (font.urlCount.aboveFold instanceof Set) {\n font.urlCount = {\n aboveFold: font.urlCount.aboveFold.size,\n belowFold: font.urlCount.belowFold.size,\n total: (/* @__PURE__ */ new Set([...font.urlCount.aboveFold, ...font.urlCount.belowFold])).size\n };\n }\n });\n return {\n externalFonts: Object.fromEntries(\n Object.entries(externalFontsResults).filter(\n (entry) => entry[1].elementCount.aboveFold > 0\n )\n ),\n hostedFonts: hostedFontsResults,\n allFonts\n };\n }\n /**\n * Processes external font pairs to identify their usage on the page.\n * \n * This method iterates through all elements on the page, checks if they are above the fold,\n * and determines the font information for each element. It then matches the font information\n * with the provided external font pairs to identify which fonts are used and where.\n * \n * @param {Object} fontPairs - An object where each key is a URL and the value is an array of font variations.\n * @returns {Promise} A promise that resolves to an object where each key is a URL and the value is an object containing information about the elements using that font.\n */\n async processExternalFonts(fontPairs) {\n const matches = /* @__PURE__ */ new Map();\n const elements = Array.from(document.getElementsByTagName(\"*\")).filter((el) => this.isElementAboveFold(el));\n const fontMap = /* @__PURE__ */ new Map();\n Object.entries(fontPairs).forEach(([url, variations]) => {\n variations.forEach((variation) => {\n const key = `${variation.family}|${variation.weight}|${variation.style}`;\n fontMap.set(key, { url, ...variation });\n });\n });\n const getFontInfoForElement = (style) => {\n const family = style.fontFamily.split(\",\")[0].replace(/['\"]+/g, \"\").trim();\n const weight = style.fontWeight;\n const fontStyle = style.fontStyle;\n const key = `${family}|${weight}|${fontStyle}`;\n let fontInfo = fontMap.get(key);\n if (!fontInfo && weight !== \"400\") {\n const fallbackKey = `${family}|400|${fontStyle}`;\n fontInfo = fontMap.get(fallbackKey);\n }\n return fontInfo;\n };\n elements.forEach((element) => {\n if (element.textContent.trim()) {\n const style = window.getComputedStyle(element);\n const fontInfo = getFontInfoForElement(style);\n if (fontInfo) {\n if (!matches.has(fontInfo.url)) {\n matches.set(fontInfo.url, {\n elements: /* @__PURE__ */ new Set(),\n variations: /* @__PURE__ */ new Set()\n });\n }\n matches.get(fontInfo.url).elements.add(element);\n matches.get(fontInfo.url).variations.add(JSON.stringify({\n family: fontInfo.family,\n weight: fontInfo.weight,\n style: fontInfo.style\n }));\n }\n }\n [\"::before\", \"::after\"].forEach((pseudo) => {\n const pseudoStyle = window.getComputedStyle(element, pseudo);\n if (pseudoStyle.content !== \"none\" && pseudoStyle.content !== '\"\"') {\n const fontInfo = getFontInfoForElement(pseudoStyle);\n if (fontInfo) {\n if (!matches.has(fontInfo.url)) {\n matches.set(fontInfo.url, {\n elements: /* @__PURE__ */ new Set(),\n variations: /* @__PURE__ */ new Set()\n });\n }\n matches.get(fontInfo.url).elements.add(element);\n matches.get(fontInfo.url).variations.add(JSON.stringify({\n family: fontInfo.family,\n weight: fontInfo.weight,\n style: fontInfo.style\n }));\n }\n }\n });\n });\n return Object.fromEntries(\n Array.from(matches.entries()).map(([url, data]) => [\n url,\n {\n elementCount: {\n aboveFold: Array.from(data.elements).filter((el) => this.isElementAboveFold(el)).length,\n total: data.elements.size\n },\n variations: Array.from(data.variations).map((v) => JSON.parse(v)),\n elements: Array.from(data.elements)\n }\n ])\n );\n }\n /**\n * Retrieves the results of the font analysis, specifically the fonts used above the fold.\n * This method returns an array containing the URLs of the fonts used above the fold.\n * \n * @returns {Array} An array of URLs of the fonts used above the fold.\n */\n getResults() {\n return this.aboveTheFoldFonts;\n }\n };\n var BeaconPreloadFonts_default = BeaconPreloadFonts;\n\n // src/BeaconPreconnectExternalDomain.js\n var BeaconPreconnectExternalDomain = class {\n constructor(config, logger) {\n this.logger = logger;\n this.result = [];\n this.excludedPatterns = config.preconnect_external_domain_exclusions;\n this.eligibleElements = config.preconnect_external_domain_elements;\n this.matchedItems = /* @__PURE__ */ new Set();\n this.excludedItems = /* @__PURE__ */ new Set();\n }\n /**\n * Initiates the process of identifying and logging external domains that require preconnection.\n * This method queries the document for eligible elements, processes each element to determine\n * if it should be preconnected, and logs the results.\n */\n async run() {\n const elements = document.querySelectorAll(\n `${this.eligibleElements.join(\", \")}[src], ${this.eligibleElements.join(\", \")}[href], ${this.eligibleElements.join(\", \")}[rel], ${this.eligibleElements.join(\", \")}[type]`\n );\n elements.forEach((el) => this.processElement(el));\n this.logger.logMessage({ matchedItems: this.getMatchedItems(), excludedItems: Array.from(this.excludedItems) });\n }\n /**\n * Processes a single element to determine if it should be preconnected.\n * \n * This method checks if the element is excluded based on attribute or domain rules.\n * If not excluded, it checks if the element's URL is an external domain and adds it to the list of matched items.\n * \n * @param {Element} el - The element to process.\n */\n processElement(el) {\n try {\n const url = new URL(el.src || el.href || \"\", location.href);\n if (this.isExcludedByAttribute(el)) {\n this.excludedItems.add(this.createExclusionObject(url, el, \"attribute\"));\n return;\n }\n if (this.isExcludedByDomain(url)) {\n this.excludedItems.add(this.createExclusionObject(url, el, \"domain\"));\n return;\n }\n if (this.isExternalDomain(url)) {\n this.matchedItems.add(`${url.hostname}-${el.tagName.toLowerCase()}`);\n this.result = [...new Set(this.result.concat(url.hostname))];\n }\n } catch (e) {\n this.logger.logMessage(e);\n }\n }\n /**\n * Checks if an element is excluded based on attribute rules.\n * \n * This method iterates through the excludedPatterns array and checks if any pattern matches the element's attribute.\n * If a match is found, it returns true, indicating the element is excluded.\n * \n * @param {Element} el - The element to check.\n * @returns {boolean} True if the element is excluded by an attribute rule, false otherwise.\n */\n isExcludedByAttribute(el) {\n return this.excludedPatterns.some(\n (pattern) => pattern.type === \"attribute\" && el.getAttribute(pattern.key) === pattern.value\n );\n }\n /**\n * Checks if a URL is excluded based on domain rules.\n * \n * This method iterates through the excludedPatterns array and checks if any pattern matches the URL's hostname.\n * If a match is found, it returns true, indicating the URL is excluded.\n * \n * @param {URL} url - The URL to check.\n * @returns {boolean} True if the URL is excluded by a domain rule, false otherwise.\n */\n isExcludedByDomain(url) {\n return this.excludedPatterns.some(\n (pattern) => pattern.type === \"domain\" && url.hostname.includes(pattern.value)\n );\n }\n /**\n * Checks if a URL is from an external domain.\n * \n * This method compares the hostname of the given URL with the hostname of the current location.\n * If they are not the same, it indicates the URL is from an external domain.\n * \n * @param {URL} url - The URL to check.\n * @returns {boolean} True if the URL is from an external domain, false otherwise.\n */\n isExternalDomain(url) {\n return url.hostname !== location.hostname && url.hostname;\n }\n /**\n * Creates an exclusion object based on the URL, element, and type.\n * \n * This method finds the pattern in the excludedPatterns array that matches the type and the element's attribute or the URL's hostname.\n * It then constructs a reason string based on the type and the pattern.\n * Finally, it returns an object with the URL's hostname, the element's tag name, and the reason.\n * \n * @param {URL} url - The URL to create the exclusion object for.\n * @param {Element} el - The element to create the exclusion object for.\n * @param {string} type - The type of the exclusion (attribute or domain).\n * @returns {Object} An object with the URL's hostname, the element's tag name, and the reason.\n */\n createExclusionObject(url, el, type) {\n const pattern = this.excludedPatterns.find(\n (p) => type === \"attribute\" && el.getAttribute(p.key) === p.value || type === \"domain\" && url.hostname.includes(p.value)\n );\n let reason = type === \"attribute\" ? `${pattern.key}=${pattern.value}` : `domain-partial=${pattern.value}`;\n return { domain: url.hostname, elementType: el.tagName.toLowerCase(), reason };\n }\n /**\n * Returns an array of matched items, each item split into its domain and element type.\n * \n * This method iterates through the matchedItems set, splits each item into its domain and element type using the last hyphen as a delimiter,\n * and returns an array of these split items.\n * \n * @returns {Array} An array of arrays, each containing a domain and an element type.\n */\n getMatchedItems() {\n return Array.from(this.matchedItems).map((item) => {\n const lastHyphenIndex = item.lastIndexOf(\"-\");\n return [\n item.substring(0, lastHyphenIndex),\n // Domain\n item.substring(lastHyphenIndex + 1)\n // Element type\n ];\n });\n }\n /**\n * Returns the array of unique domain names that were found to be external.\n * \n * This method returns the result array, which contains a list of unique domain names that were identified as external during the analysis process.\n * \n * @returns {Array} An array of unique domain names.\n */\n getResults() {\n return this.result;\n }\n };\n var BeaconPreconnectExternalDomain_default = BeaconPreconnectExternalDomain;\n\n // src/Logger.js\n var Logger = class {\n constructor(enabled) {\n this.enabled = enabled;\n }\n logMessage(label, msg = \"\") {\n if (!this.enabled) {\n return;\n }\n if (msg !== \"\") {\n console.log(label, msg);\n return;\n }\n console.log(label);\n }\n logColoredMessage(msg, color = \"green\") {\n if (!this.enabled) {\n return;\n }\n console.log(`%c${msg}`, `color: ${color};`);\n }\n };\n var Logger_default = Logger;\n\n // src/BeaconManager.js\n var BeaconManager = class {\n constructor(config) {\n this.config = config;\n this.lcpBeacon = null;\n this.lrcBeacon = null;\n this.preloadFontsBeacon = null;\n this.preconnectExternalDomainBeacon = null;\n this.infiniteLoopId = null;\n this.errorCode = \"\";\n this.logger = new Logger_default(this.config.debug);\n }\n async init() {\n this.scriptTimer = /* @__PURE__ */ new Date();\n if (!await this._isValidPreconditions()) {\n this._finalize();\n return;\n }\n if (Utils_default.isPageScrolled()) {\n this.logger.logMessage(\"Bailing out because the page has been scrolled\");\n this._finalize();\n return;\n }\n this.infiniteLoopId = setTimeout(() => {\n this._handleInfiniteLoop();\n }, 1e4);\n const isGeneratedBefore = await this._getGeneratedBefore();\n const shouldGenerateLcp = this.config.status.atf && (isGeneratedBefore === false || isGeneratedBefore.lcp === false);\n const shouldGeneratelrc = this.config.status.lrc && (isGeneratedBefore === false || isGeneratedBefore.lrc === false);\n const shouldGeneratePreloadFonts = this.config.status.preload_fonts && (isGeneratedBefore === false || isGeneratedBefore.preload_fonts === false);\n const shouldGeneratePreconnectExternalDomain = this.config.status.preconnect_external_domain && (isGeneratedBefore === false || isGeneratedBefore.preconnect_external_domain === false);\n if (shouldGenerateLcp) {\n this.lcpBeacon = new BeaconLcp_default(this.config, this.logger);\n await this.lcpBeacon.run();\n } else {\n this.logger.logMessage(\"Not running BeaconLcp because data is already available or feature is disabled\");\n }\n if (shouldGeneratelrc) {\n this.lrcBeacon = new BeaconLrc_default(this.config, this.logger);\n await this.lrcBeacon.run();\n } else {\n this.logger.logMessage(\"Not running BeaconLrc because data is already available or feature is disabled\");\n }\n if (shouldGeneratePreloadFonts) {\n this.preloadFontsBeacon = new BeaconPreloadFonts_default(this.config, this.logger);\n await this.preloadFontsBeacon.run();\n } else {\n this.logger.logMessage(\"Not running BeaconPreloadFonts because data is already available or feature is disabled\");\n }\n if (shouldGeneratePreconnectExternalDomain) {\n this.preconnectExternalDomainBeacon = new BeaconPreconnectExternalDomain_default(this.config, this.logger);\n await this.preconnectExternalDomainBeacon.run();\n } else {\n this.logger.logMessage(\"Not running BeaconPreconnectExternalDomain because data is already available or feature is disabled\");\n }\n if (shouldGenerateLcp || shouldGeneratelrc || shouldGeneratePreloadFonts || shouldGeneratePreconnectExternalDomain) {\n this._saveFinalResultIntoDB();\n } else {\n this.logger.logMessage(\"Not saving results into DB as no beacon features ran.\");\n this._finalize();\n }\n }\n async _isValidPreconditions() {\n const threshold = {\n width: this.config.width_threshold,\n height: this.config.height_threshold\n };\n if (Utils_default.isNotValidScreensize(this.config.is_mobile, threshold)) {\n this.logger.logMessage(\"Bailing out because screen size is not acceptable\");\n return false;\n }\n return true;\n }\n async _getGeneratedBefore() {\n if (!Utils_default.isPageCached()) {\n return false;\n }\n let data_check = new FormData();\n data_check.append(\"action\", \"rocket_check_beacon\");\n data_check.append(\"rocket_beacon_nonce\", this.config.nonce);\n data_check.append(\"url\", this.config.url);\n data_check.append(\"is_mobile\", this.config.is_mobile);\n const beacon_data_response = await fetch(this.config.ajax_url, {\n method: \"POST\",\n credentials: \"same-origin\",\n body: data_check\n }).then((data) => data.json());\n return beacon_data_response.data;\n }\n _saveFinalResultIntoDB() {\n const results = {\n lcp: this.lcpBeacon ? this.lcpBeacon.getResults() : null,\n lrc: this.lrcBeacon ? this.lrcBeacon.getResults() : null,\n preload_fonts: this.preloadFontsBeacon ? this.preloadFontsBeacon.getResults() : null,\n preconnect_external_domain: this.preconnectExternalDomainBeacon ? this.preconnectExternalDomainBeacon.getResults() : null\n };\n const data = new FormData();\n data.append(\"action\", \"rocket_beacon\");\n data.append(\"rocket_beacon_nonce\", this.config.nonce);\n data.append(\"url\", this.config.url);\n data.append(\"is_mobile\", this.config.is_mobile);\n data.append(\"status\", this._getFinalStatus());\n data.append(\"results\", JSON.stringify(results));\n fetch(this.config.ajax_url, {\n method: \"POST\",\n credentials: \"same-origin\",\n body: data,\n headers: {\n \"wpr-saas-no-intercept\": true\n }\n }).then((response) => response.json()).then((data2) => {\n this.logger.logMessage(data2.data.lcp);\n }).catch((error) => {\n this.logger.logMessage(error);\n }).finally(() => {\n this._finalize();\n });\n }\n _getFinalStatus() {\n if (\"\" !== this.errorCode) {\n return this.errorCode;\n }\n const scriptTime = (/* @__PURE__ */ new Date() - this.scriptTimer) / 1e3;\n if (10 <= scriptTime) {\n return \"timeout\";\n }\n return \"success\";\n }\n _handleInfiniteLoop() {\n this._saveFinalResultIntoDB();\n }\n _finalize() {\n const beaconscript = document.querySelector('[data-name=\"wpr-wpr-beacon\"]');\n beaconscript.setAttribute(\"beacon-completed\", \"true\");\n clearTimeout(this.infiniteLoopId);\n }\n };\n var BeaconManager_default = BeaconManager;\n\n // src/BeaconEntryPoint.js\n ((rocket_beacon_data) => {\n if (!rocket_beacon_data) {\n return;\n }\n const instance = new BeaconManager_default(rocket_beacon_data);\n if (document.readyState !== \"loading\") {\n setTimeout(() => {\n instance.init();\n }, rocket_beacon_data.delay);\n return;\n }\n document.addEventListener(\"DOMContentLoaded\", () => {\n setTimeout(() => {\n instance.init();\n }, rocket_beacon_data.delay);\n });\n })(window.rocket_beacon_data);\n var BeaconEntryPoint_default = BeaconManager_default;\n})();\n"], - "mappings": "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", - "names": ["BeaconUtils", "is_mobile", "threshold", "screenWidth", "screenHeight", "isNotValidForMobile", "isNotValidForDesktop", "signature", "rect", "Utils_default", "BeaconLcp", "config", "logger", "above_the_fold_images", "err", "count", "lcpElements", "element", "imgElement", "item", "a", "b", "candidate", "visibleWidth", "visibleHeight", "nodeName", "element_info", "css_bg_url_rgx", "source", "imageElement", "img", "bg_props", "prop", "full_bg_prop", "matches", "m", "elements", "firstElementWithInfo", "elementInfo", "image", "isImageOrVideo", "isBgImageOrPicture", "BeaconLcp_default", "BeaconLrc", "elementsInView", "svgUseTargets", "depth", "parent", "scrollTop", "skipStrings", "str", "exclusions", "i", "attribute", "pattern", "attributeValue", "conflictingElements", "computedStyle", "negativeMargins", "margin", "child", "childStyle", "childNegativeMargins", "distance", "hash", "conflicts", "can_push_hash", "color", "position", "pos", "sibling", "useElements", "targets", "use", "BeaconLrc_default", "BeaconPreloadFonts", "_BeaconPreloadFonts", "fontFamily", "style", "url", "resource", "stylesheetFonts", "sheet", "rule", "src", "weight", "urlMatch", "rawUrl", "normalizedUrl", "e", "fontData", "v", "elementTop", "foldPosition", "networkLoadedFonts", "hostedFonts", "externalFontPairs", "externalFontsResults", "el", "processElementFont", "pseudoElement", "pseudo", "aboveTheFoldFonts", "font", "variation", "allFonts", "hostedFontsResults", "data", "aboveElements", "belowElements", "matchingUrl", "styleUrl", "normalizedStyleUrl", "entry", "fontPairs", "fontMap", "variations", "key", "getFontInfoForElement", "family", "fontStyle", "fontInfo", "fallbackKey", "pseudoStyle", "BeaconPreloadFonts_default", "BeaconPreconnectExternalDomain", "type", "p", "reason", "lastHyphenIndex", "BeaconPreconnectExternalDomain_default", "Logger", "enabled", "label", "msg", "Logger_default", "BeaconManager", "isGeneratedBefore", "shouldGenerateLcp", "shouldGeneratelrc", "shouldGeneratePreloadFonts", "shouldGeneratePreconnectExternalDomain", "data_check", "results", "response", "data2", "error", "BeaconManager_default", "rocket_beacon_data", "instance", "BeaconEntryPoint_default"] + "sourcesContent": ["(() => {\n // src/Utils.js\n var BeaconUtils = class {\n static getScreenWidth() {\n return window.innerWidth || document.documentElement.clientWidth;\n }\n static getScreenHeight() {\n return window.innerHeight || document.documentElement.clientHeight;\n }\n static isNotValidScreensize(is_mobile, threshold) {\n const screenWidth = this.getScreenWidth();\n const screenHeight = this.getScreenHeight();\n const isNotValidForMobile = is_mobile && (screenWidth > threshold.width || screenHeight > threshold.height);\n const isNotValidForDesktop = !is_mobile && (screenWidth < threshold.width || screenHeight < threshold.height);\n return isNotValidForMobile || isNotValidForDesktop;\n }\n static isPageCached() {\n const signature = document.documentElement.nextSibling && document.documentElement.nextSibling.data ? document.documentElement.nextSibling.data : \"\";\n return signature && signature.includes(\"Debug: cached\");\n }\n static isIntersecting(rect) {\n return rect.bottom >= 0 && rect.right >= 0 && rect.top <= (window.innerHeight || document.documentElement.clientHeight) && rect.left <= (window.innerWidth || document.documentElement.clientWidth);\n }\n static isPageScrolled() {\n return window.pageYOffset > 0 || document.documentElement.scrollTop > 0;\n }\n };\n var Utils_default = BeaconUtils;\n\n // src/BeaconLcp.js\n var BeaconLcp = class {\n constructor(config, logger) {\n this.config = config;\n this.performanceImages = [];\n this.logger = logger;\n }\n async run() {\n try {\n const above_the_fold_images = this._generateLcpCandidates(Infinity);\n if (above_the_fold_images) {\n this._initWithFirstElementWithInfo(above_the_fold_images);\n this._fillATFWithoutDuplications(above_the_fold_images);\n }\n } catch (err) {\n this.errorCode = \"script_error\";\n this.logger.logMessage(\"Script Error: \" + err);\n }\n }\n _generateLcpCandidates(count) {\n const lcpElements = document.querySelectorAll(this.config.elements);\n if (lcpElements.length <= 0) {\n return [];\n }\n const potentialCandidates = Array.from(lcpElements);\n const topCandidates = potentialCandidates.map((element) => {\n if (\"img\" === element.nodeName.toLowerCase() && \"picture\" === element.parentElement.nodeName.toLowerCase()) {\n return null;\n }\n let rect;\n if (\"picture\" === element.nodeName.toLowerCase()) {\n const imgElement = element.querySelector(\"img\");\n if (imgElement) {\n rect = imgElement.getBoundingClientRect();\n } else {\n return null;\n }\n } else {\n rect = element.getBoundingClientRect();\n }\n return {\n element,\n rect\n };\n }).filter((item) => item !== null).filter((item) => {\n return item.rect.width > 0 && item.rect.height > 0 && Utils_default.isIntersecting(item.rect);\n }).map((item) => ({\n item,\n area: this._getElementArea(item.rect),\n elementInfo: this._getElementInfo(item.element)\n })).sort((a, b) => b.area - a.area).slice(0, count);\n return topCandidates.map((candidate) => ({\n element: candidate.item.element,\n elementInfo: candidate.elementInfo\n }));\n }\n _getElementArea(rect) {\n const visibleWidth = Math.min(rect.width, (window.innerWidth || document.documentElement.clientWidth) - rect.left);\n const visibleHeight = Math.min(rect.height, (window.innerHeight || document.documentElement.clientHeight) - rect.top);\n return visibleWidth * visibleHeight;\n }\n _getElementInfo(element) {\n const nodeName = element.nodeName.toLowerCase();\n const element_info = {\n type: \"\",\n src: \"\",\n srcset: \"\",\n sizes: \"\",\n sources: [],\n bg_set: [],\n current_src: \"\"\n };\n const css_bg_url_rgx = /url\\(\\s*?['\"]?\\s*?(.+?)\\s*?[\"']?\\s*?\\)/ig;\n if (nodeName === \"img\" && element.srcset) {\n element_info.type = \"img-srcset\";\n element_info.src = element.src;\n element_info.srcset = element.srcset;\n element_info.sizes = element.sizes;\n element_info.current_src = element.currentSrc;\n } else if (nodeName === \"img\") {\n element_info.type = \"img\";\n element_info.src = element.src;\n element_info.current_src = element.currentSrc;\n } else if (nodeName === \"video\") {\n element_info.type = \"img\";\n const source = element.querySelector(\"source\");\n element_info.src = element.poster || (source ? source.src : \"\");\n element_info.current_src = element_info.src;\n } else if (nodeName === \"svg\") {\n const imageElement = element.querySelector(\"image\");\n if (imageElement) {\n element_info.type = \"img\";\n element_info.src = imageElement.getAttribute(\"href\") || \"\";\n element_info.current_src = element_info.src;\n }\n } else if (nodeName === \"picture\") {\n element_info.type = \"picture\";\n const img = element.querySelector(\"img\");\n element_info.src = img ? img.src : \"\";\n element_info.sources = Array.from(element.querySelectorAll(\"source\")).map((source) => ({\n srcset: source.srcset || \"\",\n media: source.media || \"\",\n type: source.type || \"\",\n sizes: source.sizes || \"\"\n }));\n } else {\n const computed_style = window.getComputedStyle(element, null);\n const bg_props = [\n computed_style.getPropertyValue(\"background-image\"),\n getComputedStyle(element, \":after\").getPropertyValue(\"background-image\"),\n getComputedStyle(element, \":before\").getPropertyValue(\"background-image\")\n ].filter((prop) => prop !== \"none\");\n if (bg_props.length === 0) {\n return null;\n }\n const full_bg_prop = bg_props[0];\n element_info.type = \"bg-img\";\n if (full_bg_prop.includes(\"image-set(\")) {\n element_info.type = \"bg-img-set\";\n }\n if (!full_bg_prop || full_bg_prop === \"\" || full_bg_prop.includes(\"data:image\")) {\n return null;\n }\n const matches = [...full_bg_prop.matchAll(css_bg_url_rgx)];\n element_info.bg_set = matches.map((m) => m[1] ? { src: m[1].trim() + (m[2] ? \" \" + m[2].trim() : \"\") } : {});\n if (element_info.bg_set.every((item) => item.src === \"\")) {\n element_info.bg_set = matches.map((m) => m[1] ? { src: m[1].trim() } : {});\n }\n if (element_info.bg_set.length <= 0) {\n return null;\n }\n if (element_info.bg_set.length > 0) {\n element_info.src = element_info.bg_set[0].src;\n if (element_info.type === \"bg-img-set\") {\n element_info.src = element_info.bg_set;\n }\n }\n }\n return element_info;\n }\n _initWithFirstElementWithInfo(elements) {\n const firstElementWithInfo = elements.find((item) => {\n return item.elementInfo !== null && (item.elementInfo.src || item.elementInfo.srcset);\n });\n if (!firstElementWithInfo) {\n this.logger.logMessage(\"No LCP candidate found.\");\n this.performanceImages = [];\n return;\n }\n this.performanceImages = [{\n ...firstElementWithInfo.elementInfo,\n label: \"lcp\"\n }];\n }\n _fillATFWithoutDuplications(elements) {\n elements.forEach(({ element, elementInfo }) => {\n if (this._isDuplicateImage(element) || !elementInfo) {\n return;\n }\n this.performanceImages.push({ ...elementInfo, label: \"above-the-fold\" });\n });\n }\n _isDuplicateImage(image) {\n const elementInfo = this._getElementInfo(image);\n if (elementInfo === null) {\n return false;\n }\n const isImageOrVideo = elementInfo.type === \"img\" || elementInfo.type === \"img-srcset\" || elementInfo.type === \"video\";\n const isBgImageOrPicture = elementInfo.type === \"bg-img\" || elementInfo.type === \"bg-img-set\" || elementInfo.type === \"picture\";\n return (isImageOrVideo || isBgImageOrPicture) && this.performanceImages.some((item) => item.src === elementInfo.src);\n }\n getResults() {\n return this.performanceImages;\n }\n };\n var BeaconLcp_default = BeaconLcp;\n\n // src/BeaconLrc.js\n var BeaconLrc = class {\n constructor(config, logger) {\n this.config = config;\n this.logger = logger;\n this.lazyRenderElements = [];\n }\n async run() {\n try {\n const elementsInView = this._getLazyRenderElements();\n if (elementsInView) {\n this._processElements(elementsInView);\n }\n } catch (err) {\n this.errorCode = \"script_error\";\n this.logger.logMessage(\"Script Error: \" + err);\n }\n }\n _getLazyRenderElements() {\n const elements = document.querySelectorAll(\"[data-rocket-location-hash]\");\n const svgUseTargets = this._getSvgUseTargets();\n if (elements.length <= 0) {\n return [];\n }\n const validElements = Array.from(elements).filter((element) => {\n if (this._skipElement(element)) {\n return false;\n }\n if (svgUseTargets.includes(element)) {\n this.logger.logColoredMessage(`Element skipped because of SVG: ${element.tagName}`, \"orange\");\n return false;\n }\n return true;\n });\n return validElements.map((element) => ({\n element,\n depth: this._getElementDepth(element),\n distance: this._getElementDistance(element),\n hash: this._getLocationHash(element)\n }));\n }\n _getElementDepth(element) {\n let depth = 0;\n let parent = element.parentElement;\n while (parent) {\n depth++;\n parent = parent.parentElement;\n }\n return depth;\n }\n _getElementDistance(element) {\n const rect = element.getBoundingClientRect();\n const scrollTop = window.pageYOffset || document.documentElement.scrollTop;\n return Math.max(0, rect.top + scrollTop - Utils_default.getScreenHeight());\n }\n _skipElement(element) {\n const skipStrings = this.config.skipStrings || [\"memex\"];\n if (!element || !element.id) return false;\n return skipStrings.some((str) => element.id.toLowerCase().includes(str.toLowerCase()));\n }\n _shouldSkipElement(element, exclusions) {\n if (!element) return false;\n for (let i = 0; i < exclusions.length; i++) {\n const [attribute, pattern] = exclusions[i];\n const attributeValue = element.getAttribute(attribute);\n if (attributeValue && new RegExp(pattern, \"i\").test(attributeValue)) {\n return true;\n }\n }\n return false;\n }\n _checkLcrConflict(element) {\n const conflictingElements = [];\n const computedStyle = window.getComputedStyle(element);\n const validMargins = [\"marginTop\", \"marginRight\", \"marginBottom\", \"marginLeft\"];\n const negativeMargins = validMargins.some((margin) => parseFloat(computedStyle[margin]) < 0);\n const currentElementConflicts = negativeMargins || computedStyle.contentVisibility === \"auto\" || computedStyle.contentVisibility === \"hidden\";\n if (currentElementConflicts) {\n conflictingElements.push({\n element,\n conflicts: [\n negativeMargins && \"negative margin\",\n computedStyle.contentVisibility === \"auto\" && \"content-visibility:auto\",\n computedStyle.contentVisibility === \"hidden\" && \"content-visibility:hidden\"\n ].filter(Boolean)\n });\n }\n Array.from(element.children).forEach((child) => {\n const childStyle = window.getComputedStyle(child);\n const validMargins2 = [\"marginTop\", \"marginRight\", \"marginBottom\", \"marginLeft\"];\n const childNegativeMargins = validMargins2.some((margin) => parseFloat(childStyle[margin]) < 0);\n const childConflicts = childNegativeMargins || childStyle.position === \"absolute\" || childStyle.position === \"fixed\";\n if (childConflicts) {\n conflictingElements.push({\n element: child,\n conflicts: [\n childNegativeMargins && \"negative margin\",\n childStyle.position === \"absolute\" && \"position:absolute\",\n childStyle.position === \"fixed\" && \"position:fixed\"\n ].filter(Boolean)\n });\n }\n });\n return conflictingElements;\n }\n _processElements(elements) {\n elements.forEach(({ element, depth, distance, hash }) => {\n if (this._shouldSkipElement(element, this.config.exclusions || [])) {\n return;\n }\n if (\"No hash detected\" === hash) {\n return;\n }\n const conflicts = this._checkLcrConflict(element);\n if (conflicts.length > 0) {\n this.logger.logMessage(\"Skipping element due to conflicts:\", conflicts);\n return;\n }\n const can_push_hash = element.parentElement && this._getElementDistance(element.parentElement) < this.config.lrc_threshold && distance >= this.config.lrc_threshold;\n const color = can_push_hash ? \"green\" : distance === 0 ? \"red\" : \"\";\n this.logger.logColoredMessage(`${\"\t\".repeat(depth)}${element.tagName} (Depth: ${depth}, Distance from viewport bottom: ${distance}px)`, color);\n this.logger.logColoredMessage(`${\"\t\".repeat(depth)}Location hash: ${hash}`, color);\n this.logger.logColoredMessage(`${\"\t\".repeat(depth)}Dimensions Client Height: ${element.clientHeight}`, color);\n if (can_push_hash) {\n this.lazyRenderElements.push(hash);\n this.logger.logMessage(`Element pushed with hash: ${hash}`);\n }\n });\n }\n _getXPath(element) {\n if (element && element.id !== \"\") {\n return `//*[@id=\"${element.id}\"]`;\n }\n return this._getElementXPath(element);\n }\n _getElementXPath(element) {\n if (element === document.body) {\n return \"/html/body\";\n }\n const position = this._getElementPosition(element);\n return `${this._getElementXPath(element.parentNode)}/${element.nodeName.toLowerCase()}[${position}]`;\n }\n _getElementPosition(element) {\n let pos = 1;\n let sibling = element.previousElementSibling;\n while (sibling) {\n if (sibling.nodeName === element.nodeName) {\n pos++;\n }\n sibling = sibling.previousElementSibling;\n }\n return pos;\n }\n _getLocationHash(element) {\n return element.hasAttribute(\"data-rocket-location-hash\") ? element.getAttribute(\"data-rocket-location-hash\") : \"No hash detected\";\n }\n _getSvgUseTargets() {\n const useElements = document.querySelectorAll(\"use\");\n const targets = /* @__PURE__ */ new Set();\n useElements.forEach((use) => {\n let parent = use.parentElement;\n while (parent && parent !== document.body) {\n targets.add(parent);\n parent = parent.parentElement;\n }\n });\n return Array.from(targets);\n }\n getResults() {\n return this.lazyRenderElements;\n }\n };\n var BeaconLrc_default = BeaconLrc;\n\n // src/BeaconPreloadFonts.js\n var BeaconPreloadFonts = class {\n constructor(config, logger) {\n this.config = config;\n this.logger = logger;\n this.aboveTheFoldFonts = [];\n const extensions = (Array.isArray(this.config.processed_extensions) && this.config.processed_extensions.length > 0 ? this.config.processed_extensions : [\"woff\", \"woff2\", \"ttf\"]).map((ext) => ext.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\")).join(\"|\");\n this.FONT_FILE_REGEX = new RegExp(`\\\\.(${extensions})(\\\\?.*)?$`, \"i\");\n }\n /**\n * Checks if a given font family is a system font.\n * \n * This method checks if the provided font family is part of the system fonts\n * defined in the configuration. It returns true if the font family is a system\n * font, and false otherwise.\n * \n * @param {string} fontFamily - The font family to check.\n * @returns {boolean} True if the font family is a system font, false otherwise.\n */\n isSystemFont(fontFamily) {\n const systemFonts = new Set(this.config.system_fonts);\n return systemFonts.has(fontFamily);\n }\n /**\n * Checks if an element is visible in the viewport.\n * \n * This method checks if the provided element is visible in the viewport by\n * considering its display, visibility, opacity, width, and height properties.\n * It returns true if the element is visible, and false otherwise.\n * \n * @param {Element} element - The element to check for visibility.\n * @returns {boolean} True if the element is visible, false otherwise.\n */\n isElementVisible(element) {\n const style = window.getComputedStyle(element);\n const rect = element.getBoundingClientRect();\n return !(style.display === \"none\" || style.visibility === \"hidden\" || style.opacity === \"0\" || rect.width === 0 || rect.height === 0);\n }\n /**\n * Cleans a URL by removing query parameters and fragments.\n * \n * This method takes a URL as input, removes any query parameters and fragments,\n * and returns the cleaned URL.\n * \n * @param {string} url - The URL to clean.\n * @returns {string} The cleaned URL.\n */\n cleanUrl(url) {\n try {\n url = url.split(\"?\")[0].split(\"#\")[0];\n return new URL(url, window.location.href).href;\n } catch (e) {\n return url;\n }\n }\n /**\n * Retrieves a map of network-loaded fonts.\n * \n * This method uses the Performance API to get all resource entries, filters out\n * the ones that match the font file regex, and maps them to their cleaned URLs.\n * \n * @returns {Map} A map where each key is a cleaned URL of a font file and\n * each value is the original URL of the font file.\n */\n getNetworkLoadedFonts() {\n return new Map(\n window.performance.getEntriesByType(\"resource\").filter((resource) => this.FONT_FILE_REGEX.test(resource.name)).map((resource) => [this.cleanUrl(resource.name), resource.name])\n );\n }\n /**\n * Retrieves font-face rules from stylesheets.\n * \n * This method scans all stylesheets loaded on the page and collects\n * font-face rules, including their source URLs, font families, weights,\n * and styles. It returns an object containing the collected font data.\n * \n * @returns {Object} An object mapping font families to their respective\n * URLs and variations.\n */\n getFontFaceRules() {\n const stylesheetFonts = {};\n Array.from(document.styleSheets).forEach((sheet) => {\n try {\n Array.from(sheet.cssRules || []).forEach((rule) => {\n if (rule instanceof CSSFontFaceRule) {\n const src = rule.style.getPropertyValue(\"src\");\n const fontFamily = rule.style.getPropertyValue(\"font-family\").replace(/['\"]+/g, \"\").trim();\n const weight = rule.style.getPropertyValue(\"font-weight\") || \"400\";\n const style = rule.style.getPropertyValue(\"font-style\") || \"normal\";\n if (!stylesheetFonts[fontFamily]) {\n stylesheetFonts[fontFamily] = {\n urls: [],\n variations: /* @__PURE__ */ new Set()\n };\n }\n const urls = src.match(/url\\(['\"]?([^'\"]+)['\"]?\\)/g) || [];\n urls.forEach((urlMatch) => {\n let rawUrl = urlMatch.match(/url\\(['\"]?([^'\"]+)['\"]?\\)/)[1];\n if (sheet.href) {\n rawUrl = new URL(rawUrl, sheet.href).href;\n }\n const normalizedUrl = this.cleanUrl(rawUrl);\n if (!stylesheetFonts[fontFamily].urls.includes(normalizedUrl)) {\n stylesheetFonts[fontFamily].urls.push(normalizedUrl);\n stylesheetFonts[fontFamily].variations.add(JSON.stringify({\n weight,\n style\n }));\n }\n });\n }\n });\n } catch (e) {\n this.logger.logMessage(e);\n }\n });\n Object.values(stylesheetFonts).forEach((fontData) => {\n fontData.variations = Array.from(fontData.variations).map((v) => JSON.parse(v));\n });\n return stylesheetFonts;\n }\n /**\n * Checks if an element is above the fold (visible in the viewport without scrolling).\n * \n * @param {Element} element - The element to check.\n * @returns {boolean} True if the element is above the fold, false otherwise.\n */\n isElementAboveFold(element) {\n if (!this.isElementVisible(element)) return false;\n const rect = element.getBoundingClientRect();\n const scrollTop = window.pageYOffset || document.documentElement.scrollTop;\n const elementTop = rect.top + scrollTop;\n const foldPosition = window.innerHeight || document.documentElement.clientHeight;\n return elementTop <= foldPosition;\n }\n /**\n * Initiates the process of analyzing and summarizing font usage on the page.\n * This method fetches network-loaded fonts, stylesheet fonts, and external font pairs.\n * It then processes each element on the page to determine which fonts are used above the fold.\n * The results are summarized and logged.\n * \n * @returns {Promise} A promise that resolves when the analysis is complete.\n */\n async run() {\n await document.fonts.ready;\n const networkLoadedFonts = this.getNetworkLoadedFonts();\n const stylesheetFonts = this.getFontFaceRules();\n const hostedFonts = /* @__PURE__ */ new Map();\n const externalFontPairs = this.config.font_data;\n const externalFontsResults = await this.processExternalFonts(externalFontPairs);\n const elements = Array.from(document.getElementsByTagName(\"*\")).filter((el) => this.isElementAboveFold(el));\n elements.forEach((element) => {\n const processElementFont = (style, pseudoElement = null) => {\n if (!style || !this.isElementVisible(element)) return;\n const fontFamily = style.fontFamily.split(\",\")[0].replace(/['\"]+/g, \"\").trim();\n const hasContent = pseudoElement ? style.content !== \"none\" && style.content !== '\"\"' : element.textContent.trim();\n if (hasContent && !this.isSystemFont(fontFamily) && stylesheetFonts[fontFamily]) {\n if (!hostedFonts.has(fontFamily)) {\n hostedFonts.set(fontFamily, {\n elements: /* @__PURE__ */ new Set(),\n urls: stylesheetFonts[fontFamily].urls,\n variations: stylesheetFonts[fontFamily].variations\n });\n }\n hostedFonts.get(fontFamily).elements.add(element);\n }\n };\n try {\n processElementFont(window.getComputedStyle(element));\n [\"::before\", \"::after\"].forEach((pseudo) => {\n processElementFont(window.getComputedStyle(element, pseudo), pseudo);\n });\n } catch (e) {\n this.logger.logMessage(\"Error processing element:\", e);\n }\n });\n const aboveTheFoldFonts = this.summarizeMatches(externalFontsResults, hostedFonts, networkLoadedFonts);\n if (!Object.keys(aboveTheFoldFonts.allFonts).length && !Object.keys(aboveTheFoldFonts.externalFonts).length && !Object.keys(aboveTheFoldFonts.hostedFonts).length) {\n this.logger.logMessage(\"No fonts found above the fold.\");\n return;\n }\n this.logger.logMessage(\"Above the fold fonts:\", aboveTheFoldFonts);\n this.aboveTheFoldFonts = [...new Set(Object.values(aboveTheFoldFonts.allFonts).flatMap((font) => font.variations.map((variation) => variation.url)))];\n }\n /**\n * Summarizes all font matches found on the page\n * Creates a comprehensive object containing font usage data\n *\n * @param {Object} externalFontsResults - Results from External Fonts analysis\n * @param {Map} hostedFonts - Map of hosted (non-External) fonts found\n * @param {Map} networkLoadedFonts - Map of all font files loaded via network\n * @returns {Object} Complete analysis of font usage including locations and counts\n */\n summarizeMatches(externalFontsResults, hostedFonts, networkLoadedFonts) {\n const allFonts = {};\n const hostedFontsResults = {};\n if (hostedFonts.size > 0) {\n hostedFonts.forEach((data, fontFamily) => {\n if (data.variations) {\n const elements = Array.from(data.elements);\n const aboveElements = elements.filter((el) => this.isElementAboveFold(el));\n const belowElements = elements.filter((el) => !this.isElementAboveFold(el));\n if (!allFonts[fontFamily]) {\n allFonts[fontFamily] = {\n type: \"hosted\",\n variations: [],\n elementCount: {\n aboveFold: aboveElements.length,\n belowFold: belowElements.length,\n total: elements.length\n },\n urlCount: {\n aboveFold: /* @__PURE__ */ new Set(),\n belowFold: /* @__PURE__ */ new Set()\n }\n };\n }\n data.variations.forEach((variation) => {\n let matchingUrl = null;\n for (const styleUrl of data.urls) {\n const normalizedStyleUrl = this.cleanUrl(styleUrl);\n if (networkLoadedFonts.has(normalizedStyleUrl)) {\n matchingUrl = networkLoadedFonts.get(normalizedStyleUrl);\n break;\n }\n }\n allFonts[fontFamily].variations.push({\n weight: variation.weight,\n style: variation.style,\n url: matchingUrl || \"File not found\",\n elementCount: {\n aboveFold: aboveElements.length,\n belowFold: belowElements.length,\n total: elements.length\n }\n });\n if (matchingUrl) {\n if (aboveElements.length > 0) {\n allFonts[fontFamily].urlCount.aboveFold.add(matchingUrl);\n }\n if (belowElements.length > 0) {\n allFonts[fontFamily].urlCount.belowFold.add(matchingUrl);\n }\n }\n });\n if (!Object.prototype.hasOwnProperty.call(allFonts, fontFamily)) {\n return;\n }\n hostedFontsResults[fontFamily] = {\n variations: allFonts[fontFamily].variations,\n elementCount: { ...allFonts[fontFamily].elementCount },\n urlCount: { ...allFonts[fontFamily].urlCount }\n };\n }\n });\n }\n if (Object.keys(externalFontsResults).length > 0) {\n Object.entries(externalFontsResults).forEach(([url, data]) => {\n if (data.elementCount.aboveFold > 0) {\n data.variations.forEach((variation) => {\n if (!allFonts[variation.family]) {\n allFonts[variation.family] = {\n type: \"external\",\n variations: [],\n // Track element counts at font family level\n elementCount: {\n aboveFold: 0,\n belowFold: 0,\n total: 0\n },\n // Track unique URLs used in each fold location\n urlCount: {\n aboveFold: /* @__PURE__ */ new Set(),\n belowFold: /* @__PURE__ */ new Set()\n }\n };\n }\n const aboveElements = Array.from(data.elements).filter((el) => this.isElementAboveFold(el));\n const belowElements = Array.from(data.elements).filter((el) => !this.isElementAboveFold(el));\n allFonts[variation.family].variations.push({\n weight: variation.weight,\n style: variation.style,\n url,\n elementCount: {\n aboveFold: aboveElements.length,\n belowFold: belowElements.length,\n total: data.elements.length\n }\n });\n allFonts[variation.family].elementCount.aboveFold += aboveElements.length;\n allFonts[variation.family].elementCount.belowFold += belowElements.length;\n allFonts[variation.family].elementCount.total += data.elements.length;\n if (aboveElements.length > 0) {\n allFonts[variation.family].urlCount.aboveFold.add(url);\n }\n if (belowElements.length > 0) {\n allFonts[variation.family].urlCount.belowFold.add(url);\n }\n });\n }\n });\n }\n Object.values(allFonts).forEach((font) => {\n font.urlCount = {\n aboveFold: font.urlCount.aboveFold.size,\n belowFold: font.urlCount.belowFold.size,\n total: (/* @__PURE__ */ new Set([...font.urlCount.aboveFold, ...font.urlCount.belowFold])).size\n };\n });\n Object.values(hostedFontsResults).forEach((font) => {\n if (font.urlCount.aboveFold instanceof Set) {\n font.urlCount = {\n aboveFold: font.urlCount.aboveFold.size,\n belowFold: font.urlCount.belowFold.size,\n total: (/* @__PURE__ */ new Set([...font.urlCount.aboveFold, ...font.urlCount.belowFold])).size\n };\n }\n });\n return {\n externalFonts: Object.fromEntries(\n Object.entries(externalFontsResults).filter(\n (entry) => entry[1].elementCount.aboveFold > 0\n )\n ),\n hostedFonts: hostedFontsResults,\n allFonts\n };\n }\n /**\n * Processes external font pairs to identify their usage on the page.\n * \n * This method iterates through all elements on the page, checks if they are above the fold,\n * and determines the font information for each element. It then matches the font information\n * with the provided external font pairs to identify which fonts are used and where.\n * \n * @param {Object} fontPairs - An object where each key is a URL and the value is an array of font variations.\n * @returns {Promise} A promise that resolves to an object where each key is a URL and the value is an object containing information about the elements using that font.\n */\n async processExternalFonts(fontPairs) {\n const matches = /* @__PURE__ */ new Map();\n const elements = Array.from(document.getElementsByTagName(\"*\")).filter((el) => this.isElementAboveFold(el));\n const fontMap = /* @__PURE__ */ new Map();\n Object.entries(fontPairs).forEach(([url, variations]) => {\n variations.forEach((variation) => {\n const key = `${variation.family}|${variation.weight}|${variation.style}`;\n fontMap.set(key, { url, ...variation });\n });\n });\n const getFontInfoForElement = (style) => {\n const family = style.fontFamily.split(\",\")[0].replace(/['\"]+/g, \"\").trim();\n const weight = style.fontWeight;\n const fontStyle = style.fontStyle;\n const key = `${family}|${weight}|${fontStyle}`;\n let fontInfo = fontMap.get(key);\n if (!fontInfo && weight !== \"400\") {\n const fallbackKey = `${family}|400|${fontStyle}`;\n fontInfo = fontMap.get(fallbackKey);\n }\n return fontInfo;\n };\n elements.forEach((element) => {\n if (element.textContent.trim()) {\n const style = window.getComputedStyle(element);\n const fontInfo = getFontInfoForElement(style);\n if (fontInfo) {\n if (!matches.has(fontInfo.url)) {\n matches.set(fontInfo.url, {\n elements: /* @__PURE__ */ new Set(),\n variations: /* @__PURE__ */ new Set()\n });\n }\n matches.get(fontInfo.url).elements.add(element);\n matches.get(fontInfo.url).variations.add(JSON.stringify({\n family: fontInfo.family,\n weight: fontInfo.weight,\n style: fontInfo.style\n }));\n }\n }\n [\"::before\", \"::after\"].forEach((pseudo) => {\n const pseudoStyle = window.getComputedStyle(element, pseudo);\n if (pseudoStyle.content !== \"none\" && pseudoStyle.content !== '\"\"') {\n const fontInfo = getFontInfoForElement(pseudoStyle);\n if (fontInfo) {\n if (!matches.has(fontInfo.url)) {\n matches.set(fontInfo.url, {\n elements: /* @__PURE__ */ new Set(),\n variations: /* @__PURE__ */ new Set()\n });\n }\n matches.get(fontInfo.url).elements.add(element);\n matches.get(fontInfo.url).variations.add(JSON.stringify({\n family: fontInfo.family,\n weight: fontInfo.weight,\n style: fontInfo.style\n }));\n }\n }\n });\n });\n return Object.fromEntries(\n Array.from(matches.entries()).map(([url, data]) => [\n url,\n {\n elementCount: {\n aboveFold: Array.from(data.elements).filter((el) => this.isElementAboveFold(el)).length,\n total: data.elements.size\n },\n variations: Array.from(data.variations).map((v) => JSON.parse(v)),\n elements: Array.from(data.elements)\n }\n ])\n );\n }\n /**\n * Retrieves the results of the font analysis, specifically the fonts used above the fold.\n * This method returns an array containing the URLs of the fonts used above the fold.\n * \n * @returns {Array} An array of URLs of the fonts used above the fold.\n */\n getResults() {\n return this.aboveTheFoldFonts;\n }\n };\n var BeaconPreloadFonts_default = BeaconPreloadFonts;\n\n // src/BeaconPreconnectExternalDomain.js\n var BeaconPreconnectExternalDomain = class {\n constructor(config, logger) {\n this.logger = logger;\n this.result = [];\n this.excludedPatterns = config.preconnect_external_domain_exclusions;\n this.eligibleElements = config.preconnect_external_domain_elements;\n this.matchedItems = /* @__PURE__ */ new Set();\n this.excludedItems = /* @__PURE__ */ new Set();\n }\n /**\n * Initiates the process of identifying and logging external domains that require preconnection.\n * This method queries the document for eligible elements, processes each element to determine\n * if it should be preconnected, and logs the results.\n */\n async run() {\n const elements = document.querySelectorAll(\n `${this.eligibleElements.join(\", \")}[src], ${this.eligibleElements.join(\", \")}[href], ${this.eligibleElements.join(\", \")}[rel], ${this.eligibleElements.join(\", \")}[type]`\n );\n elements.forEach((el) => this.processElement(el));\n this.logger.logMessage({ matchedItems: this.getMatchedItems(), excludedItems: Array.from(this.excludedItems) });\n }\n /**\n * Processes a single element to determine if it should be preconnected.\n * \n * This method checks if the element is excluded based on attribute or domain rules.\n * If not excluded, it checks if the element's URL is an external domain and adds it to the list of matched items.\n * \n * @param {Element} el - The element to process.\n */\n processElement(el) {\n try {\n const url = new URL(el.src || el.href || \"\", location.href);\n if (this.isExcludedByAttribute(el)) {\n this.excludedItems.add(this.createExclusionObject(url, el, \"attribute\"));\n return;\n }\n if (this.isExcludedByDomain(url)) {\n this.excludedItems.add(this.createExclusionObject(url, el, \"domain\"));\n return;\n }\n if (this.isExternalDomain(url)) {\n this.matchedItems.add(`${url.hostname}-${el.tagName.toLowerCase()}`);\n this.result = [...new Set(this.result.concat(url.hostname))];\n }\n } catch (e) {\n this.logger.logMessage(e);\n }\n }\n /**\n * Checks if an element is excluded based on attribute rules.\n * \n * This method iterates through the excludedPatterns array and checks if any pattern matches the element's attribute.\n * If a match is found, it returns true, indicating the element is excluded.\n * \n * @param {Element} el - The element to check.\n * @returns {boolean} True if the element is excluded by an attribute rule, false otherwise.\n */\n isExcludedByAttribute(el) {\n return this.excludedPatterns.some(\n (pattern) => pattern.type === \"attribute\" && el.getAttribute(pattern.key) === pattern.value\n );\n }\n /**\n * Checks if a URL is excluded based on domain rules.\n * \n * This method iterates through the excludedPatterns array and checks if any pattern matches the URL's hostname.\n * If a match is found, it returns true, indicating the URL is excluded.\n * \n * @param {URL} url - The URL to check.\n * @returns {boolean} True if the URL is excluded by a domain rule, false otherwise.\n */\n isExcludedByDomain(url) {\n return this.excludedPatterns.some(\n (pattern) => pattern.type === \"domain\" && url.hostname.includes(pattern.value)\n );\n }\n /**\n * Checks if a URL is from an external domain.\n * \n * This method compares the hostname of the given URL with the hostname of the current location.\n * If they are not the same, it indicates the URL is from an external domain.\n * \n * @param {URL} url - The URL to check.\n * @returns {boolean} True if the URL is from an external domain, false otherwise.\n */\n isExternalDomain(url) {\n return url.hostname !== location.hostname && url.hostname;\n }\n /**\n * Creates an exclusion object based on the URL, element, and type.\n * \n * This method finds the pattern in the excludedPatterns array that matches the type and the element's attribute or the URL's hostname.\n * It then constructs a reason string based on the type and the pattern.\n * Finally, it returns an object with the URL's hostname, the element's tag name, and the reason.\n * \n * @param {URL} url - The URL to create the exclusion object for.\n * @param {Element} el - The element to create the exclusion object for.\n * @param {string} type - The type of the exclusion (attribute or domain).\n * @returns {Object} An object with the URL's hostname, the element's tag name, and the reason.\n */\n createExclusionObject(url, el, type) {\n const pattern = this.excludedPatterns.find(\n (p) => type === \"attribute\" && el.getAttribute(p.key) === p.value || type === \"domain\" && url.hostname.includes(p.value)\n );\n let reason = type === \"attribute\" ? `${pattern.key}=${pattern.value}` : `domain-partial=${pattern.value}`;\n return { domain: url.hostname, elementType: el.tagName.toLowerCase(), reason };\n }\n /**\n * Returns an array of matched items, each item split into its domain and element type.\n * \n * This method iterates through the matchedItems set, splits each item into its domain and element type using the last hyphen as a delimiter,\n * and returns an array of these split items.\n * \n * @returns {Array} An array of arrays, each containing a domain and an element type.\n */\n getMatchedItems() {\n return Array.from(this.matchedItems).map((item) => {\n const lastHyphenIndex = item.lastIndexOf(\"-\");\n return [\n item.substring(0, lastHyphenIndex),\n // Domain\n item.substring(lastHyphenIndex + 1)\n // Element type\n ];\n });\n }\n /**\n * Returns the array of unique domain names that were found to be external.\n * \n * This method returns the result array, which contains a list of unique domain names that were identified as external during the analysis process.\n * \n * @returns {Array} An array of unique domain names.\n */\n getResults() {\n return this.result;\n }\n };\n var BeaconPreconnectExternalDomain_default = BeaconPreconnectExternalDomain;\n\n // src/Logger.js\n var Logger = class {\n constructor(enabled) {\n this.enabled = enabled;\n }\n logMessage(label, msg = \"\") {\n if (!this.enabled) {\n return;\n }\n if (msg !== \"\") {\n console.log(label, msg);\n return;\n }\n console.log(label);\n }\n logColoredMessage(msg, color = \"green\") {\n if (!this.enabled) {\n return;\n }\n console.log(`%c${msg}`, `color: ${color};`);\n }\n };\n var Logger_default = Logger;\n\n // src/BeaconManager.js\n var BeaconManager = class {\n constructor(config) {\n this.config = config;\n this.lcpBeacon = null;\n this.lrcBeacon = null;\n this.preloadFontsBeacon = null;\n this.preconnectExternalDomainBeacon = null;\n this.infiniteLoopId = null;\n this.errorCode = \"\";\n this.logger = new Logger_default(this.config.debug);\n }\n async init() {\n this.scriptTimer = /* @__PURE__ */ new Date();\n if (!await this._isValidPreconditions()) {\n this._finalize();\n return;\n }\n if (Utils_default.isPageScrolled()) {\n this.logger.logMessage(\"Bailing out because the page has been scrolled\");\n this._finalize();\n return;\n }\n this.infiniteLoopId = setTimeout(() => {\n this._handleInfiniteLoop();\n }, 1e4);\n const isGeneratedBefore = await this._getGeneratedBefore();\n const shouldGenerateLcp = this.config.status.atf && (isGeneratedBefore === false || isGeneratedBefore.lcp === false);\n const shouldGeneratelrc = this.config.status.lrc && (isGeneratedBefore === false || isGeneratedBefore.lrc === false);\n const shouldGeneratePreloadFonts = this.config.status.preload_fonts && (isGeneratedBefore === false || isGeneratedBefore.preload_fonts === false);\n const shouldGeneratePreconnectExternalDomain = this.config.status.preconnect_external_domain && (isGeneratedBefore === false || isGeneratedBefore.preconnect_external_domain === false);\n if (shouldGenerateLcp) {\n this.lcpBeacon = new BeaconLcp_default(this.config, this.logger);\n await this.lcpBeacon.run();\n } else {\n this.logger.logMessage(\"Not running BeaconLcp because data is already available or feature is disabled\");\n }\n if (shouldGeneratelrc) {\n this.lrcBeacon = new BeaconLrc_default(this.config, this.logger);\n await this.lrcBeacon.run();\n } else {\n this.logger.logMessage(\"Not running BeaconLrc because data is already available or feature is disabled\");\n }\n if (shouldGeneratePreloadFonts) {\n this.preloadFontsBeacon = new BeaconPreloadFonts_default(this.config, this.logger);\n await this.preloadFontsBeacon.run();\n } else {\n this.logger.logMessage(\"Not running BeaconPreloadFonts because data is already available or feature is disabled\");\n }\n if (shouldGeneratePreconnectExternalDomain) {\n this.preconnectExternalDomainBeacon = new BeaconPreconnectExternalDomain_default(this.config, this.logger);\n await this.preconnectExternalDomainBeacon.run();\n } else {\n this.logger.logMessage(\"Not running BeaconPreconnectExternalDomain because data is already available or feature is disabled\");\n }\n if (shouldGenerateLcp || shouldGeneratelrc || shouldGeneratePreloadFonts || shouldGeneratePreconnectExternalDomain) {\n this._saveFinalResultIntoDB();\n } else {\n this.logger.logMessage(\"Not saving results into DB as no beacon features ran.\");\n this._finalize();\n }\n }\n async _isValidPreconditions() {\n const threshold = {\n width: this.config.width_threshold,\n height: this.config.height_threshold\n };\n if (Utils_default.isNotValidScreensize(this.config.is_mobile, threshold)) {\n this.logger.logMessage(\"Bailing out because screen size is not acceptable\");\n return false;\n }\n return true;\n }\n async _getGeneratedBefore() {\n if (!Utils_default.isPageCached()) {\n return false;\n }\n let data_check = new FormData();\n data_check.append(\"action\", \"rocket_check_beacon\");\n data_check.append(\"rocket_beacon_nonce\", this.config.nonce);\n data_check.append(\"url\", this.config.url);\n data_check.append(\"is_mobile\", this.config.is_mobile);\n const beacon_data_response = await fetch(this.config.ajax_url, {\n method: \"POST\",\n credentials: \"same-origin\",\n body: data_check\n }).then((data) => data.json());\n return beacon_data_response.data;\n }\n _saveFinalResultIntoDB() {\n const results = {\n lcp: this.lcpBeacon ? this.lcpBeacon.getResults() : null,\n lrc: this.lrcBeacon ? this.lrcBeacon.getResults() : null,\n preload_fonts: this.preloadFontsBeacon ? this.preloadFontsBeacon.getResults() : null,\n preconnect_external_domain: this.preconnectExternalDomainBeacon ? this.preconnectExternalDomainBeacon.getResults() : null\n };\n const data = new FormData();\n data.append(\"action\", \"rocket_beacon\");\n data.append(\"rocket_beacon_nonce\", this.config.nonce);\n data.append(\"url\", this.config.url);\n data.append(\"is_mobile\", this.config.is_mobile);\n data.append(\"status\", this._getFinalStatus());\n data.append(\"results\", JSON.stringify(results));\n fetch(this.config.ajax_url, {\n method: \"POST\",\n credentials: \"same-origin\",\n body: data,\n headers: {\n \"wpr-saas-no-intercept\": true\n }\n }).then((response) => response.json()).then((data2) => {\n this.logger.logMessage(data2.data.lcp);\n }).catch((error) => {\n this.logger.logMessage(error);\n }).finally(() => {\n this._finalize();\n });\n }\n _getFinalStatus() {\n if (\"\" !== this.errorCode) {\n return this.errorCode;\n }\n const scriptTime = (/* @__PURE__ */ new Date() - this.scriptTimer) / 1e3;\n if (10 <= scriptTime) {\n return \"timeout\";\n }\n return \"success\";\n }\n _handleInfiniteLoop() {\n this._saveFinalResultIntoDB();\n }\n _finalize() {\n const beaconscript = document.querySelector('[data-name=\"wpr-wpr-beacon\"]');\n beaconscript.setAttribute(\"beacon-completed\", \"true\");\n clearTimeout(this.infiniteLoopId);\n }\n };\n var BeaconManager_default = BeaconManager;\n\n // src/BeaconEntryPoint.js\n ((rocket_beacon_data) => {\n if (!rocket_beacon_data) {\n return;\n }\n const instance = new BeaconManager_default(rocket_beacon_data);\n if (document.readyState !== \"loading\") {\n setTimeout(() => {\n instance.init();\n }, rocket_beacon_data.delay);\n return;\n }\n document.addEventListener(\"DOMContentLoaded\", () => {\n setTimeout(() => {\n instance.init();\n }, rocket_beacon_data.delay);\n });\n })(window.rocket_beacon_data);\n var BeaconEntryPoint_default = BeaconManager_default;\n})();\n"], + "mappings": "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", + "names": ["BeaconUtils", "is_mobile", "threshold", "screenWidth", "screenHeight", "isNotValidForMobile", "isNotValidForDesktop", "signature", "rect", "Utils_default", "BeaconLcp", "config", "logger", "above_the_fold_images", "err", "count", "lcpElements", "element", "imgElement", "item", "a", "b", "candidate", "visibleWidth", "visibleHeight", "nodeName", "element_info", "css_bg_url_rgx", "source", "imageElement", "img", "bg_props", "prop", "full_bg_prop", "matches", "m", "elements", "firstElementWithInfo", "elementInfo", "image", "isImageOrVideo", "isBgImageOrPicture", "BeaconLcp_default", "BeaconLrc", "elementsInView", "svgUseTargets", "depth", "parent", "scrollTop", "skipStrings", "str", "exclusions", "i", "attribute", "pattern", "attributeValue", "conflictingElements", "computedStyle", "negativeMargins", "margin", "child", "childStyle", "childNegativeMargins", "distance", "hash", "conflicts", "can_push_hash", "color", "position", "pos", "sibling", "useElements", "targets", "use", "BeaconLrc_default", "BeaconPreloadFonts", "extensions", "ext", "fontFamily", "style", "url", "resource", "stylesheetFonts", "sheet", "rule", "src", "weight", "urlMatch", "rawUrl", "normalizedUrl", "e", "fontData", "v", "elementTop", "foldPosition", "networkLoadedFonts", "hostedFonts", "externalFontPairs", "externalFontsResults", "el", "processElementFont", "pseudoElement", "pseudo", "aboveTheFoldFonts", "font", "variation", "allFonts", "hostedFontsResults", "data", "aboveElements", "belowElements", "matchingUrl", "styleUrl", "normalizedStyleUrl", "entry", "fontPairs", "fontMap", "variations", "key", "getFontInfoForElement", "family", "fontStyle", "fontInfo", "fallbackKey", "pseudoStyle", "BeaconPreloadFonts_default", "BeaconPreconnectExternalDomain", "type", "p", "reason", "lastHyphenIndex", "BeaconPreconnectExternalDomain_default", "Logger", "enabled", "label", "msg", "Logger_default", "BeaconManager", "isGeneratedBefore", "shouldGenerateLcp", "shouldGeneratelrc", "shouldGeneratePreloadFonts", "shouldGeneratePreconnectExternalDomain", "data_check", "results", "response", "data2", "error", "BeaconManager_default", "rocket_beacon_data", "instance", "BeaconEntryPoint_default"] } diff --git a/inc/Engine/Media/PreloadFonts/Frontend/Controller.php b/inc/Engine/Media/PreloadFonts/Frontend/Controller.php index c87e090c5b..77b6be1886 100644 --- a/inc/Engine/Media/PreloadFonts/Frontend/Controller.php +++ b/inc/Engine/Media/PreloadFonts/Frontend/Controller.php @@ -119,9 +119,23 @@ public function add_custom_data( array $data ): array { */ $font_data = wpm_apply_filters_typed( 'array', 'rocket_preload_fonts_font_data', [] ); + $processed_extensions = [ + 'woff2', + 'woff', + 'ttf', + ]; + + /** + * Filters the list of processed font extensions. + * + * @param string[] $processed_extensions Array of processed font extensions. + */ + $processed_extensions = wpm_apply_filters_typed( 'string[]', 'rocket_preload_fonts_processed_extensions', $processed_extensions ); + $data['system_fonts'] = $system_fonts; $data['font_data'] = $font_data; $data['status']['preload_fonts'] = $this->context->is_allowed(); + $data['processed_extensions'] = $processed_extensions; return $data; } diff --git a/tests/Fixtures/inc/Engine/Common/PerformanceHints/Frontend/Subscriber/HTML/no_closing_body_tag_output.html b/tests/Fixtures/inc/Engine/Common/PerformanceHints/Frontend/Subscriber/HTML/no_closing_body_tag_output.html index 7f3be68d36..d8a6e4d05d 100644 --- a/tests/Fixtures/inc/Engine/Common/PerformanceHints/Frontend/Subscriber/HTML/no_closing_body_tag_output.html +++ b/tests/Fixtures/inc/Engine/Common/PerformanceHints/Frontend/Subscriber/HTML/no_closing_body_tag_output.html @@ -1,9 +1,11 @@ - Test + + Test - + diff --git a/tests/Fixtures/inc/Engine/Common/PerformanceHints/Frontend/Subscriber/HTML/output_double_body_tag.html b/tests/Fixtures/inc/Engine/Common/PerformanceHints/Frontend/Subscriber/HTML/output_double_body_tag.html index 3154944029..0f6e21a833 100644 --- a/tests/Fixtures/inc/Engine/Common/PerformanceHints/Frontend/Subscriber/HTML/output_double_body_tag.html +++ b/tests/Fixtures/inc/Engine/Common/PerformanceHints/Frontend/Subscriber/HTML/output_double_body_tag.html @@ -1,22 +1,29 @@ - Test + + Test - - + + + + diff --git a/tests/Fixtures/inc/Engine/Common/PerformanceHints/Frontend/Subscriber/HTML/output_preload_fonts.html b/tests/Fixtures/inc/Engine/Common/PerformanceHints/Frontend/Subscriber/HTML/output_preload_fonts.html index 0deaccf6fb..166b3833ba 100644 --- a/tests/Fixtures/inc/Engine/Common/PerformanceHints/Frontend/Subscriber/HTML/output_preload_fonts.html +++ b/tests/Fixtures/inc/Engine/Common/PerformanceHints/Frontend/Subscriber/HTML/output_preload_fonts.html @@ -1,10 +1,16 @@ - - Test - - - - - - + + + Test + + + + + + + + + diff --git a/tests/Fixtures/inc/Engine/Common/PerformanceHints/Frontend/Subscriber/HTML/output_preload_fonts_w_crossorigin.html b/tests/Fixtures/inc/Engine/Common/PerformanceHints/Frontend/Subscriber/HTML/output_preload_fonts_w_crossorigin.html index 1171596420..abe2a062d0 100644 --- a/tests/Fixtures/inc/Engine/Common/PerformanceHints/Frontend/Subscriber/HTML/output_preload_fonts_w_crossorigin.html +++ b/tests/Fixtures/inc/Engine/Common/PerformanceHints/Frontend/Subscriber/HTML/output_preload_fonts_w_crossorigin.html @@ -1,10 +1,16 @@ - - Test - - - - - - + + + Test + + + + + + + + + diff --git a/tests/Fixtures/inc/Engine/Common/PerformanceHints/Frontend/Subscriber/HTML/output_preload_fonts_w_relative_path.html b/tests/Fixtures/inc/Engine/Common/PerformanceHints/Frontend/Subscriber/HTML/output_preload_fonts_w_relative_path.html index a47615d371..1f64fad081 100644 --- a/tests/Fixtures/inc/Engine/Common/PerformanceHints/Frontend/Subscriber/HTML/output_preload_fonts_w_relative_path.html +++ b/tests/Fixtures/inc/Engine/Common/PerformanceHints/Frontend/Subscriber/HTML/output_preload_fonts_w_relative_path.html @@ -1,10 +1,16 @@ - - Test - - - - - - + + + Test + + + + + + + + + diff --git a/tests/Fixtures/inc/Engine/Common/PerformanceHints/Frontend/Subscriber/HTML/output_w_beacon.html b/tests/Fixtures/inc/Engine/Common/PerformanceHints/Frontend/Subscriber/HTML/output_w_beacon.html index fee0400b5d..341833a2f3 100644 --- a/tests/Fixtures/inc/Engine/Common/PerformanceHints/Frontend/Subscriber/HTML/output_w_beacon.html +++ b/tests/Fixtures/inc/Engine/Common/PerformanceHints/Frontend/Subscriber/HTML/output_w_beacon.html @@ -1,7 +1,12 @@ - Test + + Test - + + + diff --git a/tests/Fixtures/inc/Engine/Common/PerformanceHints/Frontend/Subscriber/HTML/output_w_beacon_external_disabled.html b/tests/Fixtures/inc/Engine/Common/PerformanceHints/Frontend/Subscriber/HTML/output_w_beacon_external_disabled.html index a6c1f2eb0e..9b67c5180f 100644 --- a/tests/Fixtures/inc/Engine/Common/PerformanceHints/Frontend/Subscriber/HTML/output_w_beacon_external_disabled.html +++ b/tests/Fixtures/inc/Engine/Common/PerformanceHints/Frontend/Subscriber/HTML/output_w_beacon_external_disabled.html @@ -1,7 +1,11 @@ - Test +Test - - + + + + \ No newline at end of file diff --git a/tests/Fixtures/inc/Engine/Common/PerformanceHints/Frontend/Subscriber/HTML/output_with_beacon_and_atf_opt.html b/tests/Fixtures/inc/Engine/Common/PerformanceHints/Frontend/Subscriber/HTML/output_with_beacon_and_atf_opt.html index b5387a6eaf..a27feae7cf 100644 --- a/tests/Fixtures/inc/Engine/Common/PerformanceHints/Frontend/Subscriber/HTML/output_with_beacon_and_atf_opt.html +++ b/tests/Fixtures/inc/Engine/Common/PerformanceHints/Frontend/Subscriber/HTML/output_with_beacon_and_atf_opt.html @@ -1,8 +1,14 @@ - LCP/ATF image test + + LCP/ATF image test + Sample alt - + + + diff --git a/tests/Fixtures/inc/Engine/Common/PerformanceHints/Frontend/Subscriber/HTML/output_with_beacon_and_only_lrc_opt.html b/tests/Fixtures/inc/Engine/Common/PerformanceHints/Frontend/Subscriber/HTML/output_with_beacon_and_only_lrc_opt.html index 3ccea1dc88..49ac1e9643 100644 --- a/tests/Fixtures/inc/Engine/Common/PerformanceHints/Frontend/Subscriber/HTML/output_with_beacon_and_only_lrc_opt.html +++ b/tests/Fixtures/inc/Engine/Common/PerformanceHints/Frontend/Subscriber/HTML/output_with_beacon_and_only_lrc_opt.html @@ -1,12 +1,20 @@ - Test - + + Test + -
-
-
-
- +
+
+
+
+
+
+ + +