diff --git a/dist/bin/js/bundle.js b/dist/bin/js/bundle.js
index f0e0ebd..ea79b6b 100644
--- a/dist/bin/js/bundle.js
+++ b/dist/bin/js/bundle.js
@@ -26,7 +26,7 @@ return /******/ (() => { // webpackBootstrap
 /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
 
 "use strict";
-eval("\n\nfunction _typeof(obj) { \"@babel/helpers - typeof\"; if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }; } return _typeof(obj); }\n\nObject.defineProperty(exports, \"__esModule\", ({\n  value: true\n}));\nexports.default = void 0;\n\nvar _AudioNub2 = _interopRequireDefault(__webpack_require__(/*! ./AudioNub.es6 */ \"./src/AudioNub.es6\"));\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { \"default\": obj }; }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\nfunction _get(target, property, receiver) { if (typeof Reflect !== \"undefined\" && Reflect.get) { _get = Reflect.get; } else { _get = function _get(target, property, receiver) { var base = _superPropBase(target, property); if (!base) return; var desc = Object.getOwnPropertyDescriptor(base, property); if (desc.get) { return desc.get.call(receiver); } return desc.value; }; } return _get(target, property, receiver || target); }\n\nfunction _superPropBase(object, property) { while (!Object.prototype.hasOwnProperty.call(object, property)) { object = _getPrototypeOf(object); if (object === null) break; } return object; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\n\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\n\nfunction _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }\n\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === \"object\" || typeof call === \"function\")) { return call; } else if (call !== void 0) { throw new TypeError(\"Derived constructors may only return object or undefined\"); } return _assertThisInitialized(self); }\n\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return self; }\n\nfunction _isNativeReflectConstruct() { if (typeof Reflect === \"undefined\" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === \"function\") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }\n\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\n\n// import Logger from \"./Logger.es6\";\nvar Logger = __webpack_require__(/*! ./Logger.es6 */ \"./src/Logger.es6\").Logger; // import TextPresenter from \"./TextPresenter.es6\";\n\n\nvar TextPresenter = __webpack_require__(/*! ./TextPresenter.es6 */ \"./src/TextPresenter.es6\").TextPresenter;\n\nvar defaultOutput = null;\n\nvar AdLeafNode = /*#__PURE__*/function (_AudioNub) {\n  _inherits(AdLeafNode, _AudioNub);\n\n  var _super = _createSuper(AdLeafNode);\n\n  function AdLeafNode(parent, node, audioContext) {\n    var _this;\n\n    _classCallCheck(this, AdLeafNode);\n\n    _this = _super.call(this, parent, node, audioContext);\n\n    if (!_this._name) {\n      _this._name = \"span (anonymous)\";\n    }\n\n    return _this;\n  }\n\n  _createClass(AdLeafNode, [{\n    key: \"makeDefaultOutput\",\n    value: function makeDefaultOutput() {\n      if (defaultOutput) {\n        defaultOutput.onInactive();\n      }\n\n      this.onActive();\n      defaultOutput = this;\n    }\n  }, {\n    key: \"onActive\",\n    value: function onActive() {\n      if (!this.isActive) {\n        this.output.connect(this.audioContext.destination);\n\n        if (defaultOutput && defaultOutput !== this) {\n          defaultOutput.onInactive();\n        }\n\n        Logger.log(\"Active leaf: \".concat(this.pathString));\n      }\n\n      _get(_getPrototypeOf(AdLeafNode.prototype), \"onActive\", this).call(this);\n\n      if (this.value) {\n        this.tpKey = TextPresenter.present(this.value, this.pathString);\n      }\n    }\n  }, {\n    key: \"onInactive\",\n    value: function onInactive() {\n      if (this.isActive) {\n        if (this.tpKey) {\n          TextPresenter.unPresent(this.tpKey);\n        }\n\n        this.output.disconnect(this.audioContext.destination);\n\n        if (defaultOutput && defaultOutput !== this) {\n          defaultOutput.onActive();\n        }\n\n        Logger.log(\"Inactive leaf: \".concat(this.pathString));\n      }\n\n      _get(_getPrototypeOf(AdLeafNode.prototype), \"onInactive\", this).call(this);\n    }\n  }]);\n\n  return AdLeafNode;\n}(_AudioNub2[\"default\"]);\n\nexports.default = AdLeafNode;\n\n//# sourceURL=webpack://adhere-lib/./src/AdLeafNode.es6?");
+eval("\n\nfunction _typeof(obj) { \"@babel/helpers - typeof\"; if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }; } return _typeof(obj); }\n\nObject.defineProperty(exports, \"__esModule\", ({\n  value: true\n}));\nexports[\"default\"] = void 0;\n\nvar _AudioNub2 = _interopRequireDefault(__webpack_require__(/*! ./AudioNub.es6 */ \"./src/AudioNub.es6\"));\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { \"default\": obj }; }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\nfunction _get(target, property, receiver) { if (typeof Reflect !== \"undefined\" && Reflect.get) { _get = Reflect.get; } else { _get = function _get(target, property, receiver) { var base = _superPropBase(target, property); if (!base) return; var desc = Object.getOwnPropertyDescriptor(base, property); if (desc.get) { return desc.get.call(receiver); } return desc.value; }; } return _get(target, property, receiver || target); }\n\nfunction _superPropBase(object, property) { while (!Object.prototype.hasOwnProperty.call(object, property)) { object = _getPrototypeOf(object); if (object === null) break; } return object; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\n\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\n\nfunction _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }\n\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === \"object\" || typeof call === \"function\")) { return call; } else if (call !== void 0) { throw new TypeError(\"Derived constructors may only return object or undefined\"); } return _assertThisInitialized(self); }\n\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return self; }\n\nfunction _isNativeReflectConstruct() { if (typeof Reflect === \"undefined\" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === \"function\") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }\n\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\n\n// import Logger from \"./Logger.es6\";\nvar Logger = __webpack_require__(/*! ./Logger.es6 */ \"./src/Logger.es6\").Logger; // import TextPresenter from \"./TextPresenter.es6\";\n\n\nvar TextPresenter = __webpack_require__(/*! ./TextPresenter.es6 */ \"./src/TextPresenter.es6\").TextPresenter;\n\nvar defaultOutput = null;\n\nvar AdLeafNode = /*#__PURE__*/function (_AudioNub) {\n  _inherits(AdLeafNode, _AudioNub);\n\n  var _super = _createSuper(AdLeafNode);\n\n  function AdLeafNode(parent, node, audioContext) {\n    var _this;\n\n    _classCallCheck(this, AdLeafNode);\n\n    _this = _super.call(this, parent, node, audioContext);\n\n    if (!_this._name) {\n      _this._name = \"span (anonymous)\";\n    }\n\n    return _this;\n  }\n\n  _createClass(AdLeafNode, [{\n    key: \"makeDefaultOutput\",\n    value: function makeDefaultOutput() {\n      if (defaultOutput) {\n        defaultOutput.onInactive();\n      }\n\n      this.onActive();\n      defaultOutput = this;\n    }\n  }, {\n    key: \"onActive\",\n    value: function onActive() {\n      if (!this.isActive) {\n        this.output.connect(this.audioContext.destination);\n\n        if (defaultOutput && defaultOutput !== this) {\n          defaultOutput.onInactive();\n        }\n\n        Logger.log(\"Active leaf: \".concat(this.pathString));\n      }\n\n      _get(_getPrototypeOf(AdLeafNode.prototype), \"onActive\", this).call(this);\n\n      if (this.value) {\n        this.tpKey = TextPresenter.present(this.value, this.pathString);\n      }\n    }\n  }, {\n    key: \"onInactive\",\n    value: function onInactive() {\n      if (this.isActive) {\n        if (this.tpKey) {\n          TextPresenter.unPresent(this.tpKey);\n        }\n\n        this.output.disconnect(this.audioContext.destination);\n\n        if (defaultOutput && defaultOutput !== this) {\n          defaultOutput.onActive();\n        }\n\n        Logger.log(\"Inactive leaf: \".concat(this.pathString));\n      }\n\n      _get(_getPrototypeOf(AdLeafNode.prototype), \"onInactive\", this).call(this);\n    }\n  }]);\n\n  return AdLeafNode;\n}(_AudioNub2[\"default\"]);\n\nexports[\"default\"] = AdLeafNode;\n\n//# sourceURL=webpack://adhere-lib/./src/AdLeafNode.es6?");
 
 /***/ }),
 
@@ -37,7 +37,7 @@ eval("\n\nfunction _typeof(obj) { \"@babel/helpers - typeof\"; if (typeof Symbol
 /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
 
 "use strict";
-eval("\n\nObject.defineProperty(exports, \"__esModule\", ({\n  value: true\n}));\nexports.default = void 0;\n\nvar _Utils = _interopRequireDefault(__webpack_require__(/*! ./Utils.es6 */ \"./src/Utils.es6\"));\n\nvar _TimingCalculator = _interopRequireDefault(__webpack_require__(/*! ./TimingCalculator.es6 */ \"./src/TimingCalculator.es6\"));\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { \"default\": obj }; }\n\nfunction _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== \"undefined\" && o[Symbol.iterator] || o[\"@@iterator\"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === \"number\") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError(\"Invalid attempt to iterate non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it[\"return\"] != null) it[\"return\"](); } finally { if (didErr) throw err; } } }; }\n\nfunction _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === \"string\") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === \"Object\" && o.constructor) n = o.constructor.name; if (n === \"Map\" || n === \"Set\") return Array.from(o); if (n === \"Arguments\" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }\n\nfunction _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\n//import Logger from \"./Logger.es6\";\nvar Logger = __webpack_require__(/*! ./Logger.es6 */ \"./src/Logger.es6\").Logger;\n\nvar AdNode = /*#__PURE__*/function () {\n  function AdNode(parent, xmlNode, audioContext) {\n    _classCallCheck(this, AdNode);\n\n    this._xmlNode = xmlNode;\n    this.parent = parent;\n    this.time = {\n      begin: _TimingCalculator[\"default\"].computeBegin(xmlNode),\n      end: undefined\n    };\n    this._name = xmlNode.name;\n    this._value = xmlNode.value;\n\n    if (xmlNode.attributes) {\n      this._pitch = _Utils[\"default\"].getAttributeByFullyQualifiedName(xmlNode, \"\".concat(_Utils[\"default\"].NS_TTML_AUDIO_URI, \"%%pitch\"));\n      this._speak = _Utils[\"default\"].getAttributeByFullyQualifiedName(xmlNode, \"\".concat(_Utils[\"default\"].NS_TTML_AUDIO_URI, \"%%speak\"));\n      this._id = _Utils[\"default\"].getAttributeByFullyQualifiedName(xmlNode, \"\".concat(_Utils[\"default\"].NS_XML_URI, \"%%id\"));\n    }\n\n    if (audioContext) {\n      this.ac = audioContext;\n    } // Logger.log(`Constructed an AdNode for ${this.pathString}, value \\\"${this.value}\\\"\n    // ${this.begin} --> ${this.end}`); // DEBUG\n\n  }\n\n  _createClass(AdNode, [{\n    key: \"postComputeEnd\",\n    value: function postComputeEnd() {\n      this.time.end = _TimingCalculator[\"default\"].computeEnd(this._xmlNode); // Logger.log(`postComputeEnd() for ${this.pathString}, value \\\"${this.value}\\\"\n      // ${this.begin} --> ${this.end}`); // DEBUG\n\n      if (this.children) {\n        this.children.forEach(function (c) {\n          c.postComputeEnd();\n        });\n      }\n    }\n  }, {\n    key: \"audioContext\",\n    get: function get() {\n      if (this.ac) {\n        return this.ac;\n      }\n\n      if (this.parent) {\n        return this.parent.audioContext;\n      }\n\n      return null;\n    }\n  }, {\n    key: \"begin\",\n    get: function get() {\n      var begin = NaN;\n\n      if (this.time) {\n        begin = this.time.begin;\n      }\n\n      return begin;\n    }\n  }, {\n    key: \"end\",\n    get: function get() {\n      var end = NaN;\n\n      if (this.time) {\n        end = this.time.end;\n      }\n\n      return end;\n    }\n  }, {\n    key: \"pitch\",\n    get: function get() {\n      if (this._pitch || this._pitch === 0) {\n        return this._pitch;\n      } else if (this.parent) {\n        return this.parent.pitch;\n      }\n\n      return undefined;\n    }\n  }, {\n    key: \"speak\",\n    get: function get() {\n      if (this._speak) {\n        return this._speak;\n      } else if (this.parent) {\n        return this.parent.speak;\n      }\n\n      return undefined;\n    }\n  }, {\n    key: \"value\",\n    get: function get() {\n      return this._value;\n    }\n  }, {\n    key: \"videoMedia\",\n    get: function get() {\n      return this._videoMedia;\n    },\n    set: function set(vm) {\n      this._videoMedia = vm;\n    }\n  }, {\n    key: \"makeCueObjects\",\n    value: function makeCueObjects(arr, videoMedia) {\n      var _this = this;\n\n      this.videoMedia = videoMedia;\n      var b = this.begin;\n      var e = !isNaN(this.end) ? this.end : videoMedia.duration;\n      var v = this.value;\n\n      if (!isNaN(b) && !isNaN(e)) {\n        // Logger.log(`Making a cue for ${ this.pathString }, \\\"${ v }\\\",\n        // ${b} --> ${e}.`); // DEBUG\n        var newCue = new VTTCue(b, e, v);\n\n        newCue.onenter = function () {\n          return _this.onActive();\n        };\n\n        newCue.onexit = function () {\n          return _this.onInactive();\n        };\n\n        arr.push(newCue); // } else {\n        //   Logger.log(`Not making a cue for ${ this.pathString }, \\\"${ v }\\\"\n        //   because b (${b}) or e (${e}) is NaN.`); // DEBUG\n      }\n\n      if (this.children) {\n        var _iterator = _createForOfIteratorHelper(this.children),\n            _step;\n\n        try {\n          for (_iterator.s(); !(_step = _iterator.n()).done;) {\n            var c = _step.value;\n            c.makeCueObjects(arr, videoMedia);\n          }\n        } catch (err) {\n          _iterator.e(err);\n        } finally {\n          _iterator.f();\n        }\n      }\n    } //Go down the tree, apply fn(c) to all children\n\n  }, {\n    key: \"traverse\",\n    value: function traverse(fn) {\n      fn(this);\n\n      if (this.children) {\n        var _iterator2 = _createForOfIteratorHelper(this.children),\n            _step2;\n\n        try {\n          for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {\n            var c = _step2.value;\n            c.traverse(fn);\n          }\n        } catch (err) {\n          _iterator2.e(err);\n        } finally {\n          _iterator2.f();\n        }\n      }\n    }\n  }, {\n    key: \"name\",\n    get: function get() {\n      return this._name;\n    }\n  }, {\n    key: \"pathString\",\n    get: function get() {\n      return (this.parent ? \"\".concat(this.parent.pathString, \" -> \") : \"\") + \"\".concat(this.name).concat(this.idString);\n    }\n  }, {\n    key: \"idString\",\n    get: function get() {\n      return this._id ? \" id:\\\"\".concat(this._id, \"\\\"\") : \"\";\n    }\n  }, {\n    key: \"onActive\",\n    value: function onActive() {\n      this.isActive = true;\n      Logger.log(\"Active AdNode: \".concat(this.pathString));\n    }\n  }, {\n    key: \"onInactive\",\n    value: function onInactive() {\n      this.isActive = false;\n      Logger.log(\"Inactive AdNode: \".concat(this.pathString));\n    }\n  }, {\n    key: \"onFinalise\",\n    value: function onFinalise() {\n      if (this.isActive) {\n        this.onInactive();\n      }\n    }\n  }]);\n\n  return AdNode;\n}();\n\nexports.default = AdNode;\n\n//# sourceURL=webpack://adhere-lib/./src/AdNode.es6?");
+eval("\n\nObject.defineProperty(exports, \"__esModule\", ({\n  value: true\n}));\nexports[\"default\"] = void 0;\n\nvar _Utils = _interopRequireDefault(__webpack_require__(/*! ./Utils.es6 */ \"./src/Utils.es6\"));\n\nvar _TimingCalculator = _interopRequireDefault(__webpack_require__(/*! ./TimingCalculator.es6 */ \"./src/TimingCalculator.es6\"));\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { \"default\": obj }; }\n\nfunction _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== \"undefined\" && o[Symbol.iterator] || o[\"@@iterator\"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === \"number\") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError(\"Invalid attempt to iterate non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it[\"return\"] != null) it[\"return\"](); } finally { if (didErr) throw err; } } }; }\n\nfunction _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === \"string\") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === \"Object\" && o.constructor) n = o.constructor.name; if (n === \"Map\" || n === \"Set\") return Array.from(o); if (n === \"Arguments\" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }\n\nfunction _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\n//import Logger from \"./Logger.es6\";\nvar Logger = __webpack_require__(/*! ./Logger.es6 */ \"./src/Logger.es6\").Logger;\n\nvar AdNode = /*#__PURE__*/function () {\n  function AdNode(parent, xmlNode, audioContext) {\n    _classCallCheck(this, AdNode);\n\n    this._xmlNode = xmlNode;\n    this.parent = parent;\n    this.time = {\n      begin: _TimingCalculator[\"default\"].computeBegin(xmlNode),\n      end: undefined\n    };\n    this._name = xmlNode.name;\n    this._value = xmlNode.value;\n\n    if (xmlNode.attributes) {\n      this._pitch = _Utils[\"default\"].getAttributeByFullyQualifiedName(xmlNode, \"\".concat(_Utils[\"default\"].NS_TTML_AUDIO_URI, \"%%pitch\"));\n      this._speak = _Utils[\"default\"].getAttributeByFullyQualifiedName(xmlNode, \"\".concat(_Utils[\"default\"].NS_TTML_AUDIO_URI, \"%%speak\"));\n      this._id = _Utils[\"default\"].getAttributeByFullyQualifiedName(xmlNode, \"\".concat(_Utils[\"default\"].NS_XML_URI, \"%%id\"));\n    }\n\n    if (audioContext) {\n      this.ac = audioContext;\n    } // Logger.log(`Constructed an AdNode for ${this.pathString}, value \\\"${this.value}\\\"\n    // ${this.begin} --> ${this.end}`); // DEBUG\n\n  }\n\n  _createClass(AdNode, [{\n    key: \"postComputeEnd\",\n    value: function postComputeEnd() {\n      this.time.end = _TimingCalculator[\"default\"].computeEnd(this._xmlNode); // Logger.log(`postComputeEnd() for ${this.pathString}, value \\\"${this.value}\\\"\n      // ${this.begin} --> ${this.end}`); // DEBUG\n\n      if (this.children) {\n        this.children.forEach(function (c) {\n          c.postComputeEnd();\n        });\n      }\n    }\n  }, {\n    key: \"audioContext\",\n    get: function get() {\n      if (this.ac) {\n        return this.ac;\n      }\n\n      if (this.parent) {\n        return this.parent.audioContext;\n      }\n\n      return null;\n    }\n  }, {\n    key: \"begin\",\n    get: function get() {\n      var begin = NaN;\n\n      if (this.time) {\n        begin = this.time.begin;\n      }\n\n      return begin;\n    }\n  }, {\n    key: \"end\",\n    get: function get() {\n      var end = NaN;\n\n      if (this.time) {\n        end = this.time.end;\n      }\n\n      return end;\n    }\n  }, {\n    key: \"pitch\",\n    get: function get() {\n      if (this._pitch || this._pitch === 0) {\n        return this._pitch;\n      } else if (this.parent) {\n        return this.parent.pitch;\n      }\n\n      return undefined;\n    }\n  }, {\n    key: \"speak\",\n    get: function get() {\n      if (this._speak) {\n        return this._speak;\n      } else if (this.parent) {\n        return this.parent.speak;\n      }\n\n      return undefined;\n    }\n  }, {\n    key: \"value\",\n    get: function get() {\n      return this._value;\n    }\n  }, {\n    key: \"videoMedia\",\n    get: function get() {\n      return this._videoMedia;\n    },\n    set: function set(vm) {\n      this._videoMedia = vm;\n    }\n  }, {\n    key: \"makeCueObjects\",\n    value: function makeCueObjects(arr, videoMedia) {\n      var _this = this;\n\n      this.videoMedia = videoMedia;\n      var b = this.begin;\n      var e = !isNaN(this.end) ? this.end : videoMedia.duration;\n      var v = this.value;\n\n      if (!isNaN(b) && !isNaN(e)) {\n        // Logger.log(`Making a cue for ${ this.pathString }, \\\"${ v }\\\",\n        // ${b} --> ${e}.`); // DEBUG\n        var newCue = new VTTCue(b, e, v);\n\n        newCue.onenter = function () {\n          return _this.onActive();\n        };\n\n        newCue.onexit = function () {\n          return _this.onInactive();\n        };\n\n        arr.push(newCue); // } else {\n        //   Logger.log(`Not making a cue for ${ this.pathString }, \\\"${ v }\\\"\n        //   because b (${b}) or e (${e}) is NaN.`); // DEBUG\n      }\n\n      if (this.children) {\n        var _iterator = _createForOfIteratorHelper(this.children),\n            _step;\n\n        try {\n          for (_iterator.s(); !(_step = _iterator.n()).done;) {\n            var c = _step.value;\n            c.makeCueObjects(arr, videoMedia);\n          }\n        } catch (err) {\n          _iterator.e(err);\n        } finally {\n          _iterator.f();\n        }\n      }\n    } //Go down the tree, apply fn(c) to all children\n\n  }, {\n    key: \"traverse\",\n    value: function traverse(fn) {\n      fn(this);\n\n      if (this.children) {\n        var _iterator2 = _createForOfIteratorHelper(this.children),\n            _step2;\n\n        try {\n          for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {\n            var c = _step2.value;\n            c.traverse(fn);\n          }\n        } catch (err) {\n          _iterator2.e(err);\n        } finally {\n          _iterator2.f();\n        }\n      }\n    }\n  }, {\n    key: \"name\",\n    get: function get() {\n      return this._name;\n    }\n  }, {\n    key: \"pathString\",\n    get: function get() {\n      return (this.parent ? \"\".concat(this.parent.pathString, \" -> \") : \"\") + \"\".concat(this.name).concat(this.idString);\n    }\n  }, {\n    key: \"idString\",\n    get: function get() {\n      return this._id ? \" id:\\\"\".concat(this._id, \"\\\"\") : \"\";\n    }\n  }, {\n    key: \"onActive\",\n    value: function onActive() {\n      this.isActive = true;\n      Logger.log(\"Active AdNode: \".concat(this.pathString));\n    }\n  }, {\n    key: \"onInactive\",\n    value: function onInactive() {\n      this.isActive = false;\n      Logger.log(\"Inactive AdNode: \".concat(this.pathString));\n    }\n  }, {\n    key: \"onFinalise\",\n    value: function onFinalise() {\n      if (this.isActive) {\n        this.onInactive();\n      }\n    }\n  }]);\n\n  return AdNode;\n}();\n\nexports[\"default\"] = AdNode;\n\n//# sourceURL=webpack://adhere-lib/./src/AdNode.es6?");
 
 /***/ }),
 
