show: make highlight legible
[debiancodesearch.git] / static / service-worker.js
blob116f202c3929e209585530b757fb8c61ffde455a
1 // vim:ts=4:sw=4:et
2 var version = 'v2/';
4 var assets = {
5     '/non-critical.min.css': true,
6     '/Pics/openlogo-50.svg': true,
7     '/jquery.min.js': true,
8     '/url-search-params.min.js': true,
9     '/loadCSS.min.js': true,
10     '/cssrelpreload.min.js': true,
11     '/instant.min.js?17': true,
12     // Only cache fonts in woff2 format, all browsers which support service
13     // workers also support woff2.
14     '/Inconsolata.woff2': true,
15     '/Roboto-Regular.woff2': true,
16     '/Roboto-Bold.woff2': true,
17     '/placeholder.html?3': true
20 var entityMap = {
21   "&": "&",
22   "<": "&lt;",
23   ">": "&gt;",
24   '"': '&quot;',
25   "'": '&#39;',
26   "/": '&#x2F;'
29 function escapeHtml(string) {
30   return String(string).replace(/[&<>"'\/]/g, function (s) {
31     return entityMap[s];
32   });
35 self.addEventListener("install", function(event) {
36     event.waitUntil(
37         caches
38             .open(version + 'assets')
39             .then(function(cache) {
40                 return cache.addAll(Object.keys(assets));
41             })
42     );
43 });
45 self.addEventListener("activate", function(event) {
46     // The new version of the service worker is activated, superseding any old
47     // version. Go through the cache and delete all assets whose key doesn’t
48     // start with the current version prefix.
49     event.waitUntil(
50         caches
51             .keys()
52             .then(function(keys) {
53                 return Promise.all(
54                     keys
55                         .filter(function(key) {
56                             return !key.startsWith(version);
57                         })
58                         .map(function(key) {
59                             return caches['delete'](key);
60                         })
61                 );
62             })
63     );
64 });
66 self.addEventListener("fetch", function(event) {
67     if (event.request.method !== 'GET') {
68         return;
69     }
70     var u = new URL(event.request.url);
71     if (assets[u.pathname + u.search] === true) {
72         event.respondWith(caches.match(event.request).then(function(response) {
73             // Defense in depth: in case the cache request fails, fall back to
74             // fetching the request.
75             return response || fetch(event.request);
76         }));
77         return;
78     }
79     if (u.pathname === '/search') {
80         event.respondWith(caches.match('/placeholder.html?3').then(function(response) {
81             if (!response) {
82                 return fetch(event.request);
83             }
84             var q = u.searchParams.get('q')
85             if (q === undefined) {
86                 return response;
87             }
89             // HTML escape q so that it is safe to string-replace into the
90             // placeholder document.
91             q = escapeHtml(q);
93             var init = {
94                 status: response.status,
95                 statusText: response.statusText,
96                 headers: {},
97             };
98             response.headers.forEach(function(v, k) {
99                 init.headers[k] = v;
100             });
101             return response.text().then(function(body) {
102                 var replaced = body.replace(/%q%/g, q);
103                 return new Response(replaced, init);
104             });
105         }));
106         return;
107     }
108     return;