From 91a0319a44973f39a9b5a2b1c643168526748c94 Mon Sep 17 00:00:00 2001
From: Stefan Schneider <stefan@netshake.com>
Date: Sun, 3 Oct 2021 12:13:32 +0200
Subject: [PATCH 1/5] style(prettier): :art: Ran prettier on all files

ref #71
---
 .babelrc                   |    8 +-
 .prettierrc                |   14 +-
 .vscode/settings.json      |   11 +-
 CODE_OF_CONDUCT.md         |   24 +-
 CONTRIBUTING.md            |   90 +-
 README.md                  |   40 +-
 package.json               |    2 +-
 public/manifest.json       |  128 +-
 public/service-worker.js   |  143 +-
 public/workbox-e536220e.js | 4952 ++++++++++++++++++------------------
 styles/global.css          |  104 +-
 tsconfig.json              |   16 +-
 vercel.json                |   18 +-
 13 files changed, 2754 insertions(+), 2796 deletions(-)

diff --git a/.babelrc b/.babelrc
index 17af82b..a6f4434 100644
--- a/.babelrc
+++ b/.babelrc
@@ -1,6 +1,4 @@
 {
-    "presets": ["next/babel"],
-    "plugins": [
-      "inline-react-svg"
-    ]
-}
\ No newline at end of file
+  "presets": ["next/babel"],
+  "plugins": ["inline-react-svg"]
+}
diff --git a/.prettierrc b/.prettierrc
index dd83658..90e2ddc 100644
--- a/.prettierrc
+++ b/.prettierrc
@@ -1,8 +1,8 @@
 {
-    "arrowParens": "avoid",
-    "printWidth": 120,
-    "singleQuote": true,
-    "tabWidth": 2,
-    "trailingComma": "es5",
-    "endOfLine": "auto"
-}
\ No newline at end of file
+  "arrowParens": "avoid",
+  "printWidth": 120,
+  "singleQuote": true,
+  "tabWidth": 2,
+  "trailingComma": "es5",
+  "endOfLine": "auto"
+}
diff --git a/.vscode/settings.json b/.vscode/settings.json
index bb621a9..1894e96 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -1,7 +1,8 @@
 {
-    "editor.codeActionsOnSave": {
-      "source.fixAll.eslint": true
-    },
+  "editor.codeActionsOnSave": {
+    "source.fixAll.eslint": true
+  },
   "editor.formatOnSave": true, // Tell VSCode to format files on save
-  "editor.defaultFormatter": "esbenp.prettier-vscode" 
-}
\ No newline at end of file
+  "editor.defaultFormatter": "esbenp.prettier-vscode",
+  "conventionalCommits.scopes": ["prettier"]
+}
diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md
index 01ab268..8b9e327 100644
--- a/CODE_OF_CONDUCT.md
+++ b/CODE_OF_CONDUCT.md
@@ -14,21 +14,21 @@ orientation.
 Examples of behavior that contributes to creating a positive environment
 include:
 
-* Using welcoming and inclusive language
-* Being respectful of differing viewpoints and experiences
-* Gracefully accepting constructive criticism
-* Focusing on what is best for the community
-* Showing empathy towards other community members
+- Using welcoming and inclusive language
+- Being respectful of differing viewpoints and experiences
+- Gracefully accepting constructive criticism
+- Focusing on what is best for the community
+- Showing empathy towards other community members
 
 Examples of unacceptable behavior by participants include:
 
-* The use of sexualized language or imagery and unwelcome sexual attention or
-advances
-* Trolling, insulting/derogatory comments, and personal or political attacks
-* Public or private harassment
-* Publishing others' private information, such as a physical or electronic
+- The use of sexualized language or imagery and unwelcome sexual attention or
+  advances
+- Trolling, insulting/derogatory comments, and personal or political attacks
+- Public or private harassment
+- Publishing others' private information, such as a physical or electronic
   address, without explicit permission
-* Other conduct which could reasonably be considered inappropriate in a
+- Other conduct which could reasonably be considered inappropriate in a
   professional setting
 
 ## Our Responsibilities
