From 40a0535fc1bc12a24994b651f5e00b35995cbdda Mon Sep 17 00:00:00 2001
From: Yassine Doghri <yassine@doghri.fr>
Date: Fri, 4 Sep 2020 09:09:26 +0000
Subject: [PATCH] feat(public-ui): adapt public podcast and episode pages to
 wireframes

- adapt wireframes with responsive design
- refactor models methods to cache requests for faster queries
- update public controllers to cache pages while retaining analytics hits
- add platform links to podcast page
- add previous / next episodes in episode page
- update npm packages to latest versions

closes #30, #13
---
 app/Controllers/Admin/Contributor.php         |    2 +-
 app/Controllers/Admin/Episode.php             |    2 +-
 app/Controllers/Admin/Podcast.php             |   72 +-
 app/Controllers/Admin/PodcastSettings.php     |    8 +-
 app/Controllers/BaseController.php            |    2 +-
 app/Controllers/Episode.php                   |   46 +-
 app/Controllers/Podcast.php                   |  108 +-
 .../2020-06-05-170000_add_episodes.php        |   16 +
 ...0000_add_analytics_episodes_by_country.php |    1 +
 app/Entities/Episode.php                      |   43 +-
 app/Entities/Podcast.php                      |   57 +-
 app/Entities/User.php                         |    4 +-
 app/Helpers/id3_helper.php                    |    3 -
 app/Helpers/page_helper.php                   |    9 +-
 app/Helpers/rss_helper.php                    |    7 +-
 app/Language/en/Common.php                    |   15 +
 app/Language/en/Episode.php                   |    6 +
 app/Language/en/Podcast.php                   |    9 +-
 app/Models/CategoryModel.php                  |   22 +
 app/Models/EpisodeModel.php                   |  206 +-
 app/Models/LanguageModel.php                  |   20 +
 app/Models/PlatformModel.php                  |   49 +-
 app/Models/PodcastModel.php                   |   84 +-
 app/Models/UserModel.php                      |   27 +-
 app/Views/_assets/icons/arrow-left.svg        |    6 +
 app/Views/_assets/icons/arrow-right.svg       |    6 +
 app/Views/_assets/icons/rss.svg               |    6 +
 app/Views/episode.php                         |  121 +-
 app/Views/podcast.php                         |  187 +-
 package-lock.json                             | 2338 ++++++++---------
 package.json                                  |   46 +-
 tailwind.config.js                            |    4 +-
 32 files changed, 2058 insertions(+), 1474 deletions(-)
 create mode 100644 app/Language/en/Common.php
 create mode 100644 app/Views/_assets/icons/arrow-left.svg
 create mode 100644 app/Views/_assets/icons/arrow-right.svg
 create mode 100644 app/Views/_assets/icons/rss.svg

