From b85d550d944ee161bba87c3e895d604c9929e41a Mon Sep 17 00:00:00 2001
From: Janne Koschinski <janne@kuschku.de>
Date: Sun, 3 Jan 2021 18:39:16 +0100
Subject: [PATCH] Improve imsc typing

---
 .../ttml/ismc.ts => @types/imsc/index.d.ts    |   63 +-
 package-lock.json                             | 1495 +++++++++--------
 package.json                                  |   20 +-
 src/global.d.ts                               |   57 -
 src/routes/player/Player.tsx                  |    4 +-
 .../player/subtitles/SubtitleRenderer.tsx     |    2 +-
 src/routes/player/subtitles/TtmlHelper.ts     |    2 +-
 src/util/ttml/doc.js                          | 1097 ------------
 src/util/ttml/html.js                         | 1006 -----------
 src/util/ttml/isd.js                          |  449 -----
 src/util/ttml/names.js                        |   33 -
 src/util/ttml/styles.js                       |  941 -----------
 src/util/ttml/utils.js                        |  284 ----
 tsconfig.json                                 |   11 +
 14 files changed, 868 insertions(+), 4596 deletions(-)
 rename src/util/ttml/ismc.ts => @types/imsc/index.d.ts (79%)
 delete mode 100644 src/global.d.ts
 delete mode 100644 src/util/ttml/doc.js
 delete mode 100644 src/util/ttml/html.js
 delete mode 100644 src/util/ttml/isd.js
 delete mode 100644 src/util/ttml/names.js
 delete mode 100644 src/util/ttml/styles.js
 delete mode 100644 src/util/ttml/utils.js

diff --git a/src/util/ttml/ismc.ts b/@types/imsc/index.d.ts
similarity index 79%
rename from src/util/ttml/ismc.ts
rename to @types/imsc/index.d.ts
index 8a33d89..344d200 100644
--- a/src/util/ttml/ismc.ts
+++ b/@types/imsc/index.d.ts
@@ -1,4 +1,4 @@
-/* 
+/*
  * Copyright (c) 2016, Pierre-Anthony Lemieux <pal@sandflow.com>
  * All rights reserved.
  *
@@ -24,14 +24,10 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
-import * as isd from './isd';
-import * as doc from './doc';
-import * as html from './html';
-
 export interface TtmlDocument {
-    getMediaTimeEvents(): number[],
+    getMediaTimeEvents(): number[];
 
-    getMediaTimeRange(): number[]
+    getMediaTimeRange(): number[];
 }
 
 export type ISD = unknown;
@@ -43,28 +39,28 @@ export type ISDState = unknown;
 export interface MetadataHandler {
     /**
      * Called when the opening tag of an element node is encountered.
-     * @param {string} ns Namespace URI of the element
-     * @param {string} name Local name of the element
-     * @param {Attribute[]} attributes List of attributes, each consisting of a `uri`, `name` and `value`
+     * @param ns Namespace URI of the element
+     * @param name Local name of the element
+     * @param attributes List of attributes, each consisting of a `uri`, `name` and `value`
      */
-    onOpenTag(ns: string, name: string, attributes: Attribute[]): void,
+    onOpenTag(ns: string, name: string, attributes: Attribute[]): void;
 
     /**
      * Called when the closing tag of an element node is encountered.
      */
-    onCloseTag(): void,
+    onCloseTag(): void;
 
     /**
      * Called when a text node is encountered.
-     * @param {string} contents Contents of the text node
+     * @param contents Contents of the text node
      */
-    onText(contents: string): void,
+    onText(contents: string): void;
 }
 
 export interface Attribute {
-    uri: string,
-    name: string,
-    value: string
+    uri: string;
+    name: string;
+    value: string;
 }
 
 /**
@@ -79,13 +75,13 @@ export interface Attribute {
  * and returns a single <pre>boolean</pre>, which terminates processing if <pre>true</pre>.
  */
 export interface ErrorHandler {
-    info(error: string): boolean
+    info(error: string): boolean;
 
-    warn(error: string): boolean
+    warn(error: string): boolean;
 
-    error(error: string): boolean
+    error(error: string): boolean;
 
-    fatal(error: string): boolean
+    fatal(error: string): boolean;
 }
 
 /**
@@ -95,22 +91,22 @@ export interface ErrorHandler {
  * representation of the document change. `metadataHandler` allows the caller to
  * be called back when nodes are present in <metadata> elements.
  */
-type fromXML = (
+export function fromXML(
     xmlstring: string,
     errorHandler?: ErrorHandler,
-    metadataHandler?: MetadataHandler
-) => TtmlDocument | null;
+    metadataHandler?: MetadataHandler,
+): TtmlDocument | null;
 
 /**
  * Creates a canonical representation of an IMSC1 document returned by <pre>imscDoc.fromXML()</pre>
  * at a given absolute offset in seconds. This offset does not have to be one of the values returned
  * by <pre>getMediaTimeEvents()</pre>.
  */
-type generateISD = (
+export function generateISD(
     tt: TtmlDocument,
     offset?: number,
-    errorHandler?: ErrorHandler,
-) => ISD;
+    errorHandler?: ErrorHandler
+): ISD;
 
 /**
  * Renders an ISD object (returned by <pre>generateISD()</pre>) into a
@@ -128,7 +124,7 @@ type generateISD = (
  * is called for the next ISD, otherwise <code>previousISDState</code> should be set to
  * <code>null</code>.
  */
