1const CACHE_VERSION = '1.7.88.1'; 2 3const BASE_CACHE_FILES = [ 4 'https://fedequinas.org/wp-content/uploads/2020/06/logo.jpg', 5'', 6'https://fedequinas.org/wp-content/uploads/2020/06/logo.jpg', 7'', 8'https://fedequinas.org/wp-content/plugins/pwa-for-wp/images/logo-512x512.png', 9'https://fedequinas.org/actualizacion-de-tarifas-de-pruebas-de-adn-y-certificados-de-registro/', 10'https://fedequinas.org/aplazamiento-1-a-copa-internacional-interclubes-2026/', 11'https://fedequinas.org/reintegro-de-transporte-apoyo-fedequinas-a-la-seleccion-colombia/', 12'https://fedequinas.org/fedequinas-activa-canal-de-atencion-para-conocer-afectaciones-por-el-sismo/', 13'https://fedequinas.org/comunicado-de-anemia-infecciosa/', 14 15]; 16 17const OFFLINE_CACHE_FILES = [ 18 'https://fedequinas.org/', 19]; 20 21const NOT_FOUND_CACHE_FILES = [ 22 'https://fedequinas.org/', 23]; 24 25const OFFLINE_PAGE = 'https://fedequinas.org/'; 26const NOT_FOUND_PAGE = 'https://fedequinas.org/'; 27 28const CACHE_VERSIONS = { 29 content: 'content-v' + CACHE_VERSION, 30 notFound: '404-v' + CACHE_VERSION, 31 offline: 'offline-v' + CACHE_VERSION, 32}; 33 34// Define MAX_TTL's in SECONDS for specific file extensions 35const MAX_TTL = { 36 '/': 3600, 37 html: 3600, 38 json: 86400, 39 js: 86400, 40 css: 86400, 41 png: 86400, 42 jpg: 86400, 43}; 44 45const CACHE_STRATEGY = { 46 default: 'cacheFirst', 47 css_js: 'cacheFirst', 48 images: 'cacheFirst', 49 fonts: 'cacheFirst', 50}; 51 52const CACHE_BLACKLIST = [ 53// (str) => { 54// return !str.includes('/wp-admin/') || !str.startsWith('https://fedequinas.org//wp-admin/'); 55// }, 56]; 57const neverCacheUrls = [/\/wp-admin/,/\/wp-login/,/preview=true/,/\/cart/,/ajax/,/login/,]; 58 59const PWA_VISIBILITY_BYPASS_PATHS = []; 60 61/** 62 * Same path rules as frontend visibility_excludes: exact path or subpaths. 63 * @param {string} pathname request URL pathname 64 * @returns {boolean} 65 */ 66function pwaForWpVisibilityBypassPath(pathname) { 67 if (!PWA_VISIBILITY_BYPASS_PATHS.length) { 68 return false; 69 } 70 var norm = pathname.replace(/\/+$/, ''); 71 if (norm === '') { 72 norm = '/'; 73 } 74 for (var i = 0; i < PWA_VISIBILITY_BYPASS_PATHS.length; i++) { 75 var prefix = String(PWA_VISIBILITY_BYPASS_PATHS[i]).replace(/\/+$/, ''); 76 if (norm === prefix || norm.indexOf(prefix + '/') === 0) { 77 return true; 78 } 79 } 80 return false; 81} 82 83const SUPPORTED_METHODS = [ 84 'GET', 85]; 86// Check if current url is in the neverCacheUrls list 87function pwaForWpcheckNeverCacheList(url) { 88 if ( this.match(url) ) { 89 return false; 90 } 91 return true; 92} 93/** 94 * pwaForWpisBlackListed 95 * @param {string} url 96 * @returns {boolean} 97 */ 98function pwaForWpisBlackListed(url) { 99 return (CACHE_BLACKLIST.length > 0) ? !CACHE_BLACKLIST.filter((rule) => { 100 if(typeof rule === 'function') { 101 return !rule(url); 102 } else { 103 return false; 104 } 105 }).length : false 106} 107 108/** 109 * pwaForWpgetFileExtension 110 * @param {string} url 111 * @returns {string} 112 */ 113function pwaForWpgetFileExtension(url) { 114 115 if (typeof url === 'string') { 116 117 let split_two = url.split('?'); 118 let split_url = split_two[0]; 119 120 let extension = split_url.split('.').reverse()[0].split('?')[0]; 121 return (extension.endsWith('/')) ? '/' : extension; 122 123 }else{ 124 return null; 125 } 126} 127/** 128 * pwaForWpgetTTL 129 * @param {string} url 130 */ 131function pwaForWpgetTTL(url) { 132 if (typeof url === 'string') { 133 let extension = pwaForWpgetFileExtension(url); 134 if (typeof MAX_TTL[extension] === 'number') { 135 return MAX_TTL[extension]; 136 } else { 137 return MAX_TTL["/"]; 138 } 139 } else { 140 return MAX_TTL["/"]; 141 } 142} 143 144/** 145 * pwaForWpinstallServiceWorker 146 * @returns {Promise} 147 */ 148function pwaForWpinstallServiceWorker() { 149 return Promise.all( 150 [ 151 caches.open(CACHE_VERSIONS.content) 152 .then( 153 (cache) => { 154 155 if(BASE_CACHE_FILES.length >0){ 156 157 for (var i = 0; i < BASE_CACHE_FILES.length; i++) { 158 159 pwaForWpprecacheUrl(BASE_CACHE_FILES[i]) 160 161 } 162 163 } 164 165 //return cache.addAll(BASE_CACHE_FILES);
166 } 167 ), 168 caches.open(CACHE_VERSIONS.offline) 169 .then( 170 (cache) => { 171 return cache.addAll(OFFLINE_CACHE_FILES); 172 } 173 ), 174 caches.open(CACHE_VERSIONS.notFound) 175 .then( 176 (cache) => { 177 return cache.addAll(NOT_FOUND_CACHE_FILES); 178 } 179 ) 180 ] 181 ) 182 .then(() => { 183 return self.skipWaiting(); 184 }); 185} 186 187/** 188 * pwaForWpcleanupLegacyCache 189 * @returns {Promise} 190 */ 191function pwaForWpcleanupLegacyCache() { 192 193 let currentCaches = Object.keys(CACHE_VERSIONS) 194 .map( 195 (key) => { 196 return CACHE_VERSIONS[key]; 197 } 198 ); 199 200 return new Promise( 201 (resolve, reject) => { 202 203 caches.keys() 204 .then( 205 (keys) => { 206 return legacyKeys = keys.filter( 207 (key) => { 208 return !~currentCaches.indexOf(key); 209 } 210 ); 211 } 212 ) 213 .then( 214 (legacy) => { 215 if (legacy.length) { 216 Promise.all( 217 legacy.map( 218 (legacyKey) => { 219 return caches.delete(legacyKey) 220 } 221 ) 222 ) 223 .then( 224 () => { 225 resolve() 226 } 227 ) 228 .catch( 229 (err) => { 230 reject(err); 231 } 232 ); 233 } else { 234 resolve(); 235 } 236 } 237 ) 238 .catch( 239 () => { 240 reject(); 241 } 242 ); 243 244 } 245 ); 246} 247 248function pwaForWpprecacheUrl(url) { 249 250 if(!pwaForWpisBlackListed(url)) { 251 caches.open(CACHE_VERSIONS.content) 252 .then((cache) => { 253 cache.match(url) 254 .then((response) => { 255 if(!response) { 256 return fetch(url) 257 } else { 258 // already in cache, nothing to do. 259 return null 260 } 261 }) 262 .then((response) => { 263 if(response) { 264 fetch(url).then(dataWrappedByPromise => dataWrappedByPromise.text()) 265 .then(data => { 266 if(data){ 267 const regex = /<img[^>]+src="(https:\/\/[^">]+)"/g; 268 let m; 269 while ((m = regex.exec(data)) !== null) { 270 if (m.index === regex.lastIndex) { 271 regex.lastIndex++; 272 } 273 m.forEach((match, groupIndex) => { 274 if(groupIndex == 1){ 275 if(new URL(match).origin == location.origin){ 276 fetch(match). 277 then((imagedata) => { 278 //console.log(imagedata); 279 cache.put(match, imagedata.clone()); 280 281 }); 282 } 283 } 284 }); 285 } 286 287 288 } 289 290 291 });
292 293 return cache.put(url, response.clone()); 294 } else { 295 return null; 296 } 297 }); 298 }) 299 } 300} 301 302var fetchRengeData = function(event){ 303 var pos = Number(/^bytes\=(\d+)\-$/g.exec(event.request.headers.get('range'))[1]); 304 console.log('Range request for', event.request.url, ', starting position:', pos); 305 event.respondWith( 306 caches.open(CACHE_VERSIONS.content) 307 .then(function(cache) { 308 return cache.match(event.request.url); 309 }).then(function(res) { 310 if (!res) { 311 return fetch(event.request) 312 .then(res => { 313 return res.arrayBuffer(); 314 }); 315 } 316 return res.arrayBuffer(); 317 }).then(function(ab) { 318 return new Response( 319 ab.slice(pos), 320 { 321 status: 206, 322 statusText: 'Partial Content', 323 headers: [ 324 // ['Content-Type', 'video/webm'], 325 ['Content-Range', 'bytes ' + pos + '-' + 326 (ab.byteLength - 1) + '/' + ab.byteLength]] 327 }); 328 })); 329} 330 331let cachingStrategy = { 332 notGetMethods: function(event){ 333 // If non-GET request, try the network first, fall back to the offline page 334 if (event.request.method !== 'GET') { 335 event.respondWith( 336 fetch(event.request) 337 .catch(error => { 338 return caches.match(offlinePage); 339 }) 340 ); 341 return false; 342 } 343 }, 344 345 fetchFromCache: function(event){ 346 /* return new Promise( 347 (resolve) => {*/ 348 return caches.open(CACHE_VERSIONS.content) 349 .then( 350 (cache) => { 351 352 return cache.match(event.request) 353 .then( 354 (response) => { 355 356 if (response) { 357 358 let headers = response.headers.entries(); 359 let date = null; 360 361 for (let pair of headers) { 362 if (pair[0] === 'date') { 363 date = new Date(pair[1]); 364 } 365 } 366 367 if (date) { 368 let age = parseInt((new Date().getTime() - date.getTime())/1000); 369 let ttl = pwaForWpgetTTL(event.request.url); 370 371 if (age > ttl) { 372 373 return new Promise( 374 (resolve) => { 375 376 return fetch(event.request.clone()) 377 .then( 378 (updatedResponse) => { 379 if (updatedResponse) { 380 cache.put(event.request, updatedResponse.clone()); 381 resolve(updatedResponse); 382 } else { 383 resolve(response) 384 } 385 } 386 ) 387 .catch( 388 () => { 389 resolve(response); 390 } 391 ); 392 393 } 394 ) 395 .catch( 396 (err) => { 397 return response; 398 } 399 ); 400 } else { 401 return response; 402 } 403 404 } else { 405 return response; 406 } 407 408 } else { 409 return null; 410 } 411 } 412 ) 413 .then( 414 (response) => { 415 if (response) { 416 return response; 417 } else { 418 return fetch(event.request.clone(), {cache: "no-store"}) 419 .then( 420 (response) => { 421 422 if(response.status < 300) { 423 if (~SUPPORTED_METHODS.indexOf(event.request.method) && !pwaForWpisBlackListed(event.request.url)) { 424 cache.put(event.request, response.clone()); 425 } 426 return response; 427 } else { 428 return caches.open(CACHE_VERSIONS.notFound).then((cache) => { 429 return cache.match(NOT_FOUND_PAGE); 430 }) 431 } 432 } 433 ) 434 .then((response) => { 435 if (response) { 436 return response; 437 } 438 return cachingStrategy.Offlinepage(); 439 }) 440 .catch( 441 () => { 442 return cachingStrategy.Offlinepage(); 443 } 444 ); 445 } 446 } 447 ) 448 .catch( 449 (error) => { 450 console.error(' Error in fetch handler:', error); 451 return cachingStrategy.Offlinepage(); 452 } 453 ); 454 } 455 ) 456 /*})*/ 457 458 }, 459 fetchnetwork: function(event){ 460 return caches.open(CACHE_VERSIONS.content) 461 .then( 462 (cache) => { 463 return fetch(event.request.clone()).then(function (response) { 464 465 if(response.status < 300) { 466 if (~SUPPORTED_METHODS.indexOf(event.request.method) && !pwaForWpisBlackListed(event.request.url)) { 467 cache.put(event.request, response.clone()); 468 } 469 return response; 470 }else if(response.status==404){ 471 return cachingStrategy.Notfoundpage(); 472 } 473 return cache.match(event.request).then(function (cached) { 474 return cached || cachingStrategy.Offlinepage(); 475 }); 476 }).catch( 477 function () { 478 return cache.match(event.request).then(function (cached) { 479 return cached || cachingStrategy.Offlinepage(); 480 }); 481 } 482 ); 483 } 484 ).catch( 485 (err) => { 486 return cachingStrategy.Offlinepage(); 487 } 488 ) 489 }, 490 addCache: function(event,updatedResponse){ 491 cache.put(event.request, updatedResponse.clone()); 492 resolve(updatedResponse); 493 }, 494 Offlinepage: function(){ 495 var fallbackHtml = '<html><head><title>Offline</title></head><body><h1>You are offline</h1><p>Please check your internet connection.</p></body></html>'; 496 var fallback = new Response(fallbackHtml, { 497 status: 503, 498 statusText: 'Service Unavailable', 499 headers: new Headers({ 500 'Content-Type': 'text/html; charset=UTF-8' 501 }) 502 }); 503 return caches.open(CACHE_VERSIONS.offline).then(function (cache) { 504 return cache.match(OFFLINE_PAGE).then(function (r) { 505 return r || cache.match(OFFLINE_PAGE, { ignoreSearch: true });
506 }); 507 }).then(function (response) { 508 return response || fallback; 509 }).catch(function () { 510 return fallback; 511 }); 512 }, 513 Notfoundpage: function(){ 514 return caches.open(CACHE_VERSIONS.notFound).then((cache) => { 515 return cache.match(NOT_FOUND_PAGE); 516 }).then(function (response) { 517 if (response) { 518 return response; 519 } 520 return new Response('<html><head><title>Page Not Found</title></head><body><h1>404 - Page Not Found</h1></body></html>', { 521 status: 404, 522 statusText: 'Not Found', 523 headers: new Headers({ 524 'Content-Type': 'text/html; charset=UTF-8' 525 }) 526 }); 527 }); 528 }, 529 /*Strategies*/ 530 networkOnlyStrategy: function(event){ 531 return caches.open(CACHE_VERSIONS.content) 532 .then( 533 (cache) => { 534 return fetch(event.request.clone()).then(function (response) { 535 if(response.status < 300) { 536 if (~SUPPORTED_METHODS.indexOf(event.request.method) && !pwaForWpisBlackListed(event.request.url)) { 537 cache.put(event.request, response.clone()); 538 } 539 return response; 540 }else if(response.status==404){ 541 return cachingStrategy.Notfoundpage(); 542 } 543 return cache.match(event.request).then(function (cached) { 544 return cached || cachingStrategy.Offlinepage(); 545 }); 546 }).catch( 547 (err) => { 548 return cachingStrategy.Offlinepage(); 549 } 550 ) 551 } 552 ).catch( 553 (err) => { 554 return cachingStrategy.Offlinepage() 555 } 556 ); 557 }, 558 cacheFirstStrategy: function(events){ 559 return cachingStrategy.fetchFromCache(events).catch( 560 (err) => { 561 return cachingStrategy.Offlinepage() 562 } 563 ); 564 }, 565 NeworkFirstStrategy: function(events){ 566 return cachingStrategy.fetchnetwork(events).catch( 567 (err) => { 568 return cachingStrategy.fetchFromCache(events) 569 } 570 ).catch( 571 (err) => { 572 return cachingStrategy.Offlinepage() 573 } 574 ); 575 } 576 577 578} 579 580/** 581 * Guarantees event.respondWith() always receives a Promise<Response>. 582 * Fixes networkFirst when a branch resolves with undefined (e.g. missing 404/offline cache). 583 */ 584function pwaForWpEnsureResponse(promise) { 585 return Promise.resolve(promise).then(function (res) { 586 if (res && res instanceof Response) { 587 return res; 588 } 589 return cachingStrategy.Offlinepage(); 590 }).catch(function () { 591 return cachingStrategy.Offlinepage(); 592 }); 593} 594 595 596self.addEventListener( 597 'install', event => { 598 event.waitUntil( 599 Promise.all([ 600 pwaForWpinstallServiceWorker(), 601 self.skipWaiting(), 602 ]) 603 ); 604 } 605); 606 607// The activate handler takes care of cleaning up old caches. 608self.addEventListener( 609 'activate', event => { 610 event.waitUntil( 611 Promise.all( 612 [ 613 pwaForWpcleanupLegacyCache(), 614 self.clients.claim(),
615 self.skipWaiting(), 616 ] 617 ) 618 .catch( 619 (err) => { 620 self.skipWaiting(); 621 } 622 ) 623 ); 624 } 625); 626self.addEventListener('online', event => { 627 if (navigator.onLine && navigator.standalone === true) { 628 isReachable(event.request.url).then(function(online) { 629 if (online) { 630 //handle online status 631 caches.delete(event.request.url); 632 console.log('online'); 633 } else { 634 console.log('no connectivity'); 635 } 636 }); 637 } else { 638 //handle offline status 639 console.log('offline'); 640 } 641}); 642 643function isReachable(url) { 644 /** 645 * Note: fetch() still "succeeds" for 404s on subdirectories, 646 * which is ok when only testing for domain reachability. 647 */ 648 return fetch(url, { method: 'HEAD', mode: 'no-cors' }) 649 .then(function(resp) { 650 return resp && (resp.ok || resp.type === 'opaque'); 651 }) 652 .catch(function(err) { 653 console.warn('[conn test failure]:', err); 654 }); 655} 656 657self.addEventListener( 658 'fetch', event => { 659 // Return if the current request url is in the never cache list 660 if ( ! neverCacheUrls.every(pwaForWpcheckNeverCacheList, event.request.url) ) { 661 //console.log( 'PWA ServiceWorker: URL exists in excluded list of cache.' + event.request.url); 662 return; 663 } 664 if(! neverCacheUrls.every(pwaForWpcheckNeverCacheList, event.request.referrer) ){ 665 //console.log( 'PWA ServiceWorker: Ref-URL exists in excluded list of cache.' + event.request.referrer); 666 return; 667 } 668 if(pwaForWpisBlackListed(event.request.url)){ 669 return; 670 } 671 672 const url = new URL(event.request.url); 673 674 if (pwaForWpVisibilityBypassPath(url.pathname)) { 675 return; 676 } 677 678 path_array = url.pathname.split('/') 679 if (event.request.method === 'POST' && path_array.includes('activity')) { 680 return event.respondWith((async () => { 681 const formData = await event.request.formData(); 682 const title = formData.get('title'); 683 const text = formData.get('text'); 684 const link = formData.get('url'); 685 const image = formData.get('externalMedia'); 686 const reader = new FileReader(); 687 688 reader.onload = async (event) => { 689 const imageData = event.target.result; 690 691 const db = await openDatabase(); 692 await saveData(db, { 693 id: 'sharedData', 694 title: title, 695 text: text, 696 url: link, 697 image: imageData 698 }); 699 700 console.log('Data saved to IndexedDB'); 701 702 // return Response.redirect('/?share-target', 303); 703 return Response.redirect(url.pathname+'/?share-target', 303); 704 }; 705 706 reader.readAsDataURL(image); 707 return Response.redirect(url.pathname+'/?share-target', 303); 708 // return Response.redirect('/?share-target', 303); 709 })()); 710 } 711 712 // Return if request url protocal isn't http or https 713 if ( ! event.request.url.match(/^(http|https):\/\//i) ) 714 return; 715 if ( event.request.referrer.match(/^(wp-admin):\/\//i) ) 716 return; 717 718 if ( new URL(event.request.url).origin !== location.origin ) 719 return; 720 721 if(event.request.method !== 'GET' ){ 722 event.respondWith( 723 fetch(event.request) 724 .catch(error => { 725 return caches.open(CACHE_VERSIONS.offline).then(function(cache) { 726 return cache.match(OFFLINE_PAGE); 727 }).then(function(res) { 728 return res || new Response('', { status: 503, statusText: 'Service Unavailable' }); 729 }); 730 }) 731 ); 732 return false; 733 } 734 const destination = event.request.destination; 735 switch (destination) { 736 case 'style': 737 case 'script': 738 cachingStrategyType = CACHE_STRATEGY.css_js; 739 break; 740 case 'document': 741 cachingStrategyType = CACHE_STRATEGY.default 742 break; 743 case 'image': 744 cachingStrategyType = CACHE_STRATEGY.images; 745 break; 746 case 'font': 747 cachingStrategyType = CACHE_STRATEGY.fonts; 748 break; 749 // All `XMLHttpRequest` or `fetch()` calls where 750 // `Request.destination` is the empty string default value 751 default: 752 cachingStrategyType = CACHE_STRATEGY.default 753 } 754 var cache = null; 755 switch(cachingStrategyType){ 756 case "networkFirst": 757 cache = cachingStrategy.NeworkFirstStrategy(event) 758 break; 759 case "networkOnly": 760 cache = cachingStrategy.networkOnlyStrategy(event) 761 break; 762 //break;
763 case "cacheFirst": 764 case "staleWhileRevalidate": 765 default: 766 cache = cachingStrategy.cacheFirstStrategy(event) 767 break; 768 } 769 event.respondWith(pwaForWpEnsureResponse(cache)); 770 771 } 772); 773 774function openDatabase() { 775 return new Promise((resolve, reject) => { 776 const request = indexedDB.open('shareTargetDB', 1); 777 778 request.onupgradeneeded = (event) => { 779 const db = event.target.result; 780 db.createObjectStore('sharedData', { keyPath: 'id' }); 781 }; 782 783 request.onsuccess = (event) => { 784 resolve(event.target.result); 785 }; 786 787 request.onerror = (event) => { 788 reject(event.target.error); 789 }; 790 }); 791 } 792 793 function saveData(db, data) { 794 return new Promise((resolve, reject) => { 795 const transaction = db.transaction('sharedData', 'readwrite'); 796 const store = transaction.objectStore('sharedData'); 797 798 const request = store.put(data); 799 800 request.onsuccess = () => { 801 resolve(); 802 }; 803 804 request.onerror = (event) => { 805 reject(event.target.error); 806 }; 807 }); 808 } 809 810 811self.addEventListener('message', (event) => { 812 813 if( 814 typeof event.data === 'object' && 815 typeof event.data.action === 'string' 816 ) { 817 switch(event.data.action) { 818 case 'cache' : 819 pwaForWpprecacheUrl(event.data.url); 820 break; 821 822 default : 823 console.log('Unknown action: ' + event.data.action); 824 break; 825 } 826 } 827 828}); 829 830
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.