1(function (root, factory) { 2 const api = factory(); 3 4 if (typeof module === 'object' && module.exports) { 5 module.exports = api; 6 } 7 8 if (root) { 9 root.Desk2QuantProductSeo = api; 10 } 11})(typeof globalThis !== 'undefined' ? globalThis : this, function () { 12 'use strict'; 13 14 const SITE_URL = 'https://desk2quant.com'; 15 const COMPLETE_BUNDLE_ID = '164308cd-e3cd-4026-8fdc-337a5955ffff'; 16 const VOL_SURFACE_PRODUCT_ID = '928a14d2-64b4-4a73-951d-dcf191fe72ad'; 17 const VOL_SURFACE_SEO_IMAGE = `${SITE_URL}/assets/images/blog-heston-vol-surface.png`; 18 19 // Product IDs are stable even when marketing names change. Keep the most 20 // valuable search landing pages on short, durable URLs and fall back to a 21 // deterministic name-based slug for the rest of the catalog. 22 const CURATED_SLUGS_BY_ID = Object.freeze({ 23 '73806d69-768b-497e-87b7-d94fa4cfd772': 'quant-interview-problem-book', 24 'c3e4c5cc-6616-4728-b979-782bec4d8811': 'cpp-for-quants', 25 '9ad9f8ac-9872-40c3-82b8-1e6168e65062': 'python-for-quants', 26 '6f4d2332-a1d0-4638-9307-0e2d9fe7453d': 'stochastic-calculus-for-quants', 27 '6b78550d-e130-41d1-9409-92335ce82a6c': 'numerical-methods-for-quants', 28 'a778e6ae-43d1-4cbd-a6a7-6dce693e5f69': 'model-validation-quant-interview', 29 '146ecb42-3df6-41de-a499-14c22b1bd36d': 'pnl-attribution-for-quants', 30 '351aa09b-681b-4da9-9b61-844cf295640c': 'xva-calculus-lab' 31 }); 32 33 function slugifyProductName(name) { 34 return String(name || '') 35 .toLowerCase() 36 .replace(/&/g, ' and ') 37 .replace(/\+/g, ' plus ') 38 .replace(/[^a-z0-9]+/g, '-') 39 .replace(/^-+|-+$/g, '') 40 .slice(0, 70) 41 .replace(/-+$/g, '') || 'product'; 42 } 43 44 function getProductSlug(product) { 45 const id = product && product.id != null ? String(product.id) : ''; 46 return CURATED_SLUGS_BY_ID[id] || slugifyProductName(product && product.name); 47 } 48 49 function getProductPath(product) { 50 return `/products/${getProductSlug(product)}.html`; 51 } 52 53 function getProductUrl(product) { 54 return `${SITE_URL}${getProductPath(product)}`; 55 } 56 57 function getProductSeoImage(product, fallback = `${SITE_URL}/assets/images/desk2quant-logo.png`) { 58 const image = product && product.cover_image_url; 59 // Merchant listings don't accept SVG product images. The Vol Surface 60 // product historically uses an inline/hosted SVG cover, so route only 61 // that legacy SVG to an existing crawlable PNG. Preserve any future 62 // raster replacement and every other product's cover unchanged. 63 if (product && product.id === VOL_SURFACE_PRODUCT_ID) { 64 const normalized = typeof image === 'string' ? image.trim() : ''; 65 if (!normalized || /^data:image\/svg\+xml/i.test(normalized) || 66 /\.svg(?:[?#]|$)/i.test(normalized)) { 67 return VOL_SURFACE_SEO_IMAGE; 68 } 69 } 70 return image || fallback; 71 } 72 73 // product.html already loads this tiny bootstrap before the product data. 74 // Use it to load conversion modules only for the Complete Bundle, leaving 75 // all other product pages and checkout code untouched. 76 if (typeof document !== 'undefined' && typeof window !== 'undefined') { 77 try { 78 const productId = String(new URLSearchParams(window.location.search).get('id') || '') 79 .replace(/^['"]|['"]$/g, ''); 80 if (productId === COMPLETE_BUNDLE_ID) { 81 const modules = [ 82 ['bundle-product-v2-script', '/bundle-product-v2.js?v=20260927a'], 83 ['bundle-proof-v3-script', '/bundle-proof-v3.js?v=20260927a'], 84 ['bundle-polish-v4-script', '/bundle-polish-v4.js?v=20260927a'] 85 ]; 86 modules.forEach(([id, src]) => { 87 if (document.getElementById(id)) return; 88 const script = document.createElement('script'); 89 script.id = id; 90 script.src = src; 91 script.defer = true; 92 document.head.appendChild(script); 93 }); 94 } 95 } catch (_) { 96 // SEO helpers must remain usable even if enhancement loading fails. 97 } 98 } 99 100 return Object.freeze({ 101 SITE_URL, 102 CURATED_SLUGS_BY_ID, 103 slugifyProductName, 104 getProductSlug, 105 getProductPath, 106 getProductUrl, 107 getProductSeoImage 108 }); 109});
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.