@@ -48,7 +48,7 @@ eval("\n\nObject.defineProperty(exports, \"__esModule\", ({\n  value: true\n}));
 /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
 
 "use strict";
-eval("\n\nfunction _typeof(obj) { \"@babel/helpers - typeof\"; if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }; } return _typeof(obj); }\n\nObject.defineProperty(exports, \"__esModule\", ({\n  value: true\n}));\nexports.default = void 0;\n\nvar _AudioNub2 = _interopRequireDefault(__webpack_require__(/*! ./AudioNub.es6 */ \"./src/AudioNub.es6\"));\n\nvar _TimingCalculator = _interopRequireDefault(__webpack_require__(/*! ./TimingCalculator.es6 */ \"./src/TimingCalculator.es6\"));\n\nvar _PlaybackProperties = _interopRequireDefault(__webpack_require__(/*! ./PlaybackProperties.es6 */ \"./src/PlaybackProperties.es6\"));\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { \"default\": obj }; }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\nfunction _get(target, property, receiver) { if (typeof Reflect !== \"undefined\" && Reflect.get) { _get = Reflect.get; } else { _get = function _get(target, property, receiver) { var base = _superPropBase(target, property); if (!base) return; var desc = Object.getOwnPropertyDescriptor(base, property); if (desc.get) { return desc.get.call(receiver); } return desc.value; }; } return _get(target, property, receiver || target); }\n\nfunction _superPropBase(object, property) { while (!Object.prototype.hasOwnProperty.call(object, property)) { object = _getPrototypeOf(object); if (object === null) break; } return object; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\n\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\n\nfunction _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }\n\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === \"object\" || typeof call === \"function\")) { return call; } else if (call !== void 0) { throw new TypeError(\"Derived constructors may only return object or undefined\"); } return _assertThisInitialized(self); }\n\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return self; }\n\nfunction _isNativeReflectConstruct() { if (typeof Reflect === \"undefined\" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === \"function\") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }\n\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\n\n// import Logger from \"./Logger.es6\";\nvar Logger = __webpack_require__(/*! ./Logger.es6 */ \"./src/Logger.es6\").Logger;\n\nvar readyStateMap = {\n  0: \"HAVE_NOTHING\",\n  1: \"HAVE_METADATA\",\n  2: \"HAVE_CURRENT_DATA\",\n  3: \"HAVE_FUTURE_DATA\",\n  4: \"HAVE_ENOUGH_DATA\"\n}; // This guy is a little weird - It's the input to it's parent; i.e. in the graph\n// it is the parent, but in the tree (and xml), it's a child.\n// Don't use it for user controlled sources like video elements:\n// instead user AdUserControlledSourceNode for them.\n\nvar AdSourceNode = /*#__PURE__*/function (_AudioNub) {\n  _inherits(AdSourceNode, _AudioNub);\n\n  var _super = _createSuper(AdSourceNode);\n\n  function AdSourceNode(parent, xmlNode, audioContext, mediaPair) {\n    var _this;\n\n    _classCallCheck(this, AdSourceNode);\n\n    _this = _super.call(this, parent, xmlNode, audioContext);\n    _this.mediaPair = mediaPair;\n    _this.media = mediaPair.media;\n    _this.mediaNode = mediaPair.mediaNode;\n\n    if (xmlNode.attributes.clipBegin) {\n      _this.clipBegin = _TimingCalculator[\"default\"].parseSeconds(xmlNode.attributes.clipBegin) || 0;\n    } else {\n      _this.clipBegin = 0;\n    }\n\n    if (xmlNode.attributes.clipEnd) {\n      _this.clipEnd = _TimingCalculator[\"default\"].parseSeconds(xmlNode.attributes.clipEnd) || NaN;\n    }\n\n    return _this;\n  }\n\n  _createClass(AdSourceNode, [{\n    key: \"mediaReadyState\",\n    value: function mediaReadyState(m) {\n      var readyState = m.readyState;\n      return readyStateMap[readyState];\n    }\n  }, {\n    key: \"addDebugEventHandlers\",\n    value: function addDebugEventHandlers() {\n      var _this2 = this;\n\n      var m = this.mediaPair.media;\n\n      if (m) {\n        m.addEventListener(\"abort\", function () {\n          Logger.log(\"Audio source aborted loading. readyState = \".concat(_this2.mediaReadyState(m)));\n        });\n        m.addEventListener(\"error\", function () {\n          Logger.log(\"Audio source error. readyState = \".concat(_this2.mediaReadyState(m)));\n        });\n        m.addEventListener(\"loadeddata\", function () {\n          Logger.log(\"Audio source loaded data. readyState = \".concat(_this2.mediaReadyState(m)));\n        });\n        m.addEventListener(\"loadstart\", function () {\n          Logger.log(\"Audio source loadstart. readyState = \".concat(_this2.mediaReadyState(m)));\n        });\n        m.addEventListener(\"playing\", function () {\n          Logger.log(\"Audio source is playing. readyState = \".concat(_this2.mediaReadyState(m)));\n        });\n        m.addEventListener(\"progress\", function () {\n          Logger.log(\"Audio source making progress. readyState = \".concat(_this2.mediaReadyState(m)));\n        });\n        m.addEventListener(\"waiting\", function () {\n          Logger.log(\"Audio source is waiting for more data. readyState = \".concat(_this2.mediaReadyState(m)));\n        });\n      }\n    }\n  }, {\n    key: \"end\",\n    get: function get() {\n      var ret;\n\n      var normalEnd = _get(_getPrototypeOf(AdSourceNode.prototype), \"end\", this);\n\n      if (this.clipEnd) {\n        //The duration of the clip added to the start time, or the span end, whichever comes first.\n        ret = Math.min(normalEnd, this.begin + (this.clipEnd - this.clipBegin));\n      } else {\n        ret = normalEnd;\n      } // Logger.log(`AdSourceNode end() super said ${normalEnd} but I'm saying ${ret}`); // DEBUG\n\n\n      return ret;\n    }\n  }, {\n    key: \"onActive\",\n    value: function onActive() {\n      var _this3 = this;\n\n      if (this.mediaPair && !this.isActive) {\n        Logger.log(\"Active AdSourceNode: \".concat(this.pathString));\n        var offset = this.videoMedia.currentTime - this.begin;\n        this.media.currentTime = this.clipBegin ? this.clipBegin + offset : offset;\n        this.input = this.mediaNode;\n        this.gainNode.gain.value = this.gain * _PlaybackProperties[\"default\"].getCurrentGain();\n        this.input.connect(this.gainNode);\n        Logger.log(\"Connected to media element source with src= \".concat(this.input.mediaElement.currentSrc));\n        this.media.play()[\"catch\"](function (e) {\n          Logger.log(\"AdSourceNode play rejected with error: \".concat(e, \".\"));\n        });\n        this.output.connect(this.parent.gainNode); //TODO Make formal with .input\n\n        Logger.log(\"Active source into: \".concat(this.parent.name, \"; src: \").concat(this.media.src, \"; from: \").concat(this.media.currentTime, \" including offset of \").concat(offset, \".\"));\n        this.startTime = this.media.currentTime;\n        this.isActive = true;\n        this.gainId = _PlaybackProperties[\"default\"].registerCallback(function (uiGain) {\n          //const oldVal = this.gainNode.gain.value;\n          //console.info(\"Base gain\", this.gain, \"UI gain\", uiGain);\n          _this3.gainNode.gain.value = _this3.gain * uiGain; //console.info(\"Final gain changes from\", oldVal, \"to\", this.gainNode.gain.value);\n        });\n      }\n    }\n  }, {\n    key: \"onInactive\",\n    value: function onInactive() {\n      if (this.media && this.isActive) {\n        Logger.log(\"Inactive AdSourceNode: \".concat(this.pathString));\n        this.media.pause();\n        this.input.disconnect(this.gainNode);\n        this.input = null;\n        this.output.disconnect(this.parent.gainNode);\n        Logger.log(\"Inactive source into: \".concat(this.parent.name, \"; src: \").concat(this.media.src));\n        this.endTime = this.media.currentTime; // DEBUG: clipBegin/clipEnd\n\n        Logger.log( // eslint-disable-next-line max-len\n        \"ran source for: \".concat(this.endTime - this.startTime, \" clipBegin: \").concat(this.startTime, \" clipEnd: \").concat(this.endTime));\n        this.isActive = false;\n\n        _PlaybackProperties[\"default\"].deregisterCallback(this.gainId);\n      }\n    }\n  }, {\n    key: \"onPause\",\n    value: function onPause() {\n      if (this.media && this.isActive) {\n        this.media.pause();\n      }\n    }\n  }, {\n    key: \"onRestart\",\n    value: function onRestart() {\n      if (this.media && this.isActive) {\n        this.media.play();\n      }\n    }\n  }, {\n    key: \"onFinalise\",\n    value: function onFinalise() {\n      if (this.media) {\n        _get(_getPrototypeOf(AdSourceNode.prototype), \"onFinalise\", this).call(this);\n\n        var src = this.media.src;\n\n        if ((src + \"\").indexOf(\"blob://\") > 0) {\n          Logger.log(\"Clear audio src \" + this.media.src);\n          this.media.src = \"\";\n          URL.revokeObjectURL(src);\n        }\n\n        if (this.input) {\n          this.input.disconnect(this.gainNode);\n        }\n      }\n    }\n  }]);\n\n  return AdSourceNode;\n}(_AudioNub2[\"default\"]);\n\nexports.default = AdSourceNode;\n\n//# sourceURL=webpack://adhere-lib/./src/AdSourceNode.es6?");
+eval("\n\nfunction _typeof(obj) { \"@babel/helpers - typeof\"; if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }; } return _typeof(obj); }\n\nObject.defineProperty(exports, \"__esModule\", ({\n  value: true\n}));\nexports[\"default\"] = void 0;\n\nvar _AudioNub2 = _interopRequireDefault(__webpack_require__(/*! ./AudioNub.es6 */ \"./src/AudioNub.es6\"));\n\nvar _TimingCalculator = _interopRequireDefault(__webpack_require__(/*! ./TimingCalculator.es6 */ \"./src/TimingCalculator.es6\"));\n\nvar _PlaybackProperties = _interopRequireDefault(__webpack_require__(/*! ./PlaybackProperties.es6 */ \"./src/PlaybackProperties.es6\"));\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { \"default\": obj }; }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\nfunction _get(target, property, receiver) { if (typeof Reflect !== \"undefined\" && Reflect.get) { _get = Reflect.get; } else { _get = function _get(target, property, receiver) { var base = _superPropBase(target, property); if (!base) return; var desc = Object.getOwnPropertyDescriptor(base, property); if (desc.get) { return desc.get.call(receiver); } return desc.value; }; } return _get(target, property, receiver || target); }\n\nfunction _superPropBase(object, property) { while (!Object.prototype.hasOwnProperty.call(object, property)) { object = _getPrototypeOf(object); if (object === null) break; } return object; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\n\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\n\nfunction _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }\n\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === \"object\" || typeof call === \"function\")) { return call; } else if (call !== void 0) { throw new TypeError(\"Derived constructors may only return object or undefined\"); } return _assertThisInitialized(self); }\n\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return self; }\n\nfunction _isNativeReflectConstruct() { if (typeof Reflect === \"undefined\" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === \"function\") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }\n\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\n\n// import Logger from \"./Logger.es6\";\nvar Logger = __webpack_require__(/*! ./Logger.es6 */ \"./src/Logger.es6\").Logger;\n\nvar readyStateMap = {\n  0: \"HAVE_NOTHING\",\n  1: \"HAVE_METADATA\",\n  2: \"HAVE_CURRENT_DATA\",\n  3: \"HAVE_FUTURE_DATA\",\n  4: \"HAVE_ENOUGH_DATA\"\n}; // This guy is a little weird - It's the input to it's parent; i.e. in the graph\n// it is the parent, but in the tree (and xml), it's a child.\n// Don't use it for user controlled sources like video elements:\n// instead user AdUserControlledSourceNode for them.\n\nvar AdSourceNode = /*#__PURE__*/function (_AudioNub) {\n  _inherits(AdSourceNode, _AudioNub);\n\n  var _super = _createSuper(AdSourceNode);\n\n  function AdSourceNode(parent, xmlNode, audioContext, mediaPair) {\n    var _this;\n\n    _classCallCheck(this, AdSourceNode);\n\n    _this = _super.call(this, parent, xmlNode, audioContext);\n    _this.mediaPair = mediaPair;\n    _this.media = mediaPair.media;\n    _this.mediaNode = mediaPair.mediaNode;\n\n    if (xmlNode.attributes.clipBegin) {\n      _this.clipBegin = _TimingCalculator[\"default\"].parseSeconds(xmlNode.attributes.clipBegin) || 0;\n    } else {\n      _this.clipBegin = 0;\n    }\n\n    if (xmlNode.attributes.clipEnd) {\n      _this.clipEnd = _TimingCalculator[\"default\"].parseSeconds(xmlNode.attributes.clipEnd) || NaN;\n    }\n\n    return _this;\n  }\n\n  _createClass(AdSourceNode, [{\n    key: \"mediaReadyState\",\n    value: function mediaReadyState(m) {\n      var readyState = m.readyState;\n      return readyStateMap[readyState];\n    }\n  }, {\n    key: \"addDebugEventHandlers\",\n    value: function addDebugEventHandlers() {\n      var _this2 = this;\n\n      var m = this.mediaPair.media;\n\n      if (m) {\n        m.addEventListener(\"abort\", function () {\n          Logger.log(\"Audio source aborted loading. readyState = \".concat(_this2.mediaReadyState(m)));\n        });\n        m.addEventListener(\"error\", function () {\n          Logger.log(\"Audio source error. readyState = \".concat(_this2.mediaReadyState(m)));\n        });\n        m.addEventListener(\"loadeddata\", function () {\n          Logger.log(\"Audio source loaded data. readyState = \".concat(_this2.mediaReadyState(m)));\n        });\n        m.addEventListener(\"loadstart\", function () {\n          Logger.log(\"Audio source loadstart. readyState = \".concat(_this2.mediaReadyState(m)));\n        });\n        m.addEventListener(\"playing\", function () {\n          Logger.log(\"Audio source is playing. readyState = \".concat(_this2.mediaReadyState(m)));\n        });\n        m.addEventListener(\"progress\", function () {\n          Logger.log(\"Audio source making progress. readyState = \".concat(_this2.mediaReadyState(m)));\n        });\n        m.addEventListener(\"waiting\", function () {\n          Logger.log(\"Audio source is waiting for more data. readyState = \".concat(_this2.mediaReadyState(m)));\n        });\n      }\n    }\n  }, {\n    key: \"end\",\n    get: function get() {\n      var ret;\n\n      var normalEnd = _get(_getPrototypeOf(AdSourceNode.prototype), \"end\", this);\n\n      if (this.clipEnd) {\n        //The duration of the clip added to the start time, or the span end, whichever comes first.\n        ret = Math.min(normalEnd, this.begin + (this.clipEnd - this.clipBegin));\n      } else {\n        ret = normalEnd;\n      } // Logger.log(`AdSourceNode end() super said ${normalEnd} but I'm saying ${ret}`); // DEBUG\n\n\n      return ret;\n    }\n  }, {\n    key: \"onActive\",\n    value: function onActive() {\n      var _this3 = this;\n\n      if (this.mediaPair && !this.isActive) {\n        Logger.log(\"Active AdSourceNode: \".concat(this.pathString));\n        var offset = this.videoMedia.currentTime - this.begin;\n        this.media.currentTime = this.clipBegin ? this.clipBegin + offset : offset;\n        this.input = this.mediaNode;\n        this.gainNode.gain.value = this.gain * _PlaybackProperties[\"default\"].getCurrentGain();\n        this.input.connect(this.gainNode);\n        Logger.log(\"Connected to media element source with src= \".concat(this.input.mediaElement.currentSrc));\n        this.media.play()[\"catch\"](function (e) {\n          Logger.log(\"AdSourceNode play rejected with error: \".concat(e, \".\"));\n        });\n        this.output.connect(this.parent.gainNode); //TODO Make formal with .input\n\n        Logger.log(\"Active source into: \".concat(this.parent.name, \"; src: \").concat(this.media.src, \"; from: \").concat(this.media.currentTime, \" including offset of \").concat(offset, \".\"));\n        this.startTime = this.media.currentTime;\n        this.isActive = true;\n        this.gainId = _PlaybackProperties[\"default\"].registerCallback(function (uiGain) {\n          //const oldVal = this.gainNode.gain.value;\n          //console.info(\"Base gain\", this.gain, \"UI gain\", uiGain);\n          _this3.gainNode.gain.value = _this3.gain * uiGain; //console.info(\"Final gain changes from\", oldVal, \"to\", this.gainNode.gain.value);\n        });\n      }\n    }\n  }, {\n    key: \"onInactive\",\n    value: function onInactive() {\n      if (this.media && this.isActive) {\n        Logger.log(\"Inactive AdSourceNode: \".concat(this.pathString));\n        this.media.pause();\n        this.input.disconnect(this.gainNode);\n        this.input = null;\n        this.output.disconnect(this.parent.gainNode);\n        Logger.log(\"Inactive source into: \".concat(this.parent.name, \"; src: \").concat(this.media.src));\n        this.endTime = this.media.currentTime; // DEBUG: clipBegin/clipEnd\n\n        Logger.log( // eslint-disable-next-line max-len\n        \"ran source for: \".concat(this.endTime - this.startTime, \" clipBegin: \").concat(this.startTime, \" clipEnd: \").concat(this.endTime));\n        this.isActive = false;\n\n        _PlaybackProperties[\"default\"].deregisterCallback(this.gainId);\n      }\n    }\n  }, {\n    key: \"onPause\",\n    value: function onPause() {\n      if (this.media && this.isActive) {\n        this.media.pause();\n      }\n    }\n  }, {\n    key: \"onRestart\",\n    value: function onRestart() {\n      if (this.media && this.isActive) {\n        this.media.play();\n      }\n    }\n  }, {\n    key: \"onFinalise\",\n    value: function onFinalise() {\n      if (this.media) {\n        _get(_getPrototypeOf(AdSourceNode.prototype), \"onFinalise\", this).call(this);\n\n        var src = this.media.src;\n\n        if ((src + \"\").indexOf(\"blob://\") > 0) {\n          Logger.log(\"Clear audio src \" + this.media.src);\n          this.media.src = \"\";\n          URL.revokeObjectURL(src);\n        }\n\n        if (this.input) {\n          this.input.disconnect(this.gainNode);\n        }\n      }\n    }\n  }]);\n\n  return AdSourceNode;\n}(_AudioNub2[\"default\"]);\n\nexports[\"default\"] = AdSourceNode;\n\n//# sourceURL=webpack://adhere-lib/./src/AdSourceNode.es6?");
 
 /***/ }),
 
@@ -59,7 +59,7 @@ eval("\n\nfunction _typeof(obj) { \"@babel/helpers - typeof\"; if (typeof Symbol
 /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
 
 "use strict";
-eval("\n\nfunction _typeof(obj) { \"@babel/helpers - typeof\"; if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }; } return _typeof(obj); }\n\nObject.defineProperty(exports, \"__esModule\", ({\n  value: true\n}));\nexports.default = void 0;\n\nvar _AdSourceNode2 = _interopRequireDefault(__webpack_require__(/*! ./AdSourceNode.es6 */ \"./src/AdSourceNode.es6\"));\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { \"default\": obj }; }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\n\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\n\nfunction _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }\n\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === \"object\" || typeof call === \"function\")) { return call; } else if (call !== void 0) { throw new TypeError(\"Derived constructors may only return object or undefined\"); } return _assertThisInitialized(self); }\n\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return self; }\n\nfunction _isNativeReflectConstruct() { if (typeof Reflect === \"undefined\" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === \"function\") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }\n\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\n\n// import Logger from \"./Logger.es6\";\nvar Logger = __webpack_require__(/*! ./Logger.es6 */ \"./src/Logger.es6\").Logger; // This guy is a little weird - It's the input to it's parent; i.e. in the graph\n// it is the parent, but in the tree (and xml), it's a child.\n// This subclass is for user controlled sources like <video> elements, as\n// opposed to sources generated by the TTML source document.\n\n\nvar AdUserControlledSourceNode = /*#__PURE__*/function (_AdSourceNode) {\n  _inherits(AdUserControlledSourceNode, _AdSourceNode);\n\n  var _super = _createSuper(AdUserControlledSourceNode);\n\n  function AdUserControlledSourceNode(parent, xmlNode, audioContext, media) {\n    _classCallCheck(this, AdUserControlledSourceNode);\n\n    return _super.call(this, parent, xmlNode, audioContext, media);\n  }\n\n  _createClass(AdUserControlledSourceNode, [{\n    key: \"onActive\",\n    value: function onActive() {\n      if (this.media && !this.isActive) {\n        this.input = this.mediaNode;\n        this.input.connect(this.gainNode);\n        Logger.log(\"Connected to media element source with src= \".concat(this.input.mediaElement.currentSrc));\n\n        if (this.parent) {\n          this.output.connect(this.parent.gainNode); //TODO Make formal with .input\n\n          Logger.log(\"Active source into: \".concat(this.parent.name, \"; src: \").concat(this.media.src, \"; from: \").concat(this.media.currentTime));\n        } else {\n          Logger.log(\"No parent to connect\");\n        }\n\n        this.startTime = this.media.currentTime;\n        this.isActive = true;\n      }\n    }\n  }, {\n    key: \"onInactive\",\n    value: function onInactive() {\n      if (this.media && this.isActive) {\n        this.input.disconnect(this.gainNode);\n        this.input = null;\n\n        if (this.parent) {\n          this.output.disconnect(this.parent.gainNode);\n          Logger.log(\"Inactive source into: \".concat(this.parent.name, \"; src: \").concat(this.media.src));\n        } else {\n          Logger.log(\"No parent to disconnect\");\n        }\n\n        this.endTime = this.media.currentTime;\n        this.isActive = false;\n      }\n    }\n  }, {\n    key: \"onPause\",\n    value: function onPause() {}\n  }, {\n    key: \"onRestart\",\n    value: function onRestart() {}\n  }, {\n    key: \"onFinalise\",\n    value: function onFinalise() {}\n  }]);\n\n  return AdUserControlledSourceNode;\n}(_AdSourceNode2[\"default\"]);\n\nexports.default = AdUserControlledSourceNode;\n\n//# sourceURL=webpack://adhere-lib/./src/AdUserControlledSourceNode.es6?");
+eval("\n\nfunction _typeof(obj) { \"@babel/helpers - typeof\"; if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }; } return _typeof(obj); }\n\nObject.defineProperty(exports, \"__esModule\", ({\n  value: true\n}));\nexports[\"default\"] = void 0;\n\nvar _AdSourceNode2 = _interopRequireDefault(__webpack_require__(/*! ./AdSourceNode.es6 */ \"./src/AdSourceNode.es6\"));\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { \"default\": obj }; }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\n\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\n\nfunction _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }\n\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === \"object\" || typeof call === \"function\")) { return call; } else if (call !== void 0) { throw new TypeError(\"Derived constructors may only return object or undefined\"); } return _assertThisInitialized(self); }\n\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return self; }\n\nfunction _isNativeReflectConstruct() { if (typeof Reflect === \"undefined\" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === \"function\") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }\n\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\n\n// import Logger from \"./Logger.es6\";\nvar Logger = __webpack_require__(/*! ./Logger.es6 */ \"./src/Logger.es6\").Logger; // This guy is a little weird - It's the input to it's parent; i.e. in the graph\n// it is the parent, but in the tree (and xml), it's a child.\n// This subclass is for user controlled sources like <video> elements, as\n// opposed to sources generated by the TTML source document.\n\n\nvar AdUserControlledSourceNode = /*#__PURE__*/function (_AdSourceNode) {\n  _inherits(AdUserControlledSourceNode, _AdSourceNode);\n\n  var _super = _createSuper(AdUserControlledSourceNode);\n\n  function AdUserControlledSourceNode(parent, xmlNode, audioContext, media) {\n    _classCallCheck(this, AdUserControlledSourceNode);\n\n    return _super.call(this, parent, xmlNode, audioContext, media);\n  }\n\n  _createClass(AdUserControlledSourceNode, [{\n    key: \"onActive\",\n    value: function onActive() {\n      if (this.media && !this.isActive) {\n        this.input = this.mediaNode;\n        this.input.connect(this.gainNode);\n        Logger.log(\"Connected to media element source with src= \".concat(this.input.mediaElement.currentSrc));\n\n        if (this.parent) {\n          this.output.connect(this.parent.gainNode); //TODO Make formal with .input\n\n          Logger.log(\"Active source into: \".concat(this.parent.name, \"; src: \").concat(this.media.src, \"; from: \").concat(this.media.currentTime));\n        } else {\n          Logger.log(\"No parent to connect\");\n        }\n\n        this.startTime = this.media.currentTime;\n        this.isActive = true;\n      }\n    }\n  }, {\n    key: \"onInactive\",\n    value: function onInactive() {\n      if (this.media && this.isActive) {\n        this.input.disconnect(this.gainNode);\n        this.input = null;\n\n        if (this.parent) {\n          this.output.disconnect(this.parent.gainNode);\n          Logger.log(\"Inactive source into: \".concat(this.parent.name, \"; src: \").concat(this.media.src));\n        } else {\n          Logger.log(\"No parent to disconnect\");\n        }\n\n        this.endTime = this.media.currentTime;\n        this.isActive = false;\n      }\n    }\n  }, {\n    key: \"onPause\",\n    value: function onPause() {}\n  }, {\n    key: \"onRestart\",\n    value: function onRestart() {}\n  }, {\n    key: \"onFinalise\",\n    value: function onFinalise() {}\n  }]);\n\n  return AdUserControlledSourceNode;\n}(_AdSourceNode2[\"default\"]);\n\nexports[\"default\"] = AdUserControlledSourceNode;\n\n//# sourceURL=webpack://adhere-lib/./src/AdUserControlledSourceNode.es6?");
 
 /***/ }),
 
@@ -70,7 +70,7 @@ eval("\n\nfunction _typeof(obj) { \"@babel/helpers - typeof\"; if (typeof Symbol
 /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
 
 "use strict";
-eval("\n\nfunction _typeof(obj) { \"@babel/helpers - typeof\"; if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }; } return _typeof(obj); }\n\nObject.defineProperty(exports, \"__esModule\", ({\n  value: true\n}));\nexports.default = void 0;\n\nvar _AdNode2 = _interopRequireDefault(__webpack_require__(/*! ./AdNode.es6 */ \"./src/AdNode.es6\"));\n\nvar _Utils = _interopRequireDefault(__webpack_require__(/*! ./Utils.es6 */ \"./src/Utils.es6\"));\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { \"default\": obj }; }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\nfunction _get(target, property, receiver) { if (typeof Reflect !== \"undefined\" && Reflect.get) { _get = Reflect.get; } else { _get = function _get(target, property, receiver) { var base = _superPropBase(target, property); if (!base) return; var desc = Object.getOwnPropertyDescriptor(base, property); if (desc.get) { return desc.get.call(receiver); } return desc.value; }; } return _get(target, property, receiver || target); }\n\nfunction _superPropBase(object, property) { while (!Object.prototype.hasOwnProperty.call(object, property)) { object = _getPrototypeOf(object); if (object === null) break; } return object; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\n\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\n\nfunction _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }\n\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === \"object\" || typeof call === \"function\")) { return call; } else if (call !== void 0) { throw new TypeError(\"Derived constructors may only return object or undefined\"); } return _assertThisInitialized(self); }\n\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return self; }\n\nfunction _isNativeReflectConstruct() { if (typeof Reflect === \"undefined\" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === \"function\") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }\n\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\n\n// import Logger from \"./Logger.es6\";\nvar Logger = __webpack_require__(/*! ./Logger.es6 */ \"./src/Logger.es6\").Logger;\n\nvar AnimateNode = /*#__PURE__*/function (_AdNode) {\n  _inherits(AnimateNode, _AdNode);\n\n  var _super = _createSuper(AnimateNode);\n\n  function AnimateNode(parent, xmlNode, audioContext) {\n    var _this;\n\n    _classCallCheck(this, AnimateNode);\n\n    _this = _super.call(this, parent, xmlNode, audioContext);\n\n    if (_Utils[\"default\"].getAttributeByFullyQualifiedName(xmlNode, \"\".concat(_Utils[\"default\"].NS_TTML_AUDIO_URI, \"%%gain\"))) {\n      _this.gains = _Utils[\"default\"].getAttributeByFullyQualifiedName(xmlNode, \"\".concat(_Utils[\"default\"].NS_TTML_AUDIO_URI, \"%%gain\")).split(\";\").map(parseFloat);\n    }\n\n    if (_Utils[\"default\"].getAttributeByFullyQualifiedName(xmlNode, \"\".concat(_Utils[\"default\"].NS_TTML_AUDIO_URI, \"%%pan\"))) {\n      _this.pans = _Utils[\"default\"].getAttributeByFullyQualifiedName(xmlNode, \"\".concat(_Utils[\"default\"].NS_TTML_AUDIO_URI, \"%%pan\")).split(\";\").map(parseFloat);\n    }\n\n    return _this;\n  }\n\n  _createClass(AnimateNode, [{\n    key: \"onActive\",\n    value: function onActive() {\n      _get(_getPrototypeOf(AnimateNode.prototype), \"onActive\", this).call(this);\n\n      var duration = this.end - this.begin;\n\n      if (this.gains && this.gains.length > 0) {\n        this.parent.gainNode.gain.setValueCurveAtTime(Float32Array.from(this.gains), this.audioContext.currentTime, duration);\n        Logger.log( // eslint-disable-next-line max-len\n        \"Active animate node into: \".concat(this.parent.name, \"; gain: \").concat(this.gains.join(\", \"), \"; dur: \").concat(duration));\n      }\n\n      if (this.pans && this.pans.length > 0) {\n        // Try to work around older spec support in Webkit, noting that\n        // the PannerNode interface does not use AudioParam and therefore\n        // the attempt to use setValueCurveAtTime fails.\n        var panPosition = this.parent.panNode.pan || this.parent.panNode.position;\n        panPosition.setValueCurveAtTime(Float32Array.from(this.pans), this.audioContext.currentTime, duration);\n        Logger.log( // eslint-disable-next-line max-len\n        \"Active animate node into: \".concat(this.parent.name, \"; pan: \").concat(this.pans.join(\", \"), \"; dur: \").concat(duration));\n      }\n    }\n  }, {\n    key: \"onInactive\",\n    value: function onInactive() {\n      _get(_getPrototypeOf(AnimateNode.prototype), \"onInactive\", this).call(this);\n    }\n  }]);\n\n  return AnimateNode;\n}(_AdNode2[\"default\"]);\n\nexports.default = AnimateNode;\n\n//# sourceURL=webpack://adhere-lib/./src/AnimateNode.es6?");
+eval("\n\nfunction _typeof(obj) { \"@babel/helpers - typeof\"; if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }; } return _typeof(obj); }\n\nObject.defineProperty(exports, \"__esModule\", ({\n  value: true\n}));\nexports[\"default\"] = void 0;\n\nvar _AdNode2 = _interopRequireDefault(__webpack_require__(/*! ./AdNode.es6 */ \"./src/AdNode.es6\"));\n\nvar _Utils = _interopRequireDefault(__webpack_require__(/*! ./Utils.es6 */ \"./src/Utils.es6\"));\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { \"default\": obj }; }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\nfunction _get(target, property, receiver) { if (typeof Reflect !== \"undefined\" && Reflect.get) { _get = Reflect.get; } else { _get = function _get(target, property, receiver) { var base = _superPropBase(target, property); if (!base) return; var desc = Object.getOwnPropertyDescriptor(base, property); if (desc.get) { return desc.get.call(receiver); } return desc.value; }; } return _get(target, property, receiver || target); }\n\nfunction _superPropBase(object, property) { while (!Object.prototype.hasOwnProperty.call(object, property)) { object = _getPrototypeOf(object); if (object === null) break; } return object; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\n\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\n\nfunction _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }\n\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === \"object\" || typeof call === \"function\")) { return call; } else if (call !== void 0) { throw new TypeError(\"Derived constructors may only return object or undefined\"); } return _assertThisInitialized(self); }\n\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return self; }\n\nfunction _isNativeReflectConstruct() { if (typeof Reflect === \"undefined\" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === \"function\") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }\n\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\n\n// import Logger from \"./Logger.es6\";\nvar Logger = __webpack_require__(/*! ./Logger.es6 */ \"./src/Logger.es6\").Logger;\n\nvar AnimateNode = /*#__PURE__*/function (_AdNode) {\n  _inherits(AnimateNode, _AdNode);\n\n  var _super = _createSuper(AnimateNode);\n\n  function AnimateNode(parent, xmlNode, audioContext) {\n    var _this;\n\n    _classCallCheck(this, AnimateNode);\n\n    _this = _super.call(this, parent, xmlNode, audioContext);\n\n    if (_Utils[\"default\"].getAttributeByFullyQualifiedName(xmlNode, \"\".concat(_Utils[\"default\"].NS_TTML_AUDIO_URI, \"%%gain\"))) {\n      _this.gains = _Utils[\"default\"].getAttributeByFullyQualifiedName(xmlNode, \"\".concat(_Utils[\"default\"].NS_TTML_AUDIO_URI, \"%%gain\")).split(\";\").map(parseFloat);\n    }\n\n    if (_Utils[\"default\"].getAttributeByFullyQualifiedName(xmlNode, \"\".concat(_Utils[\"default\"].NS_TTML_AUDIO_URI, \"%%pan\"))) {\n      _this.pans = _Utils[\"default\"].getAttributeByFullyQualifiedName(xmlNode, \"\".concat(_Utils[\"default\"].NS_TTML_AUDIO_URI, \"%%pan\")).split(\";\").map(parseFloat);\n    }\n\n    return _this;\n  }\n\n  _createClass(AnimateNode, [{\n    key: \"onActive\",\n    value: function onActive() {\n      _get(_getPrototypeOf(AnimateNode.prototype), \"onActive\", this).call(this);\n\n      var duration = this.end - this.begin;\n\n      if (this.gains && this.gains.length > 0) {\n        this.parent.gainNode.gain.setValueCurveAtTime(Float32Array.from(this.gains), this.audioContext.currentTime, duration);\n        Logger.log( // eslint-disable-next-line max-len\n        \"Active animate node into: \".concat(this.parent.name, \"; gain: \").concat(this.gains.join(\", \"), \"; dur: \").concat(duration));\n      }\n\n      if (this.pans && this.pans.length > 0) {\n        // Try to work around older spec support in Webkit, noting that\n        // the PannerNode interface does not use AudioParam and therefore\n        // the attempt to use setValueCurveAtTime fails.\n        var panPosition = this.parent.panNode.pan || this.parent.panNode.position;\n        panPosition.setValueCurveAtTime(Float32Array.from(this.pans), this.audioContext.currentTime, duration);\n        Logger.log( // eslint-disable-next-line max-len\n        \"Active animate node into: \".concat(this.parent.name, \"; pan: \").concat(this.pans.join(\", \"), \"; dur: \").concat(duration));\n      }\n    }\n  }, {\n    key: \"onInactive\",\n    value: function onInactive() {\n      _get(_getPrototypeOf(AnimateNode.prototype), \"onInactive\", this).call(this);\n    }\n  }]);\n\n  return AnimateNode;\n}(_AdNode2[\"default\"]);\n\nexports[\"default\"] = AnimateNode;\n\n//# sourceURL=webpack://adhere-lib/./src/AnimateNode.es6?");
 
 /***/ }),
 
