Plugin Directory

Changeset 3446033


Ignore:
Timestamp:
01/24/2026 09:29:03 AM (4 weeks ago)
Author:
coozywana
Message:

Update to version 1.7.1 from GitHub

Location:
staticdelivr
Files:
4 edited
1 copied

Legend:

Unmodified
Added
Removed
  • staticdelivr/tags/1.7.1/README.txt

    r3445726 r3446033  
    66Tested up to: 6.9
    77Requires PHP: 7.4
    8 Stable tag: 1.7.0
     8Stable tag: 1.7.1
    99License: GPLv2 or later
    1010License URI: https://www.gnu.org/licenses/gpl-2.0.html
    1111
    12 Enhance your WordPress site's performance by rewriting URLs to use the StaticDelivr CDN. Includes automatic image optimization, smart asset detection, failure recovery, and privacy-first Google Fonts proxy.
     12Speed up WordPress with free CDN delivery, image optimization, smart asset detection, failure recovery, and privacy-first Google Fonts proxy.
    1313
    1414== Description ==
     
    203203
    204204== 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
    205211
    206212= 1.7.0 =
  • staticdelivr/tags/1.7.1/staticdelivr.php

    r3445726 r3446033  
    33 * Plugin Name: StaticDelivr CDN
    44 * Description: Speed up your WordPress site with free CDN delivery and automatic image optimization. Reduces load times and bandwidth costs.
    5  * Version: 1.7.0
     5 * Version: 1.7.1
    66 * Requires at least: 5.8
    77 * Requires PHP: 7.4
     
    1919// Define plugin constants.
    2020if ( ! defined( 'STATICDELIVR_VERSION' ) ) {
    21     define( 'STATICDELIVR_VERSION', '1.7.0' );
     21    define( 'STATICDELIVR_VERSION', '1.7.1' );
    2222}
    2323if ( ! defined( 'STATICDELIVR_PLUGIN_FILE' ) ) {
     
    22942294        $nonce    = wp_create_nonce( 'staticdelivr_failure_report' );
    22952295
    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 .= '})();';
    24412439
    24422440        return sprintf( $script, esc_js( $ajax_url ), esc_js( $nonce ), STATICDELIVR_VERSION );
     
    28522850                            /* translators: 1: total failures, 2: blocked count */
    28532851                            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'] )
    28562854                        );
    28572855                        ?>
     
    28652863                            /* translators: 1: total failures, 2: blocked count */
    28662864                            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'] )
    28692867                        );
    28702868                        ?>
  • staticdelivr/trunk/README.txt

    r3445726 r3446033  
    66Tested up to: 6.9
    77Requires PHP: 7.4
    8 Stable tag: 1.7.0
     8Stable tag: 1.7.1
    99License: GPLv2 or later
    1010License URI: https://www.gnu.org/licenses/gpl-2.0.html
    1111
    12 Enhance your WordPress site's performance by rewriting URLs to use the StaticDelivr CDN. Includes automatic image optimization, smart asset detection, failure recovery, and privacy-first Google Fonts proxy.
     12Speed up WordPress with free CDN delivery, image optimization, smart asset detection, failure recovery, and privacy-first Google Fonts proxy.
    1313
    1414== Description ==
     
    203203
    204204== 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
    205211
    206212= 1.7.0 =
  • staticdelivr/trunk/staticdelivr.php

    r3445726 r3446033  
    33 * Plugin Name: StaticDelivr CDN
    44 * Description: Speed up your WordPress site with free CDN delivery and automatic image optimization. Reduces load times and bandwidth costs.
    5  * Version: 1.7.0
     5 * Version: 1.7.1
    66 * Requires at least: 5.8
    77 * Requires PHP: 7.4
     
    1919// Define plugin constants.
    2020if ( ! defined( 'STATICDELIVR_VERSION' ) ) {
    21     define( 'STATICDELIVR_VERSION', '1.7.0' );
     21    define( 'STATICDELIVR_VERSION', '1.7.1' );
    2222}
    2323if ( ! defined( 'STATICDELIVR_PLUGIN_FILE' ) ) {
     
    22942294        $nonce    = wp_create_nonce( 'staticdelivr_failure_report' );
    22952295
    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 .= '})();';
    24412439
    24422440        return sprintf( $script, esc_js( $ajax_url ), esc_js( $nonce ), STATICDELIVR_VERSION );
     
    28522850                            /* translators: 1: total failures, 2: blocked count */
    28532851                            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'] )
    28562854                        );
    28572855                        ?>
     
    28652863                            /* translators: 1: total failures, 2: blocked count */
    28662864                            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'] )
    28692867                        );
    28702868                        ?>
Note: See TracChangeset for help on using the changeset viewer.