diff --git a/app/Controllers/Admin/Contributor.php b/app/Controllers/Admin/Contributor.php
index c892dc5c14..693746d003 100644
--- a/app/Controllers/Admin/Contributor.php
+++ b/app/Controllers/Admin/Contributor.php
@@ -26,7 +26,7 @@ class Contributor extends BaseController
 
     public function _remap($method, ...$params)
     {
-        $this->podcast = (new PodcastModel())->find($params[0]);
+        $this->podcast = (new PodcastModel())->getPodcastById($params[0]);
 
         if (count($params) > 1) {
             if (
diff --git a/app/Controllers/Admin/Episode.php b/app/Controllers/Admin/Episode.php
index 32ca7f3a6c..1979e64f9a 100644
--- a/app/Controllers/Admin/Episode.php
+++ b/app/Controllers/Admin/Episode.php
@@ -25,7 +25,7 @@ class Episode extends BaseController
 
     public function _remap($method, ...$params)
     {
-        $this->podcast = (new PodcastModel())->find($params[0]);
+        $this->podcast = (new PodcastModel())->getPodcastById($params[0]);
 
         if (count($params) > 1) {
             if (
diff --git a/app/Controllers/Admin/Podcast.php b/app/Controllers/Admin/Podcast.php
index adfdeaac19..f2a29ec590 100644
--- a/app/Controllers/Admin/Podcast.php
+++ b/app/Controllers/Admin/Podcast.php
@@ -25,7 +25,11 @@ class Podcast extends BaseController
     public function _remap($method, ...$params)
     {
         if (count($params) > 0) {
-            if (!($this->podcast = (new PodcastModel())->find($params[0]))) {
+            if (
+                !($this->podcast = (new PodcastModel())->getPodcastById(
+                    $params[0]
+                ))
+            ) {
                 throw \CodeIgniter\Exceptions\PageNotFoundException::forPageNotFound();
             }
         }
@@ -58,26 +62,8 @@ class Podcast extends BaseController
     {
         helper(['form', 'misc']);
 
-        $categories = (new CategoryModel())->findAll();
-        $languages = (new LanguageModel())->findAll();
-        $languageOptions = array_reduce(
-            $languages,
-            function ($result, $language) {
-                $result[$language->code] = $language->native_name;
-                return $result;
-            },
-            []
-        );
-        $categoryOptions = array_reduce(
-            $categories,
-            function ($result, $category) {
-                $result[$category->id] = lang(
-                    'Podcast.category_options.' . $category->code
-                );
-                return $result;
-            },
-            []
-        );
+        $languageOptions = (new LanguageModel())->getLanguageOptions();
+        $categoryOptions = (new CategoryModel())->getCategoryOptions();
 
         $data = [
             'languageOptions' => $languageOptions,
@@ -157,26 +143,8 @@ class Podcast extends BaseController
     {
         helper(['form', 'misc']);
 
-        $categories = (new CategoryModel())->findAll();
-        $languages = (new LanguageModel())->findAll();
-        $languageOptions = array_reduce(
-            $languages,
-            function ($result, $language) {
-                $result[$language->code] = $language->native_name;
-                return $result;
-            },
-            []
-        );
-        $categoryOptions = array_reduce(
-            $categories,
-            function ($result, $category) {
-                $result[$category->id] = lang(
-                    'Podcast.category_options.' . $category->code
-                );
-                return $result;
-            },
-            []
-        );
+        $languageOptions = (new LanguageModel())->getLanguageOptions();
+        $categoryOptions = (new CategoryModel())->getCategoryOptions();
 
         $data = [
             'languageOptions' => $languageOptions,
@@ -373,26 +341,8 @@ class Podcast extends BaseController
     {
         helper('form');
 
-        $categories = (new CategoryModel())->findAll();
-        $languages = (new LanguageModel())->findAll();
-        $languageOptions = array_reduce(
-            $languages,
-            function ($result, $language) {
-                $result[$language->code] = $language->native_name;
-                return $result;
-            },
-            []
-        );
-        $categoryOptions = array_reduce(
-            $categories,
-            function ($result, $category) {
-                $result[$category->id] = lang(
-                    'Podcast.category_options.' . $category->code
-                );
-                return $result;
-            },
-            []
-        );
+        $languageOptions = (new LanguageModel())->getLanguageOptions();
+        $categoryOptions = (new CategoryModel())->getCategoryOptions();
 
         $data = [
             'podcast' => $this->podcast,
diff --git a/app/Controllers/Admin/PodcastSettings.php b/app/Controllers/Admin/PodcastSettings.php
index 012128b0ef..f4b65a8935 100644
--- a/app/Controllers/Admin/PodcastSettings.php
+++ b/app/Controllers/Admin/PodcastSettings.php
@@ -21,7 +21,9 @@ class PodcastSettings extends BaseController
 
     public function _remap($method, ...$params)
     {
-        if (!($this->podcast = (new PodcastModel())->find($params[0]))) {
+        if (
+            !($this->podcast = (new PodcastModel())->getPodcastById($params[0]))
+        ) {
             throw \CodeIgniter\Exceptions\PageNotFoundException::forPageNotFound();
         }
         unset($params[0]);
@@ -40,7 +42,9 @@ class PodcastSettings extends BaseController
 
         $data = [
             'podcast' => $this->podcast,
-            'platforms' => (new PlatformModel())->getPlatformsWithLinks(),
+            'platforms' => (new PlatformModel())->getPlatformsWithLinks(
+                $this->podcast->id
+            ),
         ];
 
         replace_breadcrumb_params([0 => $this->podcast->title]);
diff --git a/app/Controllers/BaseController.php b/app/Controllers/BaseController.php
index 895838ca79..ab5eef7da6 100644
--- a/app/Controllers/BaseController.php
+++ b/app/Controllers/BaseController.php
@@ -26,7 +26,7 @@ class BaseController extends Controller
      *
      * @var array
      */
-    protected $helpers = ['analytics'];
+    protected $helpers = ['analytics', 'svg'];
 
     /**
      * Constructor.
diff --git a/app/Controllers/Episode.php b/app/Controllers/Episode.php
index 657a161d1c..a0e0dfa2cb 100644
--- a/app/Controllers/Episode.php
+++ b/app/Controllers/Episode.php
@@ -25,18 +25,14 @@ class Episode extends BaseController
 
     public function _remap($method, ...$params)
     {
-        $this->podcast = (new PodcastModel())
-            ->where('name', $params[0])
-            ->first();
+        $this->podcast = (new PodcastModel())->getPodcastByName($params[0]);
 
         if (
             count($params) > 1 &&
-            !($this->episode = (new EpisodeModel())
-                ->where([
-                    'podcast_id' => $this->podcast->id,
-                    'slug' => $params[1],
-                ])
-                ->first())
+            !($this->episode = (new EpisodeModel())->getEpisodeBySlug(
+                $this->podcast->id,
+                $params[1]
+            ))
         ) {
             throw \CodeIgniter\Exceptions\PageNotFoundException::forPageNotFound();
         }
@@ -46,15 +42,31 @@ class Episode extends BaseController
 
     public function index()
     {
-        // The page cache is set to a decade so it is deleted manually upon podcast update
-        $this->cachePage(DECADE);
+        self::triggerWebpageHit($this->episode->podcast_id);
 
-        self::triggerWebpageHit($this->podcast->id);
+        if (
+            !($cachedView = cache(
+                "page_podcast{$this->episode->podcast_id}_episode{$this->episode->id}"
+            ))
+        ) {
+            $previousNextEpisodes = (new EpisodeModel())->getPreviousNextEpisodes(
+                $this->episode,
+                $this->podcast->type
+            );
+
+            $data = [
+                'previousEpisode' => $previousNextEpisodes['previous'],
+                'nextEpisode' => $previousNextEpisodes['next'],
+                'episode' => $this->episode,
+            ];
+
+            // The page cache is set to a decade so it is deleted manually upon podcast update
+            return view('episode', $data, [
+                'cache' => DECADE,
+                'cache_name' => "page_podcast{$this->episode->podcast_id}_episode{$this->episode->id}",
+            ]);
+        }
 
-        $data = [
-            'podcast' => $this->podcast,
-            'episode' => $this->episode,
-        ];
-        return view('episode', $data);
+        return $cachedView;
     }
 }
diff --git a/app/Controllers/Podcast.php b/app/Controllers/Podcast.php
index d867540d01..27892cdb61 100644
--- a/app/Controllers/Podcast.php
+++ b/app/Controllers/Podcast.php
@@ -8,6 +8,7 @@
 
 namespace App\Controllers;
 
+use App\Models\EpisodeModel;
 use App\Models\PodcastModel;
 
 class Podcast extends BaseController
@@ -21,9 +22,9 @@ class Podcast extends BaseController
     {
         if (count($params) > 0) {
             if (
-                !($this->podcast = (new PodcastModel())
-                    ->where('name', $params[0])
-                    ->first())
+                !($this->podcast = (new PodcastModel())->getPodcastByName(
+                    $params[0]
+                ))
             ) {
                 throw \CodeIgniter\Exceptions\PageNotFoundException::forPageNotFound();
             }
@@ -34,15 +35,100 @@ class Podcast extends BaseController
 
     public function index()
     {
-        // The page cache is set to a decade so it is deleted manually upon podcast update
-        $this->cachePage(DECADE);
-
         self::triggerWebpageHit($this->podcast->id);
 
-        $data = [
-            'podcast' => $this->podcast,
-            'episodes' => $this->podcast->episodes,
-        ];
-        return view('podcast', $data);
+        $yearQuery = $this->request->getGet('year');
+        $seasonQuery = $this->request->getGet('season');
+
+        if (!$yearQuery and !$seasonQuery) {
+            $defaultQuery = (new EpisodeModel())->getDefaultQuery(
+                $this->podcast->id
+            );
+            if ($defaultQuery['type'] == 'season') {
+                $seasonQuery = $defaultQuery['data']['season_number'];
+            } elseif ($defaultQuery['type'] == 'year') {
+                $yearQuery = $defaultQuery['data']['year'];
+            }
+        }
+
+        $cacheName = implode(
+            '_',
+            array_filter([
+                'page',
+                "podcast{$this->podcast->id}",
+                $yearQuery,
+                $seasonQuery ? 'season' . $seasonQuery : null,
+            ])
+        );
+
+        if (!($found = cache($cacheName))) {
+            // The page cache is set to a decade so it is deleted manually upon podcast update
+            // $this->cachePage(DECADE);
+            $episodeModel = new EpisodeModel();
+
+            // Build navigation array
+            $years = $episodeModel->getYears($this->podcast->id);
+            $seasons = $episodeModel->getSeasons($this->podcast->id);
+
+            $episodesNavigation = [];
+            $activeQuery = null;
+            foreach ($years as $year) {
+                $isActive = $yearQuery == $year['year'];
+                if ($isActive) {
+                    $activeQuery = ['type' => 'year', 'value' => $year['year']];
+                }
+
+                array_push($episodesNavigation, [
+                    'label' => $year['year'],
+                    'number_of_episodes' => $year['number_of_episodes'],
+                    'route' =>
+                        route_to('podcast', $this->podcast->name) .
+                        '?year=' .
+                        $year['year'],
+                    'is_active' => $isActive,
+                ]);
+            }
+
+            foreach ($seasons as $season) {
+                $isActive = $seasonQuery == $season['season_number'];
+                if ($isActive) {
+                    $activeQuery = [
+                        'type' => 'season',
+                        'value' => $season['season_number'],
+                    ];
+                }
+
+                array_push($episodesNavigation, [
+                    'label' => lang('Podcast.season', [
+                        'seasonNumber' => $season['season_number'],
+                    ]),
+                    'number_of_episodes' => $season['number_of_episodes'],
+                    'route' =>
+                        route_to('podcast', $this->podcast->name) .
+                        '?season=' .
+                        $season['season_number'],
+                    'is_active' => $isActive,
+                ]);
+            }
+
+            $data = [
+                'podcast' => $this->podcast,
+                'episodesNav' => $episodesNavigation,
+                'activeQuery' => $activeQuery,
+                'episodes' => (new EpisodeModel())->getPodcastEpisodes(
+                    $this->podcast->id,
+                    $this->podcast->type,
+                    $yearQuery,
+                    $seasonQuery
+                ),
+            ];
+
+            return view('podcast', $data, [
+                'cache' => DECADE,
+                'cache_name' => $cacheName,
+            ]);
+        }
+
+        return $found;
     }
 }
diff --git a/app/Database/Migrations/2020-06-05-170000_add_episodes.php b/app/Database/Migrations/2020-06-05-170000_add_episodes.php
index 49625900ba..e965fd8e6e 100644
--- a/app/Database/Migrations/2020-06-05-170000_add_episodes.php
+++ b/app/Database/Migrations/2020-06-05-170000_add_episodes.php
@@ -45,6 +45,22 @@ class AddEpisodes extends Migration
                 'type' => 'VARCHAR',
                 'constraint' => 1024,
             ],
+            'enclosure_duration' => [
+                'type' => 'INT',
+                'constraint' => 10,
+                'unsigned' => true,
+                'comment' => 'Playtime in seconds',
+            ],
+            'enclosure_mimetype' => [
+                'type' => 'VARCHAR',
+                'constraint' => 255,
+            ],
+            'enclosure_filesize' => [
+                'type' => 'INT',
+                'constraint' => 10,
+                'unsigned' => true,
+                'comment' => 'File size in bytes',
+            ],
             'description' => [
                 'type' => 'TEXT',
                 'null' => true,
diff --git a/app/Database/Migrations/2020-06-08-210000_add_analytics_episodes_by_country.php b/app/Database/Migrations/2020-06-08-210000_add_analytics_episodes_by_country.php
index c4f6218a54..d0e94c6c93 100644
--- a/app/Database/Migrations/2020-06-08-210000_add_analytics_episodes_by_country.php
+++ b/app/Database/Migrations/2020-06-08-210000_add_analytics_episodes_by_country.php
@@ -36,6 +36,7 @@ class AddAnalyticsEpisodesByCountry extends Migration
             'country_code' => [
                 'type' => 'VARCHAR',
                 'constraint' => 3,
+                'comment' => 'ISO 3166-1 code.',
             ],
             'date' => [
                 'type' => 'date',
diff --git a/app/Entities/Episode.php b/app/Entities/Episode.php
index 1ddc42ee39..463c496052 100644
--- a/app/Entities/Episode.php
+++ b/app/Entities/Episode.php
@@ -54,11 +54,6 @@ class Episode extends Entity
      */
     protected $enclosure_url;
 
-    /**
-     * @var array
-     */
-    protected $enclosure_metadata;
-
     /**
      * @var string
      */
@@ -76,6 +71,9 @@ class Episode extends Entity
         'slug' => 'string',
         'title' => 'string',
         'enclosure_uri' => 'string',
+        'enclosure_duration' => 'integer',
+        'enclosure_mimetype' => 'string',
+        'enclosure_filesize' => 'integer',
         'description' => 'string',
         'image_uri' => '?string',
         'explicit' => 'boolean',
@@ -106,19 +104,6 @@ class Episode extends Entity
                 $this->getPodcast()->name,
                 $this->attributes['slug']
             );
-        } elseif (
-            $APICdata = $this->getEnclosureMetadata()['attached_picture']
-        ) {
-            // if the user didn't input an image,
-            // check if the uploaded audio file has an attached cover and store it
-            $cover_image = new \CodeIgniter\Files\File('episode_cover');
-            file_put_contents($cover_image, $APICdata);
-
-            $this->attributes['image_uri'] = save_podcast_media(
-                $cover_image,
-                $this->getPodcast()->name,
-                $this->attributes['slug']
-            );
         }
 
         return $this;
@@ -155,13 +140,22 @@ class Episode extends Entity
             (!($enclosure instanceof \CodeIgniter\HTTP\Files\UploadedFile) ||
                 $enclosure->isValid())
         ) {
-            helper('media');
+            helper(['media', 'id3']);
+
+            $enclosure_metadata = get_file_tags($enclosure);
 
             $this->attributes['enclosure_uri'] = save_podcast_media(
                 $enclosure,
                 $this->getPodcast()->name,
                 $this->attributes['slug']
             );
+            $this->attributes['enclosure_duration'] = round(
+                $enclosure_metadata['playtime_seconds']
+            );
+            $this->attributes['enclosure_mimetype'] =
+                $enclosure_metadata['mime_type'];
+            $this->attributes['enclosure_filesize'] =
+                $enclosure_metadata['filesize'];
 
             return $this;
         }
@@ -191,13 +185,6 @@ class Episode extends Entity
         );
     }
 
-    public function getEnclosureMetadata()
-    {
-        helper('id3');
-
-        return get_file_tags($this->getEnclosure());
-    }
-
     public function getLink()
     {
         return base_url(
@@ -218,7 +205,9 @@ class Episode extends Entity
 
     public function getPodcast()
     {
-        return (new PodcastModel())->find($this->attributes['podcast_id']);
+        return (new PodcastModel())->getPodcastById(
+            $this->attributes['podcast_id']
+        );
     }
 
     public function getDescriptionHtml()
diff --git a/app/Entities/Podcast.php b/app/Entities/Podcast.php
index 916d723214..2d6ea40d9c 100644
--- a/app/Entities/Podcast.php
+++ b/app/Entities/Podcast.php
@@ -8,7 +8,9 @@
 
 namespace App\Entities;
 
+use App\Models\CategoryModel;
 use App\Models\EpisodeModel;
+use App\Models\PlatformModel;
 use CodeIgniter\Entity;
 use App\Models\UserModel;
 use League\CommonMark\CommonMarkConverter;
@@ -40,6 +42,11 @@ class Podcast extends Entity
      */
     protected $episodes;
 
+    /**
+     * @var \App\Entities\Category
+     */
+    protected $category;
+
     /**
      * @var \App\Entities\User[]
      */
@@ -50,6 +57,11 @@ class Podcast extends Entity
      */
     protected $description_html;
 
+    /**
+     * @var \App\Entities\Platform
+     */
+    protected $platforms;
+
     protected $casts = [
         'id' => 'integer',
         'title' => 'string',
@@ -134,13 +146,34 @@ class Podcast extends Entity
 
         if (empty($this->episodes)) {
             $this->episodes = (new EpisodeModel())->getPodcastEpisodes(
-                $this->id
+                $this->id,
+                $this->type
             );
         }
 
         return $this->episodes;
     }
 
+    /**
+     * Returns the podcast category entity
+     *
+     * @return \App\Entities\Category
+     */
+    public function getCategory()
+    {
+        if (empty($this->id)) {
+            throw new \RuntimeException(
+                'Podcast must be created before getting category.'
+            );
+        }
+
+        if (empty($this->category)) {
+            $this->category = (new CategoryModel())->find($this->category_id);
+        }
+
+        return $this->category;
+    }
+
     /**
      * Returns all podcast contributors
      *
@@ -186,4 +219,26 @@ class Podcast extends Entity
 
         return $this;
     }
+
+    /**
+     * Returns the podcast's platform links
+     *
+     * @return \App\Entities\Platform[]
+     */
+    public function getPlatforms()
+    {
+        if (empty($this->id)) {
+            throw new \RuntimeException(
+                'Podcast must be created before getting platform links.'
+            );
+        }
+
+        if (empty($this->platforms)) {
+            $this->platforms = (new PlatformModel())->getPodcastPlatformLinks(
+                $this->id
+            );
+        }
+
+        return $this->platforms;
+    }
 }
diff --git a/app/Entities/User.php b/app/Entities/User.php
index 42b6d3a17f..ed6bc92029 100644
--- a/app/Entities/User.php
+++ b/app/Entities/User.php
@@ -63,7 +63,9 @@ class User extends \Myth\Auth\Entities\User
         }
 
         if (empty($this->podcast)) {
-            $this->podcast = (new PodcastModel())->find($this->podcast_id);
+            $this->podcast = (new PodcastModel())->getPodcastById(
+                $this->podcast_id
+            );
         }
 
         return $this->podcast;
diff --git a/app/Helpers/id3_helper.php b/app/Helpers/id3_helper.php
index 7933505029..15ab043ba3 100644
--- a/app/Helpers/id3_helper.php
+++ b/app/Helpers/id3_helper.php
@@ -25,9 +25,6 @@ function get_file_tags($file)
         'filesize' => $FileInfo['filesize'],
         'mime_type' => $FileInfo['mime_type'],
         'playtime_seconds' => $FileInfo['playtime_seconds'],
-        'attached_picture' => array_key_exists('comments', $FileInfo)
-            ? $FileInfo['comments']['picture'][0]['data']
-            : null,
     ];
 }
 
diff --git a/app/Helpers/page_helper.php b/app/Helpers/page_helper.php
index 488a6740e9..74b64220d6 100644
--- a/app/Helpers/page_helper.php
+++ b/app/Helpers/page_helper.php
@@ -11,17 +11,20 @@ use App\Models\PageModel;
 /**
  * Returns instance pages as links inside nav tag
  *
+ * @param string $class
  * @return string html pages navigation
  */
-function render_page_links()
+function render_page_links($class = null)
 {
     $pages = (new PageModel())->findAll();
-    $links = '';
+    $links = anchor(route_to('home'), lang('Common.home'), [
+        'class' => 'px-2 underline hover:no-underline',
+    ]);
     foreach ($pages as $page) {
         $links .= anchor($page->link, $page->title, [
             'class' => 'px-2 underline hover:no-underline',
         ]);
     }
 
-    return '<nav class="inline-flex">' . $links . '</nav>';
+    return '<nav class="' . $class . '">' . $links . '</nav>';
 }
diff --git a/app/Helpers/rss_helper.php b/app/Helpers/rss_helper.php
index f08297f698..8ba85770e5 100644
--- a/app/Helpers/rss_helper.php
+++ b/app/Helpers/rss_helper.php
@@ -115,10 +115,9 @@ function get_rss_feed($podcast)
         $item->addChild('title', $episode->title);
         $enclosure = $item->addChild('enclosure');
 
-        $enclosure_metadata = $episode->enclosure_metadata;
         $enclosure->addAttribute('url', $episode->enclosure_url);
-        $enclosure->addAttribute('length', $enclosure_metadata['filesize']);
-        $enclosure->addAttribute('type', $enclosure_metadata['mime_type']);
+        $enclosure->addAttribute('length', $episode->enclosure_filesize);
+        $enclosure->addAttribute('type', $episode->enclosure_mimetype);
 
         $item->addChild('guid', $episode->guid);
         $item->addChild(
@@ -128,7 +127,7 @@ function get_rss_feed($podcast)
         $item->addChildWithCDATA('description', $episode->description_html);
         $item->addChild(
             'duration',
-            $enclosure_metadata['playtime_seconds'],
+            $episode->enclosure_duration,
             $itunes_namespace
         );
         $item->addChild('link', $episode->link);
diff --git a/app/Language/en/Common.php b/app/Language/en/Common.php
new file mode 100644
index 0000000000..237019ad5d
--- /dev/null
+++ b/app/Language/en/Common.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * @copyright  2020 Podlibre
+ * @license    https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
+ * @link       https://castopod.org/
+ */
+
+return [
+    'home' => 'Home',
+    'explicit' => 'Explicit',
+    'mediumDate' => '{0,date,medium}',
+    'duration' => '{0,duration}',
+    'powered_by' => 'Powered by {castopod}.',
+];
diff --git a/app/Language/en/Episode.php b/app/Language/en/Episode.php
index ae5e3db1a8..d2563a115f 100644
--- a/app/Language/en/Episode.php
+++ b/app/Language/en/Episode.php
@@ -7,6 +7,12 @@
  */
 
 return [
+    'previous_episode' => 'Previous episode',
+    'previous_season' => 'Previous season',
+    'next_episode' => 'Next episode',
+    'next_season' => 'Next season',
+    'season' => 'Season {seasonNumber}',
+    'number' => 'Episode {episodeNumber}',
     'all_podcast_episodes' => 'All podcast episodes',
     'back_to_podcast' => 'Go back to podcast',
     'edit' => 'Edit',
diff --git a/app/Language/en/Podcast.php b/app/Language/en/Podcast.php
index 8a6bda75a2..2c573d7282 100644
--- a/app/Language/en/Podcast.php
+++ b/app/Language/en/Podcast.php
@@ -219,6 +219,11 @@ return [
         'film_reviews' => 'Film Reviews',
         'tv_reviews' => 'TV Reviews',
     ],
-    'list_of_episodes' => 'List of episodes',
-    'no_episode' => 'No episode found',
+    'by' => 'By {author}',
+    'season' => 'Season {seasonNumber}',
+    'list_of_episodes_year' => '{year} episodes',
+    'list_of_episodes_season' => 'Season {seasonNumber} episodes',
+    'no_episode' => 'No episode found!',
+    'no_episode_hint' =>
+        'Navigate the podcast episodes with the navigation bar above.',
 ];
diff --git a/app/Models/CategoryModel.php b/app/Models/CategoryModel.php
index 66309406be..af52ff04e7 100644
--- a/app/Models/CategoryModel.php
+++ b/app/Models/CategoryModel.php
@@ -31,4 +31,26 @@ class CategoryModel extends Model
     {
         return $this->find($parentId);
     }
+
+    public function getCategoryOptions()
+    {
+        if (!($options = cache('category_options'))) {
+            $categories = $this->findAll();
+
+            $options = array_reduce(
+                $categories,
+                function ($result, $category) {
+                    $result[$category->id] = lang(
+                        'Podcast.category_options.' . $category->code
+                    );
+                    return $result;
+                },
+                []
+            );
+
+            cache()->save('category_options', $options, DECADE);
+        }
+
+        return $options;
+    }
 }
diff --git a/app/Models/EpisodeModel.php b/app/Models/EpisodeModel.php
index b346fcff64..e569fef7e1 100644
--- a/app/Models/EpisodeModel.php
+++ b/app/Models/EpisodeModel.php
@@ -21,6 +21,9 @@ class EpisodeModel extends Model
         'title',
         'slug',
         'enclosure_uri',
+        'enclosure_duration',
+        'enclosure_mimetype',
+        'enclosure_filesize',
         'description',
         'image_uri',
         'explicit',
@@ -75,7 +78,9 @@ class EpisodeModel extends Model
 
     protected function clearCache(array $data)
     {
-        $episode = (new EpisodeModel())->find(
+        $episodeModel = new EpisodeModel();
+
+        $episode = $episodeModel->find(
             is_array($data['id']) ? $data['id'][0] : $data['id']
         );
 
@@ -85,26 +90,213 @@ class EpisodeModel extends Model
         cache()->delete(md5($episode->link));
 
         // delete model requests cache
-        cache()->delete("{$episode->podcast_id}_episodes");
+        cache()->delete("podcast{$episode->podcast_id}_episodes");
+
+        // delete episode lists cache per year / season
+        $years = $episodeModel->getYears($episode->podcast_id);
+        $seasons = $episodeModel->getSeasons($episode->podcast_id);
+
+        foreach ($years as $year) {
+            cache()->delete(
+                "podcast{$episode->podcast_id}_{$year['year']}_episodes"
+            );
+            cache()->delete(
+                "page_podcast{$episode->podcast_id}_{$year['year']}"
+            );
+        }
+        foreach ($seasons as $season) {
+            cache()->delete(
+                "podcast{$episode->podcast_id}_season{$season['season_number']}_episodes"
+            );
+            cache()->delete(
+                "page_podcast{$episode->podcast_id}_season{$season['season_number']}"
+            );
+        }
+
+        cache()->delete("podcast{$episode->podcast_id}_defaultQuery");
+        cache()->delete("podcast{$episode->podcast_id}_years");
+        cache()->delete("podcast{$episode->podcast_id}_seasons");
+
+        cache()->delete(
+            "podcast{$episode->podcast_id}_episode@{$episode->slug}"
+        );
 
         return $data;
     }
 
+    public function getEpisodeBySlug($podcastId, $episodeSlug)
+    {
+        if (!($found = cache("podcast{$podcastId}_episode@{$episodeSlug}"))) {
+            $found = $this->where([
+                'podcast_id' => $podcastId,
+                'slug' => $episodeSlug,
+            ])->first();
+
+            cache()->save(
+                "podcast{$podcastId}_episode@{$episodeSlug}",
+                $found,
+                DECADE
+            );
+        }
+
+        return $found;
+    }
+
     /**
-     * Gets all episodes for a podcast
+     * Gets all episodes for a podcast ordered according to podcast type
+     * Filtered depending on year or season
      *
      * @param int $podcastId
      *
      * @return \App\Entities\Episode[]
      */
-    public function getPodcastEpisodes(int $podcastId): array
+    public function getPodcastEpisodes(
+        int $podcastId,
+        string $podcastType,
+        string $year = null,
+        string $season = null
+    ): array {
+        $cacheName = implode(
+            '_',
+            array_filter([
+                "podcast{$podcastId}",
+                $year,
+                $season ? 'season' . $season : null,
+                'episodes',
+            ])
+        );
+
+        if (!($found = cache($cacheName))) {
+            $where = ['podcast_id' => $podcastId];
+            if ($year) {
+                $where['YEAR(published_at)'] = $year;
+                $where['season_number'] = null;
+            }
+            if ($season) {
+                $where['season_number'] = $season;
+            }
+
+            if ($podcastType == 'serial') {
+                // podcast is serial
+                $found = $this->where($where)
+                    ->orderBy('season_number DESC, number ASC')
+                    ->findAll();
+            } else {
+                $found = $this->where($where)
+                    ->orderBy('published_at', 'DESC')
+                    ->findAll();
+            }
+
+            cache()->save($cacheName, $found, DECADE);
+        }
+
+        return $found;
+    }
+
+    public function getYears(int $podcastId): array
+    {
+        if (!($found = cache("podcast{$podcastId}_years"))) {
+            $found = $this->select(
+                'YEAR(published_at) as year, count(*) as number_of_episodes'
+            )
+                ->where(['podcast_id' => $podcastId, 'season_number' => null])
+                ->groupBy('year')
+                ->orderBy('year', 'DESC')
+                ->get()
+                ->getResultArray();
+
+            cache()->save("podcast{$podcastId}_years", $found, DECADE);
+        }
+
+        return $found;
+    }
+
+    public function getSeasons(int $podcastId): array
     {
-        if (!($found = cache("{$podcastId}_episodes"))) {
-            $found = $this->where('podcast_id', $podcastId)->findAll();
+        if (!($found = cache("podcast{$podcastId}_seasons"))) {
+            $found = $this->select(
+                'season_number, count(*) as number_of_episodes'
+            )
+                ->where([
+                    'podcast_id' => $podcastId,
+                    'season_number is not' => null,
+                ])
+                ->groupBy('season_number')
+                ->orderBy('season_number', 'ASC')
+                ->get()
+                ->getResultArray();
 
-            cache()->save("{$podcastId}_episodes", $found, 300);
+            cache()->save("podcast{$podcastId}_seasons", $found, DECADE);
         }
 
         return $found;
     }
+
+    /**
+     * Returns the default query for displaying the episode list on the podcast page
+     */
+    public function getDefaultQuery(int $podcastId)
+    {
+        if (!($defaultQuery = cache("podcast{$podcastId}_defaultQuery"))) {
+            $seasons = $this->getSeasons($podcastId);
+
+            if (!empty($seasons)) {
+                // get latest season
+                $defaultQuery = ['type' => 'season', 'data' => end($seasons)];
+            } else {
+                $years = $this->getYears($podcastId);
+                if (!empty($years)) {
+                    // get most recent year
+                    $defaultQuery = ['type' => 'year', 'data' => $years[0]];
+                } else {
+                    $defaultQuery = null;
+                }
+            }
+
+            cache()->save(
+                "podcast{$podcastId}_defaultQuery",
+                $defaultQuery,
+                DECADE
+            );
+        }
+        return $defaultQuery;
+    }
+
+    /**
+     * Returns the previous episode based on episode ordering
+     */
+    public function getPreviousNextEpisodes($episode, $podcastType)
+    {
+        $sortNumberField =
+            $podcastType == 'serial'
+                ? 'if(isnull(season_number),0,season_number)*1000+number'
+                : 'UNIX_TIMESTAMP(published_at)';
+        $sortNumberValue =
+            $podcastType == 'serial'
+                ? (empty($episode->season_number)
+                        ? 0
+                        : $episode->season_number) *
+                        1000 +
+                    $episode->number
+                : strtotime($episode->published_at);
+
+        $previousData = $this->orderBy('(' . $sortNumberField . ') DESC')
+            ->where([
+                'podcast_id' => $episode->podcast_id,
+                $sortNumberField . ' <' => $sortNumberValue,
+            ])
+            ->first();
+
+        $nextData = $this->orderBy('(' . $sortNumberField . ') ASC')
+            ->where([
+                'podcast_id' => $episode->podcast_id,
+                $sortNumberField . ' >' => $sortNumberValue,
+            ])
+            ->first();
+
+        return [
+            'previous' => $previousData,
+            'next' => $nextData,
+        ];
+    }
 }
diff --git a/app/Models/LanguageModel.php b/app/Models/LanguageModel.php
index f89f596562..5eb780f386 100644
--- a/app/Models/LanguageModel.php
+++ b/app/Models/LanguageModel.php
@@ -21,4 +21,24 @@ class LanguageModel extends Model
     protected $useSoftDeletes = false;
 
     protected $useTimestamps = false;
+
+    public function getLanguageOptions()
+    {
+        if (!($options = cache('language_options'))) {
+            $languages = $this->findAll();
+
+            $options = array_reduce(
+                $languages,
+                function ($result, $language) {
+                    $result[$language->code] = $language->native_name;
+                    return $result;
+                },
+                []
+            );
+
+            cache()->save('language_options', $options, DECADE);
+        }
+
+        return $options;
+    }
 }
diff --git a/app/Models/PlatformModel.php b/app/Models/PlatformModel.php
index d09e5ce175..cb24ad1a1e 100644
--- a/app/Models/PlatformModel.php
+++ b/app/Models/PlatformModel.php
@@ -36,21 +36,49 @@ class PlatformModel extends Model
 
     protected $useTimestamps = true;
 
-    public function getPlatformsWithLinks()
+    public function getPlatformsWithLinks($podcastId)
     {
-        return $this->select(
-            'platforms.*, platform_links.link_url, platform_links.visible'
-        )
-            ->join(
-                'platform_links',
-                'platform_links.platform_id = platforms.id',
-                'left'
+        if (!($found = cache("podcast{$podcastId}_platforms"))) {
+            $found = $this->select(
+                'platforms.*, platform_links.link_url, platform_links.visible'
             )
-            ->findAll();
+                ->join(
+                    'platform_links',
+                    "platform_links.platform_id = platforms.id AND platform_links.podcast_id = $podcastId",
+                    'left'
+                )
+                ->findAll();
+
+            cache()->save("podcast{$podcastId}_platforms", $found, DECADE);
+        }
+
+        return $found;
+    }
+
+    public function getPodcastPlatformLinks($podcastId)
+    {
+        if (!($found = cache("podcast{$podcastId}_platformLinks"))) {
+            $found = $this->select(
+                'platforms.*, platform_links.link_url, platform_links.visible'
+            )
+                ->join(
+                    'platform_links',
+                    'platform_links.platform_id = platforms.id'
+                )
+                ->where('platform_links.podcast_id', $podcastId)
+                ->findAll();
+
+            cache()->save("podcast{$podcastId}_platformLinks", $found, DECADE);
+        }
+
+        return $found;
     }
 
     public function savePlatformLinks($podcastId, $platformLinksData)
     {
+        cache()->delete("podcast{$podcastId}_platforms");
+        cache()->delete("podcast{$podcastId}_platformLinks");
+
         // Remove already previously set platforms to overwrite them
         $this->db
             ->table('platform_links')
@@ -81,6 +109,9 @@ class PlatformModel extends Model
 
     public function removePlatformLink($podcastId, $platformId)
     {
+        cache()->delete("podcast{$podcastId}_platforms");
+        cache()->delete("podcast{$podcastId}_platformLinks");
+
         return $this->db->table('platform_links')->delete([
             'podcast_id' => $podcastId,
             'platform_id' => $platformId,
diff --git a/app/Models/PodcastModel.php b/app/Models/PodcastModel.php
index 023f7a2341..16f50a264b 100644
--- a/app/Models/PodcastModel.php
+++ b/app/Models/PodcastModel.php
@@ -62,63 +62,99 @@ class PodcastModel extends Model
     protected $beforeUpdate = ['clearCache'];
     protected $beforeDelete = ['clearCache'];
 
+    public function getPodcastByName($podcastName)
+    {
+        if (!($found = cache("podcast@{$podcastName}"))) {
+            $found = $this->where('name', $podcastName)->first();
+
+            cache()->save("podcast@{$podcastName}", $found, DECADE);
+        }
+
+        return $found;
+    }
+
+    public function getPodcastById($podcastId)
+    {
+        if (!($found = cache("podcast{$podcastId}"))) {
+            $found = $this->find($podcastId);
+
+            cache()->save("podcast{$podcastId}", $found, DECADE);
+        }
+
+        return $found;
+    }
+
     /**
      *  Gets all the podcasts a given user is contributing to
      *
-     * @param int $user_id
+     * @param int $userId
      *
      * @return \App\Entities\Podcast[] podcasts
      */
-    public function getUserPodcasts($user_id)
+    public function getUserPodcasts($userId)
     {
-        return $this->select('podcasts.*')
-            ->join('users_podcasts', 'users_podcasts.podcast_id = podcasts.id')
-            ->where('users_podcasts.user_id', $user_id)
-            ->findAll();
+        if (!($found = cache("user{$userId}_podcasts"))) {
+            $found = $this->select('podcasts.*')
+                ->join(
+                    'users_podcasts',
+                    'users_podcasts.podcast_id = podcasts.id'
+                )
+                ->where('users_podcasts.user_id', $userId)
+                ->findAll();
+
+            cache()->save("user{$userId}_podcasts", $found, DECADE);
+        }
+
+        return $found;
     }
 
-    public function addPodcastContributor($user_id, $podcast_id, $group_id)
+    public function addPodcastContributor($userId, $podcastId, $groupId)
     {
+        cache()->delete("podcast{$podcastId}_contributors");
+
         $data = [
-            'user_id' => (int) $user_id,
-            'podcast_id' => (int) $podcast_id,
-            'group_id' => (int) $group_id,
+            'user_id' => (int) $userId,
+            'podcast_id' => (int) $podcastId,
+            'group_id' => (int) $groupId,
         ];
 
         return $this->db->table('users_podcasts')->insert($data);
     }
 
-    public function updatePodcastContributor($user_id, $podcast_id, $group_id)
+    public function updatePodcastContributor($userId, $podcastId, $groupId)
     {
+        cache()->delete("podcast{$podcastId}_contributors");
+
         return $this->db
             ->table('users_podcasts')
             ->where([
-                'user_id' => (int) $user_id,
-                'podcast_id' => (int) $podcast_id,
+                'user_id' => (int) $userId,
+                'podcast_id' => (int) $podcastId,
             ])
-            ->update(['group_id' => $group_id]);
+            ->update(['group_id' => $groupId]);
     }
 
-    public function removePodcastContributor($user_id, $podcast_id)
+    public function removePodcastContributor($userId, $podcastId)
     {
+        cache()->delete("podcast{$podcastId}_contributors");
+
         return $this->db
             ->table('users_podcasts')
             ->where([
-                'user_id' => $user_id,
-                'podcast_id' => $podcast_id,
+                'user_id' => $userId,
+                'podcast_id' => $podcastId,
             ])
             ->delete();
     }
 
-    public function getContributorGroupId($user_id, $podcast_id)
+    public function getContributorGroupId($userId, $podcastId)
     {
-        // TODO: return only the group id
         $user_podcast = $this->db
             ->table('users_podcasts')
             ->select('group_id')
             ->where([
-                'user_id' => $user_id,
-                'podcast_id' => $podcast_id,
+                'user_id' => $userId,
+                'podcast_id' => $podcastId,
             ])
             ->get()
             ->getResultObject();
@@ -130,7 +166,7 @@ class PodcastModel extends Model
 
     protected function clearCache(array $data)
     {
-        $podcast = (new PodcastModel())->find(
+        $podcast = (new PodcastModel())->getPodcastById(
             is_array($data['id']) ? $data['id'][0] : $data['id']
         );
 
@@ -143,6 +179,10 @@ class PodcastModel extends Model
             cache()->delete(md5($episode->link));
         }
 
+        // delete model requests cache
+        cache()->delete("podcast{$podcast->id}");
+        cache()->delete("podcast@{$podcast->name}");
+
         return $data;
     }
 }
diff --git a/app/Models/UserModel.php b/app/Models/UserModel.php
index 4f9f7d0333..3e0d942a26 100644
--- a/app/Models/UserModel.php
+++ b/app/Models/UserModel.php
@@ -1,18 +1,33 @@
 <?php
 
+/**
+ * @copyright  2020 Podlibre
+ * @license    https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
+ * @link       https://castopod.org/
+ */
+
 namespace App\Models;
 
 class UserModel extends \Myth\Auth\Models\UserModel
 {
     protected $returnType = \App\Entities\User::class;
 
-    public function getPodcastContributors($podcast_id)
+    public function getPodcastContributors($podcastId)
     {
-        return $this->select('users.*, auth_groups.name as podcast_role')
-            ->join('users_podcasts', 'users_podcasts.user_id = users.id')
-            ->join('auth_groups', 'auth_groups.id = users_podcasts.group_id')
-            ->where('users_podcasts.podcast_id', $podcast_id)
-            ->findAll();
+        if (!($found = cache("podcast{$podcastId}_contributors"))) {
+            $found = $this->select('users.*, auth_groups.name as podcast_role')
+                ->join('users_podcasts', 'users_podcasts.user_id = users.id')
+                ->join(
+                    'auth_groups',
+                    'auth_groups.id = users_podcasts.group_id'
+                )
+                ->where('users_podcasts.podcast_id', $podcastId)
+                ->findAll();
+
+            cache()->save("podcast{$podcastId}_contributors", $found, DECADE);
+        }
+
+        return $found;
     }
 
     public function getPodcastContributor($user_id, $podcast_id)
diff --git a/app/Views/_assets/icons/arrow-left.svg b/app/Views/_assets/icons/arrow-left.svg
new file mode 100644
index 0000000000..6d82f7ba31
--- /dev/null
+++ b/app/Views/_assets/icons/arrow-left.svg
@@ -0,0 +1,6 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
+    <g>
+        <path fill="none" d="M0 0h24v24H0z"/>
+        <path d="M10.828 12l4.95 4.95-1.414 1.414L8 12l6.364-6.364 1.414 1.414z"/>
+    </g>
+</svg>
diff --git a/app/Views/_assets/icons/arrow-right.svg b/app/Views/_assets/icons/arrow-right.svg
new file mode 100644
index 0000000000..f33dff5e6f
--- /dev/null
+++ b/app/Views/_assets/icons/arrow-right.svg
@@ -0,0 +1,6 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
+    <g>
+        <path fill="none" d="M0 0h24v24H0z"/>
+        <path d="M13.172 12l-4.95-4.95 1.414-1.414L16 12l-6.364 6.364-1.414-1.414z"/>
+    </g>
+</svg>
diff --git a/app/Views/_assets/icons/rss.svg b/app/Views/_assets/icons/rss.svg
new file mode 100644
index 0000000000..e8cff80175
--- /dev/null
+++ b/app/Views/_assets/icons/rss.svg
@@ -0,0 +1,6 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
+    <g>
+        <path fill="none" d="M0 0h24v24H0z"/>
+        <path d="M3 17a4 4 0 0 1 4 4H3v-4zm0-7c6.075 0 11 4.925 11 11h-2a9 9 0 0 0-9-9v-2zm0-7c9.941 0 18 8.059 18 18h-2c0-8.837-7.163-16-16-16V3z"/>
+    </g>
+</svg>
diff --git a/app/Views/episode.php b/app/Views/episode.php
index 8593876476..1fabf4fb71 100644
--- a/app/Views/episode.php
+++ b/app/Views/episode.php
@@ -1,11 +1,103 @@
-<?= $this->extend('_layout') ?>
+<?= helper('page') ?>
+<!DOCTYPE html>
+<html lang="en">
 
-<?= $this->section('title') ?>
-<?= $episode->title ?>
-<?= $this->endSection() ?>
+<head>
+    <meta charset="UTF-8"/>
+    <title><?= $episode->title ?></title>
+    <meta name="description" content="Castopod is an open-source hosting platform made for podcasters who want engage and interact with their audience."/>
+    <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
+    <link rel="shortcut icon" type="image/png" href="/favicon.ico" />
+    <link rel="stylesheet" href="/assets/index.css"/>
+</head>
 
-<?= $this->section('content') ?>
+<body class="flex flex-col min-h-screen mx-auto">
+    <header class="border-b bg-gradient-to-tr from-gray-900 to-gray-800">
+        <div class="container flex items-start px-2 py-2 mx-auto">
+          <img class="w-12 h-12 mr-2 rounded cover" src="<?= $episode->podcast
+              ->image_url ?>" alt="<?= $episode->podcast->title ?>" />
+          <a href="<?= route_to(
+              'podcast',
+              $episode->podcast->name
+          ) ?>" class="flex flex-col text-lg leading-tight text-white" title="<?= lang(
+    'Episode.back_to_podcast'
+) ?>">
+            <?= $episode->podcast->title ?>
+            <span class="text-sm text-gray-300">
+                @<?= $episode->podcast->name ?>
+            </span>
+          </a>
+        </div>
+    </header>
+    <main class="container flex-1 mx-auto">
+      <nav class="flex items-center px-2 py-4">
+            <?php if ($previousEpisode): ?>
+                <a class="flex items-center text-xs leading-snug text-gray-600 hover:text-gray-900" href="<?= $previousEpisode->link ?>" title="<?= $previousEpisode->title ?>">
+                    <?= icon('arrow-left', 'mr-2') ?>
+                    <div class="flex flex-col">
+                        <?= $previousEpisode->season_number ==
+                        $episode->season_number
+                            ? lang('Episode.previous_episode')
+                            : lang('Episode.previous_season') ?>
+                        <span class="w-40 font-semibold truncate"><?= $previousEpisode->title ?></span>
+                    </div>
+                </a>
+            <?php endif; ?>
+            <?php if ($nextEpisode): ?>
+                <a class="flex items-center ml-auto text-xs leading-snug text-right text-gray-600 hover:text-gray-900" href="<?= $nextEpisode->link ?>" title="<?= $nextEpisode->title ?>">
+                    <div class="flex flex-col">
+                        <?= $nextEpisode->season_number ==
+                        $episode->season_number
+                            ? lang('Episode.next_episode')
+                            : lang('Episode.next_season') ?>
+                        <span class="w-40 font-semibold truncate"><?= $nextEpisode->title ?></span>
+                    </div>
+                    <?= icon('arrow-right', 'ml-2') ?>
+                </a>
+            <?php endif; ?>
+      </nav>
+      <header class="flex flex-col items-center px-4 md:items-stretch md:justify-center md:flex-row">
+        <img src="<?= $episode->image_url ?>" alt="<?= $episode->title ?>" class="object-cover w-full max-w-xs mb-2 rounded-lg md:mb-0 md:mr-4" />
+        <div class="flex flex-col w-full max-w-sm">
+          <h1 class="text-lg font-semibold md:text-2xl"><?= $episode->title ?></h1>
+          <?php if ($episode->number): ?>
+            <p class="text-gray-600">
+                <?php if ($episode->season_number): ?>
+                    <a class="mr-1 underline hover:no-underline" href="<?= route_to(
+                        'podcast',
+                        $episode->podcast->name
+                    ) .
+                        '?season=' .
+                        $episode->season_number ?>">
+                        <?= lang('Episode.season', [
+                            'seasonNumber' => $episode->season_number,
+                        ]) ?></a>
+                <?php endif; ?>
+                <?= lang('Episode.number', [
+                    'episodeNumber' => $episode->number,
+                ]) ?>
+            </p>
+          <?php endif; ?>
+          <div class="text-sm">
+              <time
+              pubdate
+              datetime="<?= $episode->published_at->toDateTimeString() ?>"
+              title="<?= $episode->published_at ?>">
+              <?= lang('Common.mediumDate', [$episode->published_at]) ?>
+              </time>
+              <span class="mx-1">•</span>
+              <time datetime="PT<?= $episode->enclosure_duration ?>S">
+                  <?= lang('Common.duration', [$episode->enclosure_duration]) ?>
+              </time>
+          </div>
+          <audio controls preload="none" class="w-full mt-auto">
+            <source src="<?= $episode->enclosure_url ?>" type="<?= $episode->enclosure_type ?>">
+            Your browser does not support the audio tag.
+          </audio>
+        </div>
+      </header>
 
+<<<<<<< HEAD
 <a class="underline hover:no-underline" href="<?= route_to(
     'podcast',
     $podcast->name
@@ -27,3 +119,22 @@
 
 <?= $this->endSection() ?>
 >>>>>>> 240f1d4... feat: enhance ui using javascript in admin area
+=======
+      <section class="w-full max-w-3xl px-2 py-6 mx-auto prose md:px-6">
+      <?= $episode->description_html ?>
+      </section>
+    </main>
+    <footer class="px-2 py-4 border-t ">
+        <div class="container flex flex-col items-center justify-between mx-auto text-sm md:flex-row ">
+            <?= render_page_links('inline-flex mb-4 md:mb-0') ?>
+            <div class="flex flex-col items-end text-xs">
+                <p><?= $episode->podcast->copyright ?></p>
+                <p><?= lang('Common.powered_by', [
+                    'castopod' =>
+                        '<a class="underline hover:no-underline" href="https://castopod.org" target="_blank" rel="noreferrer noopener">Castopod</a>',
+                ]) ?></p>
+            </div>
+        </div>
+    </footer>
+</body>
+>>>>>>> ecc68b2... feat(public-ui): adapt wireframes to public podcast and episode pages
diff --git a/app/Views/podcast.php b/app/Views/podcast.php
index 9e0b4ce95d..2dcb69a8f9 100644
--- a/app/Views/podcast.php
+++ b/app/Views/podcast.php
@@ -1,46 +1,157 @@
-<?= $this->extend('_layout') ?>
+<?= helper('page') ?>
 
-<?= $this->section('title') ?>
-<?= $podcast->title ?>
-<?= $this->endSection() ?>
+<!DOCTYPE html>
+<html lang="<?= $podcast->language ?>">
 
-<?= $this->section('content') ?>
-<header class="py-4 border-b">
-    <h1 class="text-2xl"><?= $podcast->title ?></h1>
-    <img src="<?= $podcast->image_url ?>" alt="Podcast cover" class="object-cover w-40 h-40 mb-6" />
-    <a class="inline-flex px-4 py-2 bg-orange-500 hover:bg-orange-600" href="<?= route_to(
-        'podcast_feed',
-        $podcast->name
-    ) ?>"><?= lang('Podcast.feed') ?></a>
-</header>
+<head>
+    <meta charset="UTF-8"/>
+    <title><?= $podcast->title ?></title>
+    <meta name="description" content="Castopod is an open-source hosting platform made for podcasters who want engage and interact with their audience."/>
+    <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
+    <link rel="shortcut icon" type="image/png" href="/favicon.ico" />
+    <link rel="stylesheet" href="/assets/index.css"/>
+    <?= $podcast->custom_html_head ?>
+</head>
 
-<section class="flex flex-col py-4">
-    <h2 class="mb-4 text-xl"><?= lang('Podcast.list_of_episodes') ?> (<?= count(
-     $episodes
- ) ?>)</h2>
-    <?php if ($episodes): ?>
-        <?php foreach ($episodes as $episode): ?>
-            <article class="flex w-full max-w-lg p-4 mb-4 border shadow">
-                <img src="<?= $episode->image_url ?>" alt="<?= $episode->title ?>" class="object-cover w-32 h-32 mr-4" />
-                <div class="flex flex-col flex-1">
-                    <a href="<?= $episode->link ?>">
-                        <h3 class="text-xl font-semibold">
-                            <span class="mr-1 underline hover:no-underline"><?= $episode->title ?></span>
-                            <span class="text-base font-bold text-gray-600">#<?= $episode->number ?></span>
-                        </h3>
-                    </a>
-                    <audio controls class="mt-auto" preload="none">
-                        <source src="<?= $episode->enclosure_url ?>" type="<?= $episode->enclosure_type ?>">
-                        Your browser does not support the audio tag.
-                    </audio>
+<body class="flex flex-col min-h-screen">
+    <main class="flex-1 bg-gray-200">
+        <header class="border-b bg-gradient-to-tr from-gray-900 to-gray-800">
+            <div class="flex flex-col items-center justify-center md:items-stretch md:mx-auto md:container md:py-12 md:flex-row ">
+                <img src="<?= $podcast->image_url ?>" alt="Podcast cover" class="object-cover w-full max-w-xs m-4 rounded-lg shadow-xl" />
+                <div class="w-full p-4 bg-white md:w-auto md:text-white md:bg-transparent">
+                    <h1 class="text-2xl font-semibold leading-tight"><?= $podcast->title ?> <span class="text-lg font-normal opacity-75">@<?= $podcast->name ?></span></h1>
+                    <div class="flex items-center mb-4">
+                        <address>
+                            <?= lang('Podcast.by', [
+                                'author' => $podcast->author,
+                            ]) ?>
+                        </address>
+                        <?= $podcast->explicit
+                            ? '<span class="px-1 ml-2 text-xs font-semibold leading-tight tracking-wider uppercase border-2 border-gray-700 rounded md:border-white">' .
+                                lang('Common.explicit') .
+                                '</span>'
+                            : '' ?>
+                    </div>
+                    <div class="inline-flex">
+                        <?= anchor(
+                            route_to('podcast_feed', $podcast->name),
+                            icon('rss', 'mr-2') . lang('Podcast.feed'),
+                            [
+                                'class' =>
+                                    'text-white bg-gradient-to-r from-orange-400 to-red-500 hover:to-orange-500 hover:bg-orange-500 inline-flex items-center px-2 py-1 mb-2 font-semibold rounded-lg shadow-md hover:bg-orange-600',
+                            ]
+                        ) ?>
+                    <?php foreach ($podcast->platforms as $platform): ?>
+                        <a href="<?= $platform->link_url ?>" title="<?= $platform->label ?>" target="_blank" rel="noopener noreferrer" class="ml-2">
+                        <?= platform_icon($platform->icon_filename, 'h-8') ?>
+                        </a>
+                        <?php endforeach; ?>
+                    </div>
+                        <div class="mb-2 opacity-75">
+                        <?= $podcast->description_html ?>
+                    </div>
+                    <span class="px-2 py-1 text-sm text-gray-700 bg-gray-200 rounded">
+                        <?= lang(
+                            'Podcast.category_options.' .
+                                $podcast->category->code
+                        ) ?>
+                    </span>
                 </div>
-            </article>
-        <?php endforeach; ?>
-    <?php else: ?>
-        <p class="italic"><?= lang('Podcast.no_episode') ?></p>
-    <?php endif; ?>
-</section>
+            </div>
+        </header>
 
+<<<<<<< HEAD
 
 <?= $this->endSection()
 ?>
+=======
+        <section class="flex flex-col">
+            <nav class="inline-flex justify-center px-4 bg-gray-100 border-b">
+                <?php foreach ($episodesNav as $link): ?>
+                    <?= anchor(
+                        $link['route'],
+                        $link['label'] .
+                            ' (' .
+                            $link['number_of_episodes'] .
+                            ')',
+                        [
+                            'class' =>
+                                'px-2 py-1 font-semibold ' .
+                                ($link['is_active']
+                                    ? 'border-b-2 border-gray-600'
+                                    : 'text-gray-600 hover:text-gray-900'),
+                        ]
+                    ) ?>
+                <?php endforeach; ?>
+            </nav>
+            <div class="container py-6 mx-auto">
+                <?php if ($episodes): ?>
+                    <h1 class="px-4 mb-2 text-xl text-center">
+                    <?php if ($activeQuery['type'] == 'year'): ?>
+                        <?= lang('Podcast.list_of_episodes_year', [
+                            'year' => $activeQuery['value'],
+                        ]) ?> (<?= count($episodes) ?>)
+                    <?php elseif ($activeQuery['type'] == 'season'): ?>
+                        <?= lang('Podcast.list_of_episodes_season', [
+                            'seasonNumber' => $activeQuery['value'],
+                        ]) ?> (<?= count($episodes) ?>)
+                    <?php endif; ?>
+                    </h1>
+                    <?php foreach ($episodes as $episode): ?>
+                        <article class="flex w-full max-w-lg p-4 mx-auto">
+                            <img loading="lazy" src="<?= $episode->image_url ?>" alt="<?= $episode->title ?>" class="object-cover w-20 h-20 mr-2 rounded-lg" />
+                            <div class="flex flex-col flex-1">
+                                <a class="text-sm hover:underline" href="<?= $episode->link ?>">
+                                    <h2 class="inline-flex justify-between w-full font-bold leading-none group">
+                                        <span class="mr-1 group-hover:underline"><?= $episode->title ?></span>
+                                        <span class="font-bold text-gray-600">#<?= $episode->number ?></span>
+                                    </h2>
+                                </a>
+                                <div class="mb-2 text-xs">
+                                    <time
+                                    pubdate
+                                    datetime="<?= $episode->published_at->toDateTimeString() ?>"
+                                    title="<?= $episode->published_at ?>">
+                                    <?= lang('Common.mediumDate', [
+                                        $episode->published_at,
+                                    ]) ?>
+                                    </time>
+                                    <span class="mx-1">•</span>
+                                    <time datetime="PT<?= $episode->enclosure_duration ?>S">
+                                        <?= lang('Common.duration', [
+                                            $episode->enclosure_duration,
+                                        ]) ?>
+                                    </time>
+                                </div>
+                                <audio controls preload="none" class="w-full mt-auto">
+                                    <source src="<?= $episode->enclosure_url ?>" type="<?= $episode->enclosure_type ?>">
+                                    Your browser does not support the audio tag.
+                                </audio>
+                            </div>
+                        </article>
+                    <?php endforeach; ?>
+                <?php else: ?>
+                    <h1 class="px-4 mb-2 text-xl text-center"><?= lang(
+                        'Podcast.no_episode'
+                    ) ?></h1>
+                    <p class="italic text-center"><?= lang(
+                        'Podcast.no_episode_hint'
+                    ) ?></p>
+                <?php endif; ?>
+            </div>
+        </section>
+    </main>
+    <footer class="px-2 py-4 border-t ">
+        <div class="container flex flex-col items-center justify-between mx-auto text-sm md:flex-row ">
+            <?= render_page_links('inline-flex mb-4 md:mb-0') ?>
+            <div class="flex flex-col items-center text-xs md:items-end">
+                <p><?= $podcast->copyright ?></p>
+                <p><?= lang('Common.powered_by', [
+                    'castopod' =>
+                        '<a class="underline hover:no-underline" href="https://castopod.org" target="_blank" rel="noreferrer noopener">Castopod</a>',
+                ]) ?></p>
+            </div>
+        </div>
+    </footer>
+</body>
+>>>>>>> ecc68b2... feat(public-ui): adapt wireframes to public podcast and episode pages
diff --git a/package-lock.json b/package-lock.json
index a47fc27e81..ade2bd829e 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -14,38 +14,30 @@
       }
     },
     "@babel/compat-data": {
-      "version": "7.10.5",
-      "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.10.5.tgz",
-      "integrity": "sha512-mPVoWNzIpYJHbWje0if7Ck36bpbtTvIxOi9+6WSK9wjGEXearAqlwBoTQvVjsAY2VIwgcs8V940geY3okzRCEw==",
+      "version": "7.11.0",
+      "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.11.0.tgz",
+      "integrity": "sha512-TPSvJfv73ng0pfnEOh17bYMPQbI95+nGWc71Ss4vZdRBHTDqmM9Z8ZV4rYz8Ks7sfzc95n30k6ODIq5UGnXcYQ==",
       "dev": true,
       "requires": {
         "browserslist": "^4.12.0",
         "invariant": "^2.2.4",
         "semver": "^5.5.0"
-      },
-      "dependencies": {
-        "semver": {
-          "version": "5.7.1",
-          "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
-          "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
-          "dev": true
-        }
       }
     },
     "@babel/core": {
-      "version": "7.10.5",
-      "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.10.5.tgz",
-      "integrity": "sha512-O34LQooYVDXPl7QWCdW9p4NR+QlzOr7xShPPJz8GsuCU3/8ua/wqTr7gmnxXv+WBESiGU/G5s16i6tUvHkNb+w==",
+      "version": "7.11.4",
+      "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.11.4.tgz",
+      "integrity": "sha512-5deljj5HlqRXN+5oJTY7Zs37iH3z3b++KjiKtIsJy1NrjOOVSEaJHEetLBhyu0aQOSNNZ/0IuEAan9GzRuDXHg==",
       "dev": true,
       "requires": {
         "@babel/code-frame": "^7.10.4",
-        "@babel/generator": "^7.10.5",
-        "@babel/helper-module-transforms": "^7.10.5",
+        "@babel/generator": "^7.11.4",
+        "@babel/helper-module-transforms": "^7.11.0",
         "@babel/helpers": "^7.10.4",
-        "@babel/parser": "^7.10.5",
+        "@babel/parser": "^7.11.4",
         "@babel/template": "^7.10.4",
-        "@babel/traverse": "^7.10.5",
-        "@babel/types": "^7.10.5",
+        "@babel/traverse": "^7.11.0",
+        "@babel/types": "^7.11.0",
         "convert-source-map": "^1.7.0",
         "debug": "^4.1.0",
         "gensync": "^1.0.0-beta.1",
@@ -65,6 +57,26 @@
             "@babel/highlight": "^7.10.4"
           }
         },
+        "@babel/generator": {
+          "version": "7.11.4",
+          "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.11.4.tgz",
+          "integrity": "sha512-Rn26vueFx0eOoz7iifCN2UHT6rGtnkSGWSoDRIy8jZN3B91PzeSULbswfLoOWuTuAcNwpG/mxy+uCTDnZ9Mp1g==",
+          "dev": true,
+          "requires": {
+            "@babel/types": "^7.11.0",
+            "jsesc": "^2.5.1",
+            "source-map": "^0.5.0"
+          }
+        },
+        "@babel/helper-split-export-declaration": {
+          "version": "7.11.0",
+          "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.11.0.tgz",
+          "integrity": "sha512-74Vejvp6mHkGE+m+k5vHY93FX2cAtrw1zXrZXRlG4l410Nm9PxfEiVTn1PjDPV5SnmieiueY4AFg2xqhNFuuZg==",
+          "dev": true,
+          "requires": {
+            "@babel/types": "^7.11.0"
+          }
+        },
         "@babel/helper-validator-identifier": {
           "version": "7.10.4",
           "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz",
@@ -82,6 +94,40 @@
             "js-tokens": "^4.0.0"
           }
         },
+        "@babel/parser": {
+          "version": "7.11.4",
+          "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.11.4.tgz",
+          "integrity": "sha512-MggwidiH+E9j5Sh8pbrX5sJvMcsqS5o+7iB42M9/k0CD63MjYbdP4nhSh7uB5wnv2/RVzTZFTxzF/kIa5mrCqA==",
+          "dev": true
+        },
+        "@babel/traverse": {
+          "version": "7.11.0",
+          "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.11.0.tgz",
+          "integrity": "sha512-ZB2V+LskoWKNpMq6E5UUCrjtDUh5IOTAyIl0dTjIEoXum/iKWkoIEKIRDnUucO6f+2FzNkE0oD4RLKoPIufDtg==",
+          "dev": true,
+          "requires": {
+            "@babel/code-frame": "^7.10.4",
+            "@babel/generator": "^7.11.0",
+            "@babel/helper-function-name": "^7.10.4",
+            "@babel/helper-split-export-declaration": "^7.11.0",
+            "@babel/parser": "^7.11.0",
+            "@babel/types": "^7.11.0",
+            "debug": "^4.1.0",
+            "globals": "^11.1.0",
+            "lodash": "^4.17.19"
+          }
+        },
+        "@babel/types": {
+          "version": "7.11.0",
+          "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.0.tgz",
+          "integrity": "sha512-O53yME4ZZI0jO1EVGtF1ePGl0LHirG4P1ibcD80XyzZcKhcMFeCXmh4Xb1ifGBIV233Qg12x4rBfQgA+tmOukA==",
+          "dev": true,
+          "requires": {
+            "@babel/helper-validator-identifier": "^7.10.4",
+            "lodash": "^4.17.19",
+            "to-fast-properties": "^2.0.0"
+          }
+        },
         "chalk": {
           "version": "2.4.2",
           "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
@@ -93,31 +139,10 @@
             "supports-color": "^5.3.0"
           }
         },
-        "debug": {
-          "version": "4.1.1",
-          "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
-          "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
-          "dev": true,
-          "requires": {
-            "ms": "^2.1.1"
-          }
-        },
         "lodash": {
-          "version": "4.17.19",
-          "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz",
-          "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==",
-          "dev": true
-        },
-        "ms": {
-          "version": "2.1.2",
-          "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
-          "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
-          "dev": true
-        },
-        "semver": {
-          "version": "5.7.1",
-          "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
-          "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+          "version": "4.17.20",
+          "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz",
+          "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==",
           "dev": true
         }
       }
@@ -163,14 +188,6 @@
         "invariant": "^2.2.4",
         "levenary": "^1.1.1",
         "semver": "^5.5.0"
-      },
-      "dependencies": {
-        "semver": {
-          "version": "5.7.1",
-          "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
-          "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
-          "dev": true
-        }
       }
     },
     "@babel/helper-create-class-features-plugin": {
@@ -210,20 +227,19 @@
       },
       "dependencies": {
         "lodash": {
-          "version": "4.17.19",
-          "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz",
-          "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==",
+          "version": "4.17.20",
+          "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz",
+          "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==",
           "dev": true
         }
       }
     },
     "@babel/helper-explode-assignable-expression": {
-      "version": "7.10.4",
-      "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.10.4.tgz",
-      "integrity": "sha512-4K71RyRQNPRrR85sr5QY4X3VwG4wtVoXZB9+L3r1Gp38DhELyHCtovqydRi7c1Ovb17eRGiQ/FD5s8JdU0Uy5A==",
+      "version": "7.11.4",
+      "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.11.4.tgz",
+      "integrity": "sha512-ux9hm3zR4WV1Y3xXxXkdG/0gxF9nvI0YVmKVhvK9AfMoaQkemL3sJpXw+Xbz65azo8qJiEz2XVDUpK3KYhH3ZQ==",
       "dev": true,
       "requires": {
-        "@babel/traverse": "^7.10.4",
         "@babel/types": "^7.10.4"
       }
     },
@@ -275,24 +291,50 @@
       }
     },
     "@babel/helper-module-transforms": {
-      "version": "7.10.5",
-      "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.10.5.tgz",
-      "integrity": "sha512-4P+CWMJ6/j1W915ITJaUkadLObmCRRSC234uctJfn/vHrsLNxsR8dwlcXv9ZhJWzl77awf+mWXSZEKt5t0OnlA==",
+      "version": "7.11.0",
+      "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.11.0.tgz",
+      "integrity": "sha512-02EVu8COMuTRO1TAzdMtpBPbe6aQ1w/8fePD2YgQmxZU4gpNWaL9gK3Jp7dxlkUlUCJOTaSeA+Hrm1BRQwqIhg==",
       "dev": true,
       "requires": {
         "@babel/helper-module-imports": "^7.10.4",
         "@babel/helper-replace-supers": "^7.10.4",
         "@babel/helper-simple-access": "^7.10.4",
-        "@babel/helper-split-export-declaration": "^7.10.4",
+        "@babel/helper-split-export-declaration": "^7.11.0",
         "@babel/template": "^7.10.4",
-        "@babel/types": "^7.10.5",
+        "@babel/types": "^7.11.0",
         "lodash": "^4.17.19"
       },
       "dependencies": {
+        "@babel/helper-split-export-declaration": {
+          "version": "7.11.0",
+          "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.11.0.tgz",
+          "integrity": "sha512-74Vejvp6mHkGE+m+k5vHY93FX2cAtrw1zXrZXRlG4l410Nm9PxfEiVTn1PjDPV5SnmieiueY4AFg2xqhNFuuZg==",
+          "dev": true,
+          "requires": {
+            "@babel/types": "^7.11.0"
+          }
+        },
+        "@babel/helper-validator-identifier": {
+          "version": "7.10.4",
+          "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz",
+          "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==",
+          "dev": true
+        },
+        "@babel/types": {
+          "version": "7.11.0",
+          "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.0.tgz",
+          "integrity": "sha512-O53yME4ZZI0jO1EVGtF1ePGl0LHirG4P1ibcD80XyzZcKhcMFeCXmh4Xb1ifGBIV233Qg12x4rBfQgA+tmOukA==",
+          "dev": true,
+          "requires": {
+            "@babel/helper-validator-identifier": "^7.10.4",
+            "lodash": "^4.17.19",
+            "to-fast-properties": "^2.0.0"
+          }
+        },
         "lodash": {
-          "version": "4.17.19",
-          "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz",
-          "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==",
+          "version": "4.17.20",
+          "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz",
+          "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==",
           "dev": true
         }
       }
@@ -322,23 +364,22 @@
       },
       "dependencies": {
         "lodash": {
-          "version": "4.17.19",
-          "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz",
-          "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==",
+          "version": "4.17.20",
+          "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz",
+          "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==",
           "dev": true
         }
       }
     },
     "@babel/helper-remap-async-to-generator": {
-      "version": "7.10.4",
-      "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.10.4.tgz",
-      "integrity": "sha512-86Lsr6NNw3qTNl+TBcF1oRZMaVzJtbWTyTko+CQL/tvNvcGYEFKbLXDPxtW0HKk3McNOk4KzY55itGWCAGK5tg==",
+      "version": "7.11.4",
+      "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.11.4.tgz",
+      "integrity": "sha512-tR5vJ/vBa9wFy3m5LLv2faapJLnDFxNWff2SAYkSE4rLUdbp7CdObYFgI7wK4T/Mj4UzpjPwzR8Pzmr5m7MHGA==",
       "dev": true,
       "requires": {
         "@babel/helper-annotate-as-pure": "^7.10.4",
         "@babel/helper-wrap-function": "^7.10.4",
         "@babel/template": "^7.10.4",
-        "@babel/traverse": "^7.10.4",
         "@babel/types": "^7.10.4"
       }
     },
@@ -364,6 +405,40 @@
         "@babel/types": "^7.10.4"
       }
     },