@@ -81,7 +81,7 @@ eval("\n\nfunction _typeof(obj) { \"@babel/helpers - typeof\"; if (typeof Symbol
 /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
 
 "use strict";
-eval("\n\nfunction _typeof(obj) { \"@babel/helpers - typeof\"; if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }; } return _typeof(obj); }\n\nObject.defineProperty(exports, \"__esModule\", ({\n  value: true\n}));\nexports.default = void 0;\n\nvar _AdNode2 = _interopRequireDefault(__webpack_require__(/*! ./AdNode.es6 */ \"./src/AdNode.es6\"));\n\nvar _Utils = _interopRequireDefault(__webpack_require__(/*! ./Utils.es6 */ \"./src/Utils.es6\"));\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { \"default\": obj }; }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\nfunction _get(target, property, receiver) { if (typeof Reflect !== \"undefined\" && Reflect.get) { _get = Reflect.get; } else { _get = function _get(target, property, receiver) { var base = _superPropBase(target, property); if (!base) return; var desc = Object.getOwnPropertyDescriptor(base, property); if (desc.get) { return desc.get.call(receiver); } return desc.value; }; } return _get(target, property, receiver || target); }\n\nfunction _superPropBase(object, property) { while (!Object.prototype.hasOwnProperty.call(object, property)) { object = _getPrototypeOf(object); if (object === null) break; } return object; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\n\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\n\nfunction _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }\n\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === \"object\" || typeof call === \"function\")) { return call; } else if (call !== void 0) { throw new TypeError(\"Derived constructors may only return object or undefined\"); } return _assertThisInitialized(self); }\n\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return self; }\n\nfunction _isNativeReflectConstruct() { if (typeof Reflect === \"undefined\" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === \"function\") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }\n\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\n\nvar AudioNub = /*#__PURE__*/function (_AdNode) {\n  _inherits(AudioNub, _AdNode);\n\n  var _super = _createSuper(AudioNub);\n\n  function AudioNub(parent, xmlNode, audioContext) {\n    var _this;\n\n    _classCallCheck(this, AudioNub);\n\n    _this = _super.call(this, parent, xmlNode, audioContext);\n\n    _this.copyAudioAttributes(xmlNode);\n\n    _this.createAudioNodes();\n\n    return _this;\n  }\n\n  _createClass(AudioNub, [{\n    key: \"createAudioNodes\",\n    value: function createAudioNodes() {\n      this.gainNode = this.audioContext.createGain(); // Check that StereoPanner is supported. Webkit currently only\n      // supports the older interface's Panner.\n\n      var supportsStereoPanner = this.audioContext.createStereoPanner;\n      var supportsPanner = this.audioContext.createPanner;\n\n      if (supportsStereoPanner) {\n        this.panNode = this.audioContext.createStereoPanner();\n      } else if (supportsPanner) {\n        this.panNode = this.audioContext.createPanner();\n      }\n\n      this.gainNode.connect(this.panNode);\n      this.output = this.panNode;\n\n      if (supportsStereoPanner) {\n        this.panNode.pan.value = this.pan;\n      } else if (supportsPanner) {\n        this.panNode.position = 90 * this.pan;\n      }\n\n      this.gainNode.gain.value = this.gain;\n    }\n  }, {\n    key: \"onActive\",\n    value: function onActive() {\n      if (this.parent && !this.isActive) {\n        this.parent.output.connect(this.gainNode);\n      }\n\n      _get(_getPrototypeOf(AudioNub.prototype), \"onActive\", this).call(this);\n    }\n  }, {\n    key: \"onInactive\",\n    value: function onInactive() {\n      if (this.parent && this.isActive) {\n        this.parent.output.disconnect(this.gainNode);\n      }\n\n      _get(_getPrototypeOf(AudioNub.prototype), \"onInactive\", this).call(this);\n    }\n  }, {\n    key: \"onFinalise\",\n    value: function onFinalise() {\n      _get(_getPrototypeOf(AudioNub.prototype), \"onFinalise\", this).call(this);\n\n      this.gainNode.disconnect(this.panNode);\n    }\n  }, {\n    key: \"gain\",\n    get: function get() {\n      return !isNaN(this._gain) ? this._gain : 1;\n    }\n  }, {\n    key: \"pan\",\n    get: function get() {\n      return !isNaN(this._pan) ? this._pan : 0;\n    }\n  }, {\n    key: \"copyAudioAttributes\",\n    value: function copyAudioAttributes(xmlNode) {\n      if (xmlNode.attributes) {\n        this._gain = parseFloat(_Utils[\"default\"].getAttributeByFullyQualifiedName(xmlNode, \"\".concat(_Utils[\"default\"].NS_TTML_AUDIO_URI, \"%%gain\")));\n        this._pan = parseFloat(_Utils[\"default\"].getAttributeByFullyQualifiedName(xmlNode, \"\".concat(_Utils[\"default\"].NS_TTML_AUDIO_URI, \"%%pan\")));\n      }\n    }\n  }]);\n\n  return AudioNub;\n}(_AdNode2[\"default\"]);\n\nexports.default = AudioNub;\n\n//# sourceURL=webpack://adhere-lib/./src/AudioNub.es6?");
+eval("\n\nfunction _typeof(obj) { \"@babel/helpers - typeof\"; if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }; } return _typeof(obj); }\n\nObject.defineProperty(exports, \"__esModule\", ({\n  value: true\n}));\nexports[\"default\"] = void 0;\n\nvar _AdNode2 = _interopRequireDefault(__webpack_require__(/*! ./AdNode.es6 */ \"./src/AdNode.es6\"));\n\nvar _Utils = _interopRequireDefault(__webpack_require__(/*! ./Utils.es6 */ \"./src/Utils.es6\"));\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { \"default\": obj }; }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\nfunction _get(target, property, receiver) { if (typeof Reflect !== \"undefined\" && Reflect.get) { _get = Reflect.get; } else { _get = function _get(target, property, receiver) { var base = _superPropBase(target, property); if (!base) return; var desc = Object.getOwnPropertyDescriptor(base, property); if (desc.get) { return desc.get.call(receiver); } return desc.value; }; } return _get(target, property, receiver || target); }\n\nfunction _superPropBase(object, property) { while (!Object.prototype.hasOwnProperty.call(object, property)) { object = _getPrototypeOf(object); if (object === null) break; } return object; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\n\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\n\nfunction _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }\n\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === \"object\" || typeof call === \"function\")) { return call; } else if (call !== void 0) { throw new TypeError(\"Derived constructors may only return object or undefined\"); } return _assertThisInitialized(self); }\n\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return self; }\n\nfunction _isNativeReflectConstruct() { if (typeof Reflect === \"undefined\" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === \"function\") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }\n\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\n\nvar AudioNub = /*#__PURE__*/function (_AdNode) {\n  _inherits(AudioNub, _AdNode);\n\n  var _super = _createSuper(AudioNub);\n\n  function AudioNub(parent, xmlNode, audioContext) {\n    var _this;\n\n    _classCallCheck(this, AudioNub);\n\n    _this = _super.call(this, parent, xmlNode, audioContext);\n\n    _this.copyAudioAttributes(xmlNode);\n\n    _this.createAudioNodes();\n\n    return _this;\n  }\n\n  _createClass(AudioNub, [{\n    key: \"createAudioNodes\",\n    value: function createAudioNodes() {\n      this.gainNode = this.audioContext.createGain(); // Check that StereoPanner is supported. Webkit currently only\n      // supports the older interface's Panner.\n\n      var supportsStereoPanner = this.audioContext.createStereoPanner;\n      var supportsPanner = this.audioContext.createPanner;\n\n      if (supportsStereoPanner) {\n        this.panNode = this.audioContext.createStereoPanner();\n      } else if (supportsPanner) {\n        this.panNode = this.audioContext.createPanner();\n      }\n\n      this.gainNode.connect(this.panNode);\n      this.output = this.panNode;\n\n      if (supportsStereoPanner) {\n        this.panNode.pan.value = this.pan;\n      } else if (supportsPanner) {\n        this.panNode.position = 90 * this.pan;\n      }\n\n      this.gainNode.gain.value = this.gain;\n    }\n  }, {\n    key: \"onActive\",\n    value: function onActive() {\n      if (this.parent && !this.isActive) {\n        this.parent.output.connect(this.gainNode);\n      }\n\n      _get(_getPrototypeOf(AudioNub.prototype), \"onActive\", this).call(this);\n    }\n  }, {\n    key: \"onInactive\",\n    value: function onInactive() {\n      if (this.parent && this.isActive) {\n        this.parent.output.disconnect(this.gainNode);\n      }\n\n      _get(_getPrototypeOf(AudioNub.prototype), \"onInactive\", this).call(this);\n    }\n  }, {\n    key: \"onFinalise\",\n    value: function onFinalise() {\n      _get(_getPrototypeOf(AudioNub.prototype), \"onFinalise\", this).call(this);\n\n      this.gainNode.disconnect(this.panNode);\n    }\n  }, {\n    key: \"gain\",\n    get: function get() {\n      return !isNaN(this._gain) ? this._gain : 1;\n    }\n  }, {\n    key: \"pan\",\n    get: function get() {\n      return !isNaN(this._pan) ? this._pan : 0;\n    }\n  }, {\n    key: \"copyAudioAttributes\",\n    value: function copyAudioAttributes(xmlNode) {\n      if (xmlNode.attributes) {\n        this._gain = parseFloat(_Utils[\"default\"].getAttributeByFullyQualifiedName(xmlNode, \"\".concat(_Utils[\"default\"].NS_TTML_AUDIO_URI, \"%%gain\")));\n        this._pan = parseFloat(_Utils[\"default\"].getAttributeByFullyQualifiedName(xmlNode, \"\".concat(_Utils[\"default\"].NS_TTML_AUDIO_URI, \"%%pan\")));\n      }\n    }\n  }]);\n\n  return AudioNub;\n}(_AdNode2[\"default\"]);\n\nexports[\"default\"] = AudioNub;\n\n//# sourceURL=webpack://adhere-lib/./src/AudioNub.es6?");
 
 /***/ }),
 
