Unified · Split
| @@ -11,6 +11,34 @@ const urlsToCache = [ · 10 unmodified lines | |||
| 11 | '<%= doc_index_urls.join "',\n '" %>', | 11 | '<%= doc_index_urls.join "',\n '" %>', |
| 12 | ]; | 12 | ]; |
| 13 | 13 | ||
| 14 | <%# Clone a request with the mode set to 'cors' %> | ||
| 15 | function corsify(request) { | ||
| 16 | const options = { | ||
| 17 | mode: 'cors', | ||
| 18 | }; | ||
| 19 | |||
| 20 | const keys = [ | ||
| 21 | 'body', | ||
| 22 | 'cache', | ||
| 23 | 'credentials', | ||
| 24 | 'headers', | ||
| 25 | 'integrity', | ||
| 26 | 'keepalive', | ||
| 27 | 'method', | ||
| 28 | 'redirect', | ||
| 29 | 'referrer', | ||
| 30 | 'referrerPolicy', | ||
| 31 | 'signal', | ||
| 32 | 'window', | ||
| 33 | ]; | ||
| 34 | |||
| 35 | for (const key of keys) { | ||
| 36 | options[key] = request[key]; | ||
| 37 | } | ||
| 38 | |||
| 39 | return new Request(request.url, options); | ||
| 40 | } | ||
| 41 | |||
| 14 | <%# Set-up the cache %> | 42 | <%# Set-up the cache %> |
| 15 | self.addEventListener('install', event => { | 43 | self.addEventListener('install', event => { |
| 16 | self.skipWaiting(); | 44 | self.skipWaiting(); |
| @@ -36,9 +64,11 @@ self.addEventListener('fetch', event => { · 19 unmodified lines | |||
| 36 | if (cachedResponse) return cachedResponse; | 64 | if (cachedResponse) return cachedResponse; |
| 37 | 65 | ||
| 38 | try { | 66 | try { |
| 39 | const response = await fetch(event.request); | 67 | const response = await fetch(corsify(event.request)); |
| 40 | 68 | ||
| 41 | if (!response.ok) { | 69 | <%# If the status code is 0 it means the response is opaque %> |
| 70 | <%# If the response is opaque it's not possible to read whether it is successful or not, so we assume it is %> | ||
| 71 | if (!response.ok && response.status !== 0) { | ||
| 42 | throw new Error(`The HTTP request failed with status code ${response.status}`); | 72 | throw new Error(`The HTTP request failed with status code ${response.status}`); |
| 43 | } | 73 | } |
| 44 | 74 | ||
| @@ -46,11 +76,13 @@ self.addEventListener('fetch', event => { · 1 unmodified line | |||
| 46 | } catch (err) { | 76 | } catch (err) { |
| 47 | const url = new URL(event.request.url); | 77 | const url = new URL(event.request.url); |
| 48 | 78 | ||
| 49 | <%# Attempt to return the index page from the cache if the user is visiting a url like devdocs.io/offline or devdocs.io/javascript/global_objects/array/find %> | ||
| 50 | <%# The index page will make sure the correct documentation or a proper offline page is shown %> | ||
| 51 | const pathname = url.pathname; | 79 | const pathname = url.pathname; |
| 52 | const filename = pathname.substr(1 + pathname.lastIndexOf('/')).split(/\#|\?/g)[0]; | 80 | const filename = pathname.substr(1 + pathname.lastIndexOf('/')).split(/\#|\?/g)[0]; |
| 53 | if (url.origin === location.origin && !['.css', '.js', '.json', '.png', '.ico', '.svg', '.xml'].some(ext => filename.endsWith(ext))) { | 81 | const extensions = ['.html', '.css', '.js', '.json', '.png', '.ico', '.svg', '.xml']; |
| 82 | |||
| 83 | <%# Attempt to return the index page from the cache if the user is visiting a url like devdocs.io/offline or devdocs.io/javascript/global_objects/array/find %> | ||
| 84 | <%# The index page will make sure the correct documentation or a proper offline page is shown %> | ||
| 85 | if (url.origin === location.origin && !extensions.some(ext => filename.endsWith(ext))) { | ||
| 54 | const cachedIndex = await caches.match('/'); | 86 | const cachedIndex = await caches.match('/'); |
| 55 | if (cachedIndex) return cachedIndex; | 87 | if (cachedIndex) return cachedIndex; |
| 56 | } | 88 | } |