+    "@babel/helper-skip-transparent-expression-wrappers": {
+      "version": "7.11.0",
+      "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.11.0.tgz",
+      "integrity": "sha512-0XIdiQln4Elglgjbwo9wuJpL/K7AGCY26kmEt0+pRP0TAj4jjyNq1MjoRvikrTVqKcx4Gysxt4cXvVFXP/JO2Q==",
+      "dev": true,
+      "requires": {
+        "@babel/types": "^7.11.0"
+      },
+      "dependencies": {
+        "@babel/helper-validator-identifier": {
+          "version": "7.10.4",
+          "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz",
+          "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==",
+          "dev": true
+        },
+        "@babel/types": {
+          "version": "7.11.0",
+          "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.0.tgz",
+          "integrity": "sha512-O53yME4ZZI0jO1EVGtF1ePGl0LHirG4P1ibcD80XyzZcKhcMFeCXmh4Xb1ifGBIV233Qg12x4rBfQgA+tmOukA==",
+          "dev": true,
+          "requires": {
+            "@babel/helper-validator-identifier": "^7.10.4",
+            "lodash": "^4.17.19",
+            "to-fast-properties": "^2.0.0"
+          }
+        },
+        "lodash": {
+          "version": "4.17.20",
+          "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz",
+          "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==",
+          "dev": true
+        }
+      }
+    },
     "@babel/helper-split-export-declaration": {
       "version": "7.10.4",
       "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.10.4.tgz",
@@ -472,6 +547,16 @@
         "@babel/plugin-syntax-dynamic-import": "^7.8.0"
       }
     },
+    "@babel/plugin-proposal-export-namespace-from": {
+      "version": "7.10.4",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.10.4.tgz",
+      "integrity": "sha512-aNdf0LY6/3WXkhh0Fdb6Zk9j1NMD8ovj3F6r0+3j837Pn1S1PdNtcwJ5EG9WkVPNHPxyJDaxMaAOVq4eki0qbg==",
+      "dev": true,
+      "requires": {
+        "@babel/helper-plugin-utils": "^7.10.4",
+        "@babel/plugin-syntax-export-namespace-from": "^7.8.3"
+      }
+    },
     "@babel/plugin-proposal-json-strings": {
       "version": "7.10.4",
       "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.10.4.tgz",
@@ -482,6 +567,16 @@
         "@babel/plugin-syntax-json-strings": "^7.8.0"
       }
     },
+    "@babel/plugin-proposal-logical-assignment-operators": {
+      "version": "7.11.0",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.11.0.tgz",
+      "integrity": "sha512-/f8p4z+Auz0Uaf+i8Ekf1iM7wUNLcViFUGiPxKeXvxTSl63B875YPiVdUDdem7hREcI0E0kSpEhS8tF5RphK7Q==",
+      "dev": true,
+      "requires": {
+        "@babel/helper-plugin-utils": "^7.10.4",
+        "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4"
+      }
+    },
     "@babel/plugin-proposal-nullish-coalescing-operator": {
       "version": "7.10.4",
       "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.10.4.tgz",
@@ -503,9 +598,9 @@
       }
     },
     "@babel/plugin-proposal-object-rest-spread": {
-      "version": "7.10.4",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.10.4.tgz",
-      "integrity": "sha512-6vh4SqRuLLarjgeOf4EaROJAHjvu9Gl+/346PbDH9yWbJyfnJ/ah3jmYKYtswEyCoWZiidvVHjHshd4WgjB9BA==",
+      "version": "7.11.0",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.11.0.tgz",
+      "integrity": "sha512-wzch41N4yztwoRw0ak+37wxwJM2oiIiy6huGCoqkvSTA9acYWcPfn9Y4aJqmFFJ70KTJUu29f3DQ43uJ9HXzEA==",
       "dev": true,
       "requires": {
         "@babel/helper-plugin-utils": "^7.10.4",
@@ -524,12 +619,13 @@
       }
     },
     "@babel/plugin-proposal-optional-chaining": {
-      "version": "7.10.4",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.10.4.tgz",
-      "integrity": "sha512-ZIhQIEeavTgouyMSdZRap4VPPHqJJ3NEs2cuHs5p0erH+iz6khB0qfgU8g7UuJkG88+fBMy23ZiU+nuHvekJeQ==",
+      "version": "7.11.0",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.11.0.tgz",
+      "integrity": "sha512-v9fZIu3Y8562RRwhm1BbMRxtqZNFmFA2EG+pT2diuU8PT3H6T/KXoZ54KgYisfOFZHV6PfvAiBIZ9Rcz+/JCxA==",
       "dev": true,
       "requires": {
         "@babel/helper-plugin-utils": "^7.10.4",
+        "@babel/helper-skip-transparent-expression-wrappers": "^7.11.0",
         "@babel/plugin-syntax-optional-chaining": "^7.8.0"
       }
     },