@@ -92,7 +92,7 @@ eval("\n\nfunction _typeof(obj) { \"@babel/helpers - typeof\"; if (typeof Symbol
 /***/ ((module, exports) => {
 
 "use strict";
-eval("\n\nObject.defineProperty(exports, \"__esModule\", ({\n  value: true\n}));\nexports.default = void 0;\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\n// Copyright 2019 British Broadcasting Corporation\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\nvar callbacks = [];\nvar consoleEnabled = false;\nvar callbacksEnabled = true;\nvar videoplayer;\n/*eslint no-console: [\"error\", { allow: [\"warn\", \"error\", \"log\", \"dir\"] }] */\n\nvar Logger = /*#__PURE__*/function () {\n  function Logger() {\n    _classCallCheck(this, Logger);\n  }\n\n  _createClass(Logger, null, [{\n    key: \"log\",\n    value: function log(str) {\n      if (videoplayer) {\n        str = \"\".concat(videoplayer.currentTime.toFixed(3).padStart(8, \" \"), \" \").concat(str);\n      }\n\n      if (consoleEnabled) {\n        console.log(str);\n      }\n\n      if (callbacksEnabled) {\n        callbacks.forEach(function (cb) {\n          return cb(str);\n        });\n      }\n    }\n  }, {\n    key: \"addCallback\",\n    value: function addCallback(cb) {\n      callbacks.push(cb);\n    }\n  }, {\n    key: \"enableBrowserLogging\",\n    value: function enableBrowserLogging(value) {\n      consoleEnabled = value;\n    }\n  }, {\n    key: \"error\",\n    value: function error(str) {\n      if (consoleEnabled) {\n        console.error(str);\n      }\n\n      if (callbacksEnabled) {\n        callbacks.forEach(function (cb) {\n          return cb(str);\n        });\n      }\n    }\n  }, {\n    key: \"enableCallbacks\",\n    value: function enableCallbacks(value) {\n      if (consoleEnabled) {\n        console.log(\"Setting consoleEnabled to \".concat(value, \".\"));\n      }\n\n      callbacksEnabled = value;\n    }\n  }, {\n    key: \"setVideoPlayer\",\n    value: function setVideoPlayer(player) {\n      videoplayer = player;\n\n      if (videoplayer) {\n        this.log(\"Videoplayer set, log lines will be prefixed with video player currentTime.\");\n      } else {\n        this.log(\"Videoplayer unset, log lines will not have a timestamp.\");\n      }\n    }\n  }]);\n\n  return Logger;\n}();\n\nexports.default = Logger;\nmodule.exports = exports = {\n  Logger: Logger\n};\n\n//# sourceURL=webpack://adhere-lib/./src/Logger.es6?");
+eval("\n\nObject.defineProperty(exports, \"__esModule\", ({\n  value: true\n}));\nexports[\"default\"] = void 0;\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\n// Copyright 2019 British Broadcasting Corporation\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\nvar callbacks = [];\nvar consoleEnabled = false;\nvar callbacksEnabled = true;\nvar videoplayer;\n/*eslint no-console: [\"error\", { allow: [\"warn\", \"error\", \"log\", \"dir\"] }] */\n\nvar Logger = /*#__PURE__*/function () {\n  function Logger() {\n    _classCallCheck(this, Logger);\n  }\n\n  _createClass(Logger, null, [{\n    key: \"log\",\n    value: function log(str) {\n      if (videoplayer) {\n        str = \"\".concat(videoplayer.currentTime.toFixed(3).padStart(8, \" \"), \" \").concat(str);\n      }\n\n      if (consoleEnabled) {\n        console.log(str);\n      }\n\n      if (callbacksEnabled) {\n        callbacks.forEach(function (cb) {\n          return cb(str);\n        });\n      }\n    }\n  }, {\n    key: \"addCallback\",\n    value: function addCallback(cb) {\n      callbacks.push(cb);\n    }\n  }, {\n    key: \"enableBrowserLogging\",\n    value: function enableBrowserLogging(value) {\n      consoleEnabled = value;\n    }\n  }, {\n    key: \"error\",\n    value: function error(str) {\n      if (consoleEnabled) {\n        console.error(str);\n      }\n\n      if (callbacksEnabled) {\n        callbacks.forEach(function (cb) {\n          return cb(str);\n        });\n      }\n    }\n  }, {\n    key: \"enableCallbacks\",\n    value: function enableCallbacks(value) {\n      if (consoleEnabled) {\n        console.log(\"Setting consoleEnabled to \".concat(value, \".\"));\n      }\n\n      callbacksEnabled = value;\n    }\n  }, {\n    key: \"setVideoPlayer\",\n    value: function setVideoPlayer(player) {\n      videoplayer = player;\n\n      if (videoplayer) {\n        this.log(\"Videoplayer set, log lines will be prefixed with video player currentTime.\");\n      } else {\n        this.log(\"Videoplayer unset, log lines will not have a timestamp.\");\n      }\n    }\n  }]);\n\n  return Logger;\n}();\n\nexports[\"default\"] = Logger;\nmodule.exports = exports = {\n  Logger: Logger\n};\n\n//# sourceURL=webpack://adhere-lib/./src/Logger.es6?");
 
 /***/ }),
 
@@ -103,7 +103,7 @@ eval("\n\nObject.defineProperty(exports, \"__esModule\", ({\n  value: true\n}));
 /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
 
 "use strict";
-eval("\n\nObject.defineProperty(exports, \"__esModule\", ({\n  value: true\n}));\nexports.default = parseTree;\nexports.setAudioCacheStrategy = setAudioCacheStrategy;\nexports.getAudioCacheStrategy = getAudioCacheStrategy;\n\nvar _Utils = _interopRequireDefault(__webpack_require__(/*! ./Utils.es6 */ \"./src/Utils.es6\"));\n\nvar _AdSourceNode = _interopRequireDefault(__webpack_require__(/*! ./AdSourceNode.es6 */ \"./src/AdSourceNode.es6\"));\n\nvar _AdLeafNode = _interopRequireDefault(__webpack_require__(/*! ./AdLeafNode.es6 */ \"./src/AdLeafNode.es6\"));\n\nvar _AdUserControlledSourceNode = _interopRequireDefault(__webpack_require__(/*! ./AdUserControlledSourceNode.es6 */ \"./src/AdUserControlledSourceNode.es6\"));\n\nvar _SpeechSourceNode = _interopRequireDefault(__webpack_require__(/*! ./SpeechSourceNode.es6 */ \"./src/SpeechSourceNode.es6\"));\n\nvar _AudioNub = _interopRequireDefault(__webpack_require__(/*! ./AudioNub.es6 */ \"./src/AudioNub.es6\"));\n\nvar _AnimateNode = _interopRequireDefault(__webpack_require__(/*! ./AnimateNode.es6 */ \"./src/AnimateNode.es6\"));\n\nvar _base64Js = _interopRequireDefault(__webpack_require__(/*! base64-js */ \"./node_modules/base64-js/index.js\"));\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { \"default\": obj }; }\n\nfunction _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== \"undefined\" && o[Symbol.iterator] || o[\"@@iterator\"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === \"number\") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError(\"Invalid attempt to iterate non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it[\"return\"] != null) it[\"return\"](); } finally { if (didErr) throw err; } } }; }\n\nfunction _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === \"string\") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === \"Object\" && o.constructor) n = o.constructor.name; if (n === \"Map\" || n === \"Set\") return Array.from(o); if (n === \"Arguments\" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }\n\nfunction _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }\n\n// import Logger from \"./Logger.es6\";\nvar Logger = __webpack_require__(/*! ./Logger.es6 */ \"./src/Logger.es6\").Logger;\n\nvar CACHE_STRATEGY_REUSE = true;\nvar CACHE_STRATEGY_NOCACHE = false;\nvar currentUrl = \"\";\nvar audioElements = {};\nvar audioResources = {};\nvar trackPrefix = \";track=\";\nvar defaultVideoGain = 1;\nvar audioCacheStrategy = CACHE_STRATEGY_NOCACHE;\n/*eslint func-style: [\"error\", \"declaration\"]*/\n\n/*eslint no-use-before-define: [\"error\", { \"functions\": false }]*/\n\n/*eslint max-statements: [\"error\", 25]*/\n\nfunction isName(fullyQualifiedName, node) {\n  return node.fullyQualifiedName === fullyQualifiedName;\n}\n\nfunction getNamedChildren(fullyQualifiedName, node) {\n  return node.children.filter(isName.bind(null, fullyQualifiedName));\n} //For an audio with a <source> element, make a mediaSrc url from the base64.\n\n\nfunction parseEmbeddedSource(node) {\n  var source = getNamedChildren(\"\".concat(_Utils[\"default\"].NS_TTML_URI, \"%%source\"), node)[0];\n  var data = getNamedChildren(\"\".concat(_Utils[\"default\"].NS_TTML_URI, \"%%data\"), source)[0];\n  var dataType = data.attributes.type;\n  var chunks = getNamedChildren(\"\".concat(_Utils[\"default\"].NS_TTML_URI, \"%%chunk\"), data);\n  var chunk = chunks[0]; //TODO: merge multiple chunks\n\n  if (chunk.children.length > 0) {\n    chunk.value = chunk.children[0].value;\n  }\n\n  var wsRegex = /\\s/gi; // eslint-disable-next-line no-undef\n\n  var dataChunk = _base64Js[\"default\"].toByteArray(chunk.value.replace(wsRegex, \"\"));\n\n  var blob = new Blob([dataChunk], {\n    type: dataType\n  });\n  return URL.createObjectURL(blob);\n}\n\nfunction grabAudioResources(headNode) {\n  var ret = {};\n  var resources = getNamedChildren(\"\".concat(_Utils[\"default\"].NS_TTML_URI, \"%%resources\"), headNode)[0];\n\n  if (resources) {\n    var audios = getNamedChildren(\"\".concat(_Utils[\"default\"].NS_TTML_URI, \"%%audio\"), resources);\n\n    var _iterator = _createForOfIteratorHelper(audios),\n        _step;\n\n    try {\n      for (_iterator.s(); !(_step = _iterator.n()).done;) {\n        var a = _step.value;\n\n        var id = _Utils[\"default\"].getAttributeByFullyQualifiedName(a, \"\".concat(_Utils[\"default\"].NS_XML_URI, \"%%id\"));\n\n        if (id) {\n          audioResources[id] = parseEmbeddedSource(a);\n        }\n      }\n    } catch (err) {\n      _iterator.e(err);\n    } finally {\n      _iterator.f();\n    }\n  }\n\n  return ret;\n}\n\nfunction getAudioElement(audioSrc, audioContext) {\n  if (audioCacheStrategy === CACHE_STRATEGY_REUSE && audioSrc in audioElements) {\n    // Yay reuse this one\n    return audioElements[audioSrc];\n  } // Need to make one\n\n\n  var media = new Audio();\n\n  media.onError = function () {\n    Logger.error(\"Error \".concat(media.error.code, \"; details: \").concat(media.error.message));\n  };\n\n  media.src = audioSrc;\n  media.preload = \"metadata\";\n  var node = audioContext.createMediaElementSource(media);\n  var pair = {\n    media: media,\n    mediaNode: node\n  };\n\n  if (audioCacheStrategy === CACHE_STRATEGY_REUSE) {\n    audioElements[audioSrc] = pair;\n  }\n\n  return pair;\n}\n\nfunction propagateNamespaces(xmlNode) {\n  if (xmlNode.parent === null) {\n    xmlNode.namespaces = _Utils[\"default\"].gleanNamespaces(xmlNode);\n    xmlNode.fullyQualifiedName = _Utils[\"default\"].getFullyQualifiedName(xmlNode);\n  }\n\n  if (xmlNode.children) {\n    var _iterator2 = _createForOfIteratorHelper(xmlNode.children),\n        _step2;\n\n    try {\n      for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {\n        var c = _step2.value;\n\n        if (c.parent === null || c.parent.namespaces === {}) {\n          c.namespaces = _Utils[\"default\"].gleanNamespaces(c);\n        } else {\n          c.namespaces = Object.assign(c.parent.namespaces, _Utils[\"default\"].gleanNamespaces(c));\n        }\n\n        c.fullyQualifiedName = _Utils[\"default\"].getFullyQualifiedName(c);\n        propagateNamespaces(c);\n      }\n    } catch (err) {\n      _iterator2.e(err);\n    } finally {\n      _iterator2.f();\n    }\n  }\n} //The xml parser makes anonymous spans under real spans, let's flatten the two together.\n\n\nfunction flattenSpans(xmlNode) {\n  if (xmlNode.children) {\n    for (var i = 0; i < xmlNode.children.length;) {\n      var c = xmlNode.children[i];\n\n      if ((xmlNode.fullyQualifiedName === \"\".concat(_Utils[\"default\"].NS_TTML_URI, \"%%span\") || xmlNode.fullyQualifiedName === \"\".concat(_Utils[\"default\"].NS_TTML_URI, \"%%chunk\")) && c.fullyQualifiedName === \"\") {\n        xmlNode.value = c.value; //Take the text inside it\n\n        xmlNode.children.splice(i, 1);\n      } else {\n        flattenSpans(c);\n        i++;\n      }\n    }\n  }\n} //remove any nodes that don't fall under the isAudioType definition\n//clear out the unrelated ttml stuff\n\n\nfunction removeOther(xmlNode) {\n  if (xmlNode.children) {\n    for (var i = 0; i < xmlNode.children.length;) {\n      var c = xmlNode.children[i];\n\n      if (!_Utils[\"default\"].isAudioType(c.fullyQualifiedName)) {\n        xmlNode.children.splice(i, 1);\n      } else {\n        removeOther(c);\n        i++;\n      }\n    }\n  }\n}\n\nfunction siblingsHaveAudio(xmlNode) {\n  var siblings = xmlNode.parent.children;\n\n  var _iterator3 = _createForOfIteratorHelper(siblings),\n      _step3;\n\n  try {\n    for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {\n      var s = _step3.value;\n\n      // eslint-disable-next-line eqeqeq\n      if (s != xmlNode && s.fullyQualifiedName === \"\".concat(_Utils[\"default\"].NS_TTML_URI, \"%%audio\")) {\n        return true;\n      }\n    }\n  } catch (err) {\n    _iterator3.e(err);\n  } finally {\n    _iterator3.f();\n  }\n\n  return false;\n}\n\nfunction markAudio(xmlNode) {\n  if (xmlNode.parent) {\n    xmlNode.hasAudio = xmlNode.parent.hasAudio;\n  }\n\n  if (_Utils[\"default\"].isAudioElement(xmlNode) || (xmlNode.fullyQualifiedName === \"\".concat(_Utils[\"default\"].NS_TTML_URI, \"%%p\") || xmlNode.fullyQualifiedName === \"\".concat(_Utils[\"default\"].NS_TTML_URI, \"%%div\") || xmlNode.fullyQualifiedName === \"\" || xmlNode.fullyQualifiedName === \"\".concat(_Utils[\"default\"].NS_TTML_URI, \"%%span\")) && siblingsHaveAudio(xmlNode)) {\n    xmlNode.hasAudio = true;\n  }\n\n  if (xmlNode.children) {\n    var _iterator4 = _createForOfIteratorHelper(xmlNode.children),\n        _step4;\n\n    try {\n      for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {\n        var c = _step4.value;\n        markAudio(c);\n      }\n    } catch (err) {\n      _iterator4.e(err);\n    } finally {\n      _iterator4.f();\n    }\n\n    xmlNode.hasAudio = xmlNode.hasAudio || xmlNode.children.some(function (c) {\n      return c.hasAudio;\n    });\n  }\n}\n\nfunction markSpeech(xmlNode, parentSpeech) {\n  var speechSpecified = false;\n\n  if (xmlNode.attributes) {\n    var speakAttribute = _Utils[\"default\"].getAttributeByFullyQualifiedName(xmlNode, \"\".concat(_Utils[\"default\"].NS_TTML_AUDIO_URI, \"%%speak\"));\n\n    if (speakAttribute) {\n      speechSpecified = true;\n      xmlNode.hasSpeech = !(speakAttribute === \"none\");\n    }\n  }\n\n  if (!speechSpecified) {\n    // it's inherited downwards, if I don't specify, I get what my parent specifies.\n    xmlNode.hasSpeech = parentSpeech;\n  }\n\n  if (xmlNode.children) {\n    var hasSpeech = xmlNode.hasSpeech;\n\n    var _iterator5 = _createForOfIteratorHelper(xmlNode.children),\n        _step5;\n\n    try {\n      for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {\n        var c = _step5.value;\n        var thisChildHasSpeech = markSpeech(c, hasSpeech);\n        xmlNode.hasSpeech = thisChildHasSpeech || xmlNode.hasSpeech; //If any children have speech, I have speech (but that doesn't mean all my children do)\n      }\n    } catch (err) {\n      _iterator5.e(err);\n    } finally {\n      _iterator5.f();\n    }\n  }\n\n  return xmlNode.hasSpeech;\n}\n\nfunction removeNotAudio(xmlNode) {\n  //Remove anythin without .hasAudio or .hasSpeech.\n  if (xmlNode.children) {\n    for (var i = 0; i < xmlNode.children.length;) {\n      var c = xmlNode.children[i];\n\n      if (c.hasAudio || c.hasSpeech) {\n        removeNotAudio(c);\n        i++;\n      } else {\n        xmlNode.children.splice(i, 1);\n      }\n    }\n  }\n}\n\nfunction prepareXML(xmlNode) {\n  propagateNamespaces(xmlNode);\n  flattenSpans(xmlNode);\n  removeOther(xmlNode); //Mark nodes for hasSpeech and hasAudio\n  //Basically am I used in the pathway; if I or my descendants or my ascendants\n  //have speech or audio attributes, I'm marked too.\n\n  markAudio(xmlNode);\n  markSpeech(xmlNode);\n  removeNotAudio(xmlNode);\n}\n\nfunction parseAnimateNode(parent, node, audioContext) {\n  var ret = new _AnimateNode[\"default\"](parent, node, audioContext);\n  return ret;\n}\n\nfunction isLeafNode(node) {\n  return node.fullyQualifiedName === \"\".concat(_Utils[\"default\"].NS_TTML_URI, \"%%span\") || node.fullyQualifiedName === \"\"; //span or anonymous span/\n}\n\nfunction parseSpeechNode(parent, node, audioContext) {\n  var ret = new _SpeechSourceNode[\"default\"](parent, node, audioContext);\n  return ret;\n}\n\nfunction parseAudioSourceNode(parent, node) {\n  var src = node.attributes.src;\n\n  if (src && src.indexOf(trackPrefix) >= 0) {\n    //Ignore body level track specifiers.\n    return undefined;\n  }\n\n  var audioSrc;\n\n  if (src) {\n    if (src.indexOf(\"#\") === 0) {\n      audioSrc = audioResources[src.substring(1)];\n    } else {\n      audioSrc = currentUrl + src;\n    }\n  } else if (!src && node.children) {\n    audioSrc = parseEmbeddedSource(node);\n  } else {\n    Logger.error(\"Found an audio node but couldn't work out what its source is supposed to be.\");\n  }\n\n  var ret;\n\n  if (audioSrc) {\n    var mediaPair = getAudioElement(audioSrc, parent.audioContext);\n    ret = new _AdSourceNode[\"default\"](parent, node, undefined, mediaPair);\n  }\n\n  return ret;\n}\n\nfunction parseNode(parent, node) {\n  var ret = null;\n\n  if (node.fullyQualifiedName === \"\".concat(_Utils[\"default\"].NS_TTML_URI, \"%%audio\")) {\n    ret = parseAudioSourceNode(parent, node);\n  } else if (node.fullyQualifiedName === \"\".concat(_Utils[\"default\"].NS_TTML_URI, \"%%animate\")) {\n    ret = parseAnimateNode(parent, node);\n  } else if (isLeafNode(node)) {\n    ret = parseLeafNode(parent, node);\n  } else {\n    ret = parseIntermediateNode(parent, node);\n  }\n\n  return ret;\n}\n\nfunction parseLeafNode(parent, node, audioContext) {\n  var ret = new _AdLeafNode[\"default\"](parent, node, audioContext);\n  ret.children = node.children.map(parseNode.bind(null, ret)); //Remove nulls. These are nodes to nowhere. We should also remove anonymous spans if we're a leaf.\n\n  ret.children = ret.children.filter(function (n) {\n    return !!n && (n._xmlNode.fullyQualifiedName === \"\".concat(_Utils[\"default\"].NS_TTML_URI, \"%%audio\") || n._xmlNode.fullyQualifiedName === \"\".concat(_Utils[\"default\"].NS_TTML_URI, \"%%animate\"));\n  });\n\n  if (node.hasSpeech) {\n    ret.children.push(parseSpeechNode(ret, node, audioContext));\n  }\n\n  return ret;\n}\n\nfunction parseIntermediateNode(parent, node, audioContext) {\n  var ret = new _AudioNub[\"default\"](parent, node, audioContext);\n  ret.children = node.children.map(parseNode.bind(null, ret));\n  ret.children = ret.children.filter(function (n) {\n    return !!n;\n  }); //Remove nulls. These are nodes to nowhere\n\n  return ret;\n}\n\nfunction parseBody(parent, node, audioContext) {\n  var body = parseNode(parent, node, audioContext);\n  body.postComputeEnd();\n  return body;\n}\n\nfunction parseTree(audioContext, media, url, xmlTree, startRoot) {\n  var root;\n\n  if (startRoot) {\n    //We can't make a new AdSourceNode on the media without\n    root = startRoot;\n  } else {\n    //Make an magic source node for the media - there's no xml for this so fake it.\n    var mediaPair = {\n      media: media,\n      mediaNode: audioContext.createMediaElementSource(media)\n    };\n    root = new _AdUserControlledSourceNode[\"default\"](null, {\n      name: \"root(mediaAudio)\",\n      attributes: {\n        \"tta:gain\": defaultVideoGain,\n        \"tta:pan\": 0\n      },\n      namespaces: {\n        \"default\": _Utils[\"default\"].NS_TTML_URI,\n        xml: _Utils[\"default\"].NS_XML_URI,\n        tta: \"\".concat(_Utils[\"default\"].NS_TTML_AUDIO_URI)\n      },\n      fullyQualifiedName: \"\".concat(_Utils[\"default\"].NS_TTML_URI, \"%%tt\")\n    }, audioContext, mediaPair);\n  }\n\n  var defaultOutput = new _AdLeafNode[\"default\"](root, {\n    name: \"default audio out\",\n    attributes: {},\n    namespaces: {\n      xml: _Utils[\"default\"].NS_XML_URI\n    },\n    fullyQualifiedName: \"\"\n  }, audioContext);\n  defaultOutput.makeDefaultOutput();\n  root.children = [defaultOutput];\n\n  if (typeof url === \"string\") {\n    currentUrl = \"\".concat(url.slice(0, url.lastIndexOf(\"/\")), \"/\");\n  } else {\n    currentUrl = \"\";\n  }\n\n  prepareXML(xmlTree);\n  var head = getNamedChildren(\"\".concat(_Utils[\"default\"].NS_TTML_URI, \"%%head\"), xmlTree)[0];\n\n  if (head) {\n    grabAudioResources(head);\n  }\n\n  if (isName(\"\".concat(_Utils[\"default\"].NS_TTML_URI, \"%%tt\"), xmlTree)) {\n    var body = getNamedChildren(\"\".concat(_Utils[\"default\"].NS_TTML_URI, \"%%body\"), xmlTree)[0];\n\n    if (body) {\n      root.children.push(parseBody(root, body, null));\n    } else {\n      Logger.error(\"Couldn't find body element in the ttml document\");\n    }\n  }\n\n  return root;\n}\n\nfunction setAudioCacheStrategy(cacheStrategy) {\n  audioCacheStrategy = cacheStrategy;\n  Logger.log(\"Audio cache strategy set to \".concat(cacheStrategy === CACHE_STRATEGY_REUSE ? \"REUSE\" : \"NO CACHE\"));\n}\n\nfunction getAudioCacheStrategy() {\n  return audioCacheStrategy;\n}\n\n//# sourceURL=webpack://adhere-lib/./src/Parser.es6?");
+eval("\n\nObject.defineProperty(exports, \"__esModule\", ({\n  value: true\n}));\nexports[\"default\"] = parseTree;\nexports.setAudioCacheStrategy = setAudioCacheStrategy;\nexports.getAudioCacheStrategy = getAudioCacheStrategy;\n\nvar _Utils = _interopRequireDefault(__webpack_require__(/*! ./Utils.es6 */ \"./src/Utils.es6\"));\n\nvar _AdSourceNode = _interopRequireDefault(__webpack_require__(/*! ./AdSourceNode.es6 */ \"./src/AdSourceNode.es6\"));\n\nvar _AdLeafNode = _interopRequireDefault(__webpack_require__(/*! ./AdLeafNode.es6 */ \"./src/AdLeafNode.es6\"));\n\nvar _AdUserControlledSourceNode = _interopRequireDefault(__webpack_require__(/*! ./AdUserControlledSourceNode.es6 */ \"./src/AdUserControlledSourceNode.es6\"));\n\nvar _SpeechSourceNode = _interopRequireDefault(__webpack_require__(/*! ./SpeechSourceNode.es6 */ \"./src/SpeechSourceNode.es6\"));\n\nvar _AudioNub = _interopRequireDefault(__webpack_require__(/*! ./AudioNub.es6 */ \"./src/AudioNub.es6\"));\n\nvar _AnimateNode = _interopRequireDefault(__webpack_require__(/*! ./AnimateNode.es6 */ \"./src/AnimateNode.es6\"));\n\nvar _base64Js = _interopRequireDefault(__webpack_require__(/*! base64-js */ \"./node_modules/base64-js/index.js\"));\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { \"default\": obj }; }\n\nfunction _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== \"undefined\" && o[Symbol.iterator] || o[\"@@iterator\"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === \"number\") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError(\"Invalid attempt to iterate non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it[\"return\"] != null) it[\"return\"](); } finally { if (didErr) throw err; } } }; }\n\nfunction _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === \"string\") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === \"Object\" && o.constructor) n = o.constructor.name; if (n === \"Map\" || n === \"Set\") return Array.from(o); if (n === \"Arguments\" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }\n\nfunction _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }\n\n// import Logger from \"./Logger.es6\";\nvar Logger = __webpack_require__(/*! ./Logger.es6 */ \"./src/Logger.es6\").Logger;\n\nvar CACHE_STRATEGY_REUSE = true;\nvar CACHE_STRATEGY_NOCACHE = false;\nvar currentUrl = \"\";\nvar audioElements = {};\nvar audioResources = {};\nvar trackPrefix = \";track=\";\nvar defaultVideoGain = 1;\nvar audioCacheStrategy = CACHE_STRATEGY_NOCACHE;\n/*eslint func-style: [\"error\", \"declaration\"]*/\n\n/*eslint no-use-before-define: [\"error\", { \"functions\": false }]*/\n\n/*eslint max-statements: [\"error\", 25]*/\n\nfunction isName(fullyQualifiedName, node) {\n  return node.fullyQualifiedName === fullyQualifiedName;\n}\n\nfunction getNamedChildren(fullyQualifiedName, node) {\n  return node.children.filter(isName.bind(null, fullyQualifiedName));\n} //For an audio with a <source> element, make a mediaSrc url from the base64.\n\n\nfunction parseEmbeddedSource(node) {\n  var source = getNamedChildren(\"\".concat(_Utils[\"default\"].NS_TTML_URI, \"%%source\"), node)[0];\n  var data = getNamedChildren(\"\".concat(_Utils[\"default\"].NS_TTML_URI, \"%%data\"), source)[0];\n  var dataType = data.attributes.type;\n  var chunks = getNamedChildren(\"\".concat(_Utils[\"default\"].NS_TTML_URI, \"%%chunk\"), data);\n  var chunk = chunks[0]; //TODO: merge multiple chunks\n\n  if (chunk.children.length > 0) {\n    chunk.value = chunk.children[0].value;\n  }\n\n  var wsRegex = /\\s/gi; // eslint-disable-next-line no-undef\n\n  var dataChunk = _base64Js[\"default\"].toByteArray(chunk.value.replace(wsRegex, \"\"));\n\n  var blob = new Blob([dataChunk], {\n    type: dataType\n  });\n  return URL.createObjectURL(blob);\n}\n\nfunction grabAudioResources(headNode) {\n  var ret = {};\n  var resources = getNamedChildren(\"\".concat(_Utils[\"default\"].NS_TTML_URI, \"%%resources\"), headNode)[0];\n\n  if (resources) {\n    var audios = getNamedChildren(\"\".concat(_Utils[\"default\"].NS_TTML_URI, \"%%audio\"), resources);\n\n    var _iterator = _createForOfIteratorHelper(audios),\n        _step;\n\n    try {\n      for (_iterator.s(); !(_step = _iterator.n()).done;) {\n        var a = _step.value;\n\n        var id = _Utils[\"default\"].getAttributeByFullyQualifiedName(a, \"\".concat(_Utils[\"default\"].NS_XML_URI, \"%%id\"));\n\n        if (id) {\n          audioResources[id] = parseEmbeddedSource(a);\n        }\n      }\n    } catch (err) {\n      _iterator.e(err);\n    } finally {\n      _iterator.f();\n    }\n  }\n\n  return ret;\n}\n\nfunction getAudioElement(audioSrc, audioContext) {\n  if (audioCacheStrategy === CACHE_STRATEGY_REUSE && audioSrc in audioElements) {\n    // Yay reuse this one\n    return audioElements[audioSrc];\n  } // Need to make one\n\n\n  var media = new Audio();\n\n  media.onError = function () {\n    Logger.error(\"Error \".concat(media.error.code, \"; details: \").concat(media.error.message));\n  };\n\n  media.src = audioSrc;\n  media.preload = \"metadata\";\n  var node = audioContext.createMediaElementSource(media);\n  var pair = {\n    media: media,\n    mediaNode: node\n  };\n\n  if (audioCacheStrategy === CACHE_STRATEGY_REUSE) {\n    audioElements[audioSrc] = pair;\n  }\n\n  return pair;\n}\n\nfunction propagateNamespaces(xmlNode) {\n  if (xmlNode.parent === null) {\n    xmlNode.namespaces = _Utils[\"default\"].gleanNamespaces(xmlNode);\n    xmlNode.fullyQualifiedName = _Utils[\"default\"].getFullyQualifiedName(xmlNode);\n  }\n\n  if (xmlNode.children) {\n    var _iterator2 = _createForOfIteratorHelper(xmlNode.children),\n        _step2;\n\n    try {\n      for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {\n        var c = _step2.value;\n\n        if (c.parent === null || c.parent.namespaces === {}) {\n          c.namespaces = _Utils[\"default\"].gleanNamespaces(c);\n        } else {\n          c.namespaces = Object.assign(c.parent.namespaces, _Utils[\"default\"].gleanNamespaces(c));\n        }\n\n        c.fullyQualifiedName = _Utils[\"default\"].getFullyQualifiedName(c);\n        propagateNamespaces(c);\n      }\n    } catch (err) {\n      _iterator2.e(err);\n    } finally {\n      _iterator2.f();\n    }\n  }\n} //The xml parser makes anonymous spans under real spans, let's flatten the two together.\n\n\nfunction flattenSpans(xmlNode) {\n  if (xmlNode.children) {\n    for (var i = 0; i < xmlNode.children.length;) {\n      var c = xmlNode.children[i];\n\n      if ((xmlNode.fullyQualifiedName === \"\".concat(_Utils[\"default\"].NS_TTML_URI, \"%%span\") || xmlNode.fullyQualifiedName === \"\".concat(_Utils[\"default\"].NS_TTML_URI, \"%%chunk\")) && c.fullyQualifiedName === \"\") {\n        xmlNode.value = c.value; //Take the text inside it\n\n        xmlNode.children.splice(i, 1);\n      } else {\n        flattenSpans(c);\n        i++;\n      }\n    }\n  }\n} //remove any nodes that don't fall under the isAudioType definition\n//clear out the unrelated ttml stuff\n\n\nfunction removeOther(xmlNode) {\n  if (xmlNode.children) {\n    for (var i = 0; i < xmlNode.children.length;) {\n      var c = xmlNode.children[i];\n\n      if (!_Utils[\"default\"].isAudioType(c.fullyQualifiedName)) {\n        xmlNode.children.splice(i, 1);\n      } else {\n        removeOther(c);\n        i++;\n      }\n    }\n  }\n}\n\nfunction siblingsHaveAudio(xmlNode) {\n  var siblings = xmlNode.parent.children;\n\n  var _iterator3 = _createForOfIteratorHelper(siblings),\n      _step3;\n\n  try {\n    for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {\n      var s = _step3.value;\n\n      // eslint-disable-next-line eqeqeq\n      if (s != xmlNode && s.fullyQualifiedName === \"\".concat(_Utils[\"default\"].NS_TTML_URI, \"%%audio\")) {\n        return true;\n      }\n    }\n  } catch (err) {\n    _iterator3.e(err);\n  } finally {\n    _iterator3.f();\n  }\n\n  return false;\n}\n\nfunction markAudio(xmlNode) {\n  if (xmlNode.parent) {\n    xmlNode.hasAudio = xmlNode.parent.hasAudio;\n  }\n\n  if (_Utils[\"default\"].isAudioElement(xmlNode) || (xmlNode.fullyQualifiedName === \"\".concat(_Utils[\"default\"].NS_TTML_URI, \"%%p\") || xmlNode.fullyQualifiedName === \"\".concat(_Utils[\"default\"].NS_TTML_URI, \"%%div\") || xmlNode.fullyQualifiedName === \"\" || xmlNode.fullyQualifiedName === \"\".concat(_Utils[\"default\"].NS_TTML_URI, \"%%span\")) && siblingsHaveAudio(xmlNode)) {\n    xmlNode.hasAudio = true;\n  }\n\n  if (xmlNode.children) {\n    var _iterator4 = _createForOfIteratorHelper(xmlNode.children),\n        _step4;\n\n    try {\n      for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {\n        var c = _step4.value;\n        markAudio(c);\n      }\n    } catch (err) {\n      _iterator4.e(err);\n    } finally {\n      _iterator4.f();\n    }\n\n    xmlNode.hasAudio = xmlNode.hasAudio || xmlNode.children.some(function (c) {\n      return c.hasAudio;\n    });\n  }\n}\n\nfunction markSpeech(xmlNode, parentSpeech) {\n  var speechSpecified = false;\n\n  if (xmlNode.attributes) {\n    var speakAttribute = _Utils[\"default\"].getAttributeByFullyQualifiedName(xmlNode, \"\".concat(_Utils[\"default\"].NS_TTML_AUDIO_URI, \"%%speak\"));\n\n    if (speakAttribute) {\n      speechSpecified = true;\n      xmlNode.hasSpeech = !(speakAttribute === \"none\");\n    }\n  }\n\n  if (!speechSpecified) {\n    // it's inherited downwards, if I don't specify, I get what my parent specifies.\n    xmlNode.hasSpeech = parentSpeech;\n  }\n\n  if (xmlNode.children) {\n    var hasSpeech = xmlNode.hasSpeech;\n\n    var _iterator5 = _createForOfIteratorHelper(xmlNode.children),\n        _step5;\n\n    try {\n      for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {\n        var c = _step5.value;\n        var thisChildHasSpeech = markSpeech(c, hasSpeech);\n        xmlNode.hasSpeech = thisChildHasSpeech || xmlNode.hasSpeech; //If any children have speech, I have speech (but that doesn't mean all my children do)\n      }\n    } catch (err) {\n      _iterator5.e(err);\n    } finally {\n      _iterator5.f();\n    }\n  }\n\n  return xmlNode.hasSpeech;\n}\n\nfunction removeNotAudio(xmlNode) {\n  //Remove anythin without .hasAudio or .hasSpeech.\n  if (xmlNode.children) {\n    for (var i = 0; i < xmlNode.children.length;) {\n      var c = xmlNode.children[i];\n\n      if (c.hasAudio || c.hasSpeech) {\n        removeNotAudio(c);\n        i++;\n      } else {\n        xmlNode.children.splice(i, 1);\n      }\n    }\n  }\n}\n\nfunction prepareXML(xmlNode) {\n  propagateNamespaces(xmlNode);\n  flattenSpans(xmlNode);\n  removeOther(xmlNode); //Mark nodes for hasSpeech and hasAudio\n  //Basically am I used in the pathway; if I or my descendants or my ascendants\n  //have speech or audio attributes, I'm marked too.\n\n  markAudio(xmlNode);\n  markSpeech(xmlNode);\n  removeNotAudio(xmlNode);\n}\n\nfunction parseAnimateNode(parent, node, audioContext) {\n  var ret = new _AnimateNode[\"default\"](parent, node, audioContext);\n  return ret;\n}\n\nfunction isLeafNode(node) {\n  return node.fullyQualifiedName === \"\".concat(_Utils[\"default\"].NS_TTML_URI, \"%%span\") || node.fullyQualifiedName === \"\"; //span or anonymous span/\n}\n\nfunction parseSpeechNode(parent, node, audioContext) {\n  var ret = new _SpeechSourceNode[\"default\"](parent, node, audioContext);\n  return ret;\n}\n\nfunction parseAudioSourceNode(parent, node) {\n  var src = node.attributes.src;\n\n  if (src && src.indexOf(trackPrefix) >= 0) {\n    //Ignore body level track specifiers.\n    return undefined;\n  }\n\n  var audioSrc;\n\n  if (src) {\n    if (src.indexOf(\"#\") === 0) {\n      audioSrc = audioResources[src.substring(1)];\n    } else {\n      audioSrc = currentUrl + src;\n    }\n  } else if (!src && node.children) {\n    audioSrc = parseEmbeddedSource(node);\n  } else {\n    Logger.error(\"Found an audio node but couldn't work out what its source is supposed to be.\");\n  }\n\n  var ret;\n\n  if (audioSrc) {\n    var mediaPair = getAudioElement(audioSrc, parent.audioContext);\n    ret = new _AdSourceNode[\"default\"](parent, node, undefined, mediaPair);\n  }\n\n  return ret;\n}\n\nfunction parseNode(parent, node) {\n  var ret = null;\n\n  if (node.fullyQualifiedName === \"\".concat(_Utils[\"default\"].NS_TTML_URI, \"%%audio\")) {\n    ret = parseAudioSourceNode(parent, node);\n  } else if (node.fullyQualifiedName === \"\".concat(_Utils[\"default\"].NS_TTML_URI, \"%%animate\")) {\n    ret = parseAnimateNode(parent, node);\n  } else if (isLeafNode(node)) {\n    ret = parseLeafNode(parent, node);\n  } else {\n    ret = parseIntermediateNode(parent, node);\n  }\n\n  return ret;\n}\n\nfunction parseLeafNode(parent, node, audioContext) {\n  var ret = new _AdLeafNode[\"default\"](parent, node, audioContext);\n  ret.children = node.children.map(parseNode.bind(null, ret)); //Remove nulls. These are nodes to nowhere. We should also remove anonymous spans if we're a leaf.\n\n  ret.children = ret.children.filter(function (n) {\n    return !!n && (n._xmlNode.fullyQualifiedName === \"\".concat(_Utils[\"default\"].NS_TTML_URI, \"%%audio\") || n._xmlNode.fullyQualifiedName === \"\".concat(_Utils[\"default\"].NS_TTML_URI, \"%%animate\"));\n  });\n\n  if (node.hasSpeech) {\n    ret.children.push(parseSpeechNode(ret, node, audioContext));\n  }\n\n  return ret;\n}\n\nfunction parseIntermediateNode(parent, node, audioContext) {\n  var ret = new _AudioNub[\"default\"](parent, node, audioContext);\n  ret.children = node.children.map(parseNode.bind(null, ret));\n  ret.children = ret.children.filter(function (n) {\n    return !!n;\n  }); //Remove nulls. These are nodes to nowhere\n\n  return ret;\n}\n\nfunction parseBody(parent, node, audioContext) {\n  var body = parseNode(parent, node, audioContext);\n  body.postComputeEnd();\n  return body;\n}\n\nfunction parseTree(audioContext, media, url, xmlTree, startRoot) {\n  var root;\n\n  if (startRoot) {\n    //We can't make a new AdSourceNode on the media without\n    root = startRoot;\n  } else {\n    //Make an magic source node for the media - there's no xml for this so fake it.\n    var mediaPair = {\n      media: media,\n      mediaNode: audioContext.createMediaElementSource(media)\n    };\n    root = new _AdUserControlledSourceNode[\"default\"](null, {\n      name: \"root(mediaAudio)\",\n      attributes: {\n        \"tta:gain\": defaultVideoGain,\n        \"tta:pan\": 0\n      },\n      namespaces: {\n        \"default\": _Utils[\"default\"].NS_TTML_URI,\n        xml: _Utils[\"default\"].NS_XML_URI,\n        tta: \"\".concat(_Utils[\"default\"].NS_TTML_AUDIO_URI)\n      },\n      fullyQualifiedName: \"\".concat(_Utils[\"default\"].NS_TTML_URI, \"%%tt\")\n    }, audioContext, mediaPair);\n  }\n\n  var defaultOutput = new _AdLeafNode[\"default\"](root, {\n    name: \"default audio out\",\n    attributes: {},\n    namespaces: {\n      xml: _Utils[\"default\"].NS_XML_URI\n    },\n    fullyQualifiedName: \"\"\n  }, audioContext);\n  defaultOutput.makeDefaultOutput();\n  root.children = [defaultOutput];\n\n  if (typeof url === \"string\") {\n    currentUrl = \"\".concat(url.slice(0, url.lastIndexOf(\"/\")), \"/\");\n  } else {\n    currentUrl = \"\";\n  }\n\n  prepareXML(xmlTree);\n  var head = getNamedChildren(\"\".concat(_Utils[\"default\"].NS_TTML_URI, \"%%head\"), xmlTree)[0];\n\n  if (head) {\n    grabAudioResources(head);\n  }\n\n  if (isName(\"\".concat(_Utils[\"default\"].NS_TTML_URI, \"%%tt\"), xmlTree)) {\n    var body = getNamedChildren(\"\".concat(_Utils[\"default\"].NS_TTML_URI, \"%%body\"), xmlTree)[0];\n\n    if (body) {\n      root.children.push(parseBody(root, body, null));\n    } else {\n      Logger.error(\"Couldn't find body element in the ttml document\");\n    }\n  }\n\n  return root;\n}\n\nfunction setAudioCacheStrategy(cacheStrategy) {\n  audioCacheStrategy = cacheStrategy;\n  Logger.log(\"Audio cache strategy set to \".concat(cacheStrategy === CACHE_STRATEGY_REUSE ? \"REUSE\" : \"NO CACHE\"));\n}\n\nfunction getAudioCacheStrategy() {\n  return audioCacheStrategy;\n}\n\n//# sourceURL=webpack://adhere-lib/./src/Parser.es6?");
 
 /***/ }),
 
