Changeset 3446033
- Timestamp:
- 01/24/2026 09:29:03 AM (4 weeks ago)
- Location:
- staticdelivr
- Files:
-
- 4 edited
- 1 copied
-
tags/1.7.1 (copied) (copied from staticdelivr/trunk)
-
tags/1.7.1/README.txt (modified) (2 diffs)
-
tags/1.7.1/staticdelivr.php (modified) (5 diffs)
-
trunk/README.txt (modified) (2 diffs)
-
trunk/staticdelivr.php (modified) (5 diffs)
Legend:
- Unmodified
- Added
- Removed
-
staticdelivr/tags/1.7.1/README.txt
r3445726 r3446033 6 6 Tested up to: 6.9 7 7 Requires PHP: 7.4 8 Stable tag: 1.7. 08 Stable tag: 1.7.1 9 9 License: GPLv2 or later 10 10 License URI: https://www.gnu.org/licenses/gpl-2.0.html 11 11 12 Enhance your WordPress site's performance by rewriting URLs to use the StaticDelivr CDN. Includes automaticimage optimization, smart asset detection, failure recovery, and privacy-first Google Fonts proxy.12 Speed up WordPress with free CDN delivery, image optimization, smart asset detection, failure recovery, and privacy-first Google Fonts proxy. 13 13 14 14 == Description == … … 203 203 204 204 == Changelog == 205 206 = 1.7.1 = 207 * Fixed heredoc syntax to comply with WordPress coding standards 208 * Fixed output escaping for failure statistics 209 * Shortened plugin description to meet 150 character limit 210 * Code quality improvements for WordPress.org submission 205 211 206 212 = 1.7.0 = -
staticdelivr/tags/1.7.1/staticdelivr.php
r3445726 r3446033 3 3 * Plugin Name: StaticDelivr CDN 4 4 * Description: Speed up your WordPress site with free CDN delivery and automatic image optimization. Reduces load times and bandwidth costs. 5 * Version: 1.7. 05 * Version: 1.7.1 6 6 * Requires at least: 5.8 7 7 * Requires PHP: 7.4 … … 19 19 // Define plugin constants. 20 20 if ( ! defined( 'STATICDELIVR_VERSION' ) ) { 21 define( 'STATICDELIVR_VERSION', '1.7. 0' );21 define( 'STATICDELIVR_VERSION', '1.7.1' ); 22 22 } 23 23 if ( ! defined( 'STATICDELIVR_PLUGIN_FILE' ) ) { … … 2294 2294 $nonce = wp_create_nonce( 'staticdelivr_failure_report' ); 2295 2295 2296 $script = <<<JS 2297 (function(){ 2298 var SD_DEBUG = false; 2299 var SD_AJAX_URL = '%s'; 2300 var SD_NONCE = '%s'; 2301 2302 function log() { 2303 if (SD_DEBUG && console && console.log) { 2304 console.log.apply(console, ['[StaticDelivr]'].concat(Array.prototype.slice.call(arguments))); 2305 } 2306 } 2307 2308 function reportFailure(type, url, original) { 2309 try { 2310 var data = new FormData(); 2311 data.append('action', 'staticdelivr_report_failure'); 2312 data.append('nonce', SD_NONCE); 2313 data.append('type', type); 2314 data.append('url', url); 2315 data.append('original', original || ''); 2316 2317 if (navigator.sendBeacon) { 2318 navigator.sendBeacon(SD_AJAX_URL, data); 2319 } else { 2320 var xhr = new XMLHttpRequest(); 2321 xhr.open('POST', SD_AJAX_URL, true); 2322 xhr.send(data); 2323 } 2324 log('Reported failure:', type, url); 2325 } catch(e) { 2326 log('Failed to report:', e); 2327 } 2328 } 2329 2330 function copyAttributes(from, to) { 2331 if (!from || !to || !from.attributes) return; 2332 for (var i = 0; i < from.attributes.length; i++) { 2333 var attr = from.attributes[i]; 2334 if (!attr || !attr.name) continue; 2335 if (attr.name === 'src' || attr.name === 'href' || attr.name === 'data-original-src' || attr.name === 'data-original-href') continue; 2336 try { 2337 to.setAttribute(attr.name, attr.value); 2338 } catch(e) {} 2339 } 2340 } 2341 2342 function extractOriginalFromCdnUrl(cdnUrl) { 2343 if (!cdnUrl) return null; 2344 if (cdnUrl.indexOf('cdn.staticdelivr.com') === -1) return null; 2345 try { 2346 var urlObj = new URL(cdnUrl); 2347 var originalUrl = urlObj.searchParams.get('url'); 2348 if (originalUrl) { 2349 log('Extracted original URL from query param:', originalUrl); 2350 return originalUrl; 2351 } 2352 } catch(e) { 2353 log('Failed to parse CDN URL:', cdnUrl, e); 2354 } 2355 return null; 2356 } 2357 2358 function handleError(event) { 2359 var el = event.target || event.srcElement; 2360 if (!el) return; 2361 2362 var tagName = el.tagName ? el.tagName.toUpperCase() : ''; 2363 if (!tagName) return; 2364 2365 // Only handle elements we care about 2366 if (tagName !== 'SCRIPT' && tagName !== 'LINK' && tagName !== 'IMG') return; 2367 2368 // Get the failed URL 2369 var failedUrl = ''; 2370 if (tagName === 'IMG') failedUrl = el.src || el.currentSrc || ''; 2371 else if (tagName === 'SCRIPT') failedUrl = el.src || ''; 2372 else if (tagName === 'LINK') failedUrl = el.href || ''; 2373 2374 // Only handle StaticDelivr URLs 2375 if (failedUrl.indexOf('cdn.staticdelivr.com') === -1) return; 2376 2377 log('Caught error on:', tagName, failedUrl); 2378 2379 // Prevent double-processing 2380 if (el.getAttribute && el.getAttribute('data-sd-fallback') === 'done') return; 2381 2382 // Get original URL 2383 var original = el.getAttribute('data-original-src') || el.getAttribute('data-original-href'); 2384 if (!original) original = extractOriginalFromCdnUrl(failedUrl); 2385 2386 if (!original) { 2387 log('Could not determine original URL for:', failedUrl); 2388 return; 2389 } 2390 2391 el.setAttribute('data-sd-fallback', 'done'); 2392 log('Falling back to origin:', tagName, original); 2393 2394 // Report the failure 2395 var reportType = (tagName === 'IMG') ? 'image' : 'asset'; 2396 reportFailure(reportType, failedUrl, original); 2397 2398 if (tagName === 'SCRIPT') { 2399 var newScript = document.createElement('script'); 2400 newScript.src = original; 2401 newScript.async = el.async; 2402 newScript.defer = el.defer; 2403 if (el.type) newScript.type = el.type; 2404 if (el.noModule) newScript.noModule = true; 2405 if (el.crossOrigin) newScript.crossOrigin = el.crossOrigin; 2406 copyAttributes(el, newScript); 2407 if (el.parentNode) { 2408 el.parentNode.insertBefore(newScript, el.nextSibling); 2409 el.parentNode.removeChild(el); 2410 } 2411 log('Script fallback complete:', original); 2412 2413 } else if (tagName === 'LINK') { 2414 el.href = original; 2415 log('Stylesheet fallback complete:', original); 2416 2417 } else if (tagName === 'IMG') { 2418 // Handle srcset first 2419 if (el.srcset) { 2420 var newSrcset = el.srcset.split(',').map(function(entry) { 2421 var parts = entry.trim().split(/\s+/); 2422 var url = parts[0]; 2423 var descriptor = parts.slice(1).join(' '); 2424 var extracted = extractOriginalFromCdnUrl(url); 2425 if (extracted) url = extracted; 2426 return descriptor ? url + ' ' + descriptor : url; 2427 }).join(', '); 2428 el.srcset = newSrcset; 2429 } 2430 el.src = original; 2431 log('Image fallback complete:', original); 2432 } 2433 } 2434 2435 // Capture errors in capture phase 2436 window.addEventListener('error', handleError, true); 2437 2438 log('Fallback script initialized (v%s)'); 2439 })(); 2440 JS; 2296 $script = '(function(){' . "\n"; 2297 $script .= " var SD_DEBUG = false;\n"; 2298 $script .= " var SD_AJAX_URL = '%s';\n"; 2299 $script .= " var SD_NONCE = '%s';\n"; 2300 $script .= "\n"; 2301 $script .= " function log() {\n"; 2302 $script .= " if (SD_DEBUG && console && console.log) {\n"; 2303 $script .= " console.log.apply(console, ['[StaticDelivr]'].concat(Array.prototype.slice.call(arguments)));\n"; 2304 $script .= " }\n"; 2305 $script .= " }\n"; 2306 $script .= "\n"; 2307 $script .= " function reportFailure(type, url, original) {\n"; 2308 $script .= " try {\n"; 2309 $script .= " var data = new FormData();\n"; 2310 $script .= " data.append('action', 'staticdelivr_report_failure');\n"; 2311 $script .= " data.append('nonce', SD_NONCE);\n"; 2312 $script .= " data.append('type', type);\n"; 2313 $script .= " data.append('url', url);\n"; 2314 $script .= " data.append('original', original || '');\n"; 2315 $script .= "\n"; 2316 $script .= " if (navigator.sendBeacon) {\n"; 2317 $script .= " navigator.sendBeacon(SD_AJAX_URL, data);\n"; 2318 $script .= " } else {\n"; 2319 $script .= " var xhr = new XMLHttpRequest();\n"; 2320 $script .= " xhr.open('POST', SD_AJAX_URL, true);\n"; 2321 $script .= " xhr.send(data);\n"; 2322 $script .= " }\n"; 2323 $script .= " log('Reported failure:', type, url);\n"; 2324 $script .= " } catch(e) {\n"; 2325 $script .= " log('Failed to report:', e);\n"; 2326 $script .= " }\n"; 2327 $script .= " }\n"; 2328 $script .= "\n"; 2329 $script .= " function copyAttributes(from, to) {\n"; 2330 $script .= " if (!from || !to || !from.attributes) return;\n"; 2331 $script .= " for (var i = 0; i < from.attributes.length; i++) {\n"; 2332 $script .= " var attr = from.attributes[i];\n"; 2333 $script .= " if (!attr || !attr.name) continue;\n"; 2334 $script .= " if (attr.name === 'src' || attr.name === 'href' || attr.name === 'data-original-src' || attr.name === 'data-original-href') continue;\n"; 2335 $script .= " try {\n"; 2336 $script .= " to.setAttribute(attr.name, attr.value);\n"; 2337 $script .= " } catch(e) {}\n"; 2338 $script .= " }\n"; 2339 $script .= " }\n"; 2340 $script .= "\n"; 2341 $script .= " function extractOriginalFromCdnUrl(cdnUrl) {\n"; 2342 $script .= " if (!cdnUrl) return null;\n"; 2343 $script .= " if (cdnUrl.indexOf('cdn.staticdelivr.com') === -1) return null;\n"; 2344 $script .= " try {\n"; 2345 $script .= " var urlObj = new URL(cdnUrl);\n"; 2346 $script .= " var originalUrl = urlObj.searchParams.get('url');\n"; 2347 $script .= " if (originalUrl) {\n"; 2348 $script .= " log('Extracted original URL from query param:', originalUrl);\n"; 2349 $script .= " return originalUrl;\n"; 2350 $script .= " }\n"; 2351 $script .= " } catch(e) {\n"; 2352 $script .= " log('Failed to parse CDN URL:', cdnUrl, e);\n"; 2353 $script .= " }\n"; 2354 $script .= " return null;\n"; 2355 $script .= " }\n"; 2356 $script .= "\n"; 2357 $script .= " function handleError(event) {\n"; 2358 $script .= " var el = event.target || event.srcElement;\n"; 2359 $script .= " if (!el) return;\n"; 2360 $script .= "\n"; 2361 $script .= " var tagName = el.tagName ? el.tagName.toUpperCase() : '';\n"; 2362 $script .= " if (!tagName) return;\n"; 2363 $script .= "\n"; 2364 $script .= " // Only handle elements we care about\n"; 2365 $script .= " if (tagName !== 'SCRIPT' && tagName !== 'LINK' && tagName !== 'IMG') return;\n"; 2366 $script .= "\n"; 2367 $script .= " // Get the failed URL\n"; 2368 $script .= " var failedUrl = '';\n"; 2369 $script .= " if (tagName === 'IMG') failedUrl = el.src || el.currentSrc || '';\n"; 2370 $script .= " else if (tagName === 'SCRIPT') failedUrl = el.src || '';\n"; 2371 $script .= " else if (tagName === 'LINK') failedUrl = el.href || '';\n"; 2372 $script .= "\n"; 2373 $script .= " // Only handle StaticDelivr URLs\n"; 2374 $script .= " if (failedUrl.indexOf('cdn.staticdelivr.com') === -1) return;\n"; 2375 $script .= "\n"; 2376 $script .= " log('Caught error on:', tagName, failedUrl);\n"; 2377 $script .= "\n"; 2378 $script .= " // Prevent double-processing\n"; 2379 $script .= " if (el.getAttribute && el.getAttribute('data-sd-fallback') === 'done') return;\n"; 2380 $script .= "\n"; 2381 $script .= " // Get original URL\n"; 2382 $script .= " var original = el.getAttribute('data-original-src') || el.getAttribute('data-original-href');\n"; 2383 $script .= " if (!original) original = extractOriginalFromCdnUrl(failedUrl);\n"; 2384 $script .= "\n"; 2385 $script .= " if (!original) {\n"; 2386 $script .= " log('Could not determine original URL for:', failedUrl);\n"; 2387 $script .= " return;\n"; 2388 $script .= " }\n"; 2389 $script .= "\n"; 2390 $script .= " el.setAttribute('data-sd-fallback', 'done');\n"; 2391 $script .= " log('Falling back to origin:', tagName, original);\n"; 2392 $script .= "\n"; 2393 $script .= " // Report the failure\n"; 2394 $script .= " var reportType = (tagName === 'IMG') ? 'image' : 'asset';\n"; 2395 $script .= " reportFailure(reportType, failedUrl, original);\n"; 2396 $script .= "\n"; 2397 $script .= " if (tagName === 'SCRIPT') {\n"; 2398 $script .= " var newScript = document.createElement('script');\n"; 2399 $script .= " newScript.src = original;\n"; 2400 $script .= " newScript.async = el.async;\n"; 2401 $script .= " newScript.defer = el.defer;\n"; 2402 $script .= " if (el.type) newScript.type = el.type;\n"; 2403 $script .= " if (el.noModule) newScript.noModule = true;\n"; 2404 $script .= " if (el.crossOrigin) newScript.crossOrigin = el.crossOrigin;\n"; 2405 $script .= " copyAttributes(el, newScript);\n"; 2406 $script .= " if (el.parentNode) {\n"; 2407 $script .= " el.parentNode.insertBefore(newScript, el.nextSibling);\n"; 2408 $script .= " el.parentNode.removeChild(el);\n"; 2409 $script .= " }\n"; 2410 $script .= " log('Script fallback complete:', original);\n"; 2411 $script .= "\n"; 2412 $script .= " } else if (tagName === 'LINK') {\n"; 2413 $script .= " el.href = original;\n"; 2414 $script .= " log('Stylesheet fallback complete:', original);\n"; 2415 $script .= "\n"; 2416 $script .= " } else if (tagName === 'IMG') {\n"; 2417 $script .= " // Handle srcset first\n"; 2418 $script .= " if (el.srcset) {\n"; 2419 $script .= " var newSrcset = el.srcset.split(',').map(function(entry) {\n"; 2420 $script .= " var parts = entry.trim().split(/\\s+/);\n"; 2421 $script .= " var url = parts[0];\n"; 2422 $script .= " var descriptor = parts.slice(1).join(' ');\n"; 2423 $script .= " var extracted = extractOriginalFromCdnUrl(url);\n"; 2424 $script .= " if (extracted) url = extracted;\n"; 2425 $script .= " return descriptor ? url + ' ' + descriptor : url;\n"; 2426 $script .= " }).join(', ');\n"; 2427 $script .= " el.srcset = newSrcset;\n"; 2428 $script .= " }\n"; 2429 $script .= " el.src = original;\n"; 2430 $script .= " log('Image fallback complete:', original);\n"; 2431 $script .= " }\n"; 2432 $script .= " }\n"; 2433 $script .= "\n"; 2434 $script .= " // Capture errors in capture phase\n"; 2435 $script .= " window.addEventListener('error', handleError, true);\n"; 2436 $script .= "\n"; 2437 $script .= " log('Fallback script initialized (v%s)');\n"; 2438 $script .= '})();'; 2441 2439 2442 2440 return sprintf( $script, esc_js( $ajax_url ), esc_js( $nonce ), STATICDELIVR_VERSION ); … … 2852 2850 /* translators: 1: total failures, 2: blocked count */ 2853 2851 esc_html__( '%1$d failures (%2$d blocked)', 'staticdelivr' ), 2854 $failure_stats['images']['total'],2855 $failure_stats['images']['blocked']2852 intval( $failure_stats['images']['total'] ), 2853 intval( $failure_stats['images']['blocked'] ) 2856 2854 ); 2857 2855 ?> … … 2865 2863 /* translators: 1: total failures, 2: blocked count */ 2866 2864 esc_html__( '%1$d failures (%2$d blocked)', 'staticdelivr' ), 2867 $failure_stats['assets']['total'],2868 $failure_stats['assets']['blocked']2865 intval( $failure_stats['assets']['total'] ), 2866 intval( $failure_stats['assets']['blocked'] ) 2869 2867 ); 2870 2868 ?> -
staticdelivr/trunk/README.txt
r3445726 r3446033 6 6 Tested up to: 6.9 7 7 Requires PHP: 7.4 8 Stable tag: 1.7. 08 Stable tag: 1.7.1 9 9 License: GPLv2 or later 10 10 License URI: https://www.gnu.org/licenses/gpl-2.0.html 11 11 12 Enhance your WordPress site's performance by rewriting URLs to use the StaticDelivr CDN. Includes automaticimage optimization, smart asset detection, failure recovery, and privacy-first Google Fonts proxy.12 Speed up WordPress with free CDN delivery, image optimization, smart asset detection, failure recovery, and privacy-first Google Fonts proxy. 13 13 14 14 == Description == … … 203 203 204 204 == Changelog == 205 206 = 1.7.1 = 207 * Fixed heredoc syntax to comply with WordPress coding standards 208 * Fixed output escaping for failure statistics 209 * Shortened plugin description to meet 150 character limit 210 * Code quality improvements for WordPress.org submission 205 211 206 212 = 1.7.0 = -
staticdelivr/trunk/staticdelivr.php
r3445726 r3446033 3 3 * Plugin Name: StaticDelivr CDN 4 4 * Description: Speed up your WordPress site with free CDN delivery and automatic image optimization. Reduces load times and bandwidth costs. 5 * Version: 1.7. 05 * Version: 1.7.1 6 6 * Requires at least: 5.8 7 7 * Requires PHP: 7.4 … … 19 19 // Define plugin constants. 20 20 if ( ! defined( 'STATICDELIVR_VERSION' ) ) { 21 define( 'STATICDELIVR_VERSION', '1.7. 0' );21 define( 'STATICDELIVR_VERSION', '1.7.1' ); 22 22 } 23 23 if ( ! defined( 'STATICDELIVR_PLUGIN_FILE' ) ) { … … 2294 2294 $nonce = wp_create_nonce( 'staticdelivr_failure_report' ); 2295 2295 2296 $script = <<<JS 2297 (function(){ 2298 var SD_DEBUG = false; 2299 var SD_AJAX_URL = '%s'; 2300 var SD_NONCE = '%s'; 2301 2302 function log() { 2303 if (SD_DEBUG && console && console.log) { 2304 console.log.apply(console, ['[StaticDelivr]'].concat(Array.prototype.slice.call(arguments))); 2305 } 2306 } 2307 2308 function reportFailure(type, url, original) { 2309 try { 2310 var data = new FormData(); 2311 data.append('action', 'staticdelivr_report_failure'); 2312 data.append('nonce', SD_NONCE); 2313 data.append('type', type); 2314 data.append('url', url); 2315 data.append('original', original || ''); 2316 2317 if (navigator.sendBeacon) { 2318 navigator.sendBeacon(SD_AJAX_URL, data); 2319 } else { 2320 var xhr = new XMLHttpRequest(); 2321 xhr.open('POST', SD_AJAX_URL, true); 2322 xhr.send(data); 2323 } 2324 log('Reported failure:', type, url); 2325 } catch(e) { 2326 log('Failed to report:', e); 2327 } 2328 } 2329 2330 function copyAttributes(from, to) { 2331 if (!from || !to || !from.attributes) return; 2332 for (var i = 0; i < from.attributes.length; i++) { 2333 var attr = from.attributes[i]; 2334 if (!attr || !attr.name) continue; 2335 if (attr.name === 'src' || attr.name === 'href' || attr.name === 'data-original-src' || attr.name === 'data-original-href') continue; 2336 try { 2337 to.setAttribute(attr.name, attr.value); 2338 } catch(e) {} 2339 } 2340 } 2341 2342 function extractOriginalFromCdnUrl(cdnUrl) { 2343 if (!cdnUrl) return null; 2344 if (cdnUrl.indexOf('cdn.staticdelivr.com') === -1) return null; 2345 try { 2346 var urlObj = new URL(cdnUrl); 2347 var originalUrl = urlObj.searchParams.get('url'); 2348 if (originalUrl) { 2349 log('Extracted original URL from query param:', originalUrl); 2350 return originalUrl; 2351 } 2352 } catch(e) { 2353 log('Failed to parse CDN URL:', cdnUrl, e); 2354 } 2355 return null; 2356 } 2357 2358 function handleError(event) { 2359 var el = event.target || event.srcElement; 2360 if (!el) return; 2361 2362 var tagName = el.tagName ? el.tagName.toUpperCase() : ''; 2363 if (!tagName) return; 2364 2365 // Only handle elements we care about 2366 if (tagName !== 'SCRIPT' && tagName !== 'LINK' && tagName !== 'IMG') return; 2367 2368 // Get the failed URL 2369 var failedUrl = ''; 2370 if (tagName === 'IMG') failedUrl = el.src || el.currentSrc || ''; 2371 else if (tagName === 'SCRIPT') failedUrl = el.src || ''; 2372 else if (tagName === 'LINK') failedUrl = el.href || ''; 2373 2374 // Only handle StaticDelivr URLs 2375 if (failedUrl.indexOf('cdn.staticdelivr.com') === -1) return; 2376 2377 log('Caught error on:', tagName, failedUrl); 2378 2379 // Prevent double-processing 2380 if (el.getAttribute && el.getAttribute('data-sd-fallback') === 'done') return; 2381 2382 // Get original URL 2383 var original = el.getAttribute('data-original-src') || el.getAttribute('data-original-href'); 2384 if (!original) original = extractOriginalFromCdnUrl(failedUrl); 2385 2386 if (!original) { 2387 log('Could not determine original URL for:', failedUrl); 2388 return; 2389 } 2390 2391 el.setAttribute('data-sd-fallback', 'done'); 2392 log('Falling back to origin:', tagName, original); 2393 2394 // Report the failure 2395 var reportType = (tagName === 'IMG') ? 'image' : 'asset'; 2396 reportFailure(reportType, failedUrl, original); 2397 2398 if (tagName === 'SCRIPT') { 2399 var newScript = document.createElement('script'); 2400 newScript.src = original; 2401 newScript.async = el.async; 2402 newScript.defer = el.defer; 2403 if (el.type) newScript.type = el.type; 2404 if (el.noModule) newScript.noModule = true; 2405 if (el.crossOrigin) newScript.crossOrigin = el.crossOrigin; 2406 copyAttributes(el, newScript); 2407 if (el.parentNode) { 2408 el.parentNode.insertBefore(newScript, el.nextSibling); 2409 el.parentNode.removeChild(el); 2410 } 2411 log('Script fallback complete:', original); 2412 2413 } else if (tagName === 'LINK') { 2414 el.href = original; 2415 log('Stylesheet fallback complete:', original); 2416 2417 } else if (tagName === 'IMG') { 2418 // Handle srcset first 2419 if (el.srcset) { 2420 var newSrcset = el.srcset.split(',').map(function(entry) { 2421 var parts = entry.trim().split(/\s+/); 2422 var url = parts[0]; 2423 var descriptor = parts.slice(1).join(' '); 2424 var extracted = extractOriginalFromCdnUrl(url); 2425 if (extracted) url = extracted; 2426 return descriptor ? url + ' ' + descriptor : url; 2427 }).join(', '); 2428 el.srcset = newSrcset; 2429 } 2430 el.src = original; 2431 log('Image fallback complete:', original); 2432 } 2433 } 2434 2435 // Capture errors in capture phase 2436 window.addEventListener('error', handleError, true); 2437 2438 log('Fallback script initialized (v%s)'); 2439 })(); 2440 JS; 2296 $script = '(function(){' . "\n"; 2297 $script .= " var SD_DEBUG = false;\n"; 2298 $script .= " var SD_AJAX_URL = '%s';\n"; 2299 $script .= " var SD_NONCE = '%s';\n"; 2300 $script .= "\n"; 2301 $script .= " function log() {\n"; 2302 $script .= " if (SD_DEBUG && console && console.log) {\n"; 2303 $script .= " console.log.apply(console, ['[StaticDelivr]'].concat(Array.prototype.slice.call(arguments)));\n"; 2304 $script .= " }\n"; 2305 $script .= " }\n"; 2306 $script .= "\n"; 2307 $script .= " function reportFailure(type, url, original) {\n"; 2308 $script .= " try {\n"; 2309 $script .= " var data = new FormData();\n"; 2310 $script .= " data.append('action', 'staticdelivr_report_failure');\n"; 2311 $script .= " data.append('nonce', SD_NONCE);\n"; 2312 $script .= " data.append('type', type);\n"; 2313 $script .= " data.append('url', url);\n"; 2314 $script .= " data.append('original', original || '');\n"; 2315 $script .= "\n"; 2316 $script .= " if (navigator.sendBeacon) {\n"; 2317 $script .= " navigator.sendBeacon(SD_AJAX_URL, data);\n"; 2318 $script .= " } else {\n"; 2319 $script .= " var xhr = new XMLHttpRequest();\n"; 2320 $script .= " xhr.open('POST', SD_AJAX_URL, true);\n"; 2321 $script .= " xhr.send(data);\n"; 2322 $script .= " }\n"; 2323 $script .= " log('Reported failure:', type, url);\n"; 2324 $script .= " } catch(e) {\n"; 2325 $script .= " log('Failed to report:', e);\n"; 2326 $script .= " }\n"; 2327 $script .= " }\n"; 2328 $script .= "\n"; 2329 $script .= " function copyAttributes(from, to) {\n"; 2330 $script .= " if (!from || !to || !from.attributes) return;\n"; 2331 $script .= " for (var i = 0; i < from.attributes.length; i++) {\n"; 2332 $script .= " var attr = from.attributes[i];\n"; 2333 $script .= " if (!attr || !attr.name) continue;\n"; 2334 $script .= " if (attr.name === 'src' || attr.name === 'href' || attr.name === 'data-original-src' || attr.name === 'data-original-href') continue;\n"; 2335 $script .= " try {\n"; 2336 $script .= " to.setAttribute(attr.name, attr.value);\n"; 2337 $script .= " } catch(e) {}\n"; 2338 $script .= " }\n"; 2339 $script .= " }\n"; 2340 $script .= "\n"; 2341 $script .= " function extractOriginalFromCdnUrl(cdnUrl) {\n"; 2342 $script .= " if (!cdnUrl) return null;\n"; 2343 $script .= " if (cdnUrl.indexOf('cdn.staticdelivr.com') === -1) return null;\n"; 2344 $script .= " try {\n"; 2345 $script .= " var urlObj = new URL(cdnUrl);\n"; 2346 $script .= " var originalUrl = urlObj.searchParams.get('url');\n"; 2347 $script .= " if (originalUrl) {\n"; 2348 $script .= " log('Extracted original URL from query param:', originalUrl);\n"; 2349 $script .= " return originalUrl;\n"; 2350 $script .= " }\n"; 2351 $script .= " } catch(e) {\n"; 2352 $script .= " log('Failed to parse CDN URL:', cdnUrl, e);\n"; 2353 $script .= " }\n"; 2354 $script .= " return null;\n"; 2355 $script .= " }\n"; 2356 $script .= "\n"; 2357 $script .= " function handleError(event) {\n"; 2358 $script .= " var el = event.target || event.srcElement;\n"; 2359 $script .= " if (!el) return;\n"; 2360 $script .= "\n"; 2361 $script .= " var tagName = el.tagName ? el.tagName.toUpperCase() : '';\n"; 2362 $script .= " if (!tagName) return;\n"; 2363 $script .= "\n"; 2364 $script .= " // Only handle elements we care about\n"; 2365 $script .= " if (tagName !== 'SCRIPT' && tagName !== 'LINK' && tagName !== 'IMG') return;\n"; 2366 $script .= "\n"; 2367 $script .= " // Get the failed URL\n"; 2368 $script .= " var failedUrl = '';\n"; 2369 $script .= " if (tagName === 'IMG') failedUrl = el.src || el.currentSrc || '';\n"; 2370 $script .= " else if (tagName === 'SCRIPT') failedUrl = el.src || '';\n"; 2371 $script .= " else if (tagName === 'LINK') failedUrl = el.href || '';\n"; 2372 $script .= "\n"; 2373 $script .= " // Only handle StaticDelivr URLs\n"; 2374 $script .= " if (failedUrl.indexOf('cdn.staticdelivr.com') === -1) return;\n"; 2375 $script .= "\n"; 2376 $script .= " log('Caught error on:', tagName, failedUrl);\n"; 2377 $script .= "\n"; 2378 $script .= " // Prevent double-processing\n"; 2379 $script .= " if (el.getAttribute && el.getAttribute('data-sd-fallback') === 'done') return;\n"; 2380 $script .= "\n"; 2381 $script .= " // Get original URL\n"; 2382 $script .= " var original = el.getAttribute('data-original-src') || el.getAttribute('data-original-href');\n"; 2383 $script .= " if (!original) original = extractOriginalFromCdnUrl(failedUrl);\n"; 2384 $script .= "\n"; 2385 $script .= " if (!original) {\n"; 2386 $script .= " log('Could not determine original URL for:', failedUrl);\n"; 2387 $script .= " return;\n"; 2388 $script .= " }\n"; 2389 $script .= "\n"; 2390 $script .= " el.setAttribute('data-sd-fallback', 'done');\n"; 2391 $script .= " log('Falling back to origin:', tagName, original);\n"; 2392 $script .= "\n"; 2393 $script .= " // Report the failure\n"; 2394 $script .= " var reportType = (tagName === 'IMG') ? 'image' : 'asset';\n"; 2395 $script .= " reportFailure(reportType, failedUrl, original);\n"; 2396 $script .= "\n"; 2397 $script .= " if (tagName === 'SCRIPT') {\n"; 2398 $script .= " var newScript = document.createElement('script');\n"; 2399 $script .= " newScript.src = original;\n"; 2400 $script .= " newScript.async = el.async;\n"; 2401 $script .= " newScript.defer = el.defer;\n"; 2402 $script .= " if (el.type) newScript.type = el.type;\n"; 2403 $script .= " if (el.noModule) newScript.noModule = true;\n"; 2404 $script .= " if (el.crossOrigin) newScript.crossOrigin = el.crossOrigin;\n"; 2405 $script .= " copyAttributes(el, newScript);\n"; 2406 $script .= " if (el.parentNode) {\n"; 2407 $script .= " el.parentNode.insertBefore(newScript, el.nextSibling);\n"; 2408 $script .= " el.parentNode.removeChild(el);\n"; 2409 $script .= " }\n"; 2410 $script .= " log('Script fallback complete:', original);\n"; 2411 $script .= "\n"; 2412 $script .= " } else if (tagName === 'LINK') {\n"; 2413 $script .= " el.href = original;\n"; 2414 $script .= " log('Stylesheet fallback complete:', original);\n"; 2415 $script .= "\n"; 2416 $script .= " } else if (tagName === 'IMG') {\n"; 2417 $script .= " // Handle srcset first\n"; 2418 $script .= " if (el.srcset) {\n"; 2419 $script .= " var newSrcset = el.srcset.split(',').map(function(entry) {\n"; 2420 $script .= " var parts = entry.trim().split(/\\s+/);\n"; 2421 $script .= " var url = parts[0];\n"; 2422 $script .= " var descriptor = parts.slice(1).join(' ');\n"; 2423 $script .= " var extracted = extractOriginalFromCdnUrl(url);\n"; 2424 $script .= " if (extracted) url = extracted;\n"; 2425 $script .= " return descriptor ? url + ' ' + descriptor : url;\n"; 2426 $script .= " }).join(', ');\n"; 2427 $script .= " el.srcset = newSrcset;\n"; 2428 $script .= " }\n"; 2429 $script .= " el.src = original;\n"; 2430 $script .= " log('Image fallback complete:', original);\n"; 2431 $script .= " }\n"; 2432 $script .= " }\n"; 2433 $script .= "\n"; 2434 $script .= " // Capture errors in capture phase\n"; 2435 $script .= " window.addEventListener('error', handleError, true);\n"; 2436 $script .= "\n"; 2437 $script .= " log('Fallback script initialized (v%s)');\n"; 2438 $script .= '})();'; 2441 2439 2442 2440 return sprintf( $script, esc_js( $ajax_url ), esc_js( $nonce ), STATICDELIVR_VERSION ); … … 2852 2850 /* translators: 1: total failures, 2: blocked count */ 2853 2851 esc_html__( '%1$d failures (%2$d blocked)', 'staticdelivr' ), 2854 $failure_stats['images']['total'],2855 $failure_stats['images']['blocked']2852 intval( $failure_stats['images']['total'] ), 2853 intval( $failure_stats['images']['blocked'] ) 2856 2854 ); 2857 2855 ?> … … 2865 2863 /* translators: 1: total failures, 2: blocked count */ 2866 2864 esc_html__( '%1$d failures (%2$d blocked)', 'staticdelivr' ), 2867 $failure_stats['assets']['total'],2868 $failure_stats['assets']['blocked']2865 intval( $failure_stats['assets']['total'] ), 2866 intval( $failure_stats['assets']['blocked'] ) 2869 2867 ); 2870 2868 ?>
Note: See TracChangeset
for help on using the changeset viewer.