@@ -580,6 +676,15 @@
         "@babel/helper-plugin-utils": "^7.8.0"
       }
     },
+    "@babel/plugin-syntax-export-namespace-from": {
+      "version": "7.8.3",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz",
+      "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==",
+      "dev": true,
+      "requires": {
+        "@babel/helper-plugin-utils": "^7.8.3"
+      }
+    },
     "@babel/plugin-syntax-json-strings": {
       "version": "7.8.3",
       "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz",
@@ -589,6 +694,15 @@
         "@babel/helper-plugin-utils": "^7.8.0"
       }
     },
+    "@babel/plugin-syntax-logical-assignment-operators": {
+      "version": "7.10.4",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz",
+      "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==",
+      "dev": true,
+      "requires": {
+        "@babel/helper-plugin-utils": "^7.10.4"
+      }
+    },
     "@babel/plugin-syntax-nullish-coalescing-operator": {
       "version": "7.8.3",
       "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz",
@@ -682,9 +796,9 @@
       }
     },
     "@babel/plugin-transform-block-scoping": {
-      "version": "7.10.5",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.10.5.tgz",
-      "integrity": "sha512-6Ycw3hjpQti0qssQcA6AMSFDHeNJ++R6dIMnpRqUjFeBBTmTDPa8zgF90OVfTvAo11mXZTlVUViY1g8ffrURLg==",
+      "version": "7.11.1",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.11.1.tgz",
+      "integrity": "sha512-00dYeDE0EVEHuuM+26+0w/SCL0BH2Qy7LwHuI4Hi4MH5gkC8/AqMN5uWFJIsoXZrAphiMm1iXzBw6L2T+eA0ew==",
       "dev": true,
       "requires": {
         "@babel/helper-plugin-utils": "^7.10.4"
@@ -910,12 +1024,13 @@
       }
     },
     "@babel/plugin-transform-spread": {
-      "version": "7.10.4",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.10.4.tgz",
-      "integrity": "sha512-1e/51G/Ni+7uH5gktbWv+eCED9pP8ZpRhZB3jOaI3mmzfvJTWHkuyYTv0Z5PYtyM+Tr2Ccr9kUdQxn60fI5WuQ==",
+      "version": "7.11.0",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.11.0.tgz",
+      "integrity": "sha512-UwQYGOqIdQJe4aWNyS7noqAnN2VbaczPLiEtln+zPowRNlD+79w3oi2TWfYe0eZgd+gjZCbsydN7lzWysDt+gw==",
       "dev": true,
       "requires": {
-        "@babel/helper-plugin-utils": "^7.10.4"
+        "@babel/helper-plugin-utils": "^7.10.4",
+        "@babel/helper-skip-transparent-expression-wrappers": "^7.11.0"
       }
     },
     "@babel/plugin-transform-sticky-regex": {
@@ -978,30 +1093,34 @@
       }
     },
     "@babel/preset-env": {
-      "version": "7.10.4",
-      "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.10.4.tgz",
-      "integrity": "sha512-tcmuQ6vupfMZPrLrc38d0sF2OjLT3/bZ0dry5HchNCQbrokoQi4reXqclvkkAT5b+gWc23meVWpve5P/7+w/zw==",
+      "version": "7.11.0",
+      "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.11.0.tgz",
+      "integrity": "sha512-2u1/k7rG/gTh02dylX2kL3S0IJNF+J6bfDSp4DI2Ma8QN6Y9x9pmAax59fsCk6QUQG0yqH47yJWA+u1I1LccAg==",
       "dev": true,
       "requires": {
-        "@babel/compat-data": "^7.10.4",
+        "@babel/compat-data": "^7.11.0",
         "@babel/helper-compilation-targets": "^7.10.4",
         "@babel/helper-module-imports": "^7.10.4",
         "@babel/helper-plugin-utils": "^7.10.4",
         "@babel/plugin-proposal-async-generator-functions": "^7.10.4",
         "@babel/plugin-proposal-class-properties": "^7.10.4",
         "@babel/plugin-proposal-dynamic-import": "^7.10.4",
+        "@babel/plugin-proposal-export-namespace-from": "^7.10.4",
         "@babel/plugin-proposal-json-strings": "^7.10.4",
+        "@babel/plugin-proposal-logical-assignment-operators": "^7.11.0",
         "@babel/plugin-proposal-nullish-coalescing-operator": "^7.10.4",
         "@babel/plugin-proposal-numeric-separator": "^7.10.4",
-        "@babel/plugin-proposal-object-rest-spread": "^7.10.4",
+        "@babel/plugin-proposal-object-rest-spread": "^7.11.0",
         "@babel/plugin-proposal-optional-catch-binding": "^7.10.4",
-        "@babel/plugin-proposal-optional-chaining": "^7.10.4",
+        "@babel/plugin-proposal-optional-chaining": "^7.11.0",
         "@babel/plugin-proposal-private-methods": "^7.10.4",
         "@babel/plugin-proposal-unicode-property-regex": "^7.10.4",
         "@babel/plugin-syntax-async-generators": "^7.8.0",
         "@babel/plugin-syntax-class-properties": "^7.10.4",
         "@babel/plugin-syntax-dynamic-import": "^7.8.0",
+        "@babel/plugin-syntax-export-namespace-from": "^7.8.3",
         "@babel/plugin-syntax-json-strings": "^7.8.0",
+        "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4",
         "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.0",
         "@babel/plugin-syntax-numeric-separator": "^7.10.4",
         "@babel/plugin-syntax-object-rest-spread": "^7.8.0",
@@ -1034,14 +1153,14 @@
         "@babel/plugin-transform-regenerator": "^7.10.4",
         "@babel/plugin-transform-reserved-words": "^7.10.4",
         "@babel/plugin-transform-shorthand-properties": "^7.10.4",
-        "@babel/plugin-transform-spread": "^7.10.4",
+        "@babel/plugin-transform-spread": "^7.11.0",
         "@babel/plugin-transform-sticky-regex": "^7.10.4",
         "@babel/plugin-transform-template-literals": "^7.10.4",
         "@babel/plugin-transform-typeof-symbol": "^7.10.4",
         "@babel/plugin-transform-unicode-escapes": "^7.10.4",
         "@babel/plugin-transform-unicode-regex": "^7.10.4",
         "@babel/preset-modules": "^0.1.3",
-        "@babel/types": "^7.10.4",
+        "@babel/types": "^7.11.0",
         "browserslist": "^4.12.0",
         "core-js-compat": "^3.6.2",
         "invariant": "^2.2.2",
@@ -1049,18 +1168,35 @@
         "semver": "^5.5.0"
       },
       "dependencies": {
-        "semver": {
-          "version": "5.7.1",
-          "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
-          "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+        "@babel/helper-validator-identifier": {
+          "version": "7.10.4",
+          "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz",
+          "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==",
+          "dev": true
+        },
+        "@babel/types": {
+          "version": "7.11.0",
+          "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.0.tgz",
+          "integrity": "sha512-O53yME4ZZI0jO1EVGtF1ePGl0LHirG4P1ibcD80XyzZcKhcMFeCXmh4Xb1ifGBIV233Qg12x4rBfQgA+tmOukA==",
+          "dev": true,
+          "requires": {
+            "@babel/helper-validator-identifier": "^7.10.4",
+            "lodash": "^4.17.19",
+            "to-fast-properties": "^2.0.0"
+          }
+        },
+        "lodash": {
+          "version": "4.17.20",
+          "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz",
+          "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==",
           "dev": true
         }
       }
     },
     "@babel/preset-modules": {
-      "version": "0.1.3",
-      "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.3.tgz",
-      "integrity": "sha512-Ra3JXOHBq2xd56xSF7lMKXdjBn3T772Y1Wet3yWnkDly9zHvJki029tAFzvAAK5cf4YV3yoxuP61crYRol6SVg==",
+      "version": "0.1.4",
+      "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.4.tgz",
+      "integrity": "sha512-J36NhwnfdzpmH41M1DrnkkgAqhZaqr/NBdPfQ677mLzlaXo+oDiv1deyCDtgAhz8p328otdob0Du7+xgHGZbKg==",
       "dev": true,
       "requires": {
         "@babel/helper-plugin-utils": "^7.0.0",
@@ -1250,59 +1386,25 @@
       }
     },
     "@commitlint/cli": {
-      "version": "9.0.1",
-      "resolved": "https://registry.npmjs.org/@commitlint/cli/-/cli-9.0.1.tgz",
-      "integrity": "sha512-BVOc/BY0FMmKTTH5oUVE0ukhPWDFf364FiYKk3GlXLOGTZPTXQ/9ncB2eMOaCF0PdcEVY4VoMjyoRSgcVapCMg==",
+      "version": "9.1.2",
+      "resolved": "https://registry.npmjs.org/@commitlint/cli/-/cli-9.1.2.tgz",
+      "integrity": "sha512-ctRrrPqjZ8r4Vc4FXpPaScEpkPwfvB0Us3NK2SD2AnLwXGMxOLFTabDmNySU1Xc40ud2CmJsaV8lpavvzs8ZZA==",
       "dev": true,
       "requires": {
         "@babel/runtime": "^7.9.6",
-        "@commitlint/format": "^9.0.1",
-        "@commitlint/lint": "^9.0.1",
-        "@commitlint/load": "^9.0.1",
-        "@commitlint/read": "^9.0.1",
-        "chalk": "3.0.0",
+        "@commitlint/format": "^9.1.2",
+        "@commitlint/lint": "^9.1.2",
+        "@commitlint/load": "^9.1.2",
+        "@commitlint/read": "^9.1.2",
+        "chalk": "4.1.0",
         "core-js": "^3.6.1",
         "get-stdin": "7.0.0",
-        "lodash": "^4.17.15",
-        "meow": "5.0.0",
-        "regenerator-runtime": "0.13.3",
+        "lodash": "^4.17.19",
         "resolve-from": "5.0.0",
-        "resolve-global": "1.0.0"
+        "resolve-global": "1.0.0",
+        "yargs": "^15.1.0"
       },
       "dependencies": {
-        "@commitlint/execute-rule": {
-          "version": "9.0.1",
-          "resolved": "https://registry.npmjs.org/@commitlint/execute-rule/-/execute-rule-9.0.1.tgz",
-          "integrity": "sha512-fxnLadXs59qOBE9dInfQjQ4DmbGToQ0NjfqqmN6N8qS+KsCecO6N0mMUrC95et9xTeimFRr+0l9UMfmRVHNS/w==",
-          "dev": true
-        },
-        "@commitlint/load": {
-          "version": "9.0.1",
-          "resolved": "https://registry.npmjs.org/@commitlint/load/-/load-9.0.1.tgz",
-          "integrity": "sha512-6ix/pUjVAggmDLTcnpyk0bgY3H9UBBTsEeFvTkHV+WQ6LNIxsQk8SwEOEZzWHUqt0pxqMQeiUgYeSZsSw2+uiw==",
-          "dev": true,
-          "requires": {
-            "@commitlint/execute-rule": "^9.0.1",
-            "@commitlint/resolve-extends": "^9.0.1",
-            "@commitlint/types": "^9.0.1",
-            "chalk": "3.0.0",
-            "cosmiconfig": "^6.0.0",
-            "lodash": "^4.17.15",
-            "resolve-from": "^5.0.0"
-          }
-        },
-        "@commitlint/resolve-extends": {
-          "version": "9.0.1",
-          "resolved": "https://registry.npmjs.org/@commitlint/resolve-extends/-/resolve-extends-9.0.1.tgz",
-          "integrity": "sha512-o6Lya2ILg1tEfWatS5x8w4ImvDzwb1whxsr2c/cxVCFqLF4hxHHHniZ0NJ+HFhYa1kBsYeKlD1qn9fHX5Y1+PQ==",
-          "dev": true,
-          "requires": {
-            "import-fresh": "^3.0.0",
-            "lodash": "^4.17.15",
-            "resolve-from": "^5.0.0",
-            "resolve-global": "^1.0.0"
-          }
-        },
         "ansi-styles": {
           "version": "4.2.1",
           "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz",
@@ -1314,9 +1416,9 @@
           }
         },
         "chalk": {
-          "version": "3.0.0",
-          "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz",
-          "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==",
+          "version": "4.1.0",
+          "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz",
+          "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==",
           "dev": true,
           "requires": {
             "ansi-styles": "^4.1.0",
@@ -1338,65 +1440,16 @@
           "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
           "dev": true
         },
-        "core-js": {
-          "version": "3.6.5",
-          "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.6.5.tgz",
-          "integrity": "sha512-vZVEEwZoIsI+vPEuoF9Iqf5H7/M3eeQqWlQnYa8FSKKePuYTf5MWnxb5SDAzCa60b3JBRS5g9b+Dq7b1y/RCrA==",
-          "dev": true
-        },
-        "cosmiconfig": {
-          "version": "6.0.0",
-          "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz",
-          "integrity": "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==",
-          "dev": true,
-          "requires": {
-            "@types/parse-json": "^4.0.0",
-            "import-fresh": "^3.1.0",
-            "parse-json": "^5.0.0",
-            "path-type": "^4.0.0",
-            "yaml": "^1.7.2"
-          }
-        },
         "has-flag": {
           "version": "4.0.0",
           "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
           "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
           "dev": true
         },
-        "import-fresh": {
-          "version": "3.2.1",
-          "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.1.tgz",
-          "integrity": "sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ==",
-          "dev": true,
-          "requires": {
-            "parent-module": "^1.0.0",
-            "resolve-from": "^4.0.0"
-          },
-          "dependencies": {
-            "resolve-from": {
-              "version": "4.0.0",
-              "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
-              "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
-              "dev": true
-            }
-          }
-        },
-        "parse-json": {
-          "version": "5.0.0",
-          "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.0.0.tgz",
-          "integrity": "sha512-OOY5b7PAEFV0E2Fir1KOkxchnZNCdowAJgQ5NuxjpBKTRP3pQhwkrkxqQjeoKJ+fO7bCpmIZaogI4eZGDMEGOw==",
-          "dev": true,
-          "requires": {
-            "@babel/code-frame": "^7.0.0",
-            "error-ex": "^1.3.1",
-            "json-parse-better-errors": "^1.0.1",
-            "lines-and-columns": "^1.1.6"
-          }
-        },
-        "regenerator-runtime": {
-          "version": "0.13.3",
-          "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.3.tgz",
-          "integrity": "sha512-naKIZz2GQ8JWh///G7L3X6LaQUAMp2lvb1rvwwsURe/VXwD6VMfr+/1NuNw3ag8v2kY1aQ/go5SNn79O9JU7yw==",
+        "lodash": {
+          "version": "4.17.20",
+          "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz",
+          "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==",
           "dev": true
         },
         "resolve-from": {
@@ -1417,54 +1470,107 @@
       }
     },
     "@commitlint/config-conventional": {
-      "version": "9.0.1",
-      "resolved": "https://registry.npmjs.org/@commitlint/config-conventional/-/config-conventional-9.0.1.tgz",
-      "integrity": "sha512-5rGu8aT4nRhWKrd5SpXqKJKLM07wXi4X5KVD9EEAuucAh2iZgfJJK9HKZNKGEKLKBQSWlnXE6UvkeEjJgi6TPQ==",
+      "version": "9.1.2",
+      "resolved": "https://registry.npmjs.org/@commitlint/config-conventional/-/config-conventional-9.1.2.tgz",
+      "integrity": "sha512-2zfnsrBJuCNJEKMEmltYlCUEoQNE4anvEBI/SYEuiB1JYXYaELijobDBpqhUVjh5NEpprNTY16oMZat6ewnxOg==",
       "dev": true,
       "requires": {
-        "conventional-changelog-conventionalcommits": "4.2.3"
+        "conventional-changelog-conventionalcommits": "4.3.0"
       }
     },
     "@commitlint/ensure": {
-      "version": "9.0.1",
-      "resolved": "https://registry.npmjs.org/@commitlint/ensure/-/ensure-9.0.1.tgz",
-      "integrity": "sha512-z8SEkfbn0lMnAtt7Hp3A8hE3CRCDsg+Eu3Xj1UJakOyCPJgHE1/vEyM2DO2dxTXVKuttiHeLDnUSHCxklm78Ng==",
+      "version": "9.1.2",
+      "resolved": "https://registry.npmjs.org/@commitlint/ensure/-/ensure-9.1.2.tgz",
+      "integrity": "sha512-hwQICwpNSTsZgj/1/SdPvYAzhwjwgCJI4vLbT879+Jc+AJ6sj2bUDGw/F89vzgKz1VnaMm4D65bNhoWhG3pdhQ==",
       "dev": true,
       "requires": {
-        "@commitlint/types": "^9.0.1",
-        "lodash": "^4.17.15"
+        "@commitlint/types": "^9.1.2",
+        "lodash": "^4.17.19"
+      },
+      "dependencies": {
+        "lodash": {
+          "version": "4.17.20",
+          "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz",
+          "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==",
+          "dev": true
+        }
       }
     },
     "@commitlint/execute-rule": {
-      "version": "8.3.4",
-      "resolved": "https://registry.npmjs.org/@commitlint/execute-rule/-/execute-rule-8.3.4.tgz",
-      "integrity": "sha512-f4HigYjeIBn9f7OuNv5zh2y5vWaAhNFrfeul8CRJDy82l3Y+09lxOTGxfF3uMXKrZq4LmuK6qvvRCZ8mUrVvzQ==",
-      "dev": true,
-      "optional": true
+      "version": "9.1.2",
+      "resolved": "https://registry.npmjs.org/@commitlint/execute-rule/-/execute-rule-9.1.2.tgz",
+      "integrity": "sha512-NGbeo0KCVYo1yj9vVPFHv6RGFpIF6wcQxpFYUKGIzZVV9Vz1WyiKS689JXa99Dt1aN0cZlEJJLnTNDIgYls0Vg==",
+      "dev": true
     },
     "@commitlint/format": {
-      "version": "9.0.1",
-      "resolved": "https://registry.npmjs.org/@commitlint/format/-/format-9.0.1.tgz",
-      "integrity": "sha512-5oY7Jyve7Bfnx0CdbxFcpRKq92vUANFq3MVbz/ZTgvuYgUeMuYsSEwW6MJtOgOhHBQ2vZP/uPdxwmU+6pWZHcg==",
+      "version": "9.1.2",
+      "resolved": "https://registry.npmjs.org/@commitlint/format/-/format-9.1.2.tgz",
+      "integrity": "sha512-+ZWTOSGEU6dbn3NRh1q7sY5K5QLiSs7E2uSzuYnWHXcQk8nlTvnE0ibwMCQxdKLaOTZiN57fHM/7M9Re2gsRuw==",
+      "dev": true,
+      "requires": {
+        "@commitlint/types": "^9.1.2",
+        "chalk": "^4.0.0"
+      }
+    },
+    "@commitlint/is-ignored": {
+      "version": "9.1.2",
+      "resolved": "https://registry.npmjs.org/@commitlint/is-ignored/-/is-ignored-9.1.2.tgz",
+      "integrity": "sha512-423W/+Ro+Cc8cg81+t9gds1EscMZNjnGT31nKDvxVxJxXiXQsYYoFEQbU+nfUrRGQsUikEgEJ3ppVGr1linvcQ==",
       "dev": true,
       "requires": {
-        "chalk": "^3.0.0"
+        "@commitlint/types": "^9.1.2",
+        "semver": "7.3.2"
       },
       "dependencies": {
-        "ansi-styles": {
-          "version": "4.2.1",
-          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz",
-          "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==",
-          "dev": true,
-          "requires": {
-            "@types/color-name": "^1.1.1",
+        "semver": {
+          "version": "7.3.2",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz",
+          "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==",
+          "dev": true
+        }
+      }
+    },
+    "@commitlint/lint": {
+      "version": "9.1.2",
+      "resolved": "https://registry.npmjs.org/@commitlint/lint/-/lint-9.1.2.tgz",
+      "integrity": "sha512-XvggqHZ4XSTKOgzJhCzz52cWRRO57QQnEviwGj0qnD4jdwC+8h2u9LNZwoa2tGAuaNM3nSm//wNK7FRZhgiiFA==",
+      "dev": true,
+      "requires": {
+        "@commitlint/is-ignored": "^9.1.2",
+        "@commitlint/parse": "^9.1.2",
+        "@commitlint/rules": "^9.1.2",
+        "@commitlint/types": "^9.1.2"
+      }
+    },
+    "@commitlint/load": {
+      "version": "9.1.2",
+      "resolved": "https://registry.npmjs.org/@commitlint/load/-/load-9.1.2.tgz",
+      "integrity": "sha512-FPL82xBuF7J3EJ57kLVoligQP4BFRwrknooP+vNT787AXmQ/Fddc/iYYwHwy67pNkk5N++/51UyDl/CqiHb6nA==",
+      "dev": true,
+      "requires": {
+        "@commitlint/execute-rule": "^9.1.2",
+        "@commitlint/resolve-extends": "^9.1.2",
+        "@commitlint/types": "^9.1.2",
+        "chalk": "4.1.0",
+        "cosmiconfig": "^6.0.0",
+        "lodash": "^4.17.19",
+        "resolve-from": "^5.0.0"
+      },
+      "dependencies": {
+        "ansi-styles": {
+          "version": "4.2.1",
+          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz",
+          "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==",
+          "dev": true,
+          "requires": {
+            "@types/color-name": "^1.1.1",
             "color-convert": "^2.0.1"
           }
         },
         "chalk": {
-          "version": "3.0.0",
-          "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz",
-          "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==",
+          "version": "4.1.0",
+          "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz",
+          "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==",
           "dev": true,
           "requires": {
             "ansi-styles": "^4.1.0",
@@ -1486,102 +1592,88 @@
           "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
           "dev": true
         },
+        "cosmiconfig": {
+          "version": "6.0.0",
+          "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz",
+          "integrity": "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==",
+          "dev": true,
+          "requires": {
+            "@types/parse-json": "^4.0.0",
+            "import-fresh": "^3.1.0",
+            "parse-json": "^5.0.0",
+            "path-type": "^4.0.0",
+            "yaml": "^1.7.2"
+          }
+        },
         "has-flag": {
           "version": "4.0.0",
           "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
           "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
           "dev": true
         },
-        "supports-color": {
-          "version": "7.1.0",
-          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz",
-          "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==",
+        "import-fresh": {
+          "version": "3.2.1",
+          "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.1.tgz",
+          "integrity": "sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ==",
           "dev": true,
           "requires": {
-            "has-flag": "^4.0.0"
+            "parent-module": "^1.0.0",
+            "resolve-from": "^4.0.0"
+          },
+          "dependencies": {
+            "resolve-from": {
+              "version": "4.0.0",
+              "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
+              "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
+              "dev": true
+            }
           }
-        }
-      }
-    },
-    "@commitlint/is-ignored": {
-      "version": "9.0.1",
-      "resolved": "https://registry.npmjs.org/@commitlint/is-ignored/-/is-ignored-9.0.1.tgz",
-      "integrity": "sha512-doGBfQgbsi48Hc48runGdN0TQFvf5XZizck8cylQdGG/3w+YwX9WkplEor7cvz8pmmuD6PpfpdukHSKlR8KmHQ==",
-      "dev": true,
-      "requires": {
-        "@commitlint/types": "^9.0.1",
-        "semver": "7.1.3"
-      }
-    },
-    "@commitlint/lint": {
-      "version": "9.0.1",
-      "resolved": "https://registry.npmjs.org/@commitlint/lint/-/lint-9.0.1.tgz",
-      "integrity": "sha512-EAn4E6aGWZ96Dg9LN28kdELqkyFOAUGlXWmanMdWxGFGdOf24ZHzlVsbr/Yb1oSBUE2KVvAF5W2Mzn2+Ge5rOg==",
-      "dev": true,
-      "requires": {
-        "@commitlint/is-ignored": "^9.0.1",
-        "@commitlint/parse": "^9.0.1",
-        "@commitlint/rules": "^9.0.1",
-        "@commitlint/types": "^9.0.1"
-      }
-    },
-    "@commitlint/load": {
-      "version": "8.3.5",
-      "resolved": "https://registry.npmjs.org/@commitlint/load/-/load-8.3.5.tgz",
-      "integrity": "sha512-poF7R1CtQvIXRmVIe63FjSQmN9KDqjRtU5A6hxqXBga87yB2VUJzic85TV6PcQc+wStk52cjrMI+g0zFx+Zxrw==",
-      "dev": true,
-      "optional": true,
-      "requires": {
-        "@commitlint/execute-rule": "^8.3.4",
-        "@commitlint/resolve-extends": "^8.3.5",
-        "babel-runtime": "^6.23.0",
-        "chalk": "2.4.2",
-        "cosmiconfig": "^5.2.0",
-        "lodash": "4.17.15",
-        "resolve-from": "^5.0.0"
-      },
-      "dependencies": {
-        "chalk": {
-          "version": "2.4.2",
-          "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
-          "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+        },
+        "lodash": {
+          "version": "4.17.20",
+          "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz",
+          "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==",
+          "dev": true
+        },
+        "parse-json": {
+          "version": "5.1.0",
+          "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.1.0.tgz",
+          "integrity": "sha512-+mi/lmVVNKFNVyLXV31ERiy2CY5E1/F6QtJFEzoChPRwwngMNXRDQ9GJ5WdE2Z2P4AujsOi0/+2qHID68KwfIQ==",
           "dev": true,
-          "optional": true,
           "requires": {
-            "ansi-styles": "^3.2.1",
-            "escape-string-regexp": "^1.0.5",
-            "supports-color": "^5.3.0"
+            "@babel/code-frame": "^7.0.0",
+            "error-ex": "^1.3.1",
+            "json-parse-even-better-errors": "^2.3.0",
+            "lines-and-columns": "^1.1.6"
           }
         },
         "resolve-from": {
           "version": "5.0.0",
           "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz",
           "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==",
-          "dev": true,
-          "optional": true
+          "dev": true
         },
         "supports-color": {
-          "version": "5.5.0",
-          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
-          "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+          "version": "7.1.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz",
+          "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==",
           "dev": true,
-          "optional": true,
           "requires": {
-            "has-flag": "^3.0.0"
+            "has-flag": "^4.0.0"
           }
         }
       }
     },
     "@commitlint/message": {
-      "version": "9.0.1",
-      "resolved": "https://registry.npmjs.org/@commitlint/message/-/message-9.0.1.tgz",
-      "integrity": "sha512-9rKnOeBV5s5hnV895aE3aMgciC27kAjkV9BYVQOWRjZdXHFZxa+OZ94mkMp+Hcr61W++fox1JJpPiTuCTDX3TQ==",
+      "version": "9.1.2",
+      "resolved": "https://registry.npmjs.org/@commitlint/message/-/message-9.1.2.tgz",
+      "integrity": "sha512-ndlx5z7bPVLG347oYJUHuQ41eTcsw+aUYT1ZwQyci0Duy2atpuoeeSw9SuM1PjufzRCpb6ExzFEgGzcCRKAJsg==",
       "dev": true
     },
     "@commitlint/parse": {
-      "version": "9.0.1",
-      "resolved": "https://registry.npmjs.org/@commitlint/parse/-/parse-9.0.1.tgz",
-      "integrity": "sha512-O39yMSMFdBtqwyM5Ld7RT6OGeI7jiXB9UUb09liIXIkltaZZo6CeoBD9hyfRWpaw81SiGL4OwHzp92mYVHLmow==",
+      "version": "9.1.2",
+      "resolved": "https://registry.npmjs.org/@commitlint/parse/-/parse-9.1.2.tgz",
+      "integrity": "sha512-d+/VYbkotctW+lzDpus/R6xTerOqFQkW1myH+3PwnqYSE6JU/uHT4MlZNGJBv8pX9SPlR66t6X9puFobqtezEw==",
       "dev": true,
       "requires": {
         "conventional-changelog-angular": "^5.0.0",
@@ -1589,25 +1681,24 @@
       }
     },
     "@commitlint/read": {
-      "version": "9.0.1",
-      "resolved": "https://registry.npmjs.org/@commitlint/read/-/read-9.0.1.tgz",
-      "integrity": "sha512-EYbel85mAiHb56bS5jBJ71lEaGjTnkSJLxTV1u6dpxdSBkRdmAn2DSPd6KQSbwYGUlPCR+pAZeZItT1y0Xk3hg==",
+      "version": "9.1.2",
+      "resolved": "https://registry.npmjs.org/@commitlint/read/-/read-9.1.2.tgz",
+      "integrity": "sha512-C2sNBQOqeQXMxpWtRnXYKYB3D9yuybPtQNY/P67A6o8XH/UMHkFaUTyIx1KRgu0IG0yTTItRt46FGnsMWLotvA==",
       "dev": true,
       "requires": {
-        "@commitlint/top-level": "^9.0.1",
+        "@commitlint/top-level": "^9.1.2",
         "fs-extra": "^8.1.0",
         "git-raw-commits": "^2.0.0"
       }
     },
     "@commitlint/resolve-extends": {
-      "version": "8.3.5",
-      "resolved": "https://registry.npmjs.org/@commitlint/resolve-extends/-/resolve-extends-8.3.5.tgz",
-      "integrity": "sha512-nHhFAK29qiXNe6oH6uG5wqBnCR+BQnxlBW/q5fjtxIaQALgfoNLHwLS9exzbIRFqwJckpR6yMCfgMbmbAOtklQ==",
+      "version": "9.1.2",
+      "resolved": "https://registry.npmjs.org/@commitlint/resolve-extends/-/resolve-extends-9.1.2.tgz",
+      "integrity": "sha512-HcoL+qFGmWEu9VM4fY0HI+VzF4yHcg3x+9Hx6pYFZ+r2wLbnKs964y0v68oyMO/mS/46MVoLNXZGR8U3adpadg==",
       "dev": true,
-      "optional": true,
       "requires": {
         "import-fresh": "^3.0.0",
-        "lodash": "4.17.15",
+        "lodash": "^4.17.19",
         "resolve-from": "^5.0.0",
         "resolve-global": "^1.0.0"
       },
@@ -1617,7 +1708,6 @@
           "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.1.tgz",
           "integrity": "sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ==",
           "dev": true,
-          "optional": true,
           "requires": {
             "parent-module": "^1.0.0",
             "resolve-from": "^4.0.0"
@@ -1627,51 +1717,55 @@
               "version": "4.0.0",
               "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
               "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
-              "dev": true,
-              "optional": true
+              "dev": true
             }
           }
         },
+        "lodash": {
+          "version": "4.17.20",
+          "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz",
+          "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==",
+          "dev": true
+        },
         "resolve-from": {
           "version": "5.0.0",
           "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz",
           "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==",
-          "dev": true,
-          "optional": true
+          "dev": true
         }
       }
     },
     "@commitlint/rules": {
-      "version": "9.0.1",
-      "resolved": "https://registry.npmjs.org/@commitlint/rules/-/rules-9.0.1.tgz",
-      "integrity": "sha512-K9IiQzF/C2tP/0mQUPSkOtmAEUleRQhZK1NFLVbsd6r4uobaczjPSYvEH+cuSHlD9b3Ori7PRiTgVBAZTH5ORQ==",
+      "version": "9.1.2",
+      "resolved": "https://registry.npmjs.org/@commitlint/rules/-/rules-9.1.2.tgz",
+      "integrity": "sha512-1vecFuzqVqjiT57ocXq1bL8V6GEF1NZs3BR0dQzObaqHftImIxBVII299gasckTkcuxNc8M+7XxZyKxUthukpQ==",
       "dev": true,
       "requires": {
-        "@commitlint/ensure": "^9.0.1",
-        "@commitlint/message": "^9.0.1",
-        "@commitlint/to-lines": "^9.0.1",
-        "@commitlint/types": "^9.0.1"
+        "@commitlint/ensure": "^9.1.2",
+        "@commitlint/message": "^9.1.2",
+        "@commitlint/to-lines": "^9.1.2",
+        "@commitlint/types": "^9.1.2"
       }
     },
     "@commitlint/to-lines": {
-      "version": "9.0.1",
-      "resolved": "https://registry.npmjs.org/@commitlint/to-lines/-/to-lines-9.0.1.tgz",
-      "integrity": "sha512-FHiXPhFgGnvekF4rhyl1daHimEHkr81pxbHAmWG/0SOCehFr5THsWGoUYNNBMF7rdwUuVq4tXJpEOFiWBGKigg==",
+      "version": "9.1.2",
+      "resolved": "https://registry.npmjs.org/@commitlint/to-lines/-/to-lines-9.1.2.tgz",
+      "integrity": "sha512-o4zWcMf9EnzA3MOqx01780SgrKq5hqDJmUBPk30g6an0XcDuDy3OSZHHTJFdzsg4V9FjC4OY44sFeK7GN7NaxQ==",
       "dev": true
     },
     "@commitlint/top-level": {
-      "version": "9.0.1",
-      "resolved": "https://registry.npmjs.org/@commitlint/top-level/-/top-level-9.0.1.tgz",
-      "integrity": "sha512-AjCah5y7wu9F/hOwMnqsujPRWlKerX79ZGf+UfBpOdAh+USdV7a/UfQaqjgCzkxy5GcNO9ER5A+2mWrUHxJ0hQ==",
+      "version": "9.1.2",
+      "resolved": "https://registry.npmjs.org/@commitlint/top-level/-/top-level-9.1.2.tgz",
+      "integrity": "sha512-KMPP5xVePcz3B1dKqcZdU4FZBVOkT+bG3ip4RQX2TeCJoomMkTjd0utALs7rpTGLID6BXbwwXepZCZJREjR/Bw==",
       "dev": true,
       "requires": {
         "find-up": "^4.0.0"
       }
     },
     "@commitlint/types": {
-      "version": "9.0.1",
-      "resolved": "https://registry.npmjs.org/@commitlint/types/-/types-9.0.1.tgz",
-      "integrity": "sha512-wo2rHprtDzTHf4tiSxavktJ52ntiwmg7eHNGFLH38G1of8OfGVwOc1sVbpM4jN/HK/rCMhYOi6xzoPqsv0537A==",
+      "version": "9.1.2",
+      "resolved": "https://registry.npmjs.org/@commitlint/types/-/types-9.1.2.tgz",
+      "integrity": "sha512-r3fwVbVH+M8W0qYlBBZFsUwKe6NT5qvz+EmU7sr8VeN1cQ63z+3cfXyTo7WGGEMEgKiT0jboNAK3b1FZp8k9LQ==",
       "dev": true
     },
     "@csstools/convert-colors": {
@@ -1681,63 +1775,13 @@
       "dev": true
     },
     "@fullhuman/postcss-purgecss": {
-      "version": "2.2.0",
-      "resolved": "https://registry.npmjs.org/@fullhuman/postcss-purgecss/-/postcss-purgecss-2.2.0.tgz",
-      "integrity": "sha512-q4zYAn8L9olA5uneaLhxkHRBoug9dnAqytbdX9R5dbzSORobhYr1yGR2JN3Q1UMd5RB0apm1NvJekHaymal/BQ==",
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/@fullhuman/postcss-purgecss/-/postcss-purgecss-2.3.0.tgz",
+      "integrity": "sha512-qnKm5dIOyPGJ70kPZ5jiz0I9foVOic0j+cOzNDoo8KoCf6HjicIZ99UfO2OmE7vCYSKAAepEwJtNzpiiZAh9xw==",
       "dev": true,
       "requires": {
-        "postcss": "7.0.28",
-        "purgecss": "^2.2.0"
-      },
-      "dependencies": {
-        "chalk": {
-          "version": "2.4.2",
-          "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
-          "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
-          "dev": true,
-          "requires": {
-            "ansi-styles": "^3.2.1",
-            "escape-string-regexp": "^1.0.5",
-            "supports-color": "^5.3.0"
-          },
-          "dependencies": {
-            "supports-color": {
-              "version": "5.5.0",
-              "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
-              "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
-              "dev": true,
-              "requires": {
-                "has-flag": "^3.0.0"
-              }
-            }
-          }
-        },
-        "postcss": {
-          "version": "7.0.28",
-          "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.28.tgz",
-          "integrity": "sha512-YU6nVhyWIsVtlNlnAj1fHTsUKW5qxm3KEgzq2Jj6KTEFOTK8QWR12eIDvrlWhiSTK8WIBFTBhOJV4DY6dUuEbw==",
-          "dev": true,
-          "requires": {
-            "chalk": "^2.4.2",
-            "source-map": "^0.6.1",
-            "supports-color": "^6.1.0"
-          }
-        },
-        "source-map": {
-          "version": "0.6.1",
-          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
-          "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
-          "dev": true
-        },
-        "supports-color": {
-          "version": "6.1.0",
-          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
-          "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
-          "dev": true,
-          "requires": {
-            "has-flag": "^3.0.0"
-          }
-        }
+        "postcss": "7.0.32",
+        "purgecss": "^2.3.0"
       }
     },
     "@nodelib/fs.scandir": {
@@ -1772,9 +1816,9 @@
       "integrity": "sha512-1oO6+dN5kdIA3sKPZhRGJTfGVP4SWV6KqlMOwry4J3HfyD68sl/3KmG7DeYUzvN+RbhXDnv/D8vNNB8168tAMg=="
     },
     "@prettier/plugin-php": {
-      "version": "0.14.2",
-      "resolved": "https://registry.npmjs.org/@prettier/plugin-php/-/plugin-php-0.14.2.tgz",
-      "integrity": "sha512-sG713Vb/eKtlB4rsL1+7mDD85jC2cjop8z/LE2QZHBtbopemfa4okEha01fgCqMaLJ80NBwGP9SZIwY9MR/w6w==",
+      "version": "0.14.3",
+      "resolved": "https://registry.npmjs.org/@prettier/plugin-php/-/plugin-php-0.14.3.tgz",
+      "integrity": "sha512-n+r5e4p8QhF497NUyOx7AqyQjNqCNbwhd+W8wTc07dO9ME42npIwZ1N8Hyc3kZ4KeLxE+nAuU5e21VMcbJyOMQ==",
       "dev": true,
       "requires": {
         "linguist-languages": "^7.5.1",
@@ -1783,28 +1827,36 @@
       }
     },
     "@rollup/plugin-babel": {
-      "version": "5.1.0",
-      "resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.1.0.tgz",
-      "integrity": "sha512-zXBEYmfiLAMvB+ZBa6m/q9hsQYAq1sUFdjuP1F6C2pf6uQcpHwAWQveZgzS63zXdKPUYHD3Dr7BhjCqcr0bbLw==",
+      "version": "5.2.0",
+      "resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.2.0.tgz",
+      "integrity": "sha512-CPABsajaKjINgBQ3it+yMnfVO3ibsrMBxRzbUOUw2cL1hsZJ7aogU8mgglQm3S2hHJgjnAmxPz0Rq7DVdmHsTw==",
       "dev": true,
       "requires": {
-        "@babel/helper-module-imports": "^7.7.4",
-        "@rollup/pluginutils": "^3.0.8"
+        "@babel/helper-module-imports": "^7.10.4",
+        "@rollup/pluginutils": "^3.1.0"
       }
     },
     "@rollup/plugin-commonjs": {
-      "version": "14.0.0",
-      "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-14.0.0.tgz",
-      "integrity": "sha512-+PSmD9ePwTAeU106i9FRdc+Zb3XUWyW26mo5Atr2mk82hor8+nPwkztEjFo8/B1fJKfaQDg9aM2bzQkjhi7zOw==",
+      "version": "15.0.0",
+      "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-15.0.0.tgz",
+      "integrity": "sha512-8uAdikHqVyrT32w1zB9VhW6uGwGjhKgnDNP4pQJsjdnyF4FgCj6/bmv24c7v2CuKhq32CcyCwRzMPEElaKkn0w==",
       "dev": true,
       "requires": {
-        "@rollup/pluginutils": "^3.0.8",
+        "@rollup/pluginutils": "^3.1.0",
         "commondir": "^1.0.1",
-        "estree-walker": "^1.0.1",
-        "glob": "^7.1.2",
-        "is-reference": "^1.1.2",
-        "magic-string": "^0.25.2",
-        "resolve": "^1.11.0"
+        "estree-walker": "^2.0.1",
+        "glob": "^7.1.6",
+        "is-reference": "^1.2.1",
+        "magic-string": "^0.25.7",
+        "resolve": "^1.17.0"
+      },
+      "dependencies": {
+        "estree-walker": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.1.tgz",
+          "integrity": "sha512-tF0hv+Yi2Ot1cwj9eYHtxC0jB9bmjacjQs6ZBTj82H8JwUywFuc+7E83NWfNMwHXZc11mjfFcVXPe9gEP4B8dg==",
+          "dev": true
+        }
       }
     },
     "@rollup/plugin-json": {
@@ -1817,29 +1869,35 @@
       }
     },
     "@rollup/plugin-multi-entry": {
-      "version": "3.0.1",
-      "resolved": "https://registry.npmjs.org/@rollup/plugin-multi-entry/-/plugin-multi-entry-3.0.1.tgz",
-      "integrity": "sha512-Gcp9E8y68Kx+Jo8zy/ZpiiAkb0W01cSqnxOz6h9bPR7MU3gaoTEdRf7xXYplwli1SBFEswXX588ESj+50Brfxw==",
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/@rollup/plugin-multi-entry/-/plugin-multi-entry-4.0.0.tgz",
+      "integrity": "sha512-1Sw86rwFxrNS7ECY3iSZ7T940xKnruNGpmQDgSDVTp+VTa1g5cPXNzBgp+IoOer41CiVeGFLwYwvicVoJLHEDQ==",
       "dev": true,
       "requires": {
-        "matched": "^1.0.2"
+        "@rollup/plugin-virtual": "^2.0.3",
+        "matched": "^5.0.0"
       }
     },
     "@rollup/plugin-node-resolve": {
-      "version": "8.4.0",
-      "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-8.4.0.tgz",
-      "integrity": "sha512-LFqKdRLn0ShtQyf6SBYO69bGE1upV6wUhBX0vFOUnLAyzx5cwp8svA0eHUnu8+YU57XOkrMtfG63QOpQx25pHQ==",
+      "version": "9.0.0",
+      "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-9.0.0.tgz",
+      "integrity": "sha512-gPz+utFHLRrd41WMP13Jq5mqqzHL3OXrfj3/MkSyB6UBIcuNt9j60GCbarzMzdf1VHFpOxfQh/ez7wyadLMqkg==",
       "dev": true,
       "requires": {
         "@rollup/pluginutils": "^3.1.0",
         "@types/resolve": "1.17.1",
         "builtin-modules": "^3.1.0",
-        "deep-freeze": "^0.0.1",
         "deepmerge": "^4.2.2",
         "is-module": "^1.0.0",
         "resolve": "^1.17.0"
       }
     },
+    "@rollup/plugin-virtual": {
+      "version": "2.0.3",
+      "resolved": "https://registry.npmjs.org/@rollup/plugin-virtual/-/plugin-virtual-2.0.3.tgz",
+      "integrity": "sha512-pw6ziJcyjZtntQ//bkad9qXaBx665SgEL8C8KI5wO8G5iU5MPxvdWrQyVaAvjojGm9tJoS8M9Z/EEepbqieYmw==",
+      "dev": true
+    },
     "@rollup/pluginutils": {
       "version": "3.1.0",
       "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.1.0.tgz",
@@ -1949,9 +2007,9 @@
       "dev": true
     },
     "@types/node": {
-      "version": "14.0.26",
-      "resolved": "https://registry.npmjs.org/@types/node/-/node-14.0.26.tgz",
-      "integrity": "sha512-W+fpe5s91FBGE0pEa0lnqGLL4USgpLgs4nokw16SrBBco/gQxuua7KnArSEOd5iaMqbbSHV10vUDkJYJJqpXKA==",
+      "version": "14.6.1",
+      "resolved": "https://registry.npmjs.org/@types/node/-/node-14.6.1.tgz",
+      "integrity": "sha512-HnYlg/BRF8uC1FyKRFZwRaCPTPYKa+6I8QiUZFLredaGOou481cgFS4wKRFyKvQtX8xudqkSdBczJHIYSQYKrQ==",
       "dev": true
     },
     "@types/normalize-package-data": {
@@ -2012,9 +2070,9 @@
       }
     },
     "@types/prosemirror-view": {
-      "version": "1.15.0",
-      "resolved": "https://registry.npmjs.org/@types/prosemirror-view/-/prosemirror-view-1.15.0.tgz",
-      "integrity": "sha512-OBIAiVInYS0cr4txLZEVYs1t1aFKaAZvogFDgkZfLwa+uda+LNPSs6m4tNLU/KXoFu9iK9CPOpiYTlDQPEnU6g==",
+      "version": "1.15.1",
+      "resolved": "https://registry.npmjs.org/@types/prosemirror-view/-/prosemirror-view-1.15.1.tgz",
+      "integrity": "sha512-ZdgIqDLWiO4wW4DhK8OjEVam3/DhBcggQeZ6zLts+UCflAZPnEk5dzRqFBVEyrvWqSAGLuPAoOgGAPjj/XwR8w==",
       "dev": true,
       "requires": {
         "@types/prosemirror-model": "*",
@@ -2053,12 +2111,12 @@
       "dev": true
     },
     "@typescript-eslint/eslint-plugin": {
-      "version": "3.7.0",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-3.7.0.tgz",
-      "integrity": "sha512-4OEcPON3QIx0ntsuiuFP/TkldmBGXf0uKxPQlGtS/W2F3ndYm8Vgdpj/woPJkzUc65gd3iR+qi3K8SDQP/obFg==",
+      "version": "3.10.1",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-3.10.1.tgz",
+      "integrity": "sha512-PQg0emRtzZFWq6PxBcdxRH3QIQiyFO3WCVpRL3fgj5oQS3CDs3AeAKfv4DxNhzn8ITdNJGJ4D3Qw8eAJf3lXeQ==",
       "dev": true,
       "requires": {
-        "@typescript-eslint/experimental-utils": "3.7.0",
+        "@typescript-eslint/experimental-utils": "3.10.1",
         "debug": "^4.1.1",
         "functional-red-black-tree": "^1.0.1",
         "regexpp": "^3.0.0",
@@ -2066,21 +2124,6 @@
         "tsutils": "^3.17.1"
       },
       "dependencies": {
-        "debug": {
-          "version": "4.1.1",
-          "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
-          "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
-          "dev": true,
-          "requires": {
-            "ms": "^2.1.1"
-          }
-        },
-        "ms": {
-          "version": "2.1.2",
-          "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
-          "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
-          "dev": true
-        },
         "semver": {
           "version": "7.3.2",
           "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz",
@@ -2090,45 +2133,45 @@
       }
     },
     "@typescript-eslint/experimental-utils": {
-      "version": "3.7.0",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-3.7.0.tgz",
-      "integrity": "sha512-xpfXXAfZqhhqs5RPQBfAFrWDHoNxD5+sVB5A46TF58Bq1hRfVROrWHcQHHUM9aCBdy9+cwATcvCbRg8aIRbaHQ==",
+      "version": "3.10.1",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-3.10.1.tgz",
+      "integrity": "sha512-DewqIgscDzmAfd5nOGe4zm6Bl7PKtMG2Ad0KG8CUZAHlXfAKTF9Ol5PXhiMh39yRL2ChRH1cuuUGOcVyyrhQIw==",
       "dev": true,
       "requires": {
         "@types/json-schema": "^7.0.3",
-        "@typescript-eslint/types": "3.7.0",
-        "@typescript-eslint/typescript-estree": "3.7.0",
+        "@typescript-eslint/types": "3.10.1",
+        "@typescript-eslint/typescript-estree": "3.10.1",
         "eslint-scope": "^5.0.0",
         "eslint-utils": "^2.0.0"
       }
     },
     "@typescript-eslint/parser": {
-      "version": "3.7.0",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-3.7.0.tgz",
-      "integrity": "sha512-2LZauVUt7jAWkcIW7djUc3kyW+fSarNEuM3RF2JdLHR9BfX/nDEnyA4/uWz0wseoWVZbDXDF7iF9Jc342flNqQ==",
+      "version": "3.10.1",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-3.10.1.tgz",
+      "integrity": "sha512-Ug1RcWcrJP02hmtaXVS3axPPTTPnZjupqhgj+NnZ6BCkwSImWk/283347+x9wN+lqOdK9Eo3vsyiyDHgsmiEJw==",
       "dev": true,
       "requires": {
         "@types/eslint-visitor-keys": "^1.0.0",
-        "@typescript-eslint/experimental-utils": "3.7.0",
-        "@typescript-eslint/types": "3.7.0",
-        "@typescript-eslint/typescript-estree": "3.7.0",
+        "@typescript-eslint/experimental-utils": "3.10.1",
+        "@typescript-eslint/types": "3.10.1",
+        "@typescript-eslint/typescript-estree": "3.10.1",
         "eslint-visitor-keys": "^1.1.0"
       }
     },
     "@typescript-eslint/types": {
-      "version": "3.7.0",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-3.7.0.tgz",
-      "integrity": "sha512-reCaK+hyKkKF+itoylAnLzFeNYAEktB0XVfSQvf0gcVgpz1l49Lt6Vo9x4MVCCxiDydA0iLAjTF/ODH0pbfnpg==",
+      "version": "3.10.1",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-3.10.1.tgz",
+      "integrity": "sha512-+3+FCUJIahE9q0lDi1WleYzjCwJs5hIsbugIgnbB+dSCYUxl8L6PwmsyOPFZde2hc1DlTo/xnkOgiTLSyAbHiQ==",
       "dev": true
     },
     "@typescript-eslint/typescript-estree": {
-      "version": "3.7.0",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-3.7.0.tgz",
-      "integrity": "sha512-xr5oobkYRebejlACGr1TJ0Z/r0a2/HUf0SXqPvlgUMwiMqOCu/J+/Dr9U3T0IxpE5oLFSkqMx1FE/dKaZ8KsOQ==",
+      "version": "3.10.1",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-3.10.1.tgz",
+      "integrity": "sha512-QbcXOuq6WYvnB3XPsZpIwztBoquEYLXh2MtwVU+kO8jgYCiv4G5xrSP/1wg4tkvrEE+esZVquIPX/dxPlePk1w==",
       "dev": true,
       "requires": {
-        "@typescript-eslint/types": "3.7.0",
-        "@typescript-eslint/visitor-keys": "3.7.0",
+        "@typescript-eslint/types": "3.10.1",
+        "@typescript-eslint/visitor-keys": "3.10.1",
         "debug": "^4.1.1",
         "glob": "^7.1.6",
         "is-glob": "^4.0.1",
@@ -2137,21 +2180,6 @@
         "tsutils": "^3.17.1"
       },
       "dependencies": {
-        "debug": {
-          "version": "4.1.1",
-          "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
-          "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
-          "dev": true,
-          "requires": {
-            "ms": "^2.1.1"
-          }
-        },
-        "ms": {
-          "version": "2.1.2",
-          "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
-          "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
-          "dev": true
-        },
         "semver": {
           "version": "7.3.2",
           "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz",
@@ -2161,9 +2189,9 @@
       }
     },
     "@typescript-eslint/visitor-keys": {
-      "version": "3.7.0",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-3.7.0.tgz",
-      "integrity": "sha512-k5PiZdB4vklUpUX4NBncn5RBKty8G3ihTY+hqJsCdMuD0v4jofI5xuqwnVcWxfv6iTm2P/dfEa2wMUnsUY8ODw==",
+      "version": "3.10.1",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-3.10.1.tgz",
+      "integrity": "sha512-9JgC82AaQeglebjZMgYR5wgmfUdUc+EitGUUMW8u2nDckaeimzW+VsoLV6FoimPv2id3VQzfjwBxEMVz08ameQ==",
       "dev": true,
       "requires": {
         "eslint-visitor-keys": "^1.1.0"
@@ -2180,9 +2208,9 @@
       }
     },
     "acorn": {
-      "version": "7.2.0",
-      "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.2.0.tgz",
-      "integrity": "sha512-apwXVmYVpQ34m/i71vrApRrRKCWQnZZF1+npOD0WV5xZFfwWOmKGQ2RWlfdy9vWITsenisM8M0Qeq8agcFHNiQ==",
+      "version": "7.4.0",
+      "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.0.tgz",
+      "integrity": "sha512-+G7P8jJmCHr+S+cLfQxygbWhXy+8YTVGzAkpEbcLo2mLoL7tij/VG41QSHACSf5QgYRhMZYHuNc6drJaO0Da+w==",
       "dev": true
     },
     "acorn-jsx": {
@@ -2203,15 +2231,15 @@
       }
     },
     "acorn-walk": {
-      "version": "7.1.1",
-      "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.1.1.tgz",
-      "integrity": "sha512-wdlPY2tm/9XBr7QkKlq0WQVgiuGTX6YWPyRyBviSoScBuLfTVQhvwg6wJ369GJ/1nPfTLMfnrFIfjqVg6d+jQQ==",
+      "version": "7.2.0",
+      "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz",
+      "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==",
       "dev": true
     },
     "aggregate-error": {
-      "version": "3.0.1",
-      "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.0.1.tgz",
-      "integrity": "sha512-quoaXsZ9/BLNae5yiNoUz+Nhkwz83GhWwtYFglcjEQB2NDHCIpApbqXxIFnm4Pq/Nvhrsq5sYJFyohrrxnTGAA==",
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz",
+      "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==",
       "dev": true,
       "requires": {
         "clean-stack": "^2.0.0",
@@ -2237,9 +2265,9 @@
       "dev": true
     },
     "ansi-colors": {
-      "version": "3.2.4",
-      "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.4.tgz",
-      "integrity": "sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA==",
+      "version": "4.1.1",
+      "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz",
+      "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==",
       "dev": true
     },
     "ansi-escapes": {
@@ -2299,12 +2327,6 @@
       "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=",
       "dev": true
     },
-    "array-find-index": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz",
-      "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=",
-      "dev": true
-    },
     "array-ify": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/array-ify/-/array-ify-1.0.0.tgz",
@@ -2341,12 +2363,6 @@
       "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==",
       "dev": true
     },
-    "async-array-reduce": {
-      "version": "0.2.1",
-      "resolved": "https://registry.npmjs.org/async-array-reduce/-/async-array-reduce-0.2.1.tgz",
-      "integrity": "sha1-yL4BCitc0A3qlsgRFgNGk9/dgtE=",
-      "dev": true
-    },
     "at-least-node": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz",
@@ -2396,17 +2412,6 @@
         "object.assign": "^4.1.0"
       }
     },