@@ -114,7 +114,7 @@ eval("\n\nObject.defineProperty(exports, \"__esModule\", ({\n  value: true\n}));
 /***/ ((__unused_webpack_module, exports) => {
 
 "use strict";
-eval("\n\nObject.defineProperty(exports, \"__esModule\", ({\n  value: true\n}));\nexports.default = void 0;\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\nvar PlaybackPropertiesSingleton = /*#__PURE__*/function () {\n  function PlaybackPropertiesSingleton() {\n    var _this = this;\n\n    _classCallCheck(this, PlaybackPropertiesSingleton);\n\n    //console.log(\"Created instance\");\n    this.advolCallbacks = [];\n    this.advol = document.querySelector(\"#advol\");\n\n    this.advol.onchange = function () {\n      _this.advolCallbacks.forEach(function (callback) {\n        callback(_this.getCurrentGain());\n      });\n    };\n  } //Fetch UI gain value\n\n\n  _createClass(PlaybackPropertiesSingleton, [{\n    key: \"getCurrentGain\",\n    value: function getCurrentGain() {\n      //console.info(\"Call to get current gain\");\n      return parseFloat(this.advol.value);\n    } //Register function and return its index\n\n  }, {\n    key: \"registerCallback\",\n    value: function registerCallback(fn) {\n      return this.advolCallbacks.push(fn) - 1;\n    } //Deregister callback by index\n\n  }, {\n    key: \"deregisterCallback\",\n    value: function deregisterCallback(index) {\n      delete this.advolCallbacks[index];\n    }\n  }]);\n\n  return PlaybackPropertiesSingleton;\n}();\n\nvar PlaybackProperties = new PlaybackPropertiesSingleton();\nvar _default = PlaybackProperties;\nexports.default = _default;\n\n//# sourceURL=webpack://adhere-lib/./src/PlaybackProperties.es6?");
+eval("\n\nObject.defineProperty(exports, \"__esModule\", ({\n  value: true\n}));\nexports[\"default\"] = void 0;\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\nvar PlaybackPropertiesSingleton = /*#__PURE__*/function () {\n  function PlaybackPropertiesSingleton() {\n    var _this = this;\n\n    _classCallCheck(this, PlaybackPropertiesSingleton);\n\n    //console.log(\"Created instance\");\n    this.advolCallbacks = [];\n    this.advol = document.querySelector(\"#advol\");\n\n    this.advol.onchange = function () {\n      _this.advolCallbacks.forEach(function (callback) {\n        callback(_this.getCurrentGain());\n      });\n    };\n  } //Fetch UI gain value\n\n\n  _createClass(PlaybackPropertiesSingleton, [{\n    key: \"getCurrentGain\",\n    value: function getCurrentGain() {\n      //console.info(\"Call to get current gain\");\n      return parseFloat(this.advol.value);\n    } //Register function and return its index\n\n  }, {\n    key: \"registerCallback\",\n    value: function registerCallback(fn) {\n      return this.advolCallbacks.push(fn) - 1;\n    } //Deregister callback by index\n\n  }, {\n    key: \"deregisterCallback\",\n    value: function deregisterCallback(index) {\n      delete this.advolCallbacks[index];\n    }\n  }]);\n\n  return PlaybackPropertiesSingleton;\n}();\n\nvar PlaybackProperties = new PlaybackPropertiesSingleton();\nvar _default = PlaybackProperties;\nexports[\"default\"] = _default;\n\n//# sourceURL=webpack://adhere-lib/./src/PlaybackProperties.es6?");
 
 /***/ }),
 
@@ -125,7 +125,7 @@ eval("\n\nObject.defineProperty(exports, \"__esModule\", ({\n  value: true\n}));
 /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
 
 "use strict";
-eval("\n\nfunction _typeof(obj) { \"@babel/helpers - typeof\"; if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }; } return _typeof(obj); }\n\nObject.defineProperty(exports, \"__esModule\", ({\n  value: true\n}));\nexports.default = void 0;\n\nvar _AdNode2 = _interopRequireDefault(__webpack_require__(/*! ./AdNode.es6 */ \"./src/AdNode.es6\"));\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { \"default\": obj }; }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\nfunction _get(target, property, receiver) { if (typeof Reflect !== \"undefined\" && Reflect.get) { _get = Reflect.get; } else { _get = function _get(target, property, receiver) { var base = _superPropBase(target, property); if (!base) return; var desc = Object.getOwnPropertyDescriptor(base, property); if (desc.get) { return desc.get.call(receiver); } return desc.value; }; } return _get(target, property, receiver || target); }\n\nfunction _superPropBase(object, property) { while (!Object.prototype.hasOwnProperty.call(object, property)) { object = _getPrototypeOf(object); if (object === null) break; } return object; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\n\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\n\nfunction _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }\n\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === \"object\" || typeof call === \"function\")) { return call; } else if (call !== void 0) { throw new TypeError(\"Derived constructors may only return object or undefined\"); } return _assertThisInitialized(self); }\n\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return self; }\n\nfunction _isNativeReflectConstruct() { if (typeof Reflect === \"undefined\" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === \"function\") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }\n\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\n\n// import Logger from \"./Logger.es6\";\nvar Logger = __webpack_require__(/*! ./Logger.es6 */ \"./src/Logger.es6\").Logger;\n/*eslint func-style: [\"error\", \"declaration\"]*/\n\n\nfunction speakToRate(str) {\n  var ret;\n\n  switch (str) {\n    case \"fast\":\n      ret = 1.5;\n      break;\n\n    case \"slow\":\n      ret = 0.66;\n      break;\n\n    case \"normal\":\n    default:\n      ret = 1;\n      break;\n  }\n\n  return ret;\n} //Convert to a value between 0 and 2, 1 being a standard pitch\n//What this output number means isn't clear, and probably up to the browser\n\n\nfunction pitchToValue(str) {\n  var ret = 1;\n\n  if (str) {\n    var pcIdx = str.indexOf(\"%\");\n\n    if (pcIdx >= 0) {\n      var pcstr = str.substring(0, pcIdx);\n      ret = parseFloat(pcstr) / 100 + 1;\n    }\n  }\n\n  return ret;\n}\n\nvar SpeechSourceNode = /*#__PURE__*/function (_AdNode) {\n  _inherits(SpeechSourceNode, _AdNode);\n\n  var _super = _createSuper(SpeechSourceNode);\n\n  function SpeechSourceNode(parent, xmlNode, audioContext) {\n    var _this;\n\n    _classCallCheck(this, SpeechSourceNode);\n\n    _this = _super.call(this, parent, xmlNode, audioContext);\n    _this.utter = new SpeechSynthesisUtterance();\n    _this.utter.text = _this.value;\n    _this.utter.lang = \"en-US\";\n    _this.utter.rate = speakToRate(_this.speak);\n    _this.utter.pitch = pitchToValue(_this.pitch);\n    return _this;\n  }\n\n  _createClass(SpeechSourceNode, [{\n    key: \"onActive\",\n    value: function onActive() {\n      _get(_getPrototypeOf(SpeechSourceNode.prototype), \"onActive\", this).call(this);\n\n      Logger.log(\"\".concat(this.name, \" active speak: \").concat(this.utter.text));\n      speechSynthesis.speak(this.utter);\n    }\n  }, {\n    key: \"onInactive\",\n    value: function onInactive() {\n      _get(_getPrototypeOf(SpeechSourceNode.prototype), \"onInactive\", this).call(this);\n\n      Logger.log(\"\".concat(this.name, \" inactive speak: \").concat(this.utter.text));\n      speechSynthesis.cancel(this.utter);\n    }\n  }, {\n    key: \"onPause\",\n    value: function onPause() {\n      speechSynthesis.pause();\n    }\n  }, {\n    key: \"onResume\",\n    value: function onResume() {\n      speechSynthesis.resume();\n    }\n  }]);\n\n  return SpeechSourceNode;\n}(_AdNode2[\"default\"]);\n\nexports.default = SpeechSourceNode;\n\n//# sourceURL=webpack://adhere-lib/./src/SpeechSourceNode.es6?");
+eval("\n\nfunction _typeof(obj) { \"@babel/helpers - typeof\"; if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }; } return _typeof(obj); }\n\nObject.defineProperty(exports, \"__esModule\", ({\n  value: true\n}));\nexports[\"default\"] = void 0;\n\nvar _AdNode2 = _interopRequireDefault(__webpack_require__(/*! ./AdNode.es6 */ \"./src/AdNode.es6\"));\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { \"default\": obj }; }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\nfunction _get(target, property, receiver) { if (typeof Reflect !== \"undefined\" && Reflect.get) { _get = Reflect.get; } else { _get = function _get(target, property, receiver) { var base = _superPropBase(target, property); if (!base) return; var desc = Object.getOwnPropertyDescriptor(base, property); if (desc.get) { return desc.get.call(receiver); } return desc.value; }; } return _get(target, property, receiver || target); }\n\nfunction _superPropBase(object, property) { while (!Object.prototype.hasOwnProperty.call(object, property)) { object = _getPrototypeOf(object); if (object === null) break; } return object; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\n\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\n\nfunction _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }\n\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === \"object\" || typeof call === \"function\")) { return call; } else if (call !== void 0) { throw new TypeError(\"Derived constructors may only return object or undefined\"); } return _assertThisInitialized(self); }\n\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return self; }\n\nfunction _isNativeReflectConstruct() { if (typeof Reflect === \"undefined\" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === \"function\") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }\n\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\n\n// import Logger from \"./Logger.es6\";\nvar Logger = __webpack_require__(/*! ./Logger.es6 */ \"./src/Logger.es6\").Logger;\n/*eslint func-style: [\"error\", \"declaration\"]*/\n\n\nfunction speakToRate(str) {\n  var ret;\n\n  switch (str) {\n    case \"fast\":\n      ret = 1.5;\n      break;\n\n    case \"slow\":\n      ret = 0.66;\n      break;\n\n    case \"normal\":\n    default:\n      ret = 1;\n      break;\n  }\n\n  return ret;\n} //Convert to a value between 0 and 2, 1 being a standard pitch\n//What this output number means isn't clear, and probably up to the browser\n\n\nfunction pitchToValue(str) {\n  var ret = 1;\n\n  if (str) {\n    var pcIdx = str.indexOf(\"%\");\n\n    if (pcIdx >= 0) {\n      var pcstr = str.substring(0, pcIdx);\n      ret = parseFloat(pcstr) / 100 + 1;\n    }\n  }\n\n  return ret;\n}\n\nvar SpeechSourceNode = /*#__PURE__*/function (_AdNode) {\n  _inherits(SpeechSourceNode, _AdNode);\n\n  var _super = _createSuper(SpeechSourceNode);\n\n  function SpeechSourceNode(parent, xmlNode, audioContext) {\n    var _this;\n\n    _classCallCheck(this, SpeechSourceNode);\n\n    _this = _super.call(this, parent, xmlNode, audioContext);\n    _this.utter = new SpeechSynthesisUtterance();\n    _this.utter.text = _this.value;\n    _this.utter.lang = \"en-US\";\n    _this.utter.rate = speakToRate(_this.speak);\n    _this.utter.pitch = pitchToValue(_this.pitch);\n    return _this;\n  }\n\n  _createClass(SpeechSourceNode, [{\n    key: \"onActive\",\n    value: function onActive() {\n      _get(_getPrototypeOf(SpeechSourceNode.prototype), \"onActive\", this).call(this);\n\n      Logger.log(\"\".concat(this.name, \" active speak: \").concat(this.utter.text));\n      speechSynthesis.speak(this.utter);\n    }\n  }, {\n    key: \"onInactive\",\n    value: function onInactive() {\n      _get(_getPrototypeOf(SpeechSourceNode.prototype), \"onInactive\", this).call(this);\n\n      Logger.log(\"\".concat(this.name, \" inactive speak: \").concat(this.utter.text));\n      speechSynthesis.cancel(this.utter);\n    }\n  }, {\n    key: \"onPause\",\n    value: function onPause() {\n      speechSynthesis.pause();\n    }\n  }, {\n    key: \"onResume\",\n    value: function onResume() {\n      speechSynthesis.resume();\n    }\n  }]);\n\n  return SpeechSourceNode;\n}(_AdNode2[\"default\"]);\n\nexports[\"default\"] = SpeechSourceNode;\n\n//# sourceURL=webpack://adhere-lib/./src/SpeechSourceNode.es6?");
 
 /***/ }),
 