-type renderHTML = (
+export function renderHTML(
     isd: ISD,
     element: HTMLElement,
     /**
@@ -141,12 +137,5 @@ type renderHTML = (
     displayForcedOnlyMode?: boolean,
     errorHandler?: ErrorHandler,
     previousISDState?: ISDState,
-    enableRollUp?: boolean
-) => ISDState;
-
-// eslint-disable-next-line @typescript-eslint/no-redeclare
-export const generateISD: generateISD = isd.generateISD;
-// eslint-disable-next-line @typescript-eslint/no-redeclare
-export const fromXML: fromXML = doc.fromXML;
-// eslint-disable-next-line @typescript-eslint/no-redeclare
-export const renderHTML: renderHTML = html.render;
+    enableRollUp?: boolean,
+): ISDState;
diff --git a/package-lock.json b/package-lock.json
index 76bf997..cb3a523 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -5,9 +5,9 @@
   "requires": true,
   "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==",
+      "version": "7.12.11",
+      "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz",
+      "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==",
       "requires": {
         "@babel/highlight": "^7.10.4"
       }
@@ -53,11 +53,11 @@
       }
     },
     "@babel/generator": {
-      "version": "7.12.5",
-      "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.12.5.tgz",
-      "integrity": "sha512-m16TQQJ8hPt7E+OS/XVQg/7U184MLXtvuGbCdA7na61vha+ImkyyNM/9DDA0unYCVZn3ZOhng+qz48/KBOT96A==",
+      "version": "7.12.11",
+      "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.12.11.tgz",
+      "integrity": "sha512-Ggg6WPOJtSi8yYQvLVjG8F/TlpWDlKx0OpS4Kt+xMQPs5OaGYWy+v1A+1TvxI6sAMGZpKWWoAQ1DaeQbImlItA==",
       "requires": {
-        "@babel/types": "^7.12.5",
+        "@babel/types": "^7.12.11",
         "jsesc": "^2.5.1",
         "source-map": "^0.5.0"
       },
@@ -70,11 +70,11 @@
       }
     },
     "@babel/helper-annotate-as-pure": {
-      "version": "7.10.4",
-      "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.10.4.tgz",
-      "integrity": "sha512-XQlqKQP4vXFB7BN8fEEerrmYvHp3fK/rBkRFz9jaJbzK0B1DSfej9Kc7ZzE8Z/OnId1jpJdNAZ3BFQjWG68rcA==",
+      "version": "7.12.10",
+      "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.12.10.tgz",
+      "integrity": "sha512-XplmVbC1n+KY6jL8/fgLVXXUauDIB+lD5+GsQEh6F6GBF1dq1qy4DP4yXWzDKcoqXB3X58t61e85Fitoww4JVQ==",
       "requires": {
-        "@babel/types": "^7.10.4"
+        "@babel/types": "^7.12.10"
       }
     },
     "@babel/helper-builder-binary-assignment-operator-visitor": {
@@ -86,25 +86,6 @@
         "@babel/types": "^7.10.4"
       }
     },
-    "@babel/helper-builder-react-jsx": {
-      "version": "7.10.4",
-      "resolved": "https://registry.npmjs.org/@babel/helper-builder-react-jsx/-/helper-builder-react-jsx-7.10.4.tgz",
-      "integrity": "sha512-5nPcIZ7+KKDxT1427oBivl9V9YTal7qk0diccnh7RrcgrT/pGFOjgGw1dgryyx1GvHEpXVfoDF6Ak3rTiWh8Rg==",
-      "requires": {
-        "@babel/helper-annotate-as-pure": "^7.10.4",
-        "@babel/types": "^7.10.4"
-      }
-    },
-    "@babel/helper-builder-react-jsx-experimental": {
-      "version": "7.12.4",
-      "resolved": "https://registry.npmjs.org/@babel/helper-builder-react-jsx-experimental/-/helper-builder-react-jsx-experimental-7.12.4.tgz",
-      "integrity": "sha512-AjEa0jrQqNk7eDQOo0pTfUOwQBMF+xVqrausQwT9/rTKy0g04ggFNaJpaE09IQMn9yExluigWMJcj0WC7bq+Og==",
-      "requires": {
-        "@babel/helper-annotate-as-pure": "^7.10.4",
-        "@babel/helper-module-imports": "^7.12.1",
-        "@babel/types": "^7.12.1"
-      }
-    },
     "@babel/helper-compilation-targets": {
       "version": "7.12.5",
       "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.12.5.tgz",
@@ -163,21 +144,21 @@
       }
     },
     "@babel/helper-function-name": {
-      "version": "7.10.4",
-      "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz",
-      "integrity": "sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ==",
+      "version": "7.12.11",
+      "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.12.11.tgz",
+      "integrity": "sha512-AtQKjtYNolKNi6nNNVLQ27CP6D9oFR6bq/HPYSizlzbp7uC1M59XJe8L+0uXjbIaZaUJF99ruHqVGiKXU/7ybA==",
       "requires": {
-        "@babel/helper-get-function-arity": "^7.10.4",
-        "@babel/template": "^7.10.4",
-        "@babel/types": "^7.10.4"
+        "@babel/helper-get-function-arity": "^7.12.10",
+        "@babel/template": "^7.12.7",
+        "@babel/types": "^7.12.11"
       }
     },
     "@babel/helper-get-function-arity": {
-      "version": "7.10.4",
-      "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz",
-      "integrity": "sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A==",
+      "version": "7.12.10",
+      "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.12.10.tgz",
+      "integrity": "sha512-mm0n5BPjR06wh9mPQaDdXWDoll/j5UpCAPl1x8fS71GHm7HA6Ua2V4ylG1Ju8lvcTOietbPNNPaSilKj+pj+Ag==",
       "requires": {
-        "@babel/types": "^7.10.4"
+        "@babel/types": "^7.12.10"
       }
     },
     "@babel/helper-hoist-variables": {
@@ -221,11 +202,11 @@
       }
     },
     "@babel/helper-optimise-call-expression": {
-      "version": "7.12.7",
-      "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.12.7.tgz",
-      "integrity": "sha512-I5xc9oSJ2h59OwyUqjv95HRyzxj53DAubUERgQMrpcCEYQyToeHA+NEcUEsVWB4j53RDeskeBJ0SgRAYHDBckw==",
+      "version": "7.12.10",
+      "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.12.10.tgz",
+      "integrity": "sha512-4tpbU0SrSTjjt65UMWSrUOPZTsgvPgGG4S8QSTNHacKzpS51IVWGDj0yCwyeZND/i+LSN2g/O63jEXEWm49sYQ==",
       "requires": {
-        "@babel/types": "^7.12.7"
+        "@babel/types": "^7.12.10"
       }
     },
     "@babel/helper-plugin-utils": {
@@ -244,14 +225,14 @@
       }
     },
     "@babel/helper-replace-supers": {
-      "version": "7.12.5",
-      "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.12.5.tgz",
-      "integrity": "sha512-5YILoed0ZyIpF4gKcpZitEnXEJ9UoDRki1Ey6xz46rxOzfNMAhVIJMoune1hmPVxh40LRv1+oafz7UsWX+vyWA==",
+      "version": "7.12.11",
+      "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.12.11.tgz",
+      "integrity": "sha512-q+w1cqmhL7R0FNzth/PLLp2N+scXEK/L2AHbXUyydxp828F4FEa5WcVoqui9vFRiHDQErj9Zof8azP32uGVTRA==",
       "requires": {
-        "@babel/helper-member-expression-to-functions": "^7.12.1",
-        "@babel/helper-optimise-call-expression": "^7.10.4",
-        "@babel/traverse": "^7.12.5",
-        "@babel/types": "^7.12.5"
+        "@babel/helper-member-expression-to-functions": "^7.12.7",
+        "@babel/helper-optimise-call-expression": "^7.12.10",
+        "@babel/traverse": "^7.12.10",
+        "@babel/types": "^7.12.11"
       }
     },
     "@babel/helper-simple-access": {
@@ -271,22 +252,22 @@
       }
     },
     "@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==",
+      "version": "7.12.11",
+      "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.12.11.tgz",
+      "integrity": "sha512-LsIVN8j48gHgwzfocYUSkO/hjYAOJqlpJEc7tGXcIm4cubjVUf8LGW6eWRyxEu7gA25q02p0rQUWoCI33HNS5g==",
       "requires": {
-        "@babel/types": "^7.11.0"
+        "@babel/types": "^7.12.11"
       }
     },
     "@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=="
+      "version": "7.12.11",
+      "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz",
+      "integrity": "sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw=="
     },
     "@babel/helper-validator-option": {
-      "version": "7.12.1",
-      "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.12.1.tgz",
-      "integrity": "sha512-YpJabsXlJVWP0USHjnC/AQDTLlZERbON577YUVO/wLpqyj6HAtVYnWaQaN0iUN+1/tWn3c+uKKXjRut5115Y2A=="
+      "version": "7.12.11",
+      "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.12.11.tgz",
+      "integrity": "sha512-TBFCyj939mFSdeX7U7DDj32WtzYY7fDcalgq8v3fBZMNOJQNn7nOYzMaUCiPxPYfCup69mtIpqlKgMZLvQ8Xhw=="
     },
     "@babel/helper-wrap-function": {
       "version": "7.12.3",
@@ -366,14 +347,14 @@
       }
     },
     "@babel/parser": {
-      "version": "7.12.7",
-      "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.12.7.tgz",
-      "integrity": "sha512-oWR02Ubp4xTLCAqPRiNIuMVgNO5Aif/xpXtabhzW2HWUD47XJsAB4Zd/Rg30+XeQA3juXigV7hlquOTmwqLiwg=="
+      "version": "7.12.11",
+      "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.12.11.tgz",
+      "integrity": "sha512-N3UxG+uuF4CMYoNj8AhnbAcJF0PiuJ9KHuy1lQmkYsxTer/MAH9UBNHsBoAX/4s6NvlDD047No8mYVGGzLL4hg=="
     },
     "@babel/plugin-proposal-async-generator-functions": {
-      "version": "7.12.1",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.12.1.tgz",
-      "integrity": "sha512-d+/o30tJxFxrA1lhzJqiUcEJdI6jKlNregCv5bASeGf2Q4MXmnwH7viDo7nhx1/ohf09oaH8j1GVYG/e3Yqk6A==",
+      "version": "7.12.12",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.12.12.tgz",
+      "integrity": "sha512-nrz9y0a4xmUrRq51bYkWJIO5SBZyG2ys2qinHsN0zHDHVsUaModrkpyWWWXfGqYQmOL3x9sQIcTNN/pBGpo09A==",
       "requires": {
         "@babel/helper-plugin-utils": "^7.10.4",
         "@babel/helper-remap-async-to-generator": "^7.12.1",
@@ -671,9 +652,9 @@
       }
     },
     "@babel/plugin-transform-block-scoping": {
-      "version": "7.12.1",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.12.1.tgz",
-      "integrity": "sha512-zJyAC9sZdE60r1nVQHblcfCj29Dh2Y0DOvlMkcqSo0ckqjiCwNiUezUKw+RjOCwGfpLRwnAeQ2XlLpsnGkvv9w==",
+      "version": "7.12.12",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.12.12.tgz",
+      "integrity": "sha512-VOEPQ/ExOVqbukuP7BYJtI5ZxxsmegTwzZ04j1aF0dkSypGo9XpDHuOrABsJu+ie+penpSJheDJ11x1BEZNiyQ==",
       "requires": {
         "@babel/helper-plugin-utils": "^7.10.4"
       }
@@ -877,24 +858,23 @@
       }
     },
     "@babel/plugin-transform-react-jsx": {
-      "version": "7.12.7",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.12.7.tgz",
-      "integrity": "sha512-YFlTi6MEsclFAPIDNZYiCRbneg1MFGao9pPG9uD5htwE0vDbPaMUMeYd6itWjw7K4kro4UbdQf3ljmFl9y48dQ==",
+      "version": "7.12.12",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.12.12.tgz",
+      "integrity": "sha512-JDWGuzGNWscYcq8oJVCtSE61a5+XAOos+V0HrxnDieUus4UMnBEosDnY1VJqU5iZ4pA04QY7l0+JvHL1hZEfsw==",
       "requires": {
-        "@babel/helper-builder-react-jsx": "^7.10.4",
-        "@babel/helper-builder-react-jsx-experimental": "^7.12.4",
+        "@babel/helper-annotate-as-pure": "^7.12.10",
+        "@babel/helper-module-imports": "^7.12.5",
         "@babel/helper-plugin-utils": "^7.10.4",
-        "@babel/plugin-syntax-jsx": "^7.12.1"
+        "@babel/plugin-syntax-jsx": "^7.12.1",
+        "@babel/types": "^7.12.12"
       }
     },
     "@babel/plugin-transform-react-jsx-development": {
-      "version": "7.12.7",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.12.7.tgz",
-      "integrity": "sha512-Rs3ETtMtR3VLXFeYRChle5SsP/P9Jp/6dsewBQfokDSzKJThlsuFcnzLTDRALiUmTC48ej19YD9uN1mupEeEDg==",
+      "version": "7.12.12",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.12.12.tgz",
+      "integrity": "sha512-i1AxnKxHeMxUaWVXQOSIco4tvVvvCxMSfeBMnMM06mpaJt3g+MpxYQQrDfojUQldP1xxraPSJYSMEljoWM/dCg==",
       "requires": {
-        "@babel/helper-builder-react-jsx-experimental": "^7.12.4",
-        "@babel/helper-plugin-utils": "^7.10.4",
-        "@babel/plugin-syntax-jsx": "^7.12.1"
+        "@babel/plugin-transform-react-jsx": "^7.12.12"
       }
     },
     "@babel/plugin-transform-react-jsx-self": {
@@ -990,9 +970,9 @@
       }
     },
     "@babel/plugin-transform-typeof-symbol": {
-      "version": "7.12.1",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.12.1.tgz",
-      "integrity": "sha512-EPGgpGy+O5Kg5pJFNDKuxt9RdmTgj5sgrus2XVeMp/ZIbOESadgILUbm50SNpghOh3/6yrbsH+NB5+WJTmsA7Q==",
+      "version": "7.12.10",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.12.10.tgz",
+      "integrity": "sha512-JQ6H8Rnsogh//ijxspCjc21YPd3VLVoYtAwv3zQmqAt8YGYUtdo5usNhdl4b9/Vir2kPFZl6n1h0PfUz4hJhaA==",
       "requires": {
         "@babel/helper-plugin-utils": "^7.10.4"
       }
@@ -1025,15 +1005,15 @@
       }
     },
     "@babel/preset-env": {
-      "version": "7.12.7",
-      "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.12.7.tgz",
-      "integrity": "sha512-OnNdfAr1FUQg7ksb7bmbKoby4qFOHw6DKWWUNB9KqnnCldxhxJlP+21dpyaWFmf2h0rTbOkXJtAGevY3XW1eew==",
+      "version": "7.12.11",
+      "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.12.11.tgz",
+      "integrity": "sha512-j8Tb+KKIXKYlDBQyIOy4BLxzv1NUOwlHfZ74rvW+Z0Gp4/cI2IMDPBWAgWceGcE7aep9oL/0K9mlzlMGxA8yNw==",
       "requires": {
         "@babel/compat-data": "^7.12.7",
         "@babel/helper-compilation-targets": "^7.12.5",
         "@babel/helper-module-imports": "^7.12.5",
         "@babel/helper-plugin-utils": "^7.10.4",
-        "@babel/helper-validator-option": "^7.12.1",
+        "@babel/helper-validator-option": "^7.12.11",
         "@babel/plugin-proposal-async-generator-functions": "^7.12.1",
         "@babel/plugin-proposal-class-properties": "^7.12.1",
         "@babel/plugin-proposal-dynamic-import": "^7.12.1",
@@ -1062,7 +1042,7 @@
         "@babel/plugin-transform-arrow-functions": "^7.12.1",
         "@babel/plugin-transform-async-to-generator": "^7.12.1",
         "@babel/plugin-transform-block-scoped-functions": "^7.12.1",
-        "@babel/plugin-transform-block-scoping": "^7.12.1",
+        "@babel/plugin-transform-block-scoping": "^7.12.11",
         "@babel/plugin-transform-classes": "^7.12.1",
         "@babel/plugin-transform-computed-properties": "^7.12.1",
         "@babel/plugin-transform-destructuring": "^7.12.1",
@@ -1088,12 +1068,12 @@
         "@babel/plugin-transform-spread": "^7.12.1",
         "@babel/plugin-transform-sticky-regex": "^7.12.7",
         "@babel/plugin-transform-template-literals": "^7.12.1",
-        "@babel/plugin-transform-typeof-symbol": "^7.12.1",
+        "@babel/plugin-transform-typeof-symbol": "^7.12.10",
         "@babel/plugin-transform-unicode-escapes": "^7.12.1",
         "@babel/plugin-transform-unicode-regex": "^7.12.1",
         "@babel/preset-modules": "^0.1.3",
-        "@babel/types": "^7.12.7",
-        "core-js-compat": "^3.7.0",
+        "@babel/types": "^7.12.11",
+        "core-js-compat": "^3.8.0",
         "semver": "^5.5.0"
       },
       "dependencies": {
@@ -1117,16 +1097,14 @@
       }
     },
     "@babel/preset-react": {
-      "version": "7.12.7",
-      "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.12.7.tgz",
-      "integrity": "sha512-wKeTdnGUP5AEYCYQIMeXMMwU7j+2opxrG0WzuZfxuuW9nhKvvALBjl67653CWamZJVefuJGI219G591RSldrqQ==",
+      "version": "7.12.10",
+      "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.12.10.tgz",
+      "integrity": "sha512-vtQNjaHRl4DUpp+t+g4wvTHsLQuye+n0H/wsXIZRn69oz/fvNC7gQ4IK73zGJBaxvHoxElDvnYCthMcT7uzFoQ==",
       "requires": {
         "@babel/helper-plugin-utils": "^7.10.4",
         "@babel/plugin-transform-react-display-name": "^7.12.1",
-        "@babel/plugin-transform-react-jsx": "^7.12.7",
+        "@babel/plugin-transform-react-jsx": "^7.12.10",
         "@babel/plugin-transform-react-jsx-development": "^7.12.7",
-        "@babel/plugin-transform-react-jsx-self": "^7.12.1",
-        "@babel/plugin-transform-react-jsx-source": "^7.12.1",
         "@babel/plugin-transform-react-pure-annotations": "^7.12.1"
       }
     },
@@ -1140,9 +1118,9 @@
       }
     },
     "@babel/runtime": {
-      "version": "7.11.2",
-      "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.11.2.tgz",
-      "integrity": "sha512-TeWkU52so0mPtDcaCTxNBI/IHiz0pZgr8VEFqXFtZWpYD08ZB6FaSwVAS8MKRQAP3bYKiVjwysOJgMFY28o6Tw==",
+      "version": "7.12.5",
+      "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.12.5.tgz",
+      "integrity": "sha512-plcc+hbExy3McchJCEQG3knOsuh3HH+Prx1P6cLIkET/0dLuQDEnrT+s27Axgc9bqfsmNUNHfscgMUdBpC9xfg==",
       "requires": {
         "regenerator-runtime": "^0.13.4"
       }
@@ -1167,27 +1145,27 @@
       }
     },
     "@babel/traverse": {
-      "version": "7.12.9",
-      "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.12.9.tgz",
-      "integrity": "sha512-iX9ajqnLdoU1s1nHt36JDI9KG4k+vmI8WgjK5d+aDTwQbL2fUnzedNedssA645Ede3PM2ma1n8Q4h2ohwXgMXw==",
-      "requires": {
-        "@babel/code-frame": "^7.10.4",
-        "@babel/generator": "^7.12.5",
-        "@babel/helper-function-name": "^7.10.4",
-        "@babel/helper-split-export-declaration": "^7.11.0",
-        "@babel/parser": "^7.12.7",
-        "@babel/types": "^7.12.7",
+      "version": "7.12.12",
+      "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.12.12.tgz",
+      "integrity": "sha512-s88i0X0lPy45RrLM8b9mz8RPH5FqO9G9p7ti59cToE44xFm1Q+Pjh5Gq4SXBbtb88X7Uy7pexeqRIQDDMNkL0w==",
+      "requires": {
+        "@babel/code-frame": "^7.12.11",
+        "@babel/generator": "^7.12.11",
+        "@babel/helper-function-name": "^7.12.11",
+        "@babel/helper-split-export-declaration": "^7.12.11",
+        "@babel/parser": "^7.12.11",
+        "@babel/types": "^7.12.12",
         "debug": "^4.1.0",
         "globals": "^11.1.0",
         "lodash": "^4.17.19"
       }
     },
     "@babel/types": {
-      "version": "7.12.7",
-      "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.12.7.tgz",
-      "integrity": "sha512-MNyI92qZq6jrQkXvtIiykvl4WtoRrVV9MPn+ZfsoEENjiWcBQ3ZSHrkxnJWgWtLX3XXqX5hrSQ+X69wkmesXuQ==",
+      "version": "7.12.12",
+      "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.12.12.tgz",
+      "integrity": "sha512-lnIX7piTxOH22xE7fDXDbSHg9MM1/6ORnafpJmov5rs0kX5g4BZxeXNJLXsMRiO0U5Rb8/FvMS6xlTnTHvxonQ==",
       "requires": {
-        "@babel/helper-validator-identifier": "^7.10.4",
+        "@babel/helper-validator-identifier": "^7.12.11",
         "lodash": "^4.17.19",
         "to-fast-properties": "^2.0.0"
       }
@@ -1230,9 +1208,9 @@
       "integrity": "sha512-Qv4LTqO11jepd5Qmlp3M1YEjBumoTHcHFdgPTQ+sFlIL5myi/7xu/POwP7IRu6odBdmLXdtIs1D6TuW6kbwbbg=="
     },
     "@eslint/eslintrc": {
-      "version": "0.2.1",
-      "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.2.1.tgz",
-      "integrity": "sha512-XRUeBZ5zBWLYgSANMpThFddrZZkEbGHgUdt5UJjZfnlN9BGCiUBrf+nvbRupSjMvqzwnQN0qwCmOxITt1cfywA==",
+      "version": "0.2.2",
+      "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.2.2.tgz",
+      "integrity": "sha512-EfB5OHNYp1F4px/LI/FEnGylop7nOqkQ1LRzCM0KccA2U8tvV8w01KBv37LbO7nW4H+YhKyo2LcJhRwjjV17QQ==",
       "requires": {
         "ajv": "^6.12.4",
         "debug": "^4.1.1",
@@ -1434,14 +1412,6 @@
             "read-pkg": "^5.2.0",
             "type-fest": "^0.8.1"
           }
-        },
-        "rimraf": {
-          "version": "3.0.2",
-          "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
-          "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
-          "requires": {
-            "glob": "^7.1.3"
-          }
         }
       }
     },
@@ -1655,25 +1625,25 @@
       }
     },
     "@nodelib/fs.scandir": {
-      "version": "2.1.3",
-      "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.3.tgz",
-      "integrity": "sha512-eGmwYQn3gxo4r7jdQnkrrN6bY478C3P+a/y72IJukF8LjB6ZHeB3c+Ehacj3sYeSmUXGlnA67/PmbM9CVwL7Dw==",
+      "version": "2.1.4",
+      "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.4.tgz",
+      "integrity": "sha512-33g3pMJk3bg5nXbL/+CY6I2eJDzZAni49PfJnL5fghPTggPvBd/pFNSgJsdAgWptuFu7qq/ERvOYFlhvsLTCKA==",
       "requires": {
-        "@nodelib/fs.stat": "2.0.3",
+        "@nodelib/fs.stat": "2.0.4",
         "run-parallel": "^1.1.9"
       }
     },
     "@nodelib/fs.stat": {
-      "version": "2.0.3",
-      "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.3.tgz",
-      "integrity": "sha512-bQBFruR2TAwoevBEd/NWMoAAtNGzTRgdrqnYCc7dhzfoNvqPzLyqlEQnzZ3kVnNrSp25iyxE00/3h2fqGAGArA=="
+      "version": "2.0.4",
+      "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.4.tgz",
+      "integrity": "sha512-IYlHJA0clt2+Vg7bccq+TzRdJvv19c2INqBSsoOLp1je7xjtr7J26+WXR72MCdvU9q1qTzIWDfhMf+DRvQJK4Q=="
     },
     "@nodelib/fs.walk": {
-      "version": "1.2.4",
-      "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.4.tgz",
-      "integrity": "sha512-1V9XOY4rDW0rehzbrcqAmHnz8e7SKvX27gh8Gt2WgB0+pdzdiLV83p72kZPU+jvMbS1qU5mauP2iOvO8rhmurQ==",
+      "version": "1.2.6",
+      "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.6.tgz",
+      "integrity": "sha512-8Broas6vTtW4GIXTAHDoE32hnN2M5ykgCpWGbuXHQ15vEMqr23pB76e/GZcYsZCHALv50ktd24qhEyKr6wBtow==",
       "requires": {
-        "@nodelib/fs.scandir": "2.1.3",
+        "@nodelib/fs.scandir": "2.1.4",
         "fastq": "^1.6.0"
       }
     },
@@ -1885,9 +1855,9 @@
       }
     },
     "@testing-library/dom": {
-      "version": "7.28.1",
-      "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-7.28.1.tgz",
-      "integrity": "sha512-acv3l6kDwZkQif/YqJjstT3ks5aaI33uxGNVIQmdKzbZ2eMKgg3EV2tB84GDdc72k3Kjhl6mO8yUt6StVIdRDg==",
+      "version": "7.29.0",
+      "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-7.29.0.tgz",
+      "integrity": "sha512-0hhuJSmw/zLc6ewR9cVm84TehuTd7tbqBX9pRNSp8znJ9gTmSgesdbiGZtt8R6dL+2rgaPFp9Yjr7IU1HWm49w==",
       "requires": {
         "@babel/code-frame": "^7.10.4",
         "@babel/runtime": "^7.12.5",
@@ -1899,14 +1869,6 @@
         "pretty-format": "^26.6.2"
       },
       "dependencies": {
-        "@babel/runtime": {
-          "version": "7.12.5",
-          "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.12.5.tgz",
-          "integrity": "sha512-plcc+hbExy3McchJCEQG3knOsuh3HH+Prx1P6cLIkET/0dLuQDEnrT+s27Axgc9bqfsmNUNHfscgMUdBpC9xfg==",
-          "requires": {
-            "regenerator-runtime": "^0.13.4"
-          }
-        },
         "chalk": {
           "version": "4.1.0",
           "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz",
@@ -1919,9 +1881,9 @@
       }
     },
     "@testing-library/jest-dom": {
-      "version": "5.11.6",
-      "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-5.11.6.tgz",
-      "integrity": "sha512-cVZyUNRWwUKI0++yepYpYX7uhrP398I+tGz4zOlLVlUYnZS+Svuxv4fwLeCIy7TnBYKXUaOlQr3vopxL8ZfEnA==",
+      "version": "5.11.8",
+      "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-5.11.8.tgz",
+      "integrity": "sha512-ScyKrWQM5xNcr79PkSewnA79CLaoxVskE+f7knTOhDD9ftZSA1Jw8mj+pneqhEu3x37ncNfW84NUr7lqK+mXjA==",
       "requires": {
         "@babel/runtime": "^7.9.2",
         "@types/testing-library__jest-dom": "^5.9.1",
@@ -1940,24 +1902,14 @@
       "requires": {
         "@babel/runtime": "^7.12.5",
         "@testing-library/dom": "^7.28.1"
-      },
-      "dependencies": {
-        "@babel/runtime": {
-          "version": "7.12.5",
-          "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.12.5.tgz",
-          "integrity": "sha512-plcc+hbExy3McchJCEQG3knOsuh3HH+Prx1P6cLIkET/0dLuQDEnrT+s27Axgc9bqfsmNUNHfscgMUdBpC9xfg==",
-          "requires": {
-            "regenerator-runtime": "^0.13.4"
-          }
-        }
       }
     },
     "@testing-library/user-event": {
-      "version": "12.2.2",
-      "resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-12.2.2.tgz",
-      "integrity": "sha512-mTYL9LrwiSeyorStUOMuRGQDn1ca40tIhuv//o/K3lY8wBEp+9Im90MFVx5i3u7zCPmavn3uWZs/10chsbI8Tg==",
+      "version": "12.6.0",
+      "resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-12.6.0.tgz",
+      "integrity": "sha512-FNEH/HLmOk5GO70I52tKjs7WvGYckeE/SrnLX/ip7z2IGbffyd5zOUM1tZ10vsTphqm+VbDFI0oaXu0wcfQsAQ==",
       "requires": {
-        "@babel/runtime": "^7.10.2"
+        "@babel/runtime": "^7.12.5"
       }
     },
     "@types/anymatch": {
@@ -2000,17 +1952,17 @@
       }
     },
     "@types/babel__traverse": {
-      "version": "7.0.16",
-      "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.0.16.tgz",
-      "integrity": "sha512-S63Dt4CZOkuTmpLGGWtT/mQdVORJOpx6SZWGVaP56dda/0Nx5nEe82K7/LAm8zYr6SfMq+1N2OreIOrHAx656w==",
+      "version": "7.11.0",
+      "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.11.0.tgz",
+      "integrity": "sha512-kSjgDMZONiIfSH1Nxcr5JIRMwUetDki63FSQfpTCz8ogF3Ulqm8+mr5f78dUYs6vMiB6gBusQqfQmBvHZj/lwg==",
       "requires": {
         "@babel/types": "^7.3.0"
       }
     },
     "@types/eslint": {
-      "version": "7.2.5",
-      "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-7.2.5.tgz",
-      "integrity": "sha512-Dc6ar9x16BdaR3NSxSF7T4IjL9gxxViJq8RmFd+2UAyA+K6ck2W+gUwfgpG/y9TPyUuBL35109bbULpEynvltA==",
+      "version": "7.2.6",
+      "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-7.2.6.tgz",
+      "integrity": "sha512-I+1sYH+NPQ3/tVqCeUSBwTE/0heyvtXqpIopUUArlBm0Kpocb8FbMa3AZ/ASKIFpN3rnEx932TTXDbt9OXsNDw==",
       "requires": {
         "@types/estree": "*",
         "@types/json-schema": "*"
@@ -2070,9 +2022,9 @@
       }
     },
     "@types/jest": {
-      "version": "26.0.15",
-      "resolved": "https://registry.npmjs.org/@types/jest/-/jest-26.0.15.tgz",
-      "integrity": "sha512-s2VMReFXRg9XXxV+CW9e5Nz8fH2K1aEhwgjUqPPbQd7g95T0laAcvLv032EhFHIa5GHsZ8W7iJEQVaJq6k3Gog==",
+      "version": "26.0.19",
+      "resolved": "https://registry.npmjs.org/@types/jest/-/jest-26.0.19.tgz",
+      "integrity": "sha512-jqHoirTG61fee6v6rwbnEuKhpSKih0tuhqeFbCmMmErhtu3BYlOZaXWjffgOstMM4S/3iQD31lI5bGLTrs97yQ==",
       "requires": {
         "jest-diff": "^26.0.0",
         "pretty-format": "^26.0.0"
@@ -2094,9 +2046,9 @@
       "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA=="
     },
     "@types/node": {
-      "version": "14.14.10",
-      "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.10.tgz",
-      "integrity": "sha512-J32dgx2hw8vXrSbu4ZlVhn1Nm3GbeCFNw2FWL8S5QKucHGY0cyNwjdQdO+KMBZ4wpmC7KhLCiNsdk1RFRIYUQQ=="
+      "version": "14.14.19",
+      "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.19.tgz",
+      "integrity": "sha512-4nhBPStMK04rruRVtVc6cDqhu7S9GZai0fpXgPXrFpcPX6Xul8xnrjSdGB4KPBVYG/R5+fXWdCM8qBoiULWGPQ=="
     },
     "@types/normalize-package-data": {
       "version": "2.4.0",
@@ -2109,9 +2061,9 @@
       "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA=="
     },
     "@types/prettier": {
-      "version": "2.1.5",
-      "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.1.5.tgz",
-      "integrity": "sha512-UEyp8LwZ4Dg30kVU2Q3amHHyTn1jEdhCIE59ANed76GaT1Vp76DD3ZWSAxgCrw6wJ0TqeoBpqmfUHiUDPs//HQ=="
+      "version": "2.1.6",
+      "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.1.6.tgz",
+      "integrity": "sha512-6gOkRe7OIioWAXfnO/2lFiv+SJichKVSys1mSsgyrYHSEjk8Ctv4tSR/Odvnu+HWlH2C8j53dahU03XmQdd5fA=="
     },
     "@types/prop-types": {
       "version": "15.7.3",
@@ -2141,18 +2093,18 @@
       }
     },
     "@types/react-router": {
-      "version": "5.1.8",
-      "resolved": "https://registry.npmjs.org/@types/react-router/-/react-router-5.1.8.tgz",
-      "integrity": "sha512-HzOyJb+wFmyEhyfp4D4NYrumi+LQgQL/68HvJO+q6XtuHSDvw6Aqov7sCAhjbNq3bUPgPqbdvjXC5HeB2oEAPg==",
+      "version": "5.1.9",
+      "resolved": "https://registry.npmjs.org/@types/react-router/-/react-router-5.1.9.tgz",
+      "integrity": "sha512-US6C0rq2Wt/7uje1roqO0R++Sr0jqplKaBChDY5sNg5k7GC/79YFK0ZsLEdemqUjW05wq1Y/9YYEUgfNZ8TlvA==",
       "requires": {
         "@types/history": "*",
         "@types/react": "*"
       }
     },
     "@types/react-router-dom": {
-      "version": "5.1.6",
-      "resolved": "https://registry.npmjs.org/@types/react-router-dom/-/react-router-dom-5.1.6.tgz",
-      "integrity": "sha512-gjrxYqxz37zWEdMVvQtWPFMFj1dRDb4TGOcgyOfSXTrEXdF92L00WE3C471O3TV/RF1oskcStkXsOU0Ete4s/g==",
+      "version": "5.1.7",
+      "resolved": "https://registry.npmjs.org/@types/react-router-dom/-/react-router-dom-5.1.7.tgz",
+      "integrity": "sha512-D5mHD6TbdV/DNHYsnwBTv+y73ei+mMjrkGrla86HthE4/PVvL1J94Bu3qABU+COXzpL23T1EZapVVpwHuBXiUg==",
       "requires": {
         "@types/history": "*",
         "@types/react": "*",
@@ -2212,9 +2164,9 @@
       }
     },
     "@types/webpack-sources": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/@types/webpack-sources/-/webpack-sources-2.0.0.tgz",
-      "integrity": "sha512-a5kPx98CNFRKQ+wqawroFunvFqv7GHm/3KOI52NY9xWADgc8smu4R6prt4EU/M4QfVjvgBkMqU4fBhw3QfMVkg==",
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/@types/webpack-sources/-/webpack-sources-2.1.0.tgz",
+      "integrity": "sha512-LXn/oYIpBeucgP1EIJbKQ2/4ZmpvRl+dlrFdX7+94SKRUV3Evy3FsfMZY318vGhkWUS5MPhtOM3w1/hCOAOXcg==",
       "requires": {
         "@types/node": "*",
         "@types/source-list-map": "*",
@@ -2229,25 +2181,25 @@
       }
     },
     "@types/yargs": {
-      "version": "15.0.10",
-      "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.10.tgz",
-      "integrity": "sha512-z8PNtlhrj7eJNLmrAivM7rjBESG6JwC5xP3RVk12i/8HVP7Xnx/sEmERnRImyEuUaJfO942X0qMOYsoupaJbZQ==",
+      "version": "15.0.12",
+      "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.12.tgz",
+      "integrity": "sha512-f+fD/fQAo3BCbCDlrUpznF1A5Zp9rB0noS5vnoormHSIPFKL0Z2DcUJ3Gxp5ytH4uLRNxy7AwYUC9exZzqGMAw==",
       "requires": {
         "@types/yargs-parser": "*"
       }
     },
     "@types/yargs-parser": {
-      "version": "15.0.0",
-      "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-15.0.0.tgz",
-      "integrity": "sha512-FA/BWv8t8ZWJ+gEOnLLd8ygxH/2UFbAvgEonyfN6yWGLKc7zVjbpl2Y4CTjid9h2RfgPP6SEt6uHwEOply00yw=="
+      "version": "20.2.0",
+      "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-20.2.0.tgz",
+      "integrity": "sha512-37RSHht+gzzgYeobbG+KWryeAW8J33Nhr69cjTqSYymXVZEN9NbRYWoYlRtDhHKPVT1FyNKwaTPC1NynKZpzRA=="
     },
     "@typescript-eslint/eslint-plugin": {
-      "version": "4.8.2",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.8.2.tgz",
-      "integrity": "sha512-gQ06QLV5l1DtvYtqOyFLXD9PdcILYqlrJj2l+CGDlPtmgLUzc1GpqciJFIRvyfvgLALpnxYINFuw+n9AZhPBKQ==",
+      "version": "4.11.1",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.11.1.tgz",
+      "integrity": "sha512-fABclAX2QIEDmTMk6Yd7Muv1CzFLwWM4505nETzRHpP3br6jfahD9UUJkhnJ/g2m7lwfz8IlswcwGGPGiq9exw==",
       "requires": {
-        "@typescript-eslint/experimental-utils": "4.8.2",
-        "@typescript-eslint/scope-manager": "4.8.2",
+        "@typescript-eslint/experimental-utils": "4.11.1",
+        "@typescript-eslint/scope-manager": "4.11.1",
         "debug": "^4.1.1",
         "functional-red-black-tree": "^1.0.1",
         "regexpp": "^3.0.0",
@@ -2256,50 +2208,50 @@
       }
     },
     "@typescript-eslint/experimental-utils": {
-      "version": "4.8.2",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.8.2.tgz",
-      "integrity": "sha512-hpTw6o6IhBZEsQsjuw/4RWmceRyESfAiEzAEnXHKG1X7S5DXFaZ4IO1JO7CW1aQ604leQBzjZmuMI9QBCAJX8Q==",
+      "version": "4.11.1",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.11.1.tgz",
+      "integrity": "sha512-mAlWowT4A6h0TC9F+J5pdbEhjNiEMO+kqPKQ4sc3fVieKL71dEqfkKgtcFVSX3cjSBwYwhImaQ/mXQF0oaI38g==",
       "requires": {
         "@types/json-schema": "^7.0.3",
-        "@typescript-eslint/scope-manager": "4.8.2",
-        "@typescript-eslint/types": "4.8.2",
-        "@typescript-eslint/typescript-estree": "4.8.2",
+        "@typescript-eslint/scope-manager": "4.11.1",
+        "@typescript-eslint/types": "4.11.1",
+        "@typescript-eslint/typescript-estree": "4.11.1",
         "eslint-scope": "^5.0.0",
         "eslint-utils": "^2.0.0"
       }
     },
     "@typescript-eslint/parser": {
-      "version": "4.8.2",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.8.2.tgz",
-      "integrity": "sha512-u0leyJqmclYr3KcXOqd2fmx6SDGBO0MUNHHAjr0JS4Crbb3C3d8dwAdlazy133PLCcPn+aOUFiHn72wcuc5wYw==",
+      "version": "4.11.1",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.11.1.tgz",
+      "integrity": "sha512-BJ3jwPQu1jeynJ5BrjLuGfK/UJu6uwHxJ/di7sanqmUmxzmyIcd3vz58PMR7wpi8k3iWq2Q11KMYgZbUpRoIPw==",
       "requires": {
-        "@typescript-eslint/scope-manager": "4.8.2",
-        "@typescript-eslint/types": "4.8.2",
-        "@typescript-eslint/typescript-estree": "4.8.2",
+        "@typescript-eslint/scope-manager": "4.11.1",
+        "@typescript-eslint/types": "4.11.1",
+        "@typescript-eslint/typescript-estree": "4.11.1",
         "debug": "^4.1.1"
       }
     },
     "@typescript-eslint/scope-manager": {
-      "version": "4.8.2",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.8.2.tgz",
-      "integrity": "sha512-qHQ8ODi7mMin4Sq2eh/6eu03uVzsf5TX+J43xRmiq8ujng7ViQSHNPLOHGw/Wr5dFEoxq/ubKhzClIIdQy5q3g==",
+      "version": "4.11.1",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.11.1.tgz",
+      "integrity": "sha512-Al2P394dx+kXCl61fhrrZ1FTI7qsRDIUiVSuN6rTwss6lUn8uVO2+nnF4AvO0ug8vMsy3ShkbxLu/uWZdTtJMQ==",
       "requires": {
-        "@typescript-eslint/types": "4.8.2",
-        "@typescript-eslint/visitor-keys": "4.8.2"
+        "@typescript-eslint/types": "4.11.1",
+        "@typescript-eslint/visitor-keys": "4.11.1"
       }
     },
     "@typescript-eslint/types": {
-      "version": "4.8.2",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.8.2.tgz",
-      "integrity": "sha512-z1/AVcVF8ju5ObaHe2fOpZYEQrwHyZ7PTOlmjd3EoFeX9sv7UekQhfrCmgUO7PruLNfSHrJGQvrW3Q7xQ8EoAw=="
+      "version": "4.11.1",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.11.1.tgz",
+      "integrity": "sha512-5kvd38wZpqGY4yP/6W3qhYX6Hz0NwUbijVsX2rxczpY6OXaMxh0+5E5uLJKVFwaBM7PJe1wnMym85NfKYIh6CA=="
     },
     "@typescript-eslint/typescript-estree": {
-      "version": "4.8.2",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.8.2.tgz",
-      "integrity": "sha512-HToGNwI6fekH0dOw3XEVESUm71Onfam0AKin6f26S2FtUmO7o3cLlWgrIaT1q3vjB3wCTdww3Dx2iGq5wtUOCg==",
+      "version": "4.11.1",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.11.1.tgz",
+      "integrity": "sha512-tC7MKZIMRTYxQhrVAFoJq/DlRwv1bnqA4/S2r3+HuHibqvbrPcyf858lNzU7bFmy4mLeIHFYr34ar/1KumwyRw==",
       "requires": {
-        "@typescript-eslint/types": "4.8.2",
-        "@typescript-eslint/visitor-keys": "4.8.2",
+        "@typescript-eslint/types": "4.11.1",
+        "@typescript-eslint/visitor-keys": "4.11.1",
         "debug": "^4.1.1",
         "globby": "^11.0.1",
         "is-glob": "^4.0.1",
@@ -2309,11 +2261,11 @@
       }
     },
     "@typescript-eslint/visitor-keys": {
-      "version": "4.8.2",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.8.2.tgz",
-      "integrity": "sha512-Vg+/SJTMZJEKKGHW7YC21QxgKJrSbxoYYd3MEUGtW7zuytHuEcksewq0DUmo4eh/CTNrVJGSdIY9AtRb6riWFw==",
+      "version": "4.11.1",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.11.1.tgz",
+      "integrity": "sha512-IrlBhD9bm4bdYcS8xpWarazkKXlE7iYb1HzRuyBP114mIaj5DJPo11Us1HgH60dTt41TCZXMaTCAW+OILIYPOg==",
       "requires": {
-        "@typescript-eslint/types": "4.8.2",
+        "@typescript-eslint/types": "4.11.1",
         "eslint-visitor-keys": "^2.0.0"
       }
     },
@@ -2546,14 +2498,21 @@
       }
     },
     "ajv": {
-      "version": "6.12.5",
-      "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.5.tgz",
-      "integrity": "sha512-lRF8RORchjpKG50/WFf8xmg7sgCLFiYNNnqdKflk63whMQcWR5ngGjiSXkL9bjxy6B2npOK2HSMN49jEBMSkag==",
+      "version": "6.12.6",
+      "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+      "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
       "requires": {
         "fast-deep-equal": "^3.1.1",
         "fast-json-stable-stringify": "^2.0.0",
         "json-schema-traverse": "^0.4.1",
         "uri-js": "^4.2.2"
+      },
+      "dependencies": {
+        "fast-deep-equal": {
+          "version": "3.1.3",
+          "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+          "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
+        }
       }
     },
     "ajv-errors": {
@@ -2789,9 +2748,9 @@
       "integrity": "sha1-9wtzXGvKGlycItmCw+Oef+ujva0="
     },
     "astral-regex": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz",
-      "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg=="
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz",
+      "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ=="
     },
     "async": {
       "version": "2.6.3",
@@ -2846,9 +2805,9 @@
       "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg="
     },
     "aws4": {
-      "version": "1.10.1",
-      "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.10.1.tgz",
-      "integrity": "sha512-zg7Hz2k5lI8kb7U32998pRRFin7zJlkfezGJjUc2heaD4Pw2wObakCDVzkKztTm/Ln7eiVvYsjqak0Ed4LkMDA=="
+      "version": "1.11.0",
+      "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz",
+      "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA=="
     },
     "axe-core": {
       "version": "4.1.1",
@@ -3026,9 +2985,9 @@
       "integrity": "sha512-eqj0hVcJUR57/Ug2zE1Yswsw4LhuqqHhD+8v120T1cl3kjg76QwtyBrdIk4WVwK+lAhBJVYCd/v+4nc4y+8JsA=="
     },
     "babel-preset-current-node-syntax": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.0.tgz",
-      "integrity": "sha512-mGkvkpocWJes1CmMKtgGUwCeeq0pOhALyymozzDWYomHTbDLwueDYG6p4TK1YOeYHCzBzYPsWkgTto10JubI1Q==",
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz",
+      "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==",
       "requires": {
         "@babel/plugin-syntax-async-generators": "^7.8.4",
         "@babel/plugin-syntax-bigint": "^7.8.3",
@@ -3471,13 +3430,6 @@
         "parse-asn1": "^5.1.5",
         "readable-stream": "^3.6.0",
         "safe-buffer": "^5.2.0"
-      },
-      "dependencies": {
-        "safe-buffer": {
-          "version": "5.2.1",
-          "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
-          "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="
-        }
       }
     },
     "browserify-zlib": {
@@ -3489,15 +3441,15 @@
       }
     },
     "browserslist": {
-      "version": "4.14.7",
-      "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.14.7.tgz",
-      "integrity": "sha512-BSVRLCeG3Xt/j/1cCGj1019Wbty0H+Yvu2AOuZSuoaUWn3RatbL33Cxk+Q4jRMRAbOm0p7SLravLjpnT6s0vzQ==",
+      "version": "4.16.0",
+      "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.0.tgz",
+      "integrity": "sha512-/j6k8R0p3nxOC6kx5JGAxsnhc9ixaWJfYc+TNTzxg6+ARaESAvQGV7h0uNOB4t+pLQJZWzcrMxXOxjgsCj3dqQ==",
       "requires": {
-        "caniuse-lite": "^1.0.30001157",
+        "caniuse-lite": "^1.0.30001165",
         "colorette": "^1.2.1",
-        "electron-to-chromium": "^1.3.591",
+        "electron-to-chromium": "^1.3.621",
         "escalade": "^3.1.1",
-        "node-releases": "^1.1.66"
+        "node-releases": "^1.1.67"
       }
     },
     "bser": {
@@ -3516,6 +3468,13 @@
         "base64-js": "^1.0.2",
         "ieee754": "^1.1.4",
         "isarray": "^1.0.0"
+      },
+      "dependencies": {
+        "isarray": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+          "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
+        }
       }
     },
     "buffer-from": {
@@ -3534,9 +3493,9 @@
       "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk="
     },
     "builtin-modules": {
-      "version": "3.1.0",
-      "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.1.0.tgz",
-      "integrity": "sha512-k0KL0aWZuBt2lrxrcASWDfwOLMnodeQjodT/1SxEQAXsHANgo6ZC/VEaSEHCXt7aSTZ4/4H5LKa+tBXmW7Vtvw=="
+      "version": "3.2.0",
+      "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.2.0.tgz",
+      "integrity": "sha512-lGzLKcioL90C7wMczpkY0n/oART3MbBa8R9OFGE1rJxoVI86u4WAGfEk8Wjv10eKSyTHVGkSo3bvBylCEtk7LA=="
     },
     "builtin-status-codes": {
       "version": "3.0.0",
@@ -3576,14 +3535,6 @@
           "version": "1.0.4",
           "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
           "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw=="
-        },
-        "rimraf": {
-          "version": "3.0.2",
-          "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
-          "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
-          "requires": {
-            "glob": "^7.1.3"
-          }
         }
       }
     },
@@ -3641,12 +3592,19 @@
       "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ=="
     },
     "camel-case": {
-      "version": "4.1.1",
-      "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.1.tgz",
-      "integrity": "sha512-7fa2WcG4fYFkclIvEmxBbTvmibwF2/agfEBc6q3lOpVu0A13ltLsA+Hr/8Hp6kp5f+G7hKi6t8lys6XxP+1K6Q==",
+      "version": "4.1.2",
+      "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz",
+      "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==",
       "requires": {
-        "pascal-case": "^3.1.1",
-        "tslib": "^1.10.0"
+        "pascal-case": "^3.1.2",
+        "tslib": "^2.0.3"
+      },
+      "dependencies": {
+        "tslib": {
+          "version": "2.0.3",
+          "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz",
+          "integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ=="
+        }
       }
     },
     "camelcase": {
@@ -3666,9 +3624,9 @@
       }
     },
     "caniuse-lite": {
-      "version": "1.0.30001161",
-      "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001161.tgz",
-      "integrity": "sha512-JharrCDxOqPLBULF9/SPa6yMcBRTjZARJ6sc3cuKrPfyIk64JN6kuMINWqA99Xc8uElMFcROliwtz0n9pYej+g=="
+      "version": "1.0.30001171",
+      "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001171.tgz",
+      "integrity": "sha512-5Alrh8TTYPG9IH4UkRqEBZoEToWRLvPbSQokvzSz0lii8/FOWKG4keO1HoYfPWs8IF/NH/dyNPg1cmJGvV3Zlg=="
     },
     "capture-exit": {
       "version": "2.0.0",
@@ -3805,28 +3763,6 @@
         "string-width": "^4.2.0",
         "strip-ansi": "^6.0.0",
         "wrap-ansi": "^6.2.0"
-      },
-      "dependencies": {
-        "emoji-regex": {
-          "version": "8.0.0",
-          "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
-          "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
-        },
-        "is-fullwidth-code-point": {
-          "version": "3.0.0",
-          "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
-          "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="
-        },
-        "string-width": {
-          "version": "4.2.0",
-          "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz",
-          "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==",
-          "requires": {
-            "emoji-regex": "^8.0.0",
-            "is-fullwidth-code-point": "^3.0.0",
-            "strip-ansi": "^6.0.0"
-          }
-        }
       }
     },
     "clone-deep": {
@@ -4040,6 +3976,11 @@
           "version": "2.0.0",
           "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
           "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
+        },
+        "safe-buffer": {
+          "version": "5.1.2",
+          "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+          "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
         }
       }
     },
@@ -4059,6 +4000,11 @@
         "typedarray": "^0.0.6"
       },
       "dependencies": {
+        "isarray": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+          "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
+        },
         "readable-stream": {
           "version": "2.3.7",
           "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
@@ -4073,6 +4019,11 @@
             "util-deprecate": "~1.0.1"
           }
         },
+        "safe-buffer": {
+          "version": "5.1.2",
+          "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+          "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
+        },
         "string_decoder": {
           "version": "1.1.1",
           "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
@@ -4114,6 +4065,13 @@
       "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==",
       "requires": {
         "safe-buffer": "5.1.2"
+      },
+      "dependencies": {
+        "safe-buffer": {
+          "version": "5.1.2",
+          "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+          "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
+        }
       }
     },
     "content-type": {
@@ -4127,6 +4085,13 @@
       "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==",
       "requires": {
         "safe-buffer": "~5.1.1"
+      },
+      "dependencies": {
+        "safe-buffer": {
+          "version": "5.1.2",
+          "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+          "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
+        }
       }
     },
     "cookie": {
@@ -4150,6 +4115,16 @@
         "mkdirp": "^0.5.1",
         "rimraf": "^2.5.4",
         "run-queue": "^1.0.0"
+      },
+      "dependencies": {
+        "rimraf": {
+          "version": "2.7.1",
+          "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
+          "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
+          "requires": {
+            "glob": "^7.1.3"
+          }
+        }
       }
     },
     "copy-descriptor": {
@@ -4158,16 +4133,16 @@
       "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40="
     },
     "core-js": {
-      "version": "3.8.0",
-      "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.8.0.tgz",
-      "integrity": "sha512-W2VYNB0nwQQE7tKS7HzXd7r2y/y2SVJl4ga6oH/dnaLFzM0o2lB2P3zCkWj5Wc/zyMYjtgd5Hmhk0ObkQFZOIA=="
+      "version": "3.8.2",
+      "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.8.2.tgz",
+      "integrity": "sha512-FfApuSRgrR6G5s58casCBd9M2k+4ikuu4wbW6pJyYU7bd9zvFc9qf7vr5xmrZOhT9nn+8uwlH1oRR9jTnFoA3A=="
     },
     "core-js-compat": {
-      "version": "3.8.0",
-      "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.8.0.tgz",
-      "integrity": "sha512-o9QKelQSxQMYWHXc/Gc4L8bx/4F7TTraE5rhuN8I7mKBt5dBIUpXpIR3omv70ebr8ST5R3PqbDQr+ZI3+Tt1FQ==",
+      "version": "3.8.2",
+      "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.8.2.tgz",
+      "integrity": "sha512-LO8uL9lOIyRRrQmZxHZFl1RV+ZbcsAkFWTktn5SmH40WgLtSNYN4m4W2v9ONT147PxBY/XrRhrWq8TlvObyUjQ==",
       "requires": {
-        "browserslist": "^4.14.7",
+        "browserslist": "^4.16.0",
         "semver": "7.0.0"
       },
       "dependencies": {
@@ -4179,9 +4154,9 @@
       }
     },
     "core-js-pure": {
-      "version": "3.8.0",
-      "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.8.0.tgz",
-      "integrity": "sha512-fRjhg3NeouotRoIV0L1FdchA6CK7ZD+lyINyMoz19SyV+ROpC4noS1xItWHFtwZdlqfMfVPJEyEGdfri2bD1pA=="
+      "version": "3.8.2",
+      "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.8.2.tgz",
+      "integrity": "sha512-v6zfIQqL/pzTVAbZvYUozsxNfxcFb6Ks3ZfEbuneJl3FW9Jb8F6vLWB6f+qTmAu72msUdyb84V8d/yBFf7FNnw=="
     },
     "core-util-is": {
       "version": "1.0.2",
@@ -4616,9 +4591,9 @@
       }
     },
     "dashjs": {
-      "version": "3.1.3",
-      "resolved": "https://registry.npmjs.org/dashjs/-/dashjs-3.1.3.tgz",
-      "integrity": "sha512-eymNYAr1KTMNTuq9k1W9UPwkFvWvpR+ykKTXQnPnD/W00DVFqdl4bZ1B4MUdFHFE3H38Bij1/cigRnDydXJvsQ==",
+      "version": "3.2.0",
+      "resolved": "https://registry.npmjs.org/dashjs/-/dashjs-3.2.0.tgz",
+      "integrity": "sha512-hir9kgQb4lV+sKGtMNwH5rS2c8Chn0R1URSAdgo73baBgmxq7PnN0RkP5u2VXnVDGR5jbH9KnjVuDTLv0nE2kw==",
       "requires": {
         "codem-isoboxer": "0.3.6",
         "fast-deep-equal": "2.0.1",
@@ -4627,13 +4602,6 @@
         "localforage": "^1.7.1",
         "request": "^2.87.0",
         "request-promise": "^4.2.2"
-      },
-      "dependencies": {
-        "fast-deep-equal": {
-          "version": "2.0.1",
-          "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz",
-          "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk="
-        }
       }
     },
     "data-urls": {
@@ -4796,6 +4764,14 @@
           "version": "2.1.0",
           "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz",
           "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw=="
+        },
+        "rimraf": {
+          "version": "2.7.1",
+          "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
+          "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
+          "requires": {
+            "glob": "^7.1.3"
+          }
         }
       }
     },
@@ -4940,9 +4916,9 @@
       },
       "dependencies": {
         "domelementtype": {
-          "version": "2.0.2",
-          "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.0.2.tgz",
-          "integrity": "sha512-wFwTwCVebUrMgGeAwRL/NhZtHAUyT9n9yg4IMDwf10+6iCMxSkVq9MGCVEH+QZWo1nNidy8kNvwmv4zWHDTqvA=="
+          "version": "2.1.0",
+          "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.1.0.tgz",
+          "integrity": "sha512-LsTgx/L5VpD+Q8lmsXSHW2WpA+eBlZ9HPf3erD1IoPF00/3JKHZ3BknUVA2QGDNu69ZNmyFmCWBSO45XjYKC5w=="
         }
       }
     },
@@ -4989,12 +4965,19 @@
       }
     },
     "dot-case": {
-      "version": "3.0.3",
-      "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.3.tgz",
-      "integrity": "sha512-7hwEmg6RiSQfm/GwPL4AAWXKy3YNNZA3oFv2Pdiey0mwkRCPZ9x6SZbkLcn8Ma5PYeVokzoD4Twv2n7LKp5WeA==",
+      "version": "3.0.4",
+      "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz",
+      "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==",
       "requires": {
-        "no-case": "^3.0.3",
-        "tslib": "^1.10.0"
+        "no-case": "^3.0.4",
+        "tslib": "^2.0.3"
+      },
+      "dependencies": {
+        "tslib": {
+          "version": "2.0.3",
+          "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz",
+          "integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ=="
+        }
       }
     },
     "dot-prop": {
@@ -5031,6 +5014,11 @@
         "stream-shift": "^1.0.0"
       },
       "dependencies": {
+        "isarray": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+          "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
+        },
         "readable-stream": {
           "version": "2.3.7",
           "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
@@ -5045,6 +5033,11 @@
             "util-deprecate": "~1.0.1"
           }
         },
+        "safe-buffer": {
+          "version": "5.1.2",
+          "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+          "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
+        },
         "string_decoder": {
           "version": "1.1.1",
           "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
@@ -5075,9 +5068,9 @@
       "integrity": "sha512-7vmuyh5+kuUyJKePhQfRQBhXV5Ce+RnaeeQArKu1EAMpL3WbgMt5WG6uQZpEVvYSSsxMXRKOewtDk9RaTKXRlA=="
     },
     "electron-to-chromium": {
-      "version": "1.3.609",
-      "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.609.tgz",
-      "integrity": "sha512-kcmRWmlHsUKKLfsSKSf7VqeTX4takM5ndjVTM3et3qpDCceITYI1DixvIfSDIngALoaTnpoMXD3SXSMpzHkYKA=="
+      "version": "1.3.633",
+      "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.633.tgz",
+      "integrity": "sha512-bsVCsONiVX1abkWdH7KtpuDAhsQ3N3bjPYhROSAXE78roJKet0Y5wznA14JE9pzbwSZmSMAW6KiKYf1RvbTJkA=="
     },
     "elliptic": {
       "version": "6.5.3",
@@ -5106,9 +5099,9 @@
       "integrity": "sha512-A8OG5SR/ij3SsJdWDJdkkSYUjQdCUx6APQXem0SaEePBSRg4eymGYwBkKo1Y6DU+af/Jn2dBQqDBvjnr9Vi8nQ=="
     },
     "emoji-regex": {
-      "version": "7.0.3",
-      "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz",
-      "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA=="
+      "version": "8.0.0",
+      "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+      "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
     },
     "emojis-list": {
       "version": "3.0.0",
@@ -5138,6 +5131,11 @@
         "tapable": "^1.0.0"
       },
       "dependencies": {
+        "isarray": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+          "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
+        },
         "memory-fs": {
           "version": "0.5.0",
           "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.5.0.tgz",
@@ -5161,6 +5159,11 @@
             "util-deprecate": "~1.0.1"
           }
         },
+        "safe-buffer": {
+          "version": "5.1.2",
+          "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+          "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
+        },
         "string_decoder": {
           "version": "1.1.1",
           "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
@@ -5185,9 +5188,9 @@
       "integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w=="
     },
     "errno": {
-      "version": "0.1.7",
-      "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz",
-      "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==",
+      "version": "0.1.8",
+      "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz",
+      "integrity": "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==",
       "requires": {
         "prr": "~1.0.1"
       }
@@ -5331,12 +5334,12 @@
       }
     },
     "eslint": {
-      "version": "7.14.0",
-      "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.14.0.tgz",
-      "integrity": "sha512-5YubdnPXrlrYAFCKybPuHIAH++PINe1pmKNc5wQRB9HSbqIK1ywAnntE3Wwua4giKu0bjligf1gLF6qxMGOYRA==",
+      "version": "7.17.0",
+      "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.17.0.tgz",
+      "integrity": "sha512-zJk08MiBgwuGoxes5sSQhOtibZ75pz0J35XTRlZOk9xMffhpA9BTbQZxoXZzOl5zMbleShbGwtw+1kGferfFwQ==",
       "requires": {
         "@babel/code-frame": "^7.0.0",
-        "@eslint/eslintrc": "^0.2.1",
+        "@eslint/eslintrc": "^0.2.2",
         "ajv": "^6.10.0",
         "chalk": "^4.0.0",
         "cross-spawn": "^7.0.2",
@@ -5346,10 +5349,10 @@
         "eslint-scope": "^5.1.1",
         "eslint-utils": "^2.1.0",
         "eslint-visitor-keys": "^2.0.0",
-        "espree": "^7.3.0",
+        "espree": "^7.3.1",
         "esquery": "^1.2.0",
         "esutils": "^2.0.2",
-        "file-entry-cache": "^5.0.1",
+        "file-entry-cache": "^6.0.0",
         "functional-red-black-tree": "^1.0.1",
         "glob-parent": "^5.0.0",
         "globals": "^12.1.0",
@@ -5369,7 +5372,7 @@
         "semver": "^7.2.1",
         "strip-ansi": "^6.0.0",
         "strip-json-comments": "^3.1.0",
-        "table": "^5.2.3",
+        "table": "^6.0.4",
         "text-table": "^0.2.0",
         "v8-compile-cache": "^2.0.3"
       },
@@ -5587,6 +5590,11 @@
             "isarray": "^1.0.0"
           }
         },
+        "isarray": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+          "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
+        },
         "ms": {
           "version": "2.0.0",
           "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
@@ -5628,9 +5636,9 @@
       }
     },
     "eslint-plugin-react": {
-      "version": "7.21.5",
-      "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.21.5.tgz",
-      "integrity": "sha512-8MaEggC2et0wSF6bUeywF7qQ46ER81irOdWS4QWxnnlAEsnzeBevk1sWh7fhpCghPpXb+8Ks7hvaft6L/xsR6g==",
+      "version": "7.22.0",
+      "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.22.0.tgz",
+      "integrity": "sha512-p30tuX3VS+NWv9nQot9xIGAHBXR0+xJVaZriEsHoJrASGCJZDJ8JLNM0YqKqI0AKm6Uxaa1VUHoNEibxRCMQHA==",
       "requires": {
         "array-includes": "^3.1.1",
         "array.prototype.flatmap": "^1.2.3",
@@ -5745,9 +5753,9 @@
       "integrity": "sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ=="
     },
     "eslint-webpack-plugin": {
-      "version": "2.4.0",
-      "resolved": "https://registry.npmjs.org/eslint-webpack-plugin/-/eslint-webpack-plugin-2.4.0.tgz",
-      "integrity": "sha512-j0lAJj3RnStAFdIH2P0+nsEImiBijwogZhL1go4bI6DE+9OhQuOmJ/xtmxkLtNr1w0cf5SRNkDlmIe8t/pHgww==",
+      "version": "2.4.1",
+      "resolved": "https://registry.npmjs.org/eslint-webpack-plugin/-/eslint-webpack-plugin-2.4.1.tgz",
+      "integrity": "sha512-cj8iPWZKuAiVD8MMgTSunyMCAvxQxp5mxoPHZl1UMGkApFXaXJHdCFcCR+oZEJbBNhReNa5SjESIn34uqUbBtg==",
       "requires": {
         "@types/eslint": "^7.2.4",
         "arrify": "^2.0.1",
@@ -5769,12 +5777,12 @@
       }
     },
     "espree": {
-      "version": "7.3.0",
-      "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.0.tgz",
-      "integrity": "sha512-dksIWsvKCixn1yrEXO8UosNSxaDoSYpq9reEjZSbHLpT5hpaCAKTLBwq0RHtLrIr+c0ByiYzWT8KTMRzoRCNlw==",
+      "version": "7.3.1",
+      "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz",
+      "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==",
       "requires": {
         "acorn": "^7.4.0",
-        "acorn-jsx": "^5.2.0",
+        "acorn-jsx": "^5.3.1",
         "eslint-visitor-keys": "^1.3.0"
       },
       "dependencies": {
@@ -6004,10 +6012,20 @@
           "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
           "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
         },
+        "path-to-regexp": {
+          "version": "0.1.7",
+          "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
+          "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w="
+        },
         "qs": {
           "version": "6.7.0",
           "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz",
           "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ=="
+        },
+        "safe-buffer": {
+          "version": "5.1.2",
+          "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+          "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
         }
       }
     },
@@ -6115,9 +6133,9 @@
       "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU="
     },
     "fast-deep-equal": {
-      "version": "3.1.3",
-      "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
-      "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz",
+      "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk="
     },
     "fast-glob": {
       "version": "3.2.4",
@@ -6143,9 +6161,9 @@
       "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc="
     },
     "fastq": {
-      "version": "1.9.0",
-      "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.9.0.tgz",
-      "integrity": "sha512-i7FVWL8HhVY+CTkwFxkN2mk3h+787ixS5S63eb78diVRc1MCssarHq3W5cj0av7YDSwmaV928RNag+U1etRQ7w==",
+      "version": "1.10.0",
+      "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.10.0.tgz",
+      "integrity": "sha512-NL2Qc5L3iQEsyYzweq7qfgy5OtXCmGzGvhElGEd/SoFWEMOEczNh5s5ocaF01HDetxz+p8ecjNPA6cZxxIHmzA==",
       "requires": {
         "reusify": "^1.0.4"
       }
@@ -6172,11 +6190,11 @@
       "integrity": "sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw=="
     },
     "file-entry-cache": {
-      "version": "5.0.1",
-      "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz",
-      "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==",
+      "version": "6.0.0",
+      "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.0.tgz",
+      "integrity": "sha512-fqoO76jZ3ZnYrXLDRxBR1YvOvc0k844kcOg40bgsPrE25LAb/PDqTY+ho64Xh2c8ZXgIKldchCFHczG2UVRcWA==",
       "requires": {
-        "flat-cache": "^2.0.1"
+        "flat-cache": "^3.0.4"
       }
     },
     "file-loader": {
@@ -6262,19 +6280,18 @@
       }
     },
     "flat-cache": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz",
-      "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==",
+      "version": "3.0.4",
+      "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz",
+      "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==",
       "requires": {
-        "flatted": "^2.0.0",
-        "rimraf": "2.6.3",
-        "write": "1.0.3"
+        "flatted": "^3.1.0",
+        "rimraf": "^3.0.2"
       }
     },
     "flatted": {
-      "version": "2.0.2",
-      "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.2.tgz",
-      "integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA=="
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.1.0.tgz",
+      "integrity": "sha512-tW+UkmtNg/jv9CSofAKvgVcO7c2URjhTdW1ZTkcAritblu8tajiYy7YisnIflEwtKssCtOxpnBRoCB7iap0/TA=="
     },
     "flatten": {
       "version": "1.0.3",
@@ -6290,6 +6307,11 @@
         "readable-stream": "^2.3.6"
       },
       "dependencies": {
+        "isarray": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+          "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
+        },
         "readable-stream": {
           "version": "2.3.7",
           "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
@@ -6304,6 +6326,11 @@
             "util-deprecate": "~1.0.1"
           }
         },
+        "safe-buffer": {
+          "version": "5.1.2",
+          "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+          "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
+        },
         "string_decoder": {
           "version": "1.1.1",
           "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
@@ -6315,9 +6342,9 @@
       }
     },
     "follow-redirects": {
-      "version": "1.13.0",
-      "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.0.tgz",
-      "integrity": "sha512-aq6gF1BEKje4a9i9+5jimNFIpq4Q1WiwBToeRK5NvZBd/TRsmW8BsJfOEGkr76TbOyPVD3OVDN910EcUNtRYEA=="
+      "version": "1.13.1",
+      "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.1.tgz",
+      "integrity": "sha512-SSG5xmZh1mkPGyKzjZP8zLjltIfpW32Y5QpdNJyjcfGxK3qo3NDDkZOZSFiGn1A6SclQxY9GzEwAHQ3dmYRWpg=="
     },
     "for-in": {
       "version": "1.0.2",
@@ -6526,6 +6553,11 @@
         "readable-stream": "^2.0.0"
       },
       "dependencies": {
+        "isarray": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+          "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
+        },
         "readable-stream": {
           "version": "2.3.7",
           "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
@@ -6540,6 +6572,11 @@
             "util-deprecate": "~1.0.1"
           }
         },
+        "safe-buffer": {
+          "version": "5.1.2",
+          "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+          "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
+        },
         "string_decoder": {
           "version": "1.1.1",
           "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
@@ -6580,6 +6617,11 @@
         "readable-stream": "1 || 2"
       },
       "dependencies": {
+        "isarray": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+          "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
+        },
         "readable-stream": {
           "version": "2.3.7",
           "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
@@ -6594,6 +6636,11 @@
             "util-deprecate": "~1.0.1"
           }
         },
+        "safe-buffer": {
+          "version": "5.1.2",
+          "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+          "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
+        },
         "string_decoder": {
           "version": "1.1.1",
           "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
@@ -6636,9 +6683,9 @@
       "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg=="
     },
     "get-intrinsic": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.0.1.tgz",
-      "integrity": "sha512-ZnWP+AmS1VUaLgTRy47+zKtjTxz+0xMpx3I52i+aalBK1QP19ggLF3Db89KJX7kjfOfP2eoa01qc++GwPgufPg==",
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.0.2.tgz",
+      "integrity": "sha512-aeX0vrFm21ILl3+JpFFRNe9aUvp6VFZb2/CTbgLb8j75kOhvoNYjt9d8KA/tJG4gSo8nzEDedRl0h7vDmBYRVg==",
       "requires": {
         "function-bind": "^1.1.1",
         "has": "^1.0.3",
@@ -6850,13 +6897,6 @@
         "inherits": "^2.0.4",
         "readable-stream": "^3.6.0",
         "safe-buffer": "^5.2.0"
-      },
-      "dependencies": {
-        "safe-buffer": {
-          "version": "5.2.1",
-          "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
-          "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="
-        }
       }
     },
     "hash.js": {
@@ -6907,6 +6947,13 @@
       "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==",
       "requires": {
         "react-is": "^16.7.0"
+      },
+      "dependencies": {
+        "react-is": {
+          "version": "16.13.1",
+          "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
+          "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
+        }
       }
     },
     "hoopy": {
@@ -6930,6 +6977,11 @@
         "wbuf": "^1.1.0"
       },
       "dependencies": {
+        "isarray": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+          "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
+        },
         "readable-stream": {
           "version": "2.3.7",
           "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
@@ -6944,6 +6996,11 @@
             "util-deprecate": "~1.0.1"
           }
         },
+        "safe-buffer": {
+          "version": "5.1.2",
+          "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+          "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
+        },
         "string_decoder": {
           "version": "1.1.1",
           "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
@@ -6978,9 +7035,9 @@
       }
     },
     "html-entities": {
-      "version": "1.3.1",
-      "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.3.1.tgz",
-      "integrity": "sha512-rhE/4Z3hIhzHAUKbW8jVcCyuT5oJCXXqhN/6mXXVCpzTmvJnoH2HL/bt3EZ6p55jbFJBeAe1ZNpL5BugLujxNA=="
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.4.0.tgz",
+      "integrity": "sha512-8nxjcBcd8wovbeKx7h3wTji4e6+rhaVuPNpMqwWgnHh+N9ToqsCs6XztWRBPQ+UtzsoMAdKZtUENoVzU/EMtZA=="
     },
     "html-escaper": {
       "version": "2.0.2",
@@ -7291,9 +7348,9 @@
       }
     },
     "import-fresh": {
-      "version": "3.2.2",
-      "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.2.tgz",
-      "integrity": "sha512-cTPNrlvJT6twpYy+YmKUKrTSjWFs3bjYjAhCwm+z4EOCubZxAuO+hHpRN64TqjEaYSHs7tJAE0w1CKMGmsG/lw==",
+      "version": "3.3.0",
+      "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
+      "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==",
       "requires": {
         "parent-module": "^1.0.0",
         "resolve-from": "^4.0.0"
@@ -7391,9 +7448,9 @@
       "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
     },
     "ini": {
-      "version": "1.3.5",
-      "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz",
-      "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw=="
+      "version": "1.3.8",
+      "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
+      "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew=="
     },
     "internal-ip": {
       "version": "4.3.0",
@@ -7473,9 +7530,12 @@
       }
     },
     "is-arguments": {
-      "version": "1.0.4",
-      "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.0.4.tgz",
-      "integrity": "sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA=="
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.0.tgz",
+      "integrity": "sha512-1Ij4lOMPl/xB5kBDn7I+b2ttPMKa8szhEIrXDuXQD/oe3HJLTLhqhgGspwgyGd6MOywBUqVvYicF72lkgDnIHg==",
+      "requires": {
+        "call-bind": "^1.0.0"
+      }
     },
     "is-arrayish": {
       "version": "0.2.1",
@@ -7591,9 +7651,9 @@
       "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI="
     },
     "is-fullwidth-code-point": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
-      "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8="
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+      "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="
     },
     "is-generator-fn": {
       "version": "2.1.0",
@@ -7619,9 +7679,9 @@
       "integrity": "sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE="
     },
     "is-negative-zero": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.0.tgz",
-      "integrity": "sha1-lVOxIbD6wohp2p7UWeIMdUN4hGE="
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.1.tgz",
+      "integrity": "sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w=="
     },
     "is-number": {
       "version": "7.0.0",
@@ -7740,9 +7800,9 @@
       }
     },
     "isarray": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
-      "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
+      "version": "0.0.1",
+      "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
+      "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8="
     },
     "isexe": {
       "version": "2.0.0",
@@ -8727,9 +8787,9 @@
       "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="
     },
     "js-yaml": {
-      "version": "3.14.0",
-      "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz",
-      "integrity": "sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==",
+      "version": "3.14.1",
+      "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz",
+      "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==",
       "requires": {
         "argparse": "^1.0.7",
         "esprima": "^4.0.0"
@@ -9010,12 +9070,12 @@
       }
     },
     "jsx-ast-utils": {
-      "version": "3.1.0",
-      "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.1.0.tgz",
-      "integrity": "sha512-d4/UOjg+mxAWxCiF0c5UTSwyqbchkbqCvK87aBovhnh8GtysTjWmgC63tY0cJx/HzGgm9qnA147jVBdpOiQ2RA==",
+      "version": "3.2.0",
+      "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.2.0.tgz",
+      "integrity": "sha512-EIsmt3O3ljsU6sot/J4E1zDRxfBNrhjyf/OKjlydwgEimQuznlM4Wv7U+ueONJMyEn1WRE0K8dhi3dVAXYT24Q==",
       "requires": {
-        "array-includes": "^3.1.1",
-        "object.assign": "^4.1.1"
+        "array-includes": "^3.1.2",
+        "object.assign": "^4.1.2"
       }
     },
     "killable": {
@@ -9069,6 +9129,11 @@
         "type-check": "~0.4.0"
       }
     },
+    "libjass": {
+      "version": "0.11.0",
+      "resolved": "https://registry.npmjs.org/libjass/-/libjass-0.11.0.tgz",
+      "integrity": "sha1-v/H0ZKJCjDvd+2jkUDstUq/j1uY="
+    },
     "lie": {
       "version": "3.1.1",
       "resolved": "https://registry.npmjs.org/lie/-/lie-3.1.1.tgz",
@@ -9195,11 +9260,18 @@
       }
     },
     "lower-case": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.1.tgz",
-      "integrity": "sha512-LiWgfDLLb1dwbFQZsSglpRj+1ctGnayXz3Uv0/WO8n558JycT5fg6zkNcnW0G68Nn0aEldTFeEfmjCfmqry/rQ==",
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz",
+      "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==",
       "requires": {
-        "tslib": "^1.10.0"
+        "tslib": "^2.0.3"
+      },
+      "dependencies": {
+        "tslib": {
+          "version": "2.0.3",
+          "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz",
+          "integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ=="
+        }
       }
     },
     "lru-cache": {
@@ -9289,6 +9361,11 @@
         "readable-stream": "^2.0.1"
       },
       "dependencies": {
+        "isarray": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+          "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
+        },
         "readable-stream": {
           "version": "2.3.7",
           "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
@@ -9303,6 +9380,11 @@
             "util-deprecate": "~1.0.1"
           }
         },
+        "safe-buffer": {
+          "version": "5.1.2",
+          "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+          "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
+        },
         "string_decoder": {
           "version": "1.1.1",
           "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
@@ -9369,16 +9451,16 @@
       "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg=="
     },
     "mime-db": {
-      "version": "1.44.0",
-      "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz",
-      "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg=="
+      "version": "1.45.0",
+      "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.45.0.tgz",
+      "integrity": "sha512-CkqLUxUk15hofLoLyljJSrukZi8mAtgd+yE5uO4tqRZsdsAJKv0O+rFMhVDRJgozy+yG6md5KwuXhD4ocIoP+w=="
     },
     "mime-types": {
-      "version": "2.1.27",
-      "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz",
-      "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==",
+      "version": "2.1.28",
+      "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.28.tgz",
+      "integrity": "sha512-0TO2yJ5YHYr7M2zzT7gDU1tbwHxEUWBCLt0lscSNpcdAfFyJOVEpRYNS7EXVcTLNj/25QO8gulHC5JtTzSE2UQ==",
       "requires": {
-        "mime-db": "1.44.0"
+        "mime-db": "1.45.0"
       }
     },
     "mimic-fn": {
@@ -9392,11 +9474,11 @@
       "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg=="
     },
     "mini-create-react-context": {
-      "version": "0.4.0",
-      "resolved": "https://registry.npmjs.org/mini-create-react-context/-/mini-create-react-context-0.4.0.tgz",
-      "integrity": "sha512-b0TytUgFSbgFJGzJqXPKCFCBWigAjpjo+Fl7Vf7ZbKRDptszpppKxXH6DRXEABZ/gcEQczeb0iZ7JvL8e8jjCA==",
+      "version": "0.4.1",
+      "resolved": "https://registry.npmjs.org/mini-create-react-context/-/mini-create-react-context-0.4.1.tgz",
+      "integrity": "sha512-YWCYEmd5CQeHGSAKrYvXgmzzkrvssZcuuQDDeqkT+PziKGMgE+0MCCtcKbROzocGBG1meBLl2FotlRwf4gAzbQ==",
       "requires": {
-        "@babel/runtime": "^7.5.5",
+        "@babel/runtime": "^7.12.1",
         "tiny-warning": "^1.0.3"
       }
     },
@@ -9560,6 +9642,16 @@
         "mkdirp": "^0.5.1",
         "rimraf": "^2.5.4",
         "run-queue": "^1.0.3"
+      },
+      "dependencies": {
+        "rimraf": {
+          "version": "2.7.1",
+          "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
+          "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
+          "requires": {
+            "glob": "^7.1.3"
+          }
+        }
       }
     },
     "ms": {
@@ -9582,9 +9674,9 @@
       "integrity": "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE="
     },
     "nanoid": {
-      "version": "3.1.18",
-      "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.18.tgz",
-      "integrity": "sha512-rndlDjbbHbcV3xi+R2fpJ+PbGMdfBxz5v1fATIQFq0DP64FsicQdwnKLy47K4kZHdRpmQXtz24eGsxQqamzYTA=="
+      "version": "3.1.20",
+      "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.20.tgz",
+      "integrity": "sha512-a1cQNyczgKbLX9jwbS/+d7W8fX/RfgYR7lVWwWOGIPNgK2m0MWvrGF6/m4kk6U3QcFMnZf3RIhL0v2Jgh/0Uxw=="
     },
     "nanomatch": {
       "version": "1.2.13",
@@ -9638,12 +9730,19 @@
       "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ=="
     },
     "no-case": {
-      "version": "3.0.3",
-      "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.3.tgz",
-      "integrity": "sha512-ehY/mVQCf9BL0gKfsJBvFJen+1V//U+0HQMPrWct40ixE4jnv0bfvxDbWtAHL9EcaPEOJHVVYKoQn1TlZUB8Tw==",
+      "version": "3.0.4",
+      "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz",
+      "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==",
       "requires": {
-        "lower-case": "^2.0.1",
-        "tslib": "^1.10.0"
+        "lower-case": "^2.0.2",
+        "tslib": "^2.0.3"
+      },
+      "dependencies": {
+        "tslib": {
+          "version": "2.0.3",
+          "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz",
+          "integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ=="
+        }
       }
     },
     "node-forge": {
@@ -9686,6 +9785,11 @@
         "vm-browserify": "^1.0.1"
       },
       "dependencies": {
+        "isarray": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+          "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
+        },
         "punycode": {
           "version": "1.4.1",
           "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
@@ -9714,6 +9818,11 @@
               }
             }
           }
+        },
+        "safe-buffer": {
+          "version": "5.1.2",
+          "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+          "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
         }
       }
     },
@@ -9723,9 +9832,9 @@
       "integrity": "sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA="
     },
     "node-notifier": {
-      "version": "8.0.0",
-      "resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-8.0.0.tgz",
-      "integrity": "sha512-46z7DUmcjoYdaWyXouuFNNfUo6eFa94t23c53c+lG/9Cvauk4a98rAUp9672X5dxGdQmLpPzTxzu8f/OeEPaFA==",
+      "version": "8.0.1",
+      "resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-8.0.1.tgz",
+      "integrity": "sha512-BvEXF+UmsnAfYfoapKM9nGxnP+Wn7P91YfXmrKnfcYCx6VBeoN5Ez5Ogck6I8Bi5k4RlpqRYaw75pAwzX9OphA==",
       "optional": true,
       "requires": {
         "growly": "^1.3.0",
@@ -9737,9 +9846,9 @@
       },
       "dependencies": {
         "uuid": {
-          "version": "8.3.1",
-          "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.1.tgz",
-          "integrity": "sha512-FOmRr+FmWEIG8uhZv6C2bTgEVXsHk08kE7mPlrBbEe+c3r9pjceVPgupIfNIhc4yx55H69OXANrUaSuu9eInKg==",
+          "version": "8.3.2",
+          "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
+          "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
           "optional": true
         },
         "which": {
@@ -9862,9 +9971,9 @@
       }
     },
     "object-inspect": {
-      "version": "1.8.0",
-      "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz",
-      "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA=="
+      "version": "1.9.0",
+      "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.9.0.tgz",
+      "integrity": "sha512-i3Bp9iTqwhaLZBxGkRfo5ZbE07BQRT7MGu8+nNgwW9ItGp1TzCTw2DLEoWwjClxBjOFI/hWljTAmYGCEwmtnOw=="
     },
     "object-is": {
       "version": "1.1.4",
@@ -10105,6 +10214,11 @@
         "readable-stream": "^2.1.5"
       },
       "dependencies": {
+        "isarray": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+          "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
+        },
         "readable-stream": {
           "version": "2.3.7",
           "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
@@ -10119,6 +10233,11 @@
             "util-deprecate": "~1.0.1"
           }
         },
+        "safe-buffer": {
+          "version": "5.1.2",
+          "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+          "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
+        },
         "string_decoder": {
           "version": "1.1.1",
           "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
@@ -10130,12 +10249,19 @@
       }
     },
     "param-case": {
-      "version": "3.0.3",
-      "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.3.tgz",
-      "integrity": "sha512-VWBVyimc1+QrzappRs7waeN2YmoZFCGXWASRYX1/rGHtXqEcrGEIDm+jqIwFa2fRXNgQEwrxaYuIrX0WcAguTA==",
+      "version": "3.0.4",
+      "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz",
+      "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==",
       "requires": {
-        "dot-case": "^3.0.3",
-        "tslib": "^1.10.0"
+        "dot-case": "^3.0.4",
+        "tslib": "^2.0.3"
+      },
+      "dependencies": {
+        "tslib": {
+          "version": "2.0.3",
+          "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz",
+          "integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ=="
+        }
       }
     },
     "parent-module": {
@@ -10180,12 +10306,19 @@
       "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ=="
     },
     "pascal-case": {
-      "version": "3.1.1",
-      "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.1.tgz",
-      "integrity": "sha512-XIeHKqIrsquVTQL2crjq3NfJUxmdLasn3TYOU0VBM+UX2a6ztAWBlJQBePLGY7VHW8+2dRadeIPK5+KImwTxQA==",
+      "version": "3.1.2",
+      "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz",
+      "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==",
       "requires": {
-        "no-case": "^3.0.3",
-        "tslib": "^1.10.0"
+        "no-case": "^3.0.4",
+        "tslib": "^2.0.3"
+      },
+      "dependencies": {
+        "tslib": {
+          "version": "2.0.3",
+          "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz",
+          "integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ=="
+        }
       }
     },
     "pascalcase": {
@@ -10229,9 +10362,12 @@
       "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw=="
     },
     "path-to-regexp": {
-      "version": "0.1.7",
-      "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
-      "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w="
+      "version": "1.8.0",
+      "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz",
+      "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==",
+      "requires": {
+        "isarray": "0.0.1"
+      }
     },
     "path-type": {
       "version": "4.0.0",
@@ -11349,14 +11485,13 @@
       },
       "dependencies": {
         "postcss": {
-          "version": "8.1.10",
-          "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.1.10.tgz",
-          "integrity": "sha512-iBXEV5VTTYaRRdxiFYzTtuv2lGMQBExqkZKSzkJe+Fl6rvQrA/49UVGKqB+LG54hpW/TtDBMGds8j33GFNW7pg==",
+          "version": "8.2.2",
+          "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.2.2.tgz",
+          "integrity": "sha512-HM1NDNWLgglJPQQMNwvLxgH2KcrKZklKLi/xXYIOaqQB57p/pDWEJNS83PVICYsn1Dg/9C26TiejNr422/ePaQ==",
           "requires": {
             "colorette": "^1.2.1",
-            "nanoid": "^3.1.18",
-            "source-map": "^0.6.1",
-            "vfile-location": "^3.2.0"
+            "nanoid": "^3.1.20",
+            "source-map": "^0.6.1"
           }
         }
       }
@@ -11371,9 +11506,9 @@
       }
     },
     "postcss-selector-not": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/postcss-selector-not/-/postcss-selector-not-4.0.0.tgz",
-      "integrity": "sha512-W+bkBZRhqJaYN8XAnbbZPLWMvZD1wKTu0UxtFKdhtGjWYmxhkUneoeOhRJKdAE5V7ZTlnbHfCR+6bNwK9e1dTQ==",
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/postcss-selector-not/-/postcss-selector-not-4.0.1.tgz",
+      "integrity": "sha512-YolvBgInEK5/79C+bdFMyzqTg6pkYqDbzZIST/PDMqa/o3qtXenD05apBG2jLgT0/BQ77d4U2UK12jWpilqMAQ==",
       "requires": {
         "balanced-match": "^1.0.0",
         "postcss": "^7.0.2"
@@ -11444,9 +11579,9 @@
       "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw="
     },
     "pretty-bytes": {
-      "version": "5.4.1",
-      "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.4.1.tgz",
-      "integrity": "sha512-s1Iam6Gwz3JI5Hweaz4GoCD1WUNUIyzePFy5+Js2hjwGVt2Z79wNN+ZKOZ2vB6C+Xs6njyB84Z1IthQg8d9LxA=="
+      "version": "5.5.0",
+      "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.5.0.tgz",
+      "integrity": "sha512-p+T744ZyjjiaFlMUZZv6YPC5JrkNj8maRmPaQCWFJFplUAzpIUTRaTcS+7wmZtUoFXHtESJb23ISliaWyz3SHA=="
     },
     "pretty-error": {
       "version": "2.1.2",
@@ -11466,13 +11601,6 @@
         "ansi-regex": "^5.0.0",
         "ansi-styles": "^4.0.0",
         "react-is": "^17.0.1"
-      },
-      "dependencies": {
-        "react-is": {
-          "version": "17.0.1",
-          "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.1.tgz",
-          "integrity": "sha512-NAnt2iGDXohE5LI7uBnLnqvLQMtzhkiAOLXTmv+qnF9Ky7xAPcX8Up/xWIhxvLVGJvuLiNc4xQLtuqDRzb4fSA=="
-        }
       }
     },
     "process": {
@@ -11520,6 +11648,13 @@
         "loose-envify": "^1.4.0",
         "object-assign": "^4.1.1",
         "react-is": "^16.8.1"
+      },
+      "dependencies": {
+        "react-is": {
+          "version": "16.13.1",
+          "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
+          "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
+        }
       }
     },
     "proxy-addr": {
@@ -11731,6 +11866,14 @@
         "text-table": "0.2.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==",
+          "requires": {
+            "@babel/highlight": "^7.10.4"
+          }
+        },
         "ansi-styles": {
           "version": "3.2.1",
           "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
@@ -11862,9 +12005,9 @@
       "integrity": "sha512-HvPuUQnLp5H7TouGq3kzBeioJmXms1wHy9EGjz2OURWBp4qZO6AfGEcnxts1D/CbwPLRAgTMPCEgYhA3sEM4vw=="
     },
     "react-is": {
-      "version": "16.13.1",
-      "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
-      "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
+      "version": "17.0.1",
+      "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.1.tgz",
+      "integrity": "sha512-NAnt2iGDXohE5LI7uBnLnqvLQMtzhkiAOLXTmv+qnF9Ky7xAPcX8Up/xWIhxvLVGJvuLiNc4xQLtuqDRzb4fSA=="
     },
     "react-jss": {
       "version": "10.5.0",
@@ -11906,18 +12049,10 @@
         "tiny-warning": "^1.0.0"
       },
       "dependencies": {
-        "isarray": {
-          "version": "0.0.1",
-          "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
-          "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8="
-        },
-        "path-to-regexp": {
-          "version": "1.8.0",
-          "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz",
-          "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==",
-          "requires": {
-            "isarray": "0.0.1"
-          }
+        "react-is": {
+          "version": "16.13.1",
+          "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
+          "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
         }
       }
     },
@@ -12002,9 +12137,9 @@
       }
     },
     "react-sweet-state": {
-      "version": "2.4.4",
-      "resolved": "https://registry.npmjs.org/react-sweet-state/-/react-sweet-state-2.4.4.tgz",
-      "integrity": "sha512-k2R3uJBrPTJQXVloXBoBcszqtgL3FqMGlYw34en6WGQCw4NpoRzNPyihoi6KWUOd0FUHwp9RMfaFGj5Ov+OSCQ=="
+      "version": "2.5.1",
+      "resolved": "https://registry.npmjs.org/react-sweet-state/-/react-sweet-state-2.5.1.tgz",
+      "integrity": "sha512-/hPzgN3xw3Mw27BPiS+bkFmvhQC0PexvehWtd4n2H9N7d+RjO3AxduMYB6rsJaw0DxbxUwWMJn4kCU/y+kTLIg=="
     },
     "read-pkg": {
       "version": "2.0.0",
@@ -12239,13 +12374,13 @@
       "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8="
     },
     "renderkid": {
-      "version": "2.0.4",
-      "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-2.0.4.tgz",
-      "integrity": "sha512-K2eXrSOJdq+HuKzlcjOlGoOarUu5SDguDEhE7+Ah4zuOWL40j8A/oHvLlLob9PSTNvVnBd+/q0Er1QfpEuem5g==",
+      "version": "2.0.5",
+      "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-2.0.5.tgz",
+      "integrity": "sha512-ccqoLg+HLOHq1vdfYNm4TBeaCDIi1FLt3wGojTDSvdewUv65oTmI3cnT2E4hRjl1gzKZIPK+KZrXzlUYKnR+vQ==",
       "requires": {
-        "css-select": "^1.1.0",
+        "css-select": "^2.0.2",
         "dom-converter": "^0.2",
-        "htmlparser2": "^3.3.0",
+        "htmlparser2": "^3.10.1",
         "lodash": "^4.17.20",
         "strip-ansi": "^3.0.0"
       },
@@ -12255,31 +12390,6 @@
           "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
           "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8="
         },
-        "css-select": {
-          "version": "1.2.0",
-          "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz",
-          "integrity": "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=",
-          "requires": {
-            "boolbase": "~1.0.0",
-            "css-what": "2.1",
-            "domutils": "1.5.1",
-            "nth-check": "~1.0.1"
-          }
-        },
-        "css-what": {
-          "version": "2.1.3",
-          "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.3.tgz",
-          "integrity": "sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg=="
-        },
-        "domutils": {
-          "version": "1.5.1",
-          "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz",
-          "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=",
-          "requires": {
-            "dom-serializer": "0",
-            "domelementtype": "1"
-          }
-        },
         "strip-ansi": {
           "version": "3.0.1",
           "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
@@ -12361,6 +12471,11 @@
       "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
       "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I="
     },
+    "require-from-string": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
+      "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw=="
+    },
     "require-main-filename": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz",
@@ -12596,9 +12711,9 @@
       "integrity": "sha1-QzdOLiyglosO8VI0YLfXMP8i7rM="
     },
     "rimraf": {
-      "version": "2.6.3",
-      "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz",
-      "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==",
+      "version": "3.0.2",
+      "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
+      "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
       "requires": {
         "glob": "^7.1.3"
       }
@@ -12709,9 +12824,9 @@
       }
     },
     "safe-buffer": {
-      "version": "5.1.2",
-      "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
-      "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
+      "version": "5.2.1",
+      "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+      "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="
     },
     "safe-regex": {
       "version": "1.1.0",
@@ -13142,12 +13257,13 @@
       "optional": true
     },
     "side-channel": {
-      "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.3.tgz",
-      "integrity": "sha512-A6+ByhlLkksFoUepsGxfj5x1gTSrs+OydsRptUxeNCabQpCFUvcwIczgOigI8vhY/OJCnPnyE9rGiwgvr9cS1g==",
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
+      "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==",
       "requires": {
-        "es-abstract": "^1.18.0-next.0",
-        "object-inspect": "^1.8.0"
+        "call-bind": "^1.0.0",
+        "get-intrinsic": "^1.0.2",
+        "object-inspect": "^1.9.0"
       }
     },
     "signal-exit": {
@@ -13181,36 +13297,13 @@
       "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q=="
     },
     "slice-ansi": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz",
-      "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==",
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz",
+      "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==",
       "requires": {
-        "ansi-styles": "^3.2.0",
-        "astral-regex": "^1.0.0",
-        "is-fullwidth-code-point": "^2.0.0"
-      },
-      "dependencies": {
-        "ansi-styles": {
-          "version": "3.2.1",
-          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
-          "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
-          "requires": {
-            "color-convert": "^1.9.0"
-          }
-        },
-        "color-convert": {
-          "version": "1.9.3",
-          "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
-          "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
-          "requires": {
-            "color-name": "1.1.3"
-          }
-        },
-        "color-name": {
-          "version": "1.1.3",
-          "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
-          "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
-        }
+        "ansi-styles": "^4.0.0",
+        "astral-regex": "^2.0.0",
+        "is-fullwidth-code-point": "^3.0.0"
       }
     },
     "snapdragon": {
@@ -13451,9 +13544,9 @@
       }
     },
     "spdx-license-ids": {
-      "version": "3.0.6",
-      "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.6.tgz",
-      "integrity": "sha512-+orQK83kyMva3WyPf59k1+Y525csj5JejicWut55zeTWANuN17qSiSLUXWtzHeNWORSvT7GLDJ/E/XiIWoXBTw=="
+      "version": "3.0.7",
+      "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.7.tgz",
+      "integrity": "sha512-U+MTEOO0AiDzxwFvoa4JVnMV6mZlJKk2sBLt90s7G0Gd0Mlknc7kxEn3nuDPNZRta7O2uy8oLcZLVT+4sqNZHQ=="
     },
     "spdy": {
       "version": "4.0.2",
@@ -13580,6 +13673,11 @@
         "readable-stream": "^2.0.2"
       },
       "dependencies": {
+        "isarray": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+          "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
+        },
         "readable-stream": {
           "version": "2.3.7",
           "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
@@ -13594,6 +13692,11 @@
             "util-deprecate": "~1.0.1"
           }
         },
+        "safe-buffer": {
+          "version": "5.1.2",
+          "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+          "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
+        },
         "string_decoder": {
           "version": "1.1.1",
           "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
@@ -13625,6 +13728,11 @@
         "xtend": "^4.0.0"
       },
       "dependencies": {
+        "isarray": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+          "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
+        },
         "readable-stream": {
           "version": "2.3.7",
           "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
@@ -13639,6 +13747,11 @@
             "util-deprecate": "~1.0.1"
           }
         },
+        "safe-buffer": {
+          "version": "5.1.2",
+          "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+          "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
+        },
         "string_decoder": {
           "version": "1.1.1",
           "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
@@ -13674,28 +13787,13 @@
       "integrity": "sha512-n3sPwynL1nwKi3WJ6AIsClwBMa0zTi54fn2oLU6ndfTSIO05xaznjSf15PcBZU6FNWbmN5Q6cxT4V5hGvB4taw=="
     },
     "string-width": {
-      "version": "3.1.0",
-      "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
-      "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
+      "version": "4.2.0",
+      "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz",
+      "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==",
       "requires": {
-        "emoji-regex": "^7.0.1",
-        "is-fullwidth-code-point": "^2.0.0",
-        "strip-ansi": "^5.1.0"
-      },
-      "dependencies": {
-        "ansi-regex": {
-          "version": "4.1.0",
-          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
-          "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg=="
-        },
-        "strip-ansi": {
-          "version": "5.2.0",
-          "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
-          "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
-          "requires": {
-            "ansi-regex": "^4.1.0"
-          }
-        }
+        "emoji-regex": "^8.0.0",
+        "is-fullwidth-code-point": "^3.0.0",
+        "strip-ansi": "^6.0.0"
       }
     },
     "string.prototype.matchall": {
@@ -13736,13 +13834,6 @@
       "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
       "requires": {
         "safe-buffer": "~5.2.0"
-      },
-      "dependencies": {
-        "safe-buffer": {
-          "version": "5.2.1",
-          "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
-          "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="
-        }
       }
     },
     "stringify-object": {
@@ -13937,14 +14028,37 @@
       "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw=="
     },
     "table": {
-      "version": "5.4.6",
-      "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz",
-      "integrity": "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==",
+      "version": "6.0.6",
+      "resolved": "https://registry.npmjs.org/table/-/table-6.0.6.tgz",
+      "integrity": "sha512-OInCtPmDNieVBkVFi6C8RwU2S2H0h8mF3e3TQK4nreaUNCpooQUkI+A/KuEkm5FawfhWIfNqG+qfelVVR+V00g==",
       "requires": {
-        "ajv": "^6.10.2",
-        "lodash": "^4.17.14",
-        "slice-ansi": "^2.1.0",
-        "string-width": "^3.0.0"
+        "ajv": "^7.0.2",
+        "lodash": "^4.17.20",
+        "slice-ansi": "^4.0.0",
+        "string-width": "^4.2.0"
+      },
+      "dependencies": {
+        "ajv": {
+          "version": "7.0.3",
+          "resolved": "https://registry.npmjs.org/ajv/-/ajv-7.0.3.tgz",
+          "integrity": "sha512-R50QRlXSxqXcQP5SvKUrw8VZeypvo12i2IX0EeR5PiZ7bEKeHWgzgo264LDadUsCU42lTJVhFikTqJwNeH34gQ==",
+          "requires": {
+            "fast-deep-equal": "^3.1.1",
+            "json-schema-traverse": "^1.0.0",
+            "require-from-string": "^2.0.2",
+            "uri-js": "^4.2.2"
+          }
+        },
+        "fast-deep-equal": {
+          "version": "3.1.3",
+          "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+          "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
+        },
+        "json-schema-traverse": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
+          "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="
+        }
       }
     },
     "tapable": {
@@ -14091,9 +14205,9 @@
           "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
         },
         "terser": {
-          "version": "5.5.0",
-          "resolved": "https://registry.npmjs.org/terser/-/terser-5.5.0.tgz",
-          "integrity": "sha512-eopt1Gf7/AQyPhpygdKePTzaet31TvQxXvrf7xYUvD/d8qkCJm4SKPDzu+GHK5ZaYTn8rvttfqaZc3swK21e5g==",
+          "version": "5.5.1",
+          "resolved": "https://registry.npmjs.org/terser/-/terser-5.5.1.tgz",
+          "integrity": "sha512-6VGWZNVP2KTUcltUQJ25TtNjx/XgdDsBDKGt8nN0MpydU36LmbPPcMBd2kmtZNNGVVDLg44k7GKeHHj+4zPIBQ==",
           "requires": {
             "commander": "^2.20.0",
             "source-map": "~0.7.2",
@@ -14149,6 +14263,11 @@
         "xtend": "~4.0.1"
       },
       "dependencies": {
+        "isarray": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+          "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
+        },
         "readable-stream": {
           "version": "2.3.7",
           "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
@@ -14163,6 +14282,11 @@
             "util-deprecate": "~1.0.1"
           }
         },
+        "safe-buffer": {
+          "version": "5.1.2",
+          "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+          "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
+        },
         "string_decoder": {
           "version": "1.1.1",
           "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
@@ -14383,9 +14507,9 @@
       }
     },
     "typescript": {
-      "version": "4.1.2",
-      "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.1.2.tgz",
-      "integrity": "sha512-thGloWsGH3SOxv1SoY7QojKi0tc+8FnOmiarEGMbd/lar7QOEd3hvlx3Fp5y6FlDUGl9L+pd4n2e+oToGMmhRQ=="
+      "version": "4.1.3",
+      "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.1.3.tgz",
+      "integrity": "sha512-B3ZIOf1IKeH2ixgHhj6la6xdwR9QrLC5d1VKeCSY4tvkqhF2eqd9O7txNlS0PO3GrBAFIdr3L1ndNwteUbZLYg=="
     },
     "unicode-canonical-property-names-ecmascript": {
       "version": "1.0.4",
@@ -14504,6 +14628,11 @@
           "version": "0.1.4",
           "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz",
           "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E="
+        },
+        "isarray": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+          "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
         }
       }
     },
@@ -14649,9 +14778,9 @@
       "integrity": "sha512-gTpR5XQNKFwOd4clxfnhaqvfqMpqEwr4tOtCyz4MtYZX2JYhfr1JvBFKdS+7K/9rfpZR3VLX+YWBbKoxCgS43Q=="
     },
     "v8-to-istanbul": {
-      "version": "7.0.0",
-      "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-7.0.0.tgz",
-      "integrity": "sha512-fLL2rFuQpMtm9r8hrAV2apXX/WqHJ6+IC4/eQVdMDGBUgH/YMV4Gv3duk3kjmyg6uiQWBAA9nJwue4iJUOkHeA==",
+      "version": "7.1.0",
+      "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-7.1.0.tgz",
+      "integrity": "sha512-uXUVqNUCLa0AH1vuVxzi+MI4RfxEOKt9pBgKwHbgH7st8Kv2P1m+jvWNnektzBh5QShF3ODgKmUFCf38LnVz1g==",
       "requires": {
         "@types/istanbul-lib-coverage": "^2.0.1",
         "convert-source-map": "^1.6.0",
@@ -14699,11 +14828,6 @@
         "extsprintf": "^1.2.0"
       }
     },
-    "vfile-location": {
-      "version": "3.2.0",
-      "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-3.2.0.tgz",
-      "integrity": "sha512-aLEIZKv/oxuCDZ8lkJGhuhztf/BW4M+iHdCwglA/eWc+vtuRFJj8EtgceYFX4LRjOhCAAiNHsKGssC6onJ+jbA=="
-    },
     "vm-browserify": {
       "version": "1.1.2",
       "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz",
@@ -14908,6 +15032,12 @@
             }
           }
         },
+        "isarray": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+          "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
+          "optional": true
+        },
         "micromatch": {
           "version": "3.1.10",
           "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz",
@@ -14955,6 +15085,12 @@
             "readable-stream": "^2.0.2"
           }
         },
+        "safe-buffer": {
+          "version": "5.1.2",
+          "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+          "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
+          "optional": true
+        },
         "string_decoder": {
           "version": "1.1.1",
           "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
@@ -15177,6 +15313,14 @@
             "to-regex": "^3.0.2"
           }
         },
+        "rimraf": {
+          "version": "2.7.1",
+          "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
+          "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
+          "requires": {
+            "glob": "^7.1.3"
+          }
+        },
         "schema-utils": {
           "version": "1.0.0",
           "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz",
@@ -15236,9 +15380,9 @@
       }
     },
     "webpack-dev-middleware": {
-      "version": "3.7.2",
-      "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-3.7.2.tgz",
-      "integrity": "sha512-1xC42LxbYoqLNAhV6YzTYacicgMZQTqRd27Sim9wn5hJrX3I5nxYy1SxSd4+gjUFsz1dQFj+yEe6zEVmSkeJjw==",
+      "version": "3.7.3",
+      "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-3.7.3.tgz",
+      "integrity": "sha512-djelc/zGiz9nZj/U7PTBi2ViorGJXEWo/3ltkPbDyxCXhhEXkW0ce99falaok4TPj+AsxLiXJR0EBOb0zh9fKQ==",
       "requires": {
         "memory-fs": "^0.4.1",
         "mime": "^2.4.4",
@@ -15248,9 +15392,9 @@
       },
       "dependencies": {
         "mime": {
-          "version": "2.4.6",
-          "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.6.tgz",
-          "integrity": "sha512-RZKhC3EmpBchfTGBVb8fb+RL2cWyw/32lshnsETttkBAyAUXSGHxbEJWWRXc751DrIxG1q04b8QwMbAwkRPpUA=="
+          "version": "2.4.7",
+          "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.7.tgz",
+          "integrity": "sha512-dhNd1uA2u397uQk3Nv5LM4lm93WYDUXFn3Fu291FJerns4jyTudqhIWe4W04YLy7Uk1tm1Ore04NpjRvQp/NPA=="
         }
       }
     },
@@ -15420,6 +15564,11 @@
           "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
           "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
         },
+        "emoji-regex": {
+          "version": "7.0.3",
+          "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz",
+          "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA=="
+        },
         "fill-range": {
           "version": "4.0.0",
           "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz",
@@ -15501,6 +15650,11 @@
             "binary-extensions": "^1.0.0"
           }
         },
+        "is-fullwidth-code-point": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
+          "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8="
+        },
         "is-number": {
           "version": "3.0.0",
           "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
@@ -15519,6 +15673,11 @@
             }
           }
         },
+        "isarray": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+          "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
+        },
         "locate-path": {
           "version": "3.0.0",
           "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
@@ -15598,6 +15757,11 @@
           "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz",
           "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g="
         },
+        "safe-buffer": {
+          "version": "5.1.2",
+          "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+          "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
+        },
         "schema-utils": {
           "version": "1.0.0",
           "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz",
@@ -15613,6 +15777,31 @@
           "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
           "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
         },
+        "string-width": {
+          "version": "3.1.0",
+          "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
+          "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
+          "requires": {
+            "emoji-regex": "^7.0.1",
+            "is-fullwidth-code-point": "^2.0.0",
+            "strip-ansi": "^5.1.0"
+          },
+          "dependencies": {
+            "ansi-regex": {
+              "version": "4.1.0",
+              "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
+              "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg=="
+            },
+            "strip-ansi": {
+              "version": "5.2.0",
+              "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
+              "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
+              "requires": {
+                "ansi-regex": "^4.1.0"
+              }
+            }
+          }
+        },
         "string_decoder": {
           "version": "1.1.1",
           "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
@@ -16048,28 +16237,6 @@
         "ansi-styles": "^4.0.0",
         "string-width": "^4.1.0",
         "strip-ansi": "^6.0.0"
-      },
-      "dependencies": {
-        "emoji-regex": {
-          "version": "8.0.0",
-          "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
-          "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
-        },
-        "is-fullwidth-code-point": {
-          "version": "3.0.0",
-          "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
-          "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="
-        },
-        "string-width": {
-          "version": "4.2.0",
-          "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz",
-          "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==",
-          "requires": {
-            "emoji-regex": "^8.0.0",
-            "is-fullwidth-code-point": "^3.0.0",
-            "strip-ansi": "^6.0.0"
-          }
-        }
       }
     },
     "wrappy": {
@@ -16077,14 +16244,6 @@
       "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
       "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
     },
-    "write": {
-      "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz",
-      "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==",
-      "requires": {
-        "mkdirp": "^0.5.1"
-      }
-    },
     "write-file-atomic": {
       "version": "3.0.3",
       "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz",
@@ -16097,9 +16256,9 @@
       }
     },
     "ws": {
-      "version": "7.4.0",
-      "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.0.tgz",
-      "integrity": "sha512-kyFwXuV/5ymf+IXhS6f0+eAFvydbaBW3zjpT6hUdAh/hbVjTIB5EHBGi0bPoCLSK2wcuz3BrEkB9LrYv1Nm4NQ=="
+      "version": "7.4.2",
+      "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.2.tgz",
+      "integrity": "sha512-T4tewALS3+qsrpGI/8dqNMLIVdq/g/85U98HPMa6F0m6xTbvhXU6RCQLqPH3+SlomNV/LdY6RXEbBpMH6EOJnA=="
     },
     "xml-name-validator": {
       "version": "3.0.0",
@@ -16117,9 +16276,9 @@
       "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ=="
     },
     "y18n": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz",
-      "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w=="
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.1.tgz",
+      "integrity": "sha512-wNcy4NvjMYL8gogWWYAO7ZFWFfHcbdbE57tZO8e4cbpj8tfUcwrwqSl3ad8HxpYWCdXcJUCeKKZS62Av1affwQ=="
     },
     "yallist": {
       "version": "4.0.0",
@@ -16147,28 +16306,6 @@
         "which-module": "^2.0.0",
         "y18n": "^4.0.0",
         "yargs-parser": "^18.1.2"
-      },
-      "dependencies": {
-        "emoji-regex": {
-          "version": "8.0.0",
-          "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
-          "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
-        },
-        "is-fullwidth-code-point": {
-          "version": "3.0.0",
-          "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
-          "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="
-        },
-        "string-width": {
-          "version": "4.2.0",
-          "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz",
-          "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==",
-          "requires": {
-            "emoji-regex": "^8.0.0",
-            "is-fullwidth-code-point": "^3.0.0",
-            "strip-ansi": "^6.0.0"
-          }
-        }
       }
     },
     "yargs-parser": {
diff --git a/package.json b/package.json
index bd0a5c4..a945e11 100644
--- a/package.json
+++ b/package.json
@@ -3,27 +3,29 @@
   "version": "0.1.0",
   "private": true,
   "dependencies": {
-    "@testing-library/jest-dom": "^5.11.6",
+    "@testing-library/jest-dom": "^5.11.8",
     "@testing-library/react": "^11.2.2",
-    "@testing-library/user-event": "^12.2.2",
-    "@types/jest": "^26.0.15",
-    "@types/node": "^14.14.10",
+    "@testing-library/user-event": "^12.6.0",
+    "@types/jest": "^26.0.19",
+    "@types/node": "^14.14.19",
     "@types/react": "^17.0.0",
     "@types/react-dom": "^17.0.0",
-    "@types/react-router": "^5.1.8",
-    "@types/react-router-dom": "^5.1.6",
-    "dashjs": "^3.1.3",
+    "@types/react-router": "^5.1.9",
+    "@types/react-router-dom": "^5.1.7",
+    "dashjs": "^3.2.0",
     "immer": "^8.0.0",
+    "imsc": "^1.1.1",
+    "libjass": "^0.11.0",
     "react": "^17.0.1",
     "react-dom": "^17.0.1",
     "react-jss": "^10.5.0",
     "react-router": "^5.2.0",
     "react-router-dom": "^5.2.0",
     "react-scripts": "4.0.1",
-    "react-sweet-state": "^2.4.4",
+    "react-sweet-state": "^2.5.1",
     "resize-observer-polyfill": "^1.5.1",
     "sax": "1.2.4",
-    "typescript": "^4.1.2"
+    "typescript": "^4.1.3"
   },
   "scripts": {
     "start": "react-scripts start",
diff --git a/src/global.d.ts b/src/global.d.ts
deleted file mode 100644
index 3da6d5d..0000000
--- a/src/global.d.ts
+++ /dev/null
@@ -1,57 +0,0 @@
-declare module "imsc" {
-    export interface TtmlDocument {
-        getMediaTimeEvents(): number[],
-        getMediaTimeRange(): number[]
-    }
-
-    export type ISD = unknown;
-    export type ISDState = unknown;
-
-    export interface MetadataHandler {
-        onOpenTag(ns: string, name: string, attributes: Attribute[]): void,
-
-        onCloseTag(): void,
-
-        onText(contents: string): void,
-    }
-
-    export interface Attribute {
-        uri: string,
-        name: string,
-        value: string
-    }
-
-    export interface ErrorHandler {
-        info(error: string): boolean
-
-        warn(error: string): boolean
-
-        error(error: string): boolean
-
-        fatal(error: string): boolean
-    }
-
-    export function fromXML(
-        xmlstring: string,
-        errorHandler?: ErrorHandler,
-        metadataHandler?: MetadataHandler
-    ): TtmlDocument;
-
-    export function generateISD(
-        tt: TtmlDocument,
-        offset?: number,
-        errorHandler?: ErrorHandler,
-    ): ISD;
-
-    export function renderHTML(
-        isd: ISD,
-        element: HTMLElement,
-        imgResolver?: (backgroundUri: string) => string,
-        height?: number,
-        width?: number,
-        displayForcedOnlyMode?: boolean,
-        errorHandler?: ErrorHandler,
-        previousISDState?: ISDState,
-        enableRollUp?: boolean
-    ): ISDState;
-}
diff --git a/src/routes/player/Player.tsx b/src/routes/player/Player.tsx
index 7a5b1f5..ab2c2c0 100644
--- a/src/routes/player/Player.tsx
+++ b/src/routes/player/Player.tsx
@@ -14,9 +14,9 @@ import {PlayerApi} from "./video/PlayerApi";
 import {useAudioTracks} from "../../util/media/useAudioTracks";
 import {useDebugInfo} from "../../util/media/useDebugInfo";
 import {Subtitle} from "../../api/models/Subtitle";
-import {TtmlRenderer} from "./subtitles/TtmlRenderer";
 import {MousePosition} from "../../util/mouse/MousePosition";
 import {VideoProvider} from "./video/VideoContext";
+import {SubtitleRenderer} from "./subtitles/SubtitleRenderer";
 
 interface Props {
     meta: ContentMeta,
@@ -67,7 +67,7 @@ export function Player(
                             autoPlay={true}
                             ref={setPlayerApi}
                         />
-                        <TtmlRenderer
+                        <SubtitleRenderer
                             className={classes.subtitleCanvas}
                             videoElement={playerApi?.getVideoElement() || null}
                             subtitle={subtitle}
diff --git a/src/routes/player/subtitles/SubtitleRenderer.tsx b/src/routes/player/subtitles/SubtitleRenderer.tsx
index dc33205..72d1546 100644
--- a/src/routes/player/subtitles/SubtitleRenderer.tsx
+++ b/src/routes/player/subtitles/SubtitleRenderer.tsx
@@ -15,7 +15,7 @@ export function SubtitleRenderer(
     switch (props.subtitle?.format) {
         case "ttml":
             return (<TtmlRenderer {...props} />);
-        //case "ass": return (<AssRendered {...props} />);
+        //case "ass": return (<AssRenderer {...props} />);
         default:
             return (<Fragment/>);
     }
diff --git a/src/routes/player/subtitles/TtmlHelper.ts b/src/routes/player/subtitles/TtmlHelper.ts
index d207048..6e9e945 100644
--- a/src/routes/player/subtitles/TtmlHelper.ts
+++ b/src/routes/player/subtitles/TtmlHelper.ts
@@ -1,4 +1,4 @@
-import {fromXML, generateISD, renderHTML, TtmlDocument} from "../../../util/ttml/ismc";
+import {fromXML, generateISD, renderHTML, TtmlDocument} from "imsc";
 
 interface TtmlState {
     target: HTMLElement | null,
diff --git a/src/util/ttml/doc.js b/src/util/ttml/doc.js
deleted file mode 100644
index 774e356..0000000
--- a/src/util/ttml/doc.js
+++ /dev/null
@@ -1,1097 +0,0 @@
-/* 
- * Copyright (c) 2016, Pierre-Anthony Lemieux <pal@sandflow.com>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * * Redistributions of source code must retain the above copyright notice, this
- *   list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright notice,
- *   this list of conditions and the following disclaimer in the documentation
- *   and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-import sax from 'sax';
-import * as imscNames from './names';
-import * as imscStyles from './styles';
-import * as imscUtils from './utils';
-import {reportError, reportFatal, reportWarning} from "./utils";
-
-export function fromXML(xmlstring, errorHandler, metadataHandler) {
-    var p = sax.parser(true, {xmlns: true});
-    var estack = [];
-    var xmllangstack = [];
-    var xmlspacestack = [];
-    var metadata_depth = 0;
-    var doc = null;
-    p.onclosetag = function (node) {
-        if (estack[0] instanceof Styling) {
-            /* flatten chained referential styling */
-            for (var sid in estack[0].styles) {
-                mergeChainedStyles(estack[0], estack[0].styles[sid], errorHandler);
-            }
-        } else if (estack[0] instanceof P || estack[0] instanceof Span) {
-            /* merge anonymous spans */
-            if (estack[0].contents.length > 1) {
-                var cs = [estack[0].contents[0]];
-                var c;
-                for (c = 1; c < estack[0].contents.length; c++) {
-                    if (estack[0].contents[c] instanceof AnonymousSpan &&
-                        cs[cs.length - 1] instanceof AnonymousSpan) {
-                        cs[cs.length - 1].text += estack[0].contents[c].text;
-                    } else {
-                        cs.push(estack[0].contents[c]);
-                    }
-                }
-                estack[0].contents = cs;
-            }
-            // remove redundant nested anonymous spans (9.3.3(1)(c))
-            if (estack[0] instanceof Span &&
-                estack[0].contents.length === 1 &&
-                estack[0].contents[0] instanceof AnonymousSpan) {
-                estack[0].text = estack[0].contents[0].text;
-                delete estack[0].contents;
-            }
-        } else if (estack[0] instanceof ForeignElement) {
-            if (estack[0].node.uri === imscNames.ns_tt &&
-                estack[0].node.local === 'metadata') {
-                /* leave the metadata element */
-                metadata_depth--;
-            } else if (metadata_depth > 0 &&
-                metadataHandler &&
-                'onCloseTag' in metadataHandler) {
-                /* end of child of metadata element */
-                metadataHandler.onCloseTag();
-            }
-        }
-        // TODO: delete stylerefs?
-        // maintain the xml:space stack
-        xmlspacestack.shift();
-        // maintain the xml:lang stack
-        xmllangstack.shift();
-        // prepare for the next element
-        estack.shift();
-    };
-    p.ontext = function (str) {
-        if (estack[0] === undefined) {
-            /* ignoring text outside of elements */
-        } else if (estack[0] instanceof Span || estack[0] instanceof P) {
-            /* ignore children text nodes in ruby container spans */
-            if (estack[0] instanceof Span) {
-                var ruby = estack[0].styleAttrs[imscStyles.byName.ruby.qname];
-                if (ruby === 'container' || ruby === 'textContainer' || ruby === 'baseContainer') {
-                    return;
-                }
-            }
-            /* create an anonymous span */
-            var s = new AnonymousSpan();
-            s.initFromText(doc, estack[0], str, xmlspacestack[0], errorHandler);
-            estack[0].contents.push(s);
-        } else if (estack[0] instanceof ForeignElement &&
-            metadata_depth > 0 &&
-            metadataHandler &&
-            'onText' in metadataHandler) {
-            /* text node within a child of metadata element */
-            metadataHandler.onText(str);
-        }
-    };
-    p.onopentag = function (node) {
-        // maintain the xml:space stack
-        var xmlspace = node.attributes["xml:space"];
-        if (xmlspace) {
-            xmlspacestack.unshift(xmlspace.value);
-        } else {
-            if (xmlspacestack.length === 0) {
-                xmlspacestack.unshift("default");
-            } else {
-                xmlspacestack.unshift(xmlspacestack[0]);
-            }
-        }
-        /* maintain the xml:lang stack */
-        var xmllang = node.attributes["xml:lang"];
-        if (xmllang) {
-            xmllangstack.unshift(xmllang.value);
-        } else {
-            if (xmllangstack.length === 0) {
-                xmllangstack.unshift("");
-            } else {
-                xmllangstack.unshift(xmllangstack[0]);
-            }
-        }
-        /* process the element */
-        if (node.uri === imscNames.ns_tt) {
-            if (node.local === 'tt') {
-                if (doc !== null) {
-                    reportFatal(errorHandler, "Two <tt> elements at (" + this.line + "," + this.column + ")");
-                }
-                doc = new TT();
-                doc.initFromNode(node, errorHandler);
-                estack.unshift(doc);
-            } else if (node.local === 'head') {
-                if (!(estack[0] instanceof TT)) {
-                    reportFatal(errorHandler, "Parent of <head> element is not <tt> at (" + this.line + "," + this.column + ")");
-                }
-                estack.unshift(doc.head);
-            } else if (node.local === 'styling') {
-                if (!(estack[0] instanceof Head)) {
-                    reportFatal(errorHandler, "Parent of <styling> element is not <head> at (" + this.line + "," + this.column + ")");
-                }
-                estack.unshift(doc.head.styling);
-            } else if (node.local === 'style') {
-                var s;
-                if (estack[0] instanceof Styling) {
-                    s = new Style();
-                    s.initFromNode(node, errorHandler);
-                    /* ignore <style> element missing @id */
-                    if (!s.id) {
-                        reportError(errorHandler, "<style> element missing @id attribute");
-                    } else {
-                        doc.head.styling.styles[s.id] = s;
-                    }
-                    estack.unshift(s);
-                } else if (estack[0] instanceof Region) {
-                    /* nested styles can be merged with specified styles
-                     * immediately, with lower priority
-                     * (see 8.4.4.2(3) at TTML1 )
-                     */
-                    s = new Style();
-                    s.initFromNode(node, errorHandler);
-                    mergeStylesIfNotPresent(s.styleAttrs, estack[0].styleAttrs);
-                    estack.unshift(s);
-                } else {
-                    reportFatal(errorHandler, "Parent of <style> element is not <styling> or <region> at (" + this.line + "," + this.column + ")");
-                }
-            } else if (node.local === 'initial') {
-                var ini;
-                if (estack[0] instanceof Styling) {
-                    ini = new Initial();
-                    ini.initFromNode(node, errorHandler);
-                    for (var qn in ini.styleAttrs) {
-                        doc.head.styling.initials[qn] = ini.styleAttrs[qn];
-                    }
-                    estack.unshift(ini);
-                } else {
-                    reportFatal(errorHandler, "Parent of <initial> element is not <styling> at (" + this.line + "," + this.column + ")");
-                }
-            } else if (node.local === 'layout') {
-                if (!(estack[0] instanceof Head)) {
-                    reportFatal(errorHandler, "Parent of <layout> element is not <head> at " + this.line + "," + this.column + ")");
-                }
-                estack.unshift(doc.head.layout);
-            } else if (node.local === 'region') {
-                if (!(estack[0] instanceof Layout)) {
-                    reportFatal(errorHandler, "Parent of <region> element is not <layout> at " + this.line + "," + this.column + ")");
-                }
-                var r = new Region();
-                r.initFromNode(doc, node, errorHandler);
-                if (!r.id || r.id in doc.head.layout.regions) {
-                    reportError(errorHandler, "Ignoring <region> with duplicate or missing @id at " + this.line + "," + this.column + ")");
-                } else {
-                    doc.head.layout.regions[r.id] = r;
-                }
-                estack.unshift(r);
-            } else if (node.local === 'body') {
-                if (!(estack[0] instanceof TT)) {
-                    reportFatal(errorHandler, "Parent of <body> element is not <tt> at " + this.line + "," + this.column + ")");
-                }
-                if (doc.body !== null) {
-                    reportFatal(errorHandler, "Second <body> element at " + this.line + "," + this.column + ")");
-                }
-                var b = new Body();
-                b.initFromNode(doc, node, errorHandler);
-                doc.body = b;
-                estack.unshift(b);
-            } else if (node.local === 'div') {
-                if (!(estack[0] instanceof Div || estack[0] instanceof Body)) {
-                    reportFatal(errorHandler, "Parent of <div> element is not <body> or <div> at " + this.line + "," + this.column + ")");
-                }
-                var d = new Div();
-                d.initFromNode(doc, estack[0], node, errorHandler);
-                /* transform smpte:backgroundImage to TTML2 image element */
-                var bi = d.styleAttrs[imscStyles.byName.backgroundImage.qname];
-                if (bi) {
-                    d.contents.push(new Image(bi));
-                    delete d.styleAttrs[imscStyles.byName.backgroundImage.qname];
-                }
-                estack[0].contents.push(d);
-                estack.unshift(d);
-            } else if (node.local === 'image') {
-                if (!(estack[0] instanceof Div)) {
-                    reportFatal(errorHandler, "Parent of <image> element is not <div> at " + this.line + "," + this.column + ")");
-                }
-                var img = new Image();
-                img.initFromNode(doc, estack[0], node, errorHandler);
-                estack[0].contents.push(img);
-                estack.unshift(img);
-            } else if (node.local === 'p') {
-                if (!(estack[0] instanceof Div)) {
-                    reportFatal(errorHandler, "Parent of <p> element is not <div> at " + this.line + "," + this.column + ")");
-                }
-                var p = new P();
-                p.initFromNode(doc, estack[0], node, errorHandler);
-                estack[0].contents.push(p);
-                estack.unshift(p);
-            } else if (node.local === 'span') {
-                if (!(estack[0] instanceof Span || estack[0] instanceof P)) {
-                    reportFatal(errorHandler, "Parent of <span> element is not <span> or <p> at " + this.line + "," + this.column + ")");
-                }
-                var ns = new Span();
-                ns.initFromNode(doc, estack[0], node, xmlspacestack[0], errorHandler);
-                estack[0].contents.push(ns);
-                estack.unshift(ns);
-            } else if (node.local === 'br') {
-                if (!(estack[0] instanceof Span || estack[0] instanceof P)) {
-                    reportFatal(errorHandler, "Parent of <br> element is not <span> or <p> at " + this.line + "," + this.column + ")");
-                }
-                var nb = new Br();
-                nb.initFromNode(doc, estack[0], node, errorHandler);
-                estack[0].contents.push(nb);
-                estack.unshift(nb);
-            } else if (node.local === 'set') {
-                if (!(estack[0] instanceof Span ||
-                    estack[0] instanceof P ||
-                    estack[0] instanceof Div ||
-                    estack[0] instanceof Body ||
-                    estack[0] instanceof Region ||
-                    estack[0] instanceof Br)) {
-                    reportFatal(errorHandler, "Parent of <set> element is not a content element or a region at " + this.line + "," + this.column + ")");
-                }
-                var st = new Set();
-                st.initFromNode(doc, estack[0], node, errorHandler);
-                estack[0].sets.push(st);
-                estack.unshift(st);
-            } else {
-                /* element in the TT namespace, but not a content element */
-                estack.unshift(new ForeignElement(node));
-            }
-        } else {
-            /* ignore elements not in the TTML namespace unless in metadata element */
-            estack.unshift(new ForeignElement(node));
-        }
-        /* handle metadata callbacks */
-        if (estack[0] instanceof ForeignElement) {
-            if (node.uri === imscNames.ns_tt &&
-                node.local === 'metadata') {
-                /* enter the metadata element */
-                metadata_depth++;
-            } else if (
-                metadata_depth > 0 &&
-                metadataHandler &&
-                'onOpenTag' in metadataHandler
-            ) {
-                /* start of child of metadata element */
-                var attrs = [];
-                for (var a in node.attributes) {
-                    attrs[node.attributes[a].uri + " " + node.attributes[a].local] =
-                        {
-                            uri: node.attributes[a].uri,
-                            local: node.attributes[a].local,
-                            value: node.attributes[a].value
-                        };
-                }
-                metadataHandler.onOpenTag(node.uri, node.local, attrs);
-            }
-        }
-    };
-    // parse the document
-    p.write(xmlstring).close();
-    // all referential styling has been flatten, so delete styles
-    delete doc.head.styling.styles;
-    // create default region if no regions specified
-    var hasRegions = false;
-    /* AFAIK the only way to determine whether an object has members */
-    for (var i in doc.head.layout.regions) {
-        if (doc.head.layout.regions.hasOwnProperty(i)) {
-            hasRegions = true;
-            break;
-        }
-    }
-    if (!hasRegions) {
-        /* create default region */
-        var dr = Region.prototype.createDefaultRegion();
-        doc.head.layout.regions[dr.id] = dr;
-    }
-    /* resolve desired timing for regions */
-    for (var region_i in doc.head.layout.regions) {
-        resolveTiming(doc, doc.head.layout.regions[region_i], null, null);
-    }
-    /* resolve desired timing for content elements */
-    if (doc.body) {
-        resolveTiming(doc, doc.body, null, null);
-    }
-    /* remove undefined spans in ruby containers */
-    if (doc.body) {
-        cleanRubyContainers(doc.body);
-    }
-    return doc;
-};
-
-function cleanRubyContainers(element) {
-    if (!('contents' in element)) return;
-    var rubyval = 'styleAttrs' in element ? element.styleAttrs[imscStyles.byName.ruby.qname] : null;
-    var isrubycontainer = (element.kind === 'span' && (rubyval === "container" || rubyval === "textContainer" || rubyval === "baseContainer"));
-    for (var i = element.contents.length - 1; i >= 0; i--) {
-        if (isrubycontainer && !('styleAttrs' in element.contents[i] && imscStyles.byName.ruby.qname in element.contents[i].styleAttrs)) {
-            /* prune undefined <span> in ruby containers */
-            delete element.contents[i];
-        } else {
-            cleanRubyContainers(element.contents[i]);
-        }
-    }
-}
-
-function resolveTiming(doc, element, prev_sibling, parent) {
-    /* are we in a seq container? */
-    var isinseq = parent && parent.timeContainer === "seq";
-    /* determine implicit begin */
-    var implicit_begin = 0; /* default */
-    if (parent) {
-        if (isinseq && prev_sibling) {
-            /*
-             * if seq time container, offset from the previous sibling end
-             */
-            implicit_begin = prev_sibling.end;
-        } else {
-            implicit_begin = parent.begin;
-        }
-    }
-    /* compute desired begin */
-    element.begin = element.explicit_begin ? element.explicit_begin + implicit_begin : implicit_begin;
-    /* determine implicit end */
-    var implicit_end = element.begin;
-    var s = null;
-    for (var set_i in element.sets) {
-        resolveTiming(doc, element.sets[set_i], s, element);
-        if (element.timeContainer === "seq") {
-            implicit_end = element.sets[set_i].end;
-        } else {
-            implicit_end = Math.max(implicit_end, element.sets[set_i].end);
-        }
-        s = element.sets[set_i];
-    }
-    if (!('contents' in element)) {
-        /* anonymous spans and regions and <set> and <br>s and spans with only children text nodes */
-        if (isinseq) {
-            /* in seq container, implicit duration is zero */
-            implicit_end = element.begin;
-        } else {
-            /* in par container, implicit duration is indefinite */
-            implicit_end = Number.POSITIVE_INFINITY;
-        }
-    } else {
-        for (var content_i in element.contents) {
-            resolveTiming(doc, element.contents[content_i], s, element);
-            if (element.timeContainer === "seq") {
-                implicit_end = element.contents[content_i].end;
-            } else {
-                implicit_end = Math.max(implicit_end, element.contents[content_i].end);
-            }
-            s = element.contents[content_i];
-        }
-    }
-    /* determine desired end */
-    /* it is never made really clear in SMIL that the explicit end is offset by the implicit begin */
-    if (element.explicit_end !== null && element.explicit_dur !== null) {
-        element.end = Math.min(element.begin + element.explicit_dur, implicit_begin + element.explicit_end);
-    } else if (element.explicit_end === null && element.explicit_dur !== null) {
-        element.end = element.begin + element.explicit_dur;
-    } else if (element.explicit_end !== null && element.explicit_dur === null) {
-        element.end = implicit_begin + element.explicit_end;
-    } else {
-        element.end = implicit_end;
-    }
-    delete element.explicit_begin;
-    delete element.explicit_dur;
-    delete element.explicit_end;
-    doc._registerEvent(element);
-}
-
-function ForeignElement(node) {
-    this.node = node;
-}
-
-function TT() {
-    this.events = [];
-    this.head = new Head();
-    this.body = null;
-}
-
-TT.prototype.initFromNode = function (node, errorHandler) {
-    /* compute cell resolution */
-    var cr = extractCellResolution(node, errorHandler);
-    this.cellLength = {
-        'h': new imscUtils.ComputedLength(0, 1 / cr.h),
-        'w': new imscUtils.ComputedLength(1 / cr.w, 0)
-    };
-    /* extract frame rate and tick rate */
-    var frtr = extractFrameAndTickRate(node, errorHandler);
-    this.effectiveFrameRate = frtr.effectiveFrameRate;
-    this.tickRate = frtr.tickRate;
-    /* extract aspect ratio */
-    this.aspectRatio = extractAspectRatio(node, errorHandler);
-    /* check timebase */
-    var attr = findAttribute(node, imscNames.ns_ttp, "timeBase");
-    if (attr !== null && attr !== "media") {
-        reportFatal(errorHandler, "Unsupported time base");
-    }
-    /* retrieve extent */
-    var e = extractExtent(node, errorHandler);
-    if (e === null) {
-        this.pxLength = {
-            'h': null,
-            'w': null
-        };
-    } else {
-        if (e.h.unit !== "px" || e.w.unit !== "px") {
-            reportFatal(errorHandler, "Extent on TT must be in px or absent");
-        }
-        this.pxLength = {
-            'h': new imscUtils.ComputedLength(0, 1 / e.h.value),
-            'w': new imscUtils.ComputedLength(1 / e.w.value, 0)
-        };
-    }
-    /** set root container dimensions to (1, 1) arbitrarily
-     * the root container is mapped to actual dimensions at rendering
-     **/
-    this.dimensions = {
-        'h': new imscUtils.ComputedLength(0, 1),
-        'w': new imscUtils.ComputedLength(1, 0)
-    };
-};
-/* register a temporal events */
-TT.prototype._registerEvent = function (elem) {
-    /* skip if begin is not < then end */
-    if (elem.end <= elem.begin)
-        return;
-    /* index the begin time of the event */
-    var b_i = indexOf(this.events, elem.begin);
-    if (!b_i.found) {
-        this.events.splice(b_i.index, 0, elem.begin);
-    }
-    /* index the end time of the event */
-    if (elem.end !== Number.POSITIVE_INFINITY) {
-        var e_i = indexOf(this.events, elem.end);
-        if (!e_i.found) {
-            this.events.splice(e_i.index, 0, elem.end);
-        }
-    }
-};
-/*
- * Retrieves the range of ISD times covered by the document
- *
- * @returns {Array} Array of two elements: min_begin_time and max_begin_time
- *
- */
-TT.prototype.getMediaTimeRange = function () {
-    return [this.events[0], this.events[this.events.length - 1]];
-};
-/*
- * Returns list of ISD begin times
- *
- * @returns {Array}
- */
-TT.prototype.getMediaTimeEvents = function () {
-    return this.events;
-};
-
-/*
- * Represents a TTML Head element
- */
-function Head() {
-    this.styling = new Styling();
-    this.layout = new Layout();
-}
-
-/*
- * Represents a TTML Styling element
- */
-function Styling() {
-    this.styles = {};
-    this.initials = {};
-}
-
-/*
- * Represents a TTML Style element
- */
-function Style() {
-    this.id = null;
-    this.styleAttrs = null;
-    this.styleRefs = null;
-}
-
-Style.prototype.initFromNode = function (node, errorHandler) {
-    this.id = elementGetXMLID(node);
-    this.styleAttrs = elementGetStyles(node, errorHandler);
-    this.styleRefs = elementGetStyleRefs(node);
-};
-
-/*
- * Represents a TTML initial element
- */
-function Initial() {
-    this.styleAttrs = null;
-}
-
-Initial.prototype.initFromNode = function (node, errorHandler) {
-    this.styleAttrs = {};
-    for (var i in node.attributes) {
-        if (node.attributes[i].uri === imscNames.ns_itts ||
-            node.attributes[i].uri === imscNames.ns_ebutts ||
-            node.attributes[i].uri === imscNames.ns_tts) {
-            var qname = node.attributes[i].uri + " " + node.attributes[i].local;
-            this.styleAttrs[qname] = node.attributes[i].value;
-        }
-    }
-};
-
-/*
- * Represents a TTML Layout element
- *
- */
-function Layout() {
-    this.regions = {};
-}
-
-/*
- * Represents a TTML image element
- */
-function Image(src, type) {
-    ContentElement.call(this, 'image');
-    this.src = src;
-    this.type = type;
-}
-
-Image.prototype.initFromNode = function (doc, parent, node, errorHandler) {
-    this.src = 'src' in node.attributes ? node.attributes.src.value : null;
-    if (!this.src) {
-        reportError(errorHandler, "Invalid image@src attribute");
-    }
-    this.type = 'type' in node.attributes ? node.attributes.type.value : null;
-    if (!this.type) {
-        reportError(errorHandler, "Invalid image@type attribute");
-    }
-    StyledElement.prototype.initFromNode.call(this, doc, parent, node, errorHandler);
-    TimedElement.prototype.initFromNode.call(this, doc, parent, node, errorHandler);
-    AnimatedElement.prototype.initFromNode.call(this, doc, parent, node, errorHandler);
-    LayoutElement.prototype.initFromNode.call(this, doc, parent, node, errorHandler);
-};
-
-/*
- * TTML element utility functions
- *
- */
-function ContentElement(kind) {
-    this.kind = kind;
-}
-
-function IdentifiedElement(id) {
-    this.id = id;
-}
-
-IdentifiedElement.prototype.initFromNode = function (doc, parent, node, errorHandler) {
-    this.id = elementGetXMLID(node);
-};
-
-function LayoutElement(id) {
-    this.regionID = id;
-}
-
-LayoutElement.prototype.initFromNode = function (doc, parent, node, errorHandler) {
-    this.regionID = elementGetRegionID(node);
-};
-
-function StyledElement(styleAttrs) {
-    this.styleAttrs = styleAttrs;
-}
-
-StyledElement.prototype.initFromNode = function (doc, parent, node, errorHandler) {
-    this.styleAttrs = elementGetStyles(node, errorHandler);
-    if (doc.head !== null && doc.head.styling !== null) {
-        mergeReferencedStyles(doc.head.styling, elementGetStyleRefs(node), this.styleAttrs, errorHandler);
-    }
-};
-
-function AnimatedElement(sets) {
-    this.sets = sets;
-}
-
-AnimatedElement.prototype.initFromNode = function (doc, parent, node, errorHandler) {
-    this.sets = [];
-};
-
-function ContainerElement(contents) {
-    this.contents = contents;
-}
-
-ContainerElement.prototype.initFromNode = function (doc, parent, node, errorHandler) {
-    this.contents = [];
-};
-
-function TimedElement(explicit_begin, explicit_end, explicit_dur) {
-    this.explicit_begin = explicit_begin;
-    this.explicit_end = explicit_end;
-    this.explicit_dur = explicit_dur;
-}
-
-TimedElement.prototype.initFromNode = function (doc, parent, node, errorHandler) {
-    var t = processTiming(doc, parent, node, errorHandler);
-    this.explicit_begin = t.explicit_begin;
-    this.explicit_end = t.explicit_end;
-    this.explicit_dur = t.explicit_dur;
-    this.timeContainer = elementGetTimeContainer(node, errorHandler);
-};
-
-/*
- * Represents a TTML body element
- */
-function Body() {
-    ContentElement.call(this, 'body');
-}
-
-Body.prototype.initFromNode = function (doc, node, errorHandler) {
-    StyledElement.prototype.initFromNode.call(this, doc, null, node, errorHandler);
-    TimedElement.prototype.initFromNode.call(this, doc, null, node, errorHandler);
-    AnimatedElement.prototype.initFromNode.call(this, doc, null, node, errorHandler);
-    LayoutElement.prototype.initFromNode.call(this, doc, null, node, errorHandler);
-    ContainerElement.prototype.initFromNode.call(this, doc, null, node, errorHandler);
-};
-
-/*
- * Represents a TTML div element
- */
-function Div() {
-    ContentElement.call(this, 'div');
-}
-
-Div.prototype.initFromNode = function (doc, parent, node, errorHandler) {
-    StyledElement.prototype.initFromNode.call(this, doc, parent, node, errorHandler);
-    TimedElement.prototype.initFromNode.call(this, doc, parent, node, errorHandler);
-    AnimatedElement.prototype.initFromNode.call(this, doc, parent, node, errorHandler);
-    LayoutElement.prototype.initFromNode.call(this, doc, parent, node, errorHandler);
-    ContainerElement.prototype.initFromNode.call(this, doc, parent, node, errorHandler);
-};
-
-/*
- * Represents a TTML p element
- */
-function P() {
-    ContentElement.call(this, 'p');
-}
-
-P.prototype.initFromNode = function (doc, parent, node, errorHandler) {
-    StyledElement.prototype.initFromNode.call(this, doc, parent, node, errorHandler);
-    TimedElement.prototype.initFromNode.call(this, doc, parent, node, errorHandler);
-    AnimatedElement.prototype.initFromNode.call(this, doc, parent, node, errorHandler);
-    LayoutElement.prototype.initFromNode.call(this, doc, parent, node, errorHandler);
-    ContainerElement.prototype.initFromNode.call(this, doc, parent, node, errorHandler);
-};
-
-/*
- * Represents a TTML span element
- */
-function Span() {
-    ContentElement.call(this, 'span');
-}
-
-Span.prototype.initFromNode = function (doc, parent, node, xmlspace, errorHandler) {
-    StyledElement.prototype.initFromNode.call(this, doc, parent, node, errorHandler);
-    TimedElement.prototype.initFromNode.call(this, doc, parent, node, errorHandler);
-    AnimatedElement.prototype.initFromNode.call(this, doc, parent, node, errorHandler);
-    LayoutElement.prototype.initFromNode.call(this, doc, parent, node, errorHandler);
-    ContainerElement.prototype.initFromNode.call(this, doc, parent, node, errorHandler);
-    this.space = xmlspace;
-};
-
-/*
- * Represents a TTML anonymous span element
- */
-function AnonymousSpan() {
-    ContentElement.call(this, 'span');
-}
-
-AnonymousSpan.prototype.initFromText = function (doc, parent, text, xmlspace, errorHandler) {
-    TimedElement.prototype.initFromNode.call(this, doc, parent, null, errorHandler);
-    this.text = text;
-    this.space = xmlspace;
-};
-
-/*
- * Represents a TTML br element
- */
-function Br() {
-    ContentElement.call(this, 'br');
-}
-
-Br.prototype.initFromNode = function (doc, parent, node, errorHandler) {
-    LayoutElement.prototype.initFromNode.call(this, doc, parent, node, errorHandler);
-    TimedElement.prototype.initFromNode.call(this, doc, parent, node, errorHandler);
-};
-
-/*
- * Represents a TTML Region element
- *
- */
-function Region() {
-}
-
-Region.prototype.createDefaultRegion = function () {
-    var r = new Region();
-    IdentifiedElement.call(r, '');
-    StyledElement.call(r, {});
-    AnimatedElement.call(r, []);
-    TimedElement.call(r, 0, Number.POSITIVE_INFINITY, null);
-    return r;
-};
-Region.prototype.initFromNode = function (doc, node, errorHandler) {
-    IdentifiedElement.prototype.initFromNode.call(this, doc, null, node, errorHandler);
-    StyledElement.prototype.initFromNode.call(this, doc, null, node, errorHandler);
-    TimedElement.prototype.initFromNode.call(this, doc, null, node, errorHandler);
-    AnimatedElement.prototype.initFromNode.call(this, doc, null, node, errorHandler);
-    /* immediately merge referenced styles */
-    if (doc.head !== null && doc.head.styling !== null) {
-        mergeReferencedStyles(doc.head.styling, elementGetStyleRefs(node), this.styleAttrs, errorHandler);
-    }
-};
-
-/*
- * Represents a TTML Set element
- *
- */
-function Set() {
-}
-
-Set.prototype.initFromNode = function (doc, parent, node, errorHandler) {
-    TimedElement.prototype.initFromNode.call(this, doc, parent, node, errorHandler);
-    var styles = elementGetStyles(node, errorHandler);
-    this.qname = null;
-    this.value = null;
-    for (var qname in styles) {
-        if (this.qname) {
-            reportError(errorHandler, "More than one style specified on set");
-            break;
-        }
-        this.qname = qname;
-        this.value = styles[qname];
-    }
-};
-
-/*
- * Utility functions
- *
- */
-function elementGetXMLID(node) {
-    return node && 'xml:id' in node.attributes ? node.attributes['xml:id'].value || null : null;
-}
-
-function elementGetRegionID(node) {
-    return node && 'region' in node.attributes ? node.attributes.region.value : '';
-}
-
-function elementGetTimeContainer(node, errorHandler) {
-    var tc = node && 'timeContainer' in node.attributes ? node.attributes.timeContainer.value : null;
-    if ((!tc) || tc === "par") {
-        return "par";
-    } else if (tc === "seq") {
-        return "seq";
-    } else {
-        reportError(errorHandler, "Illegal value of timeContainer (assuming 'par')");
-        return "par";
-    }
-}
-
-function elementGetStyleRefs(node) {
-    return node && 'style' in node.attributes ? node.attributes.style.value.split(" ") : [];
-}
-
-function elementGetStyles(node, errorHandler) {
-    var s = {};
-    if (node !== null) {
-        for (var i in node.attributes) {
-            var qname = node.attributes[i].uri + " " + node.attributes[i].local;
-            var sa = imscStyles.byQName[qname];
-            if (sa !== undefined) {
-                var val = sa.parse(node.attributes[i].value);
-                if (val !== null) {
-                    s[qname] = val;
-                    /* TODO: consider refactoring errorHandler into parse and compute routines */
-                    if (sa === imscStyles.byName.zIndex) {
-                        reportWarning(errorHandler, "zIndex attribute present but not used by IMSC1 since regions do not overlap");
-                    }
-                } else {
-                    reportError(errorHandler, "Cannot parse styling attribute " + qname + " --> " + node.attributes[i].value);
-                }
-            }
-        }
-    }
-    return s;
-}
-
-function findAttribute(node, ns, name) {
-    for (var i in node.attributes) {
-        if (node.attributes[i].uri === ns &&
-            node.attributes[i].local === name) {
-            return node.attributes[i].value;
-        }
-    }
-    return null;
-}
-
-function extractAspectRatio(node, errorHandler) {
-    var ar = findAttribute(node, imscNames.ns_ittp, "aspectRatio");
-    if (ar === null) {
-        ar = findAttribute(node, imscNames.ns_ttp, "displayAspectRatio");
-    }
-    var rslt = null;
-    if (ar !== null) {
-        var ASPECT_RATIO_RE = /(\d+)\s+(\d+)/;
-        var m = ASPECT_RATIO_RE.exec(ar);
-        if (m !== null) {
-            var w = parseInt(m[1]);
-            var h = parseInt(m[2]);
-            if (w !== 0 && h !== 0) {
-                rslt = w / h;
-            } else {
-                reportError(errorHandler, "Illegal aspectRatio values (ignoring)");
-            }
-        } else {
-            reportError(errorHandler, "Malformed aspectRatio attribute (ignoring)");
-        }
-    }
-    return rslt;
-}
-
-/*
- * Returns the cellResolution attribute from a node
- *
- */
-function extractCellResolution(node, errorHandler) {
-    var cr = findAttribute(node, imscNames.ns_ttp, "cellResolution");
-    // initial value
-    var h = 15;
-    var w = 32;
-    if (cr !== null) {
-        var CELL_RESOLUTION_RE = /(\d+) (\d+)/;
-        var m = CELL_RESOLUTION_RE.exec(cr);
-        if (m !== null) {
-            w = parseInt(m[1]);
-            h = parseInt(m[2]);
-        } else {
-            reportWarning(errorHandler, "Malformed cellResolution value (using initial value instead)");
-        }
-    }
-    return {'w': w, 'h': h};
-}
-
-function extractFrameAndTickRate(node, errorHandler) {
-    // subFrameRate is ignored per IMSC1 specification
-    // extract frame rate
-    var fps_attr = findAttribute(node, imscNames.ns_ttp, "frameRate");
-    // initial value
-    var fps = 30;
-    // match variable
-    var m;
-    if (fps_attr !== null) {
-        var FRAME_RATE_RE = /(\d+)/;
-        m = FRAME_RATE_RE.exec(fps_attr);
-        if (m !== null) {
-            fps = parseInt(m[1]);
-        } else {
-            reportWarning(errorHandler, "Malformed frame rate attribute (using initial value instead)");
-        }
-    }
-    // extract frame rate multiplier
-    var frm_attr = findAttribute(node, imscNames.ns_ttp, "frameRateMultiplier");
-    // initial value
-    var frm = 1;
-    if (frm_attr !== null) {
-        var FRAME_RATE_MULT_RE = /(\d+) (\d+)/;
-        m = FRAME_RATE_MULT_RE.exec(frm_attr);
-        if (m !== null) {
-            frm = parseInt(m[1]) / parseInt(m[2]);
-        } else {
-            reportWarning(errorHandler, "Malformed frame rate multiplier attribute (using initial value instead)");
-        }
-    }
-    var efps = frm * fps;
-    // extract tick rate
-    var tr = 1;
-    var trattr = findAttribute(node, imscNames.ns_ttp, "tickRate");
-    if (trattr === null) {
-        if (fps_attr !== null)
-            tr = efps;
-    } else {
-        var TICK_RATE_RE = /(\d+)/;
-        m = TICK_RATE_RE.exec(trattr);
-        if (m !== null) {
-            tr = parseInt(m[1]);
-        } else {
-            reportWarning(errorHandler, "Malformed tick rate attribute (using initial value instead)");
-        }
-    }
-    return {effectiveFrameRate: efps, tickRate: tr};
-}
-
-function extractExtent(node, errorHandler) {
-    var attr = findAttribute(node, imscNames.ns_tts, "extent");
-    if (attr === null)
-        return null;
-    var s = attr.split(" ");
-    if (s.length !== 2) {
-        reportWarning(errorHandler, "Malformed extent (ignoring)");
-        return null;
-    }
-    var w = imscUtils.parseLength(s[0]);
-    var h = imscUtils.parseLength(s[1]);
-    if (!h || !w) {
-        reportWarning(errorHandler, "Malformed extent values (ignoring)");
-        return null;
-    }
-    return {'h': h, 'w': w};
-}
-
-function parseTimeExpression(tickRate, effectiveFrameRate, str) {
-    var CLOCK_TIME_FRACTION_RE = /^(\d{2,}):(\d\d):(\d\d(?:\.\d+)?)$/;
-    var CLOCK_TIME_FRAMES_RE = /^(\d{2,}):(\d\d):(\d\d):(\d{2,})$/;
-    var OFFSET_FRAME_RE = /^(\d+(?:\.\d+)?)f$/;
-    var OFFSET_TICK_RE = /^(\d+(?:\.\d+)?)t$/;
-    var OFFSET_MS_RE = /^(\d+(?:\.\d+)?)ms$/;
-    var OFFSET_S_RE = /^(\d+(?:\.\d+)?)s$/;
-    var OFFSET_H_RE = /^(\d+(?:\.\d+)?)h$/;
-    var OFFSET_M_RE = /^(\d+(?:\.\d+)?)m$/;
-    var m;
-    var r = null;
-    if ((m = OFFSET_FRAME_RE.exec(str)) !== null) {
-        if (effectiveFrameRate !== null) {
-            r = parseFloat(m[1]) / effectiveFrameRate;
-        }
-    } else if ((m = OFFSET_TICK_RE.exec(str)) !== null) {
-        if (tickRate !== null) {
-            r = parseFloat(m[1]) / tickRate;
-        }
-    } else if ((m = OFFSET_MS_RE.exec(str)) !== null) {
-        r = parseFloat(m[1]) / 1000.0;
-    } else if ((m = OFFSET_S_RE.exec(str)) !== null) {
-        r = parseFloat(m[1]);
-    } else if ((m = OFFSET_H_RE.exec(str)) !== null) {
-        r = parseFloat(m[1]) * 3600.0;
-    } else if ((m = OFFSET_M_RE.exec(str)) !== null) {
-        r = parseFloat(m[1]) * 60.0;
-    } else if ((m = CLOCK_TIME_FRACTION_RE.exec(str)) !== null) {
-        r = parseInt(m[1]) * 3600 +
-            parseInt(m[2]) * 60 +
-            parseFloat(m[3]);
-    } else if ((m = CLOCK_TIME_FRAMES_RE.exec(str)) !== null) {
-        /* this assumes that HH:MM:SS is a clock-time-with-fraction */
-        if (effectiveFrameRate !== null) {
-            r = parseInt(m[1]) * 3600 +
-                parseInt(m[2]) * 60 +
-                parseInt(m[3]) +
-                (m[4] === null ? 0 : parseInt(m[4]) / effectiveFrameRate);
-        }
-    }
-    return r;
-}
-
-function processTiming(doc, parent, node, errorHandler) {
-    /* determine explicit begin */
-    var explicit_begin = null;
-    if (node && 'begin' in node.attributes) {
-        explicit_begin = parseTimeExpression(doc.tickRate, doc.effectiveFrameRate, node.attributes.begin.value);
-        if (explicit_begin === null) {
-            reportWarning(errorHandler, "Malformed begin value " + node.attributes.begin.value + " (using 0)");
-        }
-    }
-    /* determine explicit duration */
-    var explicit_dur = null;
-    if (node && 'dur' in node.attributes) {
-        explicit_dur = parseTimeExpression(doc.tickRate, doc.effectiveFrameRate, node.attributes.dur.value);
-        if (explicit_dur === null) {
-            reportWarning(errorHandler, "Malformed dur value " + node.attributes.dur.value + " (ignoring)");
-        }
-    }
-    /* determine explicit end */
-    var explicit_end = null;
-    if (node && 'end' in node.attributes) {
-        explicit_end = parseTimeExpression(doc.tickRate, doc.effectiveFrameRate, node.attributes.end.value);
-        if (explicit_end === null) {
-            reportWarning(errorHandler, "Malformed end value (ignoring)");
-        }
-    }
-    return {
-        explicit_begin: explicit_begin,
-        explicit_end: explicit_end,
-        explicit_dur: explicit_dur
-    };
-}
-
-function mergeChainedStyles(styling, style, errorHandler) {
-    while (style.styleRefs.length > 0) {
-        var sref = style.styleRefs.pop();
-        if (!(sref in styling.styles)) {
-            reportError(errorHandler, "Non-existant style id referenced");
-            continue;
-        }
-        mergeChainedStyles(styling, styling.styles[sref], errorHandler);
-        mergeStylesIfNotPresent(styling.styles[sref].styleAttrs, style.styleAttrs);
-    }
-}
-
-function mergeReferencedStyles(styling, stylerefs, styleattrs, errorHandler) {
-    for (var i = stylerefs.length - 1; i >= 0; i--) {
-        var sref = stylerefs[i];
-        if (!(sref in styling.styles)) {
-            reportError(errorHandler, "Non-existant style id referenced");
-            continue;
-        }
-        mergeStylesIfNotPresent(styling.styles[sref].styleAttrs, styleattrs);
-    }
-}
-
-function mergeStylesIfNotPresent(from_styles, into_styles) {
-    for (var sname in from_styles) {
-        if (sname in into_styles)
-            continue;
-        into_styles[sname] = from_styles[sname];
-    }
-}
-
-/* TODO: validate style format at parsing */
-
-/*
- * Binary search utility function
- *
- * @typedef {Object} BinarySearchResult
- * @property {boolean} found Was an exact match found?
- * @property {number} index Position of the exact match or insert position
- *
- * @returns {BinarySearchResult}
- */
-function indexOf(arr, searchval) {
-    var min = 0;
-    var max = arr.length - 1;
-    var cur;
-    while (min <= max) {
-        cur = Math.floor((min + max) / 2);
-        var curval = arr[cur];
-        if (curval < searchval) {
-            min = cur + 1;
-        } else if (curval > searchval) {
-            max = cur - 1;
-        } else {
-            return {found: true, index: cur};
-        }
-    }
-    return {found: false, index: min};
-}
diff --git a/src/util/ttml/html.js b/src/util/ttml/html.js
deleted file mode 100644
index a76ee4a..0000000
--- a/src/util/ttml/html.js
+++ /dev/null
@@ -1,1006 +0,0 @@
-/* 
- * Copyright (c) 2016, Pierre-Anthony Lemieux <pal@sandflow.com>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * * Redistributions of source code must retain the above copyright notice, this
- *   list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright notice,
- *   this list of conditions and the following disclaimer in the documentation
- *   and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-import * as imscStyles from './styles';
-
-export function render(isd,
-                       element,
-                       imgResolver,
-                       eheight,
-                       ewidth,
-                       displayForcedOnlyMode,
-                       errorHandler,
-                       previousISDState,
-                       enableRollUp
-) {
-    /* maintain aspect ratio if specified */
-    let height = eheight || element.clientHeight;
-    let width = ewidth || element.clientWidth;
-    if (isd.aspectRatio !== null) {
-        let twidth = height * isd.aspectRatio;
-        if (twidth > width) {
-            height = Math.round(width / isd.aspectRatio);
-        } else {
-            width = twidth;
-        }
-    }
-    let rootcontainer = document.createElement("div");
-    rootcontainer.style.position = "relative";
-    rootcontainer.style.width = width + "px";
-    rootcontainer.style.height = height + "px";
-    rootcontainer.style.margin = "auto";
-    rootcontainer.style.top = 0;
-    rootcontainer.style.bottom = 0;
-    rootcontainer.style.left = 0;
-    rootcontainer.style.right = 0;
-    rootcontainer.style.zIndex = 0;
-    let context = {
-        h: height,
-        w: width,
-        regionH: null,
-        regionW: null,
-        imgResolver: imgResolver,
-        displayForcedOnlyMode: displayForcedOnlyMode || false,
-        isd: isd,
-        errorHandler: errorHandler,
-        previousISDState: previousISDState,
-        enableRollUp: enableRollUp || false,
-        currentISDState: {},
-        flg: null, /* current fillLineGap value if active, null otherwise */
-        lp: null, /* current linePadding value if active, null otherwise */
-        mra: null, /* current multiRowAlign value if active, null otherwise */
-        ipd: null, /* inline progression direction (lr, rl, tb) */
-        bpd: null, /* block progression direction (lr, rl, tb) */
-        ruby: null, /* is ruby present in a <p> */
-        textEmphasis: null, /* is textEmphasis present in a <p> */
-        rubyReserve: null /* is rubyReserve applicable to a <p> */
-    };
-    element.appendChild(rootcontainer);
-    if (isd.contents) {
-        for (let content of isd.contents) {
-            processElement(context, rootcontainer, content);
-        }
-    }
-    return context.currentISDState;
-}
-
-function processElement(context, dom_parent, isd_element) {
-    let e;
-    if (isd_element.kind === 'region') {
-        e = document.createElement("div");
-        e.style.position = "absolute";
-    } else if (isd_element.kind === 'body') {
-        e = document.createElement("div");
-    } else if (isd_element.kind === 'div') {
-        e = document.createElement("div");
-    } else if (isd_element.kind === 'image') {
-        e = document.createElement("img");
-        if (context.imgResolver !== null && isd_element.src !== null) {
-            let uri = context.imgResolver(isd_element.src, e);
-            if (uri)
-                e.src = uri;
-            e.height = context.regionH;
-            e.width = context.regionW;
-        }
-    } else if (isd_element.kind === 'p') {
-        e = document.createElement("p");
-    } else if (isd_element.kind === 'span') {
-        if (isd_element.styleAttrs[imscStyles.byName.ruby.qname] === "container") {
-            e = document.createElement("ruby");
-            context.ruby = true;
-        } else if (isd_element.styleAttrs[imscStyles.byName.ruby.qname] === "base") {
-            e = document.createElement("rb");
-        } else if (isd_element.styleAttrs[imscStyles.byName.ruby.qname] === "text") {
-            e = document.createElement("rt");
-        } else if (isd_element.styleAttrs[imscStyles.byName.ruby.qname] === "baseContainer") {
-            e = document.createElement("rbc");
-        } else if (isd_element.styleAttrs[imscStyles.byName.ruby.qname] === "textContainer") {
-            e = document.createElement("rtc");
-        } else if (isd_element.styleAttrs[imscStyles.byName.ruby.qname] === "delimiter") {
-            /* ignore rp */
-            return;
-        } else {
-            e = document.createElement("span");
-        }
-        let te = isd_element.styleAttrs[imscStyles.byName.textEmphasis.qname];
-        if (te && te.style !== "none") {
-            context.textEmphasis = true;
-        }
-        //e.textContent = isd_element.text;
-    } else if (isd_element.kind === 'br') {
-        e = document.createElement("br");
-    }
-    if (!e) {
-        reportError(context.errorHandler, "Error processing ISD element kind: " + isd_element.kind);
-        return;
-    }
-    /* add to parent */
-    dom_parent.appendChild(e);
-    /* override UA default margin */
-    /* TODO: should apply to <p> only */
-    e.style.margin = "0";
-    /* tranform TTML styles to CSS styles */
-    for (let i in STYLING_MAP_DEFS) {
-        let sm = STYLING_MAP_DEFS[i];
-        let attr = isd_element.styleAttrs[sm.qname];
-        if (attr !== undefined && sm.map !== null) {
-            sm.map(context, e, isd_element, attr);
-        }
-    }
-    let proc_e = e;
-    /* remember writing direction */
-    if (isd_element.kind === "region") {
-        let wdir = isd_element.styleAttrs[imscStyles.byName.writingMode.qname];
-        if (wdir === "lrtb" || wdir === "lr") {
-            context.ipd = "lr";
-            context.bpd = "tb";
-        } else if (wdir === "rltb" || wdir === "rl") {
-            context.ipd = "rl";
-            context.bpd = "tb";
-        } else if (wdir === "tblr") {
-            context.ipd = "tb";
-            context.bpd = "lr";
-        } else if (wdir === "tbrl" || wdir === "tb") {
-            context.ipd = "tb";
-            context.bpd = "rl";
-        }
-    }
-    /* do we have linePadding ? */
-    let lp = isd_element.styleAttrs[imscStyles.byName.linePadding.qname];
-    if (lp && (!lp.isZero())) {
-        let plength = lp.toUsedLength(context.w, context.h);
-        if (plength > 0) {
-            /* apply padding to the <p> so that line padding does not cause line wraps */
-            let padmeasure = Math.ceil(plength) + "px";
-            if (context.bpd === "tb") {
-                proc_e.style.paddingLeft = padmeasure;
-                proc_e.style.paddingRight = padmeasure;
-            } else {
-                proc_e.style.paddingTop = padmeasure;
-                proc_e.style.paddingBottom = padmeasure;
-            }
-            context.lp = lp;
-        }
-    }
-    // do we have multiRowAlign?
-    let mra = isd_element.styleAttrs[imscStyles.byName.multiRowAlign.qname];
-    if (mra && mra !== "auto") {
-        /* create inline block to handle multirowAlign */
-        let s = document.createElement("span");
-        s.style.display = "inline-block";
-        s.style.textAlign = mra;
-        e.appendChild(s);
-        proc_e = s;
-        context.mra = mra;
-    }
-    /* do we have rubyReserve? */
-    let rr = isd_element.styleAttrs[imscStyles.byName.rubyReserve.qname];
-    if (rr && rr[0] !== "none") {
-        context.rubyReserve = rr;
-    }
-    /* remember we are filling line gaps */
-    if (isd_element.styleAttrs[imscStyles.byName.fillLineGap.qname]) {
-        context.flg = true;
-    }
-    if (isd_element.kind === "span" && isd_element.text) {
-        if (imscStyles.byName.textCombine.qname in isd_element.styleAttrs &&
-            isd_element.styleAttrs[imscStyles.byName.textCombine.qname][0] === "all") {
-            /* ignore tate-chu-yoku since line break cannot happen within */
-            e.textContent = isd_element.text;
-        } else {
-            // wrap characters in spans to find the line wrap locations
-            let cbuf = '';
-            for (let j = 0; j < isd_element.text.length; j++) {
-                cbuf += isd_element.text.charAt(j);
-                let cc = isd_element.text.charCodeAt(j);
-                if (cc < 0xD800 || cc > 0xDBFF || j === isd_element.text.length) {
-                    /* wrap the character(s) in a span unless it is a high surrogate */
-                    let span = document.createElement("span");
-                    span.textContent = cbuf;
-                    e.appendChild(span);
-                    cbuf = '';
-                }
-            }
-        }
-    }
-    /* process the children of the ISD element */
-    if (isd_element.contents) {
-        for (let content of isd_element.contents) {
-            processElement(context, proc_e, content);
-        }
-    }
-    /* list of lines */
-    let linelist = [];
-    /* paragraph processing */
-    /* TODO: linePadding only supported for horizontal scripts */
-    if ((context.lp || context.mra || context.flg || context.ruby || context.textEmphasis || context.rubyReserve) &&
-        isd_element.kind === "p") {
-        constructLineList(context, proc_e, linelist, null);
-        /* apply rubyReserve */
-        if (context.rubyReserve) {
-            applyRubyReserve(linelist, context);
-            context.rubyReserve = null;
-        }
-        /* apply tts:rubyPosition="outside" */
-        if (context.ruby || context.rubyReserve) {
-            applyRubyPosition(linelist, context);
-            context.ruby = null;
-        }
-        /* apply text emphasis "outside" position */
-        if (context.textEmphasis) {
-            applyTextEmphasis(linelist, context);
-            context.textEmphasis = null;
-        }
-        /* insert line breaks for multirowalign */
-        if (context.mra) {
-            applyMultiRowAlign(linelist);
-            context.mra = null;
-        }
-        /* add linepadding */
-        if (context.lp) {
-            applyLinePadding(linelist, context.lp.toUsedLength(context.w, context.h), context);
-            context.lp = null;
-        }
-        /* fill line gaps linepadding */
-        if (context.flg) {
-            let par_edges = rect2edges(proc_e.getBoundingClientRect(), context);
-            applyFillLineGap(linelist, par_edges.before, par_edges.after, context);
-            context.flg = null;
-        }
-    }
-    /* region processing */
-    if (isd_element.kind === "region") {
-        /* build line list */
-        constructLineList(context, proc_e, linelist);
-        /* perform roll up if needed */
-        if ((context.bpd === "tb") &&
-            context.enableRollUp &&
-            isd_element.contents.length > 0 &&
-            isd_element.styleAttrs[imscStyles.byName.displayAlign.qname] === 'after') {
-            /* horrible hack, perhaps default region id should be underscore everywhere? */
-            let rid = isd_element.id === '' ? '_' : isd_element.id;
-            let rb = new RegionPBuffer(rid, linelist);
-            context.currentISDState[rb.id] = rb;
-            if (context.previousISDState &&
-                rb.id in context.previousISDState &&
-                context.previousISDState[rb.id].plist.length > 0 &&
-                rb.plist.length > 1 &&
-                rb.plist[rb.plist.length - 2].text ===
-                context.previousISDState[rb.id].plist[context.previousISDState[rb.id].plist.length - 1].text) {
-                let body_elem = e.firstElementChild;
-                let h = rb.plist[rb.plist.length - 1].after - rb.plist[rb.plist.length - 1].before;
-                body_elem.style.bottom = "-" + h + "px";
-                body_elem.style.transition = "transform 0.4s";
-                body_elem.style.position = "relative";
-                body_elem.style.transform = "translateY(-" + h + "px)";
-            }
-        }
-        /* TODO: clean-up the spans ? */
-    }
-}
-
-function applyLinePadding(lineList, lp, context) {
-    if (lineList) {
-        for (let line of lineList) {
-            let l = line.elements.length;
-            let se = line.elements[line.start_elem];
-            let ee = line.elements[line.end_elem];
-            let pospadpxlen = Math.ceil(lp) + "px";
-            let negpadpxlen = "-" + Math.ceil(lp) + "px";
-            if (l !== 0) {
-                if (context.ipd === "lr") {
-                    se.node.style.borderLeftColor = se.bgcolor || "#00000000";
-                    se.node.style.borderLeftStyle = "solid";
-                    se.node.style.borderLeftWidth = pospadpxlen;
-                    se.node.style.marginLeft = negpadpxlen;
-                } else if (context.ipd === "rl") {
-                    se.node.style.borderRightColor = se.bgcolor || "#00000000";
-                    se.node.style.borderRightStyle = "solid";
-                    se.node.style.borderRightWidth = pospadpxlen;
-                    se.node.style.marginRight = negpadpxlen;
-                } else if (context.ipd === "tb") {
-                    se.node.style.borderTopColor = se.bgcolor || "#00000000";
-                    se.node.style.borderTopStyle = "solid";
-                    se.node.style.borderTopWidth = pospadpxlen;
-                    se.node.style.marginTop = negpadpxlen;
-                }
-                if (context.ipd === "lr") {
-                    ee.node.style.borderRightColor = ee.bgcolor || "#00000000";
-                    ee.node.style.borderRightStyle = "solid";
-                    ee.node.style.borderRightWidth = pospadpxlen;
-                    ee.node.style.marginRight = negpadpxlen;
-                } else if (context.ipd === "rl") {
-                    ee.node.style.borderLeftColor = ee.bgcolor || "#00000000";
-                    ee.node.style.borderLeftStyle = "solid";
-                    ee.node.style.borderLeftWidth = pospadpxlen;
-                    ee.node.style.marginLeft = negpadpxlen;
-                } else if (context.ipd === "tb") {
-                    ee.node.style.borderBottomColor = ee.bgcolor || "#00000000";
-                    ee.node.style.borderBottomStyle = "solid";
-                    ee.node.style.borderBottomWidth = pospadpxlen;
-                    ee.node.style.marginBottom = negpadpxlen;
-                }
-            }
-        }
-    }
-}
-
-function applyMultiRowAlign(lineList) {
-    /* apply an explicit br to all but the last line */
-    for (let i = 0; i < lineList.length - 1; i++) {
-        let l = lineList[i].elements.length;
-        if (l !== 0 && lineList[i].br === false) {
-            let br = document.createElement("br");
-            let lastnode = lineList[i].elements[l - 1].node;
-            lastnode.parentElement.insertBefore(br, lastnode.nextSibling);
-        }
-    }
-}
-
-function applyTextEmphasis(lineList, context) {
-    /* supports "outside" only */
-    for (let i = 0; i < lineList.length; i++) {
-        for (let j = 0; j < lineList[i].te.length; j++) {
-            /* skip if position already set */
-            if (lineList[i].te[j].style.textEmphasisPosition &&
-                lineList[i].te[j].style.textEmphasisPosition !== "none")
-                continue;
-            let pos;
-            if (context.bpd === "tb") {
-                pos = (i === 0) ? "left over" : "left under";
-            } else {
-                if (context.bpd === "rl") {
-                    pos = (i === 0) ? "right under" : "left under";
-                } else {
-                    pos = (i === 0) ? "left under" : "right under";
-                }
-            }
-            lineList[i].te[j].style.textEmphasisPosition = pos;
-        }
-    }
-}
-
-function applyRubyPosition(lineList, context) {
-    for (let i = 0; i < lineList.length; i++) {
-        for (let j = 0; j < lineList[i].rbc.length; j++) {
-            /* skip if ruby-position already set */
-            if (lineList[i].rbc[j].style.rubyPosition)
-                continue;
-            let pos;
-            if (context.bpd === "tb") {
-                pos = (i === 0) ? "over" : "under";
-            } else {
-                if (context.bpd === "rl") {
-                    pos = (i === 0) ? "over" : "under";
-                } else {
-                    pos = (i === 0) ? "under" : "over";
-                }
-            }
-            lineList[i].rbc[j].style.rubyPosition = pos;
-        }
-    }
-}
-
-function applyRubyReserve(lineList, context) {
-    for (let i = 0; i < lineList.length; i++) {
-        let ruby = document.createElement("ruby");
-        let rb = document.createElement("rb");
-        rb.textContent = "\u200B";
-        ruby.appendChild(rb);
-        let rt1;
-        let rt2;
-        let fs = context.rubyReserve[1].toUsedLength(context.w, context.h) + "px";
-        if (context.rubyReserve[0] === "both") {
-            rt1 = document.createElement("rtc");
-            rt1.style.rubyPosition = "under";
-            rt1.textContent = "\u200B";
-            rt1.style.fontSize = fs;
-            rt2 = document.createElement("rtc");
-            rt2.style.rubyPosition = "over";
-            rt2.textContent = "\u200B";
-            rt2.style.fontSize = fs;
-            ruby.appendChild(rt1);
-            ruby.appendChild(rt2);
-        } else {
-            rt1 = document.createElement("rtc");
-            rt1.textContent = "\u200B";
-            rt1.style.fontSize = fs;
-            if (context.rubyReserve[0] === "after" || (context.rubyReserve[0] === "outside" && i > 0)) {
-                rt1.style.rubyPosition = (context.bpd === "tb" || context.bpd === "rl") ? "under" : "over";
-            } else {
-                rt1.style.rubyPosition = (context.bpd === "tb" || context.bpd === "rl") ? "over" : "under";
-            }
-            ruby.appendChild(rt1);
-        }
-        lineList[i].elements[0].node.parentElement.insertBefore(
-            ruby,
-            lineList[i].elements[0].node
-        );
-    }
-}
-
-function applyFillLineGap(lineList, par_before, par_after, context) {
-    /* positive for BPD = lr and tb, negative for BPD = rl */
-    let s = Math.sign(par_after - par_before);
-    for (let i = 0; i <= lineList.length; i++) {
-        /* compute frontier between lines */
-        let frontier;
-        if (i === 0) {
-            frontier = par_before;
-        } else if (i === lineList.length) {
-            frontier = par_after;
-        } else {
-            frontier = (lineList[i].before + lineList[i - 1].after) / 2;
-        }
-        /* padding amount */
-        let pad;
-        /* current element */
-        let e;
-        /* before line */
-        if (i > 0) {
-            for (let j = 0; j < lineList[i - 1].elements.length; j++) {
-                if (lineList[i - 1].elements[j].bgcolor === null)
-                    continue;
-                e = lineList[i - 1].elements[j];
-                if (s * (e.after - frontier) < 0) {
-                    pad = Math.ceil(Math.abs(frontier - e.after)) + "px";
-                    e.node.style.backgroundColor = e.bgcolor;
-                    if (context.bpd === "lr") {
-                        e.node.style.paddingRight = pad;
-                    } else if (context.bpd === "rl") {
-                        e.node.style.paddingLeft = pad;
-                    } else if (context.bpd === "tb") {
-                        e.node.style.paddingBottom = pad;
-                    }
-                }
-            }
-        }
-        /* after line */
-        if (i < lineList.length) {
-            for (let k = 0; k < lineList[i].elements.length; k++) {
-                e = lineList[i].elements[k];
-                if (e.bgcolor === null)
-                    continue;
-                if (s * (e.before - frontier) > 0) {
-                    pad = Math.ceil(Math.abs(e.before - frontier)) + "px";
-                    e.node.style.backgroundColor = e.bgcolor;
-                    if (context.bpd === "lr") {
-                        e.node.style.paddingLeft = pad;
-                    } else if (context.bpd === "rl") {
-                        e.node.style.paddingRight = pad;
-                    } else if (context.bpd === "tb") {
-                        e.node.style.paddingTop = pad;
-                    }
-                }
-            }
-        }
-    }
-}
-
-function RegionPBuffer(id, lineList) {
-    this.id = id;
-    this.plist = lineList;
-}
-
-function rect2edges(rect, context) {
-    let edges = {before: null, after: null, start: null, end: null};
-    if (context.bpd === "tb") {
-        edges.before = rect.top;
-        edges.after = rect.bottom;
-        if (context.ipd === "lr") {
-            edges.start = rect.left;
-            edges.end = rect.right;
-        } else {
-            edges.start = rect.right;
-            edges.end = rect.left;
-        }
-    } else if (context.bpd === "lr") {
-        edges.before = rect.left;
-        edges.after = rect.right;
-        edges.start = rect.top;
-        edges.end = rect.bottom;
-    } else if (context.bpd === "rl") {
-        edges.before = rect.right;
-        edges.after = rect.left;
-        edges.start = rect.top;
-        edges.end = rect.bottom;
-    }
-    return edges;
-}
-
-function constructLineList(context, element, llist, bgcolor) {
-    if (element.localName === "rt" || element.localName === "rtc") {
-        /* skip ruby annotations */
-        return;
-    }
-    let curbgcolor = element.style.backgroundColor || bgcolor;
-    if (element.childElementCount === 0) {
-        if (element.localName === 'span' || element.localName === 'rb') {
-            let r = element.getBoundingClientRect();
-            /* skip if span is not displayed */
-            if (r.height === 0 || r.width === 0)
-                return;
-            let edges = rect2edges(r, context);
-            if (llist.length === 0 ||
-                (!isSameLine(edges.before, edges.after, llist[llist.length - 1].before, llist[llist.length - 1].after))
-            ) {
-                llist.push({
-                    before: edges.before,
-                    after: edges.after,
-                    start: edges.start,
-                    end: edges.end,
-                    start_elem: 0,
-                    end_elem: 0,
-                    elements: [],
-                    rbc: [],
-                    te: [],
-                    text: "",
-                    br: false
-                });
-            } else {
-                /* positive for BPD = lr and tb, negative for BPD = rl */
-                let bpd_dir = Math.sign(edges.after - edges.before);
-                /* positive for IPD = lr and tb, negative for IPD = rl */
-                let ipd_dir = Math.sign(edges.end - edges.start);
-                /* check if the line height has increased */
-                if (bpd_dir * (edges.before - llist[llist.length - 1].before) < 0) {
-                    llist[llist.length - 1].before = edges.before;
-                }
-                if (bpd_dir * (edges.after - llist[llist.length - 1].after) > 0) {
-                    llist[llist.length - 1].after = edges.after;
-                }
-                if (ipd_dir * (edges.start - llist[llist.length - 1].start) < 0) {
-                    llist[llist.length - 1].start = edges.start;
-                    llist[llist.length - 1].start_elem = llist[llist.length - 1].elements.length;
-                }
-                if (ipd_dir * (edges.end - llist[llist.length - 1].end) > 0) {
-                    llist[llist.length - 1].end = edges.end;
-                    llist[llist.length - 1].end_elem = llist[llist.length - 1].elements.length;
-                }
-            }
-            llist[llist.length - 1].text += element.textContent;
-            llist[llist.length - 1].elements.push(
-                {
-                    node: element,
-                    bgcolor: curbgcolor,
-                    before: edges.before,
-                    after: edges.after
-                }
-            );
-        } else if (element.localName === 'br' && llist.length !== 0) {
-            llist[llist.length - 1].br = true;
-        }
-    } else {
-        let child = element.firstChild;
-        while (child) {
-            if (child.nodeType === Node.ELEMENT_NODE) {
-                constructLineList(context, child, llist, curbgcolor);
-                if (child.localName === 'ruby' || child.localName === 'rtc') {
-                    /* remember non-empty ruby and rtc elements so that tts:rubyPosition can be applied */
-                    if (llist.length > 0) {
-                        llist[llist.length - 1].rbc.push(child);
-                    }
-                } else if (child.localName === 'span' &&
-                    child.style.textEmphasisStyle &&
-                    child.style.textEmphasisStyle !== "none") {
-                    /* remember non-empty span elements with textEmphasis */
-                    if (llist.length > 0) {
-                        llist[llist.length - 1].te.push(child);
-                    }
-                }
-            }
-            child = child.nextSibling;
-        }
-    }
-}
-
-function isSameLine(before1, after1, before2, after2) {
-    return ((after1 < after2) && (before1 > before2)) || ((after2 <= after1) && (before2 >= before1));
-}
-
-function HTMLStylingMapDefintion(qName, mapFunc) {
-    this.qname = qName;
-    this.map = mapFunc;
-}
-
-let STYLING_MAP_DEFS = [
-    new HTMLStylingMapDefintion(
-        "http://www.w3.org/ns/ttml#styling backgroundColor",
-        function (context, dom_element, isd_element, attr) {
-            /* skip if transparent */
-            if (attr[3] === 0)
-                return;
-            dom_element.style.backgroundColor = "rgba(" +
-                attr[0].toString() + "," +
-                attr[1].toString() + "," +
-                attr[2].toString() + "," +
-                (attr[3] / 255).toString() +
-                ")";
-        }
-    ),
-    new HTMLStylingMapDefintion(
-        "http://www.w3.org/ns/ttml#styling color",
-        function (context, dom_element, isd_element, attr) {
-            dom_element.style.color = "rgba(" +
-                attr[0].toString() + "," +
-                attr[1].toString() + "," +
-                attr[2].toString() + "," +
-                (attr[3] / 255).toString() +
-                ")";
-        }
-    ),
-    new HTMLStylingMapDefintion(
-        "http://www.w3.org/ns/ttml#styling direction",
-        function (context, dom_element, isd_element, attr) {
-            dom_element.style.direction = attr;
-        }
-    ),
-    new HTMLStylingMapDefintion(
-        "http://www.w3.org/ns/ttml#styling display",
-        function (context, dom_element, isd_element, attr) {
-        }
-    ),
-    new HTMLStylingMapDefintion(
-        "http://www.w3.org/ns/ttml#styling displayAlign",
-        function (context, dom_element, isd_element, attr) {
-            /* see https://css-tricks.com/snippets/css/a-guide-to-flexbox/ */
-            /* TODO: is this affected by writing direction? */
-            dom_element.style.display = "flex";
-            dom_element.style.flexDirection = "column";
-            if (attr === "before") {
-                dom_element.style.justifyContent = "flex-start";
-            } else if (attr === "center") {
-                dom_element.style.justifyContent = "center";
-            } else if (attr === "after") {
-                dom_element.style.justifyContent = "flex-end";
-            }
-        }
-    ),
-    new HTMLStylingMapDefintion(
-        "http://www.w3.org/ns/ttml#styling extent",
-        function (context, dom_element, isd_element, attr) {
-            /* TODO: this is super ugly */
-            context.regionH = attr.h.toUsedLength(context.w, context.h);
-            context.regionW = attr.w.toUsedLength(context.w, context.h);
-            /*
-             * CSS height/width are measured against the content rectangle,
-             * whereas TTML height/width include padding
-             */
-            let hdelta = 0;
-            let wdelta = 0;
-            let p = isd_element.styleAttrs["http://www.w3.org/ns/ttml#styling padding"];
-            if (!p) {
-                /* error */
-            } else {
-                hdelta = p[0].toUsedLength(context.w, context.h) + p[2].toUsedLength(context.w, context.h);
-                wdelta = p[1].toUsedLength(context.w, context.h) + p[3].toUsedLength(context.w, context.h);
-            }
-            dom_element.style.height = (context.regionH - hdelta) + "px";
-            dom_element.style.width = (context.regionW - wdelta) + "px";
-        }
-    ),
-    new HTMLStylingMapDefintion(
-        "http://www.w3.org/ns/ttml#styling fontFamily",
-        function (context, dom_element, isd_element, attr) {
-            /* per IMSC1 */
-            const styleClasses = ["monospaceSerif", "proportionalSerif", "monospace", "sansSerif", "serif", "monospaceSansSerif", "proportionalSansSerif"];
-            for (let attribute of attr) {
-                if (styleClasses.includes(attribute)) {
-                    dom_element.classList.add("ttml-" + attribute);
-                } else {
-                    dom_element.style.fontFamily = attribute;
-                }
-            }
-        }
-    ),
-    new HTMLStylingMapDefintion(
-        "http://www.w3.org/ns/ttml#styling shear",
-        function (context, dom_element, isd_element, attr) {
-            /* return immediately if tts:shear is 0% since CSS transforms are not inherited*/
-            if (attr === 0)
-                return;
-            let angle = attr * -0.9;
-            /* context.writingMode is needed since writing mode is not inherited and sets the inline progression */
-            if (context.bpd === "tb") {
-                dom_element.style.transform = "skewX(" + angle + "deg)";
-            } else {
-                dom_element.style.transform = "skewY(" + angle + "deg)";
-            }
-        }
-    ),
-    new HTMLStylingMapDefintion(
-        "http://www.w3.org/ns/ttml#styling fontSize",
-        function (context, dom_element, isd_element, attr) {
-            dom_element.style.fontSize = attr.toUsedLength(context.w, context.h) + "px";
-        }
-    ),
-    new HTMLStylingMapDefintion(
-        "http://www.w3.org/ns/ttml#styling fontStyle",
-        function (context, dom_element, isd_element, attr) {
-            dom_element.style.fontStyle = attr;
-        }
-    ),
-    new HTMLStylingMapDefintion(
-        "http://www.w3.org/ns/ttml#styling fontWeight",
-        function (context, dom_element, isd_element, attr) {
-            dom_element.style.fontWeight = attr;
-        }
-    ),
-    new HTMLStylingMapDefintion(
-        "http://www.w3.org/ns/ttml#styling lineHeight",
-        function (context, dom_element, isd_element, attr) {
-            if (attr === "normal") {
-                dom_element.style.lineHeight = "normal";
-            } else {
-                dom_element.style.lineHeight = attr.toUsedLength(context.w, context.h) + "px";
-            }
-        }
-    ),
-    new HTMLStylingMapDefintion(
-        "http://www.w3.org/ns/ttml#styling opacity",
-        function (context, dom_element, isd_element, attr) {
-            dom_element.style.opacity = attr;
-        }
-    ),
-    new HTMLStylingMapDefintion(
-        "http://www.w3.org/ns/ttml#styling origin",
-        function (context, dom_element, isd_element, attr) {
-            dom_element.style.top = attr.h.toUsedLength(context.w, context.h) + "px";
-            dom_element.style.left = attr.w.toUsedLength(context.w, context.h) + "px";
-        }
-    ),
-    new HTMLStylingMapDefintion(
-        "http://www.w3.org/ns/ttml#styling overflow",
-        function (context, dom_element, isd_element, attr) {
-            dom_element.style.overflow = attr;
-        }
-    ),
-    new HTMLStylingMapDefintion(
-        "http://www.w3.org/ns/ttml#styling padding",
-        function (context, dom_element, isd_element, attr) {
-            /* attr: top,left,bottom,right*/
-            /* style: top right bottom left*/
-            let rslt = [];
-            rslt[0] = attr[0].toUsedLength(context.w, context.h) + "px";
-            rslt[1] = attr[3].toUsedLength(context.w, context.h) + "px";
-            rslt[2] = attr[2].toUsedLength(context.w, context.h) + "px";
-            rslt[3] = attr[1].toUsedLength(context.w, context.h) + "px";
-            dom_element.style.padding = rslt.join(" ");
-        }
-    ),
-    new HTMLStylingMapDefintion(
-        "http://www.w3.org/ns/ttml#styling position",
-        function (context, dom_element, isd_element, attr) {
-            dom_element.style.top = attr.h.toUsedLength(context.w, context.h) + "px";
-            dom_element.style.left = attr.w.toUsedLength(context.w, context.h) + "px";
-        }
-    ),
-    new HTMLStylingMapDefintion(
-        "http://www.w3.org/ns/ttml#styling rubyAlign",
-        function (context, dom_element, isd_element, attr) {
-            dom_element.style.rubyAlign = attr;
-        }
-    ),
-    new HTMLStylingMapDefintion(
-        "http://www.w3.org/ns/ttml#styling rubyPosition",
-        function (context, dom_element, isd_element, attr) {
-            /* skip if "outside", which is handled by applyRubyPosition() */
-            if (attr === "before" || attr === "after") {
-                let pos;
-                if (context.bpd === "tb") {
-                    pos = (attr === "before") ? "over" : "under";
-                } else {
-                    if (context.bpd === "rl") {
-                        pos = (attr === "before") ? "over" : "under";
-                    } else {
-                        pos = (attr === "before") ? "under" : "over";
-                    }
-                }
-                /* apply position to the parent dom_element, i.e. ruby or rtc */
-                dom_element.parentElement.style.rubyPosition = pos;
-            }
-        }
-    ),
-    new HTMLStylingMapDefintion(
-        "http://www.w3.org/ns/ttml#styling showBackground",
-        null
-    ),
-    new HTMLStylingMapDefintion(
-        "http://www.w3.org/ns/ttml#styling textAlign",
-        function (context, dom_element, isd_element, attr) {
-            let ta;
-            let dir = isd_element.styleAttrs[imscStyles.byName.direction.qname];
-            /* handle UAs that do not understand start or end */
-            if (attr === "start") {
-                ta = (dir === "rtl") ? "right" : "left";
-            } else if (attr === "end") {
-                ta = (dir === "rtl") ? "left" : "right";
-            } else {
-                ta = attr;
-            }
-            dom_element.style.textAlign = ta;
-        }
-    ),
-    new HTMLStylingMapDefintion(
-        "http://www.w3.org/ns/ttml#styling textDecoration",
-        function (context, dom_element, isd_element, attr) {
-            dom_element.style.textDecoration = attr.join(" ").replace("lineThrough", "line-through");
-        }
-    ),
-    new HTMLStylingMapDefintion(
-        "http://www.w3.org/ns/ttml#styling textOutline",
-        function (context, dom_element, isd_element, attr) {
-            /* defer to tts:textShadow */
-        }
-    ),
-    new HTMLStylingMapDefintion(
-        "http://www.w3.org/ns/ttml#styling textShadow",
-        function (context, dom_element, isd_element, attr) {
-            let txto = isd_element.styleAttrs[imscStyles.byName.textOutline.qname];
-            if (attr === "none" && txto === "none") {
-                dom_element.style.textShadow = "";
-            } else {
-                let s = [];
-                if (txto !== "none") {
-                    /* emulate text outline */
-                    s.push(
-                        "rgba(" +
-                        txto.color[0].toString() + "," +
-                        txto.color[1].toString() + "," +
-                        txto.color[2].toString() + "," +
-                        (txto.color[3] / 255).toString() +
-                        ") 0px 0px " +
-                        txto.thickness.toUsedLength(context.w, context.h) + "px"
-                    );
-                }
-                /* add text shadow */
-                if (attr !== "none") {
-                    for (let attribute of attr) {
-                        s.push(attribute.x_off.toUsedLength(context.w, context.h) + "px " +
-                            attribute.y_off.toUsedLength(context.w, context.h) + "px " +
-                            attribute.b_radius.toUsedLength(context.w, context.h) + "px " +
-                            "rgba(" +
-                            attribute.color[0].toString() + "," +
-                            attribute.color[1].toString() + "," +
-                            attribute.color[2].toString() + "," +
-                            (attribute.color[3] / 255).toString() +
-                            ")"
-                        );
-                    }
-                }
-                dom_element.style.textShadow = s.join(",");
-            }
-        }
-    ),
-    new HTMLStylingMapDefintion(
-        "http://www.w3.org/ns/ttml#styling textCombine",
-        function (context, dom_element, isd_element, attr) {
-            dom_element.style.textCombineUpright = attr.join(" ");
-        }
-    ),
-    new HTMLStylingMapDefintion(
-        "http://www.w3.org/ns/ttml#styling textEmphasis",
-        function (context, dom_element, isd_element, attr) {
-            /* ignore color (not used in IMSC 1.1) */
-            if (attr.style === "none") {
-                dom_element.style.textEmphasisStyle = "none";
-                /* no need to set position, so return */
-                return;
-            } else if (attr.style === "auto") {
-                dom_element.style.textEmphasisStyle = "filled";
-            } else {
-                dom_element.style.textEmphasisStyle = attr.style + " " + attr.symbol;
-            }
-            /* ignore "outside" position (set in postprocessing) */
-            if (attr.position === "before" || attr.position === "after") {
-                let pos;
-                if (context.bpd === "tb") {
-                    pos = (attr.position === "before") ? "left over" : "left under";
-                } else {
-                    if (context.bpd === "rl") {
-                        pos = (attr.position === "before") ? "right under" : "left under";
-                    } else {
-                        pos = (attr.position === "before") ? "left under" : "right under";
-                    }
-                }
-                dom_element.style.textEmphasisPosition = pos;
-            }
-        }
-    ),
-    new HTMLStylingMapDefintion(
-        "http://www.w3.org/ns/ttml#styling unicodeBidi",
-        function (context, dom_element, isd_element, attr) {
-            let ub;
-            if (attr === 'bidiOverride') {
-                ub = "bidi-override";
-            } else {
-                ub = attr;
-            }
-            dom_element.style.unicodeBidi = ub;
-        }
-    ),
-    new HTMLStylingMapDefintion(
-        "http://www.w3.org/ns/ttml#styling visibility",
-        function (context, dom_element, isd_element, attr) {
-            dom_element.style.visibility = attr;
-        }
-    ),
-    new HTMLStylingMapDefintion(
-        "http://www.w3.org/ns/ttml#styling wrapOption",
-        function (context, dom_element, isd_element, attr) {
-            if (attr === "wrap") {
-                if (isd_element.space === "preserve") {
-                    dom_element.style.whiteSpace = "pre-wrap";
-                } else {
-                    dom_element.style.whiteSpace = "normal";
-                }
-            } else {
-                if (isd_element.space === "preserve") {
-                    dom_element.style.whiteSpace = "pre";
-                } else {
-                    dom_element.style.whiteSpace = "noWrap";
-                }
-            }
-        }
-    ),
-    new HTMLStylingMapDefintion(
-        "http://www.w3.org/ns/ttml#styling writingMode",
-        function (context, dom_element, isd_element, attr) {
-            if (attr === "lrtb" || attr === "lr") {
-                context.writingMode = "horizontal-tb";
-            } else if (attr === "rltb" || attr === "rl") {
-                context.writingMode = "horizontal-tb";
-            } else if (attr === "tblr") {
-                context.writingMode = "vertical-lr";
-            } else if (attr === "tbrl" || attr === "tb") {
-                context.writingMode = "vertical-rl";
-            }
-            dom_element.style.writingMode = context.writingMode;
-        }
-    ),
-    new HTMLStylingMapDefintion(
-        "http://www.w3.org/ns/ttml#styling zIndex",
-        function (context, dom_element, isd_element, attr) {
-            dom_element.style.zIndex = attr;
-        }
-    ),
-    new HTMLStylingMapDefintion(
-        "http://www.w3.org/ns/ttml/profile/imsc1#styling forcedDisplay",
-        function (context, dom_element, isd_element, attr) {
-            if (context.displayForcedOnlyMode && attr === false) {
-                dom_element.style.visibility = "hidden";
-            }
-        }
-    )
-];
-let STYLMAP_BY_QNAME = {};
-for (let i in STYLING_MAP_DEFS) {
-    STYLMAP_BY_QNAME[STYLING_MAP_DEFS[i].qname] = STYLING_MAP_DEFS[i];
-}
-
-function reportError(errorHandler, msg) {
-    if (errorHandler && errorHandler.error && errorHandler.error(msg))
-        throw msg;
-}
diff --git a/src/util/ttml/isd.js b/src/util/ttml/isd.js
deleted file mode 100644
index dbf8d54..0000000
--- a/src/util/ttml/isd.js
+++ /dev/null
@@ -1,449 +0,0 @@
-/* 
- * Copyright (c) 2016, Pierre-Anthony Lemieux <pal@sandflow.com>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * * Redistributions of source code must retain the above copyright notice, this
- *   list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright notice,
- *   this list of conditions and the following disclaimer in the documentation
- *   and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-import * as imscStyles from './styles';
-import * as imscUtils from './utils';
-import {reportError} from './utils';
-
-export function generateISD(tt, offset, errorHandler) {
-    /* TODO check for tt and offset validity */
-    /* create the ISD object from the IMSC1 doc */
-    let isd = new ISD(tt);
-    /* context */
-    let context = {
-        /*rubyfs: []*/ /* font size of the nearest textContainer or container */
-    };
-    /* process regions */
-    for (let r in tt.head.layout.regions) {
-        /* post-order traversal of the body tree per [construct intermediate document] */
-        let c = isdProcessContentElement(tt, offset, tt.head.layout.regions[r], tt.body, null, '', tt.head.layout.regions[r], errorHandler, context);
-        if (c !== null) {
-            /* add the region to the ISD */
-            isd.contents.push(c.element);
-        }
-    }
-    return isd;
-}
-
-/* set of styles not applicable to ruby container spans */
-let _rcs_na_styles = [
-    imscStyles.byName.color.qname,
-    imscStyles.byName.textCombine.qname,
-    imscStyles.byName.textDecoration.qname,
-    imscStyles.byName.textEmphasis.qname,
-    imscStyles.byName.textOutline.qname,
-    imscStyles.byName.textShadow.qname
-];
-
-function isdProcessContentElement(doc, offset, region, body, parent, inherited_region_id, elem, errorHandler, context) {
-    /* prune if temporally inactive */
-    if (offset < elem.begin || offset >= elem.end) {
-        return null;
-    }
-    /*
-     * set the associated region as specified by the regionID attribute, or the
-     * inherited associated region otherwise
-     */
-    let associated_region_id = 'regionID' in elem && elem.regionID !== '' ? elem.regionID : inherited_region_id;
-    /* prune the element if either:
-     * - the element is not terminal and the associated region is neither the default
-     *   region nor the parent region (this allows children to be associated with a
-     *   region later on)
-     * - the element is terminal and the associated region is not the parent region
-     */
-    /* TODO: improve detection of terminal elements since <region> has no contents */
-    if (parent !== null /* are we in the region element */ &&
-        associated_region_id !== region.id &&
-        (
-            (!('contents' in elem)) ||
-            ('contents' in elem && elem.contents.length === 0) ||
-            associated_region_id !== ''
-        )
-    )
-        return null;
-    /* create an ISD element, including applying specified styles */
-    let isd_element = new ISDContentElement(elem);
-    /* apply set (animation) styling */
-    if (elem.sets) {
-        for (let set of elem.sets) {
-            if (offset < set.begin || offset >= set.end)
-                continue;
-            isd_element.styleAttrs[set.qname] = set.value;
-        }
-    }
-    /*
-     * keep track of specified styling attributes so that we
-     * can compute them later
-     */
-    let spec_attr = {};
-    for (let qname in isd_element.styleAttrs) {
-        spec_attr[qname] = true;
-        /* special rule for tts:writingMode (section 7.29.1 of XSL)
-         * direction is set consistently with writingMode only
-         * if writingMode sets inline-direction to LTR or RTL
-         */
-        if (qname === imscStyles.byName.writingMode.qname &&
-            !(imscStyles.byName.direction.qname in isd_element.styleAttrs)) {
-            let wm = isd_element.styleAttrs[qname];
-            if (wm === "lrtb" || wm === "lr") {
-                isd_element.styleAttrs[imscStyles.byName.direction.qname] = "ltr";
-            } else if (wm === "rltb" || wm === "rl") {
-                isd_element.styleAttrs[imscStyles.byName.direction.qname] = "rtl";
-            }
-        }
-    }
-    /* inherited styling */
-    if (parent !== null) {
-        for (let j in imscStyles.all) {
-            let sa = imscStyles.all[j];
-            /* textDecoration has special inheritance rules */
-            if (sa.qname === imscStyles.byName.textDecoration.qname) {
-                /* handle both textDecoration inheritance and specification */
-                let ps = parent.styleAttrs[sa.qname];
-                let es = isd_element.styleAttrs[sa.qname];
-                let outs = [];
-                if (es === undefined) {
-                    outs = ps;
-                } else if (es.indexOf("none") === -1) {
-                    if ((es.indexOf("noUnderline") === -1 &&
-                        ps.indexOf("underline") !== -1) ||
-                        es.indexOf("underline") !== -1) {
-                        outs.push("underline");
-                    }
-                    if ((es.indexOf("noLineThrough") === -1 &&
-                        ps.indexOf("lineThrough") !== -1) ||
-                        es.indexOf("lineThrough") !== -1) {
-                        outs.push("lineThrough");
-                    }
-                    if ((es.indexOf("noOverline") === -1 &&
-                        ps.indexOf("overline") !== -1) ||
-                        es.indexOf("overline") !== -1) {
-                        outs.push("overline");
-                    }
-                } else {
-                    outs.push("none");
-                }
-                isd_element.styleAttrs[sa.qname] = outs;
-            } else if (sa.qname === imscStyles.byName.fontSize.qname &&
-                !(sa.qname in isd_element.styleAttrs) &&
-                isd_element.kind === 'span' &&
-                isd_element.styleAttrs[imscStyles.byName.ruby.qname] === "textContainer") {
-                /* special inheritance rule for ruby text container font size */
-                let ruby_fs = parent.styleAttrs[imscStyles.byName.fontSize.qname];
-                isd_element.styleAttrs[sa.qname] = new imscUtils.ComputedLength(
-                    0.5 * ruby_fs.rw,
-                    0.5 * ruby_fs.rh);
-            } else if (sa.qname === imscStyles.byName.fontSize.qname &&
-                !(sa.qname in isd_element.styleAttrs) &&
-                isd_element.kind === 'span' &&
-                isd_element.styleAttrs[imscStyles.byName.ruby.qname] === "text") {
-                /* special inheritance rule for ruby text font size */
-                let parent_fs = parent.styleAttrs[imscStyles.byName.fontSize.qname];
-                if (parent.styleAttrs[imscStyles.byName.ruby.qname] === "textContainer") {
-                    isd_element.styleAttrs[sa.qname] = parent_fs;
-                } else {
-                    isd_element.styleAttrs[sa.qname] = new imscUtils.ComputedLength(
-                        0.5 * parent_fs.rw,
-                        0.5 * parent_fs.rh);
-                }
-            } else if (sa.inherit &&
-                (sa.qname in parent.styleAttrs) &&
-                !(sa.qname in isd_element.styleAttrs)) {
-                isd_element.styleAttrs[sa.qname] = parent.styleAttrs[sa.qname];
-            }
-        }
-    }
-    /* initial value styling */
-    for (let k in imscStyles.all) {
-        let ivs = imscStyles.all[k];
-        /* skip if value is already specified */
-        if (ivs.qname in isd_element.styleAttrs) continue;
-        /* skip tts:position if tts:origin is specified */
-        if (ivs.qname === imscStyles.byName.position.qname &&
-            imscStyles.byName.origin.qname in isd_element.styleAttrs)
-            continue;
-        /* skip tts:origin if tts:position is specified */
-        if (ivs.qname === imscStyles.byName.origin.qname &&
-            imscStyles.byName.position.qname in isd_element.styleAttrs)
-            continue;
-        /* determine initial value */
-        let iv = doc.head.styling.initials[ivs.qname] || ivs.initial;
-        /* apply initial value to elements other than region only if non-inherited */
-        if (isd_element.kind === 'region' || (ivs.inherit === false && iv !== null)) {
-            isd_element.styleAttrs[ivs.qname] = ivs.parse(iv);
-            /* keep track of the style as specified */
-            spec_attr[ivs.qname] = true;
-        }
-    }
-    /* compute styles (only for non-inherited styles) */
-    /* TODO: get rid of spec_attr */
-    for (let z in imscStyles.all) {
-        let cs = imscStyles.all[z];
-        if (!(cs.qname in spec_attr)) continue;
-        if (cs.compute !== null) {
-            let cstyle = cs.compute(
-                /*doc, parent, element, attr, context*/
-                doc,
-                parent,
-                isd_element,
-                isd_element.styleAttrs[cs.qname],
-                context
-            );
-            if (cstyle !== null) {
-                isd_element.styleAttrs[cs.qname] = cstyle;
-            } else {
-                /* if the style cannot be computed, replace it by its initial value */
-                isd_element.styleAttrs[cs.qname] = cs.compute(
-                    /*doc, parent, element, attr, context*/
-                    doc,
-                    parent,
-                    isd_element,
-                    cs.parse(cs.initial),
-                    context
-                );
-                reportError(errorHandler, "Style '" + cs.qname + "' on element '" + isd_element.kind + "' cannot be computed");
-            }
-        }
-    }
-    /* tts:fontSize special ineritance for ruby */
-    /*        let isrubycontainer = false;
-            if (isd_element.kind === "span") {
-                let rtemp = isd_element.styleAttrs[imscStyles.byName.ruby.qname];
-                if (rtemp === "container" || rtemp === "textContainer") {
-                    isrubycontainer = true;
-                    context.rubyfs.unshift(isd_element.styleAttrs[imscStyles.byName.fontSize.qname]);
-                }
-            } */
-    /* prune if tts:display is none */
-    if (isd_element.styleAttrs[imscStyles.byName.display.qname] === "none")
-        return null;
-    /* process contents of the element */
-    let contents;
-    if (parent === null) {
-        /* we are processing the region */
-        if (body === null) {
-            /* if there is no body, still process the region but with empty content */
-            contents = [];
-        } else {
-            /*use the body element as contents */
-            contents = [body];
-        }
-    } else if ('contents' in elem) {
-        contents = elem.contents;
-    }
-    for (let x in contents) {
-        let c = isdProcessContentElement(doc, offset, region, body, isd_element, associated_region_id, contents[x], errorHandler, context);
-        /*
-         * keep child element only if they are non-null and their region match
-         * the region of this element
-         */
-        if (c !== null) {
-            isd_element.contents.push(c.element);
-        }
-    }
-    /* compute used value of lineHeight="normal" */
-    /*        if (isd_element.styleAttrs[imscStyles.byName.lineHeight.qname] === "normal"  ) {
-     isd_element.styleAttrs[imscStyles.byName.lineHeight.qname] =
-     isd_element.styleAttrs[imscStyles.byName.fontSize.qname] * 1.2;
-     }
-     */
-    /* tts:fontSize special ineritance for ruby */
-    /*if (isrubycontainer) {
-        context.rubyfs.shift();
-    }*/
-    /* remove styles that are not applicable */
-    for (let qnameb in isd_element.styleAttrs) {
-        /* true if not applicable */
-        let na = false;
-        /* special applicability of certain style properties to ruby container spans */
-        /* TODO: in the future ruby elements should be translated to elements instead of kept as spans */
-        if (isd_element.kind === 'span') {
-            let rsp = isd_element.styleAttrs[imscStyles.byName.ruby.qname];
-            na = (rsp === 'container' || rsp === 'textContainer' || rsp === 'baseContainer') &&
-                _rcs_na_styles.indexOf(qnameb) !== -1;
-            if (!na) {
-                na = rsp !== 'container' &&
-                    qnameb === imscStyles.byName.rubyAlign.qname;
-            }
-            if (!na) {
-                na = (!(rsp === 'textContainer' || rsp === 'text')) &&
-                    qnameb === imscStyles.byName.rubyPosition.qname;
-            }
-        }
-        /* normal applicability */
-        if (!na) {
-            let da = imscStyles.byQName[qnameb];
-            na = da.applies.indexOf(isd_element.kind) === -1;
-        }
-        if (na) {
-            delete isd_element.styleAttrs[qnameb];
-        }
-    }
-    /* collapse white space if space is "default" */
-    if (isd_element.kind === 'span' && isd_element.text && isd_element.space === "default") {
-        isd_element.text = isd_element.text.replace(/[\t\r\n ]+/g, ' ');
-    }
-    /* trim whitespace around explicit line breaks */
-    if (isd_element.kind === 'p') {
-        let elist = [];
-        constructSpanList(isd_element, elist);
-        let l = 0;
-        let state = "after_br";
-        let br_pos = 0;
-        while (true) {
-            if (state === "after_br") {
-                if (l >= elist.length || elist[l].kind === "br") {
-                    state = "before_br";
-                    br_pos = l;
-                    l--;
-                } else {
-                    if (elist[l].space !== "preserve") {
-                        elist[l].text = elist[l].text.replace(/^[\t\r\n ]+/g, '');
-                    }
-                    if (elist[l].text.length > 0) {
-                        state = "looking_br";
-                        l++;
-                    } else {
-                        elist.splice(l, 1);
-                    }
-                }
-            } else if (state === "before_br") {
-                if (l < 0 || elist[l].kind === "br") {
-                    state = "after_br";
-                    l = br_pos + 1;
-                    if (l >= elist.length) break;
-                } else {
-                    if (elist[l].space !== "preserve") {
-                        elist[l].text = elist[l].text.replace(/[\t\r\n ]+$/g, '');
-                    }
-                    if (elist[l].text.length > 0) {
-                        state = "after_br";
-                        l = br_pos + 1;
-                        if (l >= elist.length) break;
-                    } else {
-                        elist.splice(l, 1);
-                        l--;
-                    }
-                }
-            } else {
-                if (l >= elist.length || elist[l].kind === "br") {
-                    state = "before_br";
-                    br_pos = l;
-                    l--;
-                } else {
-                    l++;
-                }
-            }
-        }
-        pruneEmptySpans(isd_element);
-    }
-    /* keep element if:
-     * * contains a background image
-     * * <br/>
-     * * if there are children
-     * * if it is an image
-     * * if <span> and has text
-     * * if region and showBackground = always
-     */
-    if ((isd_element.kind === 'div' && imscStyles.byName.backgroundImage.qname in isd_element.styleAttrs) ||
-        isd_element.kind === 'br' ||
-        isd_element.kind === 'image' ||
-        ('contents' in isd_element && isd_element.contents.length > 0) ||
-        (isd_element.kind === 'span' && isd_element.text !== null) ||
-        (isd_element.kind === 'region' &&
-            isd_element.styleAttrs[imscStyles.byName.showBackground.qname] === 'always')) {
-        return {
-            region_id: associated_region_id,
-            element: isd_element
-        };
-    }
-    return null;
-}
-
-function constructSpanList(element, elist) {
-    if ('contents' in element) {
-        for (let content of element.contents) {
-            constructSpanList(content, elist);
-        }
-    } else if (element.kind === 'span' || element.kind === 'br') {
-        elist.push(element);
-    }
-}
-
-function pruneEmptySpans(element) {
-    if (element.kind === 'br') {
-        return false;
-    } else if ('text' in element) {
-        return element.text.length === 0;
-    } else if ('contents' in element) {
-        let i = element.contents.length;
-        while (i--) {
-            if (pruneEmptySpans(element.contents[i])) {
-                element.contents.splice(i, 1);
-            }
-        }
-        return element.contents.length === 0;
-    }
-}
-
-function ISD(tt) {
-    this.contents = [];
-    this.aspectRatio = tt.aspectRatio;
-}
-
-function ISDContentElement(ttelem) {
-    /* assume the element is a region if it does not have a kind */
-    this.kind = ttelem.kind || 'region';
-    /* copy id */
-    if (ttelem.id) {
-        this.id = ttelem.id;
-    }
-    /* deep copy of style attributes */
-    this.styleAttrs = {};
-    for (let sname in ttelem.styleAttrs) {
-        if (!ttelem.styleAttrs.hasOwnProperty(sname)) {
-            continue;
-        }
-        this.styleAttrs[sname] =
-            ttelem.styleAttrs[sname];
-    }
-    /* copy src and type if image */
-    if ('src' in ttelem) {
-        this.src = ttelem.src;
-    }
-    if ('type' in ttelem) {
-        this.type = ttelem.type;
-    }
-    /* TODO: clean this!
-     * TODO: ISDElement and document element should be better tied together */
-    if ('text' in ttelem) {
-        this.text = ttelem.text;
-    } else if (this.kind === 'region' || 'contents' in ttelem) {
-        this.contents = [];
-    }
-    if ('space' in ttelem) {
-        this.space = ttelem.space;
-    }
-}
diff --git a/src/util/ttml/names.js b/src/util/ttml/names.js
deleted file mode 100644
index 53d6c68..0000000
--- a/src/util/ttml/names.js
+++ /dev/null
@@ -1,33 +0,0 @@
-/* 
- * Copyright (c) 2016, Pierre-Anthony Lemieux <pal@sandflow.com>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * * Redistributions of source code must retain the above copyright notice, this
- *   list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright notice,
- *   this list of conditions and the following disclaimer in the documentation
- *   and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-export const ns_tt = "http://www.w3.org/ns/ttml";
-export const ns_tts = "http://www.w3.org/ns/ttml#styling";
-export const ns_ttp = "http://www.w3.org/ns/ttml#parameter";
-export const ns_xml = "http://www.w3.org/XML/1998/namespace";
-export const ns_itts = "http://www.w3.org/ns/ttml/profile/imsc1#styling";
-export const ns_ittp = "http://www.w3.org/ns/ttml/profile/imsc1#parameter";
-export const ns_smpte = "http://www.smpte-ra.org/schemas/2052-1/2010/smpte-tt";
-export const ns_ebutts = "urn:ebu:tt:style";
diff --git a/src/util/ttml/styles.js b/src/util/ttml/styles.js
deleted file mode 100644
index 4510f64..0000000
--- a/src/util/ttml/styles.js
+++ /dev/null
@@ -1,941 +0,0 @@
-/* 
- * Copyright (c) 2016, Pierre-Anthony Lemieux <pal@sandflow.com>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * * Redistributions of source code must retain the above copyright notice, this
- *   list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright notice,
- *   this list of conditions and the following disclaimer in the documentation
- *   and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-import * as imscNames from './names';
-import * as imscUtils from './utils';
-
-const DEFAULT_FONT_FAMILY = "monospaceSansSerif";
-
-function StylingAttributeDefinition(ns, name, initialValue, appliesTo, isInherit, isAnimatable, parseFunc, computeFunc) {
-    this.name = name;
-    this.ns = ns;
-    this.qname = this.ns + " " + this.name;
-    this.inherit = isInherit;
-    this.animatable = isAnimatable;
-    this.initial = initialValue;
-    this.applies = appliesTo;
-    this.parse = parseFunc;
-    this.compute = computeFunc;
-}
-
-export const all = [
-    new StylingAttributeDefinition(
-        imscNames.ns_tts,
-        "backgroundColor",
-        "transparent",
-        ['body', 'div', 'p', 'region', 'span'],
-        false,
-        true,
-        imscUtils.parseColor,
-        null
-    ),
-    new StylingAttributeDefinition(
-        imscNames.ns_tts,
-        "color",
-        "white",
-        ['span'],
-        true,
-        true,
-        imscUtils.parseColor,
-        null
-    ),
-    new StylingAttributeDefinition(
-        imscNames.ns_tts,
-        "direction",
-        "ltr",
-        ['p', 'span'],
-        true,
-        true,
-        function (str) {
-            return str;
-        },
-        null
-    ),
-    new StylingAttributeDefinition(
-        imscNames.ns_tts,
-        "display",
-        "auto",
-        ['body', 'div', 'p', 'region', 'span'],
-        false,
-        true,
-        function (str) {
-            return str;
-        },
-        null
-    ),
-    new StylingAttributeDefinition(
-        imscNames.ns_tts,
-        "displayAlign",
-        "before",
-        ['region'],
-        false,
-        true,
-        function (str) {
-            return str;
-        },
-        null
-    ),
-    new StylingAttributeDefinition(
-        imscNames.ns_tts,
-        "extent",
-        "auto",
-        ['tt', 'region'],
-        false,
-        true,
-        function (str) {
-            if (str === "auto") {
-                return str;
-            } else {
-                let s = str.split(" ");
-                if (s.length !== 2)
-                    return null;
-                let w = imscUtils.parseLength(s[0]);
-                let h = imscUtils.parseLength(s[1]);
-                if (!h || !w)
-                    return null;
-                return {'h': h, 'w': w};
-            }
-        },
-        function (doc, parent, element, attr) {
-            let h;
-            let w;
-            if (attr === "auto") {
-                h = new imscUtils.ComputedLength(0, 1);
-            } else {
-                h = imscUtils.toComputedLength(
-                    attr.h.value,
-                    attr.h.unit,
-                    null,
-                    doc.dimensions.h,
-                    null,
-                    doc.pxLength.h
-                );
-                if (h === null) {
-                    return null;
-                }
-            }
-            if (attr === "auto") {
-                w = new imscUtils.ComputedLength(1, 0);
-            } else {
-                w = imscUtils.toComputedLength(
-                    attr.w.value,
-                    attr.w.unit,
-                    null,
-                    doc.dimensions.w,
-                    null,
-                    doc.pxLength.w
-                );
-                if (w === null) {
-                    return null;
-                }
-            }
-            return {'h': h, 'w': w};
-        }
-    ),
-    new StylingAttributeDefinition(
-        imscNames.ns_tts,
-        "fontFamily",
-        "default",
-        ['span'],
-        true,
-        true,
-        function (str) {
-            let ffs = str.split(",");
-            let rslt = [];
-            for (let element of ffs) {
-                if (element.charAt(0) !== "'" && element.charAt(0) !== '"') {
-                    if (element === "default") {
-                        /* per IMSC1 */
-                        rslt.push(DEFAULT_FONT_FAMILY);
-                    } else {
-                        rslt.push(element);
-                    }
-                } else {
-                    rslt.push(element);
-                }
-            }
-            return rslt;
-        },
-        null
-    ),
-    new StylingAttributeDefinition(
-        imscNames.ns_tts,
-        "shear",
-        "0%",
-        ['p'],
-        true,
-        true,
-        imscUtils.parseLength,
-        function (doc, parent, element, attr) {
-            let fs;
-            if (attr.unit === "%") {
-                fs = Math.abs(attr.value) > 100 ? Math.sign(attr.value) * 100 : attr.value;
-            } else {
-                return null;
-            }
-            return fs;
-        }
-    ),
-    new StylingAttributeDefinition(
-        imscNames.ns_tts,
-        "fontSize",
-        "1c",
-        ['span'],
-        true,
-        true,
-        imscUtils.parseLength,
-        function (doc, parent, element, attr) {
-            let fs;
-            fs = imscUtils.toComputedLength(
-                attr.value,
-                attr.unit,
-                parent !== null ? parent.styleAttrs[byName.fontSize.qname] : doc.cellLength.h,
-                parent !== null ? parent.styleAttrs[byName.fontSize.qname] : doc.cellLength.h,
-                doc.cellLength.h,
-                doc.pxLength.h
-            );
-            return fs;
-        }
-    ),
-    new StylingAttributeDefinition(
-        imscNames.ns_tts,
-        "fontStyle",
-        "normal",
-        ['span'],
-        true,
-        true,
-        function (str) {
-            /* TODO: handle font style */
-            return str;
-        },
-        null
-    ),
-    new StylingAttributeDefinition(
-        imscNames.ns_tts,
-        "fontWeight",
-        "normal",
-        ['span'],
-        true,
-        true,
-        function (str) {
-            /* TODO: handle font weight */
-            return str;
-        },
-        null
-    ),
-    new StylingAttributeDefinition(
-        imscNames.ns_tts,
-        "lineHeight",
-        "normal",
-        ['p'],
-        true,
-        true,
-        function (str) {
-            if (str === "normal") {
-                return str;
-            } else {
-                return imscUtils.parseLength(str);
-            }
-        },
-        function (doc, parent, element, attr) {
-            let lh;
-            if (attr === "normal") {
-                /* inherit normal per https://github.com/w3c/ttml1/issues/220 */
-                lh = attr;
-            } else {
-                lh = imscUtils.toComputedLength(
-                    attr.value,
-                    attr.unit,
-                    element.styleAttrs[byName.fontSize.qname],
-                    element.styleAttrs[byName.fontSize.qname],
-                    doc.cellLength.h,
-                    doc.pxLength.h
-                );
-                if (lh === null) {
-                    return null;
-                }
-            }
-            /* TODO: create a Length constructor */
-            return lh;
-        }
-    ),
-    new StylingAttributeDefinition(
-        imscNames.ns_tts,
-        "opacity",
-        1.0,
-        ['region'],
-        false,
-        true,
-        parseFloat,
-        null
-    ),
-    new StylingAttributeDefinition(
-        imscNames.ns_tts,
-        "origin",
-        "auto",
-        ['region'],
-        false,
-        true,
-        function (str) {
-            if (str === "auto") {
-                return str;
-            } else {
-                let s = str.split(" ");
-                if (s.length !== 2)
-                    return null;
-                let w = imscUtils.parseLength(s[0]);
-                let h = imscUtils.parseLength(s[1]);
-                if (!h || !w)
-                    return null;
-                return {'h': h, 'w': w};
-            }
-        },
-        function (doc, parent, element, attr) {
-            let h;
-            let w;
-            if (attr === "auto") {
-                h = new imscUtils.ComputedLength(0, 0);
-            } else {
-                h = imscUtils.toComputedLength(
-                    attr.h.value,
-                    attr.h.unit,
-                    null,
-                    doc.dimensions.h,
-                    null,
-                    doc.pxLength.h
-                );
-                if (h === null) {
-                    return null;
-                }
-            }
-            if (attr === "auto") {
-                w = new imscUtils.ComputedLength(0, 0);
-            } else {
-                w = imscUtils.toComputedLength(
-                    attr.w.value,
-                    attr.w.unit,
-                    null,
-                    doc.dimensions.w,
-                    null,
-                    doc.pxLength.w
-                );
-                if (w === null) {
-                    return null;
-                }
-            }
-            return {'h': h, 'w': w};
-        }
-    ),
-    new StylingAttributeDefinition(
-        imscNames.ns_tts,
-        "overflow",
-        "hidden",
-        ['region'],
-        false,
-        true,
-        function (str) {
-            return str;
-        },
-        null
-    ),
-    new StylingAttributeDefinition(
-        imscNames.ns_tts,
-        "padding",
-        "0px",
-        ['region'],
-        false,
-        true,
-        function (str) {
-            let s = str.split(" ");
-            if (s.length > 4)
-                return null;
-            let r = [];
-            for (let el of s) {
-                let l = imscUtils.parseLength(el);
-                if (!l)
-                    return null;
-                r.push(l);
-            }
-            return r;
-        },
-        function (doc, parent, element, attr) {
-            let padding;
-            /* TODO: make sure we are in region */
-            /*
-             * expand padding shortcuts to
-             * [before, end, after, start]
-             *
-             */
-            if (attr.length === 1) {
-                padding = [attr[0], attr[0], attr[0], attr[0]];
-            } else if (attr.length === 2) {
-                padding = [attr[0], attr[1], attr[0], attr[1]];
-            } else if (attr.length === 3) {
-                padding = [attr[0], attr[1], attr[2], attr[1]];
-            } else if (attr.length === 4) {
-                padding = [attr[0], attr[1], attr[2], attr[3]];
-            } else {
-                return null;
-            }
-            /* TODO: take into account tts:direction */
-            /*
-             * transform [before, end, after, start] according to writingMode to
-             * [top,left,bottom,right]
-             *
-             */
-            let dir = element.styleAttrs[byName.writingMode.qname];
-            if (dir === "lrtb" || dir === "lr") {
-                padding = [padding[0], padding[3], padding[2], padding[1]];
-            } else if (dir === "rltb" || dir === "rl") {
-                padding = [padding[0], padding[1], padding[2], padding[3]];
-            } else if (dir === "tblr") {
-                padding = [padding[3], padding[0], padding[1], padding[2]];
-            } else if (dir === "tbrl" || dir === "tb") {
-                padding = [padding[3], padding[2], padding[1], padding[0]];
-            } else {
-                return null;
-            }
-            let out = [];
-            for (let i in padding) {
-                if (padding[i].value === 0) {
-                    out[i] = new imscUtils.ComputedLength(0, 0);
-                } else {
-                    out[i] = imscUtils.toComputedLength(
-                        padding[i].value,
-                        padding[i].unit,
-                        element.styleAttrs[byName.fontSize.qname],
-                        i === "0" || i === "2" ? element.styleAttrs[byName.extent.qname].h : element.styleAttrs[byName.extent.qname].w,
-                        i === "0" || i === "2" ? doc.cellLength.h : doc.cellLength.w,
-                        i === "0" || i === "2" ? doc.pxLength.h : doc.pxLength.w
-                    );
-                    if (out[i] === null) return null;
-                }
-            }
-            return out;
-        }
-    ),
-    new StylingAttributeDefinition(
-        imscNames.ns_tts,
-        "position",
-        "top left",
-        ['region'],
-        false,
-        true,
-        function (str) {
-            return imscUtils.parsePosition(str);
-        },
-        function (doc, parent, element, attr) {
-            let h;
-            let w;
-            h = imscUtils.toComputedLength(
-                attr.v.offset.value,
-                attr.v.offset.unit,
-                null,
-                new imscUtils.ComputedLength(
-                    -element.styleAttrs[byName.extent.qname].h.rw,
-                    doc.dimensions.h.rh - element.styleAttrs[byName.extent.qname].h.rh
-                ),
-                null,
-                doc.pxLength.h
-            );
-            if (h === null) return null;
-            if (attr.v.edge === "bottom") {
-                h = new imscUtils.ComputedLength(
-                    -h.rw - element.styleAttrs[byName.extent.qname].h.rw,
-                    doc.dimensions.h.rh - h.rh - element.styleAttrs[byName.extent.qname].h.rh
-                );
-            }
-            w = imscUtils.toComputedLength(
-                attr.h.offset.value,
-                attr.h.offset.unit,
-                null,
-                new imscUtils.ComputedLength(
-                    doc.dimensions.w.rw - element.styleAttrs[byName.extent.qname].w.rw,
-                    -element.styleAttrs[byName.extent.qname].w.rh
-                ),
-                null,
-                doc.pxLength.w
-            );
-            if (h === null) return null;
-            if (attr.h.edge === "right") {
-                w = new imscUtils.ComputedLength(
-                    doc.dimensions.w.rw - w.rw - element.styleAttrs[byName.extent.qname].w.rw,
-                    -w.rh - element.styleAttrs[byName.extent.qname].w.rh
-                );
-            }
-            return {'h': h, 'w': w};
-        }
-    ),
-    new StylingAttributeDefinition(
-        imscNames.ns_tts,
-        "ruby",
-        "none",
-        ['span'],
-        false,
-        true,
-        function (str) {
-            return str;
-        },
-        null
-    ),
-    new StylingAttributeDefinition(
-        imscNames.ns_tts,
-        "rubyAlign",
-        "center",
-        ['span'],
-        true,
-        true,
-        function (str) {
-            if (!(str === "center" || str === "spaceAround")) {
-                return null;
-            }
-            return str;
-        },
-        null
-    ),
-    new StylingAttributeDefinition(
-        imscNames.ns_tts,
-        "rubyPosition",
-        "outside",
-        ['span'],
-        true,
-        true,
-        function (str) {
-            return str;
-        },
-        null
-    ),
-    new StylingAttributeDefinition(
-        imscNames.ns_tts,
-        "rubyReserve",
-        "none",
-        ['p'],
-        true,
-        true,
-        function (str) {
-            let s = str.split(" ");
-            let r = [null, null];
-            if (s.length === 0 || s.length > 2)
-                return null;
-            if (s[0] === "none" ||
-                s[0] === "both" ||
-                s[0] === "after" ||
-                s[0] === "before" ||
-                s[0] === "outside") {
-                r[0] = s[0];
-            } else {
-                return null;
-            }
-            if (s.length === 2 && s[0] !== "none") {
-                let l = imscUtils.parseLength(s[1]);
-                if (l) {
-                    r[1] = l;
-                } else {
-                    return null;
-                }
-            }
-            return r;
-        },
-        function (doc, parent, element, attr) {
-            if (attr[0] === "none") {
-                return attr;
-            }
-            let fs;
-            if (attr[1] === null) {
-                fs = new imscUtils.ComputedLength(
-                    element.styleAttrs[byName.fontSize.qname].rw * 0.5,
-                    element.styleAttrs[byName.fontSize.qname].rh * 0.5
-                );
-            } else {
-                fs = imscUtils.toComputedLength(attr[1].value,
-                    attr[1].unit,
-                    element.styleAttrs[byName.fontSize.qname],
-                    element.styleAttrs[byName.fontSize.qname],
-                    doc.cellLength.h,
-                    doc.pxLength.h
-                );
-            }
-            if (fs === null) return null;
-            return [attr[0], fs];
-        }
-    ),
-    new StylingAttributeDefinition(
-        imscNames.ns_tts,
-        "showBackground",
-        "always",
-        ['region'],
-        false,
-        true,
-        function (str) {
-            return str;
-        },
-        null
-    ),
-    new StylingAttributeDefinition(
-        imscNames.ns_tts,
-        "textAlign",
-        "start",
-        ['p'],
-        true,
-        true,
-        function (str) {
-            return str;
-        },
-        function (doc, parent, element, attr) {
-            /* Section 7.16.9 of XSL */
-            if (attr === "left") {
-                return "start";
-            } else if (attr === "right") {
-                return "end";
-            } else {
-                return attr;
-            }
-        }
-    ),
-    new StylingAttributeDefinition(
-        imscNames.ns_tts,
-        "textCombine",
-        "none",
-        ['span'],
-        true,
-        true,
-        function (str) {
-            let s = str.split(" ");
-            if (s.length === 1) {
-                if (s[0] === "none" || s[0] === "all") {
-                    return [s[0]];
-                }
-            }
-            return null;
-        },
-        null
-    ),
-    new StylingAttributeDefinition(
-        imscNames.ns_tts,
-        "textDecoration",
-        "none",
-        ['span'],
-        true,
-        true,
-        function (str) {
-            return str.split(" ");
-        },
-        null
-    ),
-    new StylingAttributeDefinition(
-        imscNames.ns_tts,
-        "textEmphasis",
-        "none",
-        ['span'],
-        true,
-        true,
-        function (str) {
-            let e = str.split(" ");
-            let rslt = {style: null, symbol: null, color: null, position: null};
-            for (let el of e) {
-                if (el === "none" || el === "auto") {
-                    rslt.style = el;
-                } else if (el === "filled" ||
-                    el === "open") {
-                    rslt.style = el;
-                } else if (el === "circle" ||
-                    el === "dot" ||
-                    el === "sesame") {
-                    rslt.symbol = el;
-                } else if (el === "current") {
-                    rslt.color = el;
-                } else if (el === "outside" || el === "before" || el === "after") {
-                    rslt.position = el;
-                } else {
-                    rslt.color = imscUtils.parseColor(el);
-                    if (rslt.color === null)
-                        return null;
-                }
-            }
-            if (rslt.style == null && rslt.symbol == null) {
-                rslt.style = "auto";
-            } else {
-                rslt.symbol = rslt.symbol || "circle";
-                rslt.style = rslt.style || "filled";
-            }
-            rslt.position = rslt.position || "outside";
-            rslt.color = rslt.color || "current";
-            return rslt;
-        },
-        null
-    ),
-    new StylingAttributeDefinition(
-        imscNames.ns_tts,
-        "textOutline",
-        "none",
-        ['span'],
-        true,
-        true,
-        function (str) {
-            /*
-             * returns {c: <color>?, thichness: <length>} | "none"
-             *
-             */
-            if (str === "none") {
-                return str;
-            } else {
-                let r = {};
-                let s = str.split(" ");
-                if (s.length === 0 || s.length > 2)
-                    return null;
-                let c = imscUtils.parseColor(s[0]);
-                r.color = c;
-                if (c !== null)
-                    s.shift();
-                if (s.length !== 1)
-                    return null;
-                let l = imscUtils.parseLength(s[0]);
-                if (!l)
-                    return null;
-                r.thickness = l;
-                return r;
-            }
-        },
-        function (doc, parent, element, attr) {
-            /*
-             * returns {color: <color>, thickness: <norm length>}
-             *
-             */
-            if (attr === "none")
-                return attr;
-            let rslt = {};
-            if (attr.color === null) {
-                rslt.color = element.styleAttrs[byName.color.qname];
-            } else {
-                rslt.color = attr.color;
-            }
-            rslt.thickness = imscUtils.toComputedLength(
-                attr.thickness.value,
-                attr.thickness.unit,
-                element.styleAttrs[byName.fontSize.qname],
-                element.styleAttrs[byName.fontSize.qname],
-                doc.cellLength.h,
-                doc.pxLength.h
-            );
-            if (rslt.thickness === null)
-                return null;
-            return rslt;
-        }
-    ),
-    new StylingAttributeDefinition(
-        imscNames.ns_tts,
-        "textShadow",
-        "none",
-        ['span'],
-        true,
-        true,
-        imscUtils.parseTextShadow,
-        function (doc, parent, element, attr) {
-            /*
-             * returns [{x_off: <length>, y_off: <length>, b_radius: <length>, color: <color>}*] or "none"
-             *
-             */
-            if (attr === "none")
-                return attr;
-            let r = [];
-            for (let el of attr) {
-                let shadow = {};
-                shadow.x_off = imscUtils.toComputedLength(
-                    el[0].value,
-                    el[0].unit,
-                    null,
-                    element.styleAttrs[byName.fontSize.qname],
-                    null,
-                    doc.pxLength.w
-                );
-                if (shadow.x_off === null)
-                    return null;
-                shadow.y_off = imscUtils.toComputedLength(
-                    el[1].value,
-                    el[1].unit,
-                    null,
-                    element.styleAttrs[byName.fontSize.qname],
-                    null,
-                    doc.pxLength.h
-                );
-                if (shadow.y_off === null)
-                    return null;
-                if (el[2] === null) {
-                    shadow.b_radius = 0;
-                } else {
-                    shadow.b_radius = imscUtils.toComputedLength(
-                        el[2].value,
-                        el[2].unit,
-                        null,
-                        element.styleAttrs[byName.fontSize.qname],
-                        null,
-                        doc.pxLength.h
-                    );
-                    if (shadow.b_radius === null)
-                        return null;
-                }
-                if (el[3] === null) {
-                    shadow.color = element.styleAttrs[byName.color.qname];
-                } else {
-                    shadow.color = el[3];
-                }
-                r.push(shadow);
-            }
-            return r;
-        }
-    ),
-    new StylingAttributeDefinition(
-        imscNames.ns_tts,
-        "unicodeBidi",
-        "normal",
-        ['span', 'p'],
-        false,
-        true,
-        function (str) {
-            return str;
-        },
-        null
-    ),
-    new StylingAttributeDefinition(
-        imscNames.ns_tts,
-        "visibility",
-        "visible",
-        ['body', 'div', 'p', 'region', 'span'],
-        true,
-        true,
-        function (str) {
-            return str;
-        },
-        null
-    ),
-    new StylingAttributeDefinition(
-        imscNames.ns_tts,
-        "wrapOption",
-        "wrap",
-        ['span'],
-        true,
-        true,
-        function (str) {
-            return str;
-        },
-        null
-    ),
-    new StylingAttributeDefinition(
-        imscNames.ns_tts,
-        "writingMode",
-        "lrtb",
-        ['region'],
-        false,
-        true,
-        function (str) {
-            return str;
-        },
-        null
-    ),
-    new StylingAttributeDefinition(
-        imscNames.ns_tts,
-        "zIndex",
-        "auto",
-        ['region'],
-        false,
-        true,
-        function (str) {
-            let rslt;
-            if (str === 'auto') {
-                rslt = str;
-            } else {
-                rslt = parseInt(str);
-                if (isNaN(rslt)) {
-                    rslt = null;
-                }
-            }
-            return rslt;
-        },
-        null
-    ),
-    new StylingAttributeDefinition(
-        imscNames.ns_ebutts,
-        "linePadding",
-        "0c",
-        ['p'],
-        true,
-        false,
-        imscUtils.parseLength,
-        function (doc, parent, element, attr) {
-            return imscUtils.toComputedLength(attr.value, attr.unit, null, null, doc.cellLength.w, null);
-        }
-    ),
-    new StylingAttributeDefinition(
-        imscNames.ns_ebutts,
-        "multiRowAlign",
-        "auto",
-        ['p'],
-        true,
-        false,
-        function (str) {
-            return str;
-        },
-        null
-    ),
-    new StylingAttributeDefinition(
-        imscNames.ns_smpte,
-        "backgroundImage",
-        null,
-        ['div'],
-        false,
-        false,
-        function (str) {
-            return str;
-        },
-        null
-    ),
-    new StylingAttributeDefinition(
-        imscNames.ns_itts,
-        "forcedDisplay",
-        "false",
-        ['body', 'div', 'p', 'region', 'span'],
-        true,
-        true,
-        function (str) {
-            return str === 'true';
-        },
-        null
-    ),
-    new StylingAttributeDefinition(
-        imscNames.ns_itts,
-        "fillLineGap",
-        "false",
-        ['p'],
-        true,
-        true,
-        function (str) {
-            return str === 'true';
-        },
-        null
-    )
-];
-/* TODO: allow null parse function */
-export const byQName = Object.fromEntries(all.map(it => [it.qname, it]));
-export const byName = Object.fromEntries(all.map(it => [it.name, it]));
diff --git a/src/util/ttml/utils.js b/src/util/ttml/utils.js
deleted file mode 100644
index 320460e..0000000
--- a/src/util/ttml/utils.js
+++ /dev/null
@@ -1,284 +0,0 @@
-/* 
- * Copyright (c) 2016, Pierre-Anthony Lemieux <pal@sandflow.com>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * * Redistributions of source code must retain the above copyright notice, this
- *   list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright notice,
- *   this list of conditions and the following disclaimer in the documentation
- *   and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-/*
- * Parses a TTML color expression
- *
- */
-let HEX_COLOR_RE = /#([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})?/;
-let DEC_COLOR_RE = /rgb\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)/;
-let DEC_COLORA_RE = /rgba\(\s*(\d+),\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)/;
-let NAMED_COLOR = {
-    transparent: [0, 0, 0, 0],
-    black: [0, 0, 0, 255],
-    silver: [192, 192, 192, 255],
-    gray: [128, 128, 128, 255],
-    white: [255, 255, 255, 255],
-    maroon: [128, 0, 0, 255],
-    red: [255, 0, 0, 255],
-    purple: [128, 0, 128, 255],
-    fuchsia: [255, 0, 255, 255],
-    magenta: [255, 0, 255, 255],
-    green: [0, 128, 0, 255],
-    lime: [0, 255, 0, 255],
-    olive: [128, 128, 0, 255],
-    yellow: [255, 255, 0, 255],
-    navy: [0, 0, 128, 255],
-    blue: [0, 0, 255, 255],
-    teal: [0, 128, 128, 255],
-    aqua: [0, 255, 255, 255],
-    cyan: [0, 255, 255, 255]
-};
-
-export function parseColor(str) {
-    let m;
-    let r = null;
-    let nc = NAMED_COLOR[str.toLowerCase()];
-    if (nc !== undefined) {
-        r = nc;
-    } else if ((m = HEX_COLOR_RE.exec(str)) !== null) {
-        r = [parseInt(m[1], 16),
-            parseInt(m[2], 16),
-            parseInt(m[3], 16),
-            (m[4] !== undefined ? parseInt(m[4], 16) : 255)];
-    } else if ((m = DEC_COLOR_RE.exec(str)) !== null) {
-        r = [parseInt(m[1]),
-            parseInt(m[2]),
-            parseInt(m[3]),
-            255];
-    } else if ((m = DEC_COLORA_RE.exec(str)) !== null) {
-        r = [parseInt(m[1]),
-            parseInt(m[2]),
-            parseInt(m[3]),
-            parseInt(m[4])];
-    }
-    return r;
-}
-
-let LENGTH_RE = /^([+-]?\d*(?:\.\d+)?)(px|em|c|%|rh|rw)$/;
-
-export function parseLength(str) {
-    let m;
-    let r = null;
-    if ((m = LENGTH_RE.exec(str)) !== null) {
-        r = {value: parseFloat(m[1]), unit: m[2]};
-    }
-    return r;
-}
-
-export function parseTextShadow(str) {
-    let shadows = str.split(",");
-    let r = [];
-    for (let element of shadows) {
-        let shadow = element.split(" ");
-        if (shadow.length === 1 && shadow[0] === "none") {
-            return "none";
-        } else if (shadow.length > 1 && shadow.length < 5) {
-            let out_shadow = [null, null, null, null];
-            /* x offset */
-            let l = parseLength(shadow.shift());
-            if (l === null)
-                return null;
-            out_shadow[0] = l;
-            /* y offset */
-            l = parseLength(shadow.shift());
-            if (l === null)
-                return null;
-            out_shadow[1] = l;
-            /* is there a third component */
-            if (shadow.length === 0) {
-                r.push(out_shadow);
-                continue;
-            }
-            l = parseLength(shadow[0]);
-            if (l !== null) {
-                out_shadow[2] = l;
-                shadow.shift();
-            }
-            if (shadow.length === 0) {
-                r.push(out_shadow);
-                continue;
-            }
-            let c = parseColor(shadow[0]);
-            if (c === null)
-                return null;
-            out_shadow[3] = c;
-            r.push(out_shadow);
-        }
-    }
-    return r;
-}
-
-export function parsePosition(str) {
-    /* see https://www.w3.org/TR/ttml2/#style-value-position */
-    let s = str.split(" ");
-    let isKeyword = function (str) {
-        return str === "center" ||
-            str === "left" ||
-            str === "top" ||
-            str === "bottom" ||
-            str === "right";
-    };
-    if (s.length > 4) {
-        return null;
-    }
-    /* initial clean-up pass */
-    for (let j = 0; j < s.length; j++) {
-        if (!isKeyword(s[j])) {
-            let l = parseLength(s[j]);
-            if (l === null)
-                return null;
-            s[j] = l;
-        }
-    }
-    /* position default */
-    let pos = {
-        h: {edge: "left", offset: {value: 50, unit: "%"}},
-        v: {edge: "top", offset: {value: 50, unit: "%"}}
-    };
-    /* update position */
-    for (let i = 0; i < s.length;) {
-        /* extract the current component */
-        let comp = s[i++];
-        if (isKeyword(comp)) {
-            /* we have a keyword */
-            let offset = {value: 0, unit: "%"};
-            /* peek at the next component */
-            if (s.length !== 2 && i < s.length && (!isKeyword(s[i]))) {
-                /* followed by an offset */
-                offset = s[i++];
-            }
-            /* skip if center */
-            if (comp === "right") {
-                pos.h.edge = comp;
-                pos.h.offset = offset;
-            } else if (comp === "bottom") {
-                pos.v.edge = comp;
-                pos.v.offset = offset;
-            } else if (comp === "left") {
-                pos.h.offset = offset;
-            } else if (comp === "top") {
-                pos.v.offset = offset;
-            }
-        } else if (s.length === 1 || s.length === 2) {
-            /* we have a bare value */
-            if (i === 1) {
-                /* assign it to left edge if first bare value */
-                pos.h.offset = comp;
-            } else {
-                /* assign it to top edge if second bare value */
-                pos.v.offset = comp;
-            }
-        } else {
-            /* error condition */
-            return null;
-        }
-    }
-    return pos;
-}
-
-export function ComputedLength(rw, rh) {
-    this.rw = rw;
-    this.rh = rh;
-}
-
-ComputedLength.prototype.toUsedLength = function (width, height) {
-    return width * this.rw + height * this.rh;
-};
-ComputedLength.prototype.isZero = function () {
-    return this.rw === 0 && this.rh === 0;
-};
-
-/**
- * Computes a specified length to a root container relative length
- *
- * @param {number} lengthVal Length value to be computed
- * @param {string} lengthUnit Units of the length value
- * @param {?ComputedLength} emScale length of 1em, or null if em is not allowed
- * @param {?ComputedLength} percentScale length to which , or null if percentage is not allowed
- * @param {?ComputedLength} cellScale length of 1c, or null if c is not allowed
- * @param {?ComputedLength} pxScale length of 1px, or null if px is not allowed
- * @return {ComputedLength} Computed length
- */
-export function toComputedLength(lengthVal, lengthUnit, emScale, percentScale, cellScale, pxScale) {
-    if (lengthUnit === "%" && percentScale) {
-        return new ComputedLength(
-            percentScale.rw * lengthVal / 100,
-            percentScale.rh * lengthVal / 100
-        );
-    } else if (lengthUnit === "em" && emScale) {
-        return new ComputedLength(
-            emScale.rw * lengthVal,
-            emScale.rh * lengthVal
-        );
-    } else if (lengthUnit === "c" && cellScale) {
-        return new ComputedLength(
-            lengthVal * cellScale.rw,
-            lengthVal * cellScale.rh
-        );
-    } else if (lengthUnit === "px" && pxScale) {
-        return new ComputedLength(
-            lengthVal * pxScale.rw,
-            lengthVal * pxScale.rh
-        );
-    } else if (lengthUnit === "rh") {
-        return new ComputedLength(
-            0,
-            lengthVal / 100
-        );
-    } else if (lengthUnit === "rw") {
-        return new ComputedLength(
-            lengthVal / 100,
-            0
-        );
-    } else {
-        return null;
-    }
-}
-
-/*
- * ERROR HANDLING UTILITY FUNCTIONS
- *
- */
-export function reportInfo(errorHandler, msg) {
-    if (errorHandler && errorHandler.info && errorHandler.info(msg))
-        throw msg;
-}
-
-export function reportWarning(errorHandler, msg) {
-    if (errorHandler && errorHandler.warn && errorHandler.warn(msg))
-        throw msg;
-}
-
-export function reportError(errorHandler, msg) {
-    if (errorHandler && errorHandler.error && errorHandler.error(msg))
-        throw msg;
-}
-
-export function reportFatal(errorHandler, msg) {
-    if (errorHandler && errorHandler.fatal)
-        errorHandler.fatal(msg);
-    throw msg;
-}
diff --git a/tsconfig.json b/tsconfig.json
index e18c413..d08a2cf 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -6,6 +6,17 @@
       "dom.iterable",
       "esnext"
     ],
+    "typeRoots": [
+      "./node_modules/@types",
+      "./@types"
+    ],
+    "baseUrl": ".",
+    "paths": {
+      "*": [
+        "*",
+        "./@types/*"
+      ]
+    },
     "allowJs": true,
     "skipLibCheck": true,
     "esModuleInterop": true,
-- 
GitLab