-    "babel-runtime": {
-      "version": "6.26.0",
-      "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz",
-      "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=",
-      "dev": true,
-      "optional": true,
-      "requires": {
-        "core-js": "^2.4.0",
-        "regenerator-runtime": "^0.11.0"
-      }
-    },
     "bail": {
       "version": "1.0.5",
       "resolved": "https://registry.npmjs.org/bail/-/bail-1.0.5.tgz",
@@ -2977,9 +2982,9 @@
       }
     },
     "codemirror": {
-      "version": "5.55.0",
-      "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.55.0.tgz",
-      "integrity": "sha512-TumikSANlwiGkdF/Blnu/rqovZ0Y3Jh8yy9TqrPbSM0xxSucq3RgnpVDQ+mD9q6JERJEIT2FMuF/fBGfkhIR/g=="
+      "version": "5.57.0",
+      "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.57.0.tgz",
+      "integrity": "sha512-WGc6UL7Hqt+8a6ZAsj/f1ApQl3NPvHY/UQSzG6fB6l4BjExgVdhFaxd7mRTw1UCiYe/6q86zHP+kfvBQcZGvUg=="
     },
     "collapse-white-space": {
       "version": "1.0.6",
@@ -3033,15 +3038,15 @@
       }
     },
     "commander": {
-      "version": "5.1.0",
-      "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz",
-      "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==",
+      "version": "6.1.0",
+      "resolved": "https://registry.npmjs.org/commander/-/commander-6.1.0.tgz",
+      "integrity": "sha512-wl7PNrYWd2y5mp1OK/LhTlv8Ff4kQJQRXXAvF+uU/TPNiVJUxZLRYGj/B0y/lPGAVcSbJqH2Za/cvHmrPMC8mA==",
       "dev": true
     },
     "commitizen": {
-      "version": "4.1.2",
-      "resolved": "https://registry.npmjs.org/commitizen/-/commitizen-4.1.2.tgz",
-      "integrity": "sha512-LBxTQKHbVgroMz9ohpm86N+GfJobonGyvDc3zBGdZazbwCLz2tqLa48Rf2TnAdKx7/06W1i1R3SXUt5QW97qVQ==",
+      "version": "4.2.1",
+      "resolved": "https://registry.npmjs.org/commitizen/-/commitizen-4.2.1.tgz",
+      "integrity": "sha512-nZsp8IThkDu7C+93BFD/mLShb9Gd6Wsaf90tpKE3x/6u5y/Q52kzanIJpGr0qvIsJ5bCMpgKtr3Lbu3miEJfaA==",
       "dev": true,
       "requires": {
         "cachedir": "2.2.0",
@@ -3052,14 +3057,40 @@
         "find-root": "1.1.0",
         "fs-extra": "8.1.0",
         "glob": "7.1.4",
-        "inquirer": "6.5.0",
+        "inquirer": "6.5.2",
         "is-utf8": "^0.2.1",
-        "lodash": "4.17.15",
+        "lodash": "^4.17.20",
         "minimist": "1.2.5",
         "strip-bom": "4.0.0",
         "strip-json-comments": "3.0.1"
       },
       "dependencies": {
+        "chalk": {
+          "version": "2.4.2",
+          "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+          "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+          "dev": true,
+          "requires": {
+            "ansi-styles": "^3.2.1",
+            "escape-string-regexp": "^1.0.5",
+            "supports-color": "^5.3.0"
+          }
+        },
+        "cz-conventional-changelog": {
+          "version": "3.2.0",
+          "resolved": "https://registry.npmjs.org/cz-conventional-changelog/-/cz-conventional-changelog-3.2.0.tgz",
+          "integrity": "sha512-yAYxeGpVi27hqIilG1nh4A9Bnx4J3Ov+eXy4koL3drrR+IO9GaWPsKjik20ht608Asqi8TQPf0mczhEeyAtMzg==",
+          "dev": true,
+          "requires": {
+            "@commitlint/load": ">6.1.1",
+            "chalk": "^2.4.1",
+            "commitizen": "^4.0.3",
+            "conventional-commit-types": "^3.0.0",
+            "lodash.map": "^4.5.1",
+            "longest": "^2.0.1",
+            "word-wrap": "^1.0.3"
+          }
+        },
         "glob": {
           "version": "7.1.4",
           "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz",
@@ -3073,7 +3104,13 @@
             "once": "^1.3.0",
             "path-is-absolute": "^1.0.0"
           }
-        }
+        },
+        "lodash": {
+          "version": "4.17.20",
+          "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz",
+          "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==",
+          "dev": true
+        }
       }
     },
     "commondir": {
@@ -3083,13 +3120,13 @@
       "dev": true
     },
     "compare-func": {
-      "version": "1.3.4",
-      "resolved": "https://registry.npmjs.org/compare-func/-/compare-func-1.3.4.tgz",
-      "integrity": "sha512-sq2sWtrqKPkEXAC8tEJA1+BqAH9GbFkGBtUOqrUX57VSfwp8xyktctk+uLoRy5eccTdxzDcVIztlYDpKs3Jv1Q==",
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/compare-func/-/compare-func-2.0.0.tgz",
+      "integrity": "sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==",
       "dev": true,
       "requires": {
         "array-ify": "^1.0.0",
-        "dot-prop": "^3.0.0"
+        "dot-prop": "^5.1.0"
       }
     },
     "compare-versions": {
@@ -3128,24 +3165,51 @@
       }
     },
     "conventional-changelog-angular": {
-      "version": "5.0.10",
-      "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-5.0.10.tgz",
-      "integrity": "sha512-k7RPPRs0vp8+BtPsM9uDxRl6KcgqtCJmzRD1wRtgqmhQ96g8ifBGo9O/TZBG23jqlXS/rg8BKRDELxfnQQGiaA==",
+      "version": "5.0.11",
+      "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-5.0.11.tgz",
+      "integrity": "sha512-nSLypht/1yEflhuTogC03i7DX7sOrXGsRn14g131Potqi6cbGbGEE9PSDEHKldabB6N76HiSyw9Ph+kLmC04Qw==",
       "dev": true,
       "requires": {
-        "compare-func": "^1.3.1",
+        "compare-func": "^2.0.0",
         "q": "^1.5.1"
       }
     },
     "conventional-changelog-conventionalcommits": {
-      "version": "4.2.3",
-      "resolved": "https://registry.npmjs.org/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-4.2.3.tgz",
-      "integrity": "sha512-atGa+R4vvEhb8N/8v3IoW59gCBJeeFiX6uIbPu876ENAmkMwsenyn0R21kdDHJFLQdy6zW4J6b4xN8KI3b9oww==",
+      "version": "4.3.0",
+      "resolved": "https://registry.npmjs.org/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-4.3.0.tgz",
+      "integrity": "sha512-oYHydvZKU+bS8LnGqTMlNrrd7769EsuEHKy4fh1oMdvvDi7fem8U+nvfresJ1IDB8K00Mn4LpiA/lR+7Gs6rgg==",
       "dev": true,
       "requires": {
         "compare-func": "^1.3.1",
         "lodash": "^4.17.15",
         "q": "^1.5.1"
+      },
+      "dependencies": {
+        "compare-func": {
+          "version": "1.3.4",
+          "resolved": "https://registry.npmjs.org/compare-func/-/compare-func-1.3.4.tgz",
+          "integrity": "sha512-sq2sWtrqKPkEXAC8tEJA1+BqAH9GbFkGBtUOqrUX57VSfwp8xyktctk+uLoRy5eccTdxzDcVIztlYDpKs3Jv1Q==",
+          "dev": true,
+          "requires": {
+            "array-ify": "^1.0.0",
+            "dot-prop": "^3.0.0"
+          }
+        },
+        "dot-prop": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-3.0.0.tgz",
+          "integrity": "sha1-G3CK8JSknJoOfbyteQq6U52sEXc=",
+          "dev": true,
+          "requires": {
+            "is-obj": "^1.0.0"
+          }
+        },
+        "is-obj": {
+          "version": "1.0.1",
+          "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz",
+          "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=",
+          "dev": true
+        }
       }
     },
     "conventional-commit-types": {
@@ -3167,29 +3231,6 @@
         "split2": "^2.0.0",
         "through2": "^3.0.0",
         "trim-off-newlines": "^1.0.0"
-      },
-      "dependencies": {
-        "meow": {
-          "version": "7.0.1",
-          "resolved": "https://registry.npmjs.org/meow/-/meow-7.0.1.tgz",
-          "integrity": "sha512-tBKIQqVrAHqwit0vfuFPY3LlzJYkEOFyKa3bPgxzNl6q/RtN8KQ+ALYEASYuFayzSAsjlhXj/JZ10rH85Q6TUw==",
-          "dev": true,
-          "requires": {
-            "@types/minimist": "^1.2.0",
-            "arrify": "^2.0.1",
-            "camelcase": "^6.0.0",
-            "camelcase-keys": "^6.2.2",
-            "decamelize-keys": "^1.1.0",
-            "hard-rejection": "^2.1.0",
-            "minimist-options": "^4.0.2",
-            "normalize-package-data": "^2.5.0",
-            "read-pkg-up": "^7.0.1",
-            "redent": "^3.0.0",
-            "trim-newlines": "^3.0.0",
-            "type-fest": "^0.13.1",
-            "yargs-parser": "^18.1.3"
-          }
-        }
       }
     },
     "convert-source-map": {
@@ -3208,11 +3249,10 @@
       "dev": true
     },
     "core-js": {
-      "version": "2.6.11",
-      "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.11.tgz",
-      "integrity": "sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg==",
-      "dev": true,
-      "optional": true
+      "version": "3.6.5",
+      "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.6.5.tgz",
+      "integrity": "sha512-vZVEEwZoIsI+vPEuoF9Iqf5H7/M3eeQqWlQnYa8FSKKePuYTf5MWnxb5SDAzCa60b3JBRS5g9b+Dq7b1y/RCrA==",
+      "dev": true
     },
     "core-js-compat": {
       "version": "3.6.5",
@@ -3613,19 +3653,10 @@
         }
       }
     },