@@ -136,7 +136,7 @@ eval("\n\nfunction _typeof(obj) { \"@babel/helpers - typeof\"; if (typeof Symbol
 /***/ ((module, exports, __webpack_require__) => {
 
 "use strict";
-eval("\n\nObject.defineProperty(exports, \"__esModule\", ({\n  value: true\n}));\nexports.default = void 0;\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\n// Copyright 2019 British Broadcasting Corporation\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n// import Logger from \"./Logger.es6\";\nvar Logger = __webpack_require__(/*! ./Logger.es6 */ \"./src/Logger.es6\").Logger;\n\nvar callbacks = [];\nvar presentedStrings = new Map();\nvar key = 1; // if you start with zero, the first one never leaves\n\n/*eslint no-console: [\"error\", { allow: [\"warn\", \"error\", \"log\", \"dir\"] }] */\n\nvar TextPresenter = /*#__PURE__*/function () {\n  function TextPresenter() {\n    _classCallCheck(this, TextPresenter);\n  }\n\n  _createClass(TextPresenter, null, [{\n    key: \"present\",\n    value: function present(str, source) {\n      var thisKey = key;\n      presentedStrings.set(thisKey, str);\n      key++;\n      Logger.log(\"TP: adding key \".concat(thisKey, \" from \").concat(source, \": \").concat(str));\n      this.updatePresentedText();\n      return thisKey;\n    }\n  }, {\n    key: \"unPresent\",\n    value: function unPresent(removeKey) {\n      // remove the text with the key\n      Logger.log(\"TP: removing value for key \".concat(removeKey));\n      presentedStrings[\"delete\"](removeKey);\n      this.updatePresentedText();\n    }\n  }, {\n    key: \"updatePresentedText\",\n    value: function updatePresentedText() {\n      var generatedString = \"\";\n      presentedStrings.forEach(function (v) {\n        generatedString = v; // change = to += to concatenate, or leave as is to just show the last one\n      });\n      callbacks.forEach(function (cb) {\n        return cb(generatedString);\n      });\n    }\n  }, {\n    key: \"addCallback\",\n    value: function addCallback(cb) {\n      callbacks.push(cb);\n    }\n  }]);\n\n  return TextPresenter;\n}();\n\nexports.default = TextPresenter;\nmodule.exports = exports = {\n  TextPresenter: TextPresenter\n};\n\n//# sourceURL=webpack://adhere-lib/./src/TextPresenter.es6?");
+eval("\n\nObject.defineProperty(exports, \"__esModule\", ({\n  value: true\n}));\nexports[\"default\"] = void 0;\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\n// Copyright 2019 British Broadcasting Corporation\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n// import Logger from \"./Logger.es6\";\nvar Logger = __webpack_require__(/*! ./Logger.es6 */ \"./src/Logger.es6\").Logger;\n\nvar callbacks = [];\nvar presentedStrings = new Map();\nvar key = 1; // if you start with zero, the first one never leaves\n\n/*eslint no-console: [\"error\", { allow: [\"warn\", \"error\", \"log\", \"dir\"] }] */\n\nvar TextPresenter = /*#__PURE__*/function () {\n  function TextPresenter() {\n    _classCallCheck(this, TextPresenter);\n  }\n\n  _createClass(TextPresenter, null, [{\n    key: \"present\",\n    value: function present(str, source) {\n      var thisKey = key;\n      presentedStrings.set(thisKey, str);\n      key++;\n      Logger.log(\"TP: adding key \".concat(thisKey, \" from \").concat(source, \": \").concat(str));\n      this.updatePresentedText();\n      return thisKey;\n    }\n  }, {\n    key: \"unPresent\",\n    value: function unPresent(removeKey) {\n      // remove the text with the key\n      Logger.log(\"TP: removing value for key \".concat(removeKey));\n      presentedStrings[\"delete\"](removeKey);\n      this.updatePresentedText();\n    }\n  }, {\n    key: \"updatePresentedText\",\n    value: function updatePresentedText() {\n      var generatedString = \"\";\n      presentedStrings.forEach(function (v) {\n        generatedString = v; // change = to += to concatenate, or leave as is to just show the last one\n      });\n      callbacks.forEach(function (cb) {\n        return cb(generatedString);\n      });\n    }\n  }, {\n    key: \"addCallback\",\n    value: function addCallback(cb) {\n      callbacks.push(cb);\n    }\n  }]);\n\n  return TextPresenter;\n}();\n\nexports[\"default\"] = TextPresenter;\nmodule.exports = exports = {\n  TextPresenter: TextPresenter\n};\n\n//# sourceURL=webpack://adhere-lib/./src/TextPresenter.es6?");
 
 /***/ }),
 
@@ -147,7 +147,7 @@ eval("\n\nObject.defineProperty(exports, \"__esModule\", ({\n  value: true\n}));
 /***/ ((__unused_webpack_module, exports) => {
 
 "use strict";
-eval("\n\nObject.defineProperty(exports, \"__esModule\", ({\n  value: true\n}));\nexports.default = void 0;\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\n// Copyright 2019 British Broadcasting Corporation\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n/*eslint func-style: [\"error\", \"declaration\"]*/\nfunction nullOrUndefined(thing) {\n  return thing === undefined || thing === null;\n}\n\nfunction specified(thing) {\n  return !nullOrUndefined(thing);\n}\n\nvar TimingCalculator = /*#__PURE__*/function () {\n  function TimingCalculator() {\n    _classCallCheck(this, TimingCalculator);\n  }\n\n  _createClass(TimingCalculator, null, [{\n    key: \"parseTimeString\",\n    value: function parseTimeString(timeStr) {\n      var rgx = /(\\d{2,}):(\\d{2,}):(\\d{2}(?:\\.\\d*)?)/;\n      var groups = timeStr.match(rgx);\n      var hours = parseInt(groups[1]);\n      var mins = parseInt(groups[2]);\n      var secs = parseFloat(groups[3]);\n      var total = hours * 3600 + mins * 60 + secs;\n      return total;\n    }\n  }, {\n    key: \"parseSeconds\",\n    value: function parseSeconds(timeText) {\n      var lowerTimeText = timeText.toLowerCase();\n      var isSecondsString = lowerTimeText.charAt(timeText.length - 1) === \"s\";\n      return isSecondsString ? this.parseSecondText(timeText) : this.parseTimeString(timeText);\n    }\n  }, {\n    key: \"parseSecondText\",\n    value: function parseSecondText(timingText) {\n      var timing = String(timingText);\n      timing = timing.substring(0, timing.length - 1);\n      return parseFloat(timing);\n    }\n  }, {\n    key: \"computeBegin\",\n    value: function computeBegin(element) {\n      var parent = element.parent;\n      var syncbase = parent ? this.computeBegin(parent) : 0;\n      var beginAttr = element.attributes.begin;\n      var begin = beginAttr ? this.parseSeconds(beginAttr) : 0;\n      return syncbase + begin;\n    }\n  }, {\n    key: \"computeEnd\",\n    value: function computeEnd(element) {\n      var _this = this;\n\n      var seekUp = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;\n      var end = this.getSpecifiedEnd(element, seekUp);\n\n      if (nullOrUndefined(end)) {\n        // now we have to get the biggest defined end from each child\n        var ends = [];\n        element.children.forEach(function (c) {\n          ends.push(_this.computeEnd(c, false));\n        });\n\n        if (!ends.includes(undefined) && ends.length > 0) {\n          end = Math.max.apply(Math, ends);\n        }\n      }\n\n      return end;\n    }\n  }, {\n    key: \"getSpecifiedEnd\",\n    value: function getSpecifiedEnd(element) {\n      var seekUp = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;\n      var parentEnd;\n      var resultingSpecifiedEnd;\n      var parent = element.parent;\n\n      if (seekUp && parent) {\n        parentEnd = this.getSpecifiedEnd(parent);\n      }\n\n      var syncbase = parent ? this.computeBegin(parent) : 0;\n      var thisEnd = element.attributes.end ? this.parseSeconds(element.attributes.end) + syncbase : undefined;\n\n      if (specified(thisEnd)) {\n        if (specified(parentEnd)) {\n          resultingSpecifiedEnd = Math.min(thisEnd, parentEnd);\n        } else {\n          resultingSpecifiedEnd = thisEnd;\n        }\n      } else {\n        // we don't specify an end\n        resultingSpecifiedEnd = parentEnd;\n      }\n\n      return resultingSpecifiedEnd;\n    }\n  }]);\n\n  return TimingCalculator;\n}();\n\nexports.default = TimingCalculator;\n\n//# sourceURL=webpack://adhere-lib/./src/TimingCalculator.es6?");
+eval("\n\nObject.defineProperty(exports, \"__esModule\", ({\n  value: true\n}));\nexports[\"default\"] = void 0;\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\n// Copyright 2019 British Broadcasting Corporation\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n/*eslint func-style: [\"error\", \"declaration\"]*/\nfunction nullOrUndefined(thing) {\n  return thing === undefined || thing === null;\n}\n\nfunction specified(thing) {\n  return !nullOrUndefined(thing);\n}\n\nvar TimingCalculator = /*#__PURE__*/function () {\n  function TimingCalculator() {\n    _classCallCheck(this, TimingCalculator);\n  }\n\n  _createClass(TimingCalculator, null, [{\n    key: \"parseTimeString\",\n    value: function parseTimeString(timeStr) {\n      var rgx = /(\\d{2,}):(\\d{2,}):(\\d{2}(?:\\.\\d*)?)/;\n      var groups = timeStr.match(rgx);\n      var hours = parseInt(groups[1]);\n      var mins = parseInt(groups[2]);\n      var secs = parseFloat(groups[3]);\n      var total = hours * 3600 + mins * 60 + secs;\n      return total;\n    }\n  }, {\n    key: \"parseSeconds\",\n    value: function parseSeconds(timeText) {\n      var lowerTimeText = timeText.toLowerCase();\n      var isSecondsString = lowerTimeText.charAt(timeText.length - 1) === \"s\";\n      return isSecondsString ? this.parseSecondText(timeText) : this.parseTimeString(timeText);\n    }\n  }, {\n    key: \"parseSecondText\",\n    value: function parseSecondText(timingText) {\n      var timing = String(timingText);\n      timing = timing.substring(0, timing.length - 1);\n      return parseFloat(timing);\n    }\n  }, {\n    key: \"computeBegin\",\n    value: function computeBegin(element) {\n      var parent = element.parent;\n      var syncbase = parent ? this.computeBegin(parent) : 0;\n      var beginAttr = element.attributes.begin;\n      var begin = beginAttr ? this.parseSeconds(beginAttr) : 0;\n      return syncbase + begin;\n    }\n  }, {\n    key: \"computeEnd\",\n    value: function computeEnd(element) {\n      var _this = this;\n\n      var seekUp = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;\n      var end = this.getSpecifiedEnd(element, seekUp);\n\n      if (nullOrUndefined(end)) {\n        // now we have to get the biggest defined end from each child\n        var ends = [];\n        element.children.forEach(function (c) {\n          ends.push(_this.computeEnd(c, false));\n        });\n\n        if (!ends.includes(undefined) && ends.length > 0) {\n          end = Math.max.apply(Math, ends);\n        }\n      }\n\n      return end;\n    }\n  }, {\n    key: \"getSpecifiedEnd\",\n    value: function getSpecifiedEnd(element) {\n      var seekUp = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;\n      var parentEnd;\n      var resultingSpecifiedEnd;\n      var parent = element.parent;\n\n      if (seekUp && parent) {\n        parentEnd = this.getSpecifiedEnd(parent);\n      }\n\n      var syncbase = parent ? this.computeBegin(parent) : 0;\n      var thisEnd = element.attributes.end ? this.parseSeconds(element.attributes.end) + syncbase : undefined;\n\n      if (specified(thisEnd)) {\n        if (specified(parentEnd)) {\n          resultingSpecifiedEnd = Math.min(thisEnd, parentEnd);\n        } else {\n          resultingSpecifiedEnd = thisEnd;\n        }\n      } else {\n        // we don't specify an end\n        resultingSpecifiedEnd = parentEnd;\n      }\n\n      return resultingSpecifiedEnd;\n    }\n  }]);\n\n  return TimingCalculator;\n}();\n\nexports[\"default\"] = TimingCalculator;\n\n//# sourceURL=webpack://adhere-lib/./src/TimingCalculator.es6?");
 
 /***/ }),
 
@@ -158,7 +158,7 @@ eval("\n\nObject.defineProperty(exports, \"__esModule\", ({\n  value: true\n}));
 /***/ ((__unused_webpack_module, exports) => {
 
 "use strict";
-eval("\n\nObject.defineProperty(exports, \"__esModule\", ({\n  value: true\n}));\nexports.default = void 0;\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\n// Copyright 2019 British Broadcasting Corporation\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\nvar TrackAPIHelper = /*#__PURE__*/function () {\n  function TrackAPIHelper(videoPlayer) {\n    _classCallCheck(this, TrackAPIHelper);\n\n    this.video = videoPlayer;\n    this.track = videoPlayer.addTextTrack(\"metadata\");\n  }\n\n  _createClass(TrackAPIHelper, [{\n    key: \"addCue\",\n    value: function addCue(newCue) {\n      this.track.addCue(newCue);\n    }\n  }, {\n    key: \"removeCues\",\n    value: function removeCues() {\n      while (this.track.cues.length > 0) {\n        this.track.removeCue(this.track.cues[0]);\n      }\n    }\n  }]);\n\n  return TrackAPIHelper;\n}();\n\nexports.default = TrackAPIHelper;\n\n//# sourceURL=webpack://adhere-lib/./src/TrackAPIHelper.es6?");
+eval("\n\nObject.defineProperty(exports, \"__esModule\", ({\n  value: true\n}));\nexports[\"default\"] = void 0;\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\n// Copyright 2019 British Broadcasting Corporation\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\nvar TrackAPIHelper = /*#__PURE__*/function () {\n  function TrackAPIHelper(videoPlayer) {\n    _classCallCheck(this, TrackAPIHelper);\n\n    this.video = videoPlayer;\n    this.track = videoPlayer.addTextTrack(\"metadata\");\n  }\n\n  _createClass(TrackAPIHelper, [{\n    key: \"addCue\",\n    value: function addCue(newCue) {\n      this.track.addCue(newCue);\n    }\n  }, {\n    key: \"removeCues\",\n    value: function removeCues() {\n      while (this.track.cues.length > 0) {\n        this.track.removeCue(this.track.cues[0]);\n      }\n    }\n  }]);\n\n  return TrackAPIHelper;\n}();\n\nexports[\"default\"] = TrackAPIHelper;\n\n//# sourceURL=webpack://adhere-lib/./src/TrackAPIHelper.es6?");
 
 /***/ }),
 
@@ -169,7 +169,7 @@ eval("\n\nObject.defineProperty(exports, \"__esModule\", ({\n  value: true\n}));
 /***/ ((__unused_webpack_module, exports) => {
 
 "use strict";
-eval("\n\nObject.defineProperty(exports, \"__esModule\", ({\n  value: true\n}));\nexports.default = void 0;\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\n// Copyright 2019 British Broadcasting Corporation\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\nvar Utils = /*#__PURE__*/function () {\n  function Utils() {\n    _classCallCheck(this, Utils);\n  }\n\n  _createClass(Utils, null, [{\n    key: \"NS_XML_URI\",\n    get: function get() {\n      return \"http://www.w3.org/XML/1998/namespace\";\n    }\n  }, {\n    key: \"NS_TTML_URI\",\n    get: function get() {\n      return \"http://www.w3.org/ns/ttml\";\n    }\n  }, {\n    key: \"NS_TTML_PARAMETER_URI\",\n    get: function get() {\n      return \"http://www.w3.org/ns/ttml#parameter\";\n    }\n  }, {\n    key: \"NS_TTML_STYLING_URI\",\n    get: function get() {\n      return \"http://www.w3.org/ns/ttml#styling\";\n    }\n  }, {\n    key: \"NS_TTML_AUDIO_URI\",\n    get: function get() {\n      return \"http://www.w3.org/ns/ttml#audio\";\n    }\n  }, {\n    key: \"NS_TTML_METADATA_URI\",\n    get: function get() {\n      return \"http://www.w3.org/ns/ttml#metadata\";\n    }\n  }, {\n    key: \"NS_TTML_ISD_URI\",\n    get: function get() {\n      return \"http://www.w3.org/ns/ttml#isd\";\n    }\n  }, {\n    key: \"isUndefined\",\n    value: function isUndefined(element) {\n      return element === null || element === undefined || element.attributes === undefined || element.name === undefined;\n    }\n  }, {\n    key: \"isAudioType\",\n    value: function isAudioType(fullyQualifiedName) {\n      return fullyQualifiedName === \"\".concat(Utils.NS_TTML_URI, \"%%body\") || fullyQualifiedName === \"\".concat(Utils.NS_TTML_URI, \"%%div\") || fullyQualifiedName === \"\".concat(Utils.NS_TTML_URI, \"%%p\") || fullyQualifiedName === \"\".concat(Utils.NS_TTML_URI, \"%%span\") || fullyQualifiedName === \"\".concat(Utils.NS_TTML_URI, \"%%animate\") || fullyQualifiedName === \"\".concat(Utils.NS_TTML_URI, \"%%audio\") || fullyQualifiedName === \"\".concat(Utils.NS_TTML_URI, \"%%source\") || fullyQualifiedName === \"\".concat(Utils.NS_TTML_URI, \"%%data\") || fullyQualifiedName === \"\".concat(Utils.NS_TTML_URI, \"%%chunk\") || fullyQualifiedName === \"\";\n    }\n  }, {\n    key: \"hasAudioAttribute\",\n    value: function hasAudioAttribute(element) {\n      return this.getAttributeByFullyQualifiedName(element, \"\".concat(Utils.NS_TTML_URI, \"#audio%%gain\")) !== undefined || this.getAttributeByFullyQualifiedName(element, \"\".concat(Utils.NS_TTML_URI, \"#audio%%pan\")) !== undefined || this.getAttributeByFullyQualifiedName(element, \"\".concat(Utils.NS_TTML_URI, \"#audio%%pitch\")) !== undefined || this.getAttributeByFullyQualifiedName(element, \"\".concat(Utils.NS_TTML_URI, \"#audio%%speak\")) !== undefined;\n    }\n  }, {\n    key: \"isAudioElement\",\n    value: function isAudioElement(element) {\n      if (Utils.isUndefined(element)) {\n        return false;\n      }\n\n      var fullyQualifiedName = element.fullyQualifiedName;\n\n      if (fullyQualifiedName === \"\".concat(Utils.NS_TTML_URI, \"%%audio\") || fullyQualifiedName === \"\".concat(Utils.NS_TTML_URI, \"%%source\") || fullyQualifiedName === \"\".concat(Utils.NS_TTML_URI, \"%%data\") || fullyQualifiedName === \"\".concat(Utils.NS_TTML_URI, \"%%chunk\")) {\n        return true;\n      }\n\n      return Utils.isAudioType(fullyQualifiedName) && Utils.hasAudioAttribute(element);\n    }\n  }, {\n    key: \"gleanNamespaces\",\n    value: function gleanNamespaces(element) {\n      var namespaces = {\n        xml: Utils.NS_XML_URI\n      };\n\n      for (var key in element.attributes) {\n        if (element.attributes.hasOwnProperty(key)) {\n          if (key === \"xmlns\") {\n            namespaces[\"default\"] = element.attributes[key];\n          } else if (key === \"xmlns:xml\" && element.attributes[key] !== Utils.NS_XML_URI) {\n            console.warn(\"Namespace xmlns:xml is reserved in XML and must not be bound to another namespace!\");\n            console.warn(\"\".concat(key, \"=\").concat(element.attributes[key], \" is ignored.\"));\n          } else if (key.startsWith(\"xmlns:\")) {\n            namespaces[key.split(\":\")[1]] = element.attributes[key];\n          } else continue;\n        }\n      }\n\n      return namespaces;\n    }\n  }, {\n    key: \"getFullyQualifiedName\",\n    value: function getFullyQualifiedName(element) {\n      if (element.name.includes(\":\")) {\n        var prefix = element.name.split(\":\")[0];\n        var suffix = element.name.split(\":\")[1];\n\n        if (element.namespaces.hasOwnProperty(prefix)) {\n          return \"\".concat(element.namespaces[prefix], \"%%\").concat(suffix);\n        } else {\n          console.warn(\"Cannot find the namespace for element \".concat(element.name, \". Make sure your TTML2 file is valid XML.\"));\n          return undefined;\n        }\n      }\n\n      return element.name === \"\" ? \"\" : \"\".concat(element.namespaces[\"default\"], \"%%\").concat(element.name);\n    }\n  }, {\n    key: \"getAttributeByFullyQualifiedName\",\n    value: function getAttributeByFullyQualifiedName(element, fullyQualifiedAttributeName) {\n      if (fullyQualifiedAttributeName.includes(\"%%\")) {\n        var namespaceURI = fullyQualifiedAttributeName.split(\"%%\")[0];\n        var name = fullyQualifiedAttributeName.split(\"%%\")[1];\n\n        if (namespaceURI === \"\" && element.attributes.hasOwnProperty(name)) {\n          return element.attributes[name];\n        }\n\n        for (var prefix in element.namespaces) {\n          if (namespaceURI === element.namespaces[prefix] && element.attributes.hasOwnProperty(\"\".concat(prefix, \":\").concat(name))) {\n            return element.attributes[\"\".concat(prefix, \":\").concat(name)];\n          }\n        }\n      }\n\n      return undefined;\n    }\n  }]);\n\n  return Utils;\n}();\n\nexports.default = Utils;\n\n//# sourceURL=webpack://adhere-lib/./src/Utils.es6?");
+eval("\n\nObject.defineProperty(exports, \"__esModule\", ({\n  value: true\n}));\nexports[\"default\"] = void 0;\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\n// Copyright 2019 British Broadcasting Corporation\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\nvar Utils = /*#__PURE__*/function () {\n  function Utils() {\n    _classCallCheck(this, Utils);\n  }\n\n  _createClass(Utils, null, [{\n    key: \"NS_XML_URI\",\n    get: function get() {\n      return \"http://www.w3.org/XML/1998/namespace\";\n    }\n  }, {\n    key: \"NS_TTML_URI\",\n    get: function get() {\n      return \"http://www.w3.org/ns/ttml\";\n    }\n  }, {\n    key: \"NS_TTML_PARAMETER_URI\",\n    get: function get() {\n      return \"http://www.w3.org/ns/ttml#parameter\";\n    }\n  }, {\n    key: \"NS_TTML_STYLING_URI\",\n    get: function get() {\n      return \"http://www.w3.org/ns/ttml#styling\";\n    }\n  }, {\n    key: \"NS_TTML_AUDIO_URI\",\n    get: function get() {\n      return \"http://www.w3.org/ns/ttml#audio\";\n    }\n  }, {\n    key: \"NS_TTML_METADATA_URI\",\n    get: function get() {\n      return \"http://www.w3.org/ns/ttml#metadata\";\n    }\n  }, {\n    key: \"NS_TTML_ISD_URI\",\n    get: function get() {\n      return \"http://www.w3.org/ns/ttml#isd\";\n    }\n  }, {\n    key: \"isUndefined\",\n    value: function isUndefined(element) {\n      return element === null || element === undefined || element.attributes === undefined || element.name === undefined;\n    }\n  }, {\n    key: \"isAudioType\",\n    value: function isAudioType(fullyQualifiedName) {\n      return fullyQualifiedName === \"\".concat(Utils.NS_TTML_URI, \"%%body\") || fullyQualifiedName === \"\".concat(Utils.NS_TTML_URI, \"%%div\") || fullyQualifiedName === \"\".concat(Utils.NS_TTML_URI, \"%%p\") || fullyQualifiedName === \"\".concat(Utils.NS_TTML_URI, \"%%span\") || fullyQualifiedName === \"\".concat(Utils.NS_TTML_URI, \"%%animate\") || fullyQualifiedName === \"\".concat(Utils.NS_TTML_URI, \"%%audio\") || fullyQualifiedName === \"\".concat(Utils.NS_TTML_URI, \"%%source\") || fullyQualifiedName === \"\".concat(Utils.NS_TTML_URI, \"%%data\") || fullyQualifiedName === \"\".concat(Utils.NS_TTML_URI, \"%%chunk\") || fullyQualifiedName === \"\";\n    }\n  }, {\n    key: \"hasAudioAttribute\",\n    value: function hasAudioAttribute(element) {\n      return this.getAttributeByFullyQualifiedName(element, \"\".concat(Utils.NS_TTML_URI, \"#audio%%gain\")) !== undefined || this.getAttributeByFullyQualifiedName(element, \"\".concat(Utils.NS_TTML_URI, \"#audio%%pan\")) !== undefined || this.getAttributeByFullyQualifiedName(element, \"\".concat(Utils.NS_TTML_URI, \"#audio%%pitch\")) !== undefined || this.getAttributeByFullyQualifiedName(element, \"\".concat(Utils.NS_TTML_URI, \"#audio%%speak\")) !== undefined;\n    }\n  }, {\n    key: \"isAudioElement\",\n    value: function isAudioElement(element) {\n      if (Utils.isUndefined(element)) {\n        return false;\n      }\n\n      var fullyQualifiedName = element.fullyQualifiedName;\n\n      if (fullyQualifiedName === \"\".concat(Utils.NS_TTML_URI, \"%%audio\") || fullyQualifiedName === \"\".concat(Utils.NS_TTML_URI, \"%%source\") || fullyQualifiedName === \"\".concat(Utils.NS_TTML_URI, \"%%data\") || fullyQualifiedName === \"\".concat(Utils.NS_TTML_URI, \"%%chunk\")) {\n        return true;\n      }\n\n      return Utils.isAudioType(fullyQualifiedName) && Utils.hasAudioAttribute(element);\n    }\n  }, {\n    key: \"gleanNamespaces\",\n    value: function gleanNamespaces(element) {\n      var namespaces = {\n        xml: Utils.NS_XML_URI\n      };\n\n      for (var key in element.attributes) {\n        if (element.attributes.hasOwnProperty(key)) {\n          if (key === \"xmlns\") {\n            namespaces[\"default\"] = element.attributes[key];\n          } else if (key === \"xmlns:xml\" && element.attributes[key] !== Utils.NS_XML_URI) {\n            console.warn(\"Namespace xmlns:xml is reserved in XML and must not be bound to another namespace!\");\n            console.warn(\"\".concat(key, \"=\").concat(element.attributes[key], \" is ignored.\"));\n          } else if (key.startsWith(\"xmlns:\")) {\n            namespaces[key.split(\":\")[1]] = element.attributes[key];\n          } else continue;\n        }\n      }\n\n      return namespaces;\n    }\n  }, {\n    key: \"getFullyQualifiedName\",\n    value: function getFullyQualifiedName(element) {\n      if (element.name.includes(\":\")) {\n        var prefix = element.name.split(\":\")[0];\n        var suffix = element.name.split(\":\")[1];\n\n        if (element.namespaces.hasOwnProperty(prefix)) {\n          return \"\".concat(element.namespaces[prefix], \"%%\").concat(suffix);\n        } else {\n          console.warn(\"Cannot find the namespace for element \".concat(element.name, \". Make sure your TTML2 file is valid XML.\"));\n          return undefined;\n        }\n      }\n\n      return element.name === \"\" ? \"\" : \"\".concat(element.namespaces[\"default\"], \"%%\").concat(element.name);\n    }\n  }, {\n    key: \"getAttributeByFullyQualifiedName\",\n    value: function getAttributeByFullyQualifiedName(element, fullyQualifiedAttributeName) {\n      if (fullyQualifiedAttributeName.includes(\"%%\")) {\n        var namespaceURI = fullyQualifiedAttributeName.split(\"%%\")[0];\n        var name = fullyQualifiedAttributeName.split(\"%%\")[1];\n\n        if (namespaceURI === \"\" && element.attributes.hasOwnProperty(name)) {\n          return element.attributes[name];\n        }\n\n        for (var prefix in element.namespaces) {\n          if (namespaceURI === element.namespaces[prefix] && element.attributes.hasOwnProperty(\"\".concat(prefix, \":\").concat(name))) {\n            return element.attributes[\"\".concat(prefix, \":\").concat(name)];\n          }\n        }\n      }\n\n      return undefined;\n    }\n  }]);\n\n  return Utils;\n}();\n\nexports[\"default\"] = Utils;\n\n//# sourceURL=webpack://adhere-lib/./src/Utils.es6?");
 
 /***/ }),
 
@@ -180,7 +180,7 @@ eval("\n\nObject.defineProperty(exports, \"__esModule\", ({\n  value: true\n}));
 /***/ ((module, exports, __webpack_require__) => {
 
 "use strict";
-eval("\n\nfunction _typeof(obj) { \"@babel/helpers - typeof\"; if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }; } return _typeof(obj); }\n\nObject.defineProperty(exports, \"__esModule\", ({\n  value: true\n}));\nexports.default = void 0;\n\nvar _Utils = _interopRequireDefault(__webpack_require__(/*! ./Utils.es6 */ \"./src/Utils.es6\"));\n\nvar _TrackAPIHelper = _interopRequireDefault(__webpack_require__(/*! ./TrackAPIHelper.es6 */ \"./src/TrackAPIHelper.es6\"));\n\nvar _XMLReader = _interopRequireDefault(__webpack_require__(/*! ./XMLReader.es6 */ \"./src/XMLReader.es6\"));\n\nvar _Parser = _interopRequireWildcard(__webpack_require__(/*! ./Parser.es6 */ \"./src/Parser.es6\"));\n\nfunction _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== \"function\") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }\n\nfunction _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== \"object\" && typeof obj !== \"function\") { return { \"default\": obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== \"default\" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj[\"default\"] = obj; if (cache) { cache.set(obj, newObj); } return newObj; }\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { \"default\": obj }; }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\n// import Logger from \"./Logger.es6\";\nvar Logger = __webpack_require__(/*! ./Logger.es6 */ \"./src/Logger.es6\").Logger;\n\nvar VideoAudioHook = /*#__PURE__*/function () {\n  function VideoAudioHook(videoplayer) {\n    _classCallCheck(this, VideoAudioHook);\n\n    this.videoplayer = videoplayer;\n    this.Utils = _Utils[\"default\"];\n    this.TrackApi = _TrackAPIHelper[\"default\"];\n    this.XMLReader = _XMLReader[\"default\"];\n    this.FileReader = FileReader;\n    this.firstTime = true;\n    this.videoplayer.addEventListener(\"play\", this.onVideoPlay.bind(this));\n    this.videoplayer.addEventListener(\"pause\", this.onVideoPause.bind(this));\n  }\n\n  _createClass(VideoAudioHook, [{\n    key: \"setup\",\n    value: function setup() {\n      this.xmlReader = new this.XMLReader();\n      this.track = new this.TrackApi(this.videoplayer);\n    }\n  }, {\n    key: \"attachTTMLfromFile\",\n    value: function attachTTMLfromFile(ttmlFile) {\n      var _this = this;\n\n      var reader = new this.FileReader();\n\n      reader.onload = function () {\n        _this.parseTTML(ttmlFile, reader.result);\n      };\n\n      reader.readAsText(ttmlFile);\n    }\n  }, {\n    key: \"attachTTMLfromURL\",\n    value: function attachTTMLfromURL(ttmlURL) {\n      var _this2 = this;\n\n      fetch(ttmlURL).then(function (response) {\n        if (!response.ok) throw Error(response.statusText);\n        return response.text().then(function (text) {\n          _this2.parseTTML(ttmlURL, text);\n        });\n      });\n    }\n  }, {\n    key: \"getHttpTTML\",\n    value: function getHttpTTML(ttmlUrl) {\n      var xhr = new XMLHttpRequest();\n      xhr.open(\"GET\", ttmlUrl);\n      xhr.addEventListener(\"load\", this.onTTMLLoad.bind(this));\n      Logger.log(\"GET ttml at: \".concat(ttmlUrl));\n      xhr.send();\n    }\n  }, {\n    key: \"onTTMLLoad\",\n    value: function onTTMLLoad(e) {\n      this.parseTTML(e.target.responseURL, e.target.responseText);\n    }\n  }, {\n    key: \"parseTTML\",\n    value: function parseTTML(url, result) {\n      var media = this.videoplayer;\n      this.xmlReader.parseXML(result, function () {\n        return null;\n      }, this.setupTree.bind(this, media, url));\n    }\n  }, {\n    key: \"audioCacheStrategy\",\n    get: function get() {\n      return (0, _Parser.getAudioCacheStrategy)();\n    },\n    set: function set(cacheStrategy) {\n      (0, _Parser.setAudioCacheStrategy)(cacheStrategy);\n    }\n  }, {\n    key: \"setupTree\",\n    value: function setupTree(media, documentPath, xmlTree) {\n      var _this3 = this;\n\n      if (this.tree) {\n        this.resetTree();\n      } // Work around Webkit, which currently offers the prefixed version only\n\n\n      var AudioContext = window.AudioContext || window.webkitAudioContext;\n      var audioContext = this.tree ? this.tree.audioContext : new AudioContext();\n      this.tree = (0, _Parser[\"default\"])(audioContext, media, documentPath, xmlTree, this.tree);\n      var cues = [];\n      Logger.log(\"VideoAudioHook.setupTree media.duration = \".concat(media.duration));\n      this.tree.makeCueObjects(cues, media);\n      cues.forEach(function (c) {\n        _this3.track.addCue(c);\n      });\n\n      if (this.videoplayer.currentTime > 0) {\n        this.activateTree();\n        this.videoplayer.currentTime = 0;\n      }\n    } //For all nodes in the tree with a NaN beginning, activate them.\n    //We can't do this until play() - Else audio sources without bbegin will start on load\n\n  }, {\n    key: \"activateTree\",\n    value: function activateTree() {\n      this.tree.traverse(function (c) {\n        if (isNaN(c.begin)) {\n          c.onActive();\n        }\n      });\n    } //onFinalise() goes a little further than onInactive\n    //onInactive should be sufficient for audionode garbage collection, but it's not clear if it's the case\n    //Firefox webaudio tab shows audionodes persisting(actually though?) long after use and disconnection\n    //At the very least, we need to revokeObjectURL.\n\n  }, {\n    key: \"resetTree\",\n    value: function resetTree() {\n      this.track.removeCues();\n      this.tree.traverse(function (c) {\n        if (typeof c.onFinalise === \"function\") {\n          c.onFinalise();\n        }\n      });\n      this.tree.children = [];\n    }\n  }, {\n    key: \"onVideoPlay\",\n    value: function onVideoPlay() {\n      var _this4 = this;\n\n      var audioContext = this.tree.audioContext;\n\n      if (audioContext) {\n        Logger.log(\"resuming audio context\");\n        audioContext.resume().then(function () {\n          if (_this4.firstTime) {\n            _this4.activateTree();\n\n            _this4.firstTime = false;\n          } else {\n            _this4.tree.traverse(function (c) {\n              if (typeof c.onRestart === \"function\") {\n                c.onRestart();\n              }\n            });\n          }\n        });\n      }\n    }\n  }, {\n    key: \"onVideoPause\",\n    value: function onVideoPause() {\n      var _this5 = this;\n\n      var audioContext = this.tree.audioContext;\n\n      if (audioContext && audioContext.state === \"running\") {\n        Logger.log(\"suspending audio context\");\n        audioContext.suspend().then(function () {\n          _this5.tree.traverse(function (c) {\n            if (typeof c.onPause === \"function\") {\n              c.onPause();\n            }\n          });\n        });\n      }\n    }\n  }]);\n\n  return VideoAudioHook;\n}();\n\nexports.default = VideoAudioHook;\nmodule.exports = exports = {\n  VideoAudioHook: VideoAudioHook\n};\n\n//# sourceURL=webpack://adhere-lib/./src/VideoAudioHook.es6?");
+eval("\n\nfunction _typeof(obj) { \"@babel/helpers - typeof\"; if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }; } return _typeof(obj); }\n\nObject.defineProperty(exports, \"__esModule\", ({\n  value: true\n}));\nexports[\"default\"] = void 0;\n\nvar _Utils = _interopRequireDefault(__webpack_require__(/*! ./Utils.es6 */ \"./src/Utils.es6\"));\n\nvar _TrackAPIHelper = _interopRequireDefault(__webpack_require__(/*! ./TrackAPIHelper.es6 */ \"./src/TrackAPIHelper.es6\"));\n\nvar _XMLReader = _interopRequireDefault(__webpack_require__(/*! ./XMLReader.es6 */ \"./src/XMLReader.es6\"));\n\nvar _Parser = _interopRequireWildcard(__webpack_require__(/*! ./Parser.es6 */ \"./src/Parser.es6\"));\n\nfunction _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== \"function\") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }\n\nfunction _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== \"object\" && typeof obj !== \"function\") { return { \"default\": obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== \"default\" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj[\"default\"] = obj; if (cache) { cache.set(obj, newObj); } return newObj; }\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { \"default\": obj }; }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\n// import Logger from \"./Logger.es6\";\nvar Logger = __webpack_require__(/*! ./Logger.es6 */ \"./src/Logger.es6\").Logger;\n\nvar VideoAudioHook = /*#__PURE__*/function () {\n  function VideoAudioHook(videoplayer) {\n    _classCallCheck(this, VideoAudioHook);\n\n    this.videoplayer = videoplayer;\n    this.Utils = _Utils[\"default\"];\n    this.TrackApi = _TrackAPIHelper[\"default\"];\n    this.XMLReader = _XMLReader[\"default\"];\n    this.FileReader = FileReader;\n    this.firstTime = true;\n    this.videoplayer.addEventListener(\"play\", this.onVideoPlay.bind(this));\n    this.videoplayer.addEventListener(\"pause\", this.onVideoPause.bind(this));\n  }\n\n  _createClass(VideoAudioHook, [{\n    key: \"setup\",\n    value: function setup() {\n      this.xmlReader = new this.XMLReader();\n      this.track = new this.TrackApi(this.videoplayer);\n    }\n  }, {\n    key: \"attachTTMLfromFile\",\n    value: function attachTTMLfromFile(ttmlFile) {\n      var _this = this;\n\n      var reader = new this.FileReader();\n\n      reader.onload = function () {\n        _this.parseTTML(ttmlFile, reader.result);\n      };\n\n      reader.readAsText(ttmlFile);\n    }\n  }, {\n    key: \"attachTTMLfromURL\",\n    value: function attachTTMLfromURL(ttmlURL) {\n      var _this2 = this;\n\n      fetch(ttmlURL).then(function (response) {\n        if (!response.ok) throw Error(response.statusText);\n        return response.text().then(function (text) {\n          _this2.parseTTML(ttmlURL, text);\n        });\n      });\n    }\n  }, {\n    key: \"getHttpTTML\",\n    value: function getHttpTTML(ttmlUrl) {\n      var xhr = new XMLHttpRequest();\n      xhr.open(\"GET\", ttmlUrl);\n      xhr.addEventListener(\"load\", this.onTTMLLoad.bind(this));\n      Logger.log(\"GET ttml at: \".concat(ttmlUrl));\n      xhr.send();\n    }\n  }, {\n    key: \"onTTMLLoad\",\n    value: function onTTMLLoad(e) {\n      this.parseTTML(e.target.responseURL, e.target.responseText);\n    }\n  }, {\n    key: \"parseTTML\",\n    value: function parseTTML(url, result) {\n      var media = this.videoplayer;\n      this.xmlReader.parseXML(result, function () {\n        return null;\n      }, this.setupTree.bind(this, media, url));\n    }\n  }, {\n    key: \"audioCacheStrategy\",\n    get: function get() {\n      return (0, _Parser.getAudioCacheStrategy)();\n    },\n    set: function set(cacheStrategy) {\n      (0, _Parser.setAudioCacheStrategy)(cacheStrategy);\n    }\n  }, {\n    key: \"setupTree\",\n    value: function setupTree(media, documentPath, xmlTree) {\n      var _this3 = this;\n\n      if (this.tree) {\n        this.resetTree();\n      } // Work around Webkit, which currently offers the prefixed version only\n\n\n      var AudioContext = window.AudioContext || window.webkitAudioContext;\n      var audioContext = this.tree ? this.tree.audioContext : new AudioContext();\n      this.tree = (0, _Parser[\"default\"])(audioContext, media, documentPath, xmlTree, this.tree);\n      var cues = [];\n      Logger.log(\"VideoAudioHook.setupTree media.duration = \".concat(media.duration));\n      this.tree.makeCueObjects(cues, media);\n      cues.forEach(function (c) {\n        _this3.track.addCue(c);\n      });\n\n      if (this.videoplayer.currentTime > 0) {\n        this.activateTree();\n        this.videoplayer.currentTime = 0;\n      }\n    } //For all nodes in the tree with a NaN beginning, activate them.\n    //We can't do this until play() - Else audio sources without bbegin will start on load\n\n  }, {\n    key: \"activateTree\",\n    value: function activateTree() {\n      this.tree.traverse(function (c) {\n        if (isNaN(c.begin)) {\n          c.onActive();\n        }\n      });\n    } //onFinalise() goes a little further than onInactive\n    //onInactive should be sufficient for audionode garbage collection, but it's not clear if it's the case\n    //Firefox webaudio tab shows audionodes persisting(actually though?) long after use and disconnection\n    //At the very least, we need to revokeObjectURL.\n\n  }, {\n    key: \"resetTree\",\n    value: function resetTree() {\n      this.track.removeCues();\n      this.tree.traverse(function (c) {\n        if (typeof c.onFinalise === \"function\") {\n          c.onFinalise();\n        }\n      });\n      this.tree.children = [];\n    }\n  }, {\n    key: \"onVideoPlay\",\n    value: function onVideoPlay() {\n      var _this4 = this;\n\n      var audioContext = this.tree.audioContext;\n\n      if (audioContext) {\n        Logger.log(\"resuming audio context\");\n        audioContext.resume().then(function () {\n          if (_this4.firstTime) {\n            _this4.activateTree();\n\n            _this4.firstTime = false;\n          } else {\n            _this4.tree.traverse(function (c) {\n              if (typeof c.onRestart === \"function\") {\n                c.onRestart();\n              }\n            });\n          }\n        });\n      }\n    }\n  }, {\n    key: \"onVideoPause\",\n    value: function onVideoPause() {\n      var _this5 = this;\n\n      var audioContext = this.tree.audioContext;\n\n      if (audioContext && audioContext.state === \"running\") {\n        Logger.log(\"suspending audio context\");\n        audioContext.suspend().then(function () {\n          _this5.tree.traverse(function (c) {\n            if (typeof c.onPause === \"function\") {\n              c.onPause();\n            }\n          });\n        });\n      }\n    }\n  }]);\n\n  return VideoAudioHook;\n}();\n\nexports[\"default\"] = VideoAudioHook;\nmodule.exports = exports = {\n  VideoAudioHook: VideoAudioHook\n};\n\n//# sourceURL=webpack://adhere-lib/./src/VideoAudioHook.es6?");
 
 /***/ }),
 
@@ -191,7 +191,7 @@ eval("\n\nfunction _typeof(obj) { \"@babel/helpers - typeof\"; if (typeof Symbol
 /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
 
 "use strict";
-eval("\n\nObject.defineProperty(exports, \"__esModule\", ({\n  value: true\n}));\nexports.default = void 0;\n\nvar _xmlReader = _interopRequireDefault(__webpack_require__(/*! xml-reader */ \"./node_modules/xml-reader/dist/reader.js\"));\n\nvar _xmlQuery = _interopRequireDefault(__webpack_require__(/*! xml-query */ \"./node_modules/xml-query/dist/index.js\"));\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { \"default\": obj }; }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\nvar XMLReader = /*#__PURE__*/function () {\n  function XMLReader() {\n    _classCallCheck(this, XMLReader);\n\n    this.xmlReader = _xmlReader[\"default\"].create();\n    this.xmlQuery = _xmlQuery[\"default\"];\n  }\n\n  _createClass(XMLReader, [{\n    key: \"parseXML\",\n    value: function parseXML(ttmlFile, processDiv, doneCB) {\n      this.xmlReader.reset();\n      this.xmlReader.once(\"done\", doneCB);\n      this.xmlReader.parse(ttmlFile);\n    }\n  }]);\n\n  return XMLReader;\n}();\n\nexports.default = XMLReader;\n\n//# sourceURL=webpack://adhere-lib/./src/XMLReader.es6?");
+eval("\n\nObject.defineProperty(exports, \"__esModule\", ({\n  value: true\n}));\nexports[\"default\"] = void 0;\n\nvar _xmlReader = _interopRequireDefault(__webpack_require__(/*! xml-reader */ \"./node_modules/xml-reader/dist/reader.js\"));\n\nvar _xmlQuery = _interopRequireDefault(__webpack_require__(/*! xml-query */ \"./node_modules/xml-query/dist/index.js\"));\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { \"default\": obj }; }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\nvar XMLReader = /*#__PURE__*/function () {\n  function XMLReader() {\n    _classCallCheck(this, XMLReader);\n\n    this.xmlReader = _xmlReader[\"default\"].create();\n    this.xmlQuery = _xmlQuery[\"default\"];\n  }\n\n  _createClass(XMLReader, [{\n    key: \"parseXML\",\n    value: function parseXML(ttmlFile, processDiv, doneCB) {\n      this.xmlReader.reset();\n      this.xmlReader.once(\"done\", doneCB);\n      this.xmlReader.parse(ttmlFile);\n    }\n  }]);\n\n  return XMLReader;\n}();\n\nexports[\"default\"] = XMLReader;\n\n//# sourceURL=webpack://adhere-lib/./src/XMLReader.es6?");
 
 /***/ }),
 
diff --git a/package-lock.json b/package-lock.json
index 960e07a..02eabdd 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -13,9 +13,9 @@
                 "xml-reader": "2.4.3"
             },
             "devDependencies": {
-                "@babel/core": "7.15.0",
-                "@babel/eslint-parser": "7.15.0",
-                "@babel/preset-env": "7.15.0",
+                "@babel/core": "7.15.5",
+                "@babel/eslint-parser": "7.15.4",
+                "@babel/preset-env": "7.15.6",
                 "@babel/register": "7.15.3",
                 "@cucumber/cucumber": "7.3.1",
                 "ava": "3.15.0",
@@ -27,14 +27,14 @@
                 "eslint": "7.32.0",
                 "eslint-config-walmart": "2.2.1",
                 "eslint-plugin-filenames": "1.3.2",
-                "eslint-plugin-import": "2.24.1",
+                "eslint-plugin-import": "2.24.2",
                 "eslint-plugin-jsx-a11y": "6.4.1",
-                "eslint-plugin-react": "7.24.0",
+                "eslint-plugin-react": "7.25.2",
                 "nyc": "15.1.0",
                 "tap-nyan": "1.1.0",
-                "webpack": "5.51.1",
+                "webpack": "5.53.0",
                 "webpack-cli": "4.8.0",
-                "webpack-dev-server": "4.0.0"
+                "webpack-dev-server": "4.2.1"
             },
             "engines": {
                 "node": ">=12.12.0"
@@ -75,19 +75,19 @@
             }
         },
         "node_modules/@babel/core": {
-            "version": "7.15.0",
-            "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.15.0.tgz",
-            "integrity": "sha512-tXtmTminrze5HEUPn/a0JtOzzfp0nk+UEXQ/tqIJo3WDGypl/2OFQEMll/zSFU8f/lfmfLXvTaORHF3cfXIQMw==",
+            "version": "7.15.5",
+            "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.15.5.tgz",
+            "integrity": "sha512-pYgXxiwAgQpgM1bNkZsDEq85f0ggXMA5L7c+o3tskGMh2BunCI9QUwB9Z4jpvXUOuMdyGKiGKQiRe11VS6Jzvg==",
             "dependencies": {
                 "@babel/code-frame": "^7.14.5",
-                "@babel/generator": "^7.15.0",
-                "@babel/helper-compilation-targets": "^7.15.0",
-                "@babel/helper-module-transforms": "^7.15.0",
-                "@babel/helpers": "^7.14.8",
-                "@babel/parser": "^7.15.0",
-                "@babel/template": "^7.14.5",
-                "@babel/traverse": "^7.15.0",
-                "@babel/types": "^7.15.0",
+                "@babel/generator": "^7.15.4",
+                "@babel/helper-compilation-targets": "^7.15.4",
+                "@babel/helper-module-transforms": "^7.15.4",
+                "@babel/helpers": "^7.15.4",
+                "@babel/parser": "^7.15.5",
+                "@babel/template": "^7.15.4",
+                "@babel/traverse": "^7.15.4",
+                "@babel/types": "^7.15.4",
                 "convert-source-map": "^1.7.0",
                 "debug": "^4.1.0",
                 "gensync": "^1.0.0-beta.2",
@@ -128,9 +128,9 @@
             }
         },
         "node_modules/@babel/eslint-parser": {
-            "version": "7.15.0",
-            "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.15.0.tgz",
-            "integrity": "sha512-+gSPtjSBxOZz4Uh8Ggqu7HbfpB8cT1LwW0DnVVLZEJvzXauiD0Di3zszcBkRmfGGrLdYeHUwcflG7i3tr9kQlw==",
+            "version": "7.15.4",
+            "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.15.4.tgz",
+            "integrity": "sha512-hPMIAmGNbmQzXJIo2P43Zj9UhRmGev5f9nqdBFOWNGDGh6XKmjby79woBvg6y0Jur6yRfQBneDbUQ8ZVc1krFw==",
             "dev": true,
             "dependencies": {
                 "eslint-scope": "^5.1.1",
@@ -237,17 +237,17 @@
             }
         },
         "node_modules/@babel/helper-create-class-features-plugin": {
-            "version": "7.14.6",
-            "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.14.6.tgz",
-            "integrity": "sha512-Z6gsfGofTxH/+LQXqYEK45kxmcensbzmk/oi8DmaQytlQCgqNZt9XQF8iqlI/SeXWVjaMNxvYvzaYw+kh42mDg==",
+            "version": "7.15.4",
+            "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.15.4.tgz",
+            "integrity": "sha512-7ZmzFi+DwJx6A7mHRwbuucEYpyBwmh2Ca0RvI6z2+WLZYCqV0JOaLb+u0zbtmDicebgKBZgqbYfLaKNqSgv5Pw==",
             "dev": true,
             "dependencies": {
-                "@babel/helper-annotate-as-pure": "^7.14.5",
-                "@babel/helper-function-name": "^7.14.5",
-                "@babel/helper-member-expression-to-functions": "^7.14.5",
-                "@babel/helper-optimise-call-expression": "^7.14.5",
-                "@babel/helper-replace-supers": "^7.14.5",
-                "@babel/helper-split-export-declaration": "^7.14.5"
+                "@babel/helper-annotate-as-pure": "^7.15.4",
+                "@babel/helper-function-name": "^7.15.4",
+                "@babel/helper-member-expression-to-functions": "^7.15.4",
+                "@babel/helper-optimise-call-expression": "^7.15.4",
+                "@babel/helper-replace-supers": "^7.15.4",
+                "@babel/helper-split-export-declaration": "^7.15.4"
             },
             "engines": {
                 "node": ">=6.9.0"
@@ -467,12 +467,12 @@
             }
         },
         "node_modules/@babel/helper-skip-transparent-expression-wrappers": {
-            "version": "7.14.5",
-            "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.14.5.tgz",
-            "integrity": "sha512-dmqZB7mrb94PZSAOYtr+ZN5qt5owZIAgqtoTuqiFbHFtxgEcmQlRJVI+bO++fciBunXtB6MK7HrzrfcAzIz2NQ==",
+            "version": "7.15.4",
+            "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.15.4.tgz",
+            "integrity": "sha512-BMRLsdh+D1/aap19TycS4eD1qELGrCBJwzaY9IE8LrpJtJb+H7rQkPIdsfgnMtLBA6DJls7X9z93Z4U8h7xw0A==",
             "dev": true,
             "dependencies": {
-                "@babel/types": "^7.14.5"
+                "@babel/types": "^7.15.4"
             },
             "engines": {
                 "node": ">=6.9.0"
@@ -597,13 +597,13 @@
             }
         },
         "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": {
-            "version": "7.14.5",
-            "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.14.5.tgz",
-            "integrity": "sha512-ZoJS2XCKPBfTmL122iP6NM9dOg+d4lc9fFk3zxc8iDjvt8Pk4+TlsHSKhIPf6X+L5ORCdBzqMZDjL/WHj7WknQ==",
+            "version": "7.15.4",
+            "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.15.4.tgz",
+            "integrity": "sha512-eBnpsl9tlhPhpI10kU06JHnrYXwg3+V6CaP2idsCXNef0aeslpqyITXQ74Vfk5uHgY7IG7XP0yIH8b42KSzHog==",
             "dev": true,
             "dependencies": {
                 "@babel/helper-plugin-utils": "^7.14.5",
-                "@babel/helper-skip-transparent-expression-wrappers": "^7.14.5",
+                "@babel/helper-skip-transparent-expression-wrappers": "^7.15.4",
                 "@babel/plugin-proposal-optional-chaining": "^7.14.5"
             },
             "engines": {
@@ -646,12 +646,12 @@
             }
         },
         "node_modules/@babel/plugin-proposal-class-static-block": {
-            "version": "7.14.5",
-            "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.14.5.tgz",
-            "integrity": "sha512-KBAH5ksEnYHCegqseI5N9skTdxgJdmDoAOc0uXa+4QMYKeZD0w5IARh4FMlTNtaHhbB8v+KzMdTgxMMzsIy6Yg==",
+            "version": "7.15.4",
+            "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.15.4.tgz",
+            "integrity": "sha512-M682XWrrLNk3chXCjoPUQWOyYsB93B9z3mRyjtqqYJWDf2mfCdIYgDrA11cgNVhAQieaq6F2fn2f3wI0U4aTjA==",
             "dev": true,
             "dependencies": {
-                "@babel/helper-create-class-features-plugin": "^7.14.5",
+                "@babel/helper-create-class-features-plugin": "^7.15.4",
                 "@babel/helper-plugin-utils": "^7.14.5",
                 "@babel/plugin-syntax-class-static-block": "^7.14.5"
             },
@@ -758,16 +758,16 @@
             }
         },
         "node_modules/@babel/plugin-proposal-object-rest-spread": {
-            "version": "7.14.7",
-            "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.14.7.tgz",
-            "integrity": "sha512-082hsZz+sVabfmDWo1Oct1u1AgbKbUAyVgmX4otIc7bdsRgHBXwTwb3DpDmD4Eyyx6DNiuz5UAATT655k+kL5g==",
+            "version": "7.15.6",
+            "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.15.6.tgz",
+            "integrity": "sha512-qtOHo7A1Vt+O23qEAX+GdBpqaIuD3i9VRrWgCJeq7WO6H2d14EK3q11urj5Te2MAeK97nMiIdRpwd/ST4JFbNg==",
             "dev": true,
             "dependencies": {
-                "@babel/compat-data": "^7.14.7",
-                "@babel/helper-compilation-targets": "^7.14.5",
+                "@babel/compat-data": "^7.15.0",
+                "@babel/helper-compilation-targets": "^7.15.4",
                 "@babel/helper-plugin-utils": "^7.14.5",
                 "@babel/plugin-syntax-object-rest-spread": "^7.8.3",
-                "@babel/plugin-transform-parameters": "^7.14.5"
+                "@babel/plugin-transform-parameters": "^7.15.4"
             },
             "engines": {
                 "node": ">=6.9.0"
@@ -825,13 +825,13 @@
             }
         },
         "node_modules/@babel/plugin-proposal-private-property-in-object": {
-            "version": "7.14.5",
-            "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.14.5.tgz",
-            "integrity": "sha512-62EyfyA3WA0mZiF2e2IV9mc9Ghwxcg8YTu8BS4Wss4Y3PY725OmS9M0qLORbJwLqFtGh+jiE4wAmocK2CTUK2Q==",
+            "version": "7.15.4",
+            "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.15.4.tgz",
+            "integrity": "sha512-X0UTixkLf0PCCffxgu5/1RQyGGbgZuKoI+vXP4iSbJSYwPb7hu06omsFGBvQ9lJEvwgrxHdS8B5nbfcd8GyUNA==",
             "dev": true,
             "dependencies": {
-                "@babel/helper-annotate-as-pure": "^7.14.5",
-                "@babel/helper-create-class-features-plugin": "^7.14.5",
+                "@babel/helper-annotate-as-pure": "^7.15.4",
+                "@babel/helper-create-class-features-plugin": "^7.15.4",
                 "@babel/helper-plugin-utils": "^7.14.5",
                 "@babel/plugin-syntax-private-property-in-object": "^7.14.5"
             },
@@ -1068,9 +1068,9 @@
             }
         },
         "node_modules/@babel/plugin-transform-block-scoping": {
-            "version": "7.14.5",
-            "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.14.5.tgz",
-            "integrity": "sha512-LBYm4ZocNgoCqyxMLoOnwpsmQ18HWTQvql64t3GvMUzLQrNoV1BDG0lNftC8QKYERkZgCCT/7J5xWGObGAyHDw==",
+            "version": "7.15.3",
+            "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.15.3.tgz",
+            "integrity": "sha512-nBAzfZwZb4DkaGtOes1Up1nOAp9TDRRFw4XBzBBSG9QK7KVFmYzgj9o9sbPv7TX5ofL4Auq4wZnxCoPnI/lz2Q==",
             "dev": true,
             "dependencies": {
                 "@babel/helper-plugin-utils": "^7.14.5"
@@ -1189,9 +1189,9 @@
             }
         },
         "node_modules/@babel/plugin-transform-for-of": {
-            "version": "7.14.5",
-            "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.14.5.tgz",
-            "integrity": "sha512-CfmqxSUZzBl0rSjpoQSFoR9UEj3HzbGuGNL21/iFTmjb5gFggJp3ph0xR1YBhexmLoKRHzgxuFvty2xdSt6gTA==",
+            "version": "7.15.4",
+            "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.15.4.tgz",
+            "integrity": "sha512-DRTY9fA751AFBDh2oxydvVm4SYevs5ILTWLs6xKXps4Re/KG5nfUkr+TdHCrRWB8C69TlzVgA9b3RmGWmgN9LA==",
             "dev": true,
             "dependencies": {
                 "@babel/helper-plugin-utils": "^7.14.5"
@@ -1284,15 +1284,15 @@
             }
         },
         "node_modules/@babel/plugin-transform-modules-systemjs": {
-            "version": "7.14.5",
-            "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.14.5.tgz",
-            "integrity": "sha512-mNMQdvBEE5DcMQaL5LbzXFMANrQjd2W7FPzg34Y4yEz7dBgdaC+9B84dSO+/1Wba98zoDbInctCDo4JGxz1VYA==",
+            "version": "7.15.4",
+            "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.15.4.tgz",
+            "integrity": "sha512-fJUnlQrl/mezMneR72CKCgtOoahqGJNVKpompKwzv3BrEXdlPspTcyxrZ1XmDTIr9PpULrgEQo3qNKp6dW7ssw==",
             "dev": true,
             "dependencies": {
-                "@babel/helper-hoist-variables": "^7.14.5",
-                "@babel/helper-module-transforms": "^7.14.5",
+                "@babel/helper-hoist-variables": "^7.15.4",
+                "@babel/helper-module-transforms": "^7.15.4",
                 "@babel/helper-plugin-utils": "^7.14.5",
-                "@babel/helper-validator-identifier": "^7.14.5",
+                "@babel/helper-validator-identifier": "^7.14.9",
                 "babel-plugin-dynamic-import-node": "^2.3.3"
             },
             "engines": {
@@ -1365,9 +1365,9 @@
             }
         },
         "node_modules/@babel/plugin-transform-parameters": {
-            "version": "7.14.5",
-            "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.14.5.tgz",
-            "integrity": "sha512-Tl7LWdr6HUxTmzQtzuU14SqbgrSKmaR77M0OKyq4njZLQTPfOvzblNKyNkGwOfEFCEx7KeYHQHDI0P3F02IVkA==",
+            "version": "7.15.4",
+            "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.15.4.tgz",
+            "integrity": "sha512-9WB/GUTO6lvJU3XQsSr6J/WKvBC2hcs4Pew8YxZagi6GkTdniyqp8On5kqdK8MN0LMeu0mGbhPN+O049NV/9FQ==",
             "dev": true,
             "dependencies": {
                 "@babel/helper-plugin-utils": "^7.14.5"
@@ -1532,30 +1532,31 @@
             }
         },
         "node_modules/@babel/preset-env": {
-            "version": "7.15.0",
-            "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.15.0.tgz",
-            "integrity": "sha512-FhEpCNFCcWW3iZLg0L2NPE9UerdtsCR6ZcsGHUX6Om6kbCQeL5QZDqFDmeNHC6/fy6UH3jEge7K4qG5uC9In0Q==",
+            "version": "7.15.6",
+            "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.15.6.tgz",
+            "integrity": "sha512-L+6jcGn7EWu7zqaO2uoTDjjMBW+88FXzV8KvrBl2z6MtRNxlsmUNRlZPaNNPUTgqhyC5DHNFk/2Jmra+ublZWw==",
             "dev": true,
+            "license": "MIT",
             "dependencies": {
                 "@babel/compat-data": "^7.15.0",
-                "@babel/helper-compilation-targets": "^7.15.0",
+                "@babel/helper-compilation-targets": "^7.15.4",
                 "@babel/helper-plugin-utils": "^7.14.5",
                 "@babel/helper-validator-option": "^7.14.5",
-                "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.14.5",
-                "@babel/plugin-proposal-async-generator-functions": "^7.14.9",
+                "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.15.4",
+                "@babel/plugin-proposal-async-generator-functions": "^7.15.4",
                 "@babel/plugin-proposal-class-properties": "^7.14.5",
-                "@babel/plugin-proposal-class-static-block": "^7.14.5",
+                "@babel/plugin-proposal-class-static-block": "^7.15.4",
                 "@babel/plugin-proposal-dynamic-import": "^7.14.5",
                 "@babel/plugin-proposal-export-namespace-from": "^7.14.5",
                 "@babel/plugin-proposal-json-strings": "^7.14.5",
                 "@babel/plugin-proposal-logical-assignment-operators": "^7.14.5",
                 "@babel/plugin-proposal-nullish-coalescing-operator": "^7.14.5",
                 "@babel/plugin-proposal-numeric-separator": "^7.14.5",
-                "@babel/plugin-proposal-object-rest-spread": "^7.14.7",
+                "@babel/plugin-proposal-object-rest-spread": "^7.15.6",
                 "@babel/plugin-proposal-optional-catch-binding": "^7.14.5",
                 "@babel/plugin-proposal-optional-chaining": "^7.14.5",
                 "@babel/plugin-proposal-private-methods": "^7.14.5",
-                "@babel/plugin-proposal-private-property-in-object": "^7.14.5",
+                "@babel/plugin-proposal-private-property-in-object": "^7.15.4",
                 "@babel/plugin-proposal-unicode-property-regex": "^7.14.5",
                 "@babel/plugin-syntax-async-generators": "^7.8.4",
                 "@babel/plugin-syntax-class-properties": "^7.12.13",
@@ -1574,25 +1575,25 @@
                 "@babel/plugin-transform-arrow-functions": "^7.14.5",
                 "@babel/plugin-transform-async-to-generator": "^7.14.5",
                 "@babel/plugin-transform-block-scoped-functions": "^7.14.5",
-                "@babel/plugin-transform-block-scoping": "^7.14.5",
-                "@babel/plugin-transform-classes": "^7.14.9",
+                "@babel/plugin-transform-block-scoping": "^7.15.3",
+                "@babel/plugin-transform-classes": "^7.15.4",
                 "@babel/plugin-transform-computed-properties": "^7.14.5",
                 "@babel/plugin-transform-destructuring": "^7.14.7",
                 "@babel/plugin-transform-dotall-regex": "^7.14.5",
                 "@babel/plugin-transform-duplicate-keys": "^7.14.5",
                 "@babel/plugin-transform-exponentiation-operator": "^7.14.5",
-                "@babel/plugin-transform-for-of": "^7.14.5",
+                "@babel/plugin-transform-for-of": "^7.15.4",
                 "@babel/plugin-transform-function-name": "^7.14.5",
                 "@babel/plugin-transform-literals": "^7.14.5",
                 "@babel/plugin-transform-member-expression-literals": "^7.14.5",
                 "@babel/plugin-transform-modules-amd": "^7.14.5",
-                "@babel/plugin-transform-modules-commonjs": "^7.15.0",
-                "@babel/plugin-transform-modules-systemjs": "^7.14.5",
+                "@babel/plugin-transform-modules-commonjs": "^7.15.4",
+                "@babel/plugin-transform-modules-systemjs": "^7.15.4",
                 "@babel/plugin-transform-modules-umd": "^7.14.5",
                 "@babel/plugin-transform-named-capturing-groups-regex": "^7.14.9",
                 "@babel/plugin-transform-new-target": "^7.14.5",
                 "@babel/plugin-transform-object-super": "^7.14.5",
-                "@babel/plugin-transform-parameters": "^7.14.5",
+                "@babel/plugin-transform-parameters": "^7.15.4",
                 "@babel/plugin-transform-property-literals": "^7.14.5",
                 "@babel/plugin-transform-regenerator": "^7.14.5",
                 "@babel/plugin-transform-reserved-words": "^7.14.5",
@@ -1604,7 +1605,7 @@
                 "@babel/plugin-transform-unicode-escapes": "^7.14.5",
                 "@babel/plugin-transform-unicode-regex": "^7.14.5",
                 "@babel/preset-modules": "^0.1.4",
-                "@babel/types": "^7.15.0",
+                "@babel/types": "^7.15.6",
                 "babel-plugin-polyfill-corejs2": "^0.2.2",
                 "babel-plugin-polyfill-corejs3": "^0.2.2",
                 "babel-plugin-polyfill-regenerator": "^0.2.2",
@@ -2688,10 +2689,10 @@
                 "node": ">=6"
             }
         },
