1const findFirstImageUrl = (blocks) => { 2 if (!blocks || !Array.isArray(blocks) || blocks.length === 0) { 3 return null; 4 } 5 const searchBlock = (block) => { 6 if (!block || typeof block !== "object") return null; 7 const imageFields = [ 8 "src", 9 "image", 10 "url", 11 "backgroundImage", 12 "backgroundMediaSrc" 13 ]; 14 for (const field of imageFields) { 15 if (block[field]) { 16 const imageValue = block[field]; 17 if (typeof imageValue === "string" && imageValue.startsWith("http")) { 18 return imageValue; 19 } 20 if (typeof imageValue === "object" && imageValue.src && imageValue.src.startsWith("http")) { 21 return imageValue.src; 22 } 23 } 24 } 25 if (block.settings) { 26 const settingsResult = searchBlock(block.settings); 27 if (settingsResult) return settingsResult; 28 } 29 if (block.heroBackgroundMediaSrc && Array.isArray(block.heroBackgroundMediaSrc) && block.heroBackgroundMediaSrc.length > 0) { 30 const firstMedia = block.heroBackgroundMediaSrc[0]; 31 if ((firstMedia == null ? void 0 : firstMedia.src) && firstMedia.src.startsWith("http")) { 32 return firstMedia.src; 33 } 34 } 35 if (block.placeholderImageMobile) { 36 const placeholder = block.placeholderImageMobile; 37 if (typeof placeholder === "string" && placeholder.startsWith("http")) { 38 return placeholder; 39 } 40 if (typeof placeholder === "object" && placeholder.src && placeholder.src.startsWith("http")) { 41 return placeholder.src; 42 } 43 } 44 if (block.blocks && Array.isArray(block.blocks)) { 45 for (const nestedBlock of block.blocks) { 46 const nestedResult = searchBlock(nestedBlock); 47 if (nestedResult) return nestedResult; 48 } 49 } 50 return null; 51 }; 52 for (const block of blocks) { 53 const result = searchBlock(block); 54 if (result) return result; 55 } 56 return null; 57}; 58const nuxtConfigScripts = [ 59 { 60 src: "https://assets.calendly.com/assets/external/widget.js" 61 } 62]; 63const FONT_CDN_BASE = "https://f92core-nylwebsites.azureedge.net/3/uploads/fonts"; 64const FONT_CDN_ORIGIN = "https://f92core-nylwebsites.azureedge.net"; 65const FONT_THEME_PRELOAD_MAP = { 66 "alda-effra": [ 67 { href: `${FONT_CDN_BASE}/EffraPro_Rg.ttf`, type: "font/ttf" }, 68 { href: `${FONT_CDN_BASE}/EffraPro_Bd.ttf`, type: "font/ttf" }, 69 { 70 href: `${FONT_CDN_BASE}/Alda%20Pro-Regular.otf`, 71 type: "font/otf" 72 } 73 ], 74 "georgia-effra": [ 75 { href: `${FONT_CDN_BASE}/EffraPro_Rg.ttf`, type: "font/ttf" }, 76 { href: `${FONT_CDN_BASE}/EffraPro_Bd.ttf`, type: "font/ttf" } 77 ], 78 "jost-pt-serif": [ 79 { href: `${FONT_CDN_BASE}/Jost-Regular.ttf`, type: "font/ttf" }, 80 { href: `${FONT_CDN_BASE}/Jost-Bold.ttf`, type: "font/ttf" }, 81 { href: `${FONT_CDN_BASE}/PTSerif-Regular.ttf`, type: "font/ttf" } 82 ], 83 "gfs-didot-lato": [ 84 { href: `${FONT_CDN_BASE}/GFSDidot-Regular.ttf`, type: "font/ttf" } 85 ] 86}; 87const generateFontPreloadLinks = (fontThemeTitle) => { 88 if (!fontThemeTitle) return []; 89 const fonts = FONT_THEME_PRELOAD_MAP[fontThemeTitle]; 90 if (!fonts || fonts.length === 0) return []; 91 const links = [ 92 { rel: "preconnect", href: FONT_CDN_ORIGIN }, 93 { rel: "dns-prefetch", href: FONT_CDN_ORIGIN } 94 ]; 95 fonts.forEach(({ href, type }) => { 96 links.push({ 97 rel: "preload", 98 href, 99 as: "font", 100 type, 101 crossorigin: "anonymous" 102 }); 103 }); 104 return links; 105}; 106const extractScriptDomains = (scripts) => { 107 const domains = /* @__PURE__ */ new Set(); 108 if (!scripts || !Array.isArray(scripts)) { 109 return domains; 110 } 111 scripts.forEach((script) => { 112 if (script == null ? void 0 : script.src) { 113 try { 114 const url = new URL(script.src); 115 domains.add(url.origin); 116 } catch { 117 } 118 } 119 }); 120 return domains; 121}; 122const addDisplaySwapToFontUrl = (url) => { 123 if (!url) return url; 124 if (url.includes("display=")) { 125 return url.replace(/display=[^&]*/, "display=swap"); 126 } 127 const separator = url.includes("?") ? "&" : "?"; 128 return `${url}${separator}display=swap`; 129}; 130const extractCdnDomainFromUrl = (imageUrl) => { 131 if (!imageUrl || typeof imageUrl !== "string") return null; 132 try { 133 const url = new URL(imageUrl); 134 if (url.hostname.includes("azureedge.net")) { 135 return url.origin; 136 } 137 } catch { 138 } 139 return null; 140}; 141const applyDeferToScripts = (scripts) => { 142 if (!scripts || !Array.isArray(scripts)) { 143 return []; 144 } 145 return scripts.map((script) => { 146 var _a; 147 if ((_a = script.src) == null ? void 0 : _a.includes("cookielaw.org")) { 148 return script; 149 } 150 return { 151 ...script, 152 defer: true 153 }; 154 }); 155}; 156const DEFAULT_GOOGLE_FONTS = [ 157 "https://fonts.googleapis.com/css2?family=Montserrat:wght@100;200;300;400;500;600;700;800;900&display=swap", 158 "https://fonts.googleapis.com/css2?family=Lora:ital,wght@0,400;0,700;1,400;1,700&family=Work+Sans:ital,wght@0,400;0,700;1,400;1,700&display=swap" 159]; 160const EXTERNAL_LIB_FONT_PRELOADS = [ 161 {
162 href: "https://fonts.gstatic.com/s/roboto/v48/KFO7CnqEu92Fr1ME7kSn66aGLdTylUAMa3yUBHMdazQ.woff2", 163 type: "font/woff2", 164 label: "Roboto (Calendly)", 165 fontFamily: "Roboto", 166 fontWeight: 400, 167 fontStyle: "normal" 168 } 169]; 170const getExternalLibFontStyles = () => EXTERNAL_LIB_FONT_PRELOADS.filter((f) => f.fontFamily).map( 171 ({ href, type, fontFamily, fontWeight, fontStyle }) => `@font-face{font-family:'${fontFamily}';font-style:${fontStyle};font-weight:${fontWeight};font-display:swap;src:url('${href}') format('${type.split("/")[1]}')}` 172).join(""); 173const generateAsyncCssLinks = (mobileSettingsEnabled = false) => { 174 const calendlyCss = "https://calendly.com/assets/external/widget.css"; 175 if (mobileSettingsEnabled) { 176 const asyncFontLinks = DEFAULT_GOOGLE_FONTS.flatMap((href) => [ 177 { rel: "preload", href, as: "style" }, 178 { rel: "stylesheet", href, media: "print" } 179 ]); 180 return [ 181 ...asyncFontLinks, 182 { 183 rel: "preload", 184 href: calendlyCss, 185 as: "style" 186 }, 187 { 188 rel: "stylesheet", 189 href: calendlyCss, 190 media: "print" 191 }, 192 { 193 rel: "stylesheet", 194 href: calendlyCss, 195 tagPosition: "bodyClose" 196 } 197 ]; 198 } 199 return [ 200 { 201 rel: "stylesheet", 202 href: calendlyCss 203 } 204 ]; 205}; 206const generateAllPerformanceLinks = ({ 207 existingLinks = [], 208 scripts = [], 209 googleFonts = [], 210 imageUrl = null, 211 pageBlocks = null, 212 pageFavicon = null, 213 mobileSettingsEnabled = false, 214 fontThemeTitle = null 215}) => { 216 const links = []; 217 const addedUrls = /* @__PURE__ */ new Set(); 218 const addedDomains = /* @__PURE__ */ new Set(); 219 const getLinkKey = (link) => { 220 if (link.href) { 221 return `${link.rel}-${link.href}`; 222 } 223 return `${link.rel}-${JSON.stringify(link)}`; 224 }; 225 const normalizeGoogleFontsUrl = (url) => { 226 if (!url || typeof url !== "string") return url; 227 return url.replace(/[?&]display=[^&]*/, "").replace(/&$/, ""); 228 }; 229 const isGoogleFontsUrlMatch = (url1, url2) => { 230 if (!url1 || !url2) return false; 231 if (url1.includes("fonts.googleapis.com") && url2.includes("fonts.googleapis.com")) { 232 return normalizeGoogleFontsUrl(url1) === normalizeGoogleFontsUrl(url2); 233 } 234 return false; 235 }; 236 const linkExists = (link, checkAgainstExisting = false) => { 237 const key = getLinkKey(link); 238 if (addedUrls.has(key)) return true; 239 if (checkAgainstExisting) { 240 return links.some((existing) => { 241 if (link.href && existing.href) { 242 if (link.rel === "stylesheet" && existing.rel === "stylesheet" && isGoogleFontsUrlMatch(existing.href, link.href)) { 243 return true; 244 } 245 return existing.href === link.href && existing.rel === link.rel; 246 } 247 return getLinkKey(existing) === key; 248 }); 249 } 250 return false; 251 }; 252 const addLink = (link, checkAgainstExisting = false) => { 253 if (!linkExists(link, checkAgainstExisting)) { 254 links.push(link); 255 addedUrls.add(getLinkKey(link)); 256 if (link.href) { 257 try { 258 const url = new URL(link.href); 259 addedDomains.add(url.origin); 260 } catch { 261 } 262 } 263 } 264 }; 265 existingLinks.forEach((link) => { 266 if (link && link.href) { 267 addLink(link); 268 } 269 }); 270 if (mobileSettingsEnabled) { 271 if (fontThemeTitle) { 272 const fontPreloadLinks = generateFontPreloadLinks(fontThemeTitle); 273 fontPreloadLinks.forEach((link) => addLink(link)); 274 } 275 if (imageUrl) { 276 const cdnDomain = extractCdnDomainFromUrl(imageUrl); 277 if (cdnDomain && !addedDomains.has(cdnDomain)) { 278 addLink({ 279 rel: "preconnect", 280 href: cdnDomain 281 }); 282 addLink({ 283 rel: "dns-prefetch", 284 href: cdnDomain 285 }); 286 } 287 } 288 let lcpImageUrl = imageUrl; 289 if (!lcpImageUrl && pageBlocks) { 290 lcpImageUrl = findFirstImageUrl(pageBlocks); 291 } 292 if (lcpImageUrl) { 293 addLink({ 294 rel: "preload", 295 href: lcpImageUrl, 296 as: "image", 297 fetchpriority: "high" 298 }); 299 } 300 const scriptDomains = /* @__PURE__ */ new Set(); 301 const dynamicScriptDomains = extractScriptDomains(scripts); 302 dynamicScriptDomains.forEach((domain) => scriptDomains.add(domain)); 303 const nuxtConfigDomains = extractScriptDomains(nuxtConfigScripts); 304 nuxtConfigDomains.forEach((domain) => scriptDomains.add(domain)); 305 scriptDomains.forEach((domain) => { 306 if (!addedDomains.has(domain)) { 307 addLink({ 308 rel: "preconnect", 309 href: domain 310 }); 311 } 312 }); 313 } 314 if (googleFonts && googleFonts.length > 0) { 315 if (mobileSettingsEnabled) { 316 const fontsGoogleapis = "https://fonts.googleapis.com";
317 const fontsGstatic = "https://fonts.gstatic.com"; 318 if (!addedDomains.has(fontsGoogleapis)) { 319 addLink({ 320 rel: "preconnect", 321 href: fontsGoogleapis 322 }); 323 } 324 if (!addedDomains.has(fontsGstatic)) { 325 addLink({ 326 rel: "preconnect", 327 href: fontsGstatic, 328 crossorigin: "anonymous" 329 }); 330 } 331 googleFonts.forEach((url) => { 332 const modifiedUrl = addDisplaySwapToFontUrl(url); 333 addLink( 334 { 335 rel: "stylesheet", 336 href: modifiedUrl 337 }, 338 true 339 ); 340 }); 341 } else { 342 googleFonts.forEach((url) => { 343 addLink( 344 { 345 rel: "stylesheet", 346 href: url 347 }, 348 true 349 ); 350 }); 351 } 352 } 353 if (pageFavicon) { 354 addLink({ 355 rel: "icon", 356 type: "image/x-icon", 357 href: pageFavicon 358 }); 359 } 360 return links; 361}; 362export { 363 addDisplaySwapToFontUrl, 364 applyDeferToScripts, 365 generateAllPerformanceLinks, 366 generateAsyncCssLinks, 367 generateFontPreloadLinks, 368 getExternalLibFontStyles 369};
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.