-    "currently-unhandled": {
-      "version": "0.4.1",
-      "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz",
-      "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=",
-      "dev": true,
-      "requires": {
-        "array-find-index": "^1.0.1"
-      }
-    },
     "cz-conventional-changelog": {
-      "version": "3.2.0",
-      "resolved": "https://registry.npmjs.org/cz-conventional-changelog/-/cz-conventional-changelog-3.2.0.tgz",
-      "integrity": "sha512-yAYxeGpVi27hqIilG1nh4A9Bnx4J3Ov+eXy4koL3drrR+IO9GaWPsKjik20ht608Asqi8TQPf0mczhEeyAtMzg==",
+      "version": "3.3.0",
+      "resolved": "https://registry.npmjs.org/cz-conventional-changelog/-/cz-conventional-changelog-3.3.0.tgz",
+      "integrity": "sha512-U466fIzU5U22eES5lTNiNbZ+d8dfcHcssH4o7QsdWaCcRs/feIPCxKYSWkYBNs5mny7MvEfwpTLWjvbm94hecw==",
       "dev": true,
       "requires": {
         "@commitlint/load": ">6.1.1",
@@ -3657,12 +3688,12 @@
       "dev": true
     },
     "debug": {
-      "version": "2.6.9",
-      "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
-      "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+      "version": "4.1.1",
+      "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
+      "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
       "dev": true,
       "requires": {
-        "ms": "2.0.0"
+        "ms": "^2.1.1"
       }
     },
     "decamelize": {
@@ -3701,12 +3732,6 @@
       "integrity": "sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw=",
       "dev": true
     },
-    "deep-freeze": {
-      "version": "0.0.1",
-      "resolved": "https://registry.npmjs.org/deep-freeze/-/deep-freeze-0.0.1.tgz",
-      "integrity": "sha1-OgsABd4YZygZ39OM0x+RF5yJPoQ=",
-      "dev": true
-    },
     "deep-is": {
       "version": "0.1.3",
       "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz",
@@ -3872,12 +3897,12 @@
       }
     },
     "dot-prop": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-3.0.0.tgz",
-      "integrity": "sha1-G3CK8JSknJoOfbyteQq6U52sEXc=",
+      "version": "5.2.0",
+      "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.2.0.tgz",
+      "integrity": "sha512-uEUyaDKoSQ1M4Oq8l45hSE26SnTxL6snNnqvK/VWx5wJhmff5z0FUVJDKDanor/6w3kzE3i7XZOk+7wC0EXr1A==",
       "dev": true,
       "requires": {
-        "is-obj": "^1.0.0"
+        "is-obj": "^2.0.0"
       }
     },
     "electron-to-chromium": {
@@ -3908,12 +3933,12 @@
       }
     },
     "enquirer": {
-      "version": "2.3.5",
-      "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.5.tgz",
-      "integrity": "sha512-BNT1C08P9XD0vNg3J475yIUG+mVdp9T6towYFHUv897X0KoHBjB1shyrNmhmtHWKP17iSWgo7Gqh7BBuzLZMSA==",
+      "version": "2.3.6",
+      "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz",
+      "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==",
       "dev": true,
       "requires": {
-        "ansi-colors": "^3.2.1"
+        "ansi-colors": "^4.1.1"
       }
     },
     "entities": {
@@ -3984,9 +4009,9 @@
       "dev": true
     },
     "eslint": {
-      "version": "7.5.0",
-      "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.5.0.tgz",
-      "integrity": "sha512-vlUP10xse9sWt9SGRtcr1LAC67BENcQMFeV+w5EvLEoFe3xJ8cF1Skd0msziRx/VMC+72B4DxreCE+OR12OA6Q==",
+      "version": "7.7.0",
+      "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.7.0.tgz",
+      "integrity": "sha512-1KUxLzos0ZVsyL81PnRN335nDtQ8/vZUD6uMtWbF+5zDtjKcsklIi78XoE0MVL93QvWTu+E5y44VyyCsOMBrIg==",
       "dev": true,
       "requires": {
         "@babel/code-frame": "^7.0.0",
@@ -4033,15 +4058,6 @@
           "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==",
           "dev": true
         },
-        "debug": {
-          "version": "4.1.1",
-          "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
-          "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
-          "dev": true,
-          "requires": {
-            "ms": "^2.1.1"
-          }
-        },
         "globals": {
           "version": "12.4.0",
           "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz",
@@ -4067,46 +4083,10 @@
             "resolve-from": "^4.0.0"
           }
         },
-        "levn": {
-          "version": "0.4.1",
-          "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
-          "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
-          "dev": true,
-          "requires": {
-            "prelude-ls": "^1.2.1",
-            "type-check": "~0.4.0"
-          }
-        },
         "lodash": {
-          "version": "4.17.19",
-          "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz",
-          "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==",
-          "dev": true
-        },
-        "ms": {
-          "version": "2.1.2",
-          "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
-          "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
-          "dev": true
-        },
-        "optionator": {
-          "version": "0.9.1",
-          "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz",
-          "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==",
-          "dev": true,
-          "requires": {
-            "deep-is": "^0.1.3",
-            "fast-levenshtein": "^2.0.6",
-            "levn": "^0.4.1",
-            "prelude-ls": "^1.2.1",
-            "type-check": "^0.4.0",
-            "word-wrap": "^1.2.3"
-          }
-        },
-        "prelude-ls": {
-          "version": "1.2.1",
-          "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
-          "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
+          "version": "4.17.20",
+          "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz",
+          "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==",
           "dev": true
         },
         "resolve-from": {
@@ -4136,15 +4116,6 @@
           "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
           "dev": true
         },
-        "type-check": {
-          "version": "0.4.0",
-          "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
-          "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
-          "dev": true,
-          "requires": {
-            "prelude-ls": "^1.2.1"
-          }
-        },
         "type-fest": {
           "version": "0.8.1",
           "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz",
@@ -4205,22 +4176,14 @@
       "dev": true
     },
     "espree": {
-      "version": "7.2.0",
-      "resolved": "https://registry.npmjs.org/espree/-/espree-7.2.0.tgz",
-      "integrity": "sha512-H+cQ3+3JYRMEIOl87e7QdHX70ocly5iW4+dttuR8iYSPr/hXKFb+7dBsZ7+u1adC4VrnPlTkv0+OwuPnDop19g==",
+      "version": "7.3.0",
+      "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.0.tgz",
+      "integrity": "sha512-dksIWsvKCixn1yrEXO8UosNSxaDoSYpq9reEjZSbHLpT5hpaCAKTLBwq0RHtLrIr+c0ByiYzWT8KTMRzoRCNlw==",
       "dev": true,
       "requires": {
-        "acorn": "^7.3.1",
+        "acorn": "^7.4.0",
         "acorn-jsx": "^5.2.0",
         "eslint-visitor-keys": "^1.3.0"
-      },
-      "dependencies": {
-        "acorn": {
-          "version": "7.3.1",
-          "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.3.1.tgz",
-          "integrity": "sha512-tLc0wSnatxAQHVHUapaHdz72pi9KUyHjq5KyHjGg9Y8Ifdc79pTh2XvI6I1/chZbnM7QtNKzh66ooDogPZSleA==",
-          "dev": true
-        }
       }
     },
     "esprima": {
@@ -4239,9 +4202,9 @@
       },
       "dependencies": {
         "estraverse": {
-          "version": "5.1.0",
-          "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.1.0.tgz",
-          "integrity": "sha512-FyohXK+R0vE+y1nHLoBM7ZTyqRpqAlhdZHCWIWEviFLiGB8b04H6bQs8G+XTthacvT8VuwvteiP7RJSxMs8UEw==",
+          "version": "5.2.0",
+          "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz",
+          "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==",
           "dev": true
         }
       }
@@ -4274,15 +4237,15 @@
       "dev": true
     },
     "eventemitter3": {
-      "version": "4.0.4",
-      "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.4.tgz",
-      "integrity": "sha512-rlaVLnVxtxvoyLsQQFBx53YmXHDxRIzzTLbdfxqi4yocpSjAxXwkU0cScM5JgSKMqEhrZpnvQ2D9gjylR0AimQ==",
+      "version": "4.0.7",
+      "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz",
+      "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==",
       "dev": true
     },
     "execa": {
-      "version": "4.0.2",
-      "resolved": "https://registry.npmjs.org/execa/-/execa-4.0.2.tgz",
-      "integrity": "sha512-QI2zLa6CjGWdiQsmSkZoGtDx2N+cQIGb3yNolGTdjSQzydzLgYYf8LRuagp7S7fPimjcrzUDSUFd/MgzELMi4Q==",
+      "version": "4.0.3",
+      "resolved": "https://registry.npmjs.org/execa/-/execa-4.0.3.tgz",
+      "integrity": "sha512-WFDXGHckXPWZX19t1kCsXzOpqX9LWYNqn4C+HqZlk/V0imTkzJZqf87ZBhvpHaftERYknpk0fjSylnXVlVgI0A==",
       "dev": true,
       "requires": {
         "cross-spawn": "^7.0.0",
@@ -4303,9 +4266,9 @@
           "dev": true
         },
         "onetime": {
-          "version": "5.1.0",
-          "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.0.tgz",
-          "integrity": "sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q==",
+          "version": "5.1.2",
+          "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
+          "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==",
           "dev": true,
           "requires": {
             "mimic-fn": "^2.1.0"
@@ -4337,6 +4300,15 @@
         "to-regex": "^3.0.1"
       },
       "dependencies": {
+        "debug": {
+          "version": "2.6.9",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+          "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+          "dev": true,
+          "requires": {
+            "ms": "2.0.0"
+          }
+        },
         "define-property": {
           "version": "0.2.5",
           "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
@@ -4354,6 +4326,12 @@
           "requires": {
             "is-extendable": "^0.1.0"
           }
+        },
+        "ms": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+          "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
+          "dev": true
         }
       }
     },
@@ -4774,9 +4752,9 @@
       "dev": true
     },
     "get-stream": {
-      "version": "5.1.0",
-      "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.1.0.tgz",
-      "integrity": "sha512-EXr1FOzrzTfGeL0gQdeFEvOMm2mzMOglyiOXSTpPC+iAjAKftbr3jpCMWynogwYnM+eSj9sHGc6wjIcDvYiygw==",
+      "version": "5.2.0",
+      "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz",
+      "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==",
       "dev": true,
       "requires": {
         "pump": "^3.0.0"
@@ -4799,29 +4777,6 @@
         "meow": "^7.0.0",
         "split2": "^2.0.0",
         "through2": "^3.0.0"
-      },
-      "dependencies": {
-        "meow": {
-          "version": "7.0.1",
-          "resolved": "https://registry.npmjs.org/meow/-/meow-7.0.1.tgz",
-          "integrity": "sha512-tBKIQqVrAHqwit0vfuFPY3LlzJYkEOFyKa3bPgxzNl6q/RtN8KQ+ALYEASYuFayzSAsjlhXj/JZ10rH85Q6TUw==",
-          "dev": true,
-          "requires": {
-            "@types/minimist": "^1.2.0",
-            "arrify": "^2.0.1",
-            "camelcase": "^6.0.0",
-            "camelcase-keys": "^6.2.2",
-            "decamelize-keys": "^1.1.0",
-            "hard-rejection": "^2.1.0",
-            "minimist-options": "^4.0.2",
-            "normalize-package-data": "^2.5.0",
-            "read-pkg-up": "^7.0.1",
-            "redent": "^3.0.0",
-            "trim-newlines": "^3.0.0",
-            "type-fest": "^0.13.1",
-            "yargs-parser": "^18.1.3"
-          }
-        }
       }
     },
     "glob": {
@@ -4959,26 +4914,6 @@
       "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
       "dev": true
     },
-    "has-glob": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/has-glob/-/has-glob-1.0.0.tgz",
-      "integrity": "sha1-mqqe7b/7G6OZCnsAEPtnjuAIEgc=",
-      "dev": true,
-      "requires": {
-        "is-glob": "^3.0.0"
-      },
-      "dependencies": {
-        "is-glob": {
-          "version": "3.1.0",
-          "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz",
-          "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=",
-          "dev": true,
-          "requires": {
-            "is-extglob": "^2.1.0"
-          }
-        }
-      }
-    },
     "has-symbols": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz",
@@ -5252,9 +5187,9 @@
       "dev": true
     },
     "inquirer": {
-      "version": "6.5.0",
-      "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.5.0.tgz",
-      "integrity": "sha512-scfHejeG/lVZSpvCXpsB4j/wQNPM5JC8kiElOI0OUTwmc1RTpXr4H32/HOlQHcZiYl2z2VElwuCVDRG8vFmbnA==",
+      "version": "6.5.2",
+      "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.5.2.tgz",
+      "integrity": "sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ==",
       "dev": true,
       "requires": {
         "ansi-escapes": "^3.2.0",
@@ -5500,9 +5435,9 @@
       }
     },
     "is-obj": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz",
-      "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=",
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz",
+      "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==",
       "dev": true
     },
     "is-plain-obj": {
@@ -5595,12 +5530,6 @@
       "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=",
       "dev": true
     },
