1<!doctype html> 2<html lang="en"> 3 <head> 4 <meta charset="UTF-8" /> 5 <link rel="icon" type="image/svg+xml" href="/vite.svg" /> 6 <meta name="generator" content="Hostinger Horizons" /> 7 <meta name="viewport" content="width=device-width, initial-scale=1.0" /> 8 9 <!-- Google tag (gtag.js) -->
vendor: 66 bytes, lines 9-10
9 10 <script async src="https://www.googletagmanager.com/gtag/js?id=
10G-Y2Q3PHX9CL
vendor: 14 bytes, lines 10-11
10"></script> 11
11<script> 12
vendor: 137 bytes, lines 12-16
12window.dataLayer = window.dataLayer || []; 13 function gtag(){dataLayer.push(arguments);} 14 gtag('js', new Date()); 15 16 gtag('config', '
16G-Y2Q3PHX9CL
vendor: 6 bytes, lines 16-17
16'); 17
17</script>
17 18 19 <title>Hostinger Horizons</title> 20 21 <!-- OpenAI Ads Pixel --> 22
22<script>!function(w,d,s,u){if(w.oaiq)return;var q=function(){q.q.push(arguments)};q.q=[];w.oaiq=q;var j=d.createElement(s);j.async=1;j.src=u;var f=d.getElementsByTagName(s)[0];f.parentNode.insertBefore(j,f)}(window,document,"script","https://bzrcdn.openai.com/sdk/oaiq.min.js");oaiq("init",{pixelId:"MfpjWR2whWsnfU8iihgEDA",debug:true});</script>
22 23 24
24<script type="module" crossorigin src="/assets/index-CkwtARWf.js"></script>
24 25 <link rel="stylesheet" crossorigin href="/assets/index-BIZsHscM.css"> 26
26<script type="module"> 27window.onerror = (message, source, lineno, colno, errorObj) => { 28 const errorDetails = errorObj ? JSON.stringify({ 29 name: errorObj.name, 30 message: errorObj.message, 31 stack: errorObj.stack, 32 source, 33 lineno, 34 colno, 35 }) : null; 36 37 window.parent.postMessage({ 38 type: 'horizons-runtime-error', 39 message, 40 error: errorDetails 41 }, '*'); 42}; 43</script>
43 44
44<script type="module"> 45const observer = new MutationObserver((mutations) => { 46 for (const mutation of mutations) { 47 for (const addedNode of mutation.addedNodes) { 48 if ( 49 addedNode.nodeType === Node.ELEMENT_NODE && 50 ( 51 addedNode.tagName?.toLowerCase() === 'vite-error-overlay' || 52 addedNode.classList?.contains('backdrop') 53 ) 54 ) { 55 handleViteOverlay(addedNode); 56 } 57 } 58 } 59}); 60 61observer.observe(document.documentElement, { 62 childList: true, 63 subtree: true 64}); 65 66function handleViteOverlay(node) { 67 if (!node.shadowRoot) { 68 return; 69 } 70 71 const backdrop = node.shadowRoot.querySelector('.backdrop'); 72 73 if (backdrop) { 74 const overlayHtml = backdrop.outerHTML; 75 const parser = new DOMParser(); 76 const doc = parser.parseFromString(overlayHtml, 'text/html'); 77 const messageBodyElement = doc.querySelector('.message-body'); 78 const fileElement = doc.querySelector('.file'); 79 const messageText = messageBodyElement ? messageBodyElement.textContent.trim() : ''; 80 const fileText = fileElement ? fileElement.textContent.trim() : ''; 81 const error = messageText + (fileText ? ' File:' + fileText : ''); 82 83 window.parent.postMessage({ 84 type: 'horizons-vite-error', 85 error, 86 }, '*'); 87 } 88} 89</script>
89 90
90<script type="module"> 91const originalConsoleError = console.error; 92const MATCH_LINE_COL_REGEX = /:(\d+):(\d+)\)?\s*$/; // regex to match the :lineNum:colNum 93const MATCH_AT_REGEX = /^\s*at\s+(?:async\s+)?(?:.*?\s+)?\(?/; // regex to remove the 'at' keyword and any 'async' or function name 94const MATCH_PATH_REGEX = /^\//; // regex to remove the leading slash 95 96function parseStackFrameLine(line) { 97 const lineColMatch = line.match(MATCH_LINE_COL_REGEX); 98 if (!lineColMatch) return null; 99 const [, lineNum, colNum] = lineColMatch; 100 const suffix = `:${lineNum}:${colNum}`; 101 const idx = line.lastIndexOf(suffix); 102 if (idx === -1) return null; 103 const before = line.substring(0, idx); 104 const path = before.replace(MATCH_AT_REGEX, '').trim(); 105 106 if (!path) return null; 107 108 try { 109 const pathname = new URL(path).pathname; 110 const filePath = pathname.replace(MATCH_PATH_REGEX, '') || pathname; 111 return `${filePath}:${lineNum}:${colNum}`; 112 } catch (e) { 113 const filePath = path.replace(MATCH_PATH_REGEX, '') || path; 114 return `${filePath}:${lineNum}:${colNum}`; 115 } 116} 117 118function getFilePathFromStack(stack, skipFrames = 0) { 119 if (!stack || typeof stack !== 'string') return null; 120 const lines = stack.split('\n').slice(1); 121 122 const frames = lines.map(line => parseStackFrameLine(line.replace(/\r$/, ''))).filter(Boolean); 123 124 return frames[skipFrames] ?? null; 125} 126 127function formatConsoleMessage(args, skipStackFrames = 1) { 128 let messageString = ''; 129 let filePath = null; 130 131 for (let i = 0; i < args.length; i++) { 132 const arg = args[i]; 133 if (arg instanceof Error) { 134 filePath = getFilePathFromStack(arg.stack, 0); 135 messageString = `${arg.name}: ${arg.message}`; 136 if (filePath) { 137 messageString = `${messageString} at ${filePath}`; 138 } 139 break; 140 } 141 } 142 143 if (!messageString) { 144 messageString = args.map(arg => typeof arg === 'object' ? JSON.stringify(arg) : String(arg)).join(' '); 145 const stack = new Error().stack; 146 filePath = getFilePathFromStack(stack, skipStackFrames); 147 if (filePath) { 148 messageString = `${messageString} at ${filePath}`; 149 } 150 } 151 152 return messageString; 153} 154 155console.error = function(...args) { 156 originalConsoleError.apply(console, args); 157 158 window.parent.postMessage({ 159 type: 'horizons-console-error', 160 error: formatConsoleMessage(args, 1) 161 }, '*'); 162}; 163 164const originalConsoleWarn = console.warn; 165 166console.warn = function(...args) { 167 originalConsoleWarn.apply(console, args); 168 169 window.parent.postMessage({ 170 type: 'horizons-console-warn', 171 warning: formatConsoleMessage(args, 1) 172 }, '*'); 173}; 174</script>
174 175
175<script type="module"> 176// Prevents authentication failures (PB returns 400) from crashing the app â use console.info, not console.error/PM2. 177// [urlPattern, bodyPattern] tuples; align with sandboxErrorUtils ERROR_BLACKLIST. 178const BENIGN_FETCH_ERRORS = [ 179 [/hcgi\/platform\/api\/collections\/.*auth-with-password.*/i, /Failed to authenticate/i], 180 [/hcgi\/api\//i, /Insufficient credits/i], 181 // A user-supplied integration secret (Stripe/PayPal/Twilio/...) is not set yet â an expected setup state, not a bug to fix. 182 [/hcgi\/api\//i, /INTEGRATION_NOT_CONFIGURED/i], 183]; 184 185function isBenignFetchError(url, body) { 186 return BENIGN_FETCH_ERRORS.some(([urlPattern, bodyPattern]) => 187 urlPattern.test(url) && (!bodyPattern || bodyPattern.test(body))); 188} 189 190const PLATFORM_URL_PATTERN = /hcgi\/platform\//i; 191const VALIDATION_CODE_TEXT_PATTERN = /validation_/; 192 193function hasValidationCode(value) { 194 if (value == null) { 195 return false; 196 } 197 if (typeof value === 'string') { 198 return value.startsWith('validation_'); 199 } 200 if (Array.isArray(value)) { 201 return value.some(hasValidationCode); 202 } 203 if (typeof value === 'object') { 204 return Object.values(value).some(hasValidationCode); 205 } 206 return false; 207} 208 209function isValidationFetchWarning(url, body) { 210 if (!PLATFORM_URL_PATTERN.test(url)) { 211 return false; 212 } 213 try { 214 return hasValidationCode(JSON.parse(body)); 215 } catch { 216 return VALIDATION_CODE_TEXT_PATTERN.test(body); 217 } 218} 219 220const originalFetch = window.fetch; 221 222window.fetch = function(...args) { 223 const url = args[0] instanceof Request ? args[0].url : args[0]; 224 225 // Skip WebSocket URLs 226 if (url.startsWith('ws:') || url.startsWith('wss:')) { 227 return originalFetch.apply(this, args); 228 } 229 230 return originalFetch.apply(this, args) 231 .then(async response => { 232 const contentType = response.headers.get('Content-Type') || ''; 233 234 // Exclude HTML document responses 235 const isDocumentResponse = 236 contentType.includes('text/html') || 237 contentType.includes('application/xhtml+xml'); 238 239 // no-cors requests (e.g. Google Analytics/Ads beacons) always return an opaque 240 const isOpaqueResponse = response.type === 'opaque'; 241 242 if (!response.ok && !isDocumentResponse && !isOpaqueResponse) { 243 const responseClone = response.clone(); 244 const errorFromRes = await responseClone.text(); 245 const requestUrl = response.url; 246 const errorMessage = `Fetch error from ${requestUrl}: ${errorFromRes}`; 247 248 if (isBenignFetchError(requestUrl, errorFromRes)) { 249 console.info(errorMessage); 250 } else if (isValidationFetchWarning(requestUrl, errorFromRes)) { 251 console.warn(errorMessage); 252 } else { 253 console.error(errorMessage); 254 } 255 } 256 257 return response; 258 }) 259 .catch(error => { 260 if (!url.match(/.html?$/i)) { 261 // Cancelled in-flight fetch (e.g. preview reload) â not a server failure. 262 if (error?.name === 'AbortError') { 263 console.info(error); 264 } else { 265 console.error(error); 266 } 267 } 268 269 throw error; 270 }); 271}; 272</script>
272 273
273<script type="module"> 274if (window.navigation && window.self !== window.top) { 275 window.navigation.addEventListener('navigate', (event) => { 276 const url = event.destination.url; 277 278 try { 279 const destinationUrl = new URL(url); 280 const destinationOrigin = destinationUrl.origin; 281 const currentOrigin = window.location.origin; 282 283 if (destinationOrigin === currentOrigin) { 284 return; 285 } 286 } catch (error) { 287 return; 288 } 289 290 window.parent.postMessage({ 291 type: 'horizons-navigation-error', 292 url, 293 }, '*'); 294 }); 295} 296</script>
296 297 </head> 298 <body> 299 <div id="root"></div> 300 </body> 301</html>
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.