-        "node_modules/ansi-html": {
-            "version": "0.0.7",
-            "resolved": "https://registry.npmjs.org/ansi-html/-/ansi-html-0.0.7.tgz",
-            "integrity": "sha1-gTWEAhliqenm/QOflA0S9WynhZ4=",
+        "node_modules/ansi-html-community": {
+            "version": "0.0.8",
+            "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz",
+            "integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==",
             "dev": true,
             "engines": [
                 "node >= 0.8.0"
@@ -5411,11 +5412,10 @@
             }
         },
         "node_modules/eslint-plugin-import": {
-            "version": "2.24.1",
-            "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.24.1.tgz",
-            "integrity": "sha512-KSFWhNxPH8OGJwpRJJs+Z7I0a13E2iFQZJIvSnCu6KUs4qmgAm3xN9GYBCSoiGWmwA7gERZPXqYQjcoCROnYhQ==",
+            "version": "2.24.2",
+            "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.24.2.tgz",
+            "integrity": "sha512-hNVtyhiEtZmpsabL4neEj+6M5DCLgpYyG9nzJY8lZQeQXEn5UPW1DpUdsMHMXsq98dbNm7nt1w9ZMSVpfJdi8Q==",
             "dev": true,
-            "license": "MIT",
             "dependencies": {
                 "array-includes": "^3.1.3",
                 "array.prototype.flat": "^1.2.4",
@@ -5431,7 +5431,7 @@
                 "pkg-up": "^2.0.0",
                 "read-pkg-up": "^3.0.0",
                 "resolve": "^1.20.0",
-                "tsconfig-paths": "^3.10.1"
+                "tsconfig-paths": "^3.11.0"
             },
             "engines": {
                 "node": ">=4"
@@ -5530,14 +5530,16 @@
             "dev": true
         },
         "node_modules/eslint-plugin-react": {
-            "version": "7.24.0",
-            "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.24.0.tgz",
-            "integrity": "sha512-KJJIx2SYx7PBx3ONe/mEeMz4YE0Lcr7feJTCMyyKb/341NcjuAgim3Acgan89GfPv7nxXK2+0slu0CWXYM4x+Q==",
+            "version": "7.25.2",
+            "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.25.2.tgz",
+            "integrity": "sha512-elx4585wgmryanJK4C5IoSKQyVZ+e7H0t2JOOtJNBql0cuercvSShvRReuLBbfx8687yW5yv+UL7pXwMsd6adQ==",
             "dev": true,
+            "license": "MIT",
             "dependencies": {
                 "array-includes": "^3.1.3",
                 "array.prototype.flatmap": "^1.2.4",
                 "doctrine": "^2.1.0",
+                "estraverse": "^5.2.0",
                 "has": "^1.0.3",
                 "jsx-ast-utils": "^2.4.1 || ^3.0.0",
                 "minimatch": "^3.0.4",
@@ -5555,6 +5557,15 @@
                 "eslint": "^3 || ^4 || ^5 || ^6 || ^7"
             }
         },
+        "node_modules/eslint-plugin-react/node_modules/estraverse": {
+            "version": "5.2.0",
+            "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz",
+            "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==",
+            "dev": true,
+            "engines": {
+                "node": ">=4.0"
+            }
+        },
         "node_modules/eslint-plugin-react/node_modules/resolve": {
             "version": "2.0.0-next.3",
             "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.3.tgz",
@@ -11973,9 +11984,9 @@
             "dev": true
         },
         "node_modules/webpack": {
-            "version": "5.51.1",
-            "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.51.1.tgz",
-            "integrity": "sha512-xsn3lwqEKoFvqn4JQggPSRxE4dhsRcysWTqYABAZlmavcoTmwlOb9b1N36Inbt/eIispSkuHa80/FJkDTPos1A==",
+            "version": "5.53.0",
+            "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.53.0.tgz",
+            "integrity": "sha512-RZ1Z3z3ni44snoWjfWeHFyzvd9HMVYDYC5VXmlYUT6NWgEOWdCNpad5Fve2CzzHoRED7WtsKe+FCyP5Vk4pWiQ==",
             "dev": true,
             "dependencies": {
                 "@types/eslint-scope": "^3.7.0",
@@ -12105,12 +12116,12 @@
             }
         },
         "node_modules/webpack-dev-server": {
-            "version": "4.0.0",
-            "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.0.0.tgz",
-            "integrity": "sha512-ya5cjoBSf3LqrshZn2HMaRZQx8YRNBE+tx+CQNFGaLLHrvs4Y1aik0sl5SFhLz2cW1O9/NtyaZhthc+8UiuvkQ==",
+            "version": "4.2.1",
+            "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.2.1.tgz",
+            "integrity": "sha512-SQrIyQDZsTaF84p/WMAXNRKxjTeIaewhDIiHYZ423ENhNAsQWyubvqPTn0IoLMGkbhWyWv8/GYnCjItt0ZNC5w==",
             "dev": true,
             "dependencies": {
-                "ansi-html": "^0.0.7",
+                "ansi-html-community": "^0.0.8",
                 "bonjour": "^3.5.0",
                 "chokidar": "^3.5.1",
                 "colorette": "^1.2.2",
@@ -12133,7 +12144,7 @@
                 "spdy": "^4.0.2",
                 "strip-ansi": "^7.0.0",
                 "url": "^0.11.0",
-                "webpack-dev-middleware": "^5.0.0",
+                "webpack-dev-middleware": "^5.1.0",
                 "ws": "^8.1.0"
             },
             "bin": {
@@ -12648,19 +12659,19 @@
             "integrity": "sha512-0NqAC1IJE0S0+lL1SWFMxMkz1pKCNCjI4tr2Zx4LJSXxCLAdr6KyArnY+sno5m3yH9g737ygOyPABDsnXkpxiA=="
         },
         "@babel/core": {
-            "version": "7.15.0",
-            "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.15.0.tgz",
-            "integrity": "sha512-tXtmTminrze5HEUPn/a0JtOzzfp0nk+UEXQ/tqIJo3WDGypl/2OFQEMll/zSFU8f/lfmfLXvTaORHF3cfXIQMw==",
+            "version": "7.15.5",
+            "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.15.5.tgz",
+            "integrity": "sha512-pYgXxiwAgQpgM1bNkZsDEq85f0ggXMA5L7c+o3tskGMh2BunCI9QUwB9Z4jpvXUOuMdyGKiGKQiRe11VS6Jzvg==",
             "requires": {
                 "@babel/code-frame": "^7.14.5",
-                "@babel/generator": "^7.15.0",
-                "@babel/helper-compilation-targets": "^7.15.0",
-                "@babel/helper-module-transforms": "^7.15.0",
-                "@babel/helpers": "^7.14.8",
-                "@babel/parser": "^7.15.0",
-                "@babel/template": "^7.14.5",
-                "@babel/traverse": "^7.15.0",
-                "@babel/types": "^7.15.0",
+                "@babel/generator": "^7.15.4",
+                "@babel/helper-compilation-targets": "^7.15.4",
+                "@babel/helper-module-transforms": "^7.15.4",
+                "@babel/helpers": "^7.15.4",
+                "@babel/parser": "^7.15.5",
+                "@babel/template": "^7.15.4",
+                "@babel/traverse": "^7.15.4",
+                "@babel/types": "^7.15.4",
                 "convert-source-map": "^1.7.0",
                 "debug": "^4.1.0",
                 "gensync": "^1.0.0-beta.2",
@@ -12690,9 +12701,9 @@
             }
         },
         "@babel/eslint-parser": {
-            "version": "7.15.0",
-            "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.15.0.tgz",
-            "integrity": "sha512-+gSPtjSBxOZz4Uh8Ggqu7HbfpB8cT1LwW0DnVVLZEJvzXauiD0Di3zszcBkRmfGGrLdYeHUwcflG7i3tr9kQlw==",
+            "version": "7.15.4",
+            "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.15.4.tgz",
+            "integrity": "sha512-hPMIAmGNbmQzXJIo2P43Zj9UhRmGev5f9nqdBFOWNGDGh6XKmjby79woBvg6y0Jur6yRfQBneDbUQ8ZVc1krFw==",
             "dev": true,
             "requires": {
                 "eslint-scope": "^5.1.1",
@@ -12768,17 +12779,17 @@
             }
         },
         "@babel/helper-create-class-features-plugin": {
-            "version": "7.14.6",
-            "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.14.6.tgz",
-            "integrity": "sha512-Z6gsfGofTxH/+LQXqYEK45kxmcensbzmk/oi8DmaQytlQCgqNZt9XQF8iqlI/SeXWVjaMNxvYvzaYw+kh42mDg==",
+            "version": "7.15.4",
+            "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.15.4.tgz",
+            "integrity": "sha512-7ZmzFi+DwJx6A7mHRwbuucEYpyBwmh2Ca0RvI6z2+WLZYCqV0JOaLb+u0zbtmDicebgKBZgqbYfLaKNqSgv5Pw==",
             "dev": true,
             "requires": {
-                "@babel/helper-annotate-as-pure": "^7.14.5",
-                "@babel/helper-function-name": "^7.14.5",
-                "@babel/helper-member-expression-to-functions": "^7.14.5",
-                "@babel/helper-optimise-call-expression": "^7.14.5",
-                "@babel/helper-replace-supers": "^7.14.5",
-                "@babel/helper-split-export-declaration": "^7.14.5"
+                "@babel/helper-annotate-as-pure": "^7.15.4",
+                "@babel/helper-function-name": "^7.15.4",
+                "@babel/helper-member-expression-to-functions": "^7.15.4",
+                "@babel/helper-optimise-call-expression": "^7.15.4",
+                "@babel/helper-replace-supers": "^7.15.4",
+                "@babel/helper-split-export-declaration": "^7.15.4"
             }
         },
         "@babel/helper-create-regexp-features-plugin": {
@@ -12938,12 +12949,12 @@
             }
         },
         "@babel/helper-skip-transparent-expression-wrappers": {
-            "version": "7.14.5",
-            "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.14.5.tgz",
-            "integrity": "sha512-dmqZB7mrb94PZSAOYtr+ZN5qt5owZIAgqtoTuqiFbHFtxgEcmQlRJVI+bO++fciBunXtB6MK7HrzrfcAzIz2NQ==",
+            "version": "7.15.4",
+            "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.15.4.tgz",
+            "integrity": "sha512-BMRLsdh+D1/aap19TycS4eD1qELGrCBJwzaY9IE8LrpJtJb+H7rQkPIdsfgnMtLBA6DJls7X9z93Z4U8h7xw0A==",
             "dev": true,
             "requires": {
-                "@babel/types": "^7.14.5"
+                "@babel/types": "^7.15.4"
             }
         },
         "@babel/helper-split-export-declaration": {
@@ -13034,13 +13045,13 @@
             "integrity": "sha512-S/TSCcsRuCkmpUuoWijua0Snt+f3ewU/8spLo+4AXJCZfT0bVCzLD5MuOKdrx0mlAptbKzn5AdgEIIKXxXkz9Q=="
         },
         "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": {
-            "version": "7.14.5",
-            "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.14.5.tgz",
-            "integrity": "sha512-ZoJS2XCKPBfTmL122iP6NM9dOg+d4lc9fFk3zxc8iDjvt8Pk4+TlsHSKhIPf6X+L5ORCdBzqMZDjL/WHj7WknQ==",
+            "version": "7.15.4",
+            "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.15.4.tgz",
+            "integrity": "sha512-eBnpsl9tlhPhpI10kU06JHnrYXwg3+V6CaP2idsCXNef0aeslpqyITXQ74Vfk5uHgY7IG7XP0yIH8b42KSzHog==",
             "dev": true,
             "requires": {
                 "@babel/helper-plugin-utils": "^7.14.5",
-                "@babel/helper-skip-transparent-expression-wrappers": "^7.14.5",
+                "@babel/helper-skip-transparent-expression-wrappers": "^7.15.4",
                 "@babel/plugin-proposal-optional-chaining": "^7.14.5"
             }
         },
@@ -13065,12 +13076,12 @@
             }
         },
         "@babel/plugin-proposal-class-static-block": {
-            "version": "7.14.5",
-            "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.14.5.tgz",
-            "integrity": "sha512-KBAH5ksEnYHCegqseI5N9skTdxgJdmDoAOc0uXa+4QMYKeZD0w5IARh4FMlTNtaHhbB8v+KzMdTgxMMzsIy6Yg==",
+            "version": "7.15.4",
+            "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.15.4.tgz",
+            "integrity": "sha512-M682XWrrLNk3chXCjoPUQWOyYsB93B9z3mRyjtqqYJWDf2mfCdIYgDrA11cgNVhAQieaq6F2fn2f3wI0U4aTjA==",
             "dev": true,
             "requires": {
-                "@babel/helper-create-class-features-plugin": "^7.14.5",
+                "@babel/helper-create-class-features-plugin": "^7.15.4",
                 "@babel/helper-plugin-utils": "^7.14.5",
                 "@babel/plugin-syntax-class-static-block": "^7.14.5"
             }
@@ -13135,16 +13146,16 @@
             }
         },
         "@babel/plugin-proposal-object-rest-spread": {
-            "version": "7.14.7",
-            "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.14.7.tgz",
-            "integrity": "sha512-082hsZz+sVabfmDWo1Oct1u1AgbKbUAyVgmX4otIc7bdsRgHBXwTwb3DpDmD4Eyyx6DNiuz5UAATT655k+kL5g==",
+            "version": "7.15.6",
+            "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.15.6.tgz",
+            "integrity": "sha512-qtOHo7A1Vt+O23qEAX+GdBpqaIuD3i9VRrWgCJeq7WO6H2d14EK3q11urj5Te2MAeK97nMiIdRpwd/ST4JFbNg==",
             "dev": true,
             "requires": {
-                "@babel/compat-data": "^7.14.7",
-                "@babel/helper-compilation-targets": "^7.14.5",
+                "@babel/compat-data": "^7.15.0",
+                "@babel/helper-compilation-targets": "^7.15.4",
                 "@babel/helper-plugin-utils": "^7.14.5",
                 "@babel/plugin-syntax-object-rest-spread": "^7.8.3",
-                "@babel/plugin-transform-parameters": "^7.14.5"
+                "@babel/plugin-transform-parameters": "^7.15.4"
             }
         },
         "@babel/plugin-proposal-optional-catch-binding": {
@@ -13178,13 +13189,13 @@
             }
         },
         "@babel/plugin-proposal-private-property-in-object": {
-            "version": "7.14.5",
-            "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.14.5.tgz",
-            "integrity": "sha512-62EyfyA3WA0mZiF2e2IV9mc9Ghwxcg8YTu8BS4Wss4Y3PY725OmS9M0qLORbJwLqFtGh+jiE4wAmocK2CTUK2Q==",
+            "version": "7.15.4",
+            "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.15.4.tgz",
+            "integrity": "sha512-X0UTixkLf0PCCffxgu5/1RQyGGbgZuKoI+vXP4iSbJSYwPb7hu06omsFGBvQ9lJEvwgrxHdS8B5nbfcd8GyUNA==",
             "dev": true,
             "requires": {
-                "@babel/helper-annotate-as-pure": "^7.14.5",
-                "@babel/helper-create-class-features-plugin": "^7.14.5",
+                "@babel/helper-annotate-as-pure": "^7.15.4",
+                "@babel/helper-create-class-features-plugin": "^7.15.4",
                 "@babel/helper-plugin-utils": "^7.14.5",
                 "@babel/plugin-syntax-private-property-in-object": "^7.14.5"
             }
@@ -13352,9 +13363,9 @@
             }
         },
         "@babel/plugin-transform-block-scoping": {
-            "version": "7.14.5",
-            "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.14.5.tgz",
-            "integrity": "sha512-LBYm4ZocNgoCqyxMLoOnwpsmQ18HWTQvql64t3GvMUzLQrNoV1BDG0lNftC8QKYERkZgCCT/7J5xWGObGAyHDw==",
+            "version": "7.15.3",
+            "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.15.3.tgz",
+            "integrity": "sha512-nBAzfZwZb4DkaGtOes1Up1nOAp9TDRRFw4XBzBBSG9QK7KVFmYzgj9o9sbPv7TX5ofL4Auq4wZnxCoPnI/lz2Q==",
             "dev": true,
             "requires": {
                 "@babel/helper-plugin-utils": "^7.14.5"
@@ -13430,9 +13441,9 @@
             }
         },
         "@babel/plugin-transform-for-of": {
-            "version": "7.14.5",
-            "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.14.5.tgz",
-            "integrity": "sha512-CfmqxSUZzBl0rSjpoQSFoR9UEj3HzbGuGNL21/iFTmjb5gFggJp3ph0xR1YBhexmLoKRHzgxuFvty2xdSt6gTA==",
+            "version": "7.15.4",
+            "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.15.4.tgz",
+            "integrity": "sha512-DRTY9fA751AFBDh2oxydvVm4SYevs5ILTWLs6xKXps4Re/KG5nfUkr+TdHCrRWB8C69TlzVgA9b3RmGWmgN9LA==",
             "dev": true,
             "requires": {
                 "@babel/helper-plugin-utils": "^7.14.5"
@@ -13489,15 +13500,15 @@
             }
         },
         "@babel/plugin-transform-modules-systemjs": {
-            "version": "7.14.5",
-            "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.14.5.tgz",
-            "integrity": "sha512-mNMQdvBEE5DcMQaL5LbzXFMANrQjd2W7FPzg34Y4yEz7dBgdaC+9B84dSO+/1Wba98zoDbInctCDo4JGxz1VYA==",
+            "version": "7.15.4",
+            "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.15.4.tgz",
+            "integrity": "sha512-fJUnlQrl/mezMneR72CKCgtOoahqGJNVKpompKwzv3BrEXdlPspTcyxrZ1XmDTIr9PpULrgEQo3qNKp6dW7ssw==",
             "dev": true,
             "requires": {
-                "@babel/helper-hoist-variables": "^7.14.5",
-                "@babel/helper-module-transforms": "^7.14.5",
+                "@babel/helper-hoist-variables": "^7.15.4",
+                "@babel/helper-module-transforms": "^7.15.4",
                 "@babel/helper-plugin-utils": "^7.14.5",
-                "@babel/helper-validator-identifier": "^7.14.5",
+                "@babel/helper-validator-identifier": "^7.14.9",
                 "babel-plugin-dynamic-import-node": "^2.3.3"
             }
         },