-    "is-valid-glob": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-1.0.0.tgz",
-      "integrity": "sha1-Kb8+/3Ab4tTTFdusw5vDn+j2Aao=",
-      "dev": true
-    },
     "is-whitespace-character": {
       "version": "1.0.4",
       "resolved": "https://registry.npmjs.org/is-whitespace-character/-/is-whitespace-character-1.0.4.tgz",
@@ -5638,11 +5567,12 @@
       "dev": true
     },
     "jest-worker": {
-      "version": "26.1.0",
-      "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.1.0.tgz",
-      "integrity": "sha512-Z9P5pZ6UC+kakMbNJn+tA2RdVdNX5WH1x+5UCBZ9MxIK24pjYtFt96fK+UwBTrjLYm232g1xz0L3eTh51OW+yQ==",
+      "version": "26.3.0",
+      "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.3.0.tgz",
+      "integrity": "sha512-Vmpn2F6IASefL+DVBhPzI2J9/GJUsqzomdeN+P+dK8/jKxbh8R3BtFnx3FIta7wYlPU62cpJMJQo4kuOowcMnw==",
       "dev": true,
       "requires": {
+        "@types/node": "*",
         "merge-stream": "^2.0.0",
         "supports-color": "^7.0.0"
       },
@@ -5692,6 +5622,12 @@
       "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==",
       "dev": true
     },
+    "json-parse-even-better-errors": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.0.tgz",
+      "integrity": "sha512-o3aP+RsWDJZayj1SbHNQAI8x0v3T3SKiGoZlNYfbUP1S3omJQ6i9CnqADqkSPaOAxwua4/1YWx5CM7oiChJt2Q==",
+      "dev": true
+    },
     "json-schema-traverse": {
       "version": "0.4.1",
       "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
@@ -5755,6 +5691,16 @@
         "leven": "^3.1.0"
       }
     },
+    "levn": {
+      "version": "0.4.1",
+      "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
+      "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
+      "dev": true,
+      "requires": {
+        "prelude-ls": "^1.2.1",
+        "type-check": "~0.4.0"
+      }
+    },
     "lines-and-columns": {
       "version": "1.1.6",
       "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz",
@@ -5762,9 +5708,9 @@
       "dev": true
     },
     "linguist-languages": {
-      "version": "7.9.0",
-      "resolved": "https://registry.npmjs.org/linguist-languages/-/linguist-languages-7.9.0.tgz",
-      "integrity": "sha512-saKTpS7BH8vOOwzrZNTkFL/DuT2JN7cg6oHWY8nAjt89+pV1qFcpbjEEcZdAv9ogc4DcxVFHkXmjeyU/DiFHQw==",
+      "version": "7.10.0",
+      "resolved": "https://registry.npmjs.org/linguist-languages/-/linguist-languages-7.10.0.tgz",
+      "integrity": "sha512-Uqt94P4iAznscZtccnNE1IBi105U+fmQKEUlDJv54JDdFZDInomkepEIRpZLOQcPyGdcNu3JO9Tvo5wpQVbfKw==",
       "dev": true
     },
     "linkify-it": {
@@ -5776,20 +5722,20 @@
       }
     },
     "lint-staged": {
-      "version": "10.2.11",
-      "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-10.2.11.tgz",
-      "integrity": "sha512-LRRrSogzbixYaZItE2APaS4l2eJMjjf5MbclRZpLJtcQJShcvUzKXsNeZgsLIZ0H0+fg2tL4B59fU9wHIHtFIA==",
+      "version": "10.2.13",
+      "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-10.2.13.tgz",
+      "integrity": "sha512-conwlukNV6aL9SiMWjFtDp5exeDnTMekdNPDZsKGnpfQuHcO0E3L3Bbf58lcR+M7vk6LpCilxDAVks/DDVBYlA==",
       "dev": true,
       "requires": {
-        "chalk": "^4.0.0",
-        "cli-truncate": "2.1.0",
-        "commander": "^5.1.0",
-        "cosmiconfig": "^6.0.0",
+        "chalk": "^4.1.0",
+        "cli-truncate": "^2.1.0",
+        "commander": "^6.0.0",
+        "cosmiconfig": "^7.0.0",
         "debug": "^4.1.1",
         "dedent": "^0.7.0",
-        "enquirer": "^2.3.5",
-        "execa": "^4.0.1",
-        "listr2": "^2.1.0",
+        "enquirer": "^2.3.6",
+        "execa": "^4.0.3",
+        "listr2": "^2.6.0",
         "log-symbols": "^4.0.0",
         "micromatch": "^4.0.2",
         "normalize-path": "^3.0.0",
@@ -5798,6 +5744,16 @@
         "stringify-object": "^3.3.0"
       },
       "dependencies": {
+        "ansi-styles": {
+          "version": "4.2.1",
+          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz",
+          "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==",
+          "dev": true,
+          "requires": {
+            "@types/color-name": "^1.1.1",
+            "color-convert": "^2.0.1"
+          }
+        },
         "braces": {
           "version": "3.0.2",
           "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
@@ -5807,26 +5763,42 @@
             "fill-range": "^7.0.1"
           }
         },
-        "cosmiconfig": {
-          "version": "6.0.0",
-          "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz",
-          "integrity": "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==",
+        "chalk": {
+          "version": "4.1.0",
+          "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz",
+          "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==",
           "dev": true,
           "requires": {
-            "@types/parse-json": "^4.0.0",
-            "import-fresh": "^3.1.0",
-            "parse-json": "^5.0.0",
-            "path-type": "^4.0.0",
-            "yaml": "^1.7.2"
+            "ansi-styles": "^4.1.0",
+            "supports-color": "^7.1.0"
           }
         },
-        "debug": {
-          "version": "4.1.1",
-          "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
-          "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+        "color-convert": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+          "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
           "dev": true,
           "requires": {
-            "ms": "^2.1.1"
+            "color-name": "~1.1.4"
+          }
+        },
+        "color-name": {
+          "version": "1.1.4",
+          "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+          "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+          "dev": true
+        },
+        "cosmiconfig": {
+          "version": "7.0.0",
+          "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.0.tgz",
+          "integrity": "sha512-pondGvTuVYDk++upghXJabWzL6Kxu6f26ljFw64Swq9v6sQPUL3EUlVDV56diOjpCayKihL6hVe8exIACU4XcA==",
+          "dev": true,
+          "requires": {
+            "@types/parse-json": "^4.0.0",
+            "import-fresh": "^3.2.1",
+            "parse-json": "^5.0.0",
+            "path-type": "^4.0.0",
+            "yaml": "^1.10.0"
           }
         },
         "fill-range": {
@@ -5838,6 +5810,12 @@
             "to-regex-range": "^5.0.1"
           }
         },
+        "has-flag": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+          "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+          "dev": true
+        },
         "import-fresh": {
           "version": "3.2.1",
           "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.1.tgz",
@@ -5873,21 +5851,15 @@
             "picomatch": "^2.0.5"
           }
         },
-        "ms": {
-          "version": "2.1.2",
-          "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
-          "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
-          "dev": true
-        },
         "parse-json": {
-          "version": "5.0.0",
-          "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.0.0.tgz",
-          "integrity": "sha512-OOY5b7PAEFV0E2Fir1KOkxchnZNCdowAJgQ5NuxjpBKTRP3pQhwkrkxqQjeoKJ+fO7bCpmIZaogI4eZGDMEGOw==",
+          "version": "5.1.0",
+          "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.1.0.tgz",
+          "integrity": "sha512-+mi/lmVVNKFNVyLXV31ERiy2CY5E1/F6QtJFEzoChPRwwngMNXRDQ9GJ5WdE2Z2P4AujsOi0/+2qHID68KwfIQ==",
           "dev": true,
           "requires": {
             "@babel/code-frame": "^7.0.0",
             "error-ex": "^1.3.1",
-            "json-parse-better-errors": "^1.0.1",
+            "json-parse-even-better-errors": "^2.3.0",
             "lines-and-columns": "^1.1.6"
           }
         },
@@ -5897,6 +5869,15 @@
           "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
           "dev": true
         },
+        "supports-color": {
+          "version": "7.1.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz",
+          "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==",
+          "dev": true,
+          "requires": {
+            "has-flag": "^4.0.0"
+          }
+        },
         "to-regex-range": {
           "version": "5.0.1",
           "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
@@ -5909,55 +5890,79 @@
       }
     },
     "listr2": {
-      "version": "2.1.8",
-      "resolved": "https://registry.npmjs.org/listr2/-/listr2-2.1.8.tgz",
-      "integrity": "sha512-Op+hheiChfAphkJ5qUxZtHgyjlX9iNnAeFS/S134xw7mVSg0YVrQo1IY4/K+ElY6XgOPg2Ij4z07urUXR+YEew==",
+      "version": "2.6.1",
+      "resolved": "https://registry.npmjs.org/listr2/-/listr2-2.6.1.tgz",
+      "integrity": "sha512-1aPX9GkS+W0aHfPUDedJqeqj0DOe1605NaNoqdwEYw/UF2UbZgCIIMpXXZALeG/8xzwMBztguzQEubU5Xw1Qbw==",
       "dev": true,
       "requires": {
-        "chalk": "^4.0.0",
+        "chalk": "^4.1.0",
         "cli-truncate": "^2.1.0",
         "figures": "^3.2.0",
         "indent-string": "^4.0.0",
         "log-update": "^4.0.0",
         "p-map": "^4.0.0",
-        "rxjs": "^6.5.5",
+        "rxjs": "^6.6.2",
         "through": "^2.3.8"
       },
       "dependencies": {
-        "figures": {
-          "version": "3.2.0",
-          "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz",
-          "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==",
-          "dev": true,
-          "requires": {
-            "escape-string-regexp": "^1.0.5"
+        "ansi-styles": {
+          "version": "4.2.1",
+          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz",
+          "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==",
+          "dev": true,
+          "requires": {
+            "@types/color-name": "^1.1.1",
+            "color-convert": "^2.0.1"
           }
-        }
-      }
-    },
-    "load-json-file": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz",
-      "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=",
-      "dev": true,
-      "requires": {
-        "graceful-fs": "^4.1.2",
-        "parse-json": "^4.0.0",
-        "pify": "^3.0.0",
-        "strip-bom": "^3.0.0"
-      },
-      "dependencies": {
-        "pify": {
-          "version": "3.0.0",
-          "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
-          "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
+        },
+        "chalk": {
+          "version": "4.1.0",
+          "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz",
+          "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==",
+          "dev": true,
+          "requires": {
+            "ansi-styles": "^4.1.0",
+            "supports-color": "^7.1.0"
+          }
+        },
+        "color-convert": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+          "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+          "dev": true,
+          "requires": {
+            "color-name": "~1.1.4"
+          }
+        },
+        "color-name": {
+          "version": "1.1.4",
+          "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+          "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
           "dev": true
         },
-        "strip-bom": {
-          "version": "3.0.0",
-          "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
-          "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=",
+        "figures": {
+          "version": "3.2.0",
+          "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz",
+          "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==",
+          "dev": true,
+          "requires": {
+            "escape-string-regexp": "^1.0.5"
+          }
+        },
+        "has-flag": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+          "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
           "dev": true
+        },
+        "supports-color": {
+          "version": "7.1.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz",
+          "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==",
+          "dev": true,
+          "requires": {
+            "has-flag": "^4.0.0"
+          }
         }
       }
     },
@@ -6143,9 +6148,9 @@
           "dev": true
         },
         "onetime": {
-          "version": "5.1.0",
-          "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.0.tgz",
-          "integrity": "sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q==",
+          "version": "5.1.2",
+          "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
+          "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==",
           "dev": true,
           "requires": {
             "mimic-fn": "^2.1.0"
@@ -6201,16 +6206,6 @@
         "js-tokens": "^3.0.0 || ^4.0.0"
       }
     },
-    "loud-rejection": {
-      "version": "1.6.0",
-      "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz",
-      "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=",
-      "dev": true,
-      "requires": {
-        "currently-unhandled": "^0.4.1",
-        "signal-exit": "^3.0.0"
-      }
-    },
     "magic-string": {
       "version": "0.25.7",
       "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.7.tgz",
@@ -6224,310 +6219,131 @@
       "version": "0.1.3",
       "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz",
       "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==",
-      "dev": true,
-      "requires": {
-        "p-defer": "^1.0.0"
-      }
-    },
-    "map-cache": {
-      "version": "0.2.2",
-      "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz",
-      "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=",
-      "dev": true
-    },
-    "map-obj": {
-      "version": "4.1.0",
-      "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.1.0.tgz",
-      "integrity": "sha512-glc9y00wgtwcDmp7GaE/0b0OnxpNJsVf3ael/An6Fe2Q51LLwN1er6sdomLRzz5h0+yMpiYLhWYF5R7HeqVd4g==",
-      "dev": true
-    },
-    "map-visit": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz",
-      "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=",
-      "dev": true,
-      "requires": {
-        "object-visit": "^1.0.0"
-      }
-    },
-    "markdown-escapes": {
-      "version": "1.0.4",
-      "resolved": "https://registry.npmjs.org/markdown-escapes/-/markdown-escapes-1.0.4.tgz",
-      "integrity": "sha512-8z4efJYk43E0upd0NbVXwgSTQs6cT3T06etieCMEg7dRbzCbxUCK/GHlX8mhHRDcp+OLlHkPKsvqQTCvsRl2cg==",
-      "dev": true
-    },
-    "markdown-it": {
-      "version": "10.0.0",
-      "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-10.0.0.tgz",
-      "integrity": "sha512-YWOP1j7UbDNz+TumYP1kpwnP0aEa711cJjrAQrzd0UXlbJfc5aAq0F/PZHjiioqDC1NKgvIMX+o+9Bk7yuM2dg==",
-      "requires": {
-        "argparse": "^1.0.7",
-        "entities": "~2.0.0",
-        "linkify-it": "^2.0.0",
-        "mdurl": "^1.0.1",
-        "uc.micro": "^1.0.5"
-      },
-      "dependencies": {
-        "entities": {
-          "version": "2.0.3",
-          "resolved": "https://registry.npmjs.org/entities/-/entities-2.0.3.tgz",
-          "integrity": "sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ=="
-        }
-      }
-    },
-    "markdown-table": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-2.0.0.tgz",
-      "integrity": "sha512-Ezda85ToJUBhM6WGaG6veasyym+Tbs3cMAw/ZhOPqXiYsr0jgocBV3j3nx+4lk47plLlIqjwuTm/ywVI+zjJ/A==",
-      "dev": true,
-      "requires": {
-        "repeat-string": "^1.0.0"
-      }
-    },
-    "matched": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/matched/-/matched-1.0.2.tgz",
-      "integrity": "sha512-7ivM1jFZVTOOS77QsR+TtYHH0ecdLclMkqbf5qiJdX2RorqfhsL65QHySPZgDE0ZjHoh+mQUNHTanNXIlzXd0Q==",
-      "dev": true,
-      "requires": {
-        "arr-union": "^3.1.0",
-        "async-array-reduce": "^0.2.1",
-        "glob": "^7.1.2",
-        "has-glob": "^1.0.0",
-        "is-valid-glob": "^1.0.0",
-        "resolve-dir": "^1.0.0"
-      }
-    },
-    "mathml-tag-names": {
-      "version": "2.1.3",
-      "resolved": "https://registry.npmjs.org/mathml-tag-names/-/mathml-tag-names-2.1.3.tgz",
-      "integrity": "sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg==",
-      "dev": true
-    },
-    "mdast-util-compact": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/mdast-util-compact/-/mdast-util-compact-2.0.1.tgz",
-      "integrity": "sha512-7GlnT24gEwDrdAwEHrU4Vv5lLWrEer4KOkAiKT9nYstsTad7Oc1TwqT2zIMKRdZF7cTuaf+GA1E4Kv7jJh8mPA==",
-      "dev": true,
-      "requires": {
-        "unist-util-visit": "^2.0.0"
-      }
-    },
-    "mdn-data": {
-      "version": "2.0.4",
-      "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.4.tgz",
-      "integrity": "sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA==",
-      "dev": true
-    },
-    "mdurl": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz",
-      "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4="
-    },
-    "mem": {
-      "version": "6.1.0",
-      "resolved": "https://registry.npmjs.org/mem/-/mem-6.1.0.tgz",
-      "integrity": "sha512-RlbnLQgRHk5lwqTtpEkBTQ2ll/CG/iB+J4Hy2Wh97PjgZgXgWJWrFF+XXujh3UUVLvR4OOTgZzcWMMwnehlEUg==",
-      "dev": true,
-      "requires": {
-        "map-age-cleaner": "^0.1.3",
-        "mimic-fn": "^3.0.0"
-      },
-      "dependencies": {
-        "mimic-fn": {
-          "version": "3.0.0",
-          "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-3.0.0.tgz",
-          "integrity": "sha512-PiVO95TKvhiwgSwg1IdLYlCTdul38yZxZMIcnDSFIBUm4BNZha2qpQ4GpJ++15bHoKDtrW2D69lMfFwdFYtNZQ==",
-          "dev": true
-        }
-      }
-    },
-    "meow": {
-      "version": "5.0.0",
-      "resolved": "https://registry.npmjs.org/meow/-/meow-5.0.0.tgz",
-      "integrity": "sha512-CbTqYU17ABaLefO8vCU153ZZlprKYWDljcndKKDCFcYQITzWCXZAVk4QMFZPgvzrnUQ3uItnIE/LoUOwrT15Ig==",
-      "dev": true,
-      "requires": {
-        "camelcase-keys": "^4.0.0",
-        "decamelize-keys": "^1.0.0",
-        "loud-rejection": "^1.0.0",
-        "minimist-options": "^3.0.1",
-        "normalize-package-data": "^2.3.4",
-        "read-pkg-up": "^3.0.0",
-        "redent": "^2.0.0",
-        "trim-newlines": "^2.0.0",
-        "yargs-parser": "^10.0.0"
-      },
-      "dependencies": {
-        "arrify": {
-          "version": "1.0.1",
-          "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz",
-          "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=",
-          "dev": true
-        },
-        "camelcase": {
-          "version": "4.1.0",
-          "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz",
-          "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=",
-          "dev": true
-        },
-        "camelcase-keys": {
-          "version": "4.2.0",
-          "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-4.2.0.tgz",
-          "integrity": "sha1-oqpfsa9oh1glnDLBQUJteJI7m3c=",
-          "dev": true,
-          "requires": {
-            "camelcase": "^4.1.0",
-            "map-obj": "^2.0.0",
-            "quick-lru": "^1.0.0"
-          }
-        },
-        "find-up": {
-          "version": "2.1.0",
-          "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz",
-          "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=",
-          "dev": true,
-          "requires": {
-            "locate-path": "^2.0.0"
-          }
-        },
-        "indent-string": {
-          "version": "3.2.0",
-          "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz",
-          "integrity": "sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=",
-          "dev": true
-        },
-        "locate-path": {
-          "version": "2.0.0",
-          "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz",
-          "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=",
-          "dev": true,
-          "requires": {
-            "p-locate": "^2.0.0",
-            "path-exists": "^3.0.0"
-          }
-        },
-        "map-obj": {
-          "version": "2.0.0",
-          "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-2.0.0.tgz",
-          "integrity": "sha1-plzSkIepJZi4eRJXpSPgISIqwfk=",
-          "dev": true
-        },
-        "minimist-options": {
-          "version": "3.0.2",
-          "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-3.0.2.tgz",
-          "integrity": "sha512-FyBrT/d0d4+uiZRbqznPXqw3IpZZG3gl3wKWiX784FycUKVwBt0uLBFkQrtE4tZOrgo78nZp2jnKz3L65T5LdQ==",
-          "dev": true,
-          "requires": {
-            "arrify": "^1.0.1",
-            "is-plain-obj": "^1.1.0"
-          }
-        },
-        "p-limit": {
-          "version": "1.3.0",
-          "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz",
-          "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==",
-          "dev": true,
-          "requires": {
-            "p-try": "^1.0.0"
-          }
-        },
-        "p-locate": {
-          "version": "2.0.0",
-          "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz",
-          "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=",
-          "dev": true,
-          "requires": {
-            "p-limit": "^1.1.0"
-          }
-        },
-        "p-try": {
-          "version": "1.0.0",
-          "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz",
-          "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=",
-          "dev": true
-        },
-        "path-exists": {
-          "version": "3.0.0",
-          "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
-          "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=",
-          "dev": true
-        },
-        "path-type": {
-          "version": "3.0.0",
-          "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz",
-          "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==",
-          "dev": true,
-          "requires": {
-            "pify": "^3.0.0"
-          }
-        },
-        "pify": {
-          "version": "3.0.0",
-          "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
-          "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
-          "dev": true
-        },
-        "quick-lru": {
-          "version": "1.1.0",
-          "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-1.1.0.tgz",
-          "integrity": "sha1-Q2CxfGETatOAeDl/8RQW4Ybc+7g=",
-          "dev": true
-        },
-        "read-pkg": {
-          "version": "3.0.0",
-          "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz",
-          "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=",
-          "dev": true,
-          "requires": {
-            "load-json-file": "^4.0.0",
-            "normalize-package-data": "^2.3.2",
-            "path-type": "^3.0.0"
-          }
-        },
-        "read-pkg-up": {
-          "version": "3.0.0",
-          "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-3.0.0.tgz",
-          "integrity": "sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc=",
-          "dev": true,
-          "requires": {
-            "find-up": "^2.0.0",
-            "read-pkg": "^3.0.0"
-          }
-        },
-        "redent": {
-          "version": "2.0.0",
-          "resolved": "https://registry.npmjs.org/redent/-/redent-2.0.0.tgz",
-          "integrity": "sha1-wbIAe0LVfrE4kHmzyDM2OdXhzKo=",
-          "dev": true,
-          "requires": {
-            "indent-string": "^3.0.0",
-            "strip-indent": "^2.0.0"
-          }
-        },
-        "strip-indent": {
-          "version": "2.0.0",
-          "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-2.0.0.tgz",
-          "integrity": "sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g=",
-          "dev": true
-        },
-        "trim-newlines": {
-          "version": "2.0.0",
-          "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-2.0.0.tgz",
-          "integrity": "sha1-tAPQuRvlDDMd/EuC7s6yLD3hbSA=",
-          "dev": true
-        },
-        "yargs-parser": {
-          "version": "10.1.0",
-          "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-10.1.0.tgz",
-          "integrity": "sha512-VCIyR1wJoEBZUqk5PA+oOBF6ypbwh5aNB3I50guxAL/quggdfs4TtNHQrSazFA3fYZ+tEqfs0zIGlv0c/rgjbQ==",
-          "dev": true,
-          "requires": {
-            "camelcase": "^4.1.0"
-          }
+      "dev": true,
+      "requires": {
+        "p-defer": "^1.0.0"
+      }
+    },
+    "map-cache": {
+      "version": "0.2.2",
+      "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz",
+      "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=",
+      "dev": true
+    },
+    "map-obj": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.1.0.tgz",
+      "integrity": "sha512-glc9y00wgtwcDmp7GaE/0b0OnxpNJsVf3ael/An6Fe2Q51LLwN1er6sdomLRzz5h0+yMpiYLhWYF5R7HeqVd4g==",
+      "dev": true
+    },
+    "map-visit": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz",
+      "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=",
+      "dev": true,
+      "requires": {
+        "object-visit": "^1.0.0"
+      }
+    },
+    "markdown-escapes": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/markdown-escapes/-/markdown-escapes-1.0.4.tgz",
+      "integrity": "sha512-8z4efJYk43E0upd0NbVXwgSTQs6cT3T06etieCMEg7dRbzCbxUCK/GHlX8mhHRDcp+OLlHkPKsvqQTCvsRl2cg==",
+      "dev": true
+    },
+    "markdown-it": {
+      "version": "10.0.0",
+      "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-10.0.0.tgz",
+      "integrity": "sha512-YWOP1j7UbDNz+TumYP1kpwnP0aEa711cJjrAQrzd0UXlbJfc5aAq0F/PZHjiioqDC1NKgvIMX+o+9Bk7yuM2dg==",
+      "requires": {
+        "argparse": "^1.0.7",
+        "entities": "~2.0.0",
+        "linkify-it": "^2.0.0",
+        "mdurl": "^1.0.1",
+        "uc.micro": "^1.0.5"
+      },
+      "dependencies": {
+        "entities": {
+          "version": "2.0.3",
+          "resolved": "https://registry.npmjs.org/entities/-/entities-2.0.3.tgz",
+          "integrity": "sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ=="
         }
       }
     },