@@ -71,4 +71,4 @@ This Code of Conduct is adapted from the [Contributor Covenant][homepage], versi
 available at [http://contributor-covenant.org/version/1/4][version]
 
 [homepage]: http://contributor-covenant.org
-[version]: http://contributor-covenant.org/version/1/4/
\ No newline at end of file
+[version]: http://contributor-covenant.org/version/1/4/
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 7bf054f..daa345c 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -1,43 +1,49 @@
- # Contributing
- ## Issues
- Issues are very valuable to this project.
- 
- * Ideas are a valuable source of contributions others can make
- * Problems show where this project is lacking
- * With a question you show where contributors can improve the user experience
- 
- Thank you for creating them.
- 
- ## Pull Requests
- Pull requests are, a great way to get your ideas into this repository.
- 
- When deciding if we merge in a pull request we look at the following things:
- 
- ### Does it state intent
- You should be clear which problem you're trying to solve with your contribution.
- 
- For example:
- 
-  Add link to code of conduct in README.md
- 
- Doesn't tell us anything about why you're doing that
- 
-  Add link to code of conduct in README.md because users don't always look in the CONTRIBUTING.md
- 
- Tells us the problem that you have found, and the pull request shows us the action you have taken to solve it.
- 
- ### Is it of good quality
- * There are no spelling mistakes
- * It reads well
- * For english language contributions: Has a good score on [Grammarly](grammarly.com) or [Hemingway App](http://www.hemingwayapp.com/)
- 
- ### Does it move this repository closer to my vision for the repository
- The aim of this repository is:
- 
- * To provide a README.md and assorted documents anyone can copy and paste, into their project
- * The content is usable by someone who hasn't written something like this before
- * Foster a culture of respect and gratitude in the open source community.
- 
- ### Does it follow the contributor covenant
- This repository has a [code of conduct](CODE_OF_CONDUCT.md), This repository has a code of conduct, we will remove things that do not respect it.
+# Contributing
 
+## Issues
+
+Issues are very valuable to this project.
+
+- Ideas are a valuable source of contributions others can make
+- Problems show where this project is lacking
+- With a question you show where contributors can improve the user experience
+
+Thank you for creating them.
+
+## Pull Requests
+
+Pull requests are, a great way to get your ideas into this repository.
+
+When deciding if we merge in a pull request we look at the following things:
+
+### Does it state intent
+
+You should be clear which problem you're trying to solve with your contribution.
+
+For example:
+
+Add link to code of conduct in README.md
+
+Doesn't tell us anything about why you're doing that
+
+Add link to code of conduct in README.md because users don't always look in the CONTRIBUTING.md
+
+Tells us the problem that you have found, and the pull request shows us the action you have taken to solve it.
+
+### Is it of good quality
+
+- There are no spelling mistakes
+- It reads well
+- For english language contributions: Has a good score on [Grammarly](grammarly.com) or [Hemingway App](http://www.hemingwayapp.com/)
+
+### Does it move this repository closer to my vision for the repository
+
+The aim of this repository is:
+
+- To provide a README.md and assorted documents anyone can copy and paste, into their project
+- The content is usable by someone who hasn't written something like this before
+- Foster a culture of respect and gratitude in the open source community.
+
+### Does it follow the contributor covenant
+
+This repository has a [code of conduct](CODE_OF_CONDUCT.md), This repository has a code of conduct, we will remove things that do not respect it.
diff --git a/README.md b/README.md
index a639e44..871335b 100644
--- a/README.md
+++ b/README.md
@@ -35,39 +35,39 @@ A weekly newsletter with insightful tips, tools, resources & more on React and J
 
 1. Clone the project
 
-    ```bash
-    git clone https://github.com/scriptified/scriptified.git
-    ```
+   ```bash
+   git clone https://github.com/scriptified/scriptified.git
+   ```
 
 2. Go to the project directory
 
-    ```bash
-    cd scriptified
-    ```
+   ```bash
+   cd scriptified
+   ```
 
 3. Install dependencies
 
-    ```bash
-    npm install
-    ```
+   ```bash
+   npm install
+   ```
 
-    or
+   or
 
-    ```bash
-    yarn install
-    ```
+   ```bash
+   yarn install
+   ```
 
 4. Start the development server
 
-    ```bash
-    npm run dev
-    ```
+   ```bash
+   npm run dev
+   ```
 
-    or
+   or
 
-    ```bash
-    yarn dev
-    ```
+   ```bash
+   yarn dev
+   ```
 
 ## Scriptified CMS
 
diff --git a/package.json b/package.json
index 652c0c8..3a2e5d9 100644
--- a/package.json
+++ b/package.json
@@ -45,4 +45,4 @@
     "prettier": "2.1.1",
     "typescript": "4.3.5"
   }
-}
\ No newline at end of file
+}
diff --git a/public/manifest.json b/public/manifest.json
index ea064da..8f06eb4 100644
--- a/public/manifest.json
+++ b/public/manifest.json
@@ -1,65 +1,65 @@
 {
-    "short_name": "Scriptified",
-    "name": "Scriptified",
-    "description": "Insightful tips, tools, resources & more on React and JavaScript",
-    "icons": [
-      {
-        "src": "/icons/android-icon-36x36.png",
-        "sizes": "36x36",
-        "type": "image/png"
-      },
-      {
-        "src": "/icons/android-icon-48x48.png",
-        "sizes": "48x48",
-        "type": "image/png"
-      },
-      {
-        "src": "/icons/android-icon-72x72.png",
-        "sizes": "72x72",
-        "type": "image/png"
-      },
-      {
-        "src": "/icons/android-icon-96x96.png",
-        "sizes": "96x96",
-        "type": "image/png"
-      },
-      {
-        "src": "/icons/android-icon-144x144.png",
-        "sizes": "144x144",
-        "type": "image/png"
-      },
-      {
-        "src": "/icons/maskable_icon.png",
-        "sizes": "345x345",
-        "type": "image/png",
-        "purpose": "maskable"
-      },
-      {
-        "src": "/icons/android-icon-512x512.png",
-        "sizes": "512x512",
-        "type": "image/png"
-      }
-    ],
-    "theme_color": "#FFFFFF",
-    "background_color": "#FFFFFF",
-    "start_url": "/?utm_source=pwa",
-    "scope": "/",
-    "display": "standalone",
-    "orientation": "portrait",
-    "shortcuts": [
-      {
-        "name": "View All Issues",
-        "short_name": "Issues",
-        "description": "Read all the issues of Scriptified",
-        "url": "/issues?utm_source=pwa",
-        "icons": [{ "src": "/icons/view-issues.png", "sizes": "192x192" }]
-      },
-      {
-        "name": "Scriptified on Twitter",
-        "short_name": "Twitter",
-        "description": "Open twitter profile of Scriptified",
-        "url": "/twitter?utm_source=scriptified_pwa",
-        "icons": [{ "src": "/icons/twitter.png", "sizes": "192x192" }]
-      }
-    ]
-  }
\ No newline at end of file
+  "short_name": "Scriptified",
+  "name": "Scriptified",
+  "description": "Insightful tips, tools, resources & more on React and JavaScript",
+  "icons": [
+    {
+      "src": "/icons/android-icon-36x36.png",
+      "sizes": "36x36",
+      "type": "image/png"
+    },
+    {
+      "src": "/icons/android-icon-48x48.png",
+      "sizes": "48x48",
+      "type": "image/png"
+    },
+    {
+      "src": "/icons/android-icon-72x72.png",
+      "sizes": "72x72",
+      "type": "image/png"
+    },
+    {
+      "src": "/icons/android-icon-96x96.png",
+      "sizes": "96x96",
+      "type": "image/png"
+    },
+    {
+      "src": "/icons/android-icon-144x144.png",
+      "sizes": "144x144",
+      "type": "image/png"
+    },
+    {
+      "src": "/icons/maskable_icon.png",
+      "sizes": "345x345",
+      "type": "image/png",
+      "purpose": "maskable"
+    },
+    {
+      "src": "/icons/android-icon-512x512.png",
+      "sizes": "512x512",
+      "type": "image/png"
+    }
+  ],
+  "theme_color": "#FFFFFF",
+  "background_color": "#FFFFFF",
+  "start_url": "/?utm_source=pwa",
+  "scope": "/",
+  "display": "standalone",
+  "orientation": "portrait",
+  "shortcuts": [
+    {
+      "name": "View All Issues",
+      "short_name": "Issues",
+      "description": "Read all the issues of Scriptified",
+      "url": "/issues?utm_source=pwa",
+      "icons": [{ "src": "/icons/view-issues.png", "sizes": "192x192" }]
+    },
+    {
+      "name": "Scriptified on Twitter",
+      "short_name": "Twitter",
+      "description": "Open twitter profile of Scriptified",
+      "url": "/twitter?utm_source=scriptified_pwa",
+      "icons": [{ "src": "/icons/twitter.png", "sizes": "192x192" }]
+    }
+  ]
+}
diff --git a/public/service-worker.js b/public/service-worker.js
index 7266f59..8f67e2d 100644
--- a/public/service-worker.js
+++ b/public/service-worker.js
@@ -19,19 +19,17 @@ if (!self.define) {
     }
     let promise = Promise.resolve();
     if (!registry[name]) {
-      
-        promise = new Promise(async resolve => {
-          if ("document" in self) {
-            const script = document.createElement("script");
-            script.src = name;
-            document.head.appendChild(script);
-            script.onload = resolve;
-          } else {
-            importScripts(name);
-            resolve();
-          }
-        });
-      
+      promise = new Promise(async resolve => {
+        if ('document' in self) {
+          const script = document.createElement('script');
+          script.src = name;
+          document.head.appendChild(script);
+          script.onload = resolve;
+        } else {
+          importScripts(name);
+          resolve();
+        }
+      });
     }
     return promise.then(() => {
       if (!registry[name]) {
@@ -42,12 +40,11 @@ if (!self.define) {
   };
 
   const require = (names, resolve) => {
-    Promise.all(names.map(singleRequire))
-      .then(modules => resolve(modules.length === 1 ? modules[0] : modules));
+    Promise.all(names.map(singleRequire)).then(modules => resolve(modules.length === 1 ? modules[0] : modules));
   };
-  
+
   const registry = {
-    require: Promise.resolve(require)
+    require: Promise.resolve(require),
   };
 
   self.define = (moduleName, depsNames, factory) => {
@@ -58,14 +55,14 @@ if (!self.define) {
     registry[moduleName] = Promise.resolve().then(() => {
       let exports = {};
       const module = {
-        uri: location.origin + moduleName.slice(1)
+        uri: location.origin + moduleName.slice(1),
       };
       return Promise.all(
         depsNames.map(depName => {
-          switch(depName) {
-            case "exports":
+          switch (depName) {
+            case 'exports':
               return exports;
-            case "module":
+            case 'module':
               return module;
             default:
               return singleRequire(depName);
@@ -73,7 +70,7 @@ if (!self.define) {
         })
       ).then(deps => {
         const facValue = factory(...deps);
-        if(!exports.default) {
+        if (!exports.default) {
           exports.default = facValue;
         }
         return exports;
@@ -81,19 +78,20 @@ if (!self.define) {
     });
   };
 }
-define("./service-worker.js",['./workbox-e536220e'], function (workbox) { 'use strict';
+define('./service-worker.js', ['./workbox-e536220e'], function (workbox) {
+  'use strict';
 
   /**
-  * Welcome to your Workbox-powered service worker!
-  *
-  * You'll need to register this file in your web app.
-  * See https://goo.gl/nhQhGp
-  *
-  * The rest of the code is auto-generated. Please don't update this file
-  * directly; instead, make changes to your Workbox build configuration
-  * and re-run your build process.
-  * See https://goo.gl/2aRDsh
-  */
+   * Welcome to your Workbox-powered service worker!
+   *
+   * You'll need to register this file in your web app.
+   * See https://goo.gl/nhQhGp
+   *
+   * The rest of the code is auto-generated. Please don't update this file
+   * directly; instead, make changes to your Workbox build configuration
+   * and re-run your build process.
+   * See https://goo.gl/2aRDsh
+   */
 
   importScripts();
   workbox.skipWaiting();
@@ -104,38 +102,53 @@ define("./service-worker.js",['./workbox-e536220e'], function (workbox) { 'use s
    * See https://goo.gl/S9QRab
    */
 
-  workbox.precacheAndRoute([{
-    "url": "/_next/static/runtime/amp.js",
-    "revision": "448564b2ecdefde43bd36b481b74be5f"
-  }, {
-    "url": "/_next/static/runtime/amp.js.map",
-    "revision": "151ff324f19c73a7d9934f1e640c6656"
-  }, {
-    "url": "/_next/static/runtime/main.js",
-    "revision": "fea8f8ade32915207a95e8f2e602c5ce"
-  }, {
-    "url": "/_next/static/runtime/main.js.map",
-    "revision": "2a4ffc62b29c786a35c62f28421cfdfb"
-  }, {
-    "url": "/_next/static/runtime/polyfills.js",
-    "revision": "cf6f4b12f4634f8f79378d41f3a855a4"
-  }, {
-    "url": "/_next/static/runtime/polyfills.js.map",
-    "revision": "82dca635a629d8ab38c3ad85b2ad65a2"
-  }, {
-    "url": "/_next/static/runtime/webpack.js",
-    "revision": "3d406d49f9f25eb6a505df647f073679"
-  }, {
-    "url": "/_next/static/runtime/webpack.js.map",
-    "revision": "1cbb5424a843655e7cfac1e6c3ba0c94"
-  }], {
-    "ignoreURLParametersMatching": [/ts/]
-  });
+  workbox.precacheAndRoute(
+    [
+      {
+        url: '/_next/static/runtime/amp.js',
+        revision: '448564b2ecdefde43bd36b481b74be5f',
+      },
+      {
+        url: '/_next/static/runtime/amp.js.map',
+        revision: '151ff324f19c73a7d9934f1e640c6656',
+      },
+      {
+        url: '/_next/static/runtime/main.js',
+        revision: 'fea8f8ade32915207a95e8f2e602c5ce',
+      },
+      {
+        url: '/_next/static/runtime/main.js.map',
+        revision: '2a4ffc62b29c786a35c62f28421cfdfb',
+      },
+      {
+        url: '/_next/static/runtime/polyfills.js',
+        revision: 'cf6f4b12f4634f8f79378d41f3a855a4',
+      },
+      {
+        url: '/_next/static/runtime/polyfills.js.map',
+        revision: '82dca635a629d8ab38c3ad85b2ad65a2',
+      },
+      {
+        url: '/_next/static/runtime/webpack.js',
+        revision: '3d406d49f9f25eb6a505df647f073679',
+      },
+      {
+        url: '/_next/static/runtime/webpack.js.map',
+        revision: '1cbb5424a843655e7cfac1e6c3ba0c94',
+      },
+    ],
+    {
+      ignoreURLParametersMatching: [/ts/],
+    }
+  );
   workbox.cleanupOutdatedCaches();
-  workbox.registerRoute(/.*/i, new workbox.NetworkOnly({
-    "cacheName": "dev",
-    plugins: []
-  }), 'GET');
-
+  workbox.registerRoute(
+    /.*/i,
+    new workbox.NetworkOnly({
+      cacheName: 'dev',
+      plugins: [],
+    }),
+    'GET'
+  );
 });
 //# sourceMappingURL=service-worker.js.map
diff --git a/public/workbox-e536220e.js b/public/workbox-e536220e.js
index 1be8eeb..fa7fd51 100644
--- a/public/workbox-e536220e.js
+++ b/public/workbox-e536220e.js
@@ -1,348 +1,343 @@
-define("./workbox-e536220e.js",['exports'], function (exports) { 'use strict';
+define('./workbox-e536220e.js', ['exports'], function (exports) {
+  'use strict';
 
-    try {
-      self['workbox:core:5.1.4'] && _();
-    } catch (e) {}
+  try {
+    self['workbox:core:5.1.4'] && _();
+  } catch (e) {}
 
-    /*
+  /*
       Copyright 2019 Google LLC
       Use of this source code is governed by an MIT-style
       license that can be found in the LICENSE file or at
       https://opensource.org/licenses/MIT.
     */
-    const logger =  (() => {
-      // Don't overwrite this value if it's already set.
-      // See https://github.com/GoogleChrome/workbox/pull/2284#issuecomment-560470923
-      if (!('__WB_DISABLE_DEV_LOGS' in self)) {
-        self.__WB_DISABLE_DEV_LOGS = false;
-      }
-
-      let inGroup = false;
-      const methodToColorMap = {
-        debug: `#7f8c8d`,
-        log: `#2ecc71`,
-        warn: `#f39c12`,
-        error: `#c0392b`,
-        groupCollapsed: `#3498db`,
-        groupEnd: null
-      };
+  const logger = (() => {
+    // Don't overwrite this value if it's already set.
+    // See https://github.com/GoogleChrome/workbox/pull/2284#issuecomment-560470923
+    if (!('__WB_DISABLE_DEV_LOGS' in self)) {
+      self.__WB_DISABLE_DEV_LOGS = false;
+    }
 
-      const print = function (method, args) {
-        if (self.__WB_DISABLE_DEV_LOGS) {
-          return;
-        }
+    let inGroup = false;
+    const methodToColorMap = {
+      debug: `#7f8c8d`,
+      log: `#2ecc71`,
+      warn: `#f39c12`,
+      error: `#c0392b`,
+      groupCollapsed: `#3498db`,
+      groupEnd: null,
+    };
 
-        if (method === 'groupCollapsed') {
-          // Safari doesn't print all console.groupCollapsed() arguments:
-          // https://bugs.webkit.org/show_bug.cgi?id=182754
-          if (/^((?!chrome|android).)*safari/i.test(navigator.userAgent)) {
-            console[method](...args);
-            return;
-          }
+    const print = function (method, args) {
+      if (self.__WB_DISABLE_DEV_LOGS) {
+        return;
+      }
+
+      if (method === 'groupCollapsed') {
+        // Safari doesn't print all console.groupCollapsed() arguments:
+        // https://bugs.webkit.org/show_bug.cgi?id=182754
+        if (/^((?!chrome|android).)*safari/i.test(navigator.userAgent)) {
+          console[method](...args);
+          return;
         }
+      }
 
-        const styles = [`background: ${methodToColorMap[method]}`, `border-radius: 0.5em`, `color: white`, `font-weight: bold`, `padding: 2px 0.5em`]; // When in a group, the workbox prefix is not displayed.
+      const styles = [
+        `background: ${methodToColorMap[method]}`,
+        `border-radius: 0.5em`,
+        `color: white`,
+        `font-weight: bold`,
+        `padding: 2px 0.5em`,
+      ]; // When in a group, the workbox prefix is not displayed.
 
-        const logPrefix = inGroup ? [] : ['%cworkbox', styles.join(';')];
-        console[method](...logPrefix, ...args);
+      const logPrefix = inGroup ? [] : ['%cworkbox', styles.join(';')];
+      console[method](...logPrefix, ...args);
 
-        if (method === 'groupCollapsed') {
-          inGroup = true;
-        }
+      if (method === 'groupCollapsed') {
+        inGroup = true;
+      }
 
-        if (method === 'groupEnd') {
-          inGroup = false;
-        }
-      };
+      if (method === 'groupEnd') {
+        inGroup = false;
+      }
+    };
 
-      const api = {};
-      const loggerMethods = Object.keys(methodToColorMap);
+    const api = {};
+    const loggerMethods = Object.keys(methodToColorMap);
 
-      for (const key of loggerMethods) {
-        const method = key;
+    for (const key of loggerMethods) {
+      const method = key;
 
-        api[method] = (...args) => {
-          print(method, args);
-        };
-      }
+      api[method] = (...args) => {
+        print(method, args);
+      };
+    }
 
-      return api;
-    })();
+    return api;
+  })();
 
-    /*
+  /*
       Copyright 2018 Google LLC
 
       Use of this source code is governed by an MIT-style
       license that can be found in the LICENSE file or at
       https://opensource.org/licenses/MIT.
     */
-    const messages = {
-      'invalid-value': ({
-        paramName,
-        validValueDescription,
-        value
-      }) => {
-        if (!paramName || !validValueDescription) {
-          throw new Error(`Unexpected input to 'invalid-value' error.`);
-        }
-
-        return `The '${paramName}' parameter was given a value with an ` + `unexpected value. ${validValueDescription} Received a value of ` + `${JSON.stringify(value)}.`;
-      },
-      'not-an-array': ({
-        moduleName,
-        className,
-        funcName,
-        paramName
-      }) => {
-        if (!moduleName || !className || !funcName || !paramName) {
-          throw new Error(`Unexpected input to 'not-an-array' error.`);
-        }
-
-        return `The parameter '${paramName}' passed into ` + `'${moduleName}.${className}.${funcName}()' must be an array.`;
-      },
-      'incorrect-type': ({
-        expectedType,
-        paramName,
-        moduleName,
-        className,
-        funcName
-      }) => {
-        if (!expectedType || !paramName || !moduleName || !funcName) {
-          throw new Error(`Unexpected input to 'incorrect-type' error.`);
-        }
-
-        return `The parameter '${paramName}' passed into ` + `'${moduleName}.${className ? className + '.' : ''}` + `${funcName}()' must be of type ${expectedType}.`;
-      },
-      'incorrect-class': ({
-        expectedClass,
-        paramName,
-        moduleName,
-        className,
-        funcName,
-        isReturnValueProblem
-      }) => {
-        if (!expectedClass || !moduleName || !funcName) {
-          throw new Error(`Unexpected input to 'incorrect-class' error.`);
-        }
-
-        if (isReturnValueProblem) {
-          return `The return value from ` + `'${moduleName}.${className ? className + '.' : ''}${funcName}()' ` + `must be an instance of class ${expectedClass.name}.`;
-        }
-
-        return `The parameter '${paramName}' passed into ` + `'${moduleName}.${className ? className + '.' : ''}${funcName}()' ` + `must be an instance of class ${expectedClass.name}.`;
-      },
-      'missing-a-method': ({
-        expectedMethod,
-        paramName,
-        moduleName,
-        className,
-        funcName
-      }) => {
-        if (!expectedMethod || !paramName || !moduleName || !className || !funcName) {
-          throw new Error(`Unexpected input to 'missing-a-method' error.`);
-        }
+  const messages = {
+    'invalid-value': ({ paramName, validValueDescription, value }) => {
+      if (!paramName || !validValueDescription) {
+        throw new Error(`Unexpected input to 'invalid-value' error.`);
+      }
 
-        return `${moduleName}.${className}.${funcName}() expected the ` + `'${paramName}' parameter to expose a '${expectedMethod}' method.`;
-      },
-      'add-to-cache-list-unexpected-type': ({
-        entry
-      }) => {
-        return `An unexpected entry was passed to ` + `'workbox-precaching.PrecacheController.addToCacheList()' The entry ` + `'${JSON.stringify(entry)}' isn't supported. You must supply an array of ` + `strings with one or more characters, objects with a url property or ` + `Request objects.`;
-      },
-      'add-to-cache-list-conflicting-entries': ({
-        firstEntry,
-        secondEntry
-      }) => {
-        if (!firstEntry || !secondEntry) {
-          throw new Error(`Unexpected input to ` + `'add-to-cache-list-duplicate-entries' error.`);
-        }
+      return (
+        `The '${paramName}' parameter was given a value with an ` +
+        `unexpected value. ${validValueDescription} Received a value of ` +
+        `${JSON.stringify(value)}.`
+      );
+    },
+    'not-an-array': ({ moduleName, className, funcName, paramName }) => {
+      if (!moduleName || !className || !funcName || !paramName) {
+        throw new Error(`Unexpected input to 'not-an-array' error.`);
+      }
 
-        return `Two of the entries passed to ` + `'workbox-precaching.PrecacheController.addToCacheList()' had the URL ` + `${firstEntry._entryId} but different revision details. Workbox is ` + `unable to cache and version the asset correctly. Please remove one ` + `of the entries.`;
-      },
-      'plugin-error-request-will-fetch': ({
-        thrownError
-      }) => {
-        if (!thrownError) {
-          throw new Error(`Unexpected input to ` + `'plugin-error-request-will-fetch', error.`);
-        }
+      return (
+        `The parameter '${paramName}' passed into ` + `'${moduleName}.${className}.${funcName}()' must be an array.`
+      );
+    },
+    'incorrect-type': ({ expectedType, paramName, moduleName, className, funcName }) => {
+      if (!expectedType || !paramName || !moduleName || !funcName) {
+        throw new Error(`Unexpected input to 'incorrect-type' error.`);
+      }
 
-        return `An error was thrown by a plugins 'requestWillFetch()' method. ` + `The thrown error message was: '${thrownError.message}'.`;
-      },
-      'invalid-cache-name': ({
-        cacheNameId,
-        value
-      }) => {
-        if (!cacheNameId) {
-          throw new Error(`Expected a 'cacheNameId' for error 'invalid-cache-name'`);
-        }
+      return (
+        `The parameter '${paramName}' passed into ` +
+        `'${moduleName}.${className ? className + '.' : ''}` +
+        `${funcName}()' must be of type ${expectedType}.`
+      );
+    },
+    'incorrect-class': ({ expectedClass, paramName, moduleName, className, funcName, isReturnValueProblem }) => {
+      if (!expectedClass || !moduleName || !funcName) {
+        throw new Error(`Unexpected input to 'incorrect-class' error.`);
+      }
 
-        return `You must provide a name containing at least one character for ` + `setCacheDetails({${cacheNameId}: '...'}). Received a value of ` + `'${JSON.stringify(value)}'`;
-      },
-      'unregister-route-but-not-found-with-method': ({
-        method
-      }) => {
-        if (!method) {
-          throw new Error(`Unexpected input to ` + `'unregister-route-but-not-found-with-method' error.`);
-        }
+      if (isReturnValueProblem) {
+        return (
+          `The return value from ` +
+          `'${moduleName}.${className ? className + '.' : ''}${funcName}()' ` +
+          `must be an instance of class ${expectedClass.name}.`
+        );
+      }
 
-        return `The route you're trying to unregister was not  previously ` + `registered for the method type '${method}'.`;
-      },
-      'unregister-route-route-not-registered': () => {
-        return `The route you're trying to unregister was not previously ` + `registered.`;
-      },
-      'queue-replay-failed': ({
-        name
-      }) => {
-        return `Replaying the background sync queue '${name}' failed.`;
-      },
-      'duplicate-queue-name': ({
-        name
-      }) => {
-        return `The Queue name '${name}' is already being used. ` + `All instances of backgroundSync.Queue must be given unique names.`;
-      },
-      'expired-test-without-max-age': ({
-        methodName,
-        paramName
-      }) => {
-        return `The '${methodName}()' method can only be used when the ` + `'${paramName}' is used in the constructor.`;
-      },
-      'unsupported-route-type': ({
-        moduleName,
-        className,
-        funcName,
-        paramName
-      }) => {
-        return `The supplied '${paramName}' parameter was an unsupported type. ` + `Please check the docs for ${moduleName}.${className}.${funcName} for ` + `valid input types.`;
-      },
-      'not-array-of-class': ({
-        value,
-        expectedClass,
-        moduleName,
-        className,
-        funcName,
-        paramName
-      }) => {
-        return `The supplied '${paramName}' parameter must be an array of ` + `'${expectedClass}' objects. Received '${JSON.stringify(value)},'. ` + `Please check the call to ${moduleName}.${className}.${funcName}() ` + `to fix the issue.`;
-      },
-      'max-entries-or-age-required': ({
-        moduleName,
-        className,
-        funcName
-      }) => {
-        return `You must define either config.maxEntries or config.maxAgeSeconds` + `in ${moduleName}.${className}.${funcName}`;
-      },
-      'statuses-or-headers-required': ({
-        moduleName,
-        className,
-        funcName
-      }) => {
-        return `You must define either config.statuses or config.headers` + `in ${moduleName}.${className}.${funcName}`;
-      },
-      'invalid-string': ({
-        moduleName,
-        funcName,
-        paramName
-      }) => {
-        if (!paramName || !moduleName || !funcName) {
-          throw new Error(`Unexpected input to 'invalid-string' error.`);
-        }
+      return (
+        `The parameter '${paramName}' passed into ` +
+        `'${moduleName}.${className ? className + '.' : ''}${funcName}()' ` +
+        `must be an instance of class ${expectedClass.name}.`
+      );
+    },
+    'missing-a-method': ({ expectedMethod, paramName, moduleName, className, funcName }) => {
+      if (!expectedMethod || !paramName || !moduleName || !className || !funcName) {
+        throw new Error(`Unexpected input to 'missing-a-method' error.`);
+      }
 
-        return `When using strings, the '${paramName}' parameter must start with ` + `'http' (for cross-origin matches) or '/' (for same-origin matches). ` + `Please see the docs for ${moduleName}.${funcName}() for ` + `more info.`;
-      },
-      'channel-name-required': () => {
-        return `You must provide a channelName to construct a ` + `BroadcastCacheUpdate instance.`;
-      },
-      'invalid-responses-are-same-args': () => {
-        return `The arguments passed into responsesAreSame() appear to be ` + `invalid. Please ensure valid Responses are used.`;
-      },
-      'expire-custom-caches-only': () => {
-        return `You must provide a 'cacheName' property when using the ` + `expiration plugin with a runtime caching strategy.`;
-      },
-      'unit-must-be-bytes': ({
-        normalizedRangeHeader
-      }) => {
-        if (!normalizedRangeHeader) {
-          throw new Error(`Unexpected input to 'unit-must-be-bytes' error.`);
-        }
+      return (
+        `${moduleName}.${className}.${funcName}() expected the ` +
+        `'${paramName}' parameter to expose a '${expectedMethod}' method.`
+      );
+    },
+    'add-to-cache-list-unexpected-type': ({ entry }) => {
+      return (
+        `An unexpected entry was passed to ` +
+        `'workbox-precaching.PrecacheController.addToCacheList()' The entry ` +
+        `'${JSON.stringify(entry)}' isn't supported. You must supply an array of ` +
+        `strings with one or more characters, objects with a url property or ` +
+        `Request objects.`
+      );
+    },
+    'add-to-cache-list-conflicting-entries': ({ firstEntry, secondEntry }) => {
+      if (!firstEntry || !secondEntry) {
+        throw new Error(`Unexpected input to ` + `'add-to-cache-list-duplicate-entries' error.`);
+      }
+
+      return (
+        `Two of the entries passed to ` +
+        `'workbox-precaching.PrecacheController.addToCacheList()' had the URL ` +
+        `${firstEntry._entryId} but different revision details. Workbox is ` +
+        `unable to cache and version the asset correctly. Please remove one ` +
+        `of the entries.`
+      );
+    },
+    'plugin-error-request-will-fetch': ({ thrownError }) => {
+      if (!thrownError) {
+        throw new Error(`Unexpected input to ` + `'plugin-error-request-will-fetch', error.`);
+      }
 
-        return `The 'unit' portion of the Range header must be set to 'bytes'. ` + `The Range header provided was "${normalizedRangeHeader}"`;
-      },
-      'single-range-only': ({
-        normalizedRangeHeader
-      }) => {
-        if (!normalizedRangeHeader) {
-          throw new Error(`Unexpected input to 'single-range-only' error.`);
-        }
+      return (
+        `An error was thrown by a plugins 'requestWillFetch()' method. ` +
+        `The thrown error message was: '${thrownError.message}'.`
+      );
+    },
+    'invalid-cache-name': ({ cacheNameId, value }) => {
+      if (!cacheNameId) {
+        throw new Error(`Expected a 'cacheNameId' for error 'invalid-cache-name'`);
+      }
 
-        return `Multiple ranges are not supported. Please use a  single start ` + `value, and optional end value. The Range header provided was ` + `"${normalizedRangeHeader}"`;
-      },
-      'invalid-range-values': ({
-        normalizedRangeHeader
-      }) => {
-        if (!normalizedRangeHeader) {
-          throw new Error(`Unexpected input to 'invalid-range-values' error.`);
-        }
+      return (
+        `You must provide a name containing at least one character for ` +
+        `setCacheDetails({${cacheNameId}: '...'}). Received a value of ` +
+        `'${JSON.stringify(value)}'`
+      );
+    },
+    'unregister-route-but-not-found-with-method': ({ method }) => {
+      if (!method) {
+        throw new Error(`Unexpected input to ` + `'unregister-route-but-not-found-with-method' error.`);
+      }
 
-        return `The Range header is missing both start and end values. At least ` + `one of those values is needed. The Range header provided was ` + `"${normalizedRangeHeader}"`;
-      },
-      'no-range-header': () => {
-        return `No Range header was found in the Request provided.`;
-      },
-      'range-not-satisfiable': ({
-        size,
-        start,
-        end
-      }) => {
-        return `The start (${start}) and end (${end}) values in the Range are ` + `not satisfiable by the cached response, which is ${size} bytes.`;
-      },
-      'attempt-to-cache-non-get-request': ({
-        url,
-        method
-      }) => {
-        return `Unable to cache '${url}' because it is a '${method}' request and ` + `only 'GET' requests can be cached.`;
-      },
-      'cache-put-with-no-response': ({
-        url
-      }) => {
-        return `There was an attempt to cache '${url}' but the response was not ` + `defined.`;
-      },
-      'no-response': ({
-        url,
-        error
-      }) => {
-        let message = `The strategy could not generate a response for '${url}'.`;
+      return (
+        `The route you're trying to unregister was not  previously ` + `registered for the method type '${method}'.`
+      );
+    },
+    'unregister-route-route-not-registered': () => {
+      return `The route you're trying to unregister was not previously ` + `registered.`;
+    },
+    'queue-replay-failed': ({ name }) => {
+      return `Replaying the background sync queue '${name}' failed.`;
+    },
+    'duplicate-queue-name': ({ name }) => {
+      return (
+        `The Queue name '${name}' is already being used. ` +
+        `All instances of backgroundSync.Queue must be given unique names.`
+      );
+    },
+    'expired-test-without-max-age': ({ methodName, paramName }) => {
+      return `The '${methodName}()' method can only be used when the ` + `'${paramName}' is used in the constructor.`;
+    },
+    'unsupported-route-type': ({ moduleName, className, funcName, paramName }) => {
+      return (
+        `The supplied '${paramName}' parameter was an unsupported type. ` +
+        `Please check the docs for ${moduleName}.${className}.${funcName} for ` +
+        `valid input types.`
+      );
+    },
+    'not-array-of-class': ({ value, expectedClass, moduleName, className, funcName, paramName }) => {
+      return (
+        `The supplied '${paramName}' parameter must be an array of ` +
+        `'${expectedClass}' objects. Received '${JSON.stringify(value)},'. ` +
+        `Please check the call to ${moduleName}.${className}.${funcName}() ` +
+        `to fix the issue.`
+      );
+    },
+    'max-entries-or-age-required': ({ moduleName, className, funcName }) => {
+      return (
+        `You must define either config.maxEntries or config.maxAgeSeconds` + `in ${moduleName}.${className}.${funcName}`
+      );
+    },
+    'statuses-or-headers-required': ({ moduleName, className, funcName }) => {
+      return `You must define either config.statuses or config.headers` + `in ${moduleName}.${className}.${funcName}`;
+    },
+    'invalid-string': ({ moduleName, funcName, paramName }) => {
+      if (!paramName || !moduleName || !funcName) {
+        throw new Error(`Unexpected input to 'invalid-string' error.`);
+      }
+
+      return (
+        `When using strings, the '${paramName}' parameter must start with ` +
+        `'http' (for cross-origin matches) or '/' (for same-origin matches). ` +
+        `Please see the docs for ${moduleName}.${funcName}() for ` +
+        `more info.`
+      );
+    },
+    'channel-name-required': () => {
+      return `You must provide a channelName to construct a ` + `BroadcastCacheUpdate instance.`;
+    },
+    'invalid-responses-are-same-args': () => {
+      return (
+        `The arguments passed into responsesAreSame() appear to be ` +
+        `invalid. Please ensure valid Responses are used.`
+      );
+    },
+    'expire-custom-caches-only': () => {
+      return (
+        `You must provide a 'cacheName' property when using the ` + `expiration plugin with a runtime caching strategy.`
+      );
+    },
+    'unit-must-be-bytes': ({ normalizedRangeHeader }) => {
+      if (!normalizedRangeHeader) {
+        throw new Error(`Unexpected input to 'unit-must-be-bytes' error.`);
+      }
 
-        if (error) {
-          message += ` The underlying error is ${error}.`;
-        }
+      return (
+        `The 'unit' portion of the Range header must be set to 'bytes'. ` +
+        `The Range header provided was "${normalizedRangeHeader}"`
+      );
+    },
+    'single-range-only': ({ normalizedRangeHeader }) => {
+      if (!normalizedRangeHeader) {
+        throw new Error(`Unexpected input to 'single-range-only' error.`);
+      }
 
-        return message;
-      },
-      'bad-precaching-response': ({
-        url,
-        status
-      }) => {
-        return `The precaching request for '${url}' failed with an HTTP ` + `status of ${status}.`;
-      },
-      'non-precached-url': ({
-        url
-      }) => {
-        return `createHandlerBoundToURL('${url}') was called, but that URL is ` + `not precached. Please pass in a URL that is precached instead.`;
-      },
-      'add-to-cache-list-conflicting-integrities': ({
-        url
-      }) => {
-        return `Two of the entries passed to ` + `'workbox-precaching.PrecacheController.addToCacheList()' had the URL ` + `${url} with different integrity values. Please remove one of them.`;
-      },
-      'missing-precache-entry': ({
-        cacheName,
-        url
-      }) => {
-        return `Unable to find a precached response in ${cacheName} for ${url}.`;
+      return (
+        `Multiple ranges are not supported. Please use a  single start ` +
+        `value, and optional end value. The Range header provided was ` +
+        `"${normalizedRangeHeader}"`
+      );
+    },
+    'invalid-range-values': ({ normalizedRangeHeader }) => {
+      if (!normalizedRangeHeader) {
+        throw new Error(`Unexpected input to 'invalid-range-values' error.`);
       }
-    };
 
-    /*
+      return (
+        `The Range header is missing both start and end values. At least ` +
+        `one of those values is needed. The Range header provided was ` +
+        `"${normalizedRangeHeader}"`
+      );
+    },
+    'no-range-header': () => {
+      return `No Range header was found in the Request provided.`;
+    },
+    'range-not-satisfiable': ({ size, start, end }) => {
+      return (
+        `The start (${start}) and end (${end}) values in the Range are ` +
+        `not satisfiable by the cached response, which is ${size} bytes.`
+      );
+    },
+    'attempt-to-cache-non-get-request': ({ url, method }) => {
+      return `Unable to cache '${url}' because it is a '${method}' request and ` + `only 'GET' requests can be cached.`;
+    },
+    'cache-put-with-no-response': ({ url }) => {
+      return `There was an attempt to cache '${url}' but the response was not ` + `defined.`;
+    },
+    'no-response': ({ url, error }) => {
+      let message = `The strategy could not generate a response for '${url}'.`;
+
+      if (error) {
+        message += ` The underlying error is ${error}.`;
+      }
+
+      return message;
+    },
+    'bad-precaching-response': ({ url, status }) => {
+      return `The precaching request for '${url}' failed with an HTTP ` + `status of ${status}.`;
+    },
+    'non-precached-url': ({ url }) => {
+      return (
+        `createHandlerBoundToURL('${url}') was called, but that URL is ` +
+        `not precached. Please pass in a URL that is precached instead.`
+      );
+    },
+    'add-to-cache-list-conflicting-integrities': ({ url }) => {
+      return (
+        `Two of the entries passed to ` +
+        `'workbox-precaching.PrecacheController.addToCacheList()' had the URL ` +
+        `${url} with different integrity values. Please remove one of them.`
+      );
+    },
+    'missing-precache-entry': ({ cacheName, url }) => {
+      return `Unable to find a precached response in ${cacheName} for ${url}.`;
+    },
+  };
+
+  /*
       Copyright 2018 Google LLC
 
       Use of this source code is governed by an MIT-style
@@ -350,333 +345,329 @@ define("./workbox-e536220e.js",['exports'], function (exports) { 'use strict';
       https://opensource.org/licenses/MIT.
     */
 
-    const generatorFunction = (code, details = {}) => {
-      const message = messages[code];
+  const generatorFunction = (code, details = {}) => {
+    const message = messages[code];
 
-      if (!message) {
-        throw new Error(`Unable to find message for code '${code}'.`);
-      }
+    if (!message) {
+      throw new Error(`Unable to find message for code '${code}'.`);
+    }
 
-      return message(details);
-    };
+    return message(details);
+  };
 
-    const messageGenerator =  generatorFunction;
+  const messageGenerator = generatorFunction;
 
-    /*
+  /*
       Copyright 2018 Google LLC
 
       Use of this source code is governed by an MIT-style
       license that can be found in the LICENSE file or at
       https://opensource.org/licenses/MIT.
     */
+  /**
+   * Workbox errors should be thrown with this class.
+   * This allows use to ensure the type easily in tests,
+   * helps developers identify errors from workbox
+   * easily and allows use to optimise error
+   * messages correctly.
+   *
+   * @private
+   */
+
+  class WorkboxError extends Error {
     /**
-     * Workbox errors should be thrown with this class.
-     * This allows use to ensure the type easily in tests,
-     * helps developers identify errors from workbox
-     * easily and allows use to optimise error
-     * messages correctly.
      *
-     * @private
+     * @param {string} errorCode The error code that
+     * identifies this particular error.
+     * @param {Object=} details Any relevant arguments
+     * that will help developers identify issues should
+     * be added as a key on the context object.
      */
-
-    class WorkboxError extends Error {
-      /**
-       *
-       * @param {string} errorCode The error code that
-       * identifies this particular error.
-       * @param {Object=} details Any relevant arguments
-       * that will help developers identify issues should
-       * be added as a key on the context object.
-       */
-      constructor(errorCode, details) {
-        const message = messageGenerator(errorCode, details);
-        super(message);
-        this.name = errorCode;
-        this.details = details;
-      }
-
+    constructor(errorCode, details) {
+      const message = messageGenerator(errorCode, details);
+      super(message);
+      this.name = errorCode;
+      this.details = details;
     }
+  }
 
-    /*
+  /*
       Copyright 2018 Google LLC
 
       Use of this source code is governed by an MIT-style
       license that can be found in the LICENSE file or at
       https://opensource.org/licenses/MIT.
     */
-    /*
-     * This method throws if the supplied value is not an array.
-     * The destructed values are required to produce a meaningful error for users.
-     * The destructed and restructured object is so it's clear what is
-     * needed.
-     */
+  /*
+   * This method throws if the supplied value is not an array.
+   * The destructed values are required to produce a meaningful error for users.
+   * The destructed and restructured object is so it's clear what is
+   * needed.
+   */
+
+  const isArray = (value, details) => {
+    if (!Array.isArray(value)) {
+      throw new WorkboxError('not-an-array', details);
+    }
+  };
 
-    const isArray = (value, details) => {
-      if (!Array.isArray(value)) {
-        throw new WorkboxError('not-an-array', details);
-      }
-    };
+  const hasMethod = (object, expectedMethod, details) => {
+    const type = typeof object[expectedMethod];
 
-    const hasMethod = (object, expectedMethod, details) => {
-      const type = typeof object[expectedMethod];
+    if (type !== 'function') {
+      details['expectedMethod'] = expectedMethod;
+      throw new WorkboxError('missing-a-method', details);
+    }
+  };
 
-      if (type !== 'function') {
-        details['expectedMethod'] = expectedMethod;
-        throw new WorkboxError('missing-a-method', details);
-      }
-    };
+  const isType = (object, expectedType, details) => {
+    if (typeof object !== expectedType) {
+      details['expectedType'] = expectedType;
+      throw new WorkboxError('incorrect-type', details);
+    }
+  };
 
-    const isType = (object, expectedType, details) => {
-      if (typeof object !== expectedType) {
-        details['expectedType'] = expectedType;
-        throw new WorkboxError('incorrect-type', details);
-      }
-    };
+  const isInstance = (object, expectedClass, details) => {
+    if (!(object instanceof expectedClass)) {
+      details['expectedClass'] = expectedClass;
+      throw new WorkboxError('incorrect-class', details);
+    }
+  };
 
-    const isInstance = (object, expectedClass, details) => {
-      if (!(object instanceof expectedClass)) {
-        details['expectedClass'] = expectedClass;
-        throw new WorkboxError('incorrect-class', details);
-      }
-    };
+  const isOneOf = (value, validValues, details) => {
+    if (!validValues.includes(value)) {
+      details['validValueDescription'] = `Valid values are ${JSON.stringify(validValues)}.`;
+      throw new WorkboxError('invalid-value', details);
+    }
+  };
 
-    const isOneOf = (value, validValues, details) => {
-      if (!validValues.includes(value)) {
-        details['validValueDescription'] = `Valid values are ${JSON.stringify(validValues)}.`;
-        throw new WorkboxError('invalid-value', details);
-      }
-    };
+  const isArrayOfClass = (value, expectedClass, details) => {
+    const error = new WorkboxError('not-array-of-class', details);
 
-    const isArrayOfClass = (value, expectedClass, details) => {
-      const error = new WorkboxError('not-array-of-class', details);
+    if (!Array.isArray(value)) {
+      throw error;
+    }
 
-      if (!Array.isArray(value)) {
+    for (const item of value) {
+      if (!(item instanceof expectedClass)) {
         throw error;
       }
-
-      for (const item of value) {
-        if (!(item instanceof expectedClass)) {
-          throw error;
-        }
-      }
-    };
-
-    const finalAssertExports =  {
-      hasMethod,
-      isArray,
-      isInstance,
-      isOneOf,
-      isType,
-      isArrayOfClass
-    };
-
-    try {
-      self['workbox:routing:5.1.4'] && _();
-    } catch (e) {}
-
-    /*
+    }
+  };
+
+  const finalAssertExports = {
+    hasMethod,
+    isArray,
+    isInstance,
+    isOneOf,
+    isType,
+    isArrayOfClass,
+  };
+
+  try {
+    self['workbox:routing:5.1.4'] && _();
+  } catch (e) {}
+
+  /*
       Copyright 2018 Google LLC
 
       Use of this source code is governed by an MIT-style
       license that can be found in the LICENSE file or at
       https://opensource.org/licenses/MIT.
     */
-    /**
-     * The default HTTP method, 'GET', used when there's no specific method
-     * configured for a route.
-     *
-     * @type {string}
-     *
-     * @private
-     */
-
-    const defaultMethod = 'GET';
-    /**
-     * The list of valid HTTP methods associated with requests that could be routed.
-     *
-     * @type {Array<string>}
-     *
-     * @private
-     */
-
-    const validMethods = ['DELETE', 'GET', 'HEAD', 'PATCH', 'POST', 'PUT'];
-
-    /*
+  /**
+   * The default HTTP method, 'GET', used when there's no specific method
+   * configured for a route.
+   *
+   * @type {string}
+   *
+   * @private
+   */
+
+  const defaultMethod = 'GET';
+  /**
+   * The list of valid HTTP methods associated with requests that could be routed.
+   *
+   * @type {Array<string>}
+   *
+   * @private
+   */
+
+  const validMethods = ['DELETE', 'GET', 'HEAD', 'PATCH', 'POST', 'PUT'];
+
+  /*
       Copyright 2018 Google LLC
 
       Use of this source code is governed by an MIT-style
       license that can be found in the LICENSE file or at
       https://opensource.org/licenses/MIT.
     */
-    /**
-     * @param {function()|Object} handler Either a function, or an object with a
-     * 'handle' method.
-     * @return {Object} An object with a handle method.
-     *
-     * @private
-     */
-
-    const normalizeHandler = handler => {
-      if (handler && typeof handler === 'object') {
-        {
-          finalAssertExports.hasMethod(handler, 'handle', {
-            moduleName: 'workbox-routing',
-            className: 'Route',
-            funcName: 'constructor',
-            paramName: 'handler'
-          });
-        }
-
-        return handler;
-      } else {
-        {
-          finalAssertExports.isType(handler, 'function', {
-            moduleName: 'workbox-routing',
-            className: 'Route',
-            funcName: 'constructor',
-            paramName: 'handler'
-          });
-        }
+  /**
+   * @param {function()|Object} handler Either a function, or an object with a
+   * 'handle' method.
+   * @return {Object} An object with a handle method.
+   *
+   * @private
+   */
+
+  const normalizeHandler = handler => {
+    if (handler && typeof handler === 'object') {
+      {
+        finalAssertExports.hasMethod(handler, 'handle', {
+          moduleName: 'workbox-routing',
+          className: 'Route',
+          funcName: 'constructor',
+          paramName: 'handler',
+        });
+      }
 
-        return {
-          handle: handler
-        };
+      return handler;
+    } else {
+      {
+        finalAssertExports.isType(handler, 'function', {
+          moduleName: 'workbox-routing',
+          className: 'Route',
+          funcName: 'constructor',
+          paramName: 'handler',
+        });
       }
-    };
 
-    /*
+      return {
+        handle: handler,
+      };
+    }
+  };
+
+  /*
       Copyright 2018 Google LLC
 
       Use of this source code is governed by an MIT-style
       license that can be found in the LICENSE file or at
       https://opensource.org/licenses/MIT.
     */
+  /**
+   * A `Route` consists of a pair of callback functions, "match" and "handler".
+   * The "match" callback determine if a route should be used to "handle" a
+   * request by returning a non-falsy value if it can. The "handler" callback
+   * is called when there is a match and should return a Promise that resolves
+   * to a `Response`.
+   *
+   * @memberof module:workbox-routing
+   */
+
+  class Route {
     /**
-     * A `Route` consists of a pair of callback functions, "match" and "handler".
-     * The "match" callback determine if a route should be used to "handle" a
-     * request by returning a non-falsy value if it can. The "handler" callback
-     * is called when there is a match and should return a Promise that resolves
-     * to a `Response`.
+     * Constructor for Route class.
      *
-     * @memberof module:workbox-routing
+     * @param {module:workbox-routing~matchCallback} match
+     * A callback function that determines whether the route matches a given
+     * `fetch` event by returning a non-falsy value.
+     * @param {module:workbox-routing~handlerCallback} handler A callback
+     * function that returns a Promise resolving to a Response.
+     * @param {string} [method='GET'] The HTTP method to match the Route
+     * against.
      */
+    constructor(match, handler, method = defaultMethod) {
+      {
+        finalAssertExports.isType(match, 'function', {
+          moduleName: 'workbox-routing',
+          className: 'Route',
+          funcName: 'constructor',
+          paramName: 'match',
+        });
 
-    class Route {
-      /**
-       * Constructor for Route class.
-       *
-       * @param {module:workbox-routing~matchCallback} match
-       * A callback function that determines whether the route matches a given
-       * `fetch` event by returning a non-falsy value.
-       * @param {module:workbox-routing~handlerCallback} handler A callback
-       * function that returns a Promise resolving to a Response.
-       * @param {string} [method='GET'] The HTTP method to match the Route
-       * against.
-       */
-      constructor(match, handler, method = defaultMethod) {
-        {
-          finalAssertExports.isType(match, 'function', {
-            moduleName: 'workbox-routing',
-            className: 'Route',
-            funcName: 'constructor',
-            paramName: 'match'
+        if (method) {
+          finalAssertExports.isOneOf(method, validMethods, {
+            paramName: 'method',
           });
+        }
+      } // These values are referenced directly by Router so cannot be
+      // altered by minificaton.
 
-          if (method) {
-            finalAssertExports.isOneOf(method, validMethods, {
-              paramName: 'method'
-            });
-          }
-        } // These values are referenced directly by Router so cannot be
-        // altered by minificaton.
-
-
-        this.handler = normalizeHandler(handler);
-        this.match = match;
-        this.method = method;
-      }
-
+      this.handler = normalizeHandler(handler);
+      this.match = match;
+      this.method = method;
     }
+  }
 
-    /*
+  /*
       Copyright 2018 Google LLC
 
       Use of this source code is governed by an MIT-style
       license that can be found in the LICENSE file or at
       https://opensource.org/licenses/MIT.
     */
+  /**
+   * RegExpRoute makes it easy to create a regular expression based
+   * [Route]{@link module:workbox-routing.Route}.
+   *
+   * For same-origin requests the RegExp only needs to match part of the URL. For
+   * requests against third-party servers, you must define a RegExp that matches
+   * the start of the URL.
+   *
+   * [See the module docs for info.]{@link https://developers.google.com/web/tools/workbox/modules/workbox-routing}
+   *
+   * @memberof module:workbox-routing
+   * @extends module:workbox-routing.Route
+   */
+
+  class RegExpRoute extends Route {
     /**
-     * RegExpRoute makes it easy to create a regular expression based
-     * [Route]{@link module:workbox-routing.Route}.
-     *
-     * For same-origin requests the RegExp only needs to match part of the URL. For
-     * requests against third-party servers, you must define a RegExp that matches
-     * the start of the URL.
-     *
-     * [See the module docs for info.]{@link https://developers.google.com/web/tools/workbox/modules/workbox-routing}
-     *
-     * @memberof module:workbox-routing
-     * @extends module:workbox-routing.Route
+     * If the regular expression contains
+     * [capture groups]{@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp#grouping-back-references},
+     * the captured values will be passed to the
+     * [handler's]{@link module:workbox-routing~handlerCallback} `params`
+     * argument.
+     *
+     * @param {RegExp} regExp The regular expression to match against URLs.
+     * @param {module:workbox-routing~handlerCallback} handler A callback
+     * function that returns a Promise resulting in a Response.
+     * @param {string} [method='GET'] The HTTP method to match the Route
+     * against.
      */
+    constructor(regExp, handler, method) {
+      {
+        finalAssertExports.isInstance(regExp, RegExp, {
+          moduleName: 'workbox-routing',
+          className: 'RegExpRoute',
+          funcName: 'constructor',
+          paramName: 'pattern',
+        });
+      }
 
-    class RegExpRoute extends Route {
-      /**
-       * If the regular expression contains
-       * [capture groups]{@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp#grouping-back-references},
-       * the captured values will be passed to the
-       * [handler's]{@link module:workbox-routing~handlerCallback} `params`
-       * argument.
-       *
-       * @param {RegExp} regExp The regular expression to match against URLs.
-       * @param {module:workbox-routing~handlerCallback} handler A callback
-       * function that returns a Promise resulting in a Response.
-       * @param {string} [method='GET'] The HTTP method to match the Route
-       * against.
-       */
-      constructor(regExp, handler, method) {
-        {
-          finalAssertExports.isInstance(regExp, RegExp, {
-            moduleName: 'workbox-routing',
-            className: 'RegExpRoute',
-            funcName: 'constructor',
-            paramName: 'pattern'
-          });
-        }
-
-        const match = ({
-          url
-        }) => {
-          const result = regExp.exec(url.href); // Return immediately if there's no match.
-
-          if (!result) {
-            return;
-          } // Require that the match start at the first character in the URL string
-          // if it's a cross-origin request.
-          // See https://github.com/GoogleChrome/workbox/issues/281 for the context
-          // behind this behavior.
-
-
-          if (url.origin !== location.origin && result.index !== 0) {
-            {
-              logger.debug(`The regular expression '${regExp}' only partially matched ` + `against the cross-origin URL '${url}'. RegExpRoute's will only ` + `handle cross-origin requests if they match the entire URL.`);
-            }
+      const match = ({ url }) => {
+        const result = regExp.exec(url.href); // Return immediately if there's no match.
 
-            return;
-          } // If the route matches, but there aren't any capture groups defined, then
-          // this will return [], which is truthy and therefore sufficient to
-          // indicate a match.
-          // If there are capture groups, then it will return their values.
+        if (!result) {
+          return;
+        } // Require that the match start at the first character in the URL string
+        // if it's a cross-origin request.
+        // See https://github.com/GoogleChrome/workbox/issues/281 for the context
+        // behind this behavior.
 
+        if (url.origin !== location.origin && result.index !== 0) {
+          {
+            logger.debug(
+              `The regular expression '${regExp}' only partially matched ` +
+                `against the cross-origin URL '${url}'. RegExpRoute's will only ` +
+                `handle cross-origin requests if they match the entire URL.`
+            );
+          }
 
-          return result.slice(1);
-        };
+          return;
+        } // If the route matches, but there aren't any capture groups defined, then
+        // this will return [], which is truthy and therefore sufficient to
+        // indicate a match.
+        // If there are capture groups, then it will return their values.
 
-        super(match, handler, method);
-      }
+        return result.slice(1);
+      };
 
+      super(match, handler, method);
     }
+  }
 
-    /*
+  /*
       Copyright 2018 Google LLC
 
       Use of this source code is governed by an MIT-style
@@ -684,949 +675,930 @@ define("./workbox-e536220e.js",['exports'], function (exports) { 'use strict';
       https://opensource.org/licenses/MIT.
     */
 
-    const getFriendlyURL = url => {
-      const urlObj = new URL(String(url), location.href); // See https://github.com/GoogleChrome/workbox/issues/2323
-      // We want to include everything, except for the origin if it's same-origin.
+  const getFriendlyURL = url => {
+    const urlObj = new URL(String(url), location.href); // See https://github.com/GoogleChrome/workbox/issues/2323
+    // We want to include everything, except for the origin if it's same-origin.
 
-      return urlObj.href.replace(new RegExp(`^${location.origin}`), '');
-    };
+    return urlObj.href.replace(new RegExp(`^${location.origin}`), '');
+  };
 
-    /*
+  /*
       Copyright 2018 Google LLC
 
       Use of this source code is governed by an MIT-style
       license that can be found in the LICENSE file or at
       https://opensource.org/licenses/MIT.
     */
+  /**
+   * The Router can be used to process a FetchEvent through one or more
+   * [Routes]{@link module:workbox-routing.Route} responding  with a Request if
+   * a matching route exists.
+   *
+   * If no route matches a given a request, the Router will use a "default"
+   * handler if one is defined.
+   *
+   * Should the matching Route throw an error, the Router will use a "catch"
+   * handler if one is defined to gracefully deal with issues and respond with a
+   * Request.
+   *
+   * If a request matches multiple routes, the **earliest** registered route will
+   * be used to respond to the request.
+   *
+   * @memberof module:workbox-routing
+   */
+
+  class Router {
     /**
-     * The Router can be used to process a FetchEvent through one or more
-     * [Routes]{@link module:workbox-routing.Route} responding  with a Request if
-     * a matching route exists.
-     *
-     * If no route matches a given a request, the Router will use a "default"
-     * handler if one is defined.
-     *
-     * Should the matching Route throw an error, the Router will use a "catch"
-     * handler if one is defined to gracefully deal with issues and respond with a
-     * Request.
-     *
-     * If a request matches multiple routes, the **earliest** registered route will
-     * be used to respond to the request.
-     *
-     * @memberof module:workbox-routing
+     * Initializes a new Router.
+     */
+    constructor() {
+      this._routes = new Map();
+    }
+    /**
+     * @return {Map<string, Array<module:workbox-routing.Route>>} routes A `Map` of HTTP
+     * method name ('GET', etc.) to an array of all the corresponding `Route`
+     * instances that are registered.
      */
 
-    class Router {
-      /**
-       * Initializes a new Router.
-       */
-      constructor() {
-        this._routes = new Map();
-      }
-      /**
-       * @return {Map<string, Array<module:workbox-routing.Route>>} routes A `Map` of HTTP
-       * method name ('GET', etc.) to an array of all the corresponding `Route`
-       * instances that are registered.
-       */
-
+    get routes() {
+      return this._routes;
+    }
+    /**
+     * Adds a fetch event listener to respond to events when a route matches
+     * the event's request.
+     */
 
-      get routes() {
-        return this._routes;
-      }
-      /**
-       * Adds a fetch event listener to respond to events when a route matches
-       * the event's request.
-       */
+    addFetchListener() {
+      // See https://github.com/Microsoft/TypeScript/issues/28357#issuecomment-436484705
+      self.addEventListener('fetch', event => {
+        const { request } = event;
+        const responsePromise = this.handleRequest({
+          request,
+          event,
+        });
 
+        if (responsePromise) {
+          event.respondWith(responsePromise);
+        }
+      });
+    }
+    /**
+     * Adds a message event listener for URLs to cache from the window.
+     * This is useful to cache resources loaded on the page prior to when the
+     * service worker started controlling it.
+     *
+     * The format of the message data sent from the window should be as follows.
+     * Where the `urlsToCache` array may consist of URL strings or an array of
+     * URL string + `requestInit` object (the same as you'd pass to `fetch()`).
+     *
+     * ```
+     * {
+     *   type: 'CACHE_URLS',
+     *   payload: {
+     *     urlsToCache: [
+     *       './script1.js',
+     *       './script2.js',
+     *       ['./script3.js', {mode: 'no-cors'}],
+     *     ],
+     *   },
+     * }
+     * ```
+     */
 
-      addFetchListener() {
-        // See https://github.com/Microsoft/TypeScript/issues/28357#issuecomment-436484705
-        self.addEventListener('fetch', event => {
-          const {
-            request
-          } = event;
-          const responsePromise = this.handleRequest({
-            request,
-            event
-          });
+    addCacheListener() {
+      // See https://github.com/Microsoft/TypeScript/issues/28357#issuecomment-436484705
+      self.addEventListener('message', event => {
+        if (event.data && event.data.type === 'CACHE_URLS') {
+          const { payload } = event.data;
 
-          if (responsePromise) {
-            event.respondWith(responsePromise);
+          {
+            logger.debug(`Caching URLs from the window`, payload.urlsToCache);
           }
-        });
-      }
-      /**
-       * Adds a message event listener for URLs to cache from the window.
-       * This is useful to cache resources loaded on the page prior to when the
-       * service worker started controlling it.
-       *
-       * The format of the message data sent from the window should be as follows.
-       * Where the `urlsToCache` array may consist of URL strings or an array of
-       * URL string + `requestInit` object (the same as you'd pass to `fetch()`).
-       *
-       * ```
-       * {
-       *   type: 'CACHE_URLS',
-       *   payload: {
-       *     urlsToCache: [
-       *       './script1.js',
-       *       './script2.js',
-       *       ['./script3.js', {mode: 'no-cors'}],
-       *     ],
-       *   },
-       * }
-       * ```
-       */
-
-
-      addCacheListener() {
-        // See https://github.com/Microsoft/TypeScript/issues/28357#issuecomment-436484705
-        self.addEventListener('message', event => {
-          if (event.data && event.data.type === 'CACHE_URLS') {
-            const {
-              payload
-            } = event.data;
-
-            {
-              logger.debug(`Caching URLs from the window`, payload.urlsToCache);
-            }
 
-            const requestPromises = Promise.all(payload.urlsToCache.map(entry => {
+          const requestPromises = Promise.all(
+            payload.urlsToCache.map(entry => {
               if (typeof entry === 'string') {
                 entry = [entry];
               }
 
               const request = new Request(...entry);
               return this.handleRequest({
-                request
+                request,
               }); // TODO(philipwalton): TypeScript errors without this typecast for
               // some reason (probably a bug). The real type here should work but
               // doesn't: `Array<Promise<Response> | undefined>`.
-            })); // TypeScript
+            })
+          ); // TypeScript
 
-            event.waitUntil(requestPromises); // If a MessageChannel was used, reply to the message on success.
+          event.waitUntil(requestPromises); // If a MessageChannel was used, reply to the message on success.
 
-            if (event.ports && event.ports[0]) {
-              requestPromises.then(() => event.ports[0].postMessage(true));
-            }
+          if (event.ports && event.ports[0]) {
+            requestPromises.then(() => event.ports[0].postMessage(true));
           }
+        }
+      });
+    }
+    /**
+     * Apply the routing rules to a FetchEvent object to get a Response from an
+     * appropriate Route's handler.
+     *
+     * @param {Object} options
+     * @param {Request} options.request The request to handle (this is usually
+     *     from a fetch event, but it does not have to be).
+     * @param {FetchEvent} [options.event] The event that triggered the request,
+     *     if applicable.
+     * @return {Promise<Response>|undefined} A promise is returned if a
+     *     registered route can handle the request. If there is no matching
+     *     route and there's no `defaultHandler`, `undefined` is returned.
+     */
+
+    handleRequest({ request, event }) {
+      {
+        finalAssertExports.isInstance(request, Request, {
+          moduleName: 'workbox-routing',
+          className: 'Router',
+          funcName: 'handleRequest',
+          paramName: 'options.request',
         });
       }
-      /**
-       * Apply the routing rules to a FetchEvent object to get a Response from an
-       * appropriate Route's handler.
-       *
-       * @param {Object} options
-       * @param {Request} options.request The request to handle (this is usually
-       *     from a fetch event, but it does not have to be).
-       * @param {FetchEvent} [options.event] The event that triggered the request,
-       *     if applicable.
-       * @return {Promise<Response>|undefined} A promise is returned if a
-       *     registered route can handle the request. If there is no matching
-       *     route and there's no `defaultHandler`, `undefined` is returned.
-       */
-
-
-      handleRequest({
-        request,
-        event
-      }) {
+
+      const url = new URL(request.url, location.href);
+
+      if (!url.protocol.startsWith('http')) {
         {
-          finalAssertExports.isInstance(request, Request, {
-            moduleName: 'workbox-routing',
-            className: 'Router',
-            funcName: 'handleRequest',
-            paramName: 'options.request'
-          });
-        }
-
-        const url = new URL(request.url, location.href);
-
-        if (!url.protocol.startsWith('http')) {
-          {
-            logger.debug(`Workbox Router only supports URLs that start with 'http'.`);
-          }
-
-          return;
+          logger.debug(`Workbox Router only supports URLs that start with 'http'.`);
         }
 
-        const {
-          params,
-          route
-        } = this.findMatchingRoute({
-          url,
-          request,
-          event
-        });
-        let handler = route && route.handler;
-        const debugMessages = [];
-
-        {
-          if (handler) {
-            debugMessages.push([`Found a route to handle this request:`, route]);
+        return;
+      }
 
-            if (params) {
-              debugMessages.push([`Passing the following params to the route's handler:`, params]);
-            }
-          }
-        } // If we don't have a handler because there was no matching route, then
-        // fall back to defaultHandler if that's defined.
+      const { params, route } = this.findMatchingRoute({
+        url,
+        request,
+        event,
+      });
+      let handler = route && route.handler;
+      const debugMessages = [];
 
+      {
+        if (handler) {
+          debugMessages.push([`Found a route to handle this request:`, route]);
 
-        if (!handler && this._defaultHandler) {
-          {
-            debugMessages.push(`Failed to find a matching route. Falling ` + `back to the default handler.`);
+          if (params) {
+            debugMessages.push([`Passing the following params to the route's handler:`, params]);
           }
-
-          handler = this._defaultHandler;
-        }
-
-        if (!handler) {
-          {
-            // No handler so Workbox will do nothing. If logs is set of debug
-            // i.e. verbose, we should print out this information.
-            logger.debug(`No route found for: ${getFriendlyURL(url)}`);
-          }
-
-          return;
         }
+      } // If we don't have a handler because there was no matching route, then
+      // fall back to defaultHandler if that's defined.
 
+      if (!handler && this._defaultHandler) {
         {
-          // We have a handler, meaning Workbox is going to handle the route.
-          // print the routing details to the console.
-          logger.groupCollapsed(`Router is responding to: ${getFriendlyURL(url)}`);
-          debugMessages.forEach(msg => {
-            if (Array.isArray(msg)) {
-              logger.log(...msg);
-            } else {
-              logger.log(msg);
-            }
-          });
-          logger.groupEnd();
-        } // Wrap in try and catch in case the handle method throws a synchronous
-        // error. It should still callback to the catch handler.
-
-
-        let responsePromise;
-
-        try {
-          responsePromise = handler.handle({
-            url,
-            request,
-            event,
-            params
-          });
-        } catch (err) {
-          responsePromise = Promise.reject(err);
+          debugMessages.push(`Failed to find a matching route. Falling ` + `back to the default handler.`);
         }
 
-        if (responsePromise instanceof Promise && this._catchHandler) {
-          responsePromise = responsePromise.catch(err => {
-            {
-              // Still include URL here as it will be async from the console group
-              // and may not make sense without the URL
-              logger.groupCollapsed(`Error thrown when responding to: ` + ` ${getFriendlyURL(url)}. Falling back to Catch Handler.`);
-              logger.error(`Error thrown by:`, route);
-              logger.error(err);
-              logger.groupEnd();
-            }
-
-            return this._catchHandler.handle({
-              url,
-              request,
-              event
-            });
-          });
-        }
-
-        return responsePromise;
+        handler = this._defaultHandler;
       }
-      /**
-       * Checks a request and URL (and optionally an event) against the list of
-       * registered routes, and if there's a match, returns the corresponding
-       * route along with any params generated by the match.
-       *
-       * @param {Object} options
-       * @param {URL} options.url
-       * @param {Request} options.request The request to match.
-       * @param {Event} [options.event] The corresponding event (unless N/A).
-       * @return {Object} An object with `route` and `params` properties.
-       *     They are populated if a matching route was found or `undefined`
-       *     otherwise.
-       */
 
-
-      findMatchingRoute({
-        url,
-        request,
-        event
-      }) {
+      if (!handler) {
         {
-          finalAssertExports.isInstance(url, URL, {
-            moduleName: 'workbox-routing',
-            className: 'Router',
-            funcName: 'findMatchingRoute',
-            paramName: 'options.url'
-          });
-          finalAssertExports.isInstance(request, Request, {
-            moduleName: 'workbox-routing',
-            className: 'Router',
-            funcName: 'findMatchingRoute',
-            paramName: 'options.request'
-          });
+          // No handler so Workbox will do nothing. If logs is set of debug
+          // i.e. verbose, we should print out this information.
+          logger.debug(`No route found for: ${getFriendlyURL(url)}`);
         }
 
-        const routes = this._routes.get(request.method) || [];
-
-        for (const route of routes) {
-          let params;
-          const matchResult = route.match({
-            url,
-            request,
-            event
-          });
+        return;
+      }
 
-          if (matchResult) {
-            // See https://github.com/GoogleChrome/workbox/issues/2079
-            params = matchResult;
-
-            if (Array.isArray(matchResult) && matchResult.length === 0) {
-              // Instead of passing an empty array in as params, use undefined.
-              params = undefined;
-            } else if (matchResult.constructor === Object && Object.keys(matchResult).length === 0) {
-              // Instead of passing an empty object in as params, use undefined.
-              params = undefined;
-            } else if (typeof matchResult === 'boolean') {
-              // For the boolean value true (rather than just something truth-y),
-              // don't set params.
-              // See https://github.com/GoogleChrome/workbox/pull/2134#issuecomment-513924353
-              params = undefined;
-            } // Return early if have a match.
-
-
-            return {
-              route,
-              params
-            };
+      {
+        // We have a handler, meaning Workbox is going to handle the route.
+        // print the routing details to the console.
+        logger.groupCollapsed(`Router is responding to: ${getFriendlyURL(url)}`);
+        debugMessages.forEach(msg => {
+          if (Array.isArray(msg)) {
+            logger.log(...msg);
+          } else {
+            logger.log(msg);
           }
-        } // If no match was found above, return and empty object.
+        });
+        logger.groupEnd();
+      } // Wrap in try and catch in case the handle method throws a synchronous
+      // error. It should still callback to the catch handler.
 
+      let responsePromise;
 
-        return {};
+      try {
+        responsePromise = handler.handle({
+          url,
+          request,
+          event,
+          params,
+        });
+      } catch (err) {
+        responsePromise = Promise.reject(err);
       }
-      /**
-       * Define a default `handler` that's called when no routes explicitly
-       * match the incoming request.
-       *
-       * Without a default handler, unmatched requests will go against the
-       * network as if there were no service worker present.
-       *
-       * @param {module:workbox-routing~handlerCallback} handler A callback
-       * function that returns a Promise resulting in a Response.
-       */
 
+      if (responsePromise instanceof Promise && this._catchHandler) {
+        responsePromise = responsePromise.catch(err => {
+          {
+            // Still include URL here as it will be async from the console group
+            // and may not make sense without the URL
+            logger.groupCollapsed(
+              `Error thrown when responding to: ` + ` ${getFriendlyURL(url)}. Falling back to Catch Handler.`
+            );
+            logger.error(`Error thrown by:`, route);
+            logger.error(err);
+            logger.groupEnd();
+          }
 
-      setDefaultHandler(handler) {
-        this._defaultHandler = normalizeHandler(handler);
+          return this._catchHandler.handle({
+            url,
+            request,
+            event,
+          });
+        });
       }
-      /**
-       * If a Route throws an error while handling a request, this `handler`
-       * will be called and given a chance to provide a response.
-       *
-       * @param {module:workbox-routing~handlerCallback} handler A callback
-       * function that returns a Promise resulting in a Response.
-       */
 
+      return responsePromise;
+    }
+    /**
+     * Checks a request and URL (and optionally an event) against the list of
+     * registered routes, and if there's a match, returns the corresponding
+     * route along with any params generated by the match.
+     *
+     * @param {Object} options
+     * @param {URL} options.url
+     * @param {Request} options.request The request to match.
+     * @param {Event} [options.event] The corresponding event (unless N/A).
+     * @return {Object} An object with `route` and `params` properties.
+     *     They are populated if a matching route was found or `undefined`
+     *     otherwise.
+     */
 
-      setCatchHandler(handler) {
-        this._catchHandler = normalizeHandler(handler);
+    findMatchingRoute({ url, request, event }) {
+      {
+        finalAssertExports.isInstance(url, URL, {
+          moduleName: 'workbox-routing',
+          className: 'Router',
+          funcName: 'findMatchingRoute',
+          paramName: 'options.url',
+        });
+        finalAssertExports.isInstance(request, Request, {
+          moduleName: 'workbox-routing',
+          className: 'Router',
+          funcName: 'findMatchingRoute',
+          paramName: 'options.request',
+        });
       }
-      /**
-       * Registers a route with the router.
-       *
-       * @param {module:workbox-routing.Route} route The route to register.
-       */
 
+      const routes = this._routes.get(request.method) || [];
 
-      registerRoute(route) {
-        {
-          finalAssertExports.isType(route, 'object', {
-            moduleName: 'workbox-routing',
-            className: 'Router',
-            funcName: 'registerRoute',
-            paramName: 'route'
-          });
-          finalAssertExports.hasMethod(route, 'match', {
-            moduleName: 'workbox-routing',
-            className: 'Router',
-            funcName: 'registerRoute',
-            paramName: 'route'
-          });
-          finalAssertExports.isType(route.handler, 'object', {
-            moduleName: 'workbox-routing',
-            className: 'Router',
-            funcName: 'registerRoute',
-            paramName: 'route'
-          });
-          finalAssertExports.hasMethod(route.handler, 'handle', {
-            moduleName: 'workbox-routing',
-            className: 'Router',
-            funcName: 'registerRoute',
-            paramName: 'route.handler'
-          });
-          finalAssertExports.isType(route.method, 'string', {
-            moduleName: 'workbox-routing',
-            className: 'Router',
-            funcName: 'registerRoute',
-            paramName: 'route.method'
-          });
-        }
+      for (const route of routes) {
+        let params;
+        const matchResult = route.match({
+          url,
+          request,
+          event,
+        });
 
-        if (!this._routes.has(route.method)) {
-          this._routes.set(route.method, []);
-        } // Give precedence to all of the earlier routes by adding this additional
-        // route to the end of the array.
+        if (matchResult) {
+          // See https://github.com/GoogleChrome/workbox/issues/2079
+          params = matchResult;
+
+          if (Array.isArray(matchResult) && matchResult.length === 0) {
+            // Instead of passing an empty array in as params, use undefined.
+            params = undefined;
+          } else if (matchResult.constructor === Object && Object.keys(matchResult).length === 0) {
+            // Instead of passing an empty object in as params, use undefined.
+            params = undefined;
+          } else if (typeof matchResult === 'boolean') {
+            // For the boolean value true (rather than just something truth-y),
+            // don't set params.
+            // See https://github.com/GoogleChrome/workbox/pull/2134#issuecomment-513924353
+            params = undefined;
+          } // Return early if have a match.
+
+          return {
+            route,
+            params,
+          };
+        }
+      } // If no match was found above, return and empty object.
+
+      return {};
+    }
+    /**
+     * Define a default `handler` that's called when no routes explicitly
+     * match the incoming request.
+     *
+     * Without a default handler, unmatched requests will go against the
+     * network as if there were no service worker present.
+     *
+     * @param {module:workbox-routing~handlerCallback} handler A callback
+     * function that returns a Promise resulting in a Response.
+     */
 
+    setDefaultHandler(handler) {
+      this._defaultHandler = normalizeHandler(handler);
+    }
+    /**
+     * If a Route throws an error while handling a request, this `handler`
+     * will be called and given a chance to provide a response.
+     *
+     * @param {module:workbox-routing~handlerCallback} handler A callback
+     * function that returns a Promise resulting in a Response.
+     */
 
-        this._routes.get(route.method).push(route);
-      }
-      /**
-       * Unregisters a route with the router.
-       *
-       * @param {module:workbox-routing.Route} route The route to unregister.
-       */
+    setCatchHandler(handler) {
+      this._catchHandler = normalizeHandler(handler);
+    }
+    /**
+     * Registers a route with the router.
+     *
+     * @param {module:workbox-routing.Route} route The route to register.
+     */
 
+    registerRoute(route) {
+      {
+        finalAssertExports.isType(route, 'object', {
+          moduleName: 'workbox-routing',
+          className: 'Router',
+          funcName: 'registerRoute',
+          paramName: 'route',
+        });
+        finalAssertExports.hasMethod(route, 'match', {
+          moduleName: 'workbox-routing',
+          className: 'Router',
+          funcName: 'registerRoute',
+          paramName: 'route',
+        });
+        finalAssertExports.isType(route.handler, 'object', {
+          moduleName: 'workbox-routing',
+          className: 'Router',
+          funcName: 'registerRoute',
+          paramName: 'route',
+        });
+        finalAssertExports.hasMethod(route.handler, 'handle', {
+          moduleName: 'workbox-routing',
+          className: 'Router',
+          funcName: 'registerRoute',
+          paramName: 'route.handler',
+        });
+        finalAssertExports.isType(route.method, 'string', {
+          moduleName: 'workbox-routing',
+          className: 'Router',
+          funcName: 'registerRoute',
+          paramName: 'route.method',
+        });
+      }
 
-      unregisterRoute(route) {
-        if (!this._routes.has(route.method)) {
-          throw new WorkboxError('unregister-route-but-not-found-with-method', {
-            method: route.method
-          });
-        }
+      if (!this._routes.has(route.method)) {
+        this._routes.set(route.method, []);
+      } // Give precedence to all of the earlier routes by adding this additional
+      // route to the end of the array.
 
-        const routeIndex = this._routes.get(route.method).indexOf(route);
+      this._routes.get(route.method).push(route);
+    }
+    /**
+     * Unregisters a route with the router.
+     *
+     * @param {module:workbox-routing.Route} route The route to unregister.
+     */
 
-        if (routeIndex > -1) {
-          this._routes.get(route.method).splice(routeIndex, 1);
-        } else {
-          throw new WorkboxError('unregister-route-route-not-registered');
-        }
+    unregisterRoute(route) {
+      if (!this._routes.has(route.method)) {
+        throw new WorkboxError('unregister-route-but-not-found-with-method', {
+          method: route.method,
+        });
       }
 
+      const routeIndex = this._routes.get(route.method).indexOf(route);
+
+      if (routeIndex > -1) {
+        this._routes.get(route.method).splice(routeIndex, 1);
+      } else {
+        throw new WorkboxError('unregister-route-route-not-registered');
+      }
     }
+  }
 
-    /*
+  /*
       Copyright 2019 Google LLC
 
       Use of this source code is governed by an MIT-style
       license that can be found in the LICENSE file or at
       https://opensource.org/licenses/MIT.
     */
-    let defaultRouter;
-    /**
-     * Creates a new, singleton Router instance if one does not exist. If one
-     * does already exist, that instance is returned.
-     *
-     * @private
-     * @return {Router}
-     */
-
-    const getOrCreateDefaultRouter = () => {
-      if (!defaultRouter) {
-        defaultRouter = new Router(); // The helpers that use the default Router assume these listeners exist.
-
-        defaultRouter.addFetchListener();
-        defaultRouter.addCacheListener();
-      }
+  let defaultRouter;
+  /**
+   * Creates a new, singleton Router instance if one does not exist. If one
+   * does already exist, that instance is returned.
+   *
+   * @private
+   * @return {Router}
+   */
+
+  const getOrCreateDefaultRouter = () => {
+    if (!defaultRouter) {
+      defaultRouter = new Router(); // The helpers that use the default Router assume these listeners exist.
+
+      defaultRouter.addFetchListener();
+      defaultRouter.addCacheListener();
+    }
 
-      return defaultRouter;
-    };
+    return defaultRouter;
+  };
 
-    /*
+  /*
       Copyright 2019 Google LLC
 
       Use of this source code is governed by an MIT-style
       license that can be found in the LICENSE file or at
       https://opensource.org/licenses/MIT.
     */
-    /**
-     * Easily register a RegExp, string, or function with a caching
-     * strategy to a singleton Router instance.
-     *
-     * This method will generate a Route for you if needed and
-     * call [registerRoute()]{@link module:workbox-routing.Router#registerRoute}.
-     *
-     * @param {RegExp|string|module:workbox-routing.Route~matchCallback|module:workbox-routing.Route} capture
-     * If the capture param is a `Route`, all other arguments will be ignored.
-     * @param {module:workbox-routing~handlerCallback} [handler] A callback
-     * function that returns a Promise resulting in a Response. This parameter
-     * is required if `capture` is not a `Route` object.
-     * @param {string} [method='GET'] The HTTP method to match the Route
-     * against.
-     * @return {module:workbox-routing.Route} The generated `Route`(Useful for
-     * unregistering).
-     *
-     * @memberof module:workbox-routing
-     */
-
-    function registerRoute(capture, handler, method) {
-      let route;
-
-      if (typeof capture === 'string') {
-        const captureUrl = new URL(capture, location.href);
-
-        {
-          if (!(capture.startsWith('/') || capture.startsWith('http'))) {
-            throw new WorkboxError('invalid-string', {
-              moduleName: 'workbox-routing',
-              funcName: 'registerRoute',
-              paramName: 'capture'
-            });
-          } // We want to check if Express-style wildcards are in the pathname only.
-          // TODO: Remove this log message in v4.
+  /**
+   * Easily register a RegExp, string, or function with a caching
+   * strategy to a singleton Router instance.
+   *
+   * This method will generate a Route for you if needed and
+   * call [registerRoute()]{@link module:workbox-routing.Router#registerRoute}.
+   *
+   * @param {RegExp|string|module:workbox-routing.Route~matchCallback|module:workbox-routing.Route} capture
+   * If the capture param is a `Route`, all other arguments will be ignored.
+   * @param {module:workbox-routing~handlerCallback} [handler] A callback
+   * function that returns a Promise resulting in a Response. This parameter
+   * is required if `capture` is not a `Route` object.
+   * @param {string} [method='GET'] The HTTP method to match the Route
+   * against.
+   * @return {module:workbox-routing.Route} The generated `Route`(Useful for
+   * unregistering).
+   *
+   * @memberof module:workbox-routing
+   */
+
+  function registerRoute(capture, handler, method) {
+    let route;
+
+    if (typeof capture === 'string') {
+      const captureUrl = new URL(capture, location.href);
 
+      {
+        if (!(capture.startsWith('/') || capture.startsWith('http'))) {
+          throw new WorkboxError('invalid-string', {
+            moduleName: 'workbox-routing',
+            funcName: 'registerRoute',
+            paramName: 'capture',
+          });
+        } // We want to check if Express-style wildcards are in the pathname only.
+        // TODO: Remove this log message in v4.
 
-          const valueToCheck = capture.startsWith('http') ? captureUrl.pathname : capture; // See https://github.com/pillarjs/path-to-regexp#parameters
+        const valueToCheck = capture.startsWith('http') ? captureUrl.pathname : capture; // See https://github.com/pillarjs/path-to-regexp#parameters
 
-          const wildcards = '[*:?+]';
+        const wildcards = '[*:?+]';
 
-          if (new RegExp(`${wildcards}`).exec(valueToCheck)) {
-            logger.debug(`The '$capture' parameter contains an Express-style wildcard ` + `character (${wildcards}). Strings are now always interpreted as ` + `exact matches; use a RegExp for partial or wildcard matches.`);
-          }
+        if (new RegExp(`${wildcards}`).exec(valueToCheck)) {
+          logger.debug(
+            `The '$capture' parameter contains an Express-style wildcard ` +
+              `character (${wildcards}). Strings are now always interpreted as ` +
+              `exact matches; use a RegExp for partial or wildcard matches.`
+          );
         }
+      }
 
-        const matchCallback = ({
-          url
-        }) => {
-          {
-            if (url.pathname === captureUrl.pathname && url.origin !== captureUrl.origin) {
-              logger.debug(`${capture} only partially matches the cross-origin URL ` + `${url}. This route will only handle cross-origin requests ` + `if they match the entire URL.`);
-            }
+      const matchCallback = ({ url }) => {
+        {
+          if (url.pathname === captureUrl.pathname && url.origin !== captureUrl.origin) {
+            logger.debug(
+              `${capture} only partially matches the cross-origin URL ` +
+                `${url}. This route will only handle cross-origin requests ` +
+                `if they match the entire URL.`
+            );
           }
+        }
 
-          return url.href === captureUrl.href;
-        }; // If `capture` is a string then `handler` and `method` must be present.
-
-
-        route = new Route(matchCallback, handler, method);
-      } else if (capture instanceof RegExp) {
-        // If `capture` is a `RegExp` then `handler` and `method` must be present.
-        route = new RegExpRoute(capture, handler, method);
-      } else if (typeof capture === 'function') {
-        // If `capture` is a function then `handler` and `method` must be present.
-        route = new Route(capture, handler, method);
-      } else if (capture instanceof Route) {
-        route = capture;
-      } else {
-        throw new WorkboxError('unsupported-route-type', {
-          moduleName: 'workbox-routing',
-          funcName: 'registerRoute',
-          paramName: 'capture'
-        });
-      }
-
-      const defaultRouter = getOrCreateDefaultRouter();
-      defaultRouter.registerRoute(route);
-      return route;
+        return url.href === captureUrl.href;
+      }; // If `capture` is a string then `handler` and `method` must be present.
+
+      route = new Route(matchCallback, handler, method);
+    } else if (capture instanceof RegExp) {
+      // If `capture` is a `RegExp` then `handler` and `method` must be present.
+      route = new RegExpRoute(capture, handler, method);
+    } else if (typeof capture === 'function') {
+      // If `capture` is a function then `handler` and `method` must be present.
+      route = new Route(capture, handler, method);
+    } else if (capture instanceof Route) {
+      route = capture;
+    } else {
+      throw new WorkboxError('unsupported-route-type', {
+        moduleName: 'workbox-routing',
+        funcName: 'registerRoute',
+        paramName: 'capture',
+      });
     }
 
-    /*
+    const defaultRouter = getOrCreateDefaultRouter();
+    defaultRouter.registerRoute(route);
+    return route;
+  }
+
+  /*
       Copyright 2018 Google LLC
 
       Use of this source code is governed by an MIT-style
       license that can be found in the LICENSE file or at
       https://opensource.org/licenses/MIT.
     */
-    const pluginUtils = {
-      filter: (plugins, callbackName) => {
-        return plugins.filter(plugin => callbackName in plugin);
-      }
-    };
+  const pluginUtils = {
+    filter: (plugins, callbackName) => {
+      return plugins.filter(plugin => callbackName in plugin);
+    },
+  };
 
-    /*
+  /*
       Copyright 2018 Google LLC
 
       Use of this source code is governed by an MIT-style
       license that can be found in the LICENSE file or at
       https://opensource.org/licenses/MIT.
     */
-    /**
-     * Wrapper around the fetch API.
-     *
-     * Will call requestWillFetch on available plugins.
-     *
-     * @param {Object} options
-     * @param {Request|string} options.request
-     * @param {Object} [options.fetchOptions]
-     * @param {ExtendableEvent} [options.event]
-     * @param {Array<Object>} [options.plugins=[]]
-     * @return {Promise<Response>}
-     *
-     * @private
-     * @memberof module:workbox-core
-     */
-
-    const wrappedFetch = async ({
-      request,
-      fetchOptions,
-      event,
-      plugins = []
-    }) => {
-      if (typeof request === 'string') {
-        request = new Request(request);
-      } // We *should* be able to call `await event.preloadResponse` even if it's
-      // undefined, but for some reason, doing so leads to errors in our Node unit
-      // tests. To work around that, explicitly check preloadResponse's value first.
-
-
-      if (event instanceof FetchEvent && event.preloadResponse) {
-        const possiblePreloadResponse = await event.preloadResponse;
-
-        if (possiblePreloadResponse) {
-          {
-            logger.log(`Using a preloaded navigation response for ` + `'${getFriendlyURL(request.url)}'`);
-          }
-
-          return possiblePreloadResponse;
+  /**
+   * Wrapper around the fetch API.
+   *
+   * Will call requestWillFetch on available plugins.
+   *
+   * @param {Object} options
+   * @param {Request|string} options.request
+   * @param {Object} [options.fetchOptions]
+   * @param {ExtendableEvent} [options.event]
+   * @param {Array<Object>} [options.plugins=[]]
+   * @return {Promise<Response>}
+   *
+   * @private
+   * @memberof module:workbox-core
+   */
+
+  const wrappedFetch = async ({ request, fetchOptions, event, plugins = [] }) => {
+    if (typeof request === 'string') {
+      request = new Request(request);
+    } // We *should* be able to call `await event.preloadResponse` even if it's
+    // undefined, but for some reason, doing so leads to errors in our Node unit
+    // tests. To work around that, explicitly check preloadResponse's value first.
+
+    if (event instanceof FetchEvent && event.preloadResponse) {
+      const possiblePreloadResponse = await event.preloadResponse;
+
+      if (possiblePreloadResponse) {
+        {
+          logger.log(`Using a preloaded navigation response for ` + `'${getFriendlyURL(request.url)}'`);
         }
-      }
 
-      {
-        finalAssertExports.isInstance(request, Request, {
-          paramName: 'request',
-          expectedClass: Request,
-          moduleName: 'workbox-core',
-          className: 'fetchWrapper',
-          funcName: 'wrappedFetch'
-        });
+        return possiblePreloadResponse;
       }
+    }
+
+    {
+      finalAssertExports.isInstance(request, Request, {
+        paramName: 'request',
+        expectedClass: Request,
+        moduleName: 'workbox-core',
+        className: 'fetchWrapper',
+        funcName: 'wrappedFetch',
+      });
+    }
 
-      const failedFetchPlugins = pluginUtils.filter(plugins, "fetchDidFail"
+    const failedFetchPlugins = pluginUtils.filter(
+      plugins,
+      'fetchDidFail'
       /* FETCH_DID_FAIL */
-      ); // If there is a fetchDidFail plugin, we need to save a clone of the
-      // original request before it's either modified by a requestWillFetch
-      // plugin or before the original request's body is consumed via fetch().
+    ); // If there is a fetchDidFail plugin, we need to save a clone of the
+    // original request before it's either modified by a requestWillFetch
+    // plugin or before the original request's body is consumed via fetch().
 
-      const originalRequest = failedFetchPlugins.length > 0 ? request.clone() : null;
+    const originalRequest = failedFetchPlugins.length > 0 ? request.clone() : null;
 
-      try {
-        for (const plugin of plugins) {
-          if ("requestWillFetch"
+    try {
+      for (const plugin of plugins) {
+        if (
+          'requestWillFetch' in
           /* REQUEST_WILL_FETCH */
-          in plugin) {
-            const pluginMethod = plugin["requestWillFetch"
-            /* REQUEST_WILL_FETCH */
+          plugin
+        ) {
+          const pluginMethod =
+            plugin[
+              'requestWillFetch'
+              /* REQUEST_WILL_FETCH */
             ];
-            const requestClone = request.clone();
-            request = await pluginMethod.call(plugin, {
-              request: requestClone,
-              event
-            });
+          const requestClone = request.clone();
+          request = await pluginMethod.call(plugin, {
+            request: requestClone,
+            event,
+          });
 
-            if ("development" !== 'production') {
-              if (request) {
-                finalAssertExports.isInstance(request, Request, {
-                  moduleName: 'Plugin',
-                  funcName: "cachedResponseWillBeUsed"
-                  /* CACHED_RESPONSE_WILL_BE_USED */
-                  ,
-                  isReturnValueProblem: true
-                });
-              }
+          if ('development' !== 'production') {
+            if (request) {
+              finalAssertExports.isInstance(request, Request, {
+                moduleName: 'Plugin',
+                funcName: 'cachedResponseWillBeUsed',
+                /* CACHED_RESPONSE_WILL_BE_USED */
+                isReturnValueProblem: true,
+              });
             }
           }
         }
-      } catch (err) {
-        throw new WorkboxError('plugin-error-request-will-fetch', {
-          thrownError: err
-        });
-      } // The request can be altered by plugins with `requestWillFetch` making
-      // the original request (Most likely from a `fetch` event) to be different
-      // to the Request we make. Pass both to `fetchDidFail` to aid debugging.
-
+      }
+    } catch (err) {
+      throw new WorkboxError('plugin-error-request-will-fetch', {
+        thrownError: err,
+      });
+    } // The request can be altered by plugins with `requestWillFetch` making
+    // the original request (Most likely from a `fetch` event) to be different
+    // to the Request we make. Pass both to `fetchDidFail` to aid debugging.
 
-      const pluginFilteredRequest = request.clone();
+    const pluginFilteredRequest = request.clone();
 
-      try {
-        let fetchResponse; // See https://github.com/GoogleChrome/workbox/issues/1796
+    try {
+      let fetchResponse; // See https://github.com/GoogleChrome/workbox/issues/1796
 
-        if (request.mode === 'navigate') {
-          fetchResponse = await fetch(request);
-        } else {
-          fetchResponse = await fetch(request, fetchOptions);
-        }
+      if (request.mode === 'navigate') {
+        fetchResponse = await fetch(request);
+      } else {
+        fetchResponse = await fetch(request, fetchOptions);
+      }
 
-        if ("development" !== 'production') {
-          logger.debug(`Network request for ` + `'${getFriendlyURL(request.url)}' returned a response with ` + `status '${fetchResponse.status}'.`);
-        }
+      if ('development' !== 'production') {
+        logger.debug(
+          `Network request for ` +
+            `'${getFriendlyURL(request.url)}' returned a response with ` +
+            `status '${fetchResponse.status}'.`
+        );
+      }
 
-        for (const plugin of plugins) {
-          if ("fetchDidSucceed"
+      for (const plugin of plugins) {
+        if (
+          'fetchDidSucceed' in
           /* FETCH_DID_SUCCEED */
-          in plugin) {
-            fetchResponse = await plugin["fetchDidSucceed"
+          plugin
+        ) {
+          fetchResponse = await plugin[
+            'fetchDidSucceed'
             /* FETCH_DID_SUCCEED */
-            ].call(plugin, {
-              event,
-              request: pluginFilteredRequest,
-              response: fetchResponse
-            });
+          ].call(plugin, {
+            event,
+            request: pluginFilteredRequest,
+            response: fetchResponse,
+          });
 
-            if ("development" !== 'production') {
-              if (fetchResponse) {
-                finalAssertExports.isInstance(fetchResponse, Response, {
-                  moduleName: 'Plugin',
-                  funcName: "fetchDidSucceed"
-                  /* FETCH_DID_SUCCEED */
-                  ,
-                  isReturnValueProblem: true
-                });
-              }
+          if ('development' !== 'production') {
+            if (fetchResponse) {
+              finalAssertExports.isInstance(fetchResponse, Response, {
+                moduleName: 'Plugin',
+                funcName: 'fetchDidSucceed',
+                /* FETCH_DID_SUCCEED */
+                isReturnValueProblem: true,
+              });
             }
           }
         }
+      }
 
-        return fetchResponse;
-      } catch (error) {
-        {
-          logger.error(`Network request for ` + `'${getFriendlyURL(request.url)}' threw an error.`, error);
-        }
+      return fetchResponse;
+    } catch (error) {
+      {
+        logger.error(`Network request for ` + `'${getFriendlyURL(request.url)}' threw an error.`, error);
+      }
 
-        for (const plugin of failedFetchPlugins) {
-          await plugin["fetchDidFail"
+      for (const plugin of failedFetchPlugins) {
+        await plugin[
+          'fetchDidFail'
           /* FETCH_DID_FAIL */
-          ].call(plugin, {
-            error,
-            event,
-            originalRequest: originalRequest.clone(),
-            request: pluginFilteredRequest.clone()
-          });
-        }
-
-        throw error;
+        ].call(plugin, {
+          error,
+          event,
+          originalRequest: originalRequest.clone(),
+          request: pluginFilteredRequest.clone(),
+        });
       }
-    };
 
-    const fetchWrapper = {
-      fetch: wrappedFetch
-    };
+      throw error;
+    }
+  };
 
-    try {
-      self['workbox:strategies:5.1.4'] && _();
-    } catch (e) {}
+  const fetchWrapper = {
+    fetch: wrappedFetch,
+  };
 
-    /*
+  try {
+    self['workbox:strategies:5.1.4'] && _();
+  } catch (e) {}
+
+  /*
       Copyright 2018 Google LLC
 
       Use of this source code is governed by an MIT-style
       license that can be found in the LICENSE file or at
       https://opensource.org/licenses/MIT.
     */
-    const messages$1 = {
-      strategyStart: (strategyName, request) => `Using ${strategyName} to respond to '${getFriendlyURL(request.url)}'`,
-      printFinalResponse: response => {
-        if (response) {
-          logger.groupCollapsed(`View the final response here.`);
-          logger.log(response || '[No response returned]');
-          logger.groupEnd();
-        }
+  const messages$1 = {
+    strategyStart: (strategyName, request) => `Using ${strategyName} to respond to '${getFriendlyURL(request.url)}'`,
+    printFinalResponse: response => {
+      if (response) {
+        logger.groupCollapsed(`View the final response here.`);
+        logger.log(response || '[No response returned]');
+        logger.groupEnd();
       }
-    };
+    },
+  };
 
-    /*
+  /*
       Copyright 2018 Google LLC
 
       Use of this source code is governed by an MIT-style
       license that can be found in the LICENSE file or at
       https://opensource.org/licenses/MIT.
     */
+  /**
+   * An implementation of a
+   * [network-only]{@link https://developers.google.com/web/fundamentals/instant-and-offline/offline-cookbook/#network-only}
+   * request strategy.
+   *
+   * This class is useful if you want to take advantage of any
+   * [Workbox plugins]{@link https://developers.google.com/web/tools/workbox/guides/using-plugins}.
+   *
+   * If the network request fails, this will throw a `WorkboxError` exception.
+   *
+   * @memberof module:workbox-strategies
+   */
+
+  class NetworkOnly {
     /**
-     * An implementation of a
-     * [network-only]{@link https://developers.google.com/web/fundamentals/instant-and-offline/offline-cookbook/#network-only}
-     * request strategy.
-     *
-     * This class is useful if you want to take advantage of any
-     * [Workbox plugins]{@link https://developers.google.com/web/tools/workbox/guides/using-plugins}.
-     *
-     * If the network request fails, this will throw a `WorkboxError` exception.
+     * @param {Object} options
+     * @param {string} options.cacheName Cache name to store and retrieve
+     * requests. Defaults to cache names provided by
+     * [workbox-core]{@link module:workbox-core.cacheNames}.
+     * @param {Array<Object>} options.plugins [Plugins]{@link https://developers.google.com/web/tools/workbox/guides/using-plugins}
+     * to use in conjunction with this caching strategy.
+     * @param {Object} options.fetchOptions Values passed along to the
+     * [`init`](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch#Parameters)
+     * of all fetch() requests made by this strategy.
+     */
+    constructor(options = {}) {
+      this._plugins = options.plugins || [];
+      this._fetchOptions = options.fetchOptions;
+    }
+    /**
+     * This method will perform a request strategy and follows an API that
+     * will work with the
+     * [Workbox Router]{@link module:workbox-routing.Router}.
      *
-     * @memberof module:workbox-strategies
+     * @param {Object} options
+     * @param {Request|string} options.request The request to run this strategy for.
+     * @param {Event} [options.event] The event that triggered the request.
+     * @return {Promise<Response>}
      */
 
-    class NetworkOnly {
-      /**
-       * @param {Object} options
-       * @param {string} options.cacheName Cache name to store and retrieve
-       * requests. Defaults to cache names provided by
-       * [workbox-core]{@link module:workbox-core.cacheNames}.
-       * @param {Array<Object>} options.plugins [Plugins]{@link https://developers.google.com/web/tools/workbox/guides/using-plugins}
-       * to use in conjunction with this caching strategy.
-       * @param {Object} options.fetchOptions Values passed along to the
-       * [`init`](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch#Parameters)
-       * of all fetch() requests made by this strategy.
-       */
-      constructor(options = {}) {
-        this._plugins = options.plugins || [];
-        this._fetchOptions = options.fetchOptions;
-      }
-      /**
-       * This method will perform a request strategy and follows an API that
-       * will work with the
-       * [Workbox Router]{@link module:workbox-routing.Router}.
-       *
-       * @param {Object} options
-       * @param {Request|string} options.request The request to run this strategy for.
-       * @param {Event} [options.event] The event that triggered the request.
-       * @return {Promise<Response>}
-       */
-
-
-      async handle({
-        event,
-        request
-      }) {
-        if (typeof request === 'string') {
-          request = new Request(request);
-        }
+    async handle({ event, request }) {
+      if (typeof request === 'string') {
+        request = new Request(request);
+      }
 
-        {
-          finalAssertExports.isInstance(request, Request, {
-            moduleName: 'workbox-strategies',
-            className: 'NetworkOnly',
-            funcName: 'handle',
-            paramName: 'request'
-          });
-        }
+      {
+        finalAssertExports.isInstance(request, Request, {
+          moduleName: 'workbox-strategies',
+          className: 'NetworkOnly',
+          funcName: 'handle',
+          paramName: 'request',
+        });
+      }
 
-        let error;
-        let response;
+      let error;
+      let response;
 
-        try {
-          response = await fetchWrapper.fetch({
-            request,
-            event,
-            fetchOptions: this._fetchOptions,
-            plugins: this._plugins
-          });
-        } catch (err) {
-          error = err;
-        }
-
-        {
-          logger.groupCollapsed(messages$1.strategyStart('NetworkOnly', request));
+      try {
+        response = await fetchWrapper.fetch({
+          request,
+          event,
+          fetchOptions: this._fetchOptions,
+          plugins: this._plugins,
+        });
+      } catch (err) {
+        error = err;
+      }
 
-          if (response) {
-            logger.log(`Got response from network.`);
-          } else {
-            logger.log(`Unable to get a response from the network.`);
-          }
+      {
+        logger.groupCollapsed(messages$1.strategyStart('NetworkOnly', request));
 
-          messages$1.printFinalResponse(response);
-          logger.groupEnd();
+        if (response) {
+          logger.log(`Got response from network.`);
+        } else {
+          logger.log(`Unable to get a response from the network.`);
         }
 
-        if (!response) {
-          throw new WorkboxError('no-response', {
-            url: request.url,
-            error
-          });
-        }
+        messages$1.printFinalResponse(response);
+        logger.groupEnd();
+      }
 
-        return response;
+      if (!response) {
+        throw new WorkboxError('no-response', {
+          url: request.url,
+          error,
+        });
       }
 
+      return response;
     }
+  }
 
-    /*
+  /*
       Copyright 2019 Google LLC
 
       Use of this source code is governed by an MIT-style
       license that can be found in the LICENSE file or at
       https://opensource.org/licenses/MIT.
     */
-    /**
-     * Force a service worker to activate immediately, instead of
-     * [waiting](https://developers.google.com/web/fundamentals/primers/service-workers/lifecycle#waiting)
-     * for existing clients to close.
-     *
-     * @memberof module:workbox-core
-     */
-
-    function skipWaiting() {
-      // We need to explicitly call `self.skipWaiting()` here because we're
-      // shadowing `skipWaiting` with this local function.
-      self.addEventListener('install', () => self.skipWaiting());
-    }
-
-    /*
+  /**
+   * Force a service worker to activate immediately, instead of
+   * [waiting](https://developers.google.com/web/fundamentals/primers/service-workers/lifecycle#waiting)
+   * for existing clients to close.
+   *
+   * @memberof module:workbox-core
+   */
+
+  function skipWaiting() {
+    // We need to explicitly call `self.skipWaiting()` here because we're
+    // shadowing `skipWaiting` with this local function.
+    self.addEventListener('install', () => self.skipWaiting());
+  }
+
+  /*
       Copyright 2019 Google LLC
 
       Use of this source code is governed by an MIT-style
       license that can be found in the LICENSE file or at
       https://opensource.org/licenses/MIT.
     */
-    /**
-     * Claim any currently available clients once the service worker
-     * becomes active. This is normally used in conjunction with `skipWaiting()`.
-     *
-     * @memberof module:workbox-core
-     */
-
-    function clientsClaim() {
-      self.addEventListener('activate', () => self.clients.claim());
-    }
-
-    /*
+  /**
+   * Claim any currently available clients once the service worker
+   * becomes active. This is normally used in conjunction with `skipWaiting()`.
+   *
+   * @memberof module:workbox-core
+   */
+
+  function clientsClaim() {
+    self.addEventListener('activate', () => self.clients.claim());
+  }
+
+  /*
       Copyright 2018 Google LLC
 
       Use of this source code is governed by an MIT-style
       license that can be found in the LICENSE file or at
       https://opensource.org/licenses/MIT.
     */
-    const _cacheNameDetails = {
-      googleAnalytics: 'googleAnalytics',
-      precache: 'precache-v2',
-      prefix: 'workbox',
-      runtime: 'runtime',
-      suffix: typeof registration !== 'undefined' ? registration.scope : ''
-    };
-
-    const _createCacheName = cacheName => {
-      return [_cacheNameDetails.prefix, cacheName, _cacheNameDetails.suffix].filter(value => value && value.length > 0).join('-');
-    };
-
-    const eachCacheNameDetail = fn => {
-      for (const key of Object.keys(_cacheNameDetails)) {
-        fn(key);
-      }
-    };
-
-    const cacheNames = {
-      updateDetails: details => {
-        eachCacheNameDetail(key => {
-          if (typeof details[key] === 'string') {
-            _cacheNameDetails[key] = details[key];
-          }
-        });
-      },
-      getGoogleAnalyticsName: userCacheName => {
-        return userCacheName || _createCacheName(_cacheNameDetails.googleAnalytics);
-      },
-      getPrecacheName: userCacheName => {
-        return userCacheName || _createCacheName(_cacheNameDetails.precache);
-      },
-      getPrefix: () => {
-        return _cacheNameDetails.prefix;
-      },
-      getRuntimeName: userCacheName => {
-        return userCacheName || _createCacheName(_cacheNameDetails.runtime);
-      },
-      getSuffix: () => {
-        return _cacheNameDetails.suffix;
-      }
-    };
+  const _cacheNameDetails = {
+    googleAnalytics: 'googleAnalytics',
+    precache: 'precache-v2',
+    prefix: 'workbox',
+    runtime: 'runtime',
+    suffix: typeof registration !== 'undefined' ? registration.scope : '',
+  };
+
+  const _createCacheName = cacheName => {
+    return [_cacheNameDetails.prefix, cacheName, _cacheNameDetails.suffix]
+      .filter(value => value && value.length > 0)
+      .join('-');
+  };
+
+  const eachCacheNameDetail = fn => {
+    for (const key of Object.keys(_cacheNameDetails)) {
+      fn(key);
+    }
+  };
 
-    /*
+  const cacheNames = {
+    updateDetails: details => {
+      eachCacheNameDetail(key => {
+        if (typeof details[key] === 'string') {
+          _cacheNameDetails[key] = details[key];
+        }
+      });
+    },
+    getGoogleAnalyticsName: userCacheName => {
+      return userCacheName || _createCacheName(_cacheNameDetails.googleAnalytics);
+    },
+    getPrecacheName: userCacheName => {
+      return userCacheName || _createCacheName(_cacheNameDetails.precache);
+    },
+    getPrefix: () => {
+      return _cacheNameDetails.prefix;
+    },
+    getRuntimeName: userCacheName => {
+      return userCacheName || _createCacheName(_cacheNameDetails.runtime);
+    },
+    getSuffix: () => {
+      return _cacheNameDetails.suffix;
+    },
+  };
+
+  /*
       Copyright 2018 Google LLC
 
       Use of this source code is governed by an MIT-style
@@ -1634,438 +1606,437 @@ define("./workbox-e536220e.js",['exports'], function (exports) { 'use strict';
       https://opensource.org/licenses/MIT.
     */
 
-    const quotaErrorCallbacks = new Set();
+  const quotaErrorCallbacks = new Set();
 
-    /*
+  /*
       Copyright 2018 Google LLC
 
       Use of this source code is governed by an MIT-style
       license that can be found in the LICENSE file or at
       https://opensource.org/licenses/MIT.
     */
-    /**
-     * Runs all of the callback functions, one at a time sequentially, in the order
-     * in which they were registered.
-     *
-     * @memberof module:workbox-core
-     * @private
-     */
-
-    async function executeQuotaErrorCallbacks() {
-      {
-        logger.log(`About to run ${quotaErrorCallbacks.size} ` + `callbacks to clean up caches.`);
-      }
-
-      for (const callback of quotaErrorCallbacks) {
-        await callback();
+  /**
+   * Runs all of the callback functions, one at a time sequentially, in the order
+   * in which they were registered.
+   *
+   * @memberof module:workbox-core
+   * @private
+   */
+
+  async function executeQuotaErrorCallbacks() {
+    {
+      logger.log(`About to run ${quotaErrorCallbacks.size} ` + `callbacks to clean up caches.`);
+    }
 
-        {
-          logger.log(callback, 'is complete.');
-        }
-      }
+    for (const callback of quotaErrorCallbacks) {
+      await callback();
 
       {
-        logger.log('Finished running callbacks.');
+        logger.log(callback, 'is complete.');
       }
     }
 
-    /*
+    {
+      logger.log('Finished running callbacks.');
+    }
+  }
+
+  /*
       Copyright 2018 Google LLC
 
       Use of this source code is governed by an MIT-style
       license that can be found in the LICENSE file or at
       https://opensource.org/licenses/MIT.
     */
-    /**
-     * Checks the list of plugins for the cacheKeyWillBeUsed callback, and
-     * executes any of those callbacks found in sequence. The final `Request` object
-     * returned by the last plugin is treated as the cache key for cache reads
-     * and/or writes.
-     *
-     * @param {Object} options
-     * @param {Request} options.request
-     * @param {string} options.mode
-     * @param {Array<Object>} [options.plugins=[]]
-     * @return {Promise<Request>}
-     *
-     * @private
-     * @memberof module:workbox-core
-     */
-
-    const _getEffectiveRequest = async ({
-      request,
-      mode,
-      plugins = []
-    }) => {
-      const cacheKeyWillBeUsedPlugins = pluginUtils.filter(plugins, "cacheKeyWillBeUsed"
+  /**
+   * Checks the list of plugins for the cacheKeyWillBeUsed callback, and
+   * executes any of those callbacks found in sequence. The final `Request` object
+   * returned by the last plugin is treated as the cache key for cache reads
+   * and/or writes.
+   *
+   * @param {Object} options
+   * @param {Request} options.request
+   * @param {string} options.mode
+   * @param {Array<Object>} [options.plugins=[]]
+   * @return {Promise<Request>}
+   *
+   * @private
+   * @memberof module:workbox-core
+   */
+
+  const _getEffectiveRequest = async ({ request, mode, plugins = [] }) => {
+    const cacheKeyWillBeUsedPlugins = pluginUtils.filter(
+      plugins,
+      'cacheKeyWillBeUsed'
       /* CACHE_KEY_WILL_BE_USED */
-      );
-      let effectiveRequest = request;
+    );
+    let effectiveRequest = request;
 
-      for (const plugin of cacheKeyWillBeUsedPlugins) {
-        effectiveRequest = await plugin["cacheKeyWillBeUsed"
+    for (const plugin of cacheKeyWillBeUsedPlugins) {
+      effectiveRequest = await plugin[
+        'cacheKeyWillBeUsed'
         /* CACHE_KEY_WILL_BE_USED */
-        ].call(plugin, {
-          mode,
-          request: effectiveRequest
-        });
-
-        if (typeof effectiveRequest === 'string') {
-          effectiveRequest = new Request(effectiveRequest);
-        }
+      ].call(plugin, {
+        mode,
+        request: effectiveRequest,
+      });
 
-        {
-          finalAssertExports.isInstance(effectiveRequest, Request, {
-            moduleName: 'Plugin',
-            funcName: "cacheKeyWillBeUsed"
-            /* CACHE_KEY_WILL_BE_USED */
-            ,
-            isReturnValueProblem: true
-          });
-        }
+      if (typeof effectiveRequest === 'string') {
+        effectiveRequest = new Request(effectiveRequest);
       }
 
-      return effectiveRequest;
-    };
-    /**
-     * This method will call cacheWillUpdate on the available plugins (or use
-     * status === 200) to determine if the Response is safe and valid to cache.
-     *
-     * @param {Object} options
-     * @param {Request} options.request
-     * @param {Response} options.response
-     * @param {Event} [options.event]
-     * @param {Array<Object>} [options.plugins=[]]
-     * @return {Promise<Response>}
-     *
-     * @private
-     * @memberof module:workbox-core
-     */
-
-
-    const _isResponseSafeToCache = async ({
-      request,
-      response,
-      event,
-      plugins = []
-    }) => {
-      let responseToCache = response;
-      let pluginsUsed = false;
+      {
+        finalAssertExports.isInstance(effectiveRequest, Request, {
+          moduleName: 'Plugin',
+          funcName: 'cacheKeyWillBeUsed',
+          /* CACHE_KEY_WILL_BE_USED */
+          isReturnValueProblem: true,
+        });
+      }
+    }
 
-      for (const plugin of plugins) {
-        if ("cacheWillUpdate"
+    return effectiveRequest;
+  };
+  /**
+   * This method will call cacheWillUpdate on the available plugins (or use
+   * status === 200) to determine if the Response is safe and valid to cache.
+   *
+   * @param {Object} options
+   * @param {Request} options.request
+   * @param {Response} options.response
+   * @param {Event} [options.event]
+   * @param {Array<Object>} [options.plugins=[]]
+   * @return {Promise<Response>}
+   *
+   * @private
+   * @memberof module:workbox-core
+   */
+
+  const _isResponseSafeToCache = async ({ request, response, event, plugins = [] }) => {
+    let responseToCache = response;
+    let pluginsUsed = false;
+
+    for (const plugin of plugins) {
+      if (
+        'cacheWillUpdate' in
         /* CACHE_WILL_UPDATE */
-        in plugin) {
-          pluginsUsed = true;
-          const pluginMethod = plugin["cacheWillUpdate"
-          /* CACHE_WILL_UPDATE */
+        plugin
+      ) {
+        pluginsUsed = true;
+        const pluginMethod =
+          plugin[
+            'cacheWillUpdate'
+            /* CACHE_WILL_UPDATE */
           ];
-          responseToCache = await pluginMethod.call(plugin, {
-            request,
-            response: responseToCache,
-            event
-          });
+        responseToCache = await pluginMethod.call(plugin, {
+          request,
+          response: responseToCache,
+          event,
+        });
 
-          {
-            if (responseToCache) {
-              finalAssertExports.isInstance(responseToCache, Response, {
-                moduleName: 'Plugin',
-                funcName: "cacheWillUpdate"
-                /* CACHE_WILL_UPDATE */
-                ,
-                isReturnValueProblem: true
-              });
-            }
+        {
+          if (responseToCache) {
+            finalAssertExports.isInstance(responseToCache, Response, {
+              moduleName: 'Plugin',
+              funcName: 'cacheWillUpdate',
+              /* CACHE_WILL_UPDATE */
+              isReturnValueProblem: true,
+            });
           }
+        }
 
-          if (!responseToCache) {
-            break;
-          }
+        if (!responseToCache) {
+          break;
         }
       }
+    }
 
-      if (!pluginsUsed) {
-        {
-          if (responseToCache) {
-            if (responseToCache.status !== 200) {
-              if (responseToCache.status === 0) {
-                logger.warn(`The response for '${request.url}' is an opaque ` + `response. The caching strategy that you're using will not ` + `cache opaque responses by default.`);
-              } else {
-                logger.debug(`The response for '${request.url}' returned ` + `a status code of '${response.status}' and won't be cached as a ` + `result.`);
-              }
+    if (!pluginsUsed) {
+      {
+        if (responseToCache) {
+          if (responseToCache.status !== 200) {
+            if (responseToCache.status === 0) {
+              logger.warn(
+                `The response for '${request.url}' is an opaque ` +
+                  `response. The caching strategy that you're using will not ` +
+                  `cache opaque responses by default.`
+              );
+            } else {
+              logger.debug(
+                `The response for '${request.url}' returned ` +
+                  `a status code of '${response.status}' and won't be cached as a ` +
+                  `result.`
+              );
             }
           }
         }
-
-        responseToCache = responseToCache && responseToCache.status === 200 ? responseToCache : undefined;
       }
 
-      return responseToCache ? responseToCache : null;
-    };
-    /**
-     * This is a wrapper around cache.match().
-     *
-     * @param {Object} options
-     * @param {string} options.cacheName Name of the cache to match against.
-     * @param {Request} options.request The Request that will be used to look up
-     *     cache entries.
-     * @param {Event} [options.event] The event that prompted the action.
-     * @param {Object} [options.matchOptions] Options passed to cache.match().
-     * @param {Array<Object>} [options.plugins=[]] Array of plugins.
-     * @return {Response} A cached response if available.
-     *
-     * @private
-     * @memberof module:workbox-core
-     */
-
+      responseToCache = responseToCache && responseToCache.status === 200 ? responseToCache : undefined;
+    }
 
-    const matchWrapper = async ({
-      cacheName,
+    return responseToCache ? responseToCache : null;
+  };
+  /**
+   * This is a wrapper around cache.match().
+   *
+   * @param {Object} options
+   * @param {string} options.cacheName Name of the cache to match against.
+   * @param {Request} options.request The Request that will be used to look up
+   *     cache entries.
+   * @param {Event} [options.event] The event that prompted the action.
+   * @param {Object} [options.matchOptions] Options passed to cache.match().
+   * @param {Array<Object>} [options.plugins=[]] Array of plugins.
+   * @return {Response} A cached response if available.
+   *
+   * @private
+   * @memberof module:workbox-core
+   */
+
+  const matchWrapper = async ({ cacheName, request, event, matchOptions, plugins = [] }) => {
+    const cache = await self.caches.open(cacheName);
+    const effectiveRequest = await _getEffectiveRequest({
+      plugins,
       request,
-      event,
-      matchOptions,
-      plugins = []
-    }) => {
-      const cache = await self.caches.open(cacheName);
-      const effectiveRequest = await _getEffectiveRequest({
-        plugins,
-        request,
-        mode: 'read'
-      });
-      let cachedResponse = await cache.match(effectiveRequest, matchOptions);
+      mode: 'read',
+    });
+    let cachedResponse = await cache.match(effectiveRequest, matchOptions);
 
-      {
-        if (cachedResponse) {
-          logger.debug(`Found a cached response in '${cacheName}'.`);
-        } else {
-          logger.debug(`No cached response found in '${cacheName}'.`);
-        }
+    {
+      if (cachedResponse) {
+        logger.debug(`Found a cached response in '${cacheName}'.`);
+      } else {
+        logger.debug(`No cached response found in '${cacheName}'.`);
       }
+    }
 
-      for (const plugin of plugins) {
-        if ("cachedResponseWillBeUsed"
+    for (const plugin of plugins) {
+      if (
+        'cachedResponseWillBeUsed' in
         /* CACHED_RESPONSE_WILL_BE_USED */
-        in plugin) {
-          const pluginMethod = plugin["cachedResponseWillBeUsed"
-          /* CACHED_RESPONSE_WILL_BE_USED */
+        plugin
+      ) {
+        const pluginMethod =
+          plugin[
+            'cachedResponseWillBeUsed'
+            /* CACHED_RESPONSE_WILL_BE_USED */
           ];
-          cachedResponse = await pluginMethod.call(plugin, {
-            cacheName,
-            event,
-            matchOptions,
-            cachedResponse,
-            request: effectiveRequest
-          });
+        cachedResponse = await pluginMethod.call(plugin, {
+          cacheName,
+          event,
+          matchOptions,
+          cachedResponse,
+          request: effectiveRequest,
+        });
 
-          {
-            if (cachedResponse) {
-              finalAssertExports.isInstance(cachedResponse, Response, {
-                moduleName: 'Plugin',
-                funcName: "cachedResponseWillBeUsed"
-                /* CACHED_RESPONSE_WILL_BE_USED */
-                ,
-                isReturnValueProblem: true
-              });
-            }
+        {
+          if (cachedResponse) {
+            finalAssertExports.isInstance(cachedResponse, Response, {
+              moduleName: 'Plugin',
+              funcName: 'cachedResponseWillBeUsed',
+              /* CACHED_RESPONSE_WILL_BE_USED */
+              isReturnValueProblem: true,
+            });
           }
         }
       }
+    }
 
-      return cachedResponse;
-    };
-    /**
-     * Wrapper around cache.put().
-     *
-     * Will call `cacheDidUpdate` on plugins if the cache was updated, using
-     * `matchOptions` when determining what the old entry is.
-     *
-     * @param {Object} options
-     * @param {string} options.cacheName
-     * @param {Request} options.request
-     * @param {Response} options.response
-     * @param {Event} [options.event]
-     * @param {Array<Object>} [options.plugins=[]]
-     * @param {Object} [options.matchOptions]
-     *
-     * @private
-     * @memberof module:workbox-core
-     */
-
+    return cachedResponse;
+  };
+  /**
+   * Wrapper around cache.put().
+   *
+   * Will call `cacheDidUpdate` on plugins if the cache was updated, using
+   * `matchOptions` when determining what the old entry is.
+   *
+   * @param {Object} options
+   * @param {string} options.cacheName
+   * @param {Request} options.request
+   * @param {Response} options.response
+   * @param {Event} [options.event]
+   * @param {Array<Object>} [options.plugins=[]]
+   * @param {Object} [options.matchOptions]
+   *
+   * @private
+   * @memberof module:workbox-core
+   */
+
+  const putWrapper = async ({ cacheName, request, response, event, plugins = [], matchOptions }) => {
+    {
+      if (request.method && request.method !== 'GET') {
+        throw new WorkboxError('attempt-to-cache-non-get-request', {
+          url: getFriendlyURL(request.url),
+          method: request.method,
+        });
+      }
+    }
 
-    const putWrapper = async ({
-      cacheName,
+    const effectiveRequest = await _getEffectiveRequest({
+      plugins,
       request,
-      response,
-      event,
-      plugins = [],
-      matchOptions
-    }) => {
+      mode: 'write',
+    });
+
+    if (!response) {
       {
-        if (request.method && request.method !== 'GET') {
-          throw new WorkboxError('attempt-to-cache-non-get-request', {
-            url: getFriendlyURL(request.url),
-            method: request.method
-          });
-        }
+        logger.error(`Cannot cache non-existent response for ` + `'${getFriendlyURL(effectiveRequest.url)}'.`);
       }
 
-      const effectiveRequest = await _getEffectiveRequest({
-        plugins,
-        request,
-        mode: 'write'
+      throw new WorkboxError('cache-put-with-no-response', {
+        url: getFriendlyURL(effectiveRequest.url),
       });
+    }
 
-      if (!response) {
-        {
-          logger.error(`Cannot cache non-existent response for ` + `'${getFriendlyURL(effectiveRequest.url)}'.`);
-        }
+    const responseToCache = await _isResponseSafeToCache({
+      event,
+      plugins,
+      response,
+      request: effectiveRequest,
+    });
 
-        throw new WorkboxError('cache-put-with-no-response', {
-          url: getFriendlyURL(effectiveRequest.url)
-        });
+    if (!responseToCache) {
+      {
+        logger.debug(`Response '${getFriendlyURL(effectiveRequest.url)}' will ` + `not be cached.`, responseToCache);
       }
 
-      const responseToCache = await _isResponseSafeToCache({
-        event,
-        plugins,
-        response,
-        request: effectiveRequest
-      });
-
-      if (!responseToCache) {
-        {
-          logger.debug(`Response '${getFriendlyURL(effectiveRequest.url)}' will ` + `not be cached.`, responseToCache);
-        }
-
-        return;
-      }
+      return;
+    }
 
-      const cache = await self.caches.open(cacheName);
-      const updatePlugins = pluginUtils.filter(plugins, "cacheDidUpdate"
+    const cache = await self.caches.open(cacheName);
+    const updatePlugins = pluginUtils.filter(
+      plugins,
+      'cacheDidUpdate'
       /* CACHE_DID_UPDATE */
+    );
+    const oldResponse =
+      updatePlugins.length > 0
+        ? await matchWrapper({
+            cacheName,
+            matchOptions,
+            request: effectiveRequest,
+          })
+        : null;
+
+    {
+      logger.debug(
+        `Updating the '${cacheName}' cache with a new Response for ` + `${getFriendlyURL(effectiveRequest.url)}.`
       );
-      const oldResponse = updatePlugins.length > 0 ? await matchWrapper({
-        cacheName,
-        matchOptions,
-        request: effectiveRequest
-      }) : null;
+    }
 
-      {
-        logger.debug(`Updating the '${cacheName}' cache with a new Response for ` + `${getFriendlyURL(effectiveRequest.url)}.`);
+    try {
+      await cache.put(effectiveRequest, responseToCache);
+    } catch (error) {
+      // See https://developer.mozilla.org/en-US/docs/Web/API/DOMException#exception-QuotaExceededError
+      if (error.name === 'QuotaExceededError') {
+        await executeQuotaErrorCallbacks();
       }
 
-      try {
-        await cache.put(effectiveRequest, responseToCache);
-      } catch (error) {
-        // See https://developer.mozilla.org/en-US/docs/Web/API/DOMException#exception-QuotaExceededError
-        if (error.name === 'QuotaExceededError') {
-          await executeQuotaErrorCallbacks();
-        }
-
-        throw error;
-      }
+      throw error;
+    }
 
-      for (const plugin of updatePlugins) {
-        await plugin["cacheDidUpdate"
+    for (const plugin of updatePlugins) {
+      await plugin[
+        'cacheDidUpdate'
         /* CACHE_DID_UPDATE */
-        ].call(plugin, {
-          cacheName,
-          event,
-          oldResponse,
-          newResponse: responseToCache,
-          request: effectiveRequest
-        });
-      }
-    };
+      ].call(plugin, {
+        cacheName,
+        event,
+        oldResponse,
+        newResponse: responseToCache,
+        request: effectiveRequest,
+      });
+    }
+  };
 
-    const cacheWrapper = {
-      put: putWrapper,
-      match: matchWrapper
-    };
+  const cacheWrapper = {
+    put: putWrapper,
+    match: matchWrapper,
+  };
 
-    /*
+  /*
       Copyright 2019 Google LLC
 
       Use of this source code is governed by an MIT-style
       license that can be found in the LICENSE file or at
       https://opensource.org/licenses/MIT.
     */
-    let supportStatus;
-    /**
-     * A utility function that determines whether the current browser supports
-     * constructing a new `Response` from a `response.body` stream.
-     *
-     * @return {boolean} `true`, if the current browser can successfully
-     *     construct a `Response` from a `response.body` stream, `false` otherwise.
-     *
-     * @private
-     */
-
-    function canConstructResponseFromBodyStream() {
-      if (supportStatus === undefined) {
-        const testResponse = new Response('');
-
-        if ('body' in testResponse) {
-          try {
-            new Response(testResponse.body);
-            supportStatus = true;
-          } catch (error) {
-            supportStatus = false;
-          }
+  let supportStatus;
+  /**
+   * A utility function that determines whether the current browser supports
+   * constructing a new `Response` from a `response.body` stream.
+   *
+   * @return {boolean} `true`, if the current browser can successfully
+   *     construct a `Response` from a `response.body` stream, `false` otherwise.
+   *
+   * @private
+   */
+
+  function canConstructResponseFromBodyStream() {
+    if (supportStatus === undefined) {
+      const testResponse = new Response('');
+
+      if ('body' in testResponse) {
+        try {
+          new Response(testResponse.body);
+          supportStatus = true;
+        } catch (error) {
+          supportStatus = false;
         }
-
-        supportStatus = false;
       }
 
-      return supportStatus;
+      supportStatus = false;
     }
 
-    /*
+    return supportStatus;
+  }
+
+  /*
       Copyright 2019 Google LLC
 
       Use of this source code is governed by an MIT-style
       license that can be found in the LICENSE file or at
       https://opensource.org/licenses/MIT.
     */
-    /**
-     * Allows developers to copy a response and modify its `headers`, `status`,
-     * or `statusText` values (the values settable via a
-     * [`ResponseInit`]{@link https://developer.mozilla.org/en-US/docs/Web/API/Response/Response#Syntax}
-     * object in the constructor).
-     * To modify these values, pass a function as the second argument. That
-     * function will be invoked with a single object with the response properties
-     * `{headers, status, statusText}`. The return value of this function will
-     * be used as the `ResponseInit` for the new `Response`. To change the values
-     * either modify the passed parameter(s) and return it, or return a totally
-     * new object.
-     *
-     * @param {Response} response
-     * @param {Function} modifier
-     * @memberof module:workbox-core
-     */
-
-    async function copyResponse(response, modifier) {
-      const clonedResponse = response.clone(); // Create a fresh `ResponseInit` object by cloning the headers.
-
-      const responseInit = {
-        headers: new Headers(clonedResponse.headers),
-        status: clonedResponse.status,
-        statusText: clonedResponse.statusText
-      }; // Apply any user modifications.
-
-      const modifiedResponseInit = modifier ? modifier(responseInit) : responseInit; // Create the new response from the body stream and `ResponseInit`
-      // modifications. Note: not all browsers support the Response.body stream,
-      // so fall back to reading the entire body into memory as a blob.
-
-      const body = canConstructResponseFromBodyStream() ? clonedResponse.body : await clonedResponse.blob();
-      return new Response(body, modifiedResponseInit);
-    }
-
-    try {
-      self['workbox:precaching:5.1.4'] && _();
-    } catch (e) {}
-
-    /*
+  /**
+   * Allows developers to copy a response and modify its `headers`, `status`,
+   * or `statusText` values (the values settable via a
+   * [`ResponseInit`]{@link https://developer.mozilla.org/en-US/docs/Web/API/Response/Response#Syntax}
+   * object in the constructor).
+   * To modify these values, pass a function as the second argument. That
+   * function will be invoked with a single object with the response properties
+   * `{headers, status, statusText}`. The return value of this function will
+   * be used as the `ResponseInit` for the new `Response`. To change the values
+   * either modify the passed parameter(s) and return it, or return a totally
+   * new object.
+   *
+   * @param {Response} response
+   * @param {Function} modifier
+   * @memberof module:workbox-core
+   */
+
+  async function copyResponse(response, modifier) {
+    const clonedResponse = response.clone(); // Create a fresh `ResponseInit` object by cloning the headers.
+
+    const responseInit = {
+      headers: new Headers(clonedResponse.headers),
+      status: clonedResponse.status,
+      statusText: clonedResponse.statusText,
+    }; // Apply any user modifications.
+
+    const modifiedResponseInit = modifier ? modifier(responseInit) : responseInit; // Create the new response from the body stream and `ResponseInit`
+    // modifications. Note: not all browsers support the Response.body stream,
+    // so fall back to reading the entire body into memory as a blob.
+
+    const body = canConstructResponseFromBodyStream() ? clonedResponse.body : await clonedResponse.blob();
+    return new Response(body, modifiedResponseInit);
+  }
+
+  try {
+    self['workbox:precaching:5.1.4'] && _();
+  } catch (e) {}
+
+  /*
       Copyright 2018 Google LLC
 
       Use of this source code is governed by an MIT-style
@@ -2073,895 +2044,871 @@ define("./workbox-e536220e.js",['exports'], function (exports) { 'use strict';
       https://opensource.org/licenses/MIT.
     */
 
-    const REVISION_SEARCH_PARAM = '__WB_REVISION__';
-    /**
-     * Converts a manifest entry into a versioned URL suitable for precaching.
-     *
-     * @param {Object|string} entry
-     * @return {string} A URL with versioning info.
-     *
-     * @private
-     * @memberof module:workbox-precaching
-     */
-
-    function createCacheKey(entry) {
-      if (!entry) {
-        throw new WorkboxError('add-to-cache-list-unexpected-type', {
-          entry
-        });
-      } // If a precache manifest entry is a string, it's assumed to be a versioned
-      // URL, like '/app.abcd1234.js'. Return as-is.
-
+  const REVISION_SEARCH_PARAM = '__WB_REVISION__';
+  /**
+   * Converts a manifest entry into a versioned URL suitable for precaching.
+   *
+   * @param {Object|string} entry
+   * @return {string} A URL with versioning info.
+   *
+   * @private
+   * @memberof module:workbox-precaching
+   */
+
+  function createCacheKey(entry) {
+    if (!entry) {
+      throw new WorkboxError('add-to-cache-list-unexpected-type', {
+        entry,
+      });
+    } // If a precache manifest entry is a string, it's assumed to be a versioned
+    // URL, like '/app.abcd1234.js'. Return as-is.
 
-      if (typeof entry === 'string') {
-        const urlObject = new URL(entry, location.href);
-        return {
-          cacheKey: urlObject.href,
-          url: urlObject.href
-        };
-      }
+    if (typeof entry === 'string') {
+      const urlObject = new URL(entry, location.href);
+      return {
+        cacheKey: urlObject.href,
+        url: urlObject.href,
+      };
+    }
 
-      const {
-        revision,
-        url
-      } = entry;
+    const { revision, url } = entry;
 
-      if (!url) {
-        throw new WorkboxError('add-to-cache-list-unexpected-type', {
-          entry
-        });
-      } // If there's just a URL and no revision, then it's also assumed to be a
-      // versioned URL.
+    if (!url) {
+      throw new WorkboxError('add-to-cache-list-unexpected-type', {
+        entry,
+      });
+    } // If there's just a URL and no revision, then it's also assumed to be a
+    // versioned URL.
 
+    if (!revision) {
+      const urlObject = new URL(url, location.href);
+      return {
+        cacheKey: urlObject.href,
+        url: urlObject.href,
+      };
+    } // Otherwise, construct a properly versioned URL using the custom Workbox
+    // search parameter along with the revision info.
+
+    const cacheKeyURL = new URL(url, location.href);
+    const originalURL = new URL(url, location.href);
+    cacheKeyURL.searchParams.set(REVISION_SEARCH_PARAM, revision);
+    return {
+      cacheKey: cacheKeyURL.href,
+      url: originalURL.href,
+    };
+  }
 
-      if (!revision) {
-        const urlObject = new URL(url, location.href);
-        return {
-          cacheKey: urlObject.href,
-          url: urlObject.href
-        };
-      } // Otherwise, construct a properly versioned URL using the custom Workbox
-      // search parameter along with the revision info.
+  /*
+      Copyright 2018 Google LLC
 
+      Use of this source code is governed by an MIT-style
+      license that can be found in the LICENSE file or at
+      https://opensource.org/licenses/MIT.
+    */
+  /**
+   * @param {string} groupTitle
+   * @param {Array<string>} deletedURLs
+   *
+   * @private
+   */
+
+  const logGroup = (groupTitle, deletedURLs) => {
+    logger.groupCollapsed(groupTitle);
+
+    for (const url of deletedURLs) {
+      logger.log(url);
+    }
 
-      const cacheKeyURL = new URL(url, location.href);
-      const originalURL = new URL(url, location.href);
-      cacheKeyURL.searchParams.set(REVISION_SEARCH_PARAM, revision);
-      return {
-        cacheKey: cacheKeyURL.href,
-        url: originalURL.href
-      };
+    logger.groupEnd();
+  };
+  /**
+   * @param {Array<string>} deletedURLs
+   *
+   * @private
+   * @memberof module:workbox-precaching
+   */
+
+  function printCleanupDetails(deletedURLs) {
+    const deletionCount = deletedURLs.length;
+
+    if (deletionCount > 0) {
+      logger.groupCollapsed(
+        `During precaching cleanup, ` +
+          `${deletionCount} cached ` +
+          `request${deletionCount === 1 ? ' was' : 's were'} deleted.`
+      );
+      logGroup('Deleted Cache Requests', deletedURLs);
+      logger.groupEnd();
     }
+  }
 
-    /*
+  /*
       Copyright 2018 Google LLC
 
       Use of this source code is governed by an MIT-style
       license that can be found in the LICENSE file or at
       https://opensource.org/licenses/MIT.
     */
-    /**
-     * @param {string} groupTitle
-     * @param {Array<string>} deletedURLs
-     *
-     * @private
-     */
+  /**
+   * @param {string} groupTitle
+   * @param {Array<string>} urls
+   *
+   * @private
+   */
+
+  function _nestedGroup(groupTitle, urls) {
+    if (urls.length === 0) {
+      return;
+    }
 
-    const logGroup = (groupTitle, deletedURLs) => {
-      logger.groupCollapsed(groupTitle);
+    logger.groupCollapsed(groupTitle);
 
-      for (const url of deletedURLs) {
-        logger.log(url);
-      }
+    for (const url of urls) {
+      logger.log(url);
+    }
 
-      logger.groupEnd();
-    };
-    /**
-     * @param {Array<string>} deletedURLs
-     *
-     * @private
-     * @memberof module:workbox-precaching
-     */
+    logger.groupEnd();
+  }
+  /**
+   * @param {Array<string>} urlsToPrecache
+   * @param {Array<string>} urlsAlreadyPrecached
+   *
+   * @private
+   * @memberof module:workbox-precaching
+   */
 
+  function printInstallDetails(urlsToPrecache, urlsAlreadyPrecached) {
+    const precachedCount = urlsToPrecache.length;
+    const alreadyPrecachedCount = urlsAlreadyPrecached.length;
 
-    function printCleanupDetails(deletedURLs) {
-      const deletionCount = deletedURLs.length;
+    if (precachedCount || alreadyPrecachedCount) {
+      let message = `Precaching ${precachedCount} file${precachedCount === 1 ? '' : 's'}.`;
 
-      if (deletionCount > 0) {
-        logger.groupCollapsed(`During precaching cleanup, ` + `${deletionCount} cached ` + `request${deletionCount === 1 ? ' was' : 's were'} deleted.`);
-        logGroup('Deleted Cache Requests', deletedURLs);
-        logger.groupEnd();
+      if (alreadyPrecachedCount > 0) {
+        message +=
+          ` ${alreadyPrecachedCount} ` + `file${alreadyPrecachedCount === 1 ? ' is' : 's are'} already cached.`;
       }
+
+      logger.groupCollapsed(message);
+
+      _nestedGroup(`View newly precached URLs.`, urlsToPrecache);
+
+      _nestedGroup(`View previously precached URLs.`, urlsAlreadyPrecached);
+
+      logger.groupEnd();
     }
+  }
 
-    /*
-      Copyright 2018 Google LLC
+  /*
+      Copyright 2019 Google LLC
 
       Use of this source code is governed by an MIT-style
       license that can be found in the LICENSE file or at
       https://opensource.org/licenses/MIT.
     */
+  /**
+   * Performs efficient precaching of assets.
+   *
+   * @memberof module:workbox-precaching
+   */
+
+  class PrecacheController {
     /**
-     * @param {string} groupTitle
-     * @param {Array<string>} urls
+     * Create a new PrecacheController.
      *
-     * @private
+     * @param {string} [cacheName] An optional name for the cache, to override
+     * the default precache name.
      */
-
-    function _nestedGroup(groupTitle, urls) {
-      if (urls.length === 0) {
-        return;
-      }
-
-      logger.groupCollapsed(groupTitle);
-
-      for (const url of urls) {
-        logger.log(url);
-      }
-
-      logger.groupEnd();
+    constructor(cacheName) {
+      this._cacheName = cacheNames.getPrecacheName(cacheName);
+      this._urlsToCacheKeys = new Map();
+      this._urlsToCacheModes = new Map();
+      this._cacheKeysToIntegrities = new Map();
     }
     /**
-     * @param {Array<string>} urlsToPrecache
-     * @param {Array<string>} urlsAlreadyPrecached
+     * This method will add items to the precache list, removing duplicates
+     * and ensuring the information is valid.
      *
-     * @private
-     * @memberof module:workbox-precaching
+     * @param {
+     * Array<module:workbox-precaching.PrecacheController.PrecacheEntry|string>
+     * } entries Array of entries to precache.
      */
 
+    addToCacheList(entries) {
+      {
+        finalAssertExports.isArray(entries, {
+          moduleName: 'workbox-precaching',
+          className: 'PrecacheController',
+          funcName: 'addToCacheList',
+          paramName: 'entries',
+        });
+      }
+
+      const urlsToWarnAbout = [];
 
-    function printInstallDetails(urlsToPrecache, urlsAlreadyPrecached) {
-      const precachedCount = urlsToPrecache.length;
-      const alreadyPrecachedCount = urlsAlreadyPrecached.length;
+      for (const entry of entries) {
+        // See https://github.com/GoogleChrome/workbox/issues/2259
+        if (typeof entry === 'string') {
+          urlsToWarnAbout.push(entry);
+        } else if (entry && entry.revision === undefined) {
+          urlsToWarnAbout.push(entry.url);
+        }
 
-      if (precachedCount || alreadyPrecachedCount) {
-        let message = `Precaching ${precachedCount} file${precachedCount === 1 ? '' : 's'}.`;
+        const { cacheKey, url } = createCacheKey(entry);
+        const cacheMode = typeof entry !== 'string' && entry.revision ? 'reload' : 'default';
 
-        if (alreadyPrecachedCount > 0) {
-          message += ` ${alreadyPrecachedCount} ` + `file${alreadyPrecachedCount === 1 ? ' is' : 's are'} already cached.`;
+        if (this._urlsToCacheKeys.has(url) && this._urlsToCacheKeys.get(url) !== cacheKey) {
+          throw new WorkboxError('add-to-cache-list-conflicting-entries', {
+            firstEntry: this._urlsToCacheKeys.get(url),
+            secondEntry: cacheKey,
+          });
         }
 
-        logger.groupCollapsed(message);
+        if (typeof entry !== 'string' && entry.integrity) {
+          if (
+            this._cacheKeysToIntegrities.has(cacheKey) &&
+            this._cacheKeysToIntegrities.get(cacheKey) !== entry.integrity
+          ) {
+            throw new WorkboxError('add-to-cache-list-conflicting-integrities', {
+              url,
+            });
+          }
 
-        _nestedGroup(`View newly precached URLs.`, urlsToPrecache);
+          this._cacheKeysToIntegrities.set(cacheKey, entry.integrity);
+        }
 
-        _nestedGroup(`View previously precached URLs.`, urlsAlreadyPrecached);
+        this._urlsToCacheKeys.set(url, cacheKey);
 
-        logger.groupEnd();
-      }
-    }
+        this._urlsToCacheModes.set(url, cacheMode);
 
-    /*
-      Copyright 2019 Google LLC
+        if (urlsToWarnAbout.length > 0) {
+          const warningMessage =
+            `Workbox is precaching URLs without revision ` +
+            `info: ${urlsToWarnAbout.join(', ')}\nThis is generally NOT safe. ` +
+            `Learn more at https://bit.ly/wb-precache`;
 
-      Use of this source code is governed by an MIT-style
-      license that can be found in the LICENSE file or at
-      https://opensource.org/licenses/MIT.
-    */
+          {
+            logger.warn(warningMessage);
+          }
+        }
+      }
+    }
     /**
-     * Performs efficient precaching of assets.
+     * Precaches new and updated assets. Call this method from the service worker
+     * install event.
      *
-     * @memberof module:workbox-precaching
+     * @param {Object} options
+     * @param {Event} [options.event] The install event (if needed).
+     * @param {Array<Object>} [options.plugins] Plugins to be used for fetching
+     * and caching during install.
+     * @return {Promise<module:workbox-precaching.InstallResult>}
      */
 
-    class PrecacheController {
-      /**
-       * Create a new PrecacheController.
-       *
-       * @param {string} [cacheName] An optional name for the cache, to override
-       * the default precache name.
-       */
-      constructor(cacheName) {
-        this._cacheName = cacheNames.getPrecacheName(cacheName);
-        this._urlsToCacheKeys = new Map();
-        this._urlsToCacheModes = new Map();
-        this._cacheKeysToIntegrities = new Map();
-      }
-      /**
-       * This method will add items to the precache list, removing duplicates
-       * and ensuring the information is valid.
-       *
-       * @param {
-       * Array<module:workbox-precaching.PrecacheController.PrecacheEntry|string>
-       * } entries Array of entries to precache.
-       */
-
-
-      addToCacheList(entries) {
-        {
-          finalAssertExports.isArray(entries, {
+    async install({ event, plugins } = {}) {
+      {
+        if (plugins) {
+          finalAssertExports.isArray(plugins, {
             moduleName: 'workbox-precaching',
             className: 'PrecacheController',
-            funcName: 'addToCacheList',
-            paramName: 'entries'
+            funcName: 'install',
+            paramName: 'plugins',
           });
         }
+      }
 
-        const urlsToWarnAbout = [];
-
-        for (const entry of entries) {
-          // See https://github.com/GoogleChrome/workbox/issues/2259
-          if (typeof entry === 'string') {
-            urlsToWarnAbout.push(entry);
-          } else if (entry && entry.revision === undefined) {
-            urlsToWarnAbout.push(entry.url);
-          }
+      const toBePrecached = [];
+      const alreadyPrecached = [];
+      const cache = await self.caches.open(this._cacheName);
+      const alreadyCachedRequests = await cache.keys();
+      const existingCacheKeys = new Set(alreadyCachedRequests.map(request => request.url));
 
-          const {
+      for (const [url, cacheKey] of this._urlsToCacheKeys) {
+        if (existingCacheKeys.has(cacheKey)) {
+          alreadyPrecached.push(url);
+        } else {
+          toBePrecached.push({
             cacheKey,
-            url
-          } = createCacheKey(entry);
-          const cacheMode = typeof entry !== 'string' && entry.revision ? 'reload' : 'default';
-
-          if (this._urlsToCacheKeys.has(url) && this._urlsToCacheKeys.get(url) !== cacheKey) {
-            throw new WorkboxError('add-to-cache-list-conflicting-entries', {
-              firstEntry: this._urlsToCacheKeys.get(url),
-              secondEntry: cacheKey
-            });
-          }
+            url,
+          });
+        }
+      }
 
-          if (typeof entry !== 'string' && entry.integrity) {
-            if (this._cacheKeysToIntegrities.has(cacheKey) && this._cacheKeysToIntegrities.get(cacheKey) !== entry.integrity) {
-              throw new WorkboxError('add-to-cache-list-conflicting-integrities', {
-                url
-              });
-            }
+      const precacheRequests = toBePrecached.map(({ cacheKey, url }) => {
+        const integrity = this._cacheKeysToIntegrities.get(cacheKey);
 
-            this._cacheKeysToIntegrities.set(cacheKey, entry.integrity);
-          }
+        const cacheMode = this._urlsToCacheModes.get(url);
+
+        return this._addURLToCache({
+          cacheKey,
+          cacheMode,
+          event,
+          integrity,
+          plugins,
+          url,
+        });
+      });
+      await Promise.all(precacheRequests);
+      const updatedURLs = toBePrecached.map(item => item.url);
 
-          this._urlsToCacheKeys.set(url, cacheKey);
+      {
+        printInstallDetails(updatedURLs, alreadyPrecached);
+      }
 
-          this._urlsToCacheModes.set(url, cacheMode);
+      return {
+        updatedURLs,
+        notUpdatedURLs: alreadyPrecached,
+      };
+    }
+    /**
+     * Deletes assets that are no longer present in the current precache manifest.
+     * Call this method from the service worker activate event.
+     *
+     * @return {Promise<module:workbox-precaching.CleanupResult>}
+     */
 
-          if (urlsToWarnAbout.length > 0) {
-            const warningMessage = `Workbox is precaching URLs without revision ` + `info: ${urlsToWarnAbout.join(', ')}\nThis is generally NOT safe. ` + `Learn more at https://bit.ly/wb-precache`;
+    async activate() {
+      const cache = await self.caches.open(this._cacheName);
+      const currentlyCachedRequests = await cache.keys();
+      const expectedCacheKeys = new Set(this._urlsToCacheKeys.values());
+      const deletedURLs = [];
 
-            {
-              logger.warn(warningMessage);
-            }
-          }
+      for (const request of currentlyCachedRequests) {
+        if (!expectedCacheKeys.has(request.url)) {
+          await cache.delete(request);
+          deletedURLs.push(request.url);
         }
       }
-      /**
-       * Precaches new and updated assets. Call this method from the service worker
-       * install event.
-       *
-       * @param {Object} options
-       * @param {Event} [options.event] The install event (if needed).
-       * @param {Array<Object>} [options.plugins] Plugins to be used for fetching
-       * and caching during install.
-       * @return {Promise<module:workbox-precaching.InstallResult>}
-       */
 
+      {
+        printCleanupDetails(deletedURLs);
+      }
+
+      return {
+        deletedURLs,
+      };
+    }
+    /**
+     * Requests the entry and saves it to the cache if the response is valid.
+     * By default, any response with a status code of less than 400 (including
+     * opaque responses) is considered valid.
+     *
+     * If you need to use custom criteria to determine what's valid and what
+     * isn't, then pass in an item in `options.plugins` that implements the
+     * `cacheWillUpdate()` lifecycle event.
+     *
+     * @private
+     * @param {Object} options
+     * @param {string} options.cacheKey The string to use a cache key.
+     * @param {string} options.url The URL to fetch and cache.
+     * @param {string} [options.cacheMode] The cache mode for the network request.
+     * @param {Event} [options.event] The install event (if passed).
+     * @param {Array<Object>} [options.plugins] An array of plugins to apply to
+     * fetch and caching.
+     * @param {string} [options.integrity] The value to use for the `integrity`
+     * field when making the request.
+     */
 
-      async install({
+    async _addURLToCache({ cacheKey, url, cacheMode, event, plugins, integrity }) {
+      const request = new Request(url, {
+        integrity,
+        cache: cacheMode,
+        credentials: 'same-origin',
+      });
+      let response = await fetchWrapper.fetch({
         event,
-        plugins
-      } = {}) {
-        {
-          if (plugins) {
-            finalAssertExports.isArray(plugins, {
-              moduleName: 'workbox-precaching',
-              className: 'PrecacheController',
-              funcName: 'install',
-              paramName: 'plugins'
-            });
-          }
-        }
+        plugins,
+        request,
+      }); // Allow developers to override the default logic about what is and isn't
+      // valid by passing in a plugin implementing cacheWillUpdate(), e.g.
+      // a `CacheableResponsePlugin` instance.
 
-        const toBePrecached = [];
-        const alreadyPrecached = [];
-        const cache = await self.caches.open(this._cacheName);
-        const alreadyCachedRequests = await cache.keys();
-        const existingCacheKeys = new Set(alreadyCachedRequests.map(request => request.url));
+      let cacheWillUpdatePlugin;
 
-        for (const [url, cacheKey] of this._urlsToCacheKeys) {
-          if (existingCacheKeys.has(cacheKey)) {
-            alreadyPrecached.push(url);
-          } else {
-            toBePrecached.push({
-              cacheKey,
-              url
-            });
-          }
+      for (const plugin of plugins || []) {
+        if ('cacheWillUpdate' in plugin) {
+          cacheWillUpdatePlugin = plugin;
         }
+      }
 
-        const precacheRequests = toBePrecached.map(({
-          cacheKey,
-          url
-        }) => {
-          const integrity = this._cacheKeysToIntegrities.get(cacheKey);
-
-          const cacheMode = this._urlsToCacheModes.get(url);
-
-          return this._addURLToCache({
-            cacheKey,
-            cacheMode,
+      const isValidResponse = cacheWillUpdatePlugin // Use a callback if provided. It returns a truthy value if valid.
+        ? // NOTE: invoke the method on the plugin instance so the `this` context
+          // is correct.
+          await cacheWillUpdatePlugin.cacheWillUpdate({
             event,
-            integrity,
-            plugins,
-            url
-          });
+            request,
+            response,
+          }) // Otherwise, default to considering any response status under 400 valid.
+        : // This includes, by default, considering opaque responses valid.
+          response.status < 400; // Consider this a failure, leading to the `install` handler failing, if
+      // we get back an invalid response.
+
+      if (!isValidResponse) {
+        throw new WorkboxError('bad-precaching-response', {
+          url,
+          status: response.status,
         });
-        await Promise.all(precacheRequests);
-        const updatedURLs = toBePrecached.map(item => item.url);
-
-        {
-          printInstallDetails(updatedURLs, alreadyPrecached);
-        }
+      } // Redirected responses cannot be used to satisfy a navigation request, so
+      // any redirected response must be "copied" rather than cloned, so the new
+      // response doesn't contain the `redirected` flag. See:
+      // https://bugs.chromium.org/p/chromium/issues/detail?id=669363&desc=2#c1
 
-        return {
-          updatedURLs,
-          notUpdatedURLs: alreadyPrecached
-        };
+      if (response.redirected) {
+        response = await copyResponse(response);
       }
-      /**
-       * Deletes assets that are no longer present in the current precache manifest.
-       * Call this method from the service worker activate event.
-       *
-       * @return {Promise<module:workbox-precaching.CleanupResult>}
-       */
-
-
-      async activate() {
-        const cache = await self.caches.open(this._cacheName);
-        const currentlyCachedRequests = await cache.keys();
-        const expectedCacheKeys = new Set(this._urlsToCacheKeys.values());
-        const deletedURLs = [];
-
-        for (const request of currentlyCachedRequests) {
-          if (!expectedCacheKeys.has(request.url)) {
-            await cache.delete(request);
-            deletedURLs.push(request.url);
-          }
-        }
-
-        {
-          printCleanupDetails(deletedURLs);
-        }
 
-        return {
-          deletedURLs
-        };
-      }
-      /**
-       * Requests the entry and saves it to the cache if the response is valid.
-       * By default, any response with a status code of less than 400 (including
-       * opaque responses) is considered valid.
-       *
-       * If you need to use custom criteria to determine what's valid and what
-       * isn't, then pass in an item in `options.plugins` that implements the
-       * `cacheWillUpdate()` lifecycle event.
-       *
-       * @private
-       * @param {Object} options
-       * @param {string} options.cacheKey The string to use a cache key.
-       * @param {string} options.url The URL to fetch and cache.
-       * @param {string} [options.cacheMode] The cache mode for the network request.
-       * @param {Event} [options.event] The install event (if passed).
-       * @param {Array<Object>} [options.plugins] An array of plugins to apply to
-       * fetch and caching.
-       * @param {string} [options.integrity] The value to use for the `integrity`
-       * field when making the request.
-       */
-
-
-      async _addURLToCache({
-        cacheKey,
-        url,
-        cacheMode,
+      await cacheWrapper.put({
         event,
         plugins,
-        integrity
-      }) {
-        const request = new Request(url, {
-          integrity,
-          cache: cacheMode,
-          credentials: 'same-origin'
-        });
-        let response = await fetchWrapper.fetch({
-          event,
-          plugins,
-          request
-        }); // Allow developers to override the default logic about what is and isn't
-        // valid by passing in a plugin implementing cacheWillUpdate(), e.g.
-        // a `CacheableResponsePlugin` instance.
-
-        let cacheWillUpdatePlugin;
+        response,
+        // `request` already uses `url`. We may be able to reuse it.
+        request: cacheKey === url ? request : new Request(cacheKey),
+        cacheName: this._cacheName,
+        matchOptions: {
+          ignoreSearch: true,
+        },
+      });
+    }
+    /**
+     * Returns a mapping of a precached URL to the corresponding cache key, taking
+     * into account the revision information for the URL.
+     *
+     * @return {Map<string, string>} A URL to cache key mapping.
+     */
 
-        for (const plugin of plugins || []) {
-          if ('cacheWillUpdate' in plugin) {
-            cacheWillUpdatePlugin = plugin;
-          }
-        }
+    getURLsToCacheKeys() {
+      return this._urlsToCacheKeys;
+    }
+    /**
+     * Returns a list of all the URLs that have been precached by the current
+     * service worker.
+     *
+     * @return {Array<string>} The precached URLs.
+     */
 
-        const isValidResponse = cacheWillUpdatePlugin ? // Use a callback if provided. It returns a truthy value if valid.
-        // NOTE: invoke the method on the plugin instance so the `this` context
-        // is correct.
-        await cacheWillUpdatePlugin.cacheWillUpdate({
-          event,
-          request,
-          response
-        }) : // Otherwise, default to considering any response status under 400 valid.
-        // This includes, by default, considering opaque responses valid.
-        response.status < 400; // Consider this a failure, leading to the `install` handler failing, if
-        // we get back an invalid response.
-
-        if (!isValidResponse) {
-          throw new WorkboxError('bad-precaching-response', {
-            url,
-            status: response.status
-          });
-        } // Redirected responses cannot be used to satisfy a navigation request, so
-        // any redirected response must be "copied" rather than cloned, so the new
-        // response doesn't contain the `redirected` flag. See:
-        // https://bugs.chromium.org/p/chromium/issues/detail?id=669363&desc=2#c1
+    getCachedURLs() {
+      return [...this._urlsToCacheKeys.keys()];
+    }
+    /**
+     * Returns the cache key used for storing a given URL. If that URL is
+     * unversioned, like `/index.html', then the cache key will be the original
+     * URL with a search parameter appended to it.
+     *
+     * @param {string} url A URL whose cache key you want to look up.
+     * @return {string} The versioned URL that corresponds to a cache key
+     * for the original URL, or undefined if that URL isn't precached.
+     */
 
+    getCacheKeyForURL(url) {
+      const urlObject = new URL(url, location.href);
+      return this._urlsToCacheKeys.get(urlObject.href);
+    }
+    /**
+     * This acts as a drop-in replacement for [`cache.match()`](https://developer.mozilla.org/en-US/docs/Web/API/Cache/match)
+     * with the following differences:
+     *
+     * - It knows what the name of the precache is, and only checks in that cache.
+     * - It allows you to pass in an "original" URL without versioning parameters,
+     * and it will automatically look up the correct cache key for the currently
+     * active revision of that URL.
+     *
+     * E.g., `matchPrecache('index.html')` will find the correct precached
+     * response for the currently active service worker, even if the actual cache
+     * key is `'/index.html?__WB_REVISION__=1234abcd'`.
+     *
+     * @param {string|Request} request The key (without revisioning parameters)
+     * to look up in the precache.
+     * @return {Promise<Response|undefined>}
+     */
 
-        if (response.redirected) {
-          response = await copyResponse(response);
-        }
+    async matchPrecache(request) {
+      const url = request instanceof Request ? request.url : request;
+      const cacheKey = this.getCacheKeyForURL(url);
 
-        await cacheWrapper.put({
-          event,
-          plugins,
-          response,
-          // `request` already uses `url`. We may be able to reuse it.
-          request: cacheKey === url ? request : new Request(cacheKey),
-          cacheName: this._cacheName,
-          matchOptions: {
-            ignoreSearch: true
-          }
-        });
+      if (cacheKey) {
+        const cache = await self.caches.open(this._cacheName);
+        return cache.match(cacheKey);
       }
-      /**
-       * Returns a mapping of a precached URL to the corresponding cache key, taking
-       * into account the revision information for the URL.
-       *
-       * @return {Map<string, string>} A URL to cache key mapping.
-       */
-
-
-      getURLsToCacheKeys() {
-        return this._urlsToCacheKeys;
-      }
-      /**
-       * Returns a list of all the URLs that have been precached by the current
-       * service worker.
-       *
-       * @return {Array<string>} The precached URLs.
-       */
-
-
-      getCachedURLs() {
-        return [...this._urlsToCacheKeys.keys()];
-      }
-      /**
-       * Returns the cache key used for storing a given URL. If that URL is
-       * unversioned, like `/index.html', then the cache key will be the original
-       * URL with a search parameter appended to it.
-       *
-       * @param {string} url A URL whose cache key you want to look up.
-       * @return {string} The versioned URL that corresponds to a cache key
-       * for the original URL, or undefined if that URL isn't precached.
-       */
-
-
-      getCacheKeyForURL(url) {
-        const urlObject = new URL(url, location.href);
-        return this._urlsToCacheKeys.get(urlObject.href);
-      }
-      /**
-       * This acts as a drop-in replacement for [`cache.match()`](https://developer.mozilla.org/en-US/docs/Web/API/Cache/match)
-       * with the following differences:
-       *
-       * - It knows what the name of the precache is, and only checks in that cache.
-       * - It allows you to pass in an "original" URL without versioning parameters,
-       * and it will automatically look up the correct cache key for the currently
-       * active revision of that URL.
-       *
-       * E.g., `matchPrecache('index.html')` will find the correct precached
-       * response for the currently active service worker, even if the actual cache
-       * key is `'/index.html?__WB_REVISION__=1234abcd'`.
-       *
-       * @param {string|Request} request The key (without revisioning parameters)
-       * to look up in the precache.
-       * @return {Promise<Response|undefined>}
-       */
-
-
-      async matchPrecache(request) {
-        const url = request instanceof Request ? request.url : request;
-        const cacheKey = this.getCacheKeyForURL(url);
-
-        if (cacheKey) {
-          const cache = await self.caches.open(this._cacheName);
-          return cache.match(cacheKey);
-        }
 
-        return undefined;
-      }
-      /**
-       * Returns a function that can be used within a
-       * {@link module:workbox-routing.Route} that will find a response for the
-       * incoming request against the precache.
-       *
-       * If for an unexpected reason there is a cache miss for the request,
-       * this will fall back to retrieving the `Response` via `fetch()` when
-       * `fallbackToNetwork` is `true`.
-       *
-       * @param {boolean} [fallbackToNetwork=true] Whether to attempt to get the
-       * response from the network if there's a precache miss.
-       * @return {module:workbox-routing~handlerCallback}
-       */
-
-
-      createHandler(fallbackToNetwork = true) {
-        return async ({
-          request
-        }) => {
-          try {
-            const response = await this.matchPrecache(request);
-
-            if (response) {
-              return response;
-            } // This shouldn't normally happen, but there are edge cases:
-            // https://github.com/GoogleChrome/workbox/issues/1441
-
-
-            throw new WorkboxError('missing-precache-entry', {
-              cacheName: this._cacheName,
-              url: request instanceof Request ? request.url : request
-            });
-          } catch (error) {
-            if (fallbackToNetwork) {
-              {
-                logger.debug(`Unable to respond with precached response. ` + `Falling back to network.`, error);
-              }
+      return undefined;
+    }
+    /**
+     * Returns a function that can be used within a
+     * {@link module:workbox-routing.Route} that will find a response for the
+     * incoming request against the precache.
+     *
+     * If for an unexpected reason there is a cache miss for the request,
+     * this will fall back to retrieving the `Response` via `fetch()` when
+     * `fallbackToNetwork` is `true`.
+     *
+     * @param {boolean} [fallbackToNetwork=true] Whether to attempt to get the
+     * response from the network if there's a precache miss.
+     * @return {module:workbox-routing~handlerCallback}
+     */
 
-              return fetch(request);
+    createHandler(fallbackToNetwork = true) {
+      return async ({ request }) => {
+        try {
+          const response = await this.matchPrecache(request);
+
+          if (response) {
+            return response;
+          } // This shouldn't normally happen, but there are edge cases:
+          // https://github.com/GoogleChrome/workbox/issues/1441
+
+          throw new WorkboxError('missing-precache-entry', {
+            cacheName: this._cacheName,
+            url: request instanceof Request ? request.url : request,
+          });
+        } catch (error) {
+          if (fallbackToNetwork) {
+            {
+              logger.debug(`Unable to respond with precached response. ` + `Falling back to network.`, error);
             }
 
-            throw error;
+            return fetch(request);
           }
-        };
-      }
-      /**
-       * Returns a function that looks up `url` in the precache (taking into
-       * account revision information), and returns the corresponding `Response`.
-       *
-       * If for an unexpected reason there is a cache miss when looking up `url`,
-       * this will fall back to retrieving the `Response` via `fetch()` when
-       * `fallbackToNetwork` is `true`.
-       *
-       * @param {string} url The precached URL which will be used to lookup the
-       * `Response`.
-       * @param {boolean} [fallbackToNetwork=true] Whether to attempt to get the
-       * response from the network if there's a precache miss.
-       * @return {module:workbox-routing~handlerCallback}
-       */
-
-
-      createHandlerBoundToURL(url, fallbackToNetwork = true) {
-        const cacheKey = this.getCacheKeyForURL(url);
-
-        if (!cacheKey) {
-          throw new WorkboxError('non-precached-url', {
-            url
-          });
+
+          throw error;
         }
+      };
+    }
+    /**
+     * Returns a function that looks up `url` in the precache (taking into
+     * account revision information), and returns the corresponding `Response`.
+     *
+     * If for an unexpected reason there is a cache miss when looking up `url`,
+     * this will fall back to retrieving the `Response` via `fetch()` when
+     * `fallbackToNetwork` is `true`.
+     *
+     * @param {string} url The precached URL which will be used to lookup the
+     * `Response`.
+     * @param {boolean} [fallbackToNetwork=true] Whether to attempt to get the
+     * response from the network if there's a precache miss.
+     * @return {module:workbox-routing~handlerCallback}
+     */
 
-        const handler = this.createHandler(fallbackToNetwork);
-        const request = new Request(url);
-        return () => handler({
-          request
+    createHandlerBoundToURL(url, fallbackToNetwork = true) {
+      const cacheKey = this.getCacheKeyForURL(url);
+
+      if (!cacheKey) {
+        throw new WorkboxError('non-precached-url', {
+          url,
         });
       }
 
+      const handler = this.createHandler(fallbackToNetwork);
+      const request = new Request(url);
+      return () =>
+        handler({
+          request,
+        });
     }
+  }
 
-    /*
+  /*
       Copyright 2019 Google LLC
 
       Use of this source code is governed by an MIT-style
       license that can be found in the LICENSE file or at
       https://opensource.org/licenses/MIT.
     */
-    let precacheController;
-    /**
-     * @return {PrecacheController}
-     * @private
-     */
-
-    const getOrCreatePrecacheController = () => {
-      if (!precacheController) {
-        precacheController = new PrecacheController();
-      }
+  let precacheController;
+  /**
+   * @return {PrecacheController}
+   * @private
+   */
+
+  const getOrCreatePrecacheController = () => {
+    if (!precacheController) {
+      precacheController = new PrecacheController();
+    }
 
-      return precacheController;
-    };
+    return precacheController;
+  };
 
-    /*
+  /*
       Copyright 2018 Google LLC
 
       Use of this source code is governed by an MIT-style
       license that can be found in the LICENSE file or at
       https://opensource.org/licenses/MIT.
     */
-    /**
-     * Removes any URL search parameters that should be ignored.
-     *
-     * @param {URL} urlObject The original URL.
-     * @param {Array<RegExp>} ignoreURLParametersMatching RegExps to test against
-     * each search parameter name. Matches mean that the search parameter should be
-     * ignored.
-     * @return {URL} The URL with any ignored search parameters removed.
-     *
-     * @private
-     * @memberof module:workbox-precaching
-     */
-
-    function removeIgnoredSearchParams(urlObject, ignoreURLParametersMatching = []) {
-      // Convert the iterable into an array at the start of the loop to make sure
-      // deletion doesn't mess up iteration.
-      for (const paramName of [...urlObject.searchParams.keys()]) {
-        if (ignoreURLParametersMatching.some(regExp => regExp.test(paramName))) {
-          urlObject.searchParams.delete(paramName);
-        }
+  /**
+   * Removes any URL search parameters that should be ignored.
+   *
+   * @param {URL} urlObject The original URL.
+   * @param {Array<RegExp>} ignoreURLParametersMatching RegExps to test against
+   * each search parameter name. Matches mean that the search parameter should be
+   * ignored.
+   * @return {URL} The URL with any ignored search parameters removed.
+   *
+   * @private
+   * @memberof module:workbox-precaching
+   */
+
+  function removeIgnoredSearchParams(urlObject, ignoreURLParametersMatching = []) {
+    // Convert the iterable into an array at the start of the loop to make sure
+    // deletion doesn't mess up iteration.
+    for (const paramName of [...urlObject.searchParams.keys()]) {
+      if (ignoreURLParametersMatching.some(regExp => regExp.test(paramName))) {
+        urlObject.searchParams.delete(paramName);
       }
-
-      return urlObject;
     }
 
-    /*
+    return urlObject;
+  }
+
+  /*
       Copyright 2019 Google LLC
 
       Use of this source code is governed by an MIT-style
       license that can be found in the LICENSE file or at
       https://opensource.org/licenses/MIT.
     */
-    /**
-     * Generator function that yields possible variations on the original URL to
-     * check, one at a time.
-     *
-     * @param {string} url
-     * @param {Object} options
-     *
-     * @private
-     * @memberof module:workbox-precaching
-     */
-
-    function* generateURLVariations(url, {
-      ignoreURLParametersMatching,
-      directoryIndex,
-      cleanURLs,
-      urlManipulation
-    } = {}) {
-      const urlObject = new URL(url, location.href);
-      urlObject.hash = '';
-      yield urlObject.href;
-      const urlWithoutIgnoredParams = removeIgnoredSearchParams(urlObject, ignoreURLParametersMatching);
-      yield urlWithoutIgnoredParams.href;
-
-      if (directoryIndex && urlWithoutIgnoredParams.pathname.endsWith('/')) {
-        const directoryURL = new URL(urlWithoutIgnoredParams.href);
-        directoryURL.pathname += directoryIndex;
-        yield directoryURL.href;
-      }
+  /**
+   * Generator function that yields possible variations on the original URL to
+   * check, one at a time.
+   *
+   * @param {string} url
+   * @param {Object} options
+   *
+   * @private
+   * @memberof module:workbox-precaching
+   */
+
+  function* generateURLVariations(
+    url,
+    { ignoreURLParametersMatching, directoryIndex, cleanURLs, urlManipulation } = {}
+  ) {
+    const urlObject = new URL(url, location.href);
+    urlObject.hash = '';
+    yield urlObject.href;
+    const urlWithoutIgnoredParams = removeIgnoredSearchParams(urlObject, ignoreURLParametersMatching);
+    yield urlWithoutIgnoredParams.href;
+
+    if (directoryIndex && urlWithoutIgnoredParams.pathname.endsWith('/')) {
+      const directoryURL = new URL(urlWithoutIgnoredParams.href);
+      directoryURL.pathname += directoryIndex;
+      yield directoryURL.href;
+    }
 
-      if (cleanURLs) {
-        const cleanURL = new URL(urlWithoutIgnoredParams.href);
-        cleanURL.pathname += '.html';
-        yield cleanURL.href;
-      }
+    if (cleanURLs) {
+      const cleanURL = new URL(urlWithoutIgnoredParams.href);
+      cleanURL.pathname += '.html';
+      yield cleanURL.href;
+    }
 
-      if (urlManipulation) {
-        const additionalURLs = urlManipulation({
-          url: urlObject
-        });
+    if (urlManipulation) {
+      const additionalURLs = urlManipulation({
+        url: urlObject,
+      });
 
-        for (const urlToAttempt of additionalURLs) {
-          yield urlToAttempt.href;
-        }
+      for (const urlToAttempt of additionalURLs) {
+        yield urlToAttempt.href;
       }
     }
+  }
 
-    /*
+  /*
       Copyright 2019 Google LLC
 
       Use of this source code is governed by an MIT-style
       license that can be found in the LICENSE file or at
       https://opensource.org/licenses/MIT.
     */
-    /**
-     * This function will take the request URL and manipulate it based on the
-     * configuration options.
-     *
-     * @param {string} url
-     * @param {Object} options
-     * @return {string} Returns the URL in the cache that matches the request,
-     * if possible.
-     *
-     * @private
-     */
-
-    const getCacheKeyForURL = (url, options) => {
-      const precacheController = getOrCreatePrecacheController();
-      const urlsToCacheKeys = precacheController.getURLsToCacheKeys();
-
-      for (const possibleURL of generateURLVariations(url, options)) {
-        const possibleCacheKey = urlsToCacheKeys.get(possibleURL);
-
-        if (possibleCacheKey) {
-          return possibleCacheKey;
-        }
+  /**
+   * This function will take the request URL and manipulate it based on the
+   * configuration options.
+   *
+   * @param {string} url
+   * @param {Object} options
+   * @return {string} Returns the URL in the cache that matches the request,
+   * if possible.
+   *
+   * @private
+   */
+
+  const getCacheKeyForURL = (url, options) => {
+    const precacheController = getOrCreatePrecacheController();
+    const urlsToCacheKeys = precacheController.getURLsToCacheKeys();
+
+    for (const possibleURL of generateURLVariations(url, options)) {
+      const possibleCacheKey = urlsToCacheKeys.get(possibleURL);
+
+      if (possibleCacheKey) {
+        return possibleCacheKey;
       }
-    };
+    }
+  };
 
-    /*
+  /*
       Copyright 2019 Google LLC
 
       Use of this source code is governed by an MIT-style
       license that can be found in the LICENSE file or at
       https://opensource.org/licenses/MIT.
     */
-    /**
-     * Adds a `fetch` listener to the service worker that will
-     * respond to
-     * [network requests]{@link https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API/Using_Service_Workers#Custom_responses_to_requests}
-     * with precached assets.
-     *
-     * Requests for assets that aren't precached, the `FetchEvent` will not be
-     * responded to, allowing the event to fall through to other `fetch` event
-     * listeners.
-     *
-     * NOTE: when called more than once this method will replace the previously set
-     * configuration options. Calling it more than once is not recommended outside
-     * of tests.
-     *
-     * @private
-     * @param {Object} [options]
-     * @param {string} [options.directoryIndex=index.html] The `directoryIndex` will
-     * check cache entries for a URLs ending with '/' to see if there is a hit when
-     * appending the `directoryIndex` value.
-     * @param {Array<RegExp>} [options.ignoreURLParametersMatching=[/^utm_/]] An
-     * array of regex's to remove search params when looking for a cache match.
-     * @param {boolean} [options.cleanURLs=true] The `cleanURLs` option will
-     * check the cache for the URL with a `.html` added to the end of the end.
-     * @param {workbox.precaching~urlManipulation} [options.urlManipulation]
-     * This is a function that should take a URL and return an array of
-     * alternative URLs that should be checked for precache matches.
-     */
-
-    const addFetchListener = ({
-      ignoreURLParametersMatching = [/^utm_/],
-      directoryIndex = 'index.html',
-      cleanURLs = true,
-      urlManipulation
-    } = {}) => {
-      const cacheName = cacheNames.getPrecacheName(); // See https://github.com/Microsoft/TypeScript/issues/28357#issuecomment-436484705
-
-      self.addEventListener('fetch', event => {
-        const precachedURL = getCacheKeyForURL(event.request.url, {
-          cleanURLs,
-          directoryIndex,
-          ignoreURLParametersMatching,
-          urlManipulation
-        });
-
-        if (!precachedURL) {
-          {
-            logger.debug(`Precaching did not find a match for ` + getFriendlyURL(event.request.url));
-          }
+  /**
+   * Adds a `fetch` listener to the service worker that will
+   * respond to
+   * [network requests]{@link https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API/Using_Service_Workers#Custom_responses_to_requests}
+   * with precached assets.
+   *
+   * Requests for assets that aren't precached, the `FetchEvent` will not be
+   * responded to, allowing the event to fall through to other `fetch` event
+   * listeners.
+   *
+   * NOTE: when called more than once this method will replace the previously set
+   * configuration options. Calling it more than once is not recommended outside
+   * of tests.
+   *
+   * @private
+   * @param {Object} [options]
+   * @param {string} [options.directoryIndex=index.html] The `directoryIndex` will
+   * check cache entries for a URLs ending with '/' to see if there is a hit when
+   * appending the `directoryIndex` value.
+   * @param {Array<RegExp>} [options.ignoreURLParametersMatching=[/^utm_/]] An
+   * array of regex's to remove search params when looking for a cache match.
+   * @param {boolean} [options.cleanURLs=true] The `cleanURLs` option will
+   * check the cache for the URL with a `.html` added to the end of the end.
+   * @param {workbox.precaching~urlManipulation} [options.urlManipulation]
+   * This is a function that should take a URL and return an array of
+   * alternative URLs that should be checked for precache matches.
+   */
+
+  const addFetchListener = ({
+    ignoreURLParametersMatching = [/^utm_/],
+    directoryIndex = 'index.html',
+    cleanURLs = true,
+    urlManipulation,
+  } = {}) => {
+    const cacheName = cacheNames.getPrecacheName(); // See https://github.com/Microsoft/TypeScript/issues/28357#issuecomment-436484705
+
+    self.addEventListener('fetch', event => {
+      const precachedURL = getCacheKeyForURL(event.request.url, {
+        cleanURLs,
+        directoryIndex,
+        ignoreURLParametersMatching,
+        urlManipulation,
+      });
 
-          return;
+      if (!precachedURL) {
+        {
+          logger.debug(`Precaching did not find a match for ` + getFriendlyURL(event.request.url));
         }
 
-        let responsePromise = self.caches.open(cacheName).then(cache => {
+        return;
+      }
+
+      let responsePromise = self.caches
+        .open(cacheName)
+        .then(cache => {
           return cache.match(precachedURL);
-        }).then(cachedResponse => {
+        })
+        .then(cachedResponse => {
           if (cachedResponse) {
             return cachedResponse;
           } // Fall back to the network if we don't have a cached response
           // (perhaps due to manual cache cleanup).
 
-
           {
-            logger.warn(`The precached response for ` + `${getFriendlyURL(precachedURL)} in ${cacheName} was not found. ` + `Falling back to the network instead.`);
+            logger.warn(
+              `The precached response for ` +
+                `${getFriendlyURL(precachedURL)} in ${cacheName} was not found. ` +
+                `Falling back to the network instead.`
+            );
           }
 
           return fetch(precachedURL);
         });
 
-        {
-          responsePromise = responsePromise.then(response => {
-            // Workbox is going to handle the route.
-            // print the routing details to the console.
-            logger.groupCollapsed(`Precaching is responding to: ` + getFriendlyURL(event.request.url));
-            logger.log(`Serving the precached url: ${precachedURL}`);
-            logger.groupCollapsed(`View request details here.`);
-            logger.log(event.request);
-            logger.groupEnd();
-            logger.groupCollapsed(`View response details here.`);
-            logger.log(response);
-            logger.groupEnd();
-            logger.groupEnd();
-            return response;
-          });
-        }
+      {
+        responsePromise = responsePromise.then(response => {
+          // Workbox is going to handle the route.
+          // print the routing details to the console.
+          logger.groupCollapsed(`Precaching is responding to: ` + getFriendlyURL(event.request.url));
+          logger.log(`Serving the precached url: ${precachedURL}`);
+          logger.groupCollapsed(`View request details here.`);
+          logger.log(event.request);
+          logger.groupEnd();
+          logger.groupCollapsed(`View response details here.`);
+          logger.log(response);
+          logger.groupEnd();
+          logger.groupEnd();
+          return response;
+        });
+      }
 
-        event.respondWith(responsePromise);
-      });
-    };
+      event.respondWith(responsePromise);
+    });
+  };
 
-    /*
+  /*
       Copyright 2019 Google LLC
       Use of this source code is governed by an MIT-style
       license that can be found in the LICENSE file or at
       https://opensource.org/licenses/MIT.
     */
-    let listenerAdded = false;
-    /**
-     * Add a `fetch` listener to the service worker that will
-     * respond to
-     * [network requests]{@link https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API/Using_Service_Workers#Custom_responses_to_requests}
-     * with precached assets.
-     *
-     * Requests for assets that aren't precached, the `FetchEvent` will not be
-     * responded to, allowing the event to fall through to other `fetch` event
-     * listeners.
-     *
-     * @param {Object} [options]
-     * @param {string} [options.directoryIndex=index.html] The `directoryIndex` will
-     * check cache entries for a URLs ending with '/' to see if there is a hit when
-     * appending the `directoryIndex` value.
-     * @param {Array<RegExp>} [options.ignoreURLParametersMatching=[/^utm_/]] An
-     * array of regex's to remove search params when looking for a cache match.
-     * @param {boolean} [options.cleanURLs=true] The `cleanURLs` option will
-     * check the cache for the URL with a `.html` added to the end of the end.
-     * @param {module:workbox-precaching~urlManipulation} [options.urlManipulation]
-     * This is a function that should take a URL and return an array of
-     * alternative URLs that should be checked for precache matches.
-     *
-     * @memberof module:workbox-precaching
-     */
-
-    function addRoute(options) {
-      if (!listenerAdded) {
-        addFetchListener(options);
-        listenerAdded = true;
-      }
+  let listenerAdded = false;
+  /**
+   * Add a `fetch` listener to the service worker that will
+   * respond to
+   * [network requests]{@link https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API/Using_Service_Workers#Custom_responses_to_requests}
+   * with precached assets.
+   *
+   * Requests for assets that aren't precached, the `FetchEvent` will not be
+   * responded to, allowing the event to fall through to other `fetch` event
+   * listeners.
+   *
+   * @param {Object} [options]
+   * @param {string} [options.directoryIndex=index.html] The `directoryIndex` will
+   * check cache entries for a URLs ending with '/' to see if there is a hit when
+   * appending the `directoryIndex` value.
+   * @param {Array<RegExp>} [options.ignoreURLParametersMatching=[/^utm_/]] An
+   * array of regex's to remove search params when looking for a cache match.
+   * @param {boolean} [options.cleanURLs=true] The `cleanURLs` option will
+   * check the cache for the URL with a `.html` added to the end of the end.
+   * @param {module:workbox-precaching~urlManipulation} [options.urlManipulation]
+   * This is a function that should take a URL and return an array of
+   * alternative URLs that should be checked for precache matches.
+   *
+   * @memberof module:workbox-precaching
+   */
+
+  function addRoute(options) {
+    if (!listenerAdded) {
+      addFetchListener(options);
+      listenerAdded = true;
     }
+  }
 
-    /*
+  /*
       Copyright 2019 Google LLC
 
       Use of this source code is governed by an MIT-style
       license that can be found in the LICENSE file or at
       https://opensource.org/licenses/MIT.
     */
-    const plugins = [];
-    const precachePlugins = {
-      /*
-       * @return {Array}
-       * @private
-       */
-      get() {
-        return plugins;
-      },
-
-      /*
-       * @param {Array} newPlugins
-       * @private
-       */
-      add(newPlugins) {
-        plugins.push(...newPlugins);
-      }
-
-    };
+  const plugins = [];
+  const precachePlugins = {
+    /*
+     * @return {Array}
+     * @private
+     */
+    get() {
+      return plugins;
+    },
 
     /*
+     * @param {Array} newPlugins
+     * @private
+     */
+    add(newPlugins) {
+      plugins.push(...newPlugins);
+    },
+  };
+
+  /*
       Copyright 2019 Google LLC
 
       Use of this source code is governed by an MIT-style
@@ -2969,158 +2916,167 @@ define("./workbox-e536220e.js",['exports'], function (exports) { 'use strict';
       https://opensource.org/licenses/MIT.
     */
 
-    const installListener = event => {
-      const precacheController = getOrCreatePrecacheController();
-      const plugins = precachePlugins.get();
-      event.waitUntil(precacheController.install({
-        event,
-        plugins
-      }).catch(error => {
-        {
-          logger.error(`Service worker installation failed. It will ` + `be retried automatically during the next navigation.`);
-        } // Re-throw the error to ensure installation fails.
-
-
-        throw error;
-      }));
-    };
-
-    const activateListener = event => {
-      const precacheController = getOrCreatePrecacheController();
-      event.waitUntil(precacheController.activate());
-    };
-    /**
-     * Adds items to the precache list, removing any duplicates and
-     * stores the files in the
-     * ["precache cache"]{@link module:workbox-core.cacheNames} when the service
-     * worker installs.
-     *
-     * This method can be called multiple times.
-     *
-     * Please note: This method **will not** serve any of the cached files for you.
-     * It only precaches files. To respond to a network request you call
-     * [addRoute()]{@link module:workbox-precaching.addRoute}.
-     *
-     * If you have a single array of files to precache, you can just call
-     * [precacheAndRoute()]{@link module:workbox-precaching.precacheAndRoute}.
-     *
-     * @param {Array<Object|string>} [entries=[]] Array of entries to precache.
-     *
-     * @memberof module:workbox-precaching
-     */
-
-
-    function precache(entries) {
-      const precacheController = getOrCreatePrecacheController();
-      precacheController.addToCacheList(entries);
+  const installListener = event => {
+    const precacheController = getOrCreatePrecacheController();
+    const plugins = precachePlugins.get();
+    event.waitUntil(
+      precacheController
+        .install({
+          event,
+          plugins,
+        })
+        .catch(error => {
+          {
+            logger.error(
+              `Service worker installation failed. It will ` + `be retried automatically during the next navigation.`
+            );
+          } // Re-throw the error to ensure installation fails.
 
-      if (entries.length > 0) {
-        // NOTE: these listeners will only be added once (even if the `precache()`
-        // method is called multiple times) because event listeners are implemented
-        // as a set, where each listener must be unique.
-        // See https://github.com/Microsoft/TypeScript/issues/28357#issuecomment-436484705
-        self.addEventListener('install', installListener);
-        self.addEventListener('activate', activateListener);
-      }
+          throw error;
+        })
+    );
+  };
+
+  const activateListener = event => {
+    const precacheController = getOrCreatePrecacheController();
+    event.waitUntil(precacheController.activate());
+  };
+  /**
+   * Adds items to the precache list, removing any duplicates and
+   * stores the files in the
+   * ["precache cache"]{@link module:workbox-core.cacheNames} when the service
+   * worker installs.
+   *
+   * This method can be called multiple times.
+   *
+   * Please note: This method **will not** serve any of the cached files for you.
+   * It only precaches files. To respond to a network request you call
+   * [addRoute()]{@link module:workbox-precaching.addRoute}.
+   *
+   * If you have a single array of files to precache, you can just call
+   * [precacheAndRoute()]{@link module:workbox-precaching.precacheAndRoute}.
+   *
+   * @param {Array<Object|string>} [entries=[]] Array of entries to precache.
+   *
+   * @memberof module:workbox-precaching
+   */
+
+  function precache(entries) {
+    const precacheController = getOrCreatePrecacheController();
+    precacheController.addToCacheList(entries);
+
+    if (entries.length > 0) {
+      // NOTE: these listeners will only be added once (even if the `precache()`
+      // method is called multiple times) because event listeners are implemented
+      // as a set, where each listener must be unique.
+      // See https://github.com/Microsoft/TypeScript/issues/28357#issuecomment-436484705
+      self.addEventListener('install', installListener);
+      self.addEventListener('activate', activateListener);
     }
+  }
 
-    /*
+  /*
       Copyright 2019 Google LLC
 
       Use of this source code is governed by an MIT-style
       license that can be found in the LICENSE file or at
       https://opensource.org/licenses/MIT.
     */
-    /**
-     * This method will add entries to the precache list and add a route to
-     * respond to fetch events.
-     *
-     * This is a convenience method that will call
-     * [precache()]{@link module:workbox-precaching.precache} and
-     * [addRoute()]{@link module:workbox-precaching.addRoute} in a single call.
-     *
-     * @param {Array<Object|string>} entries Array of entries to precache.
-     * @param {Object} [options] See
-     * [addRoute() options]{@link module:workbox-precaching.addRoute}.
-     *
-     * @memberof module:workbox-precaching
-     */
-
-    function precacheAndRoute(entries, options) {
-      precache(entries);
-      addRoute(options);
-    }
-
-    /*
+  /**
+   * This method will add entries to the precache list and add a route to
+   * respond to fetch events.
+   *
+   * This is a convenience method that will call
+   * [precache()]{@link module:workbox-precaching.precache} and
+   * [addRoute()]{@link module:workbox-precaching.addRoute} in a single call.
+   *
+   * @param {Array<Object|string>} entries Array of entries to precache.
+   * @param {Object} [options] See
+   * [addRoute() options]{@link module:workbox-precaching.addRoute}.
+   *
+   * @memberof module:workbox-precaching
+   */
+
+  function precacheAndRoute(entries, options) {
+    precache(entries);
+    addRoute(options);
+  }
+
+  /*
       Copyright 2018 Google LLC
 
       Use of this source code is governed by an MIT-style
       license that can be found in the LICENSE file or at
       https://opensource.org/licenses/MIT.
     */
-    const SUBSTRING_TO_FIND = '-precache-';
-    /**
-     * Cleans up incompatible precaches that were created by older versions of
-     * Workbox, by a service worker registered under the current scope.
-     *
-     * This is meant to be called as part of the `activate` event.
-     *
-     * This should be safe to use as long as you don't include `substringToFind`
-     * (defaulting to `-precache-`) in your non-precache cache names.
-     *
-     * @param {string} currentPrecacheName The cache name currently in use for
-     * precaching. This cache won't be deleted.
-     * @param {string} [substringToFind='-precache-'] Cache names which include this
-     * substring will be deleted (excluding `currentPrecacheName`).
-     * @return {Array<string>} A list of all the cache names that were deleted.
-     *
-     * @private
-     * @memberof module:workbox-precaching
-     */
-
-    const deleteOutdatedCaches = async (currentPrecacheName, substringToFind = SUBSTRING_TO_FIND) => {
-      const cacheNames = await self.caches.keys();
-      const cacheNamesToDelete = cacheNames.filter(cacheName => {
-        return cacheName.includes(substringToFind) && cacheName.includes(self.registration.scope) && cacheName !== currentPrecacheName;
-      });
-      await Promise.all(cacheNamesToDelete.map(cacheName => self.caches.delete(cacheName)));
-      return cacheNamesToDelete;
-    };
+  const SUBSTRING_TO_FIND = '-precache-';
+  /**
+   * Cleans up incompatible precaches that were created by older versions of
+   * Workbox, by a service worker registered under the current scope.
+   *
+   * This is meant to be called as part of the `activate` event.
+   *
+   * This should be safe to use as long as you don't include `substringToFind`
+   * (defaulting to `-precache-`) in your non-precache cache names.
+   *
+   * @param {string} currentPrecacheName The cache name currently in use for
+   * precaching. This cache won't be deleted.
+   * @param {string} [substringToFind='-precache-'] Cache names which include this
+   * substring will be deleted (excluding `currentPrecacheName`).
+   * @return {Array<string>} A list of all the cache names that were deleted.
+   *
+   * @private
+   * @memberof module:workbox-precaching
+   */
+
+  const deleteOutdatedCaches = async (currentPrecacheName, substringToFind = SUBSTRING_TO_FIND) => {
+    const cacheNames = await self.caches.keys();
+    const cacheNamesToDelete = cacheNames.filter(cacheName => {
+      return (
+        cacheName.includes(substringToFind) &&
+        cacheName.includes(self.registration.scope) &&
+        cacheName !== currentPrecacheName
+      );
+    });
+    await Promise.all(cacheNamesToDelete.map(cacheName => self.caches.delete(cacheName)));
+    return cacheNamesToDelete;
+  };
 
-    /*
+  /*
       Copyright 2019 Google LLC
 
       Use of this source code is governed by an MIT-style
       license that can be found in the LICENSE file or at
       https://opensource.org/licenses/MIT.
     */
-    /**
-     * Adds an `activate` event listener which will clean up incompatible
-     * precaches that were created by older versions of Workbox.
-     *
-     * @memberof module:workbox-precaching
-     */
-
-    function cleanupOutdatedCaches() {
-      // See https://github.com/Microsoft/TypeScript/issues/28357#issuecomment-436484705
-      self.addEventListener('activate', event => {
-        const cacheName = cacheNames.getPrecacheName();
-        event.waitUntil(deleteOutdatedCaches(cacheName).then(cachesDeleted => {
+  /**
+   * Adds an `activate` event listener which will clean up incompatible
+   * precaches that were created by older versions of Workbox.
+   *
+   * @memberof module:workbox-precaching
+   */
+
+  function cleanupOutdatedCaches() {
+    // See https://github.com/Microsoft/TypeScript/issues/28357#issuecomment-436484705
+    self.addEventListener('activate', event => {
+      const cacheName = cacheNames.getPrecacheName();
+      event.waitUntil(
+        deleteOutdatedCaches(cacheName).then(cachesDeleted => {
           {
             if (cachesDeleted.length > 0) {
               logger.log(`The following out-of-date precaches were cleaned up ` + `automatically:`, cachesDeleted);
             }
           }
-        }));
-      });
-    }
-
-    exports.NetworkOnly = NetworkOnly;
-    exports.cleanupOutdatedCaches = cleanupOutdatedCaches;
-    exports.clientsClaim = clientsClaim;
-    exports.precacheAndRoute = precacheAndRoute;
-    exports.registerRoute = registerRoute;
-    exports.skipWaiting = skipWaiting;
-
+        })
+      );
+    });
+  }
+
+  exports.NetworkOnly = NetworkOnly;
+  exports.cleanupOutdatedCaches = cleanupOutdatedCaches;
+  exports.clientsClaim = clientsClaim;
+  exports.precacheAndRoute = precacheAndRoute;
+  exports.registerRoute = registerRoute;
+  exports.skipWaiting = skipWaiting;
 });
 //# sourceMappingURL=workbox-e536220e.js.map
diff --git a/styles/global.css b/styles/global.css
index c218086..3e962ad 100644
--- a/styles/global.css
+++ b/styles/global.css
@@ -1,6 +1,6 @@
-@import "tailwindcss/base";
-@import "tailwindcss/components";
-@import "tailwindcss/utilities";
+@import 'tailwindcss/base';
+@import 'tailwindcss/components';
+@import 'tailwindcss/utilities';
 
 /* FONTS */
 
@@ -11,12 +11,11 @@
   font-weight: 400;
   font-display: swap;
   src: url('/fonts/roboto-slab-v12-latin-regular.eot'); /* IE9 Compat Modes */
-  src: local(''),
-       url('/fonts/roboto-slab-v12-latin-regular.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */
-       url('/fonts/roboto-slab-v12-latin-regular.woff2') format('woff2'), /* Super Modern Browsers */
-       url('/fonts/roboto-slab-v12-latin-regular.woff') format('woff'), /* Modern Browsers */
-       url('/fonts/roboto-slab-v12-latin-regular.ttf') format('truetype'), /* Safari, Android, iOS */
-       url('/fonts/roboto-slab-v12-latin-regular.svg#RobotoSlab') format('svg'); /* Legacy iOS */
+  src: local(''), url('/fonts/roboto-slab-v12-latin-regular.eot?#iefix') format('embedded-opentype'),
+    /* IE6-IE8 */ url('/fonts/roboto-slab-v12-latin-regular.woff2') format('woff2'),
+    /* Super Modern Browsers */ url('/fonts/roboto-slab-v12-latin-regular.woff') format('woff'),
+    /* Modern Browsers */ url('/fonts/roboto-slab-v12-latin-regular.ttf') format('truetype'),
+    /* Safari, Android, iOS */ url('/fonts/roboto-slab-v12-latin-regular.svg#RobotoSlab') format('svg'); /* Legacy iOS */
 }
 /* roboto-slab-500 - latin */
 @font-face {
@@ -25,12 +24,11 @@
   font-weight: 500;
   font-display: swap;
   src: url('/fonts/roboto-slab-v12-latin-500.eot'); /* IE9 Compat Modes */
-  src: local(''),
-       url('/fonts/roboto-slab-v12-latin-500.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */
-       url('/fonts/roboto-slab-v12-latin-500.woff2') format('woff2'), /* Super Modern Browsers */
-       url('/fonts/roboto-slab-v12-latin-500.woff') format('woff'), /* Modern Browsers */
-       url('/fonts/roboto-slab-v12-latin-500.ttf') format('truetype'), /* Safari, Android, iOS */
-       url('/fonts/roboto-slab-v12-latin-500.svg#RobotoSlab') format('svg'); /* Legacy iOS */
+  src: local(''), url('/fonts/roboto-slab-v12-latin-500.eot?#iefix') format('embedded-opentype'),
+    /* IE6-IE8 */ url('/fonts/roboto-slab-v12-latin-500.woff2') format('woff2'),
+    /* Super Modern Browsers */ url('/fonts/roboto-slab-v12-latin-500.woff') format('woff'),
+    /* Modern Browsers */ url('/fonts/roboto-slab-v12-latin-500.ttf') format('truetype'),
+    /* Safari, Android, iOS */ url('/fonts/roboto-slab-v12-latin-500.svg#RobotoSlab') format('svg'); /* Legacy iOS */
 }
 /* roboto-slab-600 - latin */
 @font-face {
@@ -39,12 +37,11 @@
   font-weight: 600;
   font-display: swap;
   src: url('/fonts/roboto-slab-v12-latin-600.eot'); /* IE9 Compat Modes */
-  src: local(''),
-       url('/fonts/roboto-slab-v12-latin-600.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */
-       url('/fonts/roboto-slab-v12-latin-600.woff2') format('woff2'), /* Super Modern Browsers */
-       url('/fonts/roboto-slab-v12-latin-600.woff') format('woff'), /* Modern Browsers */
-       url('/fonts/roboto-slab-v12-latin-600.ttf') format('truetype'), /* Safari, Android, iOS */
-       url('/fonts/roboto-slab-v12-latin-600.svg#RobotoSlab') format('svg'); /* Legacy iOS */
+  src: local(''), url('/fonts/roboto-slab-v12-latin-600.eot?#iefix') format('embedded-opentype'),
+    /* IE6-IE8 */ url('/fonts/roboto-slab-v12-latin-600.woff2') format('woff2'),
+    /* Super Modern Browsers */ url('/fonts/roboto-slab-v12-latin-600.woff') format('woff'),
+    /* Modern Browsers */ url('/fonts/roboto-slab-v12-latin-600.ttf') format('truetype'),
+    /* Safari, Android, iOS */ url('/fonts/roboto-slab-v12-latin-600.svg#RobotoSlab') format('svg'); /* Legacy iOS */
 }
 /* roboto-slab-700 - latin */
 @font-face {
@@ -53,12 +50,11 @@
   font-weight: 700;
   font-display: swap;
   src: url('/fonts/roboto-slab-v12-latin-700.eot'); /* IE9 Compat Modes */
-  src: local(''),
-       url('/fonts/roboto-slab-v12-latin-700.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */
-       url('/fonts/roboto-slab-v12-latin-700.woff2') format('woff2'), /* Super Modern Browsers */
-       url('/fonts/roboto-slab-v12-latin-700.woff') format('woff'), /* Modern Browsers */
-       url('/fonts/roboto-slab-v12-latin-700.ttf') format('truetype'), /* Safari, Android, iOS */
-       url('/fonts/roboto-slab-v12-latin-700.svg#RobotoSlab') format('svg'); /* Legacy iOS */
+  src: local(''), url('/fonts/roboto-slab-v12-latin-700.eot?#iefix') format('embedded-opentype'),
+    /* IE6-IE8 */ url('/fonts/roboto-slab-v12-latin-700.woff2') format('woff2'),
+    /* Super Modern Browsers */ url('/fonts/roboto-slab-v12-latin-700.woff') format('woff'),
+    /* Modern Browsers */ url('/fonts/roboto-slab-v12-latin-700.ttf') format('truetype'),
+    /* Safari, Android, iOS */ url('/fonts/roboto-slab-v12-latin-700.svg#RobotoSlab') format('svg'); /* Legacy iOS */
 }
 
 /* amaranth-regular - latin */
@@ -68,12 +64,11 @@
   font-weight: 400;
   font-display: swap;
   src: url('/fonts/amaranth-v11-latin-regular.eot'); /* IE9 Compat Modes */
-  src: local(''),
-       url('/fonts/amaranth-v11-latin-regular.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */
-       url('/fonts/amaranth-v11-latin-regular.woff2') format('woff2'), /* Super Modern Browsers */
-       url('/fonts/amaranth-v11-latin-regular.woff') format('woff'), /* Modern Browsers */
-       url('/fonts/amaranth-v11-latin-regular.ttf') format('truetype'), /* Safari, Android, iOS */
-       url('/fonts/amaranth-v11-latin-regular.svg#Amaranth') format('svg'); /* Legacy iOS */
+  src: local(''), url('/fonts/amaranth-v11-latin-regular.eot?#iefix') format('embedded-opentype'),
+    /* IE6-IE8 */ url('/fonts/amaranth-v11-latin-regular.woff2') format('woff2'),
+    /* Super Modern Browsers */ url('/fonts/amaranth-v11-latin-regular.woff') format('woff'),
+    /* Modern Browsers */ url('/fonts/amaranth-v11-latin-regular.ttf') format('truetype'),
+    /* Safari, Android, iOS */ url('/fonts/amaranth-v11-latin-regular.svg#Amaranth') format('svg'); /* Legacy iOS */
 }
 /* amaranth-700 - latin */
 @font-face {
@@ -82,40 +77,39 @@
   font-weight: 700;
   font-display: swap;
   src: url('/fonts/amaranth-v11-latin-700.eot'); /* IE9 Compat Modes */
-  src: local(''),
-       url('/fonts/amaranth-v11-latin-700.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */
-       url('/fonts/amaranth-v11-latin-700.woff2') format('woff2'), /* Super Modern Browsers */
-       url('/fonts/amaranth-v11-latin-700.woff') format('woff'), /* Modern Browsers */
-       url('/fonts/amaranth-v11-latin-700.ttf') format('truetype'), /* Safari, Android, iOS */
-       url('/fonts/amaranth-v11-latin-700.svg#Amaranth') format('svg'); /* Legacy iOS */
+  src: local(''), url('/fonts/amaranth-v11-latin-700.eot?#iefix') format('embedded-opentype'),
+    /* IE6-IE8 */ url('/fonts/amaranth-v11-latin-700.woff2') format('woff2'),
+    /* Super Modern Browsers */ url('/fonts/amaranth-v11-latin-700.woff') format('woff'),
+    /* Modern Browsers */ url('/fonts/amaranth-v11-latin-700.ttf') format('truetype'),
+    /* Safari, Android, iOS */ url('/fonts/amaranth-v11-latin-700.svg#Amaranth') format('svg'); /* Legacy iOS */
 }
 
 @layer utilities {
   @variants responsive {
-      .text-shadow {
-        text-shadow: 1px 1px 2px rgba(0,0,0,0.2);
-      }
-      .text-shadow-md {
-        text-shadow: 4px 4px 8px rgba(0,0,0,0.5);
-      }
-      .text-shadow-lg {
-        text-shadow: 15px 15px 30px rgba(0,0,0,0.5);
-      }
-      .text-shadow-none {
-        text-shadow: none;
-      }
+    .text-shadow {
+      text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.2);
+    }
+    .text-shadow-md {
+      text-shadow: 4px 4px 8px rgba(0, 0, 0, 0.5);
+    }
+    .text-shadow-lg {
+      text-shadow: 15px 15px 30px rgba(0, 0, 0, 0.5);
+    }
+    .text-shadow-none {
+      text-shadow: none;
+    }
   }
   @variants hover {
     .img-shadow {
-      filter: drop-shadow(0 0 0.3rem rgba(0,0,0,0.3));
+      filter: drop-shadow(0 0 0.3rem rgba(0, 0, 0, 0.3));
     }
     .img-shadow-sm {
-      filter: drop-shadow(0 0 0.2rem rgba(0,0,0,0.3));
+      filter: drop-shadow(0 0 0.2rem rgba(0, 0, 0, 0.3));
     }
     .img-shadow-none {
       filter: none;
     }
-  } 
+  }
 }
 
 body {
@@ -186,4 +180,4 @@ body {
 
 .react-markdown code::after {
   content: '\`';
-}
\ No newline at end of file
+}
diff --git a/tsconfig.json b/tsconfig.json
index 48ca14a..c5d53d8 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -1,11 +1,7 @@
 {
   "compilerOptions": {
     "target": "es5",
-    "lib": [
-      "dom",
-      "dom.iterable",
-      "esnext"
-    ],
+    "lib": ["dom", "dom.iterable", "esnext"],
     "allowJs": true,
     "skipLibCheck": true,
     "strict": false,
@@ -18,12 +14,6 @@
     "isolatedModules": true,
     "jsx": "preserve"
   },
-  "exclude": [
-    "node_modules"
-  ],
-  "include": [
-    "next-env.d.ts",
-    "**/*.ts",
-    "**/*.tsx"
-  ]
+  "exclude": ["node_modules"],
+  "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"]
 }
diff --git a/vercel.json b/vercel.json
index b8e76d8..718ff20 100644
--- a/vercel.json
+++ b/vercel.json
@@ -1,10 +1,10 @@
 {
-    "cleanUrls": true,
-    "trailingSlash": false,
-    "redirects": [
-      {
-        "source": "/twitter",
-        "destination": "https://twitter.com/scriptified_dev"
-      }
-    ]
-  }
\ No newline at end of file
+  "cleanUrls": true,
+  "trailingSlash": false,
+  "redirects": [
+    {
+      "source": "/twitter",
+      "destination": "https://twitter.com/scriptified_dev"
+    }
+  ]
+}

From 949a157f7a4c0276a666bc4d01809b6e47ad4871 Mon Sep 17 00:00:00 2001
From: Stefan Schneider <stefan@netshake.com>
Date: Sun, 3 Oct 2021 12:37:56 +0200
Subject: [PATCH 2/5] fix(eslint): Fixed eslint related issues

Added eslint rule overrides. Fixed return type issues.

ref #71
---
 .eslintrc.json                    | 16 +++++++++++++++-
 .vscode/settings.json             |  2 +-
 components/Curators.tsx           |  2 +-
 components/IssueItem.tsx          |  1 -
 components/LoadingContext.tsx     |  2 +-
 components/Quiz.tsx               |  2 +-
 components/common/ThemePicker.tsx |  1 +
 custom.d.ts                       |  2 +-
 global.d.ts                       |  2 +-
 hooks/useScrollPosition.ts        | 14 +++++++-------
 lib/gtag.ts                       |  4 ++--
 lib/issues.ts                     | 10 +++++++++-
 pages/api/subscribe.ts            |  4 +++-
 pages/issues/[id].tsx             |  2 +-
 pages/sitemap.xml.tsx             |  3 ++-
 pages/thanks.tsx                  |  2 +-
 theme/ThemeContext.tsx            |  4 ++--
 utils/index.ts                    |  4 ++--
 18 files changed, 51 insertions(+), 26 deletions(-)

diff --git a/.eslintrc.json b/.eslintrc.json
index b11c46b..2692d32 100644
--- a/.eslintrc.json
+++ b/.eslintrc.json
@@ -3,5 +3,19 @@
   "extends": ["next/core-web-vitals", "plugin:@typescript-eslint/recommended", "prettier"],
   "rules": {
     "prettier/prettier": "error"
-  }
+  },
+  "overrides": [
+    {
+      "files": ["pages/*.tsx"],
+      "rules": {
+        "@next/next/no-document-import-in-page": "off"
+      }
+    },
+    {
+      "files": ["**/*.js"],
+      "rules": {
+        "@typescript-eslint/no-var-requires": "off"
+      }
+    }
+  ]
 }
diff --git a/.vscode/settings.json b/.vscode/settings.json
index 1894e96..944b5e5 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -4,5 +4,5 @@
   },
   "editor.formatOnSave": true, // Tell VSCode to format files on save
   "editor.defaultFormatter": "esbenp.prettier-vscode",
-  "conventionalCommits.scopes": ["prettier"]
+  "conventionalCommits.scopes": ["prettier", "eslint"]
 }
diff --git a/components/Curators.tsx b/components/Curators.tsx
index 60acb59..fe0e097 100644
--- a/components/Curators.tsx
+++ b/components/Curators.tsx
@@ -5,7 +5,7 @@ import SocialLinks from './common/SocialLinks';
 import Text from './common/Text';
 import Markdown from './Markdown';
 
-function shuffle(array: any[]): any[] {
+function shuffle(array: unknown[]): unknown[] {
   const shuffledArray = JSON.parse(JSON.stringify(array));
   for (let i = array.length - 1; i > 0; i--) {
     const j = Math.floor(Math.random() * (i + 1));
diff --git a/components/IssueItem.tsx b/components/IssueItem.tsx
index 9adcd8a..da4680c 100644
--- a/components/IssueItem.tsx
+++ b/components/IssueItem.tsx
@@ -5,7 +5,6 @@ import { useThemeState } from '../theme/ThemeContext';
 const IssueItem = ({
   title,
   children,
-  icon,
   id,
 }: {
   title: string;
diff --git a/components/LoadingContext.tsx b/components/LoadingContext.tsx
index 5bfb793..988e7f0 100644
--- a/components/LoadingContext.tsx
+++ b/components/LoadingContext.tsx
@@ -20,7 +20,7 @@ const LoadingProvider = ({ children }: { children: React.ReactNode }): JSX.Eleme
       setTheme(randomTheme);
       sessionStorage.setItem('theme', randomTheme);
     }
-  }, []);
+  }, [setTheme]);
 
   return <LoadingStateContext.Provider value={loading}>{children}</LoadingStateContext.Provider>;
 };
diff --git a/components/Quiz.tsx b/components/Quiz.tsx
index 173394b..5d8bc5d 100644
--- a/components/Quiz.tsx
+++ b/components/Quiz.tsx
@@ -21,7 +21,7 @@ const QuizComponent = ({ quiz }: { quiz: Quiz }): JSX.Element => {
         setOption(option);
       }
     }
-  }, [router.isReady]);
+  }, [router.isReady, router.query.option, router.query.section]);
 
   const hasSelectedCorrectOption = selectedOptions.includes(quiz.answerId);
 
diff --git a/components/common/ThemePicker.tsx b/components/common/ThemePicker.tsx
index 3210160..99c5831 100644
--- a/components/common/ThemePicker.tsx
+++ b/components/common/ThemePicker.tsx
@@ -174,6 +174,7 @@ const ThemePicker = ({ textColor }: { textColor: string }): JSX.Element => {
                   key={theme}
                   id={theme}
                   role="option"
+                  aria-selected="true"
                   tabIndex={0}
                   value={theme}
                   className={`dropdown__list-item ${
diff --git a/custom.d.ts b/custom.d.ts
index 091d25e..dda274a 100644
--- a/custom.d.ts
+++ b/custom.d.ts
@@ -1,4 +1,4 @@
 declare module '*.svg' {
-  const content: any;
+  const content: unknown;
   export default content;
 }
diff --git a/global.d.ts b/global.d.ts
index d34d80e..a240d6d 100644
--- a/global.d.ts
+++ b/global.d.ts
@@ -1,4 +1,4 @@
 declare module 'remark-html' {
-  const html: any;
+  const html: unknown;
   export default html;
 }
diff --git a/hooks/useScrollPosition.ts b/hooks/useScrollPosition.ts
index 038f588..1fc0ba2 100644
--- a/hooks/useScrollPosition.ts
+++ b/hooks/useScrollPosition.ts
@@ -1,6 +1,6 @@
 /*
 Usage - to get scroll position of an element, hide/show element accrodingly
-Example: 
+Example:
 ```
 const [sticky, setSticky] = useState(false)
 
@@ -15,7 +15,7 @@ const [sticky, setSticky] = useState(false)
 Ref - https://gist.github.com/whoisryosuke/72d9979a44e01e95400760d98ca519e8
 */
 
-import { useRef, useLayoutEffect } from 'react';
+import { useRef, useLayoutEffect, RefObject } from 'react';
 
 const isBrowser = typeof window !== `undefined`;
 
@@ -24,9 +24,9 @@ interface IPosition {
   y: number;
 }
 
-type TEffect = ({ prevPos, currPos }: { prevPos: IPosition; currPos: IPosition }) => any;
+type TEffect = ({ prevPos, currPos }: { prevPos: IPosition; currPos: IPosition }) => unknown;
 
-function getScrollPosition({ element, useWindow }: { element?: any; useWindow?: boolean }) {
+function getScrollPosition({ element, useWindow }: { element?: RefObject<HTMLElement>; useWindow?: boolean }) {
   if (!isBrowser) return { x: 0, y: 0 };
 
   const target = element ? element.current : document.body;
@@ -37,11 +37,11 @@ function getScrollPosition({ element, useWindow }: { element?: any; useWindow?:
 
 export function useScrollPosition(
   effect: TEffect,
-  deps: Array<any>,
-  element?: any,
+  deps: Array<unknown>,
+  element?: RefObject<HTMLElement>,
   useWindow?: boolean,
   wait?: number
-) {
+): void {
   const position = useRef(getScrollPosition({ useWindow }));
 
   let throttleTimeout = null;
diff --git a/lib/gtag.ts b/lib/gtag.ts
index 2dd0672..de78033 100644
--- a/lib/gtag.ts
+++ b/lib/gtag.ts
@@ -1,7 +1,7 @@
 export const GA_TRACKING_ID = 'G-QDBR45S1X4';
 
 // https://developers.google.com/analytics/devguides/collection/gtagjs/pages
-export const pageview = (url: URL) => {
+export const pageview = (url: URL): void => {
   window.gtag('config', GA_TRACKING_ID, {
     page_path: url,
   });
@@ -15,7 +15,7 @@ type GTagEvent = {
 };
 
 // https://developers.google.com/analytics/devguides/collection/gtagjs/events
-export const event = ({ action, category, label, value }: GTagEvent) => {
+export const event = ({ action, category, label, value }: GTagEvent): void => {
   if (process.env.NODE_ENV === 'production') {
     window.gtag('event', action, {
       event_category: category,
diff --git a/lib/issues.ts b/lib/issues.ts
index b647492..87f4f22 100644
--- a/lib/issues.ts
+++ b/lib/issues.ts
@@ -191,7 +191,15 @@ export function mapToIssue(issue: IssueAPIResponse): Issue {
   return issueData;
 }
 
-export function getAllIssuesMeta(issues: IssueAPIResponse[]) {
+type IssuesMeta = {
+  title: string;
+  desc: string;
+  number: number;
+  dateOfPublishing: string;
+  imgURL: string;
+};
+
+export function getAllIssuesMeta(issues: IssueAPIResponse[]): IssuesMeta[] {
   return issues.map(issue => ({
     title: issue.title,
     desc: issue.description,
diff --git a/pages/api/subscribe.ts b/pages/api/subscribe.ts
index d5fbbfd..23a2943 100644
--- a/pages/api/subscribe.ts
+++ b/pages/api/subscribe.ts
@@ -6,7 +6,7 @@ type ResponseData = {
   msg: string;
 };
 
-export default async (req: NextApiRequest, res: NextApiResponse<ResponseData>) => {
+const subscribe = async (req: NextApiRequest, res: NextApiResponse<ResponseData>): Promise<void> => {
   const { body, method } = req;
   const { email, firstName } = body;
 
@@ -55,3 +55,5 @@ export default async (req: NextApiRequest, res: NextApiResponse<ResponseData>) =
     }
   }
 };
+
+export default subscribe;
diff --git a/pages/issues/[id].tsx b/pages/issues/[id].tsx
index 4485515..e40bbf2 100644
--- a/pages/issues/[id].tsx
+++ b/pages/issues/[id].tsx
@@ -40,7 +40,7 @@ export default function IssueComponent({ issueData }: { issueData: Issue }): JSX
     if (router.isReady && typeof router.query?.section === 'string') {
       document.getElementById(router.query.section)?.scrollIntoView({ behavior: 'smooth' });
     }
-  }, [router.isReady]);
+  }, [router.isReady, router.query.section]);
 
   if (router.isFallback) {
     return <></>;
diff --git a/pages/sitemap.xml.tsx b/pages/sitemap.xml.tsx
index be2d130..c3a1272 100644
--- a/pages/sitemap.xml.tsx
+++ b/pages/sitemap.xml.tsx
@@ -1,3 +1,4 @@
+import { NextApiResponse } from 'next';
 import React from 'react';
 import { siteConfig } from '../components/Layout';
 import { issueAPI } from '../lib/issues';
@@ -32,7 +33,7 @@ const createSitemap = (posts: SitemapData) => `<?xml version="1.0" encoding="UTF
     `;
 
 class Sitemap extends React.Component {
-  static async getInitialProps({ res }) {
+  static async getInitialProps({ res }: { res: NextApiResponse }): Promise<void> {
     const posts = await issueAPI.allIssuesReversed();
     const sitemapData = posts.map(post => ({ id: post.id, date: post.dateOfPublishing }));
 
diff --git a/pages/thanks.tsx b/pages/thanks.tsx
index c5c6ce3..ca66302 100644
--- a/pages/thanks.tsx
+++ b/pages/thanks.tsx
@@ -21,7 +21,7 @@ export default function ThankYou(): JSX.Element {
           Your subscription is confirmed. You will start receiving our weekly issues now onwards.
         </Text>
         <div className="flex items-center justify-center">
-          <Link href="/issues">
+          <Link href="/issues" passHref>
             <Button size="md" type="secondary" additionalStyles="mt-4">
               Read Previous Issues
             </Button>
diff --git a/theme/ThemeContext.tsx b/theme/ThemeContext.tsx
index e5da22b..96eac1f 100644
--- a/theme/ThemeContext.tsx
+++ b/theme/ThemeContext.tsx
@@ -23,7 +23,7 @@ function ThemeProvider({ children }: { children: React.ReactNode }): JSX.Element
   );
 }
 
-function useThemeState() {
+function useThemeState(): Theme {
   const context = React.useContext(ThemeStateContext);
   if (context === undefined) {
     throw new Error('useThemeState must be used within a ThemeProvider');
@@ -31,7 +31,7 @@ function useThemeState() {
   return context;
 }
 
-function useThemeDispatch() {
+function useThemeDispatch(): Action {
   const context = React.useContext(ThemeDispatchContext);
   if (context === undefined) {
     throw new Error('useThemeDispatch must be used within a ThemeProvider');
diff --git a/utils/index.ts b/utils/index.ts
index 58e7047..2db07cf 100644
--- a/utils/index.ts
+++ b/utils/index.ts
@@ -10,8 +10,8 @@
 `wait` milliseconds.
 */
 
-export function debounce<Params extends any[]>(
-  func: (...args: Params) => any,
+export function debounce<Params extends unknown[]>(
+  func: (...args: Params) => unknown,
   timeout: number
 ): (...args: Params) => void {
   let timer: NodeJS.Timeout;

From b6e9b15ad7fd3dd442087f5b55fecde588580d6f Mon Sep 17 00:00:00 2001
From: Stefan Schneider <stefan.schneider@gmx.net>
Date: Sun, 3 Oct 2021 16:28:59 +0200
Subject: [PATCH 3/5] Update components/common/ThemePicker.tsx

Co-authored-by: Prateek Surana <prateeksurana3255@gmail.com>
---
 components/common/ThemePicker.tsx | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/components/common/ThemePicker.tsx b/components/common/ThemePicker.tsx
index 99c5831..44f2e5c 100644
--- a/components/common/ThemePicker.tsx
+++ b/components/common/ThemePicker.tsx
@@ -174,7 +174,7 @@ const ThemePicker = ({ textColor }: { textColor: string }): JSX.Element => {
                   key={theme}
                   id={theme}
                   role="option"
-                  aria-selected="true"
+                  aria-selected={currentTheme === theme ? 'true' : 'false'}
                   tabIndex={0}
                   value={theme}
                   className={`dropdown__list-item ${

From ef790272785d15e36a6d27ff4bfe6aff02b27dcd Mon Sep 17 00:00:00 2001
From: Stefan Schneider <stefan.schneider@gmx.net>
Date: Mon, 4 Oct 2021 19:16:41 +0200
Subject: [PATCH 4/5] Delete useScrollPosition.ts

---
 hooks/useScrollPosition.ts | 71 --------------------------------------
 1 file changed, 71 deletions(-)
 delete mode 100644 hooks/useScrollPosition.ts

diff --git a/hooks/useScrollPosition.ts b/hooks/useScrollPosition.ts
deleted file mode 100644
index 1fc0ba2..0000000
--- a/hooks/useScrollPosition.ts
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
-Usage - to get scroll position of an element, hide/show element accrodingly
-Example:
-```
-const [sticky, setSticky] = useState(false)
-
-  useScrollPosition(
-    ({ prevPos, currPos }) => {
-      const isShow = currPos.y > prevPos.y
-      if (isShow !== sticky) setSticky(isShow)
-    },
-    [sticky]
-  )
-```
-Ref - https://gist.github.com/whoisryosuke/72d9979a44e01e95400760d98ca519e8
-*/
-
-import { useRef, useLayoutEffect, RefObject } from 'react';
-
-const isBrowser = typeof window !== `undefined`;
-
-interface IPosition {
-  x: number;
-  y: number;
-}
-
-type TEffect = ({ prevPos, currPos }: { prevPos: IPosition; currPos: IPosition }) => unknown;
-
-function getScrollPosition({ element, useWindow }: { element?: RefObject<HTMLElement>; useWindow?: boolean }) {
-  if (!isBrowser) return { x: 0, y: 0 };
-
-  const target = element ? element.current : document.body;
-  const position = target.getBoundingClientRect();
-
-  return useWindow ? { x: window.scrollX, y: window.scrollY } : { x: position.left, y: position.top };
-}
-
-export function useScrollPosition(
-  effect: TEffect,
-  deps: Array<unknown>,
-  element?: RefObject<HTMLElement>,
-  useWindow?: boolean,
-  wait?: number
-): void {
-  const position = useRef(getScrollPosition({ useWindow }));
-
-  let throttleTimeout = null;
-
-  const callBack = () => {
-    const currPos = getScrollPosition({ element, useWindow });
-    effect({ prevPos: position.current, currPos });
-    position.current = currPos;
-    throttleTimeout = null;
-  };
-
-  useLayoutEffect(() => {
-    const handleScroll = () => {
-      if (wait) {
-        if (throttleTimeout === null) {
-          throttleTimeout = setTimeout(callBack, wait);
-        }
-      } else {
-        callBack();
-      }
-    };
-
-    window.addEventListener('scroll', handleScroll);
-
-    return () => window.removeEventListener('scroll', handleScroll);
-  }, deps);
-}

From 5949b5020189dd95cc2e61d15dd876d9912ec464 Mon Sep 17 00:00:00 2001
From: Stefan Schneider <stefan.schneider@gmx.net>
Date: Tue, 5 Oct 2021 00:45:56 +0200
Subject: [PATCH 5/5] Update pages/thanks.tsx

---
 pages/thanks.tsx | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/pages/thanks.tsx b/pages/thanks.tsx
index ca66302..c5c6ce3 100644
--- a/pages/thanks.tsx
+++ b/pages/thanks.tsx
@@ -21,7 +21,7 @@ export default function ThankYou(): JSX.Element {
           Your subscription is confirmed. You will start receiving our weekly issues now onwards.
         </Text>
         <div className="flex items-center justify-center">
-          <Link href="/issues" passHref>
+          <Link href="/issues">
             <Button size="md" type="secondary" additionalStyles="mt-4">
               Read Previous Issues
             </Button>