@@ -13540,9 +13551,9 @@
             }
         },
         "@babel/plugin-transform-parameters": {
-            "version": "7.14.5",
-            "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.14.5.tgz",
-            "integrity": "sha512-Tl7LWdr6HUxTmzQtzuU14SqbgrSKmaR77M0OKyq4njZLQTPfOvzblNKyNkGwOfEFCEx7KeYHQHDI0P3F02IVkA==",
+            "version": "7.15.4",
+            "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.15.4.tgz",
+            "integrity": "sha512-9WB/GUTO6lvJU3XQsSr6J/WKvBC2hcs4Pew8YxZagi6GkTdniyqp8On5kqdK8MN0LMeu0mGbhPN+O049NV/9FQ==",
             "dev": true,
             "requires": {
                 "@babel/helper-plugin-utils": "^7.14.5"
@@ -13641,30 +13652,30 @@
             }
         },
         "@babel/preset-env": {
-            "version": "7.15.0",
-            "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.15.0.tgz",
-            "integrity": "sha512-FhEpCNFCcWW3iZLg0L2NPE9UerdtsCR6ZcsGHUX6Om6kbCQeL5QZDqFDmeNHC6/fy6UH3jEge7K4qG5uC9In0Q==",
+            "version": "7.15.6",
+            "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.15.6.tgz",
+            "integrity": "sha512-L+6jcGn7EWu7zqaO2uoTDjjMBW+88FXzV8KvrBl2z6MtRNxlsmUNRlZPaNNPUTgqhyC5DHNFk/2Jmra+ublZWw==",
             "dev": true,
             "requires": {
                 "@babel/compat-data": "^7.15.0",
-                "@babel/helper-compilation-targets": "^7.15.0",
+                "@babel/helper-compilation-targets": "^7.15.4",
                 "@babel/helper-plugin-utils": "^7.14.5",
                 "@babel/helper-validator-option": "^7.14.5",
-                "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.14.5",
-                "@babel/plugin-proposal-async-generator-functions": "^7.14.9",
+                "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.15.4",
+                "@babel/plugin-proposal-async-generator-functions": "^7.15.4",
                 "@babel/plugin-proposal-class-properties": "^7.14.5",
-                "@babel/plugin-proposal-class-static-block": "^7.14.5",
+                "@babel/plugin-proposal-class-static-block": "^7.15.4",
                 "@babel/plugin-proposal-dynamic-import": "^7.14.5",
                 "@babel/plugin-proposal-export-namespace-from": "^7.14.5",
                 "@babel/plugin-proposal-json-strings": "^7.14.5",
                 "@babel/plugin-proposal-logical-assignment-operators": "^7.14.5",
                 "@babel/plugin-proposal-nullish-coalescing-operator": "^7.14.5",
                 "@babel/plugin-proposal-numeric-separator": "^7.14.5",
-                "@babel/plugin-proposal-object-rest-spread": "^7.14.7",
+                "@babel/plugin-proposal-object-rest-spread": "^7.15.6",
                 "@babel/plugin-proposal-optional-catch-binding": "^7.14.5",
                 "@babel/plugin-proposal-optional-chaining": "^7.14.5",
                 "@babel/plugin-proposal-private-methods": "^7.14.5",
-                "@babel/plugin-proposal-private-property-in-object": "^7.14.5",
+                "@babel/plugin-proposal-private-property-in-object": "^7.15.4",
                 "@babel/plugin-proposal-unicode-property-regex": "^7.14.5",
                 "@babel/plugin-syntax-async-generators": "^7.8.4",
                 "@babel/plugin-syntax-class-properties": "^7.12.13",
@@ -13683,25 +13694,25 @@
                 "@babel/plugin-transform-arrow-functions": "^7.14.5",
                 "@babel/plugin-transform-async-to-generator": "^7.14.5",
                 "@babel/plugin-transform-block-scoped-functions": "^7.14.5",
-                "@babel/plugin-transform-block-scoping": "^7.14.5",
-                "@babel/plugin-transform-classes": "^7.14.9",
+                "@babel/plugin-transform-block-scoping": "^7.15.3",
+                "@babel/plugin-transform-classes": "^7.15.4",
                 "@babel/plugin-transform-computed-properties": "^7.14.5",
                 "@babel/plugin-transform-destructuring": "^7.14.7",
                 "@babel/plugin-transform-dotall-regex": "^7.14.5",
                 "@babel/plugin-transform-duplicate-keys": "^7.14.5",
                 "@babel/plugin-transform-exponentiation-operator": "^7.14.5",
-                "@babel/plugin-transform-for-of": "^7.14.5",
+                "@babel/plugin-transform-for-of": "^7.15.4",
                 "@babel/plugin-transform-function-name": "^7.14.5",
                 "@babel/plugin-transform-literals": "^7.14.5",
                 "@babel/plugin-transform-member-expression-literals": "^7.14.5",
                 "@babel/plugin-transform-modules-amd": "^7.14.5",
-                "@babel/plugin-transform-modules-commonjs": "^7.15.0",
-                "@babel/plugin-transform-modules-systemjs": "^7.14.5",
+                "@babel/plugin-transform-modules-commonjs": "^7.15.4",
+                "@babel/plugin-transform-modules-systemjs": "^7.15.4",
                 "@babel/plugin-transform-modules-umd": "^7.14.5",
                 "@babel/plugin-transform-named-capturing-groups-regex": "^7.14.9",
                 "@babel/plugin-transform-new-target": "^7.14.5",
                 "@babel/plugin-transform-object-super": "^7.14.5",
-                "@babel/plugin-transform-parameters": "^7.14.5",
+                "@babel/plugin-transform-parameters": "^7.15.4",
                 "@babel/plugin-transform-property-literals": "^7.14.5",
                 "@babel/plugin-transform-regenerator": "^7.14.5",
                 "@babel/plugin-transform-reserved-words": "^7.14.5",
@@ -13713,7 +13724,7 @@
                 "@babel/plugin-transform-unicode-escapes": "^7.14.5",
                 "@babel/plugin-transform-unicode-regex": "^7.14.5",
                 "@babel/preset-modules": "^0.1.4",
-                "@babel/types": "^7.15.0",
+                "@babel/types": "^7.15.6",
                 "babel-plugin-polyfill-corejs2": "^0.2.2",
                 "babel-plugin-polyfill-corejs3": "^0.2.2",
                 "babel-plugin-polyfill-regenerator": "^0.2.2",
@@ -14624,10 +14635,10 @@
                 }
             }
         },
-        "ansi-html": {
-            "version": "0.0.7",
-            "resolved": "https://registry.npmjs.org/ansi-html/-/ansi-html-0.0.7.tgz",
-            "integrity": "sha1-gTWEAhliqenm/QOflA0S9WynhZ4=",
+        "ansi-html-community": {
+            "version": "0.0.8",
+            "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz",
+            "integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==",
             "dev": true
         },
         "ansi-regex": {
@@ -17077,9 +17088,9 @@
             }
         },
         "eslint-plugin-import": {
-            "version": "2.24.1",
-            "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.24.1.tgz",
-            "integrity": "sha512-KSFWhNxPH8OGJwpRJJs+Z7I0a13E2iFQZJIvSnCu6KUs4qmgAm3xN9GYBCSoiGWmwA7gERZPXqYQjcoCROnYhQ==",
+            "version": "2.24.2",
+            "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.24.2.tgz",
+            "integrity": "sha512-hNVtyhiEtZmpsabL4neEj+6M5DCLgpYyG9nzJY8lZQeQXEn5UPW1DpUdsMHMXsq98dbNm7nt1w9ZMSVpfJdi8Q==",
             "dev": true,
             "requires": {
                 "array-includes": "^3.1.3",
@@ -17096,7 +17107,7 @@
                 "pkg-up": "^2.0.0",
                 "read-pkg-up": "^3.0.0",
                 "resolve": "^1.20.0",
-                "tsconfig-paths": "^3.10.1"
+                "tsconfig-paths": "^3.11.0"
             },
             "dependencies": {
                 "find-up": {
@@ -17172,14 +17183,15 @@
             }
         },
         "eslint-plugin-react": {
-            "version": "7.24.0",
-            "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.24.0.tgz",
-            "integrity": "sha512-KJJIx2SYx7PBx3ONe/mEeMz4YE0Lcr7feJTCMyyKb/341NcjuAgim3Acgan89GfPv7nxXK2+0slu0CWXYM4x+Q==",
+            "version": "7.25.2",
+            "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.25.2.tgz",
+            "integrity": "sha512-elx4585wgmryanJK4C5IoSKQyVZ+e7H0t2JOOtJNBql0cuercvSShvRReuLBbfx8687yW5yv+UL7pXwMsd6adQ==",
             "dev": true,
             "requires": {
                 "array-includes": "^3.1.3",
                 "array.prototype.flatmap": "^1.2.4",
                 "doctrine": "^2.1.0",
+                "estraverse": "^5.2.0",
                 "has": "^1.0.3",
                 "jsx-ast-utils": "^2.4.1 || ^3.0.0",
                 "minimatch": "^3.0.4",
@@ -17191,6 +17203,12 @@
                 "string.prototype.matchall": "^4.0.5"
             },
             "dependencies": {
+                "estraverse": {
+                    "version": "5.2.0",
+                    "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz",
+                    "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==",
+                    "dev": true
+                },
                 "resolve": {
                     "version": "2.0.0-next.3",
                     "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.3.tgz",
@@ -22090,9 +22108,9 @@
             "dev": true
         },
         "webpack": {
-            "version": "5.51.1",
-            "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.51.1.tgz",
-            "integrity": "sha512-xsn3lwqEKoFvqn4JQggPSRxE4dhsRcysWTqYABAZlmavcoTmwlOb9b1N36Inbt/eIispSkuHa80/FJkDTPos1A==",
+            "version": "5.53.0",
+            "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.53.0.tgz",
+            "integrity": "sha512-RZ1Z3z3ni44snoWjfWeHFyzvd9HMVYDYC5VXmlYUT6NWgEOWdCNpad5Fve2CzzHoRED7WtsKe+FCyP5Vk4pWiQ==",
             "dev": true,
             "requires": {
                 "@types/eslint-scope": "^3.7.0",
@@ -22195,12 +22213,12 @@
             }
         },
         "webpack-dev-server": {
-            "version": "4.0.0",
-            "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.0.0.tgz",
-            "integrity": "sha512-ya5cjoBSf3LqrshZn2HMaRZQx8YRNBE+tx+CQNFGaLLHrvs4Y1aik0sl5SFhLz2cW1O9/NtyaZhthc+8UiuvkQ==",
+            "version": "4.2.1",
+            "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.2.1.tgz",
+            "integrity": "sha512-SQrIyQDZsTaF84p/WMAXNRKxjTeIaewhDIiHYZ423ENhNAsQWyubvqPTn0IoLMGkbhWyWv8/GYnCjItt0ZNC5w==",
             "dev": true,
             "requires": {
-                "ansi-html": "^0.0.7",
+                "ansi-html-community": "^0.0.8",
                 "bonjour": "^3.5.0",
                 "chokidar": "^3.5.1",
                 "colorette": "^1.2.2",
@@ -22223,7 +22241,7 @@
                 "spdy": "^4.0.2",
                 "strip-ansi": "^7.0.0",
                 "url": "^0.11.0",
-                "webpack-dev-middleware": "^5.0.0",
+                "webpack-dev-middleware": "^5.1.0",
                 "ws": "^8.1.0"
             },
             "dependencies": {
diff --git a/package.json b/package.json
index 5ffed80..62c6ea6 100644
--- a/package.json
+++ b/package.json
@@ -38,9 +38,9 @@
         "xml-reader": "2.4.3"
     },
     "devDependencies": {
-        "@babel/core": "7.15.0",
-        "@babel/eslint-parser": "7.15.0",
-        "@babel/preset-env": "7.15.0",
+        "@babel/core": "7.15.5",
+        "@babel/eslint-parser": "7.15.4",
+        "@babel/preset-env": "7.15.6",
         "@babel/register": "7.15.3",
         "@cucumber/cucumber": "7.3.1",
         "ava": "3.15.0",
@@ -52,22 +52,19 @@
         "eslint": "7.32.0",
         "eslint-config-walmart": "2.2.1",
         "eslint-plugin-filenames": "1.3.2",
-        "eslint-plugin-import": "2.24.1",
+        "eslint-plugin-import": "2.24.2",
         "eslint-plugin-jsx-a11y": "6.4.1",
-        "eslint-plugin-react": "7.24.0",
+        "eslint-plugin-react": "7.25.2",
         "nyc": "15.1.0",
         "tap-nyan": "1.1.0",
-        "webpack": "5.51.1",
+        "webpack": "5.53.0",
         "webpack-cli": "4.8.0",
-        "webpack-dev-server": "4.0.0"
+        "webpack-dev-server": "4.2.1"
     },
     "ava": {
         "files": [
             "test/**/*.test.js"
         ],
-        "sources": [
-            "src/**/*.es6"
-        ],
         "require": [
             "@babel/register"
         ],