+    "markdown-table": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-2.0.0.tgz",
+      "integrity": "sha512-Ezda85ToJUBhM6WGaG6veasyym+Tbs3cMAw/ZhOPqXiYsr0jgocBV3j3nx+4lk47plLlIqjwuTm/ywVI+zjJ/A==",
+      "dev": true,
+      "requires": {
+        "repeat-string": "^1.0.0"
+      }
+    },
+    "matched": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/matched/-/matched-5.0.0.tgz",
+      "integrity": "sha512-O0LCuxYYBNBjP2dmAg0i6PME0Mb0dvjulpMC0tTIeMRh6kXYsugOT5GOWpFkSzqjQjgOUs/eiyvpVhXdN2La4g==",
+      "dev": true,
+      "requires": {
+        "glob": "^7.1.6",
+        "picomatch": "^2.2.1"
+      }
+    },
+    "mathml-tag-names": {
+      "version": "2.1.3",
+      "resolved": "https://registry.npmjs.org/mathml-tag-names/-/mathml-tag-names-2.1.3.tgz",
+      "integrity": "sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg==",
+      "dev": true
+    },
+    "mdast-util-compact": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/mdast-util-compact/-/mdast-util-compact-2.0.1.tgz",
+      "integrity": "sha512-7GlnT24gEwDrdAwEHrU4Vv5lLWrEer4KOkAiKT9nYstsTad7Oc1TwqT2zIMKRdZF7cTuaf+GA1E4Kv7jJh8mPA==",
+      "dev": true,
+      "requires": {
+        "unist-util-visit": "^2.0.0"
+      }
+    },
+    "mdn-data": {
+      "version": "2.0.4",
+      "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.4.tgz",
+      "integrity": "sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA==",
+      "dev": true
+    },
+    "mdurl": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz",
+      "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4="
+    },
+    "mem": {
+      "version": "6.1.0",
+      "resolved": "https://registry.npmjs.org/mem/-/mem-6.1.0.tgz",
+      "integrity": "sha512-RlbnLQgRHk5lwqTtpEkBTQ2ll/CG/iB+J4Hy2Wh97PjgZgXgWJWrFF+XXujh3UUVLvR4OOTgZzcWMMwnehlEUg==",
+      "dev": true,
+      "requires": {
+        "map-age-cleaner": "^0.1.3",
+        "mimic-fn": "^3.0.0"
+      }
+    },
+    "meow": {
+      "version": "7.1.0",
+      "resolved": "https://registry.npmjs.org/meow/-/meow-7.1.0.tgz",
+      "integrity": "sha512-kq5F0KVteskZ3JdfyQFivJEj2RaA8NFsS4+r9DaMKLcUHpk5OcHS3Q0XkCXONB1mZRPsu/Y/qImKri0nwSEZog==",
+      "dev": true,
+      "requires": {
+        "@types/minimist": "^1.2.0",
+        "camelcase-keys": "^6.2.2",
+        "decamelize-keys": "^1.1.0",
+        "hard-rejection": "^2.1.0",
+        "minimist-options": "4.1.0",
+        "normalize-package-data": "^2.5.0",
+        "read-pkg-up": "^7.0.1",
+        "redent": "^3.0.0",
+        "trim-newlines": "^3.0.0",
+        "type-fest": "^0.13.1",
+        "yargs-parser": "^18.1.3"
+      }
+    },
     "merge": {
       "version": "1.2.1",
       "resolved": "https://registry.npmjs.org/merge/-/merge-1.2.1.tgz",
@@ -6568,9 +6384,9 @@
       }
     },
     "mimic-fn": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz",
-      "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==",
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-3.1.0.tgz",
+      "integrity": "sha512-Ysbi9uYW9hFyfrThdDEQuykN4Ey6BuwPD2kpI5ES/nFTDn/98yxYNLZJcgUAKPT/mcrLLKaGzJR9YVxJrIdASQ==",
       "dev": true
     },
     "min-indent": {
@@ -6650,9 +6466,9 @@
       }
     },
     "ms": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
-      "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+      "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
       "dev": true
     },
     "mute-stream": {
@@ -6812,6 +6628,12 @@
         }
       }
     },
+    "object-hash": {
+      "version": "2.0.3",
+      "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-2.0.3.tgz",
+      "integrity": "sha512-JPKn0GMu+Fa3zt3Bmr66JhokJU5BaNBIh4ZeTlaCBzrBsOeXzwcKKAK1tbLiPKgvwmPXsDvvLHoWh5Bm7ofIYg==",
+      "dev": true
+    },
     "object-keys": {
       "version": "1.1.1",
       "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
@@ -6886,6 +6708,14 @@
       "dev": true,
       "requires": {
         "mimic-fn": "^1.0.0"
+      },
+      "dependencies": {
+        "mimic-fn": {
+          "version": "1.2.0",
+          "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz",
+          "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==",
+          "dev": true
+        }
       }
     },
     "opencollective-postinstall": {
@@ -6894,6 +6724,20 @@
       "integrity": "sha512-8AV/sCtuzUeTo8gQK5qDZzARrulB3egtLzFgteqB2tcT4Mw7B8Kt7JcDHmltjz6FOAHsvTevk70gZEbhM4ZS9Q==",
       "dev": true
     },
+    "optionator": {
+      "version": "0.9.1",
+      "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz",
+      "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==",
+      "dev": true,
+      "requires": {
+        "deep-is": "^0.1.3",
+        "fast-levenshtein": "^2.0.6",
+        "levn": "^0.4.1",
+        "prelude-ls": "^1.2.1",
+        "type-check": "^0.4.0",
+        "word-wrap": "^1.2.3"
+      }
+    },
     "orderedmap": {
       "version": "1.1.1",
       "resolved": "https://registry.npmjs.org/orderedmap/-/orderedmap-1.1.1.tgz",
@@ -6945,9 +6789,9 @@
       }
     },
     "p-queue": {
-      "version": "6.6.0",
-      "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-6.6.0.tgz",
-      "integrity": "sha512-zPHXPNy9jZsiym0PpJjvnHQysx1fSd/QdaNVwiDRLU2KFChD6h9CkCB6b8i3U8lBwJyA+mHgNZCzcy77glUssQ==",
+      "version": "6.6.1",
+      "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-6.6.1.tgz",
+      "integrity": "sha512-miQiSxLYPYBxGkrldecZC18OTLjdUqnlRebGzPRiVxB8mco7usCmm7hFuxiTvp93K18JnLtE4KMMycjAu/cQQg==",
       "dev": true,
       "requires": {
         "eventemitter3": "^4.0.4",
@@ -8081,12 +7925,12 @@
       }
     },
     "postcss-nested": {
-      "version": "4.2.1",
-      "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-4.2.1.tgz",
-      "integrity": "sha512-AMayXX8tS0HCp4O4lolp4ygj9wBn32DJWXvG6gCv+ZvJrEa00GUxJcJEEzMh87BIe6FrWdYkpR2cuyqHKrxmXw==",
+      "version": "4.2.3",
+      "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-4.2.3.tgz",
+      "integrity": "sha512-rOv0W1HquRCamWy2kFl3QazJMMe1ku6rCFoAAH+9AcxdbpDeBr6k968MLWuLjvjMcGEip01ak09hKOEgpK9hvw==",
       "dev": true,
       "requires": {
-        "postcss": "^7.0.21",
+        "postcss": "^7.0.32",
         "postcss-selector-parser": "^6.0.2"
       }
     },
@@ -8568,10 +8412,16 @@
         "uniq": "^1.0.1"
       }
     },
+    "prelude-ls": {
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
+      "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
+      "dev": true
+    },
     "prettier": {
-      "version": "2.0.5",
-      "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.0.5.tgz",
-      "integrity": "sha512-7PtVymN48hGcO4fGjybyBSIWDsLU4H4XlvOHfq91pz9kkGlonzwTfYkaIEwiRg/dAJF9YlbsduBAgtYLi+8cFg==",
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.1.1.tgz",
+      "integrity": "sha512-9bY+5ZWCfqj3ghYBLxApy2zf6m+NJo5GzmLTpr9FsApsfjriNnS2dahWReHMi7qNPhhHl9SYHJs2cHZLgexNIw==",
       "dev": true
     },
     "prettier-linter-helpers": {
@@ -8743,9 +8593,9 @@
       }
     },
     "prosemirror-view": {
-      "version": "1.15.2",
-      "resolved": "https://registry.npmjs.org/prosemirror-view/-/prosemirror-view-1.15.2.tgz",
-      "integrity": "sha512-0wftmMDVD8VXj2HZgv6Rg//+tgJC0lpV9LkYlCiAkDLKsf4yW3Ozs5td1ZXqsyoqvX0ga/k5g2EyLbqOMmC1+w==",
+      "version": "1.15.5",
+      "resolved": "https://registry.npmjs.org/prosemirror-view/-/prosemirror-view-1.15.5.tgz",
+      "integrity": "sha512-VpAP/Rh7a4l1udpR3lEym2FlTD93JZjWChHYgzLgiBI6alOapG4GEsyAEq0l8eUJd9Ujf55+5dlEuItxI3a9Mw==",
       "requires": {
         "prosemirror-model": "^1.1.0",
         "prosemirror-state": "^1.0.0",
@@ -8769,64 +8619,22 @@
       "dev": true
     },
     "purgecss": {
-      "version": "2.2.1",
-      "resolved": "https://registry.npmjs.org/purgecss/-/purgecss-2.2.1.tgz",
-      "integrity": "sha512-wngRSLW1dpNr8kr3TL9nTJMyTFI5BiRiaUUEys5M1CA4zEHLF25fRHoshEeDqmhstaNTOddmpYM34zRrUtEGbQ==",
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/purgecss/-/purgecss-2.3.0.tgz",
+      "integrity": "sha512-BE5CROfVGsx2XIhxGuZAT7rTH9lLeQx/6M0P7DTXQH4IUc3BBzs9JUzt4yzGf3JrH9enkeq6YJBe9CTtkm1WmQ==",
       "dev": true,
       "requires": {
         "commander": "^5.0.0",
         "glob": "^7.0.0",
-        "postcss": "7.0.28",
+        "postcss": "7.0.32",
         "postcss-selector-parser": "^6.0.2"
       },
       "dependencies": {
-        "chalk": {
-          "version": "2.4.2",
-          "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
-          "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
-          "dev": true,
-          "requires": {
-            "ansi-styles": "^3.2.1",
-            "escape-string-regexp": "^1.0.5",
-            "supports-color": "^5.3.0"
-          },
-          "dependencies": {
-            "supports-color": {
-              "version": "5.5.0",
-              "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
-              "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
-              "dev": true,
-              "requires": {
-                "has-flag": "^3.0.0"
-              }
-            }
-          }
-        },
-        "postcss": {
-          "version": "7.0.28",
-          "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.28.tgz",
-          "integrity": "sha512-YU6nVhyWIsVtlNlnAj1fHTsUKW5qxm3KEgzq2Jj6KTEFOTK8QWR12eIDvrlWhiSTK8WIBFTBhOJV4DY6dUuEbw==",
-          "dev": true,
-          "requires": {
-            "chalk": "^2.4.2",
-            "source-map": "^0.6.1",
-            "supports-color": "^6.1.0"
-          }
-        },
-        "source-map": {
-          "version": "0.6.1",
-          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
-          "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+        "commander": {
+          "version": "5.1.0",
+          "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz",
+          "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==",
           "dev": true
-        },
-        "supports-color": {
-          "version": "6.1.0",
-          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
-          "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
-          "dev": true,
-          "requires": {
-            "has-flag": "^3.0.0"
-          }
         }
       }
     },
@@ -8978,13 +8786,6 @@
         "regenerate": "^1.4.0"
       }
     },
-    "regenerator-runtime": {
-      "version": "0.11.1",
-      "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz",
-      "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==",
-      "dev": true,
-      "optional": true
-    },
     "regenerator-transform": {
       "version": "0.14.5",
       "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.5.tgz",
@@ -9209,9 +9010,9 @@
       "dev": true
     },
     "rollup": {
-      "version": "2.23.0",
-      "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.23.0.tgz",
-      "integrity": "sha512-vLNmZFUGVwrnqNAJ/BvuLk1MtWzu4IuoqsH9UWK5AIdO3rt8/CSiJNvPvCIvfzrbNsqKbNzPAG1V2O4eTe2XZg==",
+      "version": "2.26.6",
+      "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.26.6.tgz",
+      "integrity": "sha512-iSB7eE3k/VNQHnI7ckS++4yIqTamoUCB1xo7MswhJ/fg22oFYR5+xCrUZVviBj97jvc5A31MPbVMw1Wc3jWxmw==",
       "dev": true,
       "requires": {
         "fsevents": "~2.1.2"
@@ -9266,9 +9067,9 @@
       }
     },
     "rollup-plugin-postcss": {
-      "version": "3.1.3",
-      "resolved": "https://registry.npmjs.org/rollup-plugin-postcss/-/rollup-plugin-postcss-3.1.3.tgz",
-      "integrity": "sha512-5Zm70/HkuYaQuhFbiGSO3U0bVj0magAPo09sd4sRE7I434Iwe4p7xF43pYfW0BcDvY0ZxzD3Fh2vRJzsm4OEiQ==",
+      "version": "3.1.6",
+      "resolved": "https://registry.npmjs.org/rollup-plugin-postcss/-/rollup-plugin-postcss-3.1.6.tgz",
+      "integrity": "sha512-lkKMTXhPyaNgELFFf7mAGLqFTr13Lswak1YkP+b9rfl6YNVHxs3PYgZFAGLOyLvOtSuCVRq6BryXs1EgyC+nHQ==",
       "dev": true,
       "requires": {
         "chalk": "^4.0.0",
@@ -9320,15 +9121,54 @@
       }
     },
     "rollup-plugin-terser": {
-      "version": "6.1.0",
-      "resolved": "https://registry.npmjs.org/rollup-plugin-terser/-/rollup-plugin-terser-6.1.0.tgz",
-      "integrity": "sha512-4fB3M9nuoWxrwm39habpd4hvrbrde2W2GG4zEGPQg1YITNkM3Tqur5jSuXlWNzbv/2aMLJ+dZJaySc3GCD8oDw==",
+      "version": "7.0.0",
+      "resolved": "https://registry.npmjs.org/rollup-plugin-terser/-/rollup-plugin-terser-7.0.0.tgz",
+      "integrity": "sha512-p/N3lLiFusCjYTLfVkoaiRTOGr5AESEaljMPH12MhOtoMkmTBhIAfuadrcWy4am1U0vU4WTxO9fi0K09O4CboQ==",
       "dev": true,
       "requires": {
-        "@babel/code-frame": "^7.8.3",
-        "jest-worker": "^26.0.0",
-        "serialize-javascript": "^3.0.0",
-        "terser": "^4.7.0"
+        "@babel/code-frame": "^7.10.4",
+        "jest-worker": "^26.2.1",
+        "serialize-javascript": "^4.0.0",
+        "terser": "^5.0.0"
+      },
+      "dependencies": {
+        "@babel/code-frame": {
+          "version": "7.10.4",
+          "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz",
+          "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==",
+          "dev": true,
+          "requires": {
+            "@babel/highlight": "^7.10.4"
+          }
+        },
+        "@babel/helper-validator-identifier": {
+          "version": "7.10.4",
+          "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz",
+          "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==",
+          "dev": true
+        },
+        "@babel/highlight": {
+          "version": "7.10.4",
+          "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz",
+          "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==",
+          "dev": true,
+          "requires": {
+            "@babel/helper-validator-identifier": "^7.10.4",
+            "chalk": "^2.0.0",
+            "js-tokens": "^4.0.0"
+          }
+        },
+        "chalk": {
+          "version": "2.4.2",
+          "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+          "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+          "dev": true,
+          "requires": {
+            "ansi-styles": "^3.2.1",
+            "escape-string-regexp": "^1.0.5",
+            "supports-color": "^5.3.0"
+          }
+        }
       }
     },
     "rollup-pluginutils": {
@@ -9366,9 +9206,9 @@
       "dev": true
     },
     "rxjs": {
-      "version": "6.5.5",
-      "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.5.tgz",
-      "integrity": "sha512-WfQI+1gohdf0Dai/Bbmk5L5ItH5tYqm3ki2c5GdWhKjalzjg93N3avFjVStyZZz+A2Em+ZxKH5bNghw9UeylGQ==",
+      "version": "6.6.2",
+      "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.2.tgz",
+      "integrity": "sha512-BHdBMVoWC2sL26w//BCu3YzKT4s2jip/WhwsGEDmeKYBhKDZeYezVUnHatYB7L85v5xs0BAQmg6BEYJEKxBabg==",
       "dev": true,
       "requires": {
         "tslib": "^1.9.0"
@@ -9381,9 +9221,9 @@
       "dev": true
     },
     "safe-identifier": {
-      "version": "0.4.1",
-      "resolved": "https://registry.npmjs.org/safe-identifier/-/safe-identifier-0.4.1.tgz",
-      "integrity": "sha512-73tOz5TXsq3apuCc3vC8c9QRhhdNZGiBhHmPPjqpH4TO5oCDqk8UIsDcSs/RG6dYcFAkOOva0pqHS3u7hh7XXA==",
+      "version": "0.4.2",
+      "resolved": "https://registry.npmjs.org/safe-identifier/-/safe-identifier-0.4.2.tgz",
+      "integrity": "sha512-6pNbSMW6OhAi9j+N8V+U715yBQsaWJ7eyEUaOrawX+isg5ZxhUlV1NipNtgaKHmFGiABwt+ZF04Ii+3Xjkg+8w==",
       "dev": true
     },
     "safe-regex": {
@@ -9408,9 +9248,9 @@
       "dev": true
     },
     "semver": {
-      "version": "7.1.3",
-      "resolved": "https://registry.npmjs.org/semver/-/semver-7.1.3.tgz",
-      "integrity": "sha512-ekM0zfiA9SCBlsKa2X1hxyxiI4L3B6EbVJkkdgQXnSEEaHlGdvyodMruTiulSRWMMB4NeIuYNMC9rTKTz97GxA==",
+      "version": "5.7.1",
+      "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+      "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
       "dev": true
     },
     "semver-compare": {
@@ -9426,9 +9266,9 @@
       "dev": true
     },
     "serialize-javascript": {
-      "version": "3.1.0",
-      "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-3.1.0.tgz",
-      "integrity": "sha512-JIJT1DGiWmIKhzRsG91aS6Ze4sFUrYbltlkg2onR5OrnNM02Kl/hnY/T4FN2omvyeBbQmMJv+K4cPOpGzOTFBg==",
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz",
+      "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==",
       "dev": true,
       "requires": {
         "randombytes": "^2.1.0"
@@ -9559,6 +9399,15 @@
         "use": "^3.1.0"
       },
       "dependencies": {
+        "debug": {
+          "version": "2.6.9",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+          "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+          "dev": true,
+          "requires": {
+            "ms": "2.0.0"
+          }
+        },
         "define-property": {
           "version": "0.2.5",
           "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
@@ -9576,6 +9425,12 @@
           "requires": {
             "is-extendable": "^0.1.0"
           }
+        },
+        "ms": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+          "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
+          "dev": true
         }
       }
     },
@@ -9889,6 +9744,14 @@
         "get-own-enumerable-property-symbols": "^3.0.0",
         "is-obj": "^1.0.1",
         "is-regexp": "^1.0.0"
+      },
+      "dependencies": {
+        "is-obj": {
+          "version": "1.0.1",
+          "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz",
+          "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=",
+          "dev": true
+        }
       }
     },
     "strip-ansi": {
@@ -10411,36 +10274,46 @@
       }
     },
     "tailwindcss": {
-      "version": "1.4.6",
-      "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-1.4.6.tgz",
-      "integrity": "sha512-qV0qInUq1FWih39Bc5CWECdgObSzRrbjGD4ke4kAPSIq6WXrPhv0wwOcUWJgJ66ltT9j+XnSRYikG8WNRU/fTQ==",
+      "version": "1.7.5",
+      "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-1.7.5.tgz",
+      "integrity": "sha512-thDHLkRioJh0/62EFcEfQCCBEsZXpluehymrPzn8Hkycy8uI9svvtOqyWtcfkBPB0s5yb6R2tY9zPzh5mIr0Wg==",
       "dev": true,
       "requires": {
         "@fullhuman/postcss-purgecss": "^2.1.2",
         "autoprefixer": "^9.4.5",
         "browserslist": "^4.12.0",
         "bytes": "^3.0.0",
-        "chalk": "^4.0.0",
+        "chalk": "^3.0.0 || ^4.0.0",
         "color": "^3.1.2",
         "detective": "^5.2.0",
         "fs-extra": "^8.0.0",
-        "lodash": "^4.17.15",
+        "lodash": "^4.17.20",
         "node-emoji": "^1.8.1",
         "normalize.css": "^8.0.1",
+        "object-hash": "^2.0.3",
         "postcss": "^7.0.11",
         "postcss-functions": "^3.0.0",
         "postcss-js": "^2.0.0",
         "postcss-nested": "^4.1.1",
         "postcss-selector-parser": "^6.0.0",
+        "postcss-value-parser": "^4.1.0",
         "pretty-hrtime": "^1.0.3",
         "reduce-css-calc": "^2.1.6",
         "resolve": "^1.14.2"
+      },
+      "dependencies": {
+        "lodash": {
+          "version": "4.17.20",
+          "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz",
+          "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==",
+          "dev": true
+        }
       }
     },
     "terser": {
-      "version": "4.8.0",
-      "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.0.tgz",
-      "integrity": "sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw==",
+      "version": "5.2.1",
+      "resolved": "https://registry.npmjs.org/terser/-/terser-5.2.1.tgz",
+      "integrity": "sha512-/AOtjRtAMNGO0fIF6m8HfcvXTw/2AKpsOzDn36tA5RfhRdeXyb4RvHxJ5Pah7iL6dFkLk+gOnCaNHGwJPl6TrQ==",
       "dev": true,
       "requires": {
         "commander": "^2.20.0",
@@ -10604,6 +10477,15 @@
         "tslib": "^1.8.1"
       }
     },
+    "type-check": {
+      "version": "0.4.0",
+      "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
+      "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
+      "dev": true,
+      "requires": {
+        "prelude-ls": "^1.2.1"
+      }
+    },
     "type-fest": {
       "version": "0.13.1",
       "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz",
@@ -10620,9 +10502,9 @@
       }
     },
     "typescript": {
-      "version": "3.9.7",
-      "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.7.tgz",
-      "integrity": "sha512-BLbiRkiBzAwsjut4x/dsibSTB6yWpwT5qWmC2OfuCg3GgVQCSgMs4vEctYPhsaGtd0AeuuHMkjZ2h2WG8MSzRw==",
+      "version": "4.0.2",
+      "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.0.2.tgz",
+      "integrity": "sha512-e4ERvRV2wb+rRZ/IQeb3jm2VxBsirQLpQhdxplZ2MEzGvDkkMmPglecnNDfSUBivMjP93vRbngYYDQqQ/78bcQ==",
       "dev": true
     },
     "uc.micro": {
diff --git a/package.json b/package.json
index f15cb530a5..7b4b8c4ff2 100644
--- a/package.json
+++ b/package.json
@@ -25,55 +25,55 @@
   },
   "dependencies": {
     "@popperjs/core": "^2.4.4",
-    "codemirror": "^5.55.0",
+    "codemirror": "^5.57.0",
     "prosemirror-example-setup": "^1.1.2",
     "prosemirror-markdown": "^1.5.0",
     "prosemirror-state": "^1.3.3",
-    "prosemirror-view": "^1.15.2"
+    "prosemirror-view": "^1.15.5"
   },
   "devDependencies": {
-    "@babel/core": "^7.10.5",
+    "@babel/core": "^7.11.4",
     "@babel/plugin-proposal-class-properties": "^7.10.4",
-    "@babel/preset-env": "^7.10.4",
+    "@babel/preset-env": "^7.11.0",
     "@babel/preset-typescript": "^7.10.4",
-    "@commitlint/cli": "^9.0.1",
-    "@commitlint/config-conventional": "^9.0.1",
-    "@prettier/plugin-php": "^0.14.2",
-    "@rollup/plugin-babel": "^5.1.0",
-    "@rollup/plugin-commonjs": "^14.0.0",
+    "@commitlint/cli": "^9.1.2",
+    "@commitlint/config-conventional": "^9.1.2",
+    "@prettier/plugin-php": "^0.14.3",
+    "@rollup/plugin-babel": "^5.2.0",
+    "@rollup/plugin-commonjs": "^15.0.0",
     "@rollup/plugin-json": "^4.1.0",
-    "@rollup/plugin-multi-entry": "^3.0.1",
-    "@rollup/plugin-node-resolve": "^8.4.0",
+    "@rollup/plugin-multi-entry": "^4.0.0",
+    "@rollup/plugin-node-resolve": "^9.0.0",
     "@tailwindcss/custom-forms": "^0.2.1",
     "@tailwindcss/typography": "^0.2.0",
     "@types/codemirror": "0.0.97",
     "@types/prosemirror-markdown": "^1.0.3",
-    "@types/prosemirror-view": "^1.15.0",
-    "@typescript-eslint/eslint-plugin": "^3.7.0",
-    "@typescript-eslint/parser": "^3.7.0",
+    "@types/prosemirror-view": "^1.15.1",
+    "@typescript-eslint/eslint-plugin": "^3.10.1",
+    "@typescript-eslint/parser": "^3.10.1",
     "cross-env": "^7.0.2",
     "cssnano": "^4.1.10",
-    "cz-conventional-changelog": "^3.2.0",
-    "eslint": "^7.5.0",
+    "cz-conventional-changelog": "^3.3.0",
+    "eslint": "^7.7.0",
     "eslint-config-prettier": "^6.11.0",
     "eslint-plugin-prettier": "^3.1.4",
     "husky": "^4.2.5",
-    "lint-staged": "^10.2.11",
+    "lint-staged": "^10.2.13",
     "postcss-cli": "^7.1.1",
     "postcss-import": "^12.0.1",
     "postcss-preset-env": "^6.7.0",
-    "prettier": "2.0.5",
+    "prettier": "2.1.1",
     "prettier-plugin-organize-imports": "^1.1.1",
-    "rollup": "^2.23.0",
+    "rollup": "^2.26.6",
     "rollup-plugin-multi-input": "^1.1.1",
     "rollup-plugin-node-polyfills": "^0.2.1",
-    "rollup-plugin-postcss": "^3.1.3",
-    "rollup-plugin-terser": "^6.1.0",
+    "rollup-plugin-postcss": "^3.1.6",
+    "rollup-plugin-terser": "^7.0.0",
     "stylelint": "^13.6.1",
     "stylelint-config-standard": "^20.0.0",
     "svgo": "^1.3.2",
-    "tailwindcss": "^1.4.6",
-    "typescript": "^3.9.7"
+    "tailwindcss": "^1.7.5",
+    "typescript": "^4.0.2"
   },
   "husky": {
     "hooks": {
diff --git a/tailwind.config.js b/tailwind.config.js
index 2f7c33d367..12a2371c5c 100644
--- a/tailwind.config.js
+++ b/tailwind.config.js
@@ -5,7 +5,9 @@ module.exports = {
   theme: {
     extend: {},
   },
-  variants: {},
+  variants: {
+    textDecoration: ["responsive", "hover", "focus", "group-hover"],
+  },
   plugins: [
     require("@tailwindcss/custom-forms"),
     require("@tailwindcss/typography"),
-- 
GitLab