File indexing completed on 2024-12-22 03:53:24

0001 (function webpackUniversalModuleDefinition(root, factory) {
0002         if(typeof exports === 'object' && typeof module === 'object')
0003                 module.exports = factory(require("JSZip"));
0004         else if(typeof define === 'function' && define.amd)
0005                 define(["JSZip"], factory);
0006         else if(typeof exports === 'object')
0007                 exports["ePub"] = factory(require("JSZip"));
0008         else
0009                 root["ePub"] = factory(root["JSZip"]);
0010 })(window, function(__WEBPACK_EXTERNAL_MODULE__29__) {
0011 return /******/ (function(modules) { // webpackBootstrap
0012 /******/        // The module cache
0013 /******/        var installedModules = {};
0014 /******/
0015 /******/        // The require function
0016 /******/        function __webpack_require__(moduleId) {
0017 /******/
0018 /******/                // Check if module is in cache
0019 /******/                if(installedModules[moduleId]) {
0020 /******/                        return installedModules[moduleId].exports;
0021 /******/                }
0022 /******/                // Create a new module (and put it into the cache)
0023 /******/                var module = installedModules[moduleId] = {
0024 /******/                        i: moduleId,
0025 /******/                        l: false,
0026 /******/                        exports: {}
0027 /******/                };
0028 /******/
0029 /******/                // Execute the module function
0030 /******/                modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
0031 /******/
0032 /******/                // Flag the module as loaded
0033 /******/                module.l = true;
0034 /******/
0035 /******/                // Return the exports of the module
0036 /******/                return module.exports;
0037 /******/        }
0038 /******/
0039 /******/
0040 /******/        // expose the modules object (__webpack_modules__)
0041 /******/        __webpack_require__.m = modules;
0042 /******/
0043 /******/        // expose the module cache
0044 /******/        __webpack_require__.c = installedModules;
0045 /******/
0046 /******/        // define getter function for harmony exports
0047 /******/        __webpack_require__.d = function(exports, name, getter) {
0048 /******/                if(!__webpack_require__.o(exports, name)) {
0049 /******/                        Object.defineProperty(exports, name, { enumerable: true, get: getter });
0050 /******/                }
0051 /******/        };
0052 /******/
0053 /******/        // define __esModule on exports
0054 /******/        __webpack_require__.r = function(exports) {
0055 /******/                if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
0056 /******/                        Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
0057 /******/                }
0058 /******/                Object.defineProperty(exports, '__esModule', { value: true });
0059 /******/        };
0060 /******/
0061 /******/        // create a fake namespace object
0062 /******/        // mode & 1: value is a module id, require it
0063 /******/        // mode & 2: merge all properties of value into the ns
0064 /******/        // mode & 4: return value when already ns object
0065 /******/        // mode & 8|1: behave like require
0066 /******/        __webpack_require__.t = function(value, mode) {
0067 /******/                if(mode & 1) value = __webpack_require__(value);
0068 /******/                if(mode & 8) return value;
0069 /******/                if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
0070 /******/                var ns = Object.create(null);
0071 /******/                __webpack_require__.r(ns);
0072 /******/                Object.defineProperty(ns, 'default', { enumerable: true, value: value });
0073 /******/                if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
0074 /******/                return ns;
0075 /******/        };
0076 /******/
0077 /******/        // getDefaultExport function for compatibility with non-harmony modules
0078 /******/        __webpack_require__.n = function(module) {
0079 /******/                var getter = module && module.__esModule ?
0080 /******/                        function getDefault() { return module['default']; } :
0081 /******/                        function getModuleExports() { return module; };
0082 /******/                __webpack_require__.d(getter, 'a', getter);
0083 /******/                return getter;
0084 /******/        };
0085 /******/
0086 /******/        // Object.prototype.hasOwnProperty.call
0087 /******/        __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
0088 /******/
0089 /******/        // __webpack_public_path__
0090 /******/        __webpack_require__.p = "/dist/";
0091 /******/
0092 /******/
0093 /******/        // Load entry module and return exports
0094 /******/        return __webpack_require__(__webpack_require__.s = 30);
0095 /******/ })
0096 /************************************************************************/
0097 /******/ ([
0098 /* 0 */
0099 /***/ (function(module, __webpack_exports__, __webpack_require__) {
0100 
0101 "use strict";
0102 __webpack_require__.r(__webpack_exports__);
0103 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "requestAnimationFrame", function() { return requestAnimationFrame; });
0104 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "uuid", function() { return uuid; });
0105 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "documentHeight", function() { return documentHeight; });
0106 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "isElement", function() { return isElement; });
0107 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "isNumber", function() { return isNumber; });
0108 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "isFloat", function() { return isFloat; });
0109 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "prefixed", function() { return prefixed; });
0110 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "defaults", function() { return defaults; });
0111 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "extend", function() { return extend; });
0112 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "insert", function() { return insert; });
0113 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "locationOf", function() { return locationOf; });
0114 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "indexOfSorted", function() { return indexOfSorted; });
0115 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "bounds", function() { return bounds; });
0116 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "borders", function() { return borders; });
0117 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "nodeBounds", function() { return nodeBounds; });
0118 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "windowBounds", function() { return windowBounds; });
0119 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "indexOfNode", function() { return indexOfNode; });
0120 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "indexOfTextNode", function() { return indexOfTextNode; });
0121 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "indexOfElementNode", function() { return indexOfElementNode; });
0122 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "isXml", function() { return isXml; });
0123 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "createBlob", function() { return createBlob; });
0124 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "createBlobUrl", function() { return createBlobUrl; });
0125 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "revokeBlobUrl", function() { return revokeBlobUrl; });
0126 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "createBase64Url", function() { return createBase64Url; });
0127 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "type", function() { return type; });
0128 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "parse", function() { return parse; });
0129 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "qs", function() { return qs; });
0130 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "qsa", function() { return qsa; });
0131 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "qsp", function() { return qsp; });
0132 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "sprint", function() { return sprint; });
0133 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "treeWalker", function() { return treeWalker; });
0134 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "walk", function() { return walk; });
0135 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "blob2base64", function() { return blob2base64; });
0136 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "defer", function() { return defer; });
0137 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "querySelectorByType", function() { return querySelectorByType; });
0138 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "findChildren", function() { return findChildren; });
0139 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "parents", function() { return parents; });
0140 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "filterChildren", function() { return filterChildren; });
0141 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getParentByTagName", function() { return getParentByTagName; });
0142 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "RangeObject", function() { return RangeObject; });
0143 /* harmony import */ var _xmldom_xmldom__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(15);
0144 /* harmony import */ var _xmldom_xmldom__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_xmldom_xmldom__WEBPACK_IMPORTED_MODULE_0__);
0145 /**
0146  * Core Utilities and Helpers
0147  * @module Core
0148 */
0149 
0150 /**
0151  * Vendor prefixed requestAnimationFrame
0152  * @returns {function} requestAnimationFrame
0153  * @memberof Core
0154  */
0155 
0156 const requestAnimationFrame = typeof window != "undefined" ? window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame : false;
0157 const ELEMENT_NODE = 1;
0158 const TEXT_NODE = 3;
0159 const COMMENT_NODE = 8;
0160 const DOCUMENT_NODE = 9;
0161 
0162 const _URL = typeof URL != "undefined" ? URL : typeof window != "undefined" ? window.URL || window.webkitURL || window.mozURL : undefined;
0163 /**
0164  * Generates a UUID
0165  * based on: http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript
0166  * @returns {string} uuid
0167  * @memberof Core
0168  */
0169 
0170 
0171 function uuid() {
0172   var d = new Date().getTime();
0173   var uuid = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function (c) {
0174     var r = (d + Math.random() * 16) % 16 | 0;
0175     d = Math.floor(d / 16);
0176     return (c == "x" ? r : r & 0x7 | 0x8).toString(16);
0177   });
0178   return uuid;
0179 }
0180 /**
0181  * Gets the height of a document
0182  * @returns {number} height
0183  * @memberof Core
0184  */
0185 
0186 function documentHeight() {
0187   return Math.max(document.documentElement.clientHeight, document.body.scrollHeight, document.documentElement.scrollHeight, document.body.offsetHeight, document.documentElement.offsetHeight);
0188 }
0189 /**
0190  * Checks if a node is an element
0191  * @param {object} obj
0192  * @returns {boolean}
0193  * @memberof Core
0194  */
0195 
0196 function isElement(obj) {
0197   return !!(obj && obj.nodeType == 1);
0198 }
0199 /**
0200  * @param {any} n
0201  * @returns {boolean}
0202  * @memberof Core
0203  */
0204 
0205 function isNumber(n) {
0206   return !isNaN(parseFloat(n)) && isFinite(n);
0207 }
0208 /**
0209  * @param {any} n
0210  * @returns {boolean}
0211  * @memberof Core
0212  */
0213 
0214 function isFloat(n) {
0215   let f = parseFloat(n);
0216 
0217   if (isNumber(n) === false) {
0218     return false;
0219   }
0220 
0221   if (typeof n === "string" && n.indexOf(".") > -1) {
0222     return true;
0223   }
0224 
0225   return Math.floor(f) !== f;
0226 }
0227 /**
0228  * Get a prefixed css property
0229  * @param {string} unprefixed
0230  * @returns {string}
0231  * @memberof Core
0232  */
0233 
0234 function prefixed(unprefixed) {
0235   var vendors = ["Webkit", "webkit", "Moz", "O", "ms"];
0236   var prefixes = ["-webkit-", "-webkit-", "-moz-", "-o-", "-ms-"];
0237   var lower = unprefixed.toLowerCase();
0238   var length = vendors.length;
0239 
0240   if (typeof document === "undefined" || typeof document.body.style[lower] != "undefined") {
0241     return unprefixed;
0242   }
0243 
0244   for (var i = 0; i < length; i++) {
0245     if (typeof document.body.style[prefixes[i] + lower] != "undefined") {
0246       return prefixes[i] + lower;
0247     }
0248   }
0249 
0250   return unprefixed;
0251 }
0252 /**
0253  * Apply defaults to an object
0254  * @param {object} obj
0255  * @returns {object}
0256  * @memberof Core
0257  */
0258 
0259 function defaults(obj) {
0260   for (var i = 1, length = arguments.length; i < length; i++) {
0261     var source = arguments[i];
0262 
0263     for (var prop in source) {
0264       if (obj[prop] === void 0) obj[prop] = source[prop];
0265     }
0266   }
0267 
0268   return obj;
0269 }
0270 /**
0271  * Extend properties of an object
0272  * @param {object} target
0273  * @returns {object}
0274  * @memberof Core
0275  */
0276 
0277 function extend(target) {
0278   var sources = [].slice.call(arguments, 1);
0279   sources.forEach(function (source) {
0280     if (!source) return;
0281     Object.getOwnPropertyNames(source).forEach(function (propName) {
0282       Object.defineProperty(target, propName, Object.getOwnPropertyDescriptor(source, propName));
0283     });
0284   });
0285   return target;
0286 }
0287 /**
0288  * Fast quicksort insert for sorted array -- based on:
0289  *  http://stackoverflow.com/questions/1344500/efficient-way-to-insert-a-number-into-a-sorted-array-of-numbers
0290  * @param {any} item
0291  * @param {array} array
0292  * @param {function} [compareFunction]
0293  * @returns {number} location (in array)
0294  * @memberof Core
0295  */
0296 
0297 function insert(item, array, compareFunction) {
0298   var location = locationOf(item, array, compareFunction);
0299   array.splice(location, 0, item);
0300   return location;
0301 }
0302 /**
0303  * Finds where something would fit into a sorted array
0304  * @param {any} item
0305  * @param {array} array
0306  * @param {function} [compareFunction]
0307  * @param {function} [_start]
0308  * @param {function} [_end]
0309  * @returns {number} location (in array)
0310  * @memberof Core
0311  */
0312 
0313 function locationOf(item, array, compareFunction, _start, _end) {
0314   var start = _start || 0;
0315   var end = _end || array.length;
0316   var pivot = parseInt(start + (end - start) / 2);
0317   var compared;
0318 
0319   if (!compareFunction) {
0320     compareFunction = function (a, b) {
0321       if (a > b) return 1;
0322       if (a < b) return -1;
0323       if (a == b) return 0;
0324     };
0325   }
0326 
0327   if (end - start <= 0) {
0328     return pivot;
0329   }
0330 
0331   compared = compareFunction(array[pivot], item);
0332 
0333   if (end - start === 1) {
0334     return compared >= 0 ? pivot : pivot + 1;
0335   }
0336 
0337   if (compared === 0) {
0338     return pivot;
0339   }
0340 
0341   if (compared === -1) {
0342     return locationOf(item, array, compareFunction, pivot, end);
0343   } else {
0344     return locationOf(item, array, compareFunction, start, pivot);
0345   }
0346 }
0347 /**
0348  * Finds index of something in a sorted array
0349  * Returns -1 if not found
0350  * @param {any} item
0351  * @param {array} array
0352  * @param {function} [compareFunction]
0353  * @param {function} [_start]
0354  * @param {function} [_end]
0355  * @returns {number} index (in array) or -1
0356  * @memberof Core
0357  */
0358 
0359 function indexOfSorted(item, array, compareFunction, _start, _end) {
0360   var start = _start || 0;
0361   var end = _end || array.length;
0362   var pivot = parseInt(start + (end - start) / 2);
0363   var compared;
0364 
0365   if (!compareFunction) {
0366     compareFunction = function (a, b) {
0367       if (a > b) return 1;
0368       if (a < b) return -1;
0369       if (a == b) return 0;
0370     };
0371   }
0372 
0373   if (end - start <= 0) {
0374     return -1; // Not found
0375   }
0376 
0377   compared = compareFunction(array[pivot], item);
0378 
0379   if (end - start === 1) {
0380     return compared === 0 ? pivot : -1;
0381   }
0382 
0383   if (compared === 0) {
0384     return pivot; // Found
0385   }
0386 
0387   if (compared === -1) {
0388     return indexOfSorted(item, array, compareFunction, pivot, end);
0389   } else {
0390     return indexOfSorted(item, array, compareFunction, start, pivot);
0391   }
0392 }
0393 /**
0394  * Find the bounds of an element
0395  * taking padding and margin into account
0396  * @param {element} el
0397  * @returns {{ width: Number, height: Number}}
0398  * @memberof Core
0399  */
0400 
0401 function bounds(el) {
0402   var style = window.getComputedStyle(el);
0403   var widthProps = ["width", "paddingRight", "paddingLeft", "marginRight", "marginLeft", "borderRightWidth", "borderLeftWidth"];
0404   var heightProps = ["height", "paddingTop", "paddingBottom", "marginTop", "marginBottom", "borderTopWidth", "borderBottomWidth"];
0405   var width = 0;
0406   var height = 0;
0407   widthProps.forEach(function (prop) {
0408     width += parseFloat(style[prop]) || 0;
0409   });
0410   heightProps.forEach(function (prop) {
0411     height += parseFloat(style[prop]) || 0;
0412   });
0413   return {
0414     height: height,
0415     width: width
0416   };
0417 }
0418 /**
0419  * Find the bounds of an element
0420  * taking padding, margin and borders into account
0421  * @param {element} el
0422  * @returns {{ width: Number, height: Number}}
0423  * @memberof Core
0424  */
0425 
0426 function borders(el) {
0427   var style = window.getComputedStyle(el);
0428   var widthProps = ["paddingRight", "paddingLeft", "marginRight", "marginLeft", "borderRightWidth", "borderLeftWidth"];
0429   var heightProps = ["paddingTop", "paddingBottom", "marginTop", "marginBottom", "borderTopWidth", "borderBottomWidth"];
0430   var width = 0;
0431   var height = 0;
0432   widthProps.forEach(function (prop) {
0433     width += parseFloat(style[prop]) || 0;
0434   });
0435   heightProps.forEach(function (prop) {
0436     height += parseFloat(style[prop]) || 0;
0437   });
0438   return {
0439     height: height,
0440     width: width
0441   };
0442 }
0443 /**
0444  * Find the bounds of any node
0445  * allows for getting bounds of text nodes by wrapping them in a range
0446  * @param {node} node
0447  * @returns {BoundingClientRect}
0448  * @memberof Core
0449  */
0450 
0451 function nodeBounds(node) {
0452   let elPos;
0453   let doc = node.ownerDocument;
0454 
0455   if (node.nodeType == Node.TEXT_NODE) {
0456     let elRange = doc.createRange();
0457     elRange.selectNodeContents(node);
0458     elPos = elRange.getBoundingClientRect();
0459   } else {
0460     elPos = node.getBoundingClientRect();
0461   }
0462 
0463   return elPos;
0464 }
0465 /**
0466  * Find the equivalent of getBoundingClientRect of a browser window
0467  * @returns {{ width: Number, height: Number, top: Number, left: Number, right: Number, bottom: Number }}
0468  * @memberof Core
0469  */
0470 
0471 function windowBounds() {
0472   var width = window.innerWidth;
0473   var height = window.innerHeight;
0474   return {
0475     top: 0,
0476     left: 0,
0477     right: width,
0478     bottom: height,
0479     width: width,
0480     height: height
0481   };
0482 }
0483 /**
0484  * Gets the index of a node in its parent
0485  * @param {Node} node
0486  * @param {string} typeId
0487  * @return {number} index
0488  * @memberof Core
0489  */
0490 
0491 function indexOfNode(node, typeId) {
0492   var parent = node.parentNode;
0493   var children = parent.childNodes;
0494   var sib;
0495   var index = -1;
0496 
0497   for (var i = 0; i < children.length; i++) {
0498     sib = children[i];
0499 
0500     if (sib.nodeType === typeId) {
0501       index++;
0502     }
0503 
0504     if (sib == node) break;
0505   }
0506 
0507   return index;
0508 }
0509 /**
0510  * Gets the index of a text node in its parent
0511  * @param {node} textNode
0512  * @returns {number} index
0513  * @memberof Core
0514  */
0515 
0516 function indexOfTextNode(textNode) {
0517   return indexOfNode(textNode, TEXT_NODE);
0518 }
0519 /**
0520  * Gets the index of an element node in its parent
0521  * @param {element} elementNode
0522  * @returns {number} index
0523  * @memberof Core
0524  */
0525 
0526 function indexOfElementNode(elementNode) {
0527   return indexOfNode(elementNode, ELEMENT_NODE);
0528 }
0529 /**
0530  * Check if extension is xml
0531  * @param {string} ext
0532  * @returns {boolean}
0533  * @memberof Core
0534  */
0535 
0536 function isXml(ext) {
0537   return ["xml", "opf", "ncx"].indexOf(ext) > -1;
0538 }
0539 /**
0540  * Create a new blob
0541  * @param {any} content
0542  * @param {string} mime
0543  * @returns {Blob}
0544  * @memberof Core
0545  */
0546 
0547 function createBlob(content, mime) {
0548   return new Blob([content], {
0549     type: mime
0550   });
0551 }
0552 /**
0553  * Create a new blob url
0554  * @param {any} content
0555  * @param {string} mime
0556  * @returns {string} url
0557  * @memberof Core
0558  */
0559 
0560 function createBlobUrl(content, mime) {
0561   var tempUrl;
0562   var blob = createBlob(content, mime);
0563   tempUrl = _URL.createObjectURL(blob);
0564   return tempUrl;
0565 }
0566 /**
0567  * Remove a blob url
0568  * @param {string} url
0569  * @memberof Core
0570  */
0571 
0572 function revokeBlobUrl(url) {
0573   return _URL.revokeObjectURL(url);
0574 }
0575 /**
0576  * Create a new base64 encoded url
0577  * @param {any} content
0578  * @param {string} mime
0579  * @returns {string} url
0580  * @memberof Core
0581  */
0582 
0583 function createBase64Url(content, mime) {
0584   var data;
0585   var datauri;
0586 
0587   if (typeof content !== "string") {
0588     // Only handles strings
0589     return;
0590   }
0591 
0592   data = btoa(content);
0593   datauri = "data:" + mime + ";base64," + data;
0594   return datauri;
0595 }
0596 /**
0597  * Get type of an object
0598  * @param {object} obj
0599  * @returns {string} type
0600  * @memberof Core
0601  */
0602 
0603 function type(obj) {
0604   return Object.prototype.toString.call(obj).slice(8, -1);
0605 }
0606 /**
0607  * Parse xml (or html) markup
0608  * @param {string} markup
0609  * @param {string} mime
0610  * @param {boolean} forceXMLDom force using xmlDom to parse instead of native parser
0611  * @returns {document} document
0612  * @memberof Core
0613  */
0614 
0615 function parse(markup, mime, forceXMLDom) {
0616   var doc;
0617   var Parser;
0618 
0619   if (typeof DOMParser === "undefined" || forceXMLDom) {
0620     Parser = _xmldom_xmldom__WEBPACK_IMPORTED_MODULE_0__["DOMParser"];
0621   } else {
0622     Parser = DOMParser;
0623   } // Remove byte order mark before parsing
0624   // https://www.w3.org/International/questions/qa-byte-order-mark
0625 
0626 
0627   if (markup.charCodeAt(0) === 0xFEFF) {
0628     markup = markup.slice(1);
0629   }
0630 
0631   doc = new Parser().parseFromString(markup, mime);
0632   return doc;
0633 }
0634 /**
0635  * querySelector polyfill
0636  * @param {element} el
0637  * @param {string} sel selector string
0638  * @returns {element} element
0639  * @memberof Core
0640  */
0641 
0642 function qs(el, sel) {
0643   var elements;
0644 
0645   if (!el) {
0646     throw new Error("No Element Provided");
0647   }
0648 
0649   if (typeof el.querySelector != "undefined") {
0650     return el.querySelector(sel);
0651   } else {
0652     elements = el.getElementsByTagName(sel);
0653 
0654     if (elements.length) {
0655       return elements[0];
0656     }
0657   }
0658 }
0659 /**
0660  * querySelectorAll polyfill
0661  * @param {element} el
0662  * @param {string} sel selector string
0663  * @returns {element[]} elements
0664  * @memberof Core
0665  */
0666 
0667 function qsa(el, sel) {
0668   if (typeof el.querySelector != "undefined") {
0669     return el.querySelectorAll(sel);
0670   } else {
0671     return el.getElementsByTagName(sel);
0672   }
0673 }
0674 /**
0675  * querySelector by property
0676  * @param {element} el
0677  * @param {string} sel selector string
0678  * @param {object[]} props
0679  * @returns {element[]} elements
0680  * @memberof Core
0681  */
0682 
0683 function qsp(el, sel, props) {
0684   var q, filtered;
0685 
0686   if (typeof el.querySelector != "undefined") {
0687     sel += "[";
0688 
0689     for (var prop in props) {
0690       sel += prop + "~='" + props[prop] + "'";
0691     }
0692 
0693     sel += "]";
0694     return el.querySelector(sel);
0695   } else {
0696     q = el.getElementsByTagName(sel);
0697     filtered = Array.prototype.slice.call(q, 0).filter(function (el) {
0698       for (var prop in props) {
0699         if (el.getAttribute(prop) === props[prop]) {
0700           return true;
0701         }
0702       }
0703 
0704       return false;
0705     });
0706 
0707     if (filtered) {
0708       return filtered[0];
0709     }
0710   }
0711 }
0712 /**
0713  * Sprint through all text nodes in a document
0714  * @memberof Core
0715  * @param  {element} root element to start with
0716  * @param  {function} func function to run on each element
0717  */
0718 
0719 function sprint(root, func) {
0720   var doc = root.ownerDocument || root;
0721 
0722   if (typeof doc.createTreeWalker !== "undefined") {
0723     treeWalker(root, func, NodeFilter.SHOW_TEXT);
0724   } else {
0725     walk(root, function (node) {
0726       if (node && node.nodeType === 3) {
0727         // Node.TEXT_NODE
0728         func(node);
0729       }
0730     }, true);
0731   }
0732 }
0733 /**
0734  * Create a treeWalker
0735  * @memberof Core
0736  * @param  {element} root element to start with
0737  * @param  {function} func function to run on each element
0738  * @param  {function | object} filter function or object to filter with
0739  */
0740 
0741 function treeWalker(root, func, filter) {
0742   var treeWalker = document.createTreeWalker(root, filter, null, false);
0743   let node;
0744 
0745   while (node = treeWalker.nextNode()) {
0746     func(node);
0747   }
0748 }
0749 /**
0750  * @memberof Core
0751  * @param {node} node
0752  * @param {callback} return false for continue,true for break inside callback
0753  */
0754 
0755 function walk(node, callback) {
0756   if (callback(node)) {
0757     return true;
0758   }
0759 
0760   node = node.firstChild;
0761 
0762   if (node) {
0763     do {
0764       let walked = walk(node, callback);
0765 
0766       if (walked) {
0767         return true;
0768       }
0769 
0770       node = node.nextSibling;
0771     } while (node);
0772   }
0773 }
0774 /**
0775  * Convert a blob to a base64 encoded string
0776  * @param {Blog} blob
0777  * @returns {string}
0778  * @memberof Core
0779  */
0780 
0781 function blob2base64(blob) {
0782   return new Promise(function (resolve, reject) {
0783     var reader = new FileReader();
0784     reader.readAsDataURL(blob);
0785 
0786     reader.onloadend = function () {
0787       resolve(reader.result);
0788     };
0789   });
0790 }
0791 /**
0792  * Creates a new pending promise and provides methods to resolve or reject it.
0793  * From: https://developer.mozilla.org/en-US/docs/Mozilla/JavaScript_code_modules/Promise.jsm/Deferred#backwards_forwards_compatible
0794  * @memberof Core
0795  */
0796 
0797 function defer() {
0798   /* A method to resolve the associated Promise with the value passed.
0799    * If the promise is already settled it does nothing.
0800    *
0801    * @param {anything} value : This value is used to resolve the promise
0802    * If the value is a Promise then the associated promise assumes the state
0803    * of Promise passed as value.
0804    */
0805   this.resolve = null;
0806   /* A method to reject the associated Promise with the value passed.
0807    * If the promise is already settled it does nothing.
0808    *
0809    * @param {anything} reason: The reason for the rejection of the Promise.
0810    * Generally its an Error object. If however a Promise is passed, then the Promise
0811    * itself will be the reason for rejection no matter the state of the Promise.
0812    */
0813 
0814   this.reject = null;
0815   this.id = uuid();
0816   /* A newly created Pomise object.
0817    * Initially in pending state.
0818    */
0819 
0820   this.promise = new Promise((resolve, reject) => {
0821     this.resolve = resolve;
0822     this.reject = reject;
0823   });
0824   Object.freeze(this);
0825 }
0826 /**
0827  * querySelector with filter by epub type
0828  * @param {element} html
0829  * @param {string} element element type to find
0830  * @param {string} type epub type to find
0831  * @returns {element[]} elements
0832  * @memberof Core
0833  */
0834 
0835 function querySelectorByType(html, element, type) {
0836   var query;
0837 
0838   if (typeof html.querySelector != "undefined") {
0839     query = html.querySelector(`${element}[*|type="${type}"]`);
0840   } // Handle IE not supporting namespaced epub:type in querySelector
0841 
0842 
0843   if (!query || query.length === 0) {
0844     query = qsa(html, element);
0845 
0846     for (var i = 0; i < query.length; i++) {
0847       if (query[i].getAttributeNS("http://www.idpf.org/2007/ops", "type") === type || query[i].getAttribute("epub:type") === type) {
0848         return query[i];
0849       }
0850     }
0851   } else {
0852     return query;
0853   }
0854 }
0855 /**
0856  * Find direct descendents of an element
0857  * @param {element} el
0858  * @returns {element[]} children
0859  * @memberof Core
0860  */
0861 
0862 function findChildren(el) {
0863   var result = [];
0864   var childNodes = el.childNodes;
0865 
0866   for (var i = 0; i < childNodes.length; i++) {
0867     let node = childNodes[i];
0868 
0869     if (node.nodeType === 1) {
0870       result.push(node);
0871     }
0872   }
0873 
0874   return result;
0875 }
0876 /**
0877  * Find all parents (ancestors) of an element
0878  * @param {element} node
0879  * @returns {element[]} parents
0880  * @memberof Core
0881  */
0882 
0883 function parents(node) {
0884   var nodes = [node];
0885 
0886   for (; node; node = node.parentNode) {
0887     nodes.unshift(node);
0888   }
0889 
0890   return nodes;
0891 }
0892 /**
0893  * Find all direct descendents of a specific type
0894  * @param {element} el
0895  * @param {string} nodeName
0896  * @param {boolean} [single]
0897  * @returns {element[]} children
0898  * @memberof Core
0899  */
0900 
0901 function filterChildren(el, nodeName, single) {
0902   var result = [];
0903   var childNodes = el.childNodes;
0904 
0905   for (var i = 0; i < childNodes.length; i++) {
0906     let node = childNodes[i];
0907 
0908     if (node.nodeType === 1 && node.nodeName.toLowerCase() === nodeName) {
0909       if (single) {
0910         return node;
0911       } else {
0912         result.push(node);
0913       }
0914     }
0915   }
0916 
0917   if (!single) {
0918     return result;
0919   }
0920 }
0921 /**
0922  * Filter all parents (ancestors) with tag name
0923  * @param {element} node
0924  * @param {string} tagname
0925  * @returns {element[]} parents
0926  * @memberof Core
0927  */
0928 
0929 function getParentByTagName(node, tagname) {
0930   let parent;
0931   if (node === null || tagname === '') return;
0932   parent = node.parentNode;
0933 
0934   while (parent.nodeType === 1) {
0935     if (parent.tagName.toLowerCase() === tagname) {
0936       return parent;
0937     }
0938 
0939     parent = parent.parentNode;
0940   }
0941 }
0942 /**
0943  * Lightweight Polyfill for DOM Range
0944  * @class
0945  * @memberof Core
0946  */
0947 
0948 class RangeObject {
0949   constructor() {
0950     this.collapsed = false;
0951     this.commonAncestorContainer = undefined;
0952     this.endContainer = undefined;
0953     this.endOffset = undefined;
0954     this.startContainer = undefined;
0955     this.startOffset = undefined;
0956   }
0957 
0958   setStart(startNode, startOffset) {
0959     this.startContainer = startNode;
0960     this.startOffset = startOffset;
0961 
0962     if (!this.endContainer) {
0963       this.collapse(true);
0964     } else {
0965       this.commonAncestorContainer = this._commonAncestorContainer();
0966     }
0967 
0968     this._checkCollapsed();
0969   }
0970 
0971   setEnd(endNode, endOffset) {
0972     this.endContainer = endNode;
0973     this.endOffset = endOffset;
0974 
0975     if (!this.startContainer) {
0976       this.collapse(false);
0977     } else {
0978       this.collapsed = false;
0979       this.commonAncestorContainer = this._commonAncestorContainer();
0980     }
0981 
0982     this._checkCollapsed();
0983   }
0984 
0985   collapse(toStart) {
0986     this.collapsed = true;
0987 
0988     if (toStart) {
0989       this.endContainer = this.startContainer;
0990       this.endOffset = this.startOffset;
0991       this.commonAncestorContainer = this.startContainer.parentNode;
0992     } else {
0993       this.startContainer = this.endContainer;
0994       this.startOffset = this.endOffset;
0995       this.commonAncestorContainer = this.endOffset.parentNode;
0996     }
0997   }
0998 
0999   selectNode(referenceNode) {
1000     let parent = referenceNode.parentNode;
1001     let index = Array.prototype.indexOf.call(parent.childNodes, referenceNode);
1002     this.setStart(parent, index);
1003     this.setEnd(parent, index + 1);
1004   }
1005 
1006   selectNodeContents(referenceNode) {
1007     let end = referenceNode.childNodes[referenceNode.childNodes - 1];
1008     let endIndex = referenceNode.nodeType === 3 ? referenceNode.textContent.length : parent.childNodes.length;
1009     this.setStart(referenceNode, 0);
1010     this.setEnd(referenceNode, endIndex);
1011   }
1012 
1013   _commonAncestorContainer(startContainer, endContainer) {
1014     var startParents = parents(startContainer || this.startContainer);
1015     var endParents = parents(endContainer || this.endContainer);
1016     if (startParents[0] != endParents[0]) return undefined;
1017 
1018     for (var i = 0; i < startParents.length; i++) {
1019       if (startParents[i] != endParents[i]) {
1020         return startParents[i - 1];
1021       }
1022     }
1023   }
1024 
1025   _checkCollapsed() {
1026     if (this.startContainer === this.endContainer && this.startOffset === this.endOffset) {
1027       this.collapsed = true;
1028     } else {
1029       this.collapsed = false;
1030     }
1031   }
1032 
1033   toString() {// TODO: implement walking between start and end to find text
1034   }
1035 
1036 }
1037 
1038 /***/ }),
1039 /* 1 */
1040 /***/ (function(module, __webpack_exports__, __webpack_require__) {
1041 
1042 "use strict";
1043 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "b", function() { return EPUBJS_VERSION; });
1044 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return DOM_EVENTS; });
1045 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "c", function() { return EVENTS; });
1046 const EPUBJS_VERSION = "0.3"; // Dom events to listen for
1047 
1048 const DOM_EVENTS = ["keydown", "keyup", "keypressed", "mouseup", "mousedown", "mousemove", "click", "touchend", "touchstart", "touchmove"];
1049 const EVENTS = {
1050   BOOK: {
1051     OPEN_FAILED: "openFailed"
1052   },
1053   CONTENTS: {
1054     EXPAND: "expand",
1055     RESIZE: "resize",
1056     SELECTED: "selected",
1057     SELECTED_RANGE: "selectedRange",
1058     LINK_CLICKED: "linkClicked"
1059   },
1060   LOCATIONS: {
1061     CHANGED: "changed"
1062   },
1063   MANAGERS: {
1064     RESIZE: "resize",
1065     RESIZED: "resized",
1066     ORIENTATION_CHANGE: "orientationchange",
1067     ADDED: "added",
1068     SCROLL: "scroll",
1069     SCROLLED: "scrolled",
1070     REMOVED: "removed"
1071   },
1072   VIEWS: {
1073     AXIS: "axis",
1074     WRITING_MODE: "writingMode",
1075     LOAD_ERROR: "loaderror",
1076     RENDERED: "rendered",
1077     RESIZED: "resized",
1078     DISPLAYED: "displayed",
1079     SHOWN: "shown",
1080     HIDDEN: "hidden",
1081     MARK_CLICKED: "markClicked"
1082   },
1083   RENDITION: {
1084     STARTED: "started",
1085     ATTACHED: "attached",
1086     DISPLAYED: "displayed",
1087     DISPLAY_ERROR: "displayerror",
1088     RENDERED: "rendered",
1089     REMOVED: "removed",
1090     RESIZED: "resized",
1091     ORIENTATION_CHANGE: "orientationchange",
1092     LOCATION_CHANGED: "locationChanged",
1093     RELOCATED: "relocated",
1094     MARK_CLICKED: "markClicked",
1095     SELECTED: "selected",
1096     LAYOUT: "layout"
1097   },
1098   LAYOUT: {
1099     UPDATED: "updated"
1100   },
1101   ANNOTATION: {
1102     ATTACH: "attach",
1103     DETACH: "detach"
1104   }
1105 };
1106 
1107 /***/ }),
1108 /* 2 */
1109 /***/ (function(module, __webpack_exports__, __webpack_require__) {
1110 
1111 "use strict";
1112 /* harmony import */ var _utils_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(0);
1113 
1114 const ELEMENT_NODE = 1;
1115 const TEXT_NODE = 3;
1116 const COMMENT_NODE = 8;
1117 const DOCUMENT_NODE = 9;
1118 /**
1119         * Parsing and creation of EpubCFIs: http://www.idpf.org/epub/linking/cfi/epub-cfi.html
1120 
1121         * Implements:
1122         * - Character Offset: epubcfi(/6/4[chap01ref]!/4[body01]/10[para05]/2/1:3)
1123         * - Simple Ranges : epubcfi(/6/4[chap01ref]!/4[body01]/10[para05],/2/1:1,/3:4)
1124 
1125         * Does Not Implement:
1126         * - Temporal Offset (~)
1127         * - Spatial Offset (@)
1128         * - Temporal-Spatial Offset (~ + @)
1129         * - Text Location Assertion ([)
1130         * @class
1131         @param {string | Range | Node } [cfiFrom]
1132         @param {string | object} [base]
1133         @param {string} [ignoreClass] class to ignore when parsing DOM
1134 */
1135 
1136 class EpubCFI {
1137   constructor(cfiFrom, base, ignoreClass) {
1138     var type;
1139     this.str = "";
1140     this.base = {};
1141     this.spinePos = 0; // For compatibility
1142 
1143     this.range = false; // true || false;
1144 
1145     this.path = {};
1146     this.start = null;
1147     this.end = null; // Allow instantiation without the "new" keyword
1148 
1149     if (!(this instanceof EpubCFI)) {
1150       return new EpubCFI(cfiFrom, base, ignoreClass);
1151     }
1152 
1153     if (typeof base === "string") {
1154       this.base = this.parseComponent(base);
1155     } else if (typeof base === "object" && base.steps) {
1156       this.base = base;
1157     }
1158 
1159     type = this.checkType(cfiFrom);
1160 
1161     if (type === "string") {
1162       this.str = cfiFrom;
1163       return Object(_utils_core__WEBPACK_IMPORTED_MODULE_0__["extend"])(this, this.parse(cfiFrom));
1164     } else if (type === "range") {
1165       return Object(_utils_core__WEBPACK_IMPORTED_MODULE_0__["extend"])(this, this.fromRange(cfiFrom, this.base, ignoreClass));
1166     } else if (type === "node") {
1167       return Object(_utils_core__WEBPACK_IMPORTED_MODULE_0__["extend"])(this, this.fromNode(cfiFrom, this.base, ignoreClass));
1168     } else if (type === "EpubCFI" && cfiFrom.path) {
1169       return cfiFrom;
1170     } else if (!cfiFrom) {
1171       return this;
1172     } else {
1173       throw new TypeError("not a valid argument for EpubCFI");
1174     }
1175   }
1176   /**
1177    * Check the type of constructor input
1178    * @private
1179    */
1180 
1181 
1182   checkType(cfi) {
1183     if (this.isCfiString(cfi)) {
1184       return "string"; // Is a range object
1185     } else if (cfi && typeof cfi === "object" && (Object(_utils_core__WEBPACK_IMPORTED_MODULE_0__["type"])(cfi) === "Range" || typeof cfi.startContainer != "undefined")) {
1186       return "range";
1187     } else if (cfi && typeof cfi === "object" && typeof cfi.nodeType != "undefined") {
1188       // || typeof cfi === "function"
1189       return "node";
1190     } else if (cfi && typeof cfi === "object" && cfi instanceof EpubCFI) {
1191       return "EpubCFI";
1192     } else {
1193       return false;
1194     }
1195   }
1196   /**
1197    * Parse a cfi string to a CFI object representation
1198    * @param {string} cfiStr
1199    * @returns {object} cfi
1200    */
1201 
1202 
1203   parse(cfiStr) {
1204     var cfi = {
1205       spinePos: -1,
1206       range: false,
1207       base: {},
1208       path: {},
1209       start: null,
1210       end: null
1211     };
1212     var baseComponent, pathComponent, range;
1213 
1214     if (typeof cfiStr !== "string") {
1215       return {
1216         spinePos: -1
1217       };
1218     }
1219 
1220     if (cfiStr.indexOf("epubcfi(") === 0 && cfiStr[cfiStr.length - 1] === ")") {
1221       // Remove initial epubcfi( and ending )
1222       cfiStr = cfiStr.slice(8, cfiStr.length - 1);
1223     }
1224 
1225     baseComponent = this.getChapterComponent(cfiStr); // Make sure this is a valid cfi or return
1226 
1227     if (!baseComponent) {
1228       return {
1229         spinePos: -1
1230       };
1231     }
1232 
1233     cfi.base = this.parseComponent(baseComponent);
1234     pathComponent = this.getPathComponent(cfiStr);
1235     cfi.path = this.parseComponent(pathComponent);
1236     range = this.getRange(cfiStr);
1237 
1238     if (range) {
1239       cfi.range = true;
1240       cfi.start = this.parseComponent(range[0]);
1241       cfi.end = this.parseComponent(range[1]);
1242     } // Get spine node position
1243     // cfi.spineSegment = cfi.base.steps[1];
1244     // Chapter segment is always the second step
1245 
1246 
1247     cfi.spinePos = cfi.base.steps[1].index;
1248     return cfi;
1249   }
1250 
1251   parseComponent(componentStr) {
1252     var component = {
1253       steps: [],
1254       terminal: {
1255         offset: null,
1256         assertion: null
1257       }
1258     };
1259     var parts = componentStr.split(":");
1260     var steps = parts[0].split("/");
1261     var terminal;
1262 
1263     if (parts.length > 1) {
1264       terminal = parts[1];
1265       component.terminal = this.parseTerminal(terminal);
1266     }
1267 
1268     if (steps[0] === "") {
1269       steps.shift(); // Ignore the first slash
1270     }
1271 
1272     component.steps = steps.map(function (step) {
1273       return this.parseStep(step);
1274     }.bind(this));
1275     return component;
1276   }
1277 
1278   parseStep(stepStr) {
1279     var type, num, index, has_brackets, id;
1280     has_brackets = stepStr.match(/\[(.*)\]/);
1281 
1282     if (has_brackets && has_brackets[1]) {
1283       id = has_brackets[1];
1284     } //-- Check if step is a text node or element
1285 
1286 
1287     num = parseInt(stepStr);
1288 
1289     if (isNaN(num)) {
1290       return;
1291     }
1292 
1293     if (num % 2 === 0) {
1294       // Even = is an element
1295       type = "element";
1296       index = num / 2 - 1;
1297     } else {
1298       type = "text";
1299       index = (num - 1) / 2;
1300     }
1301 
1302     return {
1303       "type": type,
1304       "index": index,
1305       "id": id || null
1306     };
1307   }
1308 
1309   parseTerminal(termialStr) {
1310     var characterOffset, textLocationAssertion;
1311     var assertion = termialStr.match(/\[(.*)\]/);
1312 
1313     if (assertion && assertion[1]) {
1314       characterOffset = parseInt(termialStr.split("[")[0]);
1315       textLocationAssertion = assertion[1];
1316     } else {
1317       characterOffset = parseInt(termialStr);
1318     }
1319 
1320     if (!Object(_utils_core__WEBPACK_IMPORTED_MODULE_0__["isNumber"])(characterOffset)) {
1321       characterOffset = null;
1322     }
1323 
1324     return {
1325       "offset": characterOffset,
1326       "assertion": textLocationAssertion
1327     };
1328   }
1329 
1330   getChapterComponent(cfiStr) {
1331     var indirection = cfiStr.split("!");
1332     return indirection[0];
1333   }
1334 
1335   getPathComponent(cfiStr) {
1336     var indirection = cfiStr.split("!");
1337 
1338     if (indirection[1]) {
1339       let ranges = indirection[1].split(",");
1340       return ranges[0];
1341     }
1342   }
1343 
1344   getRange(cfiStr) {
1345     var ranges = cfiStr.split(",");
1346 
1347     if (ranges.length === 3) {
1348       return [ranges[1], ranges[2]];
1349     }
1350 
1351     return false;
1352   }
1353 
1354   getCharecterOffsetComponent(cfiStr) {
1355     var splitStr = cfiStr.split(":");
1356     return splitStr[1] || "";
1357   }
1358 
1359   joinSteps(steps) {
1360     if (!steps) {
1361       return "";
1362     }
1363 
1364     return steps.map(function (part) {
1365       var segment = "";
1366 
1367       if (part.type === "element") {
1368         segment += (part.index + 1) * 2;
1369       }
1370 
1371       if (part.type === "text") {
1372         segment += 1 + 2 * part.index; // TODO: double check that this is odd
1373       }
1374 
1375       if (part.id) {
1376         segment += "[" + part.id + "]";
1377       }
1378 
1379       return segment;
1380     }).join("/");
1381   }
1382 
1383   segmentString(segment) {
1384     var segmentString = "/";
1385     segmentString += this.joinSteps(segment.steps);
1386 
1387     if (segment.terminal && segment.terminal.offset != null) {
1388       segmentString += ":" + segment.terminal.offset;
1389     }
1390 
1391     if (segment.terminal && segment.terminal.assertion != null) {
1392       segmentString += "[" + segment.terminal.assertion + "]";
1393     }
1394 
1395     return segmentString;
1396   }
1397   /**
1398    * Convert CFI to a epubcfi(...) string
1399    * @returns {string} epubcfi
1400    */
1401 
1402 
1403   toString() {
1404     var cfiString = "epubcfi(";
1405     cfiString += this.segmentString(this.base);
1406     cfiString += "!";
1407     cfiString += this.segmentString(this.path); // Add Range, if present
1408 
1409     if (this.range && this.start) {
1410       cfiString += ",";
1411       cfiString += this.segmentString(this.start);
1412     }
1413 
1414     if (this.range && this.end) {
1415       cfiString += ",";
1416       cfiString += this.segmentString(this.end);
1417     }
1418 
1419     cfiString += ")";
1420     return cfiString;
1421   }
1422   /**
1423    * Compare which of two CFIs is earlier in the text
1424    * @returns {number} First is earlier = -1, Second is earlier = 1, They are equal = 0
1425    */
1426 
1427 
1428   compare(cfiOne, cfiTwo) {
1429     var stepsA, stepsB;
1430     var terminalA, terminalB;
1431     var rangeAStartSteps, rangeAEndSteps;
1432     var rangeBEndSteps, rangeBEndSteps;
1433     var rangeAStartTerminal, rangeAEndTerminal;
1434     var rangeBStartTerminal, rangeBEndTerminal;
1435 
1436     if (typeof cfiOne === "string") {
1437       cfiOne = new EpubCFI(cfiOne);
1438     }
1439 
1440     if (typeof cfiTwo === "string") {
1441       cfiTwo = new EpubCFI(cfiTwo);
1442     } // Compare Spine Positions
1443 
1444 
1445     if (cfiOne.spinePos > cfiTwo.spinePos) {
1446       return 1;
1447     }
1448 
1449     if (cfiOne.spinePos < cfiTwo.spinePos) {
1450       return -1;
1451     }
1452 
1453     if (cfiOne.range) {
1454       stepsA = cfiOne.path.steps.concat(cfiOne.start.steps);
1455       terminalA = cfiOne.start.terminal;
1456     } else {
1457       stepsA = cfiOne.path.steps;
1458       terminalA = cfiOne.path.terminal;
1459     }
1460 
1461     if (cfiTwo.range) {
1462       stepsB = cfiTwo.path.steps.concat(cfiTwo.start.steps);
1463       terminalB = cfiTwo.start.terminal;
1464     } else {
1465       stepsB = cfiTwo.path.steps;
1466       terminalB = cfiTwo.path.terminal;
1467     } // Compare Each Step in the First item
1468 
1469 
1470     for (var i = 0; i < stepsA.length; i++) {
1471       if (!stepsA[i]) {
1472         return -1;
1473       }
1474 
1475       if (!stepsB[i]) {
1476         return 1;
1477       }
1478 
1479       if (stepsA[i].index > stepsB[i].index) {
1480         return 1;
1481       }
1482 
1483       if (stepsA[i].index < stepsB[i].index) {
1484         return -1;
1485       } // Otherwise continue checking
1486 
1487     } // All steps in First equal to Second and First is Less Specific
1488 
1489 
1490     if (stepsA.length < stepsB.length) {
1491       return -1;
1492     } // Compare the character offset of the text node
1493 
1494 
1495     if (terminalA.offset > terminalB.offset) {
1496       return 1;
1497     }
1498 
1499     if (terminalA.offset < terminalB.offset) {
1500       return -1;
1501     } // CFI's are equal
1502 
1503 
1504     return 0;
1505   }
1506 
1507   step(node) {
1508     var nodeType = node.nodeType === TEXT_NODE ? "text" : "element";
1509     return {
1510       "id": node.id,
1511       "tagName": node.tagName,
1512       "type": nodeType,
1513       "index": this.position(node)
1514     };
1515   }
1516 
1517   filteredStep(node, ignoreClass) {
1518     var filteredNode = this.filter(node, ignoreClass);
1519     var nodeType; // Node filtered, so ignore
1520 
1521     if (!filteredNode) {
1522       return;
1523     } // Otherwise add the filter node in
1524 
1525 
1526     nodeType = filteredNode.nodeType === TEXT_NODE ? "text" : "element";
1527     return {
1528       "id": filteredNode.id,
1529       "tagName": filteredNode.tagName,
1530       "type": nodeType,
1531       "index": this.filteredPosition(filteredNode, ignoreClass)
1532     };
1533   }
1534 
1535   pathTo(node, offset, ignoreClass) {
1536     var segment = {
1537       steps: [],
1538       terminal: {
1539         offset: null,
1540         assertion: null
1541       }
1542     };
1543     var currentNode = node;
1544     var step;
1545 
1546     while (currentNode && currentNode.parentNode && currentNode.parentNode.nodeType != DOCUMENT_NODE) {
1547       if (ignoreClass) {
1548         step = this.filteredStep(currentNode, ignoreClass);
1549       } else {
1550         step = this.step(currentNode);
1551       }
1552 
1553       if (step) {
1554         segment.steps.unshift(step);
1555       }
1556 
1557       currentNode = currentNode.parentNode;
1558     }
1559 
1560     if (offset != null && offset >= 0) {
1561       segment.terminal.offset = offset; // Make sure we are getting to a textNode if there is an offset
1562 
1563       if (segment.steps[segment.steps.length - 1].type != "text") {
1564         segment.steps.push({
1565           "type": "text",
1566           "index": 0
1567         });
1568       }
1569     }
1570 
1571     return segment;
1572   }
1573 
1574   equalStep(stepA, stepB) {
1575     if (!stepA || !stepB) {
1576       return false;
1577     }
1578 
1579     if (stepA.index === stepB.index && stepA.id === stepB.id && stepA.type === stepB.type) {
1580       return true;
1581     }
1582 
1583     return false;
1584   }
1585   /**
1586    * Create a CFI object from a Range
1587    * @param {Range} range
1588    * @param {string | object} base
1589    * @param {string} [ignoreClass]
1590    * @returns {object} cfi
1591    */
1592 
1593 
1594   fromRange(range, base, ignoreClass) {
1595     var cfi = {
1596       range: false,
1597       base: {},
1598       path: {},
1599       start: null,
1600       end: null
1601     };
1602     var start = range.startContainer;
1603     var end = range.endContainer;
1604     var startOffset = range.startOffset;
1605     var endOffset = range.endOffset;
1606     var needsIgnoring = false;
1607 
1608     if (ignoreClass) {
1609       // Tell pathTo if / what to ignore
1610       needsIgnoring = start.ownerDocument.querySelector("." + ignoreClass) != null;
1611     }
1612 
1613     if (typeof base === "string") {
1614       cfi.base = this.parseComponent(base);
1615       cfi.spinePos = cfi.base.steps[1].index;
1616     } else if (typeof base === "object") {
1617       cfi.base = base;
1618     }
1619 
1620     if (range.collapsed) {
1621       if (needsIgnoring) {
1622         startOffset = this.patchOffset(start, startOffset, ignoreClass);
1623       }
1624 
1625       cfi.path = this.pathTo(start, startOffset, ignoreClass);
1626     } else {
1627       cfi.range = true;
1628 
1629       if (needsIgnoring) {
1630         startOffset = this.patchOffset(start, startOffset, ignoreClass);
1631       }
1632 
1633       cfi.start = this.pathTo(start, startOffset, ignoreClass);
1634 
1635       if (needsIgnoring) {
1636         endOffset = this.patchOffset(end, endOffset, ignoreClass);
1637       }
1638 
1639       cfi.end = this.pathTo(end, endOffset, ignoreClass); // Create a new empty path
1640 
1641       cfi.path = {
1642         steps: [],
1643         terminal: null
1644       }; // Push steps that are shared between start and end to the common path
1645 
1646       var len = cfi.start.steps.length;
1647       var i;
1648 
1649       for (i = 0; i < len; i++) {
1650         if (this.equalStep(cfi.start.steps[i], cfi.end.steps[i])) {
1651           if (i === len - 1) {
1652             // Last step is equal, check terminals
1653             if (cfi.start.terminal === cfi.end.terminal) {
1654               // CFI's are equal
1655               cfi.path.steps.push(cfi.start.steps[i]); // Not a range
1656 
1657               cfi.range = false;
1658             }
1659           } else {
1660             cfi.path.steps.push(cfi.start.steps[i]);
1661           }
1662         } else {
1663           break;
1664         }
1665       }
1666 
1667       cfi.start.steps = cfi.start.steps.slice(cfi.path.steps.length);
1668       cfi.end.steps = cfi.end.steps.slice(cfi.path.steps.length); // TODO: Add Sanity check to make sure that the end if greater than the start
1669     }
1670 
1671     return cfi;
1672   }
1673   /**
1674    * Create a CFI object from a Node
1675    * @param {Node} anchor
1676    * @param {string | object} base
1677    * @param {string} [ignoreClass]
1678    * @returns {object} cfi
1679    */
1680 
1681 
1682   fromNode(anchor, base, ignoreClass) {
1683     var cfi = {
1684       range: false,
1685       base: {},
1686       path: {},
1687       start: null,
1688       end: null
1689     };
1690 
1691     if (typeof base === "string") {
1692       cfi.base = this.parseComponent(base);
1693       cfi.spinePos = cfi.base.steps[1].index;
1694     } else if (typeof base === "object") {
1695       cfi.base = base;
1696     }
1697 
1698     cfi.path = this.pathTo(anchor, null, ignoreClass);
1699     return cfi;
1700   }
1701 
1702   filter(anchor, ignoreClass) {
1703     var needsIgnoring;
1704     var sibling; // to join with
1705 
1706     var parent, previousSibling, nextSibling;
1707     var isText = false;
1708 
1709     if (anchor.nodeType === TEXT_NODE) {
1710       isText = true;
1711       parent = anchor.parentNode;
1712       needsIgnoring = anchor.parentNode.classList.contains(ignoreClass);
1713     } else {
1714       isText = false;
1715       needsIgnoring = anchor.classList.contains(ignoreClass);
1716     }
1717 
1718     if (needsIgnoring && isText) {
1719       previousSibling = parent.previousSibling;
1720       nextSibling = parent.nextSibling; // If the sibling is a text node, join the nodes
1721 
1722       if (previousSibling && previousSibling.nodeType === TEXT_NODE) {
1723         sibling = previousSibling;
1724       } else if (nextSibling && nextSibling.nodeType === TEXT_NODE) {
1725         sibling = nextSibling;
1726       }
1727 
1728       if (sibling) {
1729         return sibling;
1730       } else {
1731         // Parent will be ignored on next step
1732         return anchor;
1733       }
1734     } else if (needsIgnoring && !isText) {
1735       // Otherwise just skip the element node
1736       return false;
1737     } else {
1738       // No need to filter
1739       return anchor;
1740     }
1741   }
1742 
1743   patchOffset(anchor, offset, ignoreClass) {
1744     if (anchor.nodeType != TEXT_NODE) {
1745       throw new Error("Anchor must be a text node");
1746     }
1747 
1748     var curr = anchor;
1749     var totalOffset = offset; // If the parent is a ignored node, get offset from it's start
1750 
1751     if (anchor.parentNode.classList.contains(ignoreClass)) {
1752       curr = anchor.parentNode;
1753     }
1754 
1755     while (curr.previousSibling) {
1756       if (curr.previousSibling.nodeType === ELEMENT_NODE) {
1757         // Originally a text node, so join
1758         if (curr.previousSibling.classList.contains(ignoreClass)) {
1759           totalOffset += curr.previousSibling.textContent.length;
1760         } else {
1761           break; // Normal node, dont join
1762         }
1763       } else {
1764         // If the previous sibling is a text node, join the nodes
1765         totalOffset += curr.previousSibling.textContent.length;
1766       }
1767 
1768       curr = curr.previousSibling;
1769     }
1770 
1771     return totalOffset;
1772   }
1773 
1774   normalizedMap(children, nodeType, ignoreClass) {
1775     var output = {};
1776     var prevIndex = -1;
1777     var i,
1778         len = children.length;
1779     var currNodeType;
1780     var prevNodeType;
1781 
1782     for (i = 0; i < len; i++) {
1783       currNodeType = children[i].nodeType; // Check if needs ignoring
1784 
1785       if (currNodeType === ELEMENT_NODE && children[i].classList.contains(ignoreClass)) {
1786         currNodeType = TEXT_NODE;
1787       }
1788 
1789       if (i > 0 && currNodeType === TEXT_NODE && prevNodeType === TEXT_NODE) {
1790         // join text nodes
1791         output[i] = prevIndex;
1792       } else if (nodeType === currNodeType) {
1793         prevIndex = prevIndex + 1;
1794         output[i] = prevIndex;
1795       }
1796 
1797       prevNodeType = currNodeType;
1798     }
1799 
1800     return output;
1801   }
1802 
1803   position(anchor) {
1804     var children, index;
1805 
1806     if (anchor.nodeType === ELEMENT_NODE) {
1807       children = anchor.parentNode.children;
1808 
1809       if (!children) {
1810         children = Object(_utils_core__WEBPACK_IMPORTED_MODULE_0__["findChildren"])(anchor.parentNode);
1811       }
1812 
1813       index = Array.prototype.indexOf.call(children, anchor);
1814     } else {
1815       children = this.textNodes(anchor.parentNode);
1816       index = children.indexOf(anchor);
1817     }
1818 
1819     return index;
1820   }
1821 
1822   filteredPosition(anchor, ignoreClass) {
1823     var children, index, map;
1824 
1825     if (anchor.nodeType === ELEMENT_NODE) {
1826       children = anchor.parentNode.children;
1827       map = this.normalizedMap(children, ELEMENT_NODE, ignoreClass);
1828     } else {
1829       children = anchor.parentNode.childNodes; // Inside an ignored node
1830 
1831       if (anchor.parentNode.classList.contains(ignoreClass)) {
1832         anchor = anchor.parentNode;
1833         children = anchor.parentNode.childNodes;
1834       }
1835 
1836       map = this.normalizedMap(children, TEXT_NODE, ignoreClass);
1837     }
1838 
1839     index = Array.prototype.indexOf.call(children, anchor);
1840     return map[index];
1841   }
1842 
1843   stepsToXpath(steps) {
1844     var xpath = [".", "*"];
1845     steps.forEach(function (step) {
1846       var position = step.index + 1;
1847 
1848       if (step.id) {
1849         xpath.push("*[position()=" + position + " and @id='" + step.id + "']");
1850       } else if (step.type === "text") {
1851         xpath.push("text()[" + position + "]");
1852       } else {
1853         xpath.push("*[" + position + "]");
1854       }
1855     });
1856     return xpath.join("/");
1857   }
1858   /*
1859         To get the last step if needed:
1860         // Get the terminal step
1861   lastStep = steps[steps.length-1];
1862   // Get the query string
1863   query = this.stepsToQuery(steps);
1864   // Find the containing element
1865   startContainerParent = doc.querySelector(query);
1866   // Find the text node within that element
1867   if(startContainerParent && lastStep.type == "text") {
1868         container = startContainerParent.childNodes[lastStep.index];
1869   }
1870   */
1871 
1872 
1873   stepsToQuerySelector(steps) {
1874     var query = ["html"];
1875     steps.forEach(function (step) {
1876       var position = step.index + 1;
1877 
1878       if (step.id) {
1879         query.push("#" + step.id);
1880       } else if (step.type === "text") {// unsupported in querySelector
1881         // query.push("text()[" + position + "]");
1882       } else {
1883         query.push("*:nth-child(" + position + ")");
1884       }
1885     });
1886     return query.join(">");
1887   }
1888 
1889   textNodes(container, ignoreClass) {
1890     return Array.prototype.slice.call(container.childNodes).filter(function (node) {
1891       if (node.nodeType === TEXT_NODE) {
1892         return true;
1893       } else if (ignoreClass && node.classList.contains(ignoreClass)) {
1894         return true;
1895       }
1896 
1897       return false;
1898     });
1899   }
1900 
1901   walkToNode(steps, _doc, ignoreClass) {
1902     var doc = _doc || document;
1903     var container = doc.documentElement;
1904     var children;
1905     var step;
1906     var len = steps.length;
1907     var i;
1908 
1909     for (i = 0; i < len; i++) {
1910       step = steps[i];
1911 
1912       if (step.type === "element") {
1913         //better to get a container using id as some times step.index may not be correct
1914         //For ex.https://github.com/futurepress/epub.js/issues/561
1915         if (step.id) {
1916           container = doc.getElementById(step.id);
1917         } else {
1918           children = container.children || Object(_utils_core__WEBPACK_IMPORTED_MODULE_0__["findChildren"])(container);
1919           container = children[step.index];
1920         }
1921       } else if (step.type === "text") {
1922         container = this.textNodes(container, ignoreClass)[step.index];
1923       }
1924 
1925       if (!container) {
1926         //Break the for loop as due to incorrect index we can get error if
1927         //container is undefined so that other functionailties works fine
1928         //like navigation
1929         break;
1930       }
1931     }
1932 
1933     return container;
1934   }
1935 
1936   findNode(steps, _doc, ignoreClass) {
1937     var doc = _doc || document;
1938     var container;
1939     var xpath;
1940 
1941     if (!ignoreClass && typeof doc.evaluate != "undefined") {
1942       xpath = this.stepsToXpath(steps);
1943       container = doc.evaluate(xpath, doc, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
1944     } else if (ignoreClass) {
1945       container = this.walkToNode(steps, doc, ignoreClass);
1946     } else {
1947       container = this.walkToNode(steps, doc);
1948     }
1949 
1950     return container;
1951   }
1952 
1953   fixMiss(steps, offset, _doc, ignoreClass) {
1954     var container = this.findNode(steps.slice(0, -1), _doc, ignoreClass);
1955     var children = container.childNodes;
1956     var map = this.normalizedMap(children, TEXT_NODE, ignoreClass);
1957     var child;
1958     var len;
1959     var lastStepIndex = steps[steps.length - 1].index;
1960 
1961     for (let childIndex in map) {
1962       if (!map.hasOwnProperty(childIndex)) return;
1963 
1964       if (map[childIndex] === lastStepIndex) {
1965         child = children[childIndex];
1966         len = child.textContent.length;
1967 
1968         if (offset > len) {
1969           offset = offset - len;
1970         } else {
1971           if (child.nodeType === ELEMENT_NODE) {
1972             container = child.childNodes[0];
1973           } else {
1974             container = child;
1975           }
1976 
1977           break;
1978         }
1979       }
1980     }
1981 
1982     return {
1983       container: container,
1984       offset: offset
1985     };
1986   }
1987   /**
1988    * Creates a DOM range representing a CFI
1989    * @param {document} _doc document referenced in the base
1990    * @param {string} [ignoreClass]
1991    * @return {Range}
1992    */
1993 
1994 
1995   toRange(_doc, ignoreClass) {
1996     var doc = _doc || document;
1997     var range;
1998     var start, end, startContainer, endContainer;
1999     var cfi = this;
2000     var startSteps, endSteps;
2001     var needsIgnoring = ignoreClass ? doc.querySelector("." + ignoreClass) != null : false;
2002     var missed;
2003 
2004     if (typeof doc.createRange !== "undefined") {
2005       range = doc.createRange();
2006     } else {
2007       range = new _utils_core__WEBPACK_IMPORTED_MODULE_0__["RangeObject"]();
2008     }
2009 
2010     if (cfi.range) {
2011       start = cfi.start;
2012       startSteps = cfi.path.steps.concat(start.steps);
2013       startContainer = this.findNode(startSteps, doc, needsIgnoring ? ignoreClass : null);
2014       end = cfi.end;
2015       endSteps = cfi.path.steps.concat(end.steps);
2016       endContainer = this.findNode(endSteps, doc, needsIgnoring ? ignoreClass : null);
2017     } else {
2018       start = cfi.path;
2019       startSteps = cfi.path.steps;
2020       startContainer = this.findNode(cfi.path.steps, doc, needsIgnoring ? ignoreClass : null);
2021     }
2022 
2023     if (startContainer) {
2024       try {
2025         if (start.terminal.offset != null) {
2026           range.setStart(startContainer, start.terminal.offset);
2027         } else {
2028           range.setStart(startContainer, 0);
2029         }
2030       } catch (e) {
2031         missed = this.fixMiss(startSteps, start.terminal.offset, doc, needsIgnoring ? ignoreClass : null);
2032         range.setStart(missed.container, missed.offset);
2033       }
2034     } else {
2035       console.log("No startContainer found for", this.toString()); // No start found
2036 
2037       return null;
2038     }
2039 
2040     if (endContainer) {
2041       try {
2042         if (end.terminal.offset != null) {
2043           range.setEnd(endContainer, end.terminal.offset);
2044         } else {
2045           range.setEnd(endContainer, 0);
2046         }
2047       } catch (e) {
2048         missed = this.fixMiss(endSteps, cfi.end.terminal.offset, doc, needsIgnoring ? ignoreClass : null);
2049         range.setEnd(missed.container, missed.offset);
2050       }
2051     } // doc.defaultView.getSelection().addRange(range);
2052 
2053 
2054     return range;
2055   }
2056   /**
2057    * Check if a string is wrapped with "epubcfi()"
2058    * @param {string} str
2059    * @returns {boolean}
2060    */
2061 
2062 
2063   isCfiString(str) {
2064     if (typeof str === "string" && str.indexOf("epubcfi(") === 0 && str[str.length - 1] === ")") {
2065       return true;
2066     }
2067 
2068     return false;
2069   }
2070 
2071   generateChapterComponent(_spineNodeIndex, _pos, id) {
2072     var pos = parseInt(_pos),
2073         spineNodeIndex = (_spineNodeIndex + 1) * 2,
2074         cfi = "/" + spineNodeIndex + "/";
2075     cfi += (pos + 1) * 2;
2076 
2077     if (id) {
2078       cfi += "[" + id + "]";
2079     }
2080 
2081     return cfi;
2082   }
2083   /**
2084    * Collapse a CFI Range to a single CFI Position
2085    * @param {boolean} [toStart=false]
2086    */
2087 
2088 
2089   collapse(toStart) {
2090     if (!this.range) {
2091       return;
2092     }
2093 
2094     this.range = false;
2095 
2096     if (toStart) {
2097       this.path.steps = this.path.steps.concat(this.start.steps);
2098       this.path.terminal = this.start.terminal;
2099     } else {
2100       this.path.steps = this.path.steps.concat(this.end.steps);
2101       this.path.terminal = this.end.terminal;
2102     }
2103   }
2104 
2105 }
2106 
2107 /* harmony default export */ __webpack_exports__["a"] = (EpubCFI);
2108 
2109 /***/ }),
2110 /* 3 */
2111 /***/ (function(module, exports, __webpack_require__) {
2112 
2113 "use strict";
2114 
2115 
2116 var d        = __webpack_require__(31)
2117   , callable = __webpack_require__(45)
2118 
2119   , apply = Function.prototype.apply, call = Function.prototype.call
2120   , create = Object.create, defineProperty = Object.defineProperty
2121   , defineProperties = Object.defineProperties
2122   , hasOwnProperty = Object.prototype.hasOwnProperty
2123   , descriptor = { configurable: true, enumerable: false, writable: true }
2124 
2125   , on, once, off, emit, methods, descriptors, base;
2126 
2127 on = function (type, listener) {
2128         var data;
2129 
2130         callable(listener);
2131 
2132         if (!hasOwnProperty.call(this, '__ee__')) {
2133                 data = descriptor.value = create(null);
2134                 defineProperty(this, '__ee__', descriptor);
2135                 descriptor.value = null;
2136         } else {
2137                 data = this.__ee__;
2138         }
2139         if (!data[type]) data[type] = listener;
2140         else if (typeof data[type] === 'object') data[type].push(listener);
2141         else data[type] = [data[type], listener];
2142 
2143         return this;
2144 };
2145 
2146 once = function (type, listener) {
2147         var once, self;
2148 
2149         callable(listener);
2150         self = this;
2151         on.call(this, type, once = function () {
2152                 off.call(self, type, once);
2153                 apply.call(listener, this, arguments);
2154         });
2155 
2156         once.__eeOnceListener__ = listener;
2157         return this;
2158 };
2159 
2160 off = function (type, listener) {
2161         var data, listeners, candidate, i;
2162 
2163         callable(listener);
2164 
2165         if (!hasOwnProperty.call(this, '__ee__')) return this;
2166         data = this.__ee__;
2167         if (!data[type]) return this;
2168         listeners = data[type];
2169 
2170         if (typeof listeners === 'object') {
2171                 for (i = 0; (candidate = listeners[i]); ++i) {
2172                         if ((candidate === listener) ||
2173                                         (candidate.__eeOnceListener__ === listener)) {
2174                                 if (listeners.length === 2) data[type] = listeners[i ? 0 : 1];
2175                                 else listeners.splice(i, 1);
2176                         }
2177                 }
2178         } else {
2179                 if ((listeners === listener) ||
2180                                 (listeners.__eeOnceListener__ === listener)) {
2181                         delete data[type];
2182                 }
2183         }
2184 
2185         return this;
2186 };
2187 
2188 emit = function (type) {
2189         var i, l, listener, listeners, args;
2190 
2191         if (!hasOwnProperty.call(this, '__ee__')) return;
2192         listeners = this.__ee__[type];
2193         if (!listeners) return;
2194 
2195         if (typeof listeners === 'object') {
2196                 l = arguments.length;
2197                 args = new Array(l - 1);
2198                 for (i = 1; i < l; ++i) args[i - 1] = arguments[i];
2199 
2200                 listeners = listeners.slice();
2201                 for (i = 0; (listener = listeners[i]); ++i) {
2202                         apply.call(listener, this, args);
2203                 }
2204         } else {
2205                 switch (arguments.length) {
2206                 case 1:
2207                         call.call(listeners, this);
2208                         break;
2209                 case 2:
2210                         call.call(listeners, this, arguments[1]);
2211                         break;
2212                 case 3:
2213                         call.call(listeners, this, arguments[1], arguments[2]);
2214                         break;
2215                 default:
2216                         l = arguments.length;
2217                         args = new Array(l - 1);
2218                         for (i = 1; i < l; ++i) {
2219                                 args[i - 1] = arguments[i];
2220                         }
2221                         apply.call(listeners, this, args);
2222                 }
2223         }
2224 };
2225 
2226 methods = {
2227         on: on,
2228         once: once,
2229         off: off,
2230         emit: emit
2231 };
2232 
2233 descriptors = {
2234         on: d(on),
2235         once: d(once),
2236         off: d(off),
2237         emit: d(emit)
2238 };
2239 
2240 base = defineProperties({}, descriptors);
2241 
2242 module.exports = exports = function (o) {
2243         return (o == null) ? create(base) : defineProperties(Object(o), descriptors);
2244 };
2245 exports.methods = methods;
2246 
2247 
2248 /***/ }),
2249 /* 4 */
2250 /***/ (function(module, __webpack_exports__, __webpack_require__) {
2251 
2252 "use strict";
2253 /* harmony import */ var path_webpack__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(7);
2254 /* harmony import */ var path_webpack__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(path_webpack__WEBPACK_IMPORTED_MODULE_0__);
2255 
2256 /**
2257  * Creates a Path object for parsing and manipulation of a path strings
2258  *
2259  * Uses a polyfill for Nodejs path: https://nodejs.org/api/path.html
2260  * @param       {string} pathString     a url string (relative or absolute)
2261  * @class
2262  */
2263 
2264 class Path {
2265   constructor(pathString) {
2266     var protocol;
2267     var parsed;
2268     protocol = pathString.indexOf("://");
2269 
2270     if (protocol > -1) {
2271       pathString = new URL(pathString).pathname;
2272     }
2273 
2274     parsed = this.parse(pathString);
2275     this.path = pathString;
2276 
2277     if (this.isDirectory(pathString)) {
2278       this.directory = pathString;
2279     } else {
2280       this.directory = parsed.dir + "/";
2281     }
2282 
2283     this.filename = parsed.base;
2284     this.extension = parsed.ext.slice(1);
2285   }
2286   /**
2287    * Parse the path: https://nodejs.org/api/path.html#path_path_parse_path
2288    * @param     {string} what
2289    * @returns {object}
2290    */
2291 
2292 
2293   parse(what) {
2294     return path_webpack__WEBPACK_IMPORTED_MODULE_0___default.a.parse(what);
2295   }
2296   /**
2297    * @param     {string} what
2298    * @returns {boolean}
2299    */
2300 
2301 
2302   isAbsolute(what) {
2303     return path_webpack__WEBPACK_IMPORTED_MODULE_0___default.a.isAbsolute(what || this.path);
2304   }
2305   /**
2306    * Check if path ends with a directory
2307    * @param     {string} what
2308    * @returns {boolean}
2309    */
2310 
2311 
2312   isDirectory(what) {
2313     return what.charAt(what.length - 1) === "/";
2314   }
2315   /**
2316    * Resolve a path against the directory of the Path
2317    *
2318    * https://nodejs.org/api/path.html#path_path_resolve_paths
2319    * @param     {string} what
2320    * @returns {string} resolved
2321    */
2322 
2323 
2324   resolve(what) {
2325     return path_webpack__WEBPACK_IMPORTED_MODULE_0___default.a.resolve(this.directory, what);
2326   }
2327   /**
2328    * Resolve a path relative to the directory of the Path
2329    *
2330    * https://nodejs.org/api/path.html#path_path_relative_from_to
2331    * @param     {string} what
2332    * @returns {string} relative
2333    */
2334 
2335 
2336   relative(what) {
2337     var isAbsolute = what && what.indexOf("://") > -1;
2338 
2339     if (isAbsolute) {
2340       return what;
2341     }
2342 
2343     return path_webpack__WEBPACK_IMPORTED_MODULE_0___default.a.relative(this.directory, what);
2344   }
2345 
2346   splitPath(filename) {
2347     return this.splitPathRe.exec(filename).slice(1);
2348   }
2349   /**
2350    * Return the path string
2351    * @returns {string} path
2352    */
2353 
2354 
2355   toString() {
2356     return this.path;
2357   }
2358 
2359 }
2360 
2361 /* harmony default export */ __webpack_exports__["a"] = (Path);
2362 
2363 /***/ }),
2364 /* 5 */
2365 /***/ (function(module, __webpack_exports__, __webpack_require__) {
2366 
2367 "use strict";
2368 /* harmony import */ var _path__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(4);
2369 /* harmony import */ var path_webpack__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(7);
2370 /* harmony import */ var path_webpack__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(path_webpack__WEBPACK_IMPORTED_MODULE_1__);
2371 
2372 
2373 /**
2374  * creates a Url object for parsing and manipulation of a url string
2375  * @param       {string} urlString      a url string (relative or absolute)
2376  * @param       {string} [baseString] optional base for the url,
2377  * default to window.location.href
2378  */
2379 
2380 class Url {
2381   constructor(urlString, baseString) {
2382     var absolute = urlString.indexOf("://") > -1;
2383     var pathname = urlString;
2384     var basePath;
2385     this.Url = undefined;
2386     this.href = urlString;
2387     this.protocol = "";
2388     this.origin = "";
2389     this.hash = "";
2390     this.hash = "";
2391     this.search = "";
2392     this.base = baseString;
2393 
2394     if (!absolute && baseString !== false && typeof baseString !== "string" && window && window.location) {
2395       this.base = window.location.href;
2396     } // URL Polyfill doesn't throw an error if base is empty
2397 
2398 
2399     if (absolute || this.base) {
2400       try {
2401         if (this.base) {
2402           // Safari doesn't like an undefined base
2403           this.Url = new URL(urlString, this.base);
2404         } else {
2405           this.Url = new URL(urlString);
2406         }
2407 
2408         this.href = this.Url.href;
2409         this.protocol = this.Url.protocol;
2410         this.origin = this.Url.origin;
2411         this.hash = this.Url.hash;
2412         this.search = this.Url.search;
2413         pathname = this.Url.pathname + (this.Url.search ? this.Url.search : '');
2414       } catch (e) {
2415         // Skip URL parsing
2416         this.Url = undefined; // resolve the pathname from the base
2417 
2418         if (this.base) {
2419           basePath = new _path__WEBPACK_IMPORTED_MODULE_0__[/* default */ "a"](this.base);
2420           pathname = basePath.resolve(pathname);
2421         }
2422       }
2423     }
2424 
2425     this.Path = new _path__WEBPACK_IMPORTED_MODULE_0__[/* default */ "a"](pathname);
2426     this.directory = this.Path.directory;
2427     this.filename = this.Path.filename;
2428     this.extension = this.Path.extension;
2429   }
2430   /**
2431    * @returns {Path}
2432    */
2433 
2434 
2435   path() {
2436     return this.Path;
2437   }
2438   /**
2439    * Resolves a relative path to a absolute url
2440    * @param {string} what
2441    * @returns {string} url
2442    */
2443 
2444 
2445   resolve(what) {
2446     var isAbsolute = what.indexOf("://") > -1;
2447     var fullpath;
2448 
2449     if (isAbsolute) {
2450       return what;
2451     }
2452 
2453     fullpath = path_webpack__WEBPACK_IMPORTED_MODULE_1___default.a.resolve(this.directory, what);
2454     return this.origin + fullpath;
2455   }
2456   /**
2457    * Resolve a path relative to the url
2458    * @param {string} what
2459    * @returns {string} path
2460    */
2461 
2462 
2463   relative(what) {
2464     return path_webpack__WEBPACK_IMPORTED_MODULE_1___default.a.relative(what, this.directory);
2465   }
2466   /**
2467    * @returns {string}
2468    */
2469 
2470 
2471   toString() {
2472     return this.href;
2473   }
2474 
2475 }
2476 
2477 /* harmony default export */ __webpack_exports__["a"] = (Url);
2478 
2479 /***/ }),
2480 /* 6 */
2481 /***/ (function(module, __webpack_exports__, __webpack_require__) {
2482 
2483 "use strict";
2484 /**
2485  * Hooks allow for injecting functions that must all complete in order before finishing
2486  * They will execute in parallel but all must finish before continuing
2487  * Functions may return a promise if they are async.
2488  * @param {any} context scope of this
2489  * @example this.content = new EPUBJS.Hook(this);
2490  */
2491 class Hook {
2492   constructor(context) {
2493     this.context = context || this;
2494     this.hooks = [];
2495   }
2496   /**
2497    * Adds a function to be run before a hook completes
2498    * @example this.content.register(function(){...});
2499    */
2500 
2501 
2502   register() {
2503     for (var i = 0; i < arguments.length; ++i) {
2504       if (typeof arguments[i] === "function") {
2505         this.hooks.push(arguments[i]);
2506       } else {
2507         // unpack array
2508         for (var j = 0; j < arguments[i].length; ++j) {
2509           this.hooks.push(arguments[i][j]);
2510         }
2511       }
2512     }
2513   }
2514   /**
2515    * Removes a function
2516    * @example this.content.deregister(function(){...});
2517    */
2518 
2519 
2520   deregister(func) {
2521     let hook;
2522 
2523     for (let i = 0; i < this.hooks.length; i++) {
2524       hook = this.hooks[i];
2525 
2526       if (hook === func) {
2527         this.hooks.splice(i, 1);
2528         break;
2529       }
2530     }
2531   }
2532   /**
2533    * Triggers a hook to run all functions
2534    * @example this.content.trigger(args).then(function(){...});
2535    */
2536 
2537 
2538   trigger() {
2539     var args = arguments;
2540     var context = this.context;
2541     var promises = [];
2542     this.hooks.forEach(function (task) {
2543       try {
2544         var executing = task.apply(context, args);
2545       } catch (err) {
2546         console.log(err);
2547       }
2548 
2549       if (executing && typeof executing["then"] === "function") {
2550         // Task is a function that returns a promise
2551         promises.push(executing);
2552       } // Otherwise Task resolves immediately, continue
2553 
2554     });
2555     return Promise.all(promises);
2556   } // Adds a function to be run before a hook completes
2557 
2558 
2559   list() {
2560     return this.hooks;
2561   }
2562 
2563   clear() {
2564     return this.hooks = [];
2565   }
2566 
2567 }
2568 
2569 /* harmony default export */ __webpack_exports__["a"] = (Hook);
2570 
2571 /***/ }),
2572 /* 7 */
2573 /***/ (function(module, exports, __webpack_require__) {
2574 
2575 "use strict";
2576 
2577 
2578 if (!process) {
2579   var process = {
2580     "cwd" : function () { return '/' }
2581   };
2582 }
2583 
2584 function assertPath(path) {
2585   if (typeof path !== 'string') {
2586     throw new TypeError('Path must be a string. Received ' + path);
2587   }
2588 }
2589 
2590 // Resolves . and .. elements in a path with directory names
2591 function normalizeStringPosix(path, allowAboveRoot) {
2592   var res = '';
2593   var lastSlash = -1;
2594   var dots = 0;
2595   var code;
2596   for (var i = 0; i <= path.length; ++i) {
2597     if (i < path.length)
2598       code = path.charCodeAt(i);
2599     else if (code === 47/*/*/)
2600       break;
2601     else
2602       code = 47/*/*/;
2603     if (code === 47/*/*/) {
2604       if (lastSlash === i - 1 || dots === 1) {
2605         // NOOP
2606       } else if (lastSlash !== i - 1 && dots === 2) {
2607         if (res.length < 2 ||
2608             res.charCodeAt(res.length - 1) !== 46/*.*/ ||
2609             res.charCodeAt(res.length - 2) !== 46/*.*/) {
2610           if (res.length > 2) {
2611             var start = res.length - 1;
2612             var j = start;
2613             for (; j >= 0; --j) {
2614               if (res.charCodeAt(j) === 47/*/*/)
2615                 break;
2616             }
2617             if (j !== start) {
2618               if (j === -1)
2619                 res = '';
2620               else
2621                 res = res.slice(0, j);
2622               lastSlash = i;
2623               dots = 0;
2624               continue;
2625             }
2626           } else if (res.length === 2 || res.length === 1) {
2627             res = '';
2628             lastSlash = i;
2629             dots = 0;
2630             continue;
2631           }
2632         }
2633         if (allowAboveRoot) {
2634           if (res.length > 0)
2635             res += '/..';
2636           else
2637             res = '..';
2638         }
2639       } else {
2640         if (res.length > 0)
2641           res += '/' + path.slice(lastSlash + 1, i);
2642         else
2643           res = path.slice(lastSlash + 1, i);
2644       }
2645       lastSlash = i;
2646       dots = 0;
2647     } else if (code === 46/*.*/ && dots !== -1) {
2648       ++dots;
2649     } else {
2650       dots = -1;
2651     }
2652   }
2653   return res;
2654 }
2655 
2656 function _format(sep, pathObject) {
2657   var dir = pathObject.dir || pathObject.root;
2658   var base = pathObject.base ||
2659     ((pathObject.name || '') + (pathObject.ext || ''));
2660   if (!dir) {
2661     return base;
2662   }
2663   if (dir === pathObject.root) {
2664     return dir + base;
2665   }
2666   return dir + sep + base;
2667 }
2668 
2669 var posix = {
2670   // path.resolve([from ...], to)
2671   resolve: function resolve() {
2672     var resolvedPath = '';
2673     var resolvedAbsolute = false;
2674     var cwd;
2675 
2676     for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {
2677       var path;
2678       if (i >= 0)
2679         path = arguments[i];
2680       else {
2681         if (cwd === undefined)
2682           cwd = process.cwd();
2683         path = cwd;
2684       }
2685 
2686       assertPath(path);
2687 
2688       // Skip empty entries
2689       if (path.length === 0) {
2690         continue;
2691       }
2692 
2693       resolvedPath = path + '/' + resolvedPath;
2694       resolvedAbsolute = path.charCodeAt(0) === 47/*/*/;
2695     }
2696 
2697     // At this point the path should be resolved to a full absolute path, but
2698     // handle relative paths to be safe (might happen when process.cwd() fails)
2699 
2700     // Normalize the path
2701     resolvedPath = normalizeStringPosix(resolvedPath, !resolvedAbsolute);
2702 
2703     if (resolvedAbsolute) {
2704       if (resolvedPath.length > 0)
2705         return '/' + resolvedPath;
2706       else
2707         return '/';
2708     } else if (resolvedPath.length > 0) {
2709       return resolvedPath;
2710     } else {
2711       return '.';
2712     }
2713   },
2714 
2715 
2716   normalize: function normalize(path) {
2717     assertPath(path);
2718 
2719     if (path.length === 0)
2720       return '.';
2721 
2722     var isAbsolute = path.charCodeAt(0) === 47/*/*/;
2723     var trailingSeparator = path.charCodeAt(path.length - 1) === 47/*/*/;
2724 
2725     // Normalize the path
2726     path = normalizeStringPosix(path, !isAbsolute);
2727 
2728     if (path.length === 0 && !isAbsolute)
2729       path = '.';
2730     if (path.length > 0 && trailingSeparator)
2731       path += '/';
2732 
2733     if (isAbsolute)
2734       return '/' + path;
2735     return path;
2736   },
2737 
2738 
2739   isAbsolute: function isAbsolute(path) {
2740     assertPath(path);
2741     return path.length > 0 && path.charCodeAt(0) === 47/*/*/;
2742   },
2743 
2744 
2745   join: function join() {
2746     if (arguments.length === 0)
2747       return '.';
2748     var joined;
2749     for (var i = 0; i < arguments.length; ++i) {
2750       var arg = arguments[i];
2751       assertPath(arg);
2752       if (arg.length > 0) {
2753         if (joined === undefined)
2754           joined = arg;
2755         else
2756           joined += '/' + arg;
2757       }
2758     }
2759     if (joined === undefined)
2760       return '.';
2761     return posix.normalize(joined);
2762   },
2763 
2764 
2765   relative: function relative(from, to) {
2766     assertPath(from);
2767     assertPath(to);
2768 
2769     if (from === to)
2770       return '';
2771 
2772     from = posix.resolve(from);
2773     to = posix.resolve(to);
2774 
2775     if (from === to)
2776       return '';
2777 
2778     // Trim any leading backslashes
2779     var fromStart = 1;
2780     for (; fromStart < from.length; ++fromStart) {
2781       if (from.charCodeAt(fromStart) !== 47/*/*/)
2782         break;
2783     }
2784     var fromEnd = from.length;
2785     var fromLen = (fromEnd - fromStart);
2786 
2787     // Trim any leading backslashes
2788     var toStart = 1;
2789     for (; toStart < to.length; ++toStart) {
2790       if (to.charCodeAt(toStart) !== 47/*/*/)
2791         break;
2792     }
2793     var toEnd = to.length;
2794     var toLen = (toEnd - toStart);
2795 
2796     // Compare paths to find the longest common path from root
2797     var length = (fromLen < toLen ? fromLen : toLen);
2798     var lastCommonSep = -1;
2799     var i = 0;
2800     for (; i <= length; ++i) {
2801       if (i === length) {
2802         if (toLen > length) {
2803           if (to.charCodeAt(toStart + i) === 47/*/*/) {
2804             // We get here if `from` is the exact base path for `to`.
2805             // For example: from='/foo/bar'; to='/foo/bar/baz'
2806             return to.slice(toStart + i + 1);
2807           } else if (i === 0) {
2808             // We get here if `from` is the root
2809             // For example: from='/'; to='/foo'
2810             return to.slice(toStart + i);
2811           }
2812         } else if (fromLen > length) {
2813           if (from.charCodeAt(fromStart + i) === 47/*/*/) {
2814             // We get here if `to` is the exact base path for `from`.
2815             // For example: from='/foo/bar/baz'; to='/foo/bar'
2816             lastCommonSep = i;
2817           } else if (i === 0) {
2818             // We get here if `to` is the root.
2819             // For example: from='/foo'; to='/'
2820             lastCommonSep = 0;
2821           }
2822         }
2823         break;
2824       }
2825       var fromCode = from.charCodeAt(fromStart + i);
2826       var toCode = to.charCodeAt(toStart + i);
2827       if (fromCode !== toCode)
2828         break;
2829       else if (fromCode === 47/*/*/)
2830         lastCommonSep = i;
2831     }
2832 
2833     var out = '';
2834     // Generate the relative path based on the path difference between `to`
2835     // and `from`
2836     for (i = fromStart + lastCommonSep + 1; i <= fromEnd; ++i) {
2837       if (i === fromEnd || from.charCodeAt(i) === 47/*/*/) {
2838         if (out.length === 0)
2839           out += '..';
2840         else
2841           out += '/..';
2842       }
2843     }
2844 
2845     // Lastly, append the rest of the destination (`to`) path that comes after
2846     // the common path parts
2847     if (out.length > 0)
2848       return out + to.slice(toStart + lastCommonSep);
2849     else {
2850       toStart += lastCommonSep;
2851       if (to.charCodeAt(toStart) === 47/*/*/)
2852         ++toStart;
2853       return to.slice(toStart);
2854     }
2855   },
2856 
2857 
2858   _makeLong: function _makeLong(path) {
2859     return path;
2860   },
2861 
2862 
2863   dirname: function dirname(path) {
2864     assertPath(path);
2865     if (path.length === 0)
2866       return '.';
2867     var code = path.charCodeAt(0);
2868     var hasRoot = (code === 47/*/*/);
2869     var end = -1;
2870     var matchedSlash = true;
2871     for (var i = path.length - 1; i >= 1; --i) {
2872       code = path.charCodeAt(i);
2873       if (code === 47/*/*/) {
2874         if (!matchedSlash) {
2875           end = i;
2876           break;
2877         }
2878       } else {
2879         // We saw the first non-path separator
2880         matchedSlash = false;
2881       }
2882     }
2883 
2884     if (end === -1)
2885       return hasRoot ? '/' : '.';
2886     if (hasRoot && end === 1)
2887       return '//';
2888     return path.slice(0, end);
2889   },
2890 
2891 
2892   basename: function basename(path, ext) {
2893     if (ext !== undefined && typeof ext !== 'string')
2894       throw new TypeError('"ext" argument must be a string');
2895     assertPath(path);
2896 
2897     var start = 0;
2898     var end = -1;
2899     var matchedSlash = true;
2900     var i;
2901 
2902     if (ext !== undefined && ext.length > 0 && ext.length <= path.length) {
2903       if (ext.length === path.length && ext === path)
2904         return '';
2905       var extIdx = ext.length - 1;
2906       var firstNonSlashEnd = -1;
2907       for (i = path.length - 1; i >= 0; --i) {
2908         var code = path.charCodeAt(i);
2909         if (code === 47/*/*/) {
2910           // If we reached a path separator that was not part of a set of path
2911           // separators at the end of the string, stop now
2912           if (!matchedSlash) {
2913             start = i + 1;
2914             break;
2915           }
2916         } else {
2917           if (firstNonSlashEnd === -1) {
2918             // We saw the first non-path separator, remember this index in case
2919             // we need it if the extension ends up not matching
2920             matchedSlash = false;
2921             firstNonSlashEnd = i + 1;
2922           }
2923           if (extIdx >= 0) {
2924             // Try to match the explicit extension
2925             if (code === ext.charCodeAt(extIdx)) {
2926               if (--extIdx === -1) {
2927                 // We matched the extension, so mark this as the end of our path
2928                 // component
2929                 end = i;
2930               }
2931             } else {
2932               // Extension does not match, so our result is the entire path
2933               // component
2934               extIdx = -1;
2935               end = firstNonSlashEnd;
2936             }
2937           }
2938         }
2939       }
2940 
2941       if (start === end)
2942         end = firstNonSlashEnd;
2943       else if (end === -1)
2944         end = path.length;
2945       return path.slice(start, end);
2946     } else {
2947       for (i = path.length - 1; i >= 0; --i) {
2948         if (path.charCodeAt(i) === 47/*/*/) {
2949           // If we reached a path separator that was not part of a set of path
2950           // separators at the end of the string, stop now
2951           if (!matchedSlash) {
2952             start = i + 1;
2953             break;
2954           }
2955         } else if (end === -1) {
2956           // We saw the first non-path separator, mark this as the end of our
2957           // path component
2958           matchedSlash = false;
2959           end = i + 1;
2960         }
2961       }
2962 
2963       if (end === -1)
2964         return '';
2965       return path.slice(start, end);
2966     }
2967   },
2968 
2969 
2970   extname: function extname(path) {
2971     assertPath(path);
2972     var startDot = -1;
2973     var startPart = 0;
2974     var end = -1;
2975     var matchedSlash = true;
2976     // Track the state of characters (if any) we see before our first dot and
2977     // after any path separator we find
2978     var preDotState = 0;
2979     for (var i = path.length - 1; i >= 0; --i) {
2980       var code = path.charCodeAt(i);
2981       if (code === 47/*/*/) {
2982         // If we reached a path separator that was not part of a set of path
2983         // separators at the end of the string, stop now
2984         if (!matchedSlash) {
2985           startPart = i + 1;
2986           break;
2987         }
2988         continue;
2989       }
2990       if (end === -1) {
2991         // We saw the first non-path separator, mark this as the end of our
2992         // extension
2993         matchedSlash = false;
2994         end = i + 1;
2995       }
2996       if (code === 46/*.*/) {
2997         // If this is our first dot, mark it as the start of our extension
2998         if (startDot === -1)
2999           startDot = i;
3000         else if (preDotState !== 1)
3001           preDotState = 1;
3002       } else if (startDot !== -1) {
3003         // We saw a non-dot and non-path separator before our dot, so we should
3004         // have a good chance at having a non-empty extension
3005         preDotState = -1;
3006       }
3007     }
3008 
3009     if (startDot === -1 ||
3010         end === -1 ||
3011         // We saw a non-dot character immediately before the dot
3012         preDotState === 0 ||
3013         // The (right-most) trimmed path component is exactly '..'
3014         (preDotState === 1 &&
3015          startDot === end - 1 &&
3016          startDot === startPart + 1)) {
3017       return '';
3018     }
3019     return path.slice(startDot, end);
3020   },
3021 
3022 
3023   format: function format(pathObject) {
3024     if (pathObject === null || typeof pathObject !== 'object') {
3025       throw new TypeError(
3026         'Parameter "pathObject" must be an object, not ' + typeof(pathObject)
3027       );
3028     }
3029     return _format('/', pathObject);
3030   },
3031 
3032 
3033   parse: function parse(path) {
3034     assertPath(path);
3035 
3036     var ret = { root: '', dir: '', base: '', ext: '', name: '' };
3037     if (path.length === 0)
3038       return ret;
3039     var code = path.charCodeAt(0);
3040     var isAbsolute = (code === 47/*/*/);
3041     var start;
3042     if (isAbsolute) {
3043       ret.root = '/';
3044       start = 1;
3045     } else {
3046       start = 0;
3047     }
3048     var startDot = -1;
3049     var startPart = 0;
3050     var end = -1;
3051     var matchedSlash = true;
3052     var i = path.length - 1;
3053 
3054     // Track the state of characters (if any) we see before our first dot and
3055     // after any path separator we find
3056     var preDotState = 0;
3057 
3058     // Get non-dir info
3059     for (; i >= start; --i) {
3060       code = path.charCodeAt(i);
3061       if (code === 47/*/*/) {
3062         // If we reached a path separator that was not part of a set of path
3063         // separators at the end of the string, stop now
3064         if (!matchedSlash) {
3065           startPart = i + 1;
3066           break;
3067         }
3068         continue;
3069       }
3070       if (end === -1) {
3071         // We saw the first non-path separator, mark this as the end of our
3072         // extension
3073         matchedSlash = false;
3074         end = i + 1;
3075       }
3076       if (code === 46/*.*/) {
3077         // If this is our first dot, mark it as the start of our extension
3078         if (startDot === -1)
3079           startDot = i;
3080         else if (preDotState !== 1)
3081           preDotState = 1;
3082       } else if (startDot !== -1) {
3083         // We saw a non-dot and non-path separator before our dot, so we should
3084         // have a good chance at having a non-empty extension
3085         preDotState = -1;
3086       }
3087     }
3088 
3089     if (startDot === -1 ||
3090         end === -1 ||
3091         // We saw a non-dot character immediately before the dot
3092         preDotState === 0 ||
3093         // The (right-most) trimmed path component is exactly '..'
3094         (preDotState === 1 &&
3095          startDot === end - 1 &&
3096          startDot === startPart + 1)) {
3097       if (end !== -1) {
3098         if (startPart === 0 && isAbsolute)
3099           ret.base = ret.name = path.slice(1, end);
3100         else
3101           ret.base = ret.name = path.slice(startPart, end);
3102       }
3103     } else {
3104       if (startPart === 0 && isAbsolute) {
3105         ret.name = path.slice(1, startDot);
3106         ret.base = path.slice(1, end);
3107       } else {
3108         ret.name = path.slice(startPart, startDot);
3109         ret.base = path.slice(startPart, end);
3110       }
3111       ret.ext = path.slice(startDot, end);
3112     }
3113 
3114     if (startPart > 0)
3115       ret.dir = path.slice(0, startPart - 1);
3116     else if (isAbsolute)
3117       ret.dir = '/';
3118 
3119     return ret;
3120   },
3121 
3122 
3123   sep: '/',
3124   delimiter: ':',
3125   posix: null
3126 };
3127 
3128 
3129 module.exports = posix;
3130 
3131 
3132 /***/ }),
3133 /* 8 */
3134 /***/ (function(module, __webpack_exports__, __webpack_require__) {
3135 
3136 "use strict";
3137 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return replaceBase; });
3138 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "b", function() { return replaceCanonical; });
3139 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "d", function() { return replaceMeta; });
3140 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "c", function() { return replaceLinks; });
3141 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "e", function() { return substitute; });
3142 /* harmony import */ var _core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(0);
3143 /* harmony import */ var _url__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(5);
3144 /* harmony import */ var _path__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(4);
3145 
3146 
3147 
3148 function replaceBase(doc, section) {
3149   var base;
3150   var head;
3151   var url = section.url;
3152   var absolute = url.indexOf("://") > -1;
3153 
3154   if (!doc) {
3155     return;
3156   }
3157 
3158   head = Object(_core__WEBPACK_IMPORTED_MODULE_0__["qs"])(doc, "head");
3159   base = Object(_core__WEBPACK_IMPORTED_MODULE_0__["qs"])(head, "base");
3160 
3161   if (!base) {
3162     base = doc.createElement("base");
3163     head.insertBefore(base, head.firstChild);
3164   } // Fix for Safari crashing if the url doesn't have an origin
3165 
3166 
3167   if (!absolute && window && window.location) {
3168     url = window.location.origin + url;
3169   }
3170 
3171   base.setAttribute("href", url);
3172 }
3173 function replaceCanonical(doc, section) {
3174   var head;
3175   var link;
3176   var url = section.canonical;
3177 
3178   if (!doc) {
3179     return;
3180   }
3181 
3182   head = Object(_core__WEBPACK_IMPORTED_MODULE_0__["qs"])(doc, "head");
3183   link = Object(_core__WEBPACK_IMPORTED_MODULE_0__["qs"])(head, "link[rel='canonical']");
3184 
3185   if (link) {
3186     link.setAttribute("href", url);
3187   } else {
3188     link = doc.createElement("link");
3189     link.setAttribute("rel", "canonical");
3190     link.setAttribute("href", url);
3191     head.appendChild(link);
3192   }
3193 }
3194 function replaceMeta(doc, section) {
3195   var head;
3196   var meta;
3197   var id = section.idref;
3198 
3199   if (!doc) {
3200     return;
3201   }
3202 
3203   head = Object(_core__WEBPACK_IMPORTED_MODULE_0__["qs"])(doc, "head");
3204   meta = Object(_core__WEBPACK_IMPORTED_MODULE_0__["qs"])(head, "link[property='dc.identifier']");
3205 
3206   if (meta) {
3207     meta.setAttribute("content", id);
3208   } else {
3209     meta = doc.createElement("meta");
3210     meta.setAttribute("name", "dc.identifier");
3211     meta.setAttribute("content", id);
3212     head.appendChild(meta);
3213   }
3214 } // TODO: move me to Contents
3215 
3216 function replaceLinks(contents, fn) {
3217   var links = contents.querySelectorAll("a[href]");
3218 
3219   if (!links.length) {
3220     return;
3221   }
3222 
3223   var base = Object(_core__WEBPACK_IMPORTED_MODULE_0__["qs"])(contents.ownerDocument, "base");
3224   var location = base ? base.getAttribute("href") : undefined;
3225 
3226   var replaceLink = function (link) {
3227     var href = link.getAttribute("href");
3228 
3229     if (href.indexOf("mailto:") === 0) {
3230       return;
3231     }
3232 
3233     var absolute = href.indexOf("://") > -1;
3234 
3235     if (absolute) {
3236       link.setAttribute("target", "_blank");
3237     } else {
3238       var linkUrl;
3239 
3240       try {
3241         linkUrl = new _url__WEBPACK_IMPORTED_MODULE_1__[/* default */ "a"](href, location);
3242       } catch (error) {// NOOP
3243       }
3244 
3245       link.onclick = function () {
3246         if (linkUrl && linkUrl.hash) {
3247           fn(linkUrl.Path.path + linkUrl.hash);
3248         } else if (linkUrl) {
3249           fn(linkUrl.Path.path);
3250         } else {
3251           fn(href);
3252         }
3253 
3254         return false;
3255       };
3256     }
3257   }.bind(this);
3258 
3259   for (var i = 0; i < links.length; i++) {
3260     replaceLink(links[i]);
3261   }
3262 }
3263 function substitute(content, urls, replacements) {
3264   urls.forEach(function (url, i) {
3265     if (url && replacements[i]) {
3266       // Account for special characters in the file name.
3267       // See https://stackoverflow.com/a/6318729.
3268       url = url.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
3269       content = content.replace(new RegExp(url, "g"), replacements[i]);
3270     }
3271   });
3272   return content;
3273 }
3274 
3275 /***/ }),
3276 /* 9 */
3277 /***/ (function(module, __webpack_exports__, __webpack_require__) {
3278 
3279 "use strict";
3280 /* unused harmony export Task */
3281 /* harmony import */ var _core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(0);
3282 
3283 /**
3284  * Queue for handling tasks one at a time
3285  * @class
3286  * @param {scope} context what this will resolve to in the tasks
3287  */
3288 
3289 class Queue {
3290   constructor(context) {
3291     this._q = [];
3292     this.context = context;
3293     this.tick = _core__WEBPACK_IMPORTED_MODULE_0__["requestAnimationFrame"];
3294     this.running = false;
3295     this.paused = false;
3296   }
3297   /**
3298    * Add an item to the queue
3299    * @return {Promise}
3300    */
3301 
3302 
3303   enqueue() {
3304     var deferred, promise;
3305     var queued;
3306     var task = [].shift.call(arguments);
3307     var args = arguments; // Handle single args without context
3308     // if(args && !Array.isArray(args)) {
3309     //   args = [args];
3310     // }
3311 
3312     if (!task) {
3313       throw new Error("No Task Provided");
3314     }
3315 
3316     if (typeof task === "function") {
3317       deferred = new _core__WEBPACK_IMPORTED_MODULE_0__["defer"]();
3318       promise = deferred.promise;
3319       queued = {
3320         "task": task,
3321         "args": args,
3322         //"context"  : context,
3323         "deferred": deferred,
3324         "promise": promise
3325       };
3326     } else {
3327       // Task is a promise
3328       queued = {
3329         "promise": task
3330       };
3331     }
3332 
3333     this._q.push(queued); // Wait to start queue flush
3334 
3335 
3336     if (this.paused == false && !this.running) {
3337       // setTimeout(this.flush.bind(this), 0);
3338       // this.tick.call(window, this.run.bind(this));
3339       this.run();
3340     }
3341 
3342     return queued.promise;
3343   }
3344   /**
3345    * Run one item
3346    * @return {Promise}
3347    */
3348 
3349 
3350   dequeue() {
3351     var inwait, task, result;
3352 
3353     if (this._q.length && !this.paused) {
3354       inwait = this._q.shift();
3355       task = inwait.task;
3356 
3357       if (task) {
3358         // console.log(task)
3359         result = task.apply(this.context, inwait.args);
3360 
3361         if (result && typeof result["then"] === "function") {
3362           // Task is a function that returns a promise
3363           return result.then(function () {
3364             inwait.deferred.resolve.apply(this.context, arguments);
3365           }.bind(this), function () {
3366             inwait.deferred.reject.apply(this.context, arguments);
3367           }.bind(this));
3368         } else {
3369           // Task resolves immediately
3370           inwait.deferred.resolve.apply(this.context, result);
3371           return inwait.promise;
3372         }
3373       } else if (inwait.promise) {
3374         // Task is a promise
3375         return inwait.promise;
3376       }
3377     } else {
3378       inwait = new _core__WEBPACK_IMPORTED_MODULE_0__["defer"]();
3379       inwait.deferred.resolve();
3380       return inwait.promise;
3381     }
3382   } // Run All Immediately
3383 
3384 
3385   dump() {
3386     while (this._q.length) {
3387       this.dequeue();
3388     }
3389   }
3390   /**
3391    * Run all tasks sequentially, at convince
3392    * @return {Promise}
3393    */
3394 
3395 
3396   run() {
3397     if (!this.running) {
3398       this.running = true;
3399       this.defered = new _core__WEBPACK_IMPORTED_MODULE_0__["defer"]();
3400     }
3401 
3402     this.tick.call(window, () => {
3403       if (this._q.length) {
3404         this.dequeue().then(function () {
3405           this.run();
3406         }.bind(this));
3407       } else {
3408         this.defered.resolve();
3409         this.running = undefined;
3410       }
3411     }); // Unpause
3412 
3413     if (this.paused == true) {
3414       this.paused = false;
3415     }
3416 
3417     return this.defered.promise;
3418   }
3419   /**
3420    * Flush all, as quickly as possible
3421    * @return {Promise}
3422    */
3423 
3424 
3425   flush() {
3426     if (this.running) {
3427       return this.running;
3428     }
3429 
3430     if (this._q.length) {
3431       this.running = this.dequeue().then(function () {
3432         this.running = undefined;
3433         return this.flush();
3434       }.bind(this));
3435       return this.running;
3436     }
3437   }
3438   /**
3439    * Clear all items in wait
3440    */
3441 
3442 
3443   clear() {
3444     this._q = [];
3445   }
3446   /**
3447    * Get the number of tasks in the queue
3448    * @return {number} tasks
3449    */
3450 
3451 
3452   length() {
3453     return this._q.length;
3454   }
3455   /**
3456    * Pause a running queue
3457    */
3458 
3459 
3460   pause() {
3461     this.paused = true;
3462   }
3463   /**
3464    * End the queue
3465    */
3466 
3467 
3468   stop() {
3469     this._q = [];
3470     this.running = false;
3471     this.paused = true;
3472   }
3473 
3474 }
3475 /**
3476  * Create a new task from a callback
3477  * @class
3478  * @private
3479  * @param {function} task
3480  * @param {array} args
3481  * @param {scope} context
3482  * @return {function} task
3483  */
3484 
3485 
3486 class Task {
3487   constructor(task, args, context) {
3488     return function () {
3489       var toApply = arguments || [];
3490       return new Promise((resolve, reject) => {
3491         var callback = function (value, err) {
3492           if (!value && err) {
3493             reject(err);
3494           } else {
3495             resolve(value);
3496           }
3497         }; // Add the callback to the arguments list
3498 
3499 
3500         toApply.push(callback); // Apply all arguments to the functions
3501 
3502         task.apply(context || this, toApply);
3503       });
3504     };
3505   }
3506 
3507 }
3508 
3509 /* harmony default export */ __webpack_exports__["a"] = (Queue);
3510 
3511 
3512 /***/ }),
3513 /* 10 */
3514 /***/ (function(module, __webpack_exports__, __webpack_require__) {
3515 
3516 "use strict";
3517 
3518 // EXTERNAL MODULE: ./node_modules/event-emitter/index.js
3519 var event_emitter = __webpack_require__(3);
3520 var event_emitter_default = /*#__PURE__*/__webpack_require__.n(event_emitter);
3521 
3522 // EXTERNAL MODULE: ./src/utils/core.js
3523 var core = __webpack_require__(0);
3524 
3525 // CONCATENATED MODULE: ./src/utils/scrolltype.js
3526 // Detect RTL scroll type
3527 // Based on https://github.com/othree/jquery.rtl-scroll-type/blob/master/src/jquery.rtl-scroll.js
3528 function scrollType() {
3529   var type = "reverse";
3530   var definer = createDefiner();
3531   document.body.appendChild(definer);
3532 
3533   if (definer.scrollLeft > 0) {
3534     type = "default";
3535   } else {
3536     if (typeof Element !== 'undefined' && Element.prototype.scrollIntoView) {
3537       definer.children[0].children[1].scrollIntoView();
3538 
3539       if (definer.scrollLeft < 0) {
3540         type = "negative";
3541       }
3542     } else {
3543       definer.scrollLeft = 1;
3544 
3545       if (definer.scrollLeft === 0) {
3546         type = "negative";
3547       }
3548     }
3549   }
3550 
3551   document.body.removeChild(definer);
3552   return type;
3553 }
3554 function createDefiner() {
3555   var definer = document.createElement('div');
3556   definer.dir = "rtl";
3557   definer.style.position = "fixed";
3558   definer.style.width = "1px";
3559   definer.style.height = "1px";
3560   definer.style.top = "0px";
3561   definer.style.left = "0px";
3562   definer.style.overflow = "hidden";
3563   var innerDiv = document.createElement('div');
3564   innerDiv.style.width = "2px";
3565   var spanA = document.createElement('span');
3566   spanA.style.width = "1px";
3567   spanA.style.display = "inline-block";
3568   var spanB = document.createElement('span');
3569   spanB.style.width = "1px";
3570   spanB.style.display = "inline-block";
3571   innerDiv.appendChild(spanA);
3572   innerDiv.appendChild(spanB);
3573   definer.appendChild(innerDiv);
3574   return definer;
3575 }
3576 // EXTERNAL MODULE: ./src/mapping.js
3577 var mapping = __webpack_require__(11);
3578 
3579 // EXTERNAL MODULE: ./src/utils/queue.js
3580 var queue = __webpack_require__(9);
3581 
3582 // EXTERNAL MODULE: ./node_modules/lodash/throttle.js
3583 var throttle = __webpack_require__(28);
3584 var throttle_default = /*#__PURE__*/__webpack_require__.n(throttle);
3585 
3586 // CONCATENATED MODULE: ./src/managers/helpers/stage.js
3587 
3588 
3589 
3590 class stage_Stage {
3591   constructor(_options) {
3592     this.settings = _options || {};
3593     this.id = "epubjs-container-" + Object(core["uuid"])();
3594     this.container = this.create(this.settings);
3595 
3596     if (this.settings.hidden) {
3597       this.wrapper = this.wrap(this.container);
3598     }
3599   }
3600   /*
3601   * Creates an element to render to.
3602   * Resizes to passed width and height or to the elements size
3603   */
3604 
3605 
3606   create(options) {
3607     let height = options.height; // !== false ? options.height : "100%";
3608 
3609     let width = options.width; // !== false ? options.width : "100%";
3610 
3611     let overflow = options.overflow || false;
3612     let axis = options.axis || "vertical";
3613     let direction = options.direction;
3614     Object(core["extend"])(this.settings, options);
3615 
3616     if (options.height && Object(core["isNumber"])(options.height)) {
3617       height = options.height + "px";
3618     }
3619 
3620     if (options.width && Object(core["isNumber"])(options.width)) {
3621       width = options.width + "px";
3622     } // Create new container element
3623 
3624 
3625     let container = document.createElement("div");
3626     container.id = this.id;
3627     container.classList.add("epub-container"); // Style Element
3628     // container.style.fontSize = "0";
3629 
3630     container.style.wordSpacing = "0";
3631     container.style.lineHeight = "0";
3632     container.style.verticalAlign = "top";
3633     container.style.position = "relative";
3634 
3635     if (axis === "horizontal") {
3636       // container.style.whiteSpace = "nowrap";
3637       container.style.display = "flex";
3638       container.style.flexDirection = "row";
3639       container.style.flexWrap = "nowrap";
3640     }
3641 
3642     if (width) {
3643       container.style.width = width;
3644     }
3645 
3646     if (height) {
3647       container.style.height = height;
3648     }
3649 
3650     if (overflow) {
3651       if (overflow === "scroll" && axis === "vertical") {
3652         container.style["overflow-y"] = overflow;
3653         container.style["overflow-x"] = "hidden";
3654       } else if (overflow === "scroll" && axis === "horizontal") {
3655         container.style["overflow-y"] = "hidden";
3656         container.style["overflow-x"] = overflow;
3657       } else {
3658         container.style["overflow"] = overflow;
3659       }
3660     }
3661 
3662     if (direction) {
3663       container.dir = direction;
3664       container.style["direction"] = direction;
3665     }
3666 
3667     if (direction && this.settings.fullsize) {
3668       document.body.style["direction"] = direction;
3669     }
3670 
3671     return container;
3672   }
3673 
3674   wrap(container) {
3675     var wrapper = document.createElement("div");
3676     wrapper.style.visibility = "hidden";
3677     wrapper.style.overflow = "hidden";
3678     wrapper.style.width = "0";
3679     wrapper.style.height = "0";
3680     wrapper.appendChild(container);
3681     return wrapper;
3682   }
3683 
3684   getElement(_element) {
3685     var element;
3686 
3687     if (Object(core["isElement"])(_element)) {
3688       element = _element;
3689     } else if (typeof _element === "string") {
3690       element = document.getElementById(_element);
3691     }
3692 
3693     if (!element) {
3694       throw new Error("Not an Element");
3695     }
3696 
3697     return element;
3698   }
3699 
3700   attachTo(what) {
3701     var element = this.getElement(what);
3702     var base;
3703 
3704     if (!element) {
3705       return;
3706     }
3707 
3708     if (this.settings.hidden) {
3709       base = this.wrapper;
3710     } else {
3711       base = this.container;
3712     }
3713 
3714     element.appendChild(base);
3715     this.element = element;
3716     return element;
3717   }
3718 
3719   getContainer() {
3720     return this.container;
3721   }
3722 
3723   onResize(func) {
3724     // Only listen to window for resize event if width and height are not fixed.
3725     // This applies if it is set to a percent or auto.
3726     if (!Object(core["isNumber"])(this.settings.width) || !Object(core["isNumber"])(this.settings.height)) {
3727       this.resizeFunc = throttle_default()(func, 50);
3728       window.addEventListener("resize", this.resizeFunc, false);
3729     }
3730   }
3731 
3732   onOrientationChange(func) {
3733     this.orientationChangeFunc = func;
3734     window.addEventListener("orientationchange", this.orientationChangeFunc, false);
3735   }
3736 
3737   size(width, height) {
3738     var bounds;
3739 
3740     let _width = width || this.settings.width;
3741 
3742     let _height = height || this.settings.height; // If width or height are set to false, inherit them from containing element
3743 
3744 
3745     if (width === null) {
3746       bounds = this.element.getBoundingClientRect();
3747 
3748       if (bounds.width) {
3749         width = Math.floor(bounds.width);
3750         this.container.style.width = width + "px";
3751       }
3752     } else {
3753       if (Object(core["isNumber"])(width)) {
3754         this.container.style.width = width + "px";
3755       } else {
3756         this.container.style.width = width;
3757       }
3758     }
3759 
3760     if (height === null) {
3761       bounds = bounds || this.element.getBoundingClientRect();
3762 
3763       if (bounds.height) {
3764         height = bounds.height;
3765         this.container.style.height = height + "px";
3766       }
3767     } else {
3768       if (Object(core["isNumber"])(height)) {
3769         this.container.style.height = height + "px";
3770       } else {
3771         this.container.style.height = height;
3772       }
3773     }
3774 
3775     if (!Object(core["isNumber"])(width)) {
3776       width = this.container.clientWidth;
3777     }
3778 
3779     if (!Object(core["isNumber"])(height)) {
3780       height = this.container.clientHeight;
3781     }
3782 
3783     this.containerStyles = window.getComputedStyle(this.container);
3784     this.containerPadding = {
3785       left: parseFloat(this.containerStyles["padding-left"]) || 0,
3786       right: parseFloat(this.containerStyles["padding-right"]) || 0,
3787       top: parseFloat(this.containerStyles["padding-top"]) || 0,
3788       bottom: parseFloat(this.containerStyles["padding-bottom"]) || 0
3789     }; // Bounds not set, get them from window
3790 
3791     let _windowBounds = Object(core["windowBounds"])();
3792 
3793     let bodyStyles = window.getComputedStyle(document.body);
3794     let bodyPadding = {
3795       left: parseFloat(bodyStyles["padding-left"]) || 0,
3796       right: parseFloat(bodyStyles["padding-right"]) || 0,
3797       top: parseFloat(bodyStyles["padding-top"]) || 0,
3798       bottom: parseFloat(bodyStyles["padding-bottom"]) || 0
3799     };
3800 
3801     //if (!_width) {
3802     //  width = _windowBounds.width - bodyPadding.left - bodyPadding.right;
3803     //}
3804 
3805     if (this.settings.fullsize && !_height || !_height) {
3806       height = _windowBounds.height - bodyPadding.top - bodyPadding.bottom;
3807     }
3808 
3809     return {
3810       width: width - this.containerPadding.left - this.containerPadding.right,
3811       height: height - this.containerPadding.top - this.containerPadding.bottom
3812     };
3813   }
3814 
3815   bounds() {
3816     let box;
3817 
3818     if (this.container.style.overflow !== "visible") {
3819       box = this.container && this.container.getBoundingClientRect();
3820     }
3821 
3822     if (!box || !box.width || !box.height) {
3823       return Object(core["windowBounds"])();
3824     } else {
3825       return box;
3826     }
3827   }
3828 
3829   getSheet() {
3830     var style = document.createElement("style"); // WebKit hack --> https://davidwalsh.name/add-rules-stylesheets
3831 
3832     style.appendChild(document.createTextNode(""));
3833     document.head.appendChild(style);
3834     return style.sheet;
3835   }
3836 
3837   addStyleRules(selector, rulesArray) {
3838     var scope = "#" + this.id + " ";
3839     var rules = "";
3840 
3841     if (!this.sheet) {
3842       this.sheet = this.getSheet();
3843     }
3844 
3845     rulesArray.forEach(function (set) {
3846       for (var prop in set) {
3847         if (set.hasOwnProperty(prop)) {
3848           rules += prop + ":" + set[prop] + ";";
3849         }
3850       }
3851     });
3852     this.sheet.insertRule(scope + selector + " {" + rules + "}", 0);
3853   }
3854 
3855   axis(axis) {
3856     if (axis === "horizontal") {
3857       this.container.style.display = "flex";
3858       this.container.style.flexDirection = "row";
3859       this.container.style.flexWrap = "nowrap";
3860     } else {
3861       this.container.style.display = "block";
3862     }
3863 
3864     this.settings.axis = axis;
3865   } // orientation(orientation) {
3866   //    if (orientation === "landscape") {
3867   //
3868   //    } else {
3869   //
3870   //    }
3871   //
3872   //    this.orientation = orientation;
3873   // }
3874 
3875 
3876   direction(dir) {
3877     if (this.container) {
3878       this.container.dir = dir;
3879       this.container.style["direction"] = dir;
3880     }
3881 
3882     if (this.settings.fullsize) {
3883       document.body.style["direction"] = dir;
3884     }
3885 
3886     this.settings.dir = dir;
3887   }
3888 
3889   overflow(overflow) {
3890     if (this.container) {
3891       if (overflow === "scroll" && this.settings.axis === "vertical") {
3892         this.container.style["overflow-y"] = overflow;
3893         this.container.style["overflow-x"] = "hidden";
3894       } else if (overflow === "scroll" && this.settings.axis === "horizontal") {
3895         this.container.style["overflow-y"] = "hidden";
3896         this.container.style["overflow-x"] = overflow;
3897       } else {
3898         this.container.style["overflow"] = overflow;
3899       }
3900     }
3901 
3902     this.settings.overflow = overflow;
3903   }
3904 
3905   destroy() {
3906     var base;
3907 
3908     if (this.element) {
3909       if (this.settings.hidden) {
3910         base = this.wrapper;
3911       } else {
3912         base = this.container;
3913       }
3914 
3915       if (this.element.contains(this.container)) {
3916         this.element.removeChild(this.container);
3917       }
3918 
3919       window.removeEventListener("resize", this.resizeFunc);
3920       window.removeEventListener("orientationChange", this.orientationChangeFunc);
3921     }
3922   }
3923 
3924 }
3925 
3926 /* harmony default export */ var stage = (stage_Stage);
3927 // CONCATENATED MODULE: ./src/managers/helpers/views.js
3928 class Views {
3929   constructor(container) {
3930     this.container = container;
3931     this._views = [];
3932     this.length = 0;
3933     this.hidden = false;
3934   }
3935 
3936   all() {
3937     return this._views;
3938   }
3939 
3940   first() {
3941     return this._views[0];
3942   }
3943 
3944   last() {
3945     return this._views[this._views.length - 1];
3946   }
3947 
3948   indexOf(view) {
3949     return this._views.indexOf(view);
3950   }
3951 
3952   slice() {
3953     return this._views.slice.apply(this._views, arguments);
3954   }
3955 
3956   get(i) {
3957     return this._views[i];
3958   }
3959 
3960   append(view) {
3961     this._views.push(view);
3962 
3963     if (this.container) {
3964       this.container.appendChild(view.element);
3965     }
3966 
3967     this.length++;
3968     return view;
3969   }
3970 
3971   prepend(view) {
3972     this._views.unshift(view);
3973 
3974     if (this.container) {
3975       this.container.insertBefore(view.element, this.container.firstChild);
3976     }
3977 
3978     this.length++;
3979     return view;
3980   }
3981 
3982   insert(view, index) {
3983     this._views.splice(index, 0, view);
3984 
3985     if (this.container) {
3986       if (index < this.container.children.length) {
3987         this.container.insertBefore(view.element, this.container.children[index]);
3988       } else {
3989         this.container.appendChild(view.element);
3990       }
3991     }
3992 
3993     this.length++;
3994     return view;
3995   }
3996 
3997   remove(view) {
3998     var index = this._views.indexOf(view);
3999 
4000     if (index > -1) {
4001       this._views.splice(index, 1);
4002     }
4003 
4004     this.destroy(view);
4005     this.length--;
4006   }
4007 
4008   destroy(view) {
4009     if (view.displayed) {
4010       view.destroy();
4011     }
4012 
4013     if (this.container) {
4014       this.container.removeChild(view.element);
4015     }
4016 
4017     view = null;
4018   } // Iterators
4019 
4020 
4021   forEach() {
4022     return this._views.forEach.apply(this._views, arguments);
4023   }
4024 
4025   clear() {
4026     // Remove all views
4027     var view;
4028     var len = this.length;
4029     if (!this.length) return;
4030 
4031     for (var i = 0; i < len; i++) {
4032       view = this._views[i];
4033       this.destroy(view);
4034     }
4035 
4036     this._views = [];
4037     this.length = 0;
4038   }
4039 
4040   find(section) {
4041     var view;
4042     var len = this.length;
4043 
4044     for (var i = 0; i < len; i++) {
4045       view = this._views[i];
4046 
4047       if (view.displayed && view.section.index == section.index) {
4048         return view;
4049       }
4050     }
4051   }
4052 
4053   displayed() {
4054     var displayed = [];
4055     var view;
4056     var len = this.length;
4057 
4058     for (var i = 0; i < len; i++) {
4059       view = this._views[i];
4060 
4061       if (view.displayed) {
4062         displayed.push(view);
4063       }
4064     }
4065 
4066     return displayed;
4067   }
4068 
4069   show() {
4070     var view;
4071     var len = this.length;
4072 
4073     for (var i = 0; i < len; i++) {
4074       view = this._views[i];
4075 
4076       if (view.displayed) {
4077         view.show();
4078       }
4079     }
4080 
4081     this.hidden = false;
4082   }
4083 
4084   hide() {
4085     var view;
4086     var len = this.length;
4087 
4088     for (var i = 0; i < len; i++) {
4089       view = this._views[i];
4090 
4091       if (view.displayed) {
4092         view.hide();
4093       }
4094     }
4095 
4096     this.hidden = true;
4097   }
4098 
4099 }
4100 
4101 /* harmony default export */ var views = (Views);
4102 // EXTERNAL MODULE: ./src/utils/constants.js
4103 var constants = __webpack_require__(1);
4104 
4105 // CONCATENATED MODULE: ./src/managers/default/index.js
4106 
4107 
4108 
4109 
4110 
4111 
4112 
4113 
4114 
4115 class default_DefaultViewManager {
4116   constructor(options) {
4117     this.name = "default";
4118     this.optsSettings = options.settings;
4119     this.View = options.view;
4120     this.request = options.request;
4121     this.renditionQueue = options.queue;
4122     this.q = new queue["a" /* default */](this);
4123     this.settings = Object(core["extend"])(this.settings || {}, {
4124       infinite: true,
4125       hidden: false,
4126       width: undefined,
4127       height: undefined,
4128       axis: undefined,
4129       writingMode: undefined,
4130       flow: "scrolled",
4131       ignoreClass: "",
4132       fullsize: undefined,
4133       allowScriptedContent: false,
4134       allowPopups: false
4135     });
4136     Object(core["extend"])(this.settings, options.settings || {});
4137     this.viewSettings = {
4138       ignoreClass: this.settings.ignoreClass,
4139       axis: this.settings.axis,
4140       flow: this.settings.flow,
4141       layout: this.layout,
4142       method: this.settings.method,
4143       // srcdoc, blobUrl, write
4144       width: 0,
4145       height: 0,
4146       forceEvenPages: true,
4147       allowScriptedContent: this.settings.allowScriptedContent,
4148       allowPopups: this.settings.allowPopups
4149     };
4150     this.rendered = false;
4151   }
4152 
4153   render(element, size) {
4154     let tag = element.tagName;
4155 
4156     if (typeof this.settings.fullsize === "undefined" && tag && (tag.toLowerCase() == "body" || tag.toLowerCase() == "html")) {
4157       this.settings.fullsize = true;
4158     }
4159 
4160     if (this.settings.fullsize) {
4161       this.settings.overflow = "visible";
4162       this.overflow = this.settings.overflow;
4163     }
4164 
4165     this.settings.size = size;
4166     this.settings.rtlScrollType = scrollType(); // Save the stage
4167 
4168     this.stage = new stage({
4169       width: size.width,
4170       height: size.height,
4171       overflow: this.overflow,
4172       hidden: this.settings.hidden,
4173       axis: this.settings.axis,
4174       fullsize: this.settings.fullsize,
4175       direction: this.settings.direction
4176     });
4177     this.stage.attachTo(element); // Get this stage container div
4178 
4179     this.container = this.stage.getContainer(); // Views array methods
4180 
4181     this.views = new views(this.container); // Calculate Stage Size
4182 
4183     this._bounds = this.bounds();
4184     this._stageSize = this.stage.size(); // Set the dimensions for views
4185 
4186     this.viewSettings.width = this._stageSize.width;
4187     this.viewSettings.height = this._stageSize.height; // Function to handle a resize event.
4188     // Will only attach if width and height are both fixed.
4189 
4190     this.stage.onResize(this.onResized.bind(this));
4191     this.stage.onOrientationChange(this.onOrientationChange.bind(this)); // Add Event Listeners
4192 
4193     this.addEventListeners(); // Add Layout method
4194     // this.applyLayoutMethod();
4195 
4196     if (this.layout) {
4197       this.updateLayout();
4198     }
4199 
4200     this.rendered = true;
4201   }
4202 
4203   addEventListeners() {
4204     var scroller;
4205     window.addEventListener("unload", function (e) {
4206       this.destroy();
4207     }.bind(this));
4208 
4209     if (!this.settings.fullsize) {
4210       scroller = this.container;
4211     } else {
4212       scroller = window;
4213     }
4214 
4215     this._onScroll = this.onScroll.bind(this);
4216     scroller.addEventListener("scroll", this._onScroll);
4217   }
4218 
4219   removeEventListeners() {
4220     var scroller;
4221 
4222     if (!this.settings.fullsize) {
4223       scroller = this.container;
4224     } else {
4225       scroller = window;
4226     }
4227 
4228     scroller.removeEventListener("scroll", this._onScroll);
4229     this._onScroll = undefined;
4230   }
4231 
4232   destroy() {
4233     clearTimeout(this.orientationTimeout);
4234     clearTimeout(this.resizeTimeout);
4235     clearTimeout(this.afterScrolled);
4236     this.clear();
4237     this.removeEventListeners();
4238     this.stage.destroy();
4239     this.rendered = false;
4240     /*
4241                 clearTimeout(this.trimTimeout);
4242         if(this.settings.hidden) {
4243                 this.element.removeChild(this.wrapper);
4244         } else {
4245                 this.element.removeChild(this.container);
4246         }
4247     */
4248   }
4249 
4250   onOrientationChange(e) {
4251     let {
4252       orientation
4253     } = window;
4254 
4255     if (this.optsSettings.resizeOnOrientationChange) {
4256       this.resize();
4257     } // Per ampproject:
4258     // In IOS 10.3, the measured size of an element is incorrect if the
4259     // element size depends on window size directly and the measurement
4260     // happens in window.resize event. Adding a timeout for correct
4261     // measurement. See https://github.com/ampproject/amphtml/issues/8479
4262 
4263 
4264     clearTimeout(this.orientationTimeout);
4265     this.orientationTimeout = setTimeout(function () {
4266       this.orientationTimeout = undefined;
4267 
4268       if (this.optsSettings.resizeOnOrientationChange) {
4269         this.resize();
4270       }
4271 
4272       this.emit(constants["c" /* EVENTS */].MANAGERS.ORIENTATION_CHANGE, orientation);
4273     }.bind(this), 500);
4274   }
4275 
4276   onResized(e) {
4277     this.resize();
4278   }
4279 
4280   resize(width, height, epubcfi) {
4281     let stageSize = this.stage.size(width, height); // For Safari, wait for orientation to catch up
4282     // if the window is a square
4283 
4284     this.winBounds = Object(core["windowBounds"])();
4285 
4286     if (this.orientationTimeout && this.winBounds.width === this.winBounds.height) {
4287       // reset the stage size for next resize
4288       this._stageSize = undefined;
4289       return;
4290     }
4291 
4292     if (this._stageSize && this._stageSize.width === stageSize.width && this._stageSize.height === stageSize.height) {
4293       // Size is the same, no need to resize
4294       return;
4295     }
4296 
4297     this._stageSize = stageSize;
4298     this._bounds = this.bounds(); // Clear current views
4299 
4300     this.clear(); // Update for new views
4301 
4302     this.viewSettings.width = this._stageSize.width;
4303     this.viewSettings.height = this._stageSize.height;
4304     this.updateLayout();
4305     this.emit(constants["c" /* EVENTS */].MANAGERS.RESIZED, {
4306       width: this._stageSize.width,
4307       height: this._stageSize.height
4308     }, epubcfi);
4309   }
4310 
4311   createView(section, forceRight) {
4312     return new this.View(section, Object(core["extend"])(this.viewSettings, {
4313       forceRight
4314     }));
4315   }
4316 
4317   handleNextPrePaginated(forceRight, section, action) {
4318     let next;
4319 
4320     if (this.layout.name === "pre-paginated" && this.layout.divisor > 1) {
4321       if (forceRight || section.index === 0) {
4322         // First page (cover) should stand alone for pre-paginated books
4323         return;
4324       }
4325 
4326       next = section.next();
4327 
4328       if (next && !next.properties.includes("page-spread-left")) {
4329         return action.call(this, next);
4330       }
4331     }
4332   }
4333 
4334   display(section, target) {
4335     var displaying = new core["defer"]();
4336     var displayed = displaying.promise; // Check if moving to target is needed
4337 
4338     if (target === section.href || Object(core["isNumber"])(target)) {
4339       target = undefined;
4340     } // Check to make sure the section we want isn't already shown
4341 
4342 
4343     var visible = this.views.find(section); // View is already shown, just move to correct location in view
4344 
4345     if (visible && section && this.layout.name !== "pre-paginated") {
4346       let offset = visible.offset();
4347 
4348       if (this.settings.direction === "ltr") {
4349         this.scrollTo(offset.left, offset.top, true);
4350       } else {
4351         let width = visible.width();
4352         this.scrollTo(offset.left + width, offset.top, true);
4353       }
4354 
4355       if (target) {
4356         let offset = visible.locationOf(target);
4357         let width = visible.width();
4358         this.moveTo(offset, width);
4359       }
4360 
4361       displaying.resolve();
4362       return displayed;
4363     } // Hide all current views
4364 
4365 
4366     this.clear();
4367     let forceRight = false;
4368 
4369     if (this.layout.name === "pre-paginated" && this.layout.divisor === 2 && section.properties.includes("page-spread-right")) {
4370       forceRight = true;
4371     }
4372 
4373     this.add(section, forceRight).then(function (view) {
4374       // Move to correct place within the section, if needed
4375       if (target) {
4376         let offset = view.locationOf(target);
4377         let width = view.width();
4378         this.moveTo(offset, width);
4379       }
4380     }.bind(this), err => {
4381       displaying.reject(err);
4382     }).then(function () {
4383       return this.handleNextPrePaginated(forceRight, section, this.add);
4384     }.bind(this)).then(function () {
4385       this.views.show();
4386       displaying.resolve();
4387     }.bind(this)); // .then(function(){
4388     //  return this.hooks.display.trigger(view);
4389     // }.bind(this))
4390     // .then(function(){
4391     //  this.views.show();
4392     // }.bind(this));
4393 
4394     return displayed;
4395   }
4396 
4397   afterDisplayed(view) {
4398     this.emit(constants["c" /* EVENTS */].MANAGERS.ADDED, view);
4399   }
4400 
4401   afterResized(view) {
4402     this.emit(constants["c" /* EVENTS */].MANAGERS.RESIZE, view.section);
4403   }
4404 
4405   moveTo(offset, width) {
4406     var distX = 0,
4407         distY = 0;
4408 
4409     if (!this.isPaginated) {
4410       distY = offset.top;
4411     } else {
4412       distX = Math.floor(offset.left / this.layout.delta) * this.layout.delta;
4413 
4414       if (distX + this.layout.delta > this.container.scrollWidth) {
4415         distX = this.container.scrollWidth - this.layout.delta;
4416       }
4417 
4418       distY = Math.floor(offset.top / this.layout.delta) * this.layout.delta;
4419 
4420       if (distY + this.layout.delta > this.container.scrollHeight) {
4421         distY = this.container.scrollHeight - this.layout.delta;
4422       }
4423     }
4424 
4425     if (this.settings.direction === 'rtl') {
4426       /***
4427         the `floor` function above (L343) is on positive values, so we should add one `layout.delta`
4428         to distX or use `Math.ceil` function, or multiply offset.left by -1
4429         before `Math.floor`
4430       */
4431       distX = distX + this.layout.delta;
4432       distX = distX - width;
4433     }
4434 
4435     this.scrollTo(distX, distY, true);
4436   }
4437 
4438   add(section, forceRight) {
4439     var view = this.createView(section, forceRight);
4440     this.views.append(view); // view.on(EVENTS.VIEWS.SHOWN, this.afterDisplayed.bind(this));
4441 
4442     view.onDisplayed = this.afterDisplayed.bind(this);
4443     view.onResize = this.afterResized.bind(this);
4444     view.on(constants["c" /* EVENTS */].VIEWS.AXIS, axis => {
4445       this.updateAxis(axis);
4446     });
4447     view.on(constants["c" /* EVENTS */].VIEWS.WRITING_MODE, mode => {
4448       this.updateWritingMode(mode);
4449     });
4450     return view.display(this.request);
4451   }
4452 
4453   append(section, forceRight) {
4454     var view = this.createView(section, forceRight);
4455     this.views.append(view);
4456     view.onDisplayed = this.afterDisplayed.bind(this);
4457     view.onResize = this.afterResized.bind(this);
4458     view.on(constants["c" /* EVENTS */].VIEWS.AXIS, axis => {
4459       this.updateAxis(axis);
4460     });
4461     view.on(constants["c" /* EVENTS */].VIEWS.WRITING_MODE, mode => {
4462       this.updateWritingMode(mode);
4463     });
4464     return view.display(this.request);
4465   }
4466 
4467   prepend(section, forceRight) {
4468     var view = this.createView(section, forceRight);
4469     view.on(constants["c" /* EVENTS */].VIEWS.RESIZED, bounds => {
4470       this.counter(bounds);
4471     });
4472     this.views.prepend(view);
4473     view.onDisplayed = this.afterDisplayed.bind(this);
4474     view.onResize = this.afterResized.bind(this);
4475     view.on(constants["c" /* EVENTS */].VIEWS.AXIS, axis => {
4476       this.updateAxis(axis);
4477     });
4478     view.on(constants["c" /* EVENTS */].VIEWS.WRITING_MODE, mode => {
4479       this.updateWritingMode(mode);
4480     });
4481     return view.display(this.request);
4482   }
4483 
4484   counter(bounds) {
4485     if (this.settings.axis === "vertical") {
4486       this.scrollBy(0, bounds.heightDelta, true);
4487     } else {
4488       this.scrollBy(bounds.widthDelta, 0, true);
4489     }
4490   } // resizeView(view) {
4491   //
4492   //    if(this.settings.globalLayoutProperties.layout === "pre-paginated") {
4493   //            view.lock("both", this.bounds.width, this.bounds.height);
4494   //    } else {
4495   //            view.lock("width", this.bounds.width, this.bounds.height);
4496   //    }
4497   //
4498   // };
4499 
4500 
4501   next() {
4502     var next;
4503     var left;
4504     let dir = this.settings.direction;
4505     if (!this.views.length) return;
4506 
4507     if (this.isPaginated && this.settings.axis === "horizontal" && (!dir || dir === "ltr")) {
4508       this.scrollLeft = this.container.scrollLeft;
4509       left = this.container.scrollLeft + this.container.offsetWidth + this.layout.delta;
4510 
4511       if (left <= this.container.scrollWidth) {
4512         this.scrollBy(this.layout.delta, 0, true);
4513       } else {
4514         next = this.views.last().section.next();
4515       }
4516     } else if (this.isPaginated && this.settings.axis === "horizontal" && dir === "rtl") {
4517       this.scrollLeft = this.container.scrollLeft;
4518 
4519       if (this.settings.rtlScrollType === "default") {
4520         left = this.container.scrollLeft;
4521 
4522         if (left > 0) {
4523           this.scrollBy(this.layout.delta, 0, true);
4524         } else {
4525           next = this.views.last().section.next();
4526         }
4527       } else {
4528         left = this.container.scrollLeft + this.layout.delta * -1;
4529 
4530         if (left > this.container.scrollWidth * -1) {
4531           this.scrollBy(this.layout.delta, 0, true);
4532         } else {
4533           next = this.views.last().section.next();
4534         }
4535       }
4536     } else if (this.isPaginated && this.settings.axis === "vertical") {
4537       this.scrollTop = this.container.scrollTop;
4538       let top = this.container.scrollTop + this.container.offsetHeight;
4539 
4540       if (top < this.container.scrollHeight) {
4541         this.scrollBy(0, this.layout.height, true);
4542       } else {
4543         next = this.views.last().section.next();
4544       }
4545     } else {
4546       next = this.views.last().section.next();
4547     }
4548 
4549     if (next) {
4550       this.clear(); // The new section may have a different writing-mode from the old section. Thus, we need to update layout.
4551 
4552       this.updateLayout();
4553       let forceRight = false;
4554 
4555       if (this.layout.name === "pre-paginated" && this.layout.divisor === 2 && next.properties.includes("page-spread-right")) {
4556         forceRight = true;
4557       }
4558 
4559       return this.append(next, forceRight).then(function () {
4560         return this.handleNextPrePaginated(forceRight, next, this.append);
4561       }.bind(this), err => {
4562         return err;
4563       }).then(function () {
4564         // Reset position to start for scrolled-doc vertical-rl in default mode
4565         if (!this.isPaginated && this.settings.axis === "horizontal" && this.settings.direction === "rtl" && this.settings.rtlScrollType === "default") {
4566           this.scrollTo(this.container.scrollWidth, 0, true);
4567         }
4568 
4569         this.views.show();
4570       }.bind(this));
4571     }
4572   }
4573 
4574   prev() {
4575     var prev;
4576     var left;
4577     let dir = this.settings.direction;
4578     if (!this.views.length) return;
4579 
4580     if (this.isPaginated && this.settings.axis === "horizontal" && (!dir || dir === "ltr")) {
4581       this.scrollLeft = this.container.scrollLeft;
4582       left = this.container.scrollLeft;
4583 
4584       if (left > 0) {
4585         this.scrollBy(-this.layout.delta, 0, true);
4586       } else {
4587         prev = this.views.first().section.prev();
4588       }
4589     } else if (this.isPaginated && this.settings.axis === "horizontal" && dir === "rtl") {
4590       this.scrollLeft = this.container.scrollLeft;
4591 
4592       if (this.settings.rtlScrollType === "default") {
4593         left = this.container.scrollLeft + this.container.offsetWidth;
4594 
4595         if (left < this.container.scrollWidth) {
4596           this.scrollBy(-this.layout.delta, 0, true);
4597         } else {
4598           prev = this.views.first().section.prev();
4599         }
4600       } else {
4601         left = this.container.scrollLeft;
4602 
4603         if (left < 0) {
4604           this.scrollBy(-this.layout.delta, 0, true);
4605         } else {
4606           prev = this.views.first().section.prev();
4607         }
4608       }
4609     } else if (this.isPaginated && this.settings.axis === "vertical") {
4610       this.scrollTop = this.container.scrollTop;
4611       let top = this.container.scrollTop;
4612 
4613       if (top > 0) {
4614         this.scrollBy(0, -this.layout.height, true);
4615       } else {
4616         prev = this.views.first().section.prev();
4617       }
4618     } else {
4619       prev = this.views.first().section.prev();
4620     }
4621 
4622     if (prev) {
4623       this.clear(); // The new section may have a different writing-mode from the old section. Thus, we need to update layout.
4624 
4625       this.updateLayout();
4626       let forceRight = false;
4627 
4628       if (this.layout.name === "pre-paginated" && this.layout.divisor === 2 && typeof prev.prev() !== "object") {
4629         forceRight = true;
4630       }
4631 
4632       return this.prepend(prev, forceRight).then(function () {
4633         var left;
4634 
4635         if (this.layout.name === "pre-paginated" && this.layout.divisor > 1) {
4636           left = prev.prev();
4637 
4638           if (left) {
4639             return this.prepend(left);
4640           }
4641         }
4642       }.bind(this), err => {
4643         return err;
4644       }).then(function () {
4645         if (this.isPaginated && this.settings.axis === "horizontal") {
4646           if (this.settings.direction === "rtl") {
4647             if (this.settings.rtlScrollType === "default") {
4648               this.scrollTo(0, 0, true);
4649             } else {
4650               this.scrollTo(this.container.scrollWidth * -1 + this.layout.delta, 0, true);
4651             }
4652           } else {
4653             this.scrollTo(this.container.scrollWidth - this.layout.delta, 0, true);
4654           }
4655         }
4656 
4657         this.views.show();
4658       }.bind(this));
4659     }
4660   }
4661 
4662   current() {
4663     var visible = this.visible();
4664 
4665     if (visible.length) {
4666       // Current is the last visible view
4667       return visible[visible.length - 1];
4668     }
4669 
4670     return null;
4671   }
4672 
4673   clear() {
4674     // this.q.clear();
4675     if (this.views) {
4676       this.views.hide();
4677       this.scrollTo(0, 0, true);
4678       this.views.clear();
4679     }
4680   }
4681 
4682   currentLocation() {
4683     this.updateLayout();
4684 
4685     if (this.isPaginated && this.settings.axis === "horizontal") {
4686       this.location = this.paginatedLocation();
4687     } else {
4688       this.location = this.scrolledLocation();
4689     }
4690 
4691     return this.location;
4692   }
4693 
4694   scrolledLocation() {
4695     let visible = this.visible();
4696     let container = this.container.getBoundingClientRect();
4697     let pageHeight = container.height < window.innerHeight ? container.height : window.innerHeight;
4698     let pageWidth = container.width < window.innerWidth ? container.width : window.innerWidth;
4699     let vertical = this.settings.axis === "vertical";
4700     let rtl = this.settings.direction === "rtl";
4701     let offset = 0;
4702     let used = 0;
4703 
4704     if (this.settings.fullsize) {
4705       offset = vertical ? window.scrollY : window.scrollX;
4706     }
4707 
4708     let sections = visible.map(view => {
4709       let {
4710         index,
4711         href
4712       } = view.section;
4713       let position = view.position();
4714       let width = view.width();
4715       let height = view.height();
4716       let startPos;
4717       let endPos;
4718       let stopPos;
4719       let totalPages;
4720 
4721       if (vertical) {
4722         startPos = offset + container.top - position.top + used;
4723         endPos = startPos + pageHeight - used;
4724         totalPages = this.layout.count(height, pageHeight).pages;
4725         stopPos = pageHeight;
4726       } else {
4727         startPos = offset + container.left - position.left + used;
4728         endPos = startPos + pageWidth - used;
4729         totalPages = this.layout.count(width, pageWidth).pages;
4730         stopPos = pageWidth;
4731       }
4732 
4733       let currPage = Math.ceil(startPos / stopPos);
4734       let pages = [];
4735       let endPage = Math.ceil(endPos / stopPos); // Reverse page counts for horizontal rtl
4736 
4737       if (this.settings.direction === "rtl" && !vertical) {
4738         let tempStartPage = currPage;
4739         currPage = totalPages - endPage;
4740         endPage = totalPages - tempStartPage;
4741       }
4742 
4743       pages = [];
4744 
4745       for (var i = currPage; i <= endPage; i++) {
4746         let pg = i + 1;
4747         pages.push(pg);
4748       }
4749 
4750       let mapping = this.mapping.page(view.contents, view.section.cfiBase, startPos, endPos);
4751       return {
4752         index,
4753         href,
4754         pages,
4755         totalPages,
4756         mapping
4757       };
4758     });
4759     return sections;
4760   }
4761 
4762   paginatedLocation() {
4763     let visible = this.visible();
4764     let container = this.container.getBoundingClientRect();
4765     let left = 0;
4766     let used = 0;
4767 
4768     if (this.settings.fullsize) {
4769       left = window.scrollX;
4770     }
4771 
4772     let sections = visible.map(view => {
4773       let {
4774         index,
4775         href
4776       } = view.section;
4777       let offset;
4778       let position = view.position();
4779       let width = view.width(); // Find mapping
4780 
4781       let start;
4782       let end;
4783       let pageWidth;
4784 
4785       if (this.settings.direction === "rtl") {
4786         offset = container.right - left;
4787         pageWidth = Math.min(Math.abs(offset - position.left), this.layout.width) - used;
4788         end = position.width - (position.right - offset) - used;
4789         start = end - pageWidth;
4790       } else {
4791         offset = container.left + left;
4792         pageWidth = Math.min(position.right - offset, this.layout.width) - used;
4793         start = offset - position.left + used;
4794         end = start + pageWidth;
4795       }
4796 
4797       used += pageWidth;
4798       let mapping = this.mapping.page(view.contents, view.section.cfiBase, start, end);
4799       let totalPages = this.layout.count(width).pages;
4800       let startPage = Math.floor(start / this.layout.pageWidth);
4801       let pages = [];
4802       let endPage = Math.floor(end / this.layout.pageWidth); // start page should not be negative
4803 
4804       if (startPage < 0) {
4805         startPage = 0;
4806         endPage = endPage + 1;
4807       } // Reverse page counts for rtl
4808 
4809 
4810       if (this.settings.direction === "rtl") {
4811         let tempStartPage = startPage;
4812         startPage = totalPages - endPage;
4813         endPage = totalPages - tempStartPage;
4814       }
4815 
4816       for (var i = startPage + 1; i <= endPage; i++) {
4817         let pg = i;
4818         pages.push(pg);
4819       }
4820 
4821       return {
4822         index,
4823         href,
4824         pages,
4825         totalPages,
4826         mapping
4827       };
4828     });
4829     return sections;
4830   }
4831 
4832   isVisible(view, offsetPrev, offsetNext, _container) {
4833     var position = view.position();
4834 
4835     var container = _container || this.bounds();
4836 
4837     if (this.settings.axis === "horizontal" && position.right > container.left - offsetPrev && position.left < container.right + offsetNext) {
4838       return true;
4839     } else if (this.settings.axis === "vertical" && position.bottom > container.top - offsetPrev && position.top < container.bottom + offsetNext) {
4840       return true;
4841     }
4842 
4843     return false;
4844   }
4845 
4846   visible() {
4847     var container = this.bounds();
4848     var views = this.views.displayed();
4849     var viewsLength = views.length;
4850     var visible = [];
4851     var isVisible;
4852     var view;
4853 
4854     for (var i = 0; i < viewsLength; i++) {
4855       view = views[i];
4856       isVisible = this.isVisible(view, 0, 0, container);
4857 
4858       if (isVisible === true) {
4859         visible.push(view);
4860       }
4861     }
4862 
4863     return visible;
4864   }
4865 
4866   scrollBy(x, y, silent) {
4867     let dir = this.settings.direction === "rtl" ? -1 : 1;
4868 
4869     if (silent) {
4870       this.ignore = true;
4871     }
4872 
4873     if (!this.settings.fullsize) {
4874       if (x) this.container.scrollLeft += x * dir;
4875       if (y) this.container.scrollTop += y;
4876     } else {
4877       window.scrollBy(x * dir, y * dir);
4878     }
4879 
4880     this.scrolled = true;
4881   }
4882 
4883   scrollTo(x, y, silent) {
4884     if (silent) {
4885       this.ignore = true;
4886     }
4887 
4888     if (!this.settings.fullsize) {
4889       this.container.scrollLeft = x;
4890       this.container.scrollTop = y;
4891     } else {
4892       window.scrollTo(x, y);
4893     }
4894 
4895     this.scrolled = true;
4896   }
4897 
4898   onScroll() {
4899     let scrollTop;
4900     let scrollLeft;
4901 
4902     if (!this.settings.fullsize) {
4903       scrollTop = this.container.scrollTop;
4904       scrollLeft = this.container.scrollLeft;
4905     } else {
4906       scrollTop = window.scrollY;
4907       scrollLeft = window.scrollX;
4908     }
4909 
4910     this.scrollTop = scrollTop;
4911     this.scrollLeft = scrollLeft;
4912 
4913     if (!this.ignore) {
4914       this.emit(constants["c" /* EVENTS */].MANAGERS.SCROLL, {
4915         top: scrollTop,
4916         left: scrollLeft
4917       });
4918       clearTimeout(this.afterScrolled);
4919       this.afterScrolled = setTimeout(function () {
4920         this.emit(constants["c" /* EVENTS */].MANAGERS.SCROLLED, {
4921           top: this.scrollTop,
4922           left: this.scrollLeft
4923         });
4924       }.bind(this), 20);
4925     } else {
4926       this.ignore = false;
4927     }
4928   }
4929 
4930   bounds() {
4931     var bounds;
4932     bounds = this.stage.bounds();
4933     return bounds;
4934   }
4935 
4936   applyLayout(layout) {
4937     this.layout = layout;
4938     this.updateLayout();
4939 
4940     if (this.views && this.views.length > 0 && this.layout.name === "pre-paginated") {
4941       this.display(this.views.first().section);
4942     } // this.manager.layout(this.layout.format);
4943 
4944   }
4945 
4946   updateLayout() {
4947     if (!this.stage) {
4948       return;
4949     }
4950 
4951     this._stageSize = this.stage.size();
4952 
4953     if (!this.isPaginated) {
4954       this.layout.calculate(this._stageSize.width, this._stageSize.height);
4955     } else {
4956       this.layout.calculate(this._stageSize.width, this._stageSize.height, this.settings.gap); // Set the look ahead offset for what is visible
4957 
4958       this.settings.offset = this.layout.delta / this.layout.divisor; // this.stage.addStyleRules("iframe", [{"margin-right" : this.layout.gap + "px"}]);
4959     } // Set the dimensions for views
4960 
4961 
4962     this.viewSettings.width = this.layout.width;
4963     this.viewSettings.height = this.layout.height;
4964     this.setLayout(this.layout);
4965   }
4966 
4967   setLayout(layout) {
4968     this.viewSettings.layout = layout;
4969     this.mapping = new mapping["a" /* default */](layout.props, this.settings.direction, this.settings.axis);
4970 
4971     if (this.views) {
4972       this.views.forEach(function (view) {
4973         if (view) {
4974           view.setLayout(layout);
4975         }
4976       });
4977     }
4978   }
4979 
4980   updateWritingMode(mode) {
4981     this.writingMode = mode;
4982   }
4983 
4984   updateAxis(axis, forceUpdate) {
4985     if (!forceUpdate && axis === this.settings.axis) {
4986       return;
4987     }
4988 
4989     this.settings.axis = axis;
4990     this.stage && this.stage.axis(axis);
4991     this.viewSettings.axis = axis;
4992 
4993     if (this.mapping) {
4994       this.mapping = new mapping["a" /* default */](this.layout.props, this.settings.direction, this.settings.axis);
4995     }
4996 
4997     if (this.layout) {
4998       if (axis === "vertical") {
4999         this.layout.spread("none");
5000       } else {
5001         this.layout.spread(this.layout.settings.spread);
5002       }
5003     }
5004   }
5005 
5006   updateFlow(flow, defaultScrolledOverflow = "auto") {
5007     let isPaginated = flow === "paginated" || flow === "auto";
5008     this.isPaginated = isPaginated;
5009 
5010     if (flow === "scrolled-doc" || flow === "scrolled-continuous" || flow === "scrolled") {
5011       this.updateAxis("vertical");
5012     } else {
5013       this.updateAxis("horizontal");
5014     }
5015 
5016     this.viewSettings.flow = flow;
5017 
5018     if (!this.settings.overflow) {
5019       this.overflow = isPaginated ? "hidden" : defaultScrolledOverflow;
5020     } else {
5021       this.overflow = this.settings.overflow;
5022     }
5023 
5024     this.stage && this.stage.overflow(this.overflow);
5025     this.updateLayout();
5026   }
5027 
5028   getContents() {
5029     var contents = [];
5030 
5031     if (!this.views) {
5032       return contents;
5033     }
5034 
5035     this.views.forEach(function (view) {
5036       const viewContents = view && view.contents;
5037 
5038       if (viewContents) {
5039         contents.push(viewContents);
5040       }
5041     });
5042     return contents;
5043   }
5044 
5045   direction(dir = "ltr") {
5046     this.settings.direction = dir;
5047     this.stage && this.stage.direction(dir);
5048     this.viewSettings.direction = dir;
5049     this.updateLayout();
5050   }
5051 
5052   isRendered() {
5053     return this.rendered;
5054   }
5055 
5056 } //-- Enable binding events to Manager
5057 
5058 
5059 event_emitter_default()(default_DefaultViewManager.prototype);
5060 /* harmony default export */ var managers_default = __webpack_exports__["a"] = (default_DefaultViewManager);
5061 
5062 /***/ }),
5063 /* 11 */
5064 /***/ (function(module, __webpack_exports__, __webpack_require__) {
5065 
5066 "use strict";
5067 /* harmony import */ var _epubcfi__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2);
5068 /* harmony import */ var _utils_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(0);
5069 
5070 
5071 /**
5072  * Map text locations to CFI ranges
5073  * @class
5074  * @param {Layout} layout Layout to apply
5075  * @param {string} [direction="ltr"] Text direction
5076  * @param {string} [axis="horizontal"] vertical or horizontal axis
5077  * @param {boolean} [dev] toggle developer highlighting
5078  */
5079 
5080 class Mapping {
5081   constructor(layout, direction, axis, dev = false) {
5082     this.layout = layout;
5083     this.horizontal = axis === "horizontal" ? true : false;
5084     this.direction = direction || "ltr";
5085     this._dev = dev;
5086   }
5087   /**
5088    * Find CFI pairs for entire section at once
5089    */
5090 
5091 
5092   section(view) {
5093     var ranges = this.findRanges(view);
5094     var map = this.rangeListToCfiList(view.section.cfiBase, ranges);
5095     return map;
5096   }
5097   /**
5098    * Find CFI pairs for a page
5099    * @param {Contents} contents Contents from view
5100    * @param {string} cfiBase string of the base for a cfi
5101    * @param {number} start position to start at
5102    * @param {number} end position to end at
5103    */
5104 
5105 
5106   page(contents, cfiBase, start, end) {
5107     var root = contents && contents.document ? contents.document.body : false;
5108     var result;
5109 
5110     if (!root) {
5111       return;
5112     }
5113 
5114     result = this.rangePairToCfiPair(cfiBase, {
5115       start: this.findStart(root, start, end),
5116       end: this.findEnd(root, start, end)
5117     });
5118 
5119     if (this._dev === true) {
5120       let doc = contents.document;
5121       let startRange = new _epubcfi__WEBPACK_IMPORTED_MODULE_0__[/* default */ "a"](result.start).toRange(doc);
5122       let endRange = new _epubcfi__WEBPACK_IMPORTED_MODULE_0__[/* default */ "a"](result.end).toRange(doc);
5123       let selection = doc.defaultView.getSelection();
5124       let r = doc.createRange();
5125       selection.removeAllRanges();
5126       r.setStart(startRange.startContainer, startRange.startOffset);
5127       r.setEnd(endRange.endContainer, endRange.endOffset);
5128       selection.addRange(r);
5129     }
5130 
5131     return result;
5132   }
5133   /**
5134    * Walk a node, preforming a function on each node it finds
5135    * @private
5136    * @param {Node} root Node to walkToNode
5137    * @param {function} func walk function
5138    * @return {*} returns the result of the walk function
5139    */
5140 
5141 
5142   walk(root, func) {
5143     // IE11 has strange issue, if root is text node IE throws exception on
5144     // calling treeWalker.nextNode(), saying
5145     // Unexpected call to method or property access instead of returning null value
5146     if (root && root.nodeType === Node.TEXT_NODE) {
5147       return;
5148     } // safeFilter is required so that it can work in IE as filter is a function for IE
5149     // and for other browser filter is an object.
5150 
5151 
5152     var filter = {
5153       acceptNode: function (node) {
5154         if (node.data.trim().length > 0) {
5155           return NodeFilter.FILTER_ACCEPT;
5156         } else {
5157           return NodeFilter.FILTER_REJECT;
5158         }
5159       }
5160     };
5161     var safeFilter = filter.acceptNode;
5162     safeFilter.acceptNode = filter.acceptNode;
5163     var treeWalker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT, safeFilter, false);
5164     var node;
5165     var result;
5166 
5167     while (node = treeWalker.nextNode()) {
5168       result = func(node);
5169       if (result) break;
5170     }
5171 
5172     return result;
5173   }
5174 
5175   findRanges(view) {
5176     var columns = [];
5177     var scrollWidth = view.contents.scrollWidth();
5178     var spreads = Math.ceil(scrollWidth / this.layout.spreadWidth);
5179     var count = spreads * this.layout.divisor;
5180     var columnWidth = this.layout.columnWidth;
5181     var gap = this.layout.gap;
5182     var start, end;
5183 
5184     for (var i = 0; i < count.pages; i++) {
5185       start = (columnWidth + gap) * i;
5186       end = columnWidth * (i + 1) + gap * i;
5187       columns.push({
5188         start: this.findStart(view.document.body, start, end),
5189         end: this.findEnd(view.document.body, start, end)
5190       });
5191     }
5192 
5193     return columns;
5194   }
5195   /**
5196    * Find Start Range
5197    * @private
5198    * @param {Node} root root node
5199    * @param {number} start position to start at
5200    * @param {number} end position to end at
5201    * @return {Range}
5202    */
5203 
5204 
5205   findStart(root, start, end) {
5206     var stack = [root];
5207     var $el;
5208     var found;
5209     var $prev = root;
5210 
5211     while (stack.length) {
5212       $el = stack.shift();
5213       found = this.walk($el, node => {
5214         var left, right, top, bottom;
5215         var elPos;
5216         var elRange;
5217         elPos = Object(_utils_core__WEBPACK_IMPORTED_MODULE_1__["nodeBounds"])(node);
5218 
5219         if (this.horizontal && this.direction === "ltr") {
5220           left = this.horizontal ? elPos.left : elPos.top;
5221           right = this.horizontal ? elPos.right : elPos.bottom;
5222 
5223           if (left >= start && left <= end) {
5224             return node;
5225           } else if (right > start) {
5226             return node;
5227           } else {
5228             $prev = node;
5229             stack.push(node);
5230           }
5231         } else if (this.horizontal && this.direction === "rtl") {
5232           left = elPos.left;
5233           right = elPos.right;
5234 
5235           if (right <= end && right >= start) {
5236             return node;
5237           } else if (left < end) {
5238             return node;
5239           } else {
5240             $prev = node;
5241             stack.push(node);
5242           }
5243         } else {
5244           top = elPos.top;
5245           bottom = elPos.bottom;
5246 
5247           if (top >= start && top <= end) {
5248             return node;
5249           } else if (bottom > start) {
5250             return node;
5251           } else {
5252             $prev = node;
5253             stack.push(node);
5254           }
5255         }
5256       });
5257 
5258       if (found) {
5259         return this.findTextStartRange(found, start, end);
5260       }
5261     } // Return last element
5262 
5263 
5264     return this.findTextStartRange($prev, start, end);
5265   }
5266   /**
5267    * Find End Range
5268    * @private
5269    * @param {Node} root root node
5270    * @param {number} start position to start at
5271    * @param {number} end position to end at
5272    * @return {Range}
5273    */
5274 
5275 
5276   findEnd(root, start, end) {
5277     var stack = [root];
5278     var $el;
5279     var $prev = root;
5280     var found;
5281 
5282     while (stack.length) {
5283       $el = stack.shift();
5284       found = this.walk($el, node => {
5285         var left, right, top, bottom;
5286         var elPos;
5287         var elRange;
5288         elPos = Object(_utils_core__WEBPACK_IMPORTED_MODULE_1__["nodeBounds"])(node);
5289 
5290         if (this.horizontal && this.direction === "ltr") {
5291           left = Math.round(elPos.left);
5292           right = Math.round(elPos.right);
5293 
5294           if (left > end && $prev) {
5295             return $prev;
5296           } else if (right > end) {
5297             return node;
5298           } else {
5299             $prev = node;
5300             stack.push(node);
5301           }
5302         } else if (this.horizontal && this.direction === "rtl") {
5303           left = Math.round(this.horizontal ? elPos.left : elPos.top);
5304           right = Math.round(this.horizontal ? elPos.right : elPos.bottom);
5305 
5306           if (right < start && $prev) {
5307             return $prev;
5308           } else if (left < start) {
5309             return node;
5310           } else {
5311             $prev = node;
5312             stack.push(node);
5313           }
5314         } else {
5315           top = Math.round(elPos.top);
5316           bottom = Math.round(elPos.bottom);
5317 
5318           if (top > end && $prev) {
5319             return $prev;
5320           } else if (bottom > end) {
5321             return node;
5322           } else {
5323             $prev = node;
5324             stack.push(node);
5325           }
5326         }
5327       });
5328 
5329       if (found) {
5330         return this.findTextEndRange(found, start, end);
5331       }
5332     } // end of chapter
5333 
5334 
5335     return this.findTextEndRange($prev, start, end);
5336   }
5337   /**
5338    * Find Text Start Range
5339    * @private
5340    * @param {Node} root root node
5341    * @param {number} start position to start at
5342    * @param {number} end position to end at
5343    * @return {Range}
5344    */
5345 
5346 
5347   findTextStartRange(node, start, end) {
5348     var ranges = this.splitTextNodeIntoRanges(node);
5349     var range;
5350     var pos;
5351     var left, top, right;
5352 
5353     for (var i = 0; i < ranges.length; i++) {
5354       range = ranges[i];
5355       pos = range.getBoundingClientRect();
5356 
5357       if (this.horizontal && this.direction === "ltr") {
5358         left = pos.left;
5359 
5360         if (left >= start) {
5361           return range;
5362         }
5363       } else if (this.horizontal && this.direction === "rtl") {
5364         right = pos.right;
5365 
5366         if (right <= end) {
5367           return range;
5368         }
5369       } else {
5370         top = pos.top;
5371 
5372         if (top >= start) {
5373           return range;
5374         }
5375       } // prev = range;
5376 
5377     }
5378 
5379     return ranges[0];
5380   }
5381   /**
5382    * Find Text End Range
5383    * @private
5384    * @param {Node} root root node
5385    * @param {number} start position to start at
5386    * @param {number} end position to end at
5387    * @return {Range}
5388    */
5389 
5390 
5391   findTextEndRange(node, start, end) {
5392     var ranges = this.splitTextNodeIntoRanges(node);
5393     var prev;
5394     var range;
5395     var pos;
5396     var left, right, top, bottom;
5397 
5398     for (var i = 0; i < ranges.length; i++) {
5399       range = ranges[i];
5400       pos = range.getBoundingClientRect();
5401 
5402       if (this.horizontal && this.direction === "ltr") {
5403         left = pos.left;
5404         right = pos.right;
5405 
5406         if (left > end && prev) {
5407           return prev;
5408         } else if (right > end) {
5409           return range;
5410         }
5411       } else if (this.horizontal && this.direction === "rtl") {
5412         left = pos.left;
5413         right = pos.right;
5414 
5415         if (right < start && prev) {
5416           return prev;
5417         } else if (left < start) {
5418           return range;
5419         }
5420       } else {
5421         top = pos.top;
5422         bottom = pos.bottom;
5423 
5424         if (top > end && prev) {
5425           return prev;
5426         } else if (bottom > end) {
5427           return range;
5428         }
5429       }
5430 
5431       prev = range;
5432     } // Ends before limit
5433 
5434 
5435     return ranges[ranges.length - 1];
5436   }
5437   /**
5438    * Split up a text node into ranges for each word
5439    * @private
5440    * @param {Node} root root node
5441    * @param {string} [_splitter] what to split on
5442    * @return {Range[]}
5443    */
5444 
5445 
5446   splitTextNodeIntoRanges(node, _splitter) {
5447     var ranges = [];
5448     var textContent = node.textContent || "";
5449     var text = textContent.trim();
5450     var range;
5451     var doc = node.ownerDocument;
5452     var splitter = _splitter || " ";
5453     var pos = text.indexOf(splitter);
5454 
5455     if (pos === -1 || node.nodeType != Node.TEXT_NODE) {
5456       range = doc.createRange();
5457       range.selectNodeContents(node);
5458       return [range];
5459     }
5460 
5461     range = doc.createRange();
5462     range.setStart(node, 0);
5463     range.setEnd(node, pos);
5464     ranges.push(range);
5465     range = false;
5466 
5467     while (pos != -1) {
5468       pos = text.indexOf(splitter, pos + 1);
5469 
5470       if (pos > 0) {
5471         if (range) {
5472           range.setEnd(node, pos);
5473           ranges.push(range);
5474         }
5475 
5476         range = doc.createRange();
5477         range.setStart(node, pos + 1);
5478       }
5479     }
5480 
5481     if (range) {
5482       range.setEnd(node, text.length);
5483       ranges.push(range);
5484     }
5485 
5486     return ranges;
5487   }
5488   /**
5489    * Turn a pair of ranges into a pair of CFIs
5490    * @private
5491    * @param {string} cfiBase base string for an EpubCFI
5492    * @param {object} rangePair { start: Range, end: Range }
5493    * @return {object} { start: "epubcfi(...)", end: "epubcfi(...)" }
5494    */
5495 
5496 
5497   rangePairToCfiPair(cfiBase, rangePair) {
5498     var startRange = rangePair.start;
5499     var endRange = rangePair.end;
5500     startRange.collapse(true);
5501     endRange.collapse(false);
5502     let startCfi = new _epubcfi__WEBPACK_IMPORTED_MODULE_0__[/* default */ "a"](startRange, cfiBase).toString();
5503     let endCfi = new _epubcfi__WEBPACK_IMPORTED_MODULE_0__[/* default */ "a"](endRange, cfiBase).toString();
5504     return {
5505       start: startCfi,
5506       end: endCfi
5507     };
5508   }
5509 
5510   rangeListToCfiList(cfiBase, columns) {
5511     var map = [];
5512     var cifPair;
5513 
5514     for (var i = 0; i < columns.length; i++) {
5515       cifPair = this.rangePairToCfiPair(cfiBase, columns[i]);
5516       map.push(cifPair);
5517     }
5518 
5519     return map;
5520   }
5521   /**
5522    * Set the axis for mapping
5523    * @param {string} axis horizontal | vertical
5524    * @return {boolean} is it horizontal?
5525    */
5526 
5527 
5528   axis(axis) {
5529     if (axis) {
5530       this.horizontal = axis === "horizontal" ? true : false;
5531     }
5532 
5533     return this.horizontal;
5534   }
5535 
5536 }
5537 
5538 /* harmony default export */ __webpack_exports__["a"] = (Mapping);
5539 
5540 /***/ }),
5541 /* 12 */
5542 /***/ (function(module, __webpack_exports__, __webpack_require__) {
5543 
5544 "use strict";
5545 /* harmony import */ var event_emitter__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(3);
5546 /* harmony import */ var event_emitter__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(event_emitter__WEBPACK_IMPORTED_MODULE_0__);
5547 /* harmony import */ var _utils_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(0);
5548 /* harmony import */ var _epubcfi__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(2);
5549 /* harmony import */ var _mapping__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(11);
5550 /* harmony import */ var _utils_replacements__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(8);
5551 /* harmony import */ var _utils_constants__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(1);
5552 
5553 
5554 
5555 
5556 
5557 
5558 const hasNavigator = typeof navigator !== "undefined";
5559 const isChrome = hasNavigator && /Chrome/.test(navigator.userAgent);
5560 const isWebkit = hasNavigator && !isChrome && /AppleWebKit/.test(navigator.userAgent);
5561 const ELEMENT_NODE = 1;
5562 const TEXT_NODE = 3;
5563 /**
5564         * Handles DOM manipulation, queries and events for View contents
5565         * @class
5566         * @param {document} doc Document
5567         * @param {element} content Parent Element (typically Body)
5568         * @param {string} cfiBase Section component of CFIs
5569         * @param {number} sectionIndex Index in Spine of Conntent's Section
5570         */
5571 
5572 class Contents {
5573   constructor(doc, content, cfiBase, sectionIndex) {
5574     // Blank Cfi for Parsing
5575     this.epubcfi = new _epubcfi__WEBPACK_IMPORTED_MODULE_2__[/* default */ "a"]();
5576     this.document = doc;
5577     this.documentElement = this.document.documentElement;
5578     this.content = content || this.document.body;
5579     this.window = this.document.defaultView;
5580     this._size = {
5581       width: 0,
5582       height: 0
5583     };
5584     this.sectionIndex = sectionIndex || 0;
5585     this.cfiBase = cfiBase || "";
5586     this.epubReadingSystem("epub.js", _utils_constants__WEBPACK_IMPORTED_MODULE_5__[/* EPUBJS_VERSION */ "b"]);
5587     this.called = 0;
5588     this.active = true;
5589     this.listeners();
5590   }
5591   /**
5592         * Get DOM events that are listened for and passed along
5593         */
5594 
5595 
5596   static get listenedEvents() {
5597     return _utils_constants__WEBPACK_IMPORTED_MODULE_5__[/* DOM_EVENTS */ "a"];
5598   }
5599   /**
5600         * Get or Set width
5601         * @param {number} [w]
5602         * @returns {number} width
5603         */
5604 
5605 
5606   width(w) {
5607     // var frame = this.documentElement;
5608     var frame = this.content;
5609 
5610     if (w && Object(_utils_core__WEBPACK_IMPORTED_MODULE_1__["isNumber"])(w)) {
5611       w = w + "px";
5612     }
5613 
5614     if (w) {
5615       frame.style.width = w; // this.content.style.width = w;
5616     }
5617 
5618     return parseInt(this.window.getComputedStyle(frame)["width"]);
5619   }
5620   /**
5621         * Get or Set height
5622         * @param {number} [h]
5623         * @returns {number} height
5624         */
5625 
5626 
5627   height(h) {
5628     // var frame = this.documentElement;
5629     var frame = this.content;
5630 
5631     if (h && Object(_utils_core__WEBPACK_IMPORTED_MODULE_1__["isNumber"])(h)) {
5632       h = h + "px";
5633     }
5634 
5635     if (h) {
5636       frame.style.height = h; // this.content.style.height = h;
5637     }
5638 
5639     return parseInt(this.window.getComputedStyle(frame)["height"]);
5640   }
5641   /**
5642         * Get or Set width of the contents
5643         * @param {number} [w]
5644         * @returns {number} width
5645         */
5646 
5647 
5648   contentWidth(w) {
5649     var content = this.content || this.document.body;
5650 
5651     if (w && Object(_utils_core__WEBPACK_IMPORTED_MODULE_1__["isNumber"])(w)) {
5652       w = w + "px";
5653     }
5654 
5655     if (w) {
5656       content.style.width = w;
5657     }
5658 
5659     return parseInt(this.window.getComputedStyle(content)["width"]);
5660   }
5661   /**
5662         * Get or Set height of the contents
5663         * @param {number} [h]
5664         * @returns {number} height
5665         */
5666 
5667 
5668   contentHeight(h) {
5669     var content = this.content || this.document.body;
5670 
5671     if (h && Object(_utils_core__WEBPACK_IMPORTED_MODULE_1__["isNumber"])(h)) {
5672       h = h + "px";
5673     }
5674 
5675     if (h) {
5676       content.style.height = h;
5677     }
5678 
5679     return parseInt(this.window.getComputedStyle(content)["height"]);
5680   }
5681   /**
5682         * Get the width of the text using Range
5683         * @returns {number} width
5684         */
5685 
5686 
5687   textWidth() {
5688     let rect;
5689     let width;
5690     let range = this.document.createRange();
5691     let content = this.content || this.document.body;
5692     let border = Object(_utils_core__WEBPACK_IMPORTED_MODULE_1__["borders"])(content); // Select the contents of frame
5693 
5694     range.selectNodeContents(content); // get the width of the text content
5695 
5696     rect = range.getBoundingClientRect();
5697     width = rect.width;
5698 
5699     if (border && border.width) {
5700       width += border.width;
5701     }
5702 
5703     return Math.round(width);
5704   }
5705   /**
5706         * Get the height of the text using Range
5707         * @returns {number} height
5708         */
5709 
5710 
5711   textHeight() {
5712     let rect;
5713     let height;
5714     let range = this.document.createRange();
5715     let content = this.content || this.document.body;
5716     range.selectNodeContents(content);
5717     rect = range.getBoundingClientRect();
5718     height = rect.bottom;
5719     return Math.round(height);
5720   }
5721   /**
5722         * Get documentElement scrollWidth
5723         * @returns {number} width
5724         */
5725 
5726 
5727   scrollWidth() {
5728     var width = this.documentElement.scrollWidth;
5729     return width;
5730   }
5731   /**
5732         * Get documentElement scrollHeight
5733         * @returns {number} height
5734         */
5735 
5736 
5737   scrollHeight() {
5738     var height = this.documentElement.scrollHeight;
5739     return height;
5740   }
5741   /**
5742         * Set overflow css style of the contents
5743         * @param {string} [overflow]
5744         */
5745 
5746 
5747   overflow(overflow) {
5748     if (overflow) {
5749       this.documentElement.style.overflow = overflow;
5750     }
5751 
5752     return this.window.getComputedStyle(this.documentElement)["overflow"];
5753   }
5754   /**
5755         * Set overflowX css style of the documentElement
5756         * @param {string} [overflow]
5757         */
5758 
5759 
5760   overflowX(overflow) {
5761     if (overflow) {
5762       this.documentElement.style.overflowX = overflow;
5763     }
5764 
5765     return this.window.getComputedStyle(this.documentElement)["overflowX"];
5766   }
5767   /**
5768         * Set overflowY css style of the documentElement
5769         * @param {string} [overflow]
5770         */
5771 
5772 
5773   overflowY(overflow) {
5774     if (overflow) {
5775       this.documentElement.style.overflowY = overflow;
5776     }
5777 
5778     return this.window.getComputedStyle(this.documentElement)["overflowY"];
5779   }
5780   /**
5781         * Set Css styles on the contents element (typically Body)
5782         * @param {string} property
5783         * @param {string} value
5784         * @param {boolean} [priority] set as "important"
5785         */
5786 
5787 
5788   css(property, value, priority) {
5789     var content = this.content || this.document.body;
5790 
5791     if (value) {
5792       content.style.setProperty(property, value, priority ? "important" : "");
5793     } else {
5794       content.style.removeProperty(property);
5795     }
5796 
5797     return this.window.getComputedStyle(content)[property];
5798   }
5799   /**
5800         * Get or Set the viewport element
5801         * @param {object} [options]
5802         * @param {string} [options.width]
5803         * @param {string} [options.height]
5804         * @param {string} [options.scale]
5805         * @param {string} [options.minimum]
5806         * @param {string} [options.maximum]
5807         * @param {string} [options.scalable]
5808         */
5809 
5810 
5811   viewport(options) {
5812     var _width, _height, _scale, _minimum, _maximum, _scalable; // var width, height, scale, minimum, maximum, scalable;
5813 
5814 
5815     var $viewport = this.document.querySelector("meta[name='viewport']");
5816     var parsed = {
5817       "width": undefined,
5818       "height": undefined,
5819       "scale": undefined,
5820       "minimum": undefined,
5821       "maximum": undefined,
5822       "scalable": undefined
5823     };
5824     var newContent = [];
5825     var settings = {};
5826     /*
5827     * check for the viewport size
5828     * <meta name="viewport" content="width=1024,height=697" />
5829     */
5830 
5831     if ($viewport && $viewport.hasAttribute("content")) {
5832       let content = $viewport.getAttribute("content");
5833 
5834       let _width = content.match(/width\s*=\s*([^,]*)/);
5835 
5836       let _height = content.match(/height\s*=\s*([^,]*)/);
5837 
5838       let _scale = content.match(/initial-scale\s*=\s*([^,]*)/);
5839 
5840       let _minimum = content.match(/minimum-scale\s*=\s*([^,]*)/);
5841 
5842       let _maximum = content.match(/maximum-scale\s*=\s*([^,]*)/);
5843 
5844       let _scalable = content.match(/user-scalable\s*=\s*([^,]*)/);
5845 
5846       if (_width && _width.length && typeof _width[1] !== "undefined") {
5847         parsed.width = _width[1];
5848       }
5849 
5850       if (_height && _height.length && typeof _height[1] !== "undefined") {
5851         parsed.height = _height[1];
5852       }
5853 
5854       if (_scale && _scale.length && typeof _scale[1] !== "undefined") {
5855         parsed.scale = _scale[1];
5856       }
5857 
5858       if (_minimum && _minimum.length && typeof _minimum[1] !== "undefined") {
5859         parsed.minimum = _minimum[1];
5860       }
5861 
5862       if (_maximum && _maximum.length && typeof _maximum[1] !== "undefined") {
5863         parsed.maximum = _maximum[1];
5864       }
5865 
5866       if (_scalable && _scalable.length && typeof _scalable[1] !== "undefined") {
5867         parsed.scalable = _scalable[1];
5868       }
5869     }
5870 
5871     settings = Object(_utils_core__WEBPACK_IMPORTED_MODULE_1__["defaults"])(options || {}, parsed);
5872 
5873     if (options) {
5874       if (settings.width) {
5875         newContent.push("width=" + settings.width);
5876       }
5877 
5878       if (settings.height) {
5879         newContent.push("height=" + settings.height);
5880       }
5881 
5882       if (settings.scale) {
5883         newContent.push("initial-scale=" + settings.scale);
5884       }
5885 
5886       if (settings.scalable === "no") {
5887         newContent.push("minimum-scale=" + settings.scale);
5888         newContent.push("maximum-scale=" + settings.scale);
5889         newContent.push("user-scalable=" + settings.scalable);
5890       } else {
5891         if (settings.scalable) {
5892           newContent.push("user-scalable=" + settings.scalable);
5893         }
5894 
5895         if (settings.minimum) {
5896           newContent.push("minimum-scale=" + settings.minimum);
5897         }
5898 
5899         if (settings.maximum) {
5900           newContent.push("minimum-scale=" + settings.maximum);
5901         }
5902       }
5903 
5904       if (!$viewport) {
5905         $viewport = this.document.createElement("meta");
5906         $viewport.setAttribute("name", "viewport");
5907         this.document.querySelector("head").appendChild($viewport);
5908       }
5909 
5910       $viewport.setAttribute("content", newContent.join(", "));
5911       this.window.scrollTo(0, 0);
5912     }
5913 
5914     return settings;
5915   }
5916   /**
5917    * Event emitter for when the contents has expanded
5918    * @private
5919    */
5920 
5921 
5922   expand() {
5923     this.emit(_utils_constants__WEBPACK_IMPORTED_MODULE_5__[/* EVENTS */ "c"].CONTENTS.EXPAND);
5924   }
5925   /**
5926    * Add DOM listeners
5927    * @private
5928    */
5929 
5930 
5931   listeners() {
5932     this.imageLoadListeners();
5933     this.mediaQueryListeners(); // this.fontLoadListeners();
5934 
5935     this.addEventListeners();
5936     this.addSelectionListeners(); // this.transitionListeners();
5937 
5938     if (typeof ResizeObserver === "undefined") {
5939       this.resizeListeners();
5940       this.visibilityListeners();
5941     } else {
5942       this.resizeObservers();
5943     } // this.mutationObservers();
5944 
5945 
5946     this.linksHandler();
5947   }
5948   /**
5949    * Remove DOM listeners
5950    * @private
5951    */
5952 
5953 
5954   removeListeners() {
5955     this.removeEventListeners();
5956     this.removeSelectionListeners();
5957 
5958     if (this.observer) {
5959       this.observer.disconnect();
5960     }
5961 
5962     clearTimeout(this.expanding);
5963   }
5964   /**
5965    * Check if size of contents has changed and
5966    * emit 'resize' event if it has.
5967    * @private
5968    */
5969 
5970 
5971   resizeCheck() {
5972     let width = this.textWidth();
5973     let height = this.textHeight();
5974 
5975     if (width != this._size.width || height != this._size.height) {
5976       this._size = {
5977         width: width,
5978         height: height
5979       };
5980       this.onResize && this.onResize(this._size);
5981       this.emit(_utils_constants__WEBPACK_IMPORTED_MODULE_5__[/* EVENTS */ "c"].CONTENTS.RESIZE, this._size);
5982     }
5983   }
5984   /**
5985    * Poll for resize detection
5986    * @private
5987    */
5988 
5989 
5990   resizeListeners() {
5991     var width, height; // Test size again
5992 
5993     clearTimeout(this.expanding);
5994     requestAnimationFrame(this.resizeCheck.bind(this));
5995     this.expanding = setTimeout(this.resizeListeners.bind(this), 350);
5996   }
5997   /**
5998    * Listen for visibility of tab to change
5999    * @private
6000    */
6001 
6002 
6003   visibilityListeners() {
6004     document.addEventListener("visibilitychange", () => {
6005       if (document.visibilityState === "visible" && this.active === false) {
6006         this.active = true;
6007         this.resizeListeners();
6008       } else {
6009         this.active = false;
6010         clearTimeout(this.expanding);
6011       }
6012     });
6013   }
6014   /**
6015    * Use css transitions to detect resize
6016    * @private
6017    */
6018 
6019 
6020   transitionListeners() {
6021     let body = this.content;
6022     body.style['transitionProperty'] = "font, font-size, font-size-adjust, font-stretch, font-variation-settings, font-weight, width, height";
6023     body.style['transitionDuration'] = "0.001ms";
6024     body.style['transitionTimingFunction'] = "linear";
6025     body.style['transitionDelay'] = "0";
6026     this._resizeCheck = this.resizeCheck.bind(this);
6027     this.document.addEventListener('transitionend', this._resizeCheck);
6028   }
6029   /**
6030    * Listen for media query changes and emit 'expand' event
6031    * Adapted from: https://github.com/tylergaw/media-query-events/blob/master/js/mq-events.js
6032    * @private
6033    */
6034 
6035 
6036   mediaQueryListeners() {
6037     var sheets = this.document.styleSheets;
6038 
6039     var mediaChangeHandler = function (m) {
6040       if (m.matches && !this._expanding) {
6041         setTimeout(this.expand.bind(this), 1);
6042       }
6043     }.bind(this);
6044 
6045     for (var i = 0; i < sheets.length; i += 1) {
6046       var rules; // Firefox errors if we access cssRules cross-domain
6047 
6048       try {
6049         rules = sheets[i].cssRules;
6050       } catch (e) {
6051         return;
6052       }
6053 
6054       if (!rules) return; // Stylesheets changed
6055 
6056       for (var j = 0; j < rules.length; j += 1) {
6057         //if (rules[j].constructor === CSSMediaRule) {
6058         if (rules[j].media) {
6059           var mql = this.window.matchMedia(rules[j].media.mediaText);
6060           mql.addListener(mediaChangeHandler); //mql.onchange = mediaChangeHandler;
6061         }
6062       }
6063     }
6064   }
6065   /**
6066    * Use ResizeObserver to listen for changes in the DOM and check for resize
6067    * @private
6068    */
6069 
6070 
6071   resizeObservers() {
6072     // create an observer instance
6073     this.observer = new ResizeObserver(e => {
6074       requestAnimationFrame(this.resizeCheck.bind(this));
6075     }); // pass in the target node
6076 
6077     this.observer.observe(this.document.documentElement);
6078   }
6079   /**
6080    * Use MutationObserver to listen for changes in the DOM and check for resize
6081    * @private
6082    */
6083 
6084 
6085   mutationObservers() {
6086     // create an observer instance
6087     this.observer = new MutationObserver(mutations => {
6088       this.resizeCheck();
6089     }); // configuration of the observer:
6090 
6091     let config = {
6092       attributes: true,
6093       childList: true,
6094       characterData: true,
6095       subtree: true
6096     }; // pass in the target node, as well as the observer options
6097 
6098     this.observer.observe(this.document, config);
6099   }
6100   /**
6101    * Test if images are loaded or add listener for when they load
6102    * @private
6103    */
6104 
6105 
6106   imageLoadListeners() {
6107     var images = this.document.querySelectorAll("img");
6108     var img;
6109 
6110     for (var i = 0; i < images.length; i++) {
6111       img = images[i];
6112 
6113       if (typeof img.naturalWidth !== "undefined" && img.naturalWidth === 0) {
6114         img.onload = this.expand.bind(this);
6115       }
6116     }
6117   }
6118   /**
6119    * Listen for font load and check for resize when loaded
6120    * @private
6121    */
6122 
6123 
6124   fontLoadListeners() {
6125     if (!this.document || !this.document.fonts) {
6126       return;
6127     }
6128 
6129     this.document.fonts.ready.then(function () {
6130       this.resizeCheck();
6131     }.bind(this));
6132   }
6133   /**
6134    * Get the documentElement
6135    * @returns {element} documentElement
6136    */
6137 
6138 
6139   root() {
6140     if (!this.document) return null;
6141     return this.document.documentElement;
6142   }
6143   /**
6144    * Get the location offset of a EpubCFI or an #id
6145    * @param {string | EpubCFI} target
6146    * @param {string} [ignoreClass] for the cfi
6147    * @returns { {left: Number, top: Number }
6148    */
6149 
6150 
6151   locationOf(target, ignoreClass) {
6152     var position;
6153     var targetPos = {
6154       "left": 0,
6155       "top": 0
6156     };
6157     if (!this.document) return targetPos;
6158 
6159     if (this.epubcfi.isCfiString(target)) {
6160       let range = new _epubcfi__WEBPACK_IMPORTED_MODULE_2__[/* default */ "a"](target).toRange(this.document, ignoreClass);
6161 
6162       if (range) {
6163         try {
6164           if (!range.endContainer || range.startContainer == range.endContainer && range.startOffset == range.endOffset) {
6165             // If the end for the range is not set, it results in collapsed becoming
6166             // true. This in turn leads to inconsistent behaviour when calling
6167             // getBoundingRect. Wrong bounds lead to the wrong page being displayed.
6168             // https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/15684911/
6169             let pos = range.startContainer.textContent.indexOf(" ", range.startOffset);
6170 
6171             if (pos == -1) {
6172               pos = range.startContainer.textContent.length;
6173             }
6174 
6175             range.setEnd(range.startContainer, pos);
6176           }
6177         } catch (e) {
6178           console.error("setting end offset to start container length failed", e);
6179         }
6180 
6181         if (range.startContainer.nodeType === Node.ELEMENT_NODE) {
6182           position = range.startContainer.getBoundingClientRect();
6183           targetPos.left = position.left;
6184           targetPos.top = position.top;
6185         } else {
6186           // Webkit does not handle collapsed range bounds correctly
6187           // https://bugs.webkit.org/show_bug.cgi?id=138949
6188           // Construct a new non-collapsed range
6189           if (isWebkit) {
6190             let container = range.startContainer;
6191             let newRange = new Range();
6192 
6193             try {
6194               if (container.nodeType === ELEMENT_NODE) {
6195                 position = container.getBoundingClientRect();
6196               } else if (range.startOffset + 2 < container.length) {
6197                 newRange.setStart(container, range.startOffset);
6198                 newRange.setEnd(container, range.startOffset + 2);
6199                 position = newRange.getBoundingClientRect();
6200               } else if (range.startOffset - 2 > 0) {
6201                 newRange.setStart(container, range.startOffset - 2);
6202                 newRange.setEnd(container, range.startOffset);
6203                 position = newRange.getBoundingClientRect();
6204               } else {
6205                 // empty, return the parent element
6206                 position = container.parentNode.getBoundingClientRect();
6207               }
6208             } catch (e) {
6209               console.error(e, e.stack);
6210             }
6211           } else {
6212             position = range.getBoundingClientRect();
6213           }
6214         }
6215       }
6216     } else if (typeof target === "string" && target.indexOf("#") > -1) {
6217       let id = target.substring(target.indexOf("#") + 1);
6218       let el = this.document.getElementById(id);
6219 
6220       if (el) {
6221         if (isWebkit) {
6222           // Webkit reports incorrect bounding rects in Columns
6223           let newRange = new Range();
6224           newRange.selectNode(el);
6225           position = newRange.getBoundingClientRect();
6226         } else {
6227           position = el.getBoundingClientRect();
6228         }
6229       }
6230     }
6231 
6232     if (position) {
6233       targetPos.left = position.left;
6234       targetPos.top = position.top;
6235     }
6236 
6237     return targetPos;
6238   }
6239   /**
6240    * Append a stylesheet link to the document head
6241    * @param {string} src url
6242    */
6243 
6244 
6245   addStylesheet(src) {
6246     return new Promise(function (resolve, reject) {
6247       var $stylesheet;
6248       var ready = false;
6249 
6250       if (!this.document) {
6251         resolve(false);
6252         return;
6253       } // Check if link already exists
6254 
6255 
6256       $stylesheet = this.document.querySelector("link[href='" + src + "']");
6257 
6258       if ($stylesheet) {
6259         resolve(true);
6260         return; // already present
6261       }
6262 
6263       $stylesheet = this.document.createElement("link");
6264       $stylesheet.type = "text/css";
6265       $stylesheet.rel = "stylesheet";
6266       $stylesheet.href = src;
6267 
6268       $stylesheet.onload = $stylesheet.onreadystatechange = function () {
6269         if (!ready && (!this.readyState || this.readyState == "complete")) {
6270           ready = true; // Let apply
6271 
6272           setTimeout(() => {
6273             resolve(true);
6274           }, 1);
6275         }
6276       };
6277 
6278       this.document.head.appendChild($stylesheet);
6279     }.bind(this));
6280   }
6281 
6282   _getStylesheetNode(key) {
6283     var styleEl;
6284     key = "epubjs-inserted-css-" + (key || '');
6285     if (!this.document) return false; // Check if link already exists
6286 
6287     styleEl = this.document.getElementById(key);
6288 
6289     if (!styleEl) {
6290       styleEl = this.document.createElement("style");
6291       styleEl.id = key; // Append style element to head
6292 
6293       this.document.head.appendChild(styleEl);
6294     }
6295 
6296     return styleEl;
6297   }
6298   /**
6299    * Append stylesheet css
6300    * @param {string} serializedCss
6301    * @param {string} key If the key is the same, the CSS will be replaced instead of inserted
6302    */
6303 
6304 
6305   addStylesheetCss(serializedCss, key) {
6306     if (!this.document || !serializedCss) return false;
6307     var styleEl;
6308     styleEl = this._getStylesheetNode(key);
6309     styleEl.innerHTML = serializedCss;
6310     return true;
6311   }
6312   /**
6313    * Append stylesheet rules to a generate stylesheet
6314    * Array: https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleSheet/insertRule
6315    * Object: https://github.com/desirable-objects/json-to-css
6316    * @param {array | object} rules
6317    * @param {string} key If the key is the same, the CSS will be replaced instead of inserted
6318    */
6319 
6320 
6321   addStylesheetRules(rules, key) {
6322     var styleSheet;
6323     if (!this.document || !rules || rules.length === 0) return; // Grab style sheet
6324 
6325     styleSheet = this._getStylesheetNode(key).sheet;
6326 
6327     if (Object.prototype.toString.call(rules) === "[object Array]") {
6328       for (var i = 0, rl = rules.length; i < rl; i++) {
6329         var j = 1,
6330             rule = rules[i],
6331             selector = rules[i][0],
6332             propStr = ""; // If the second argument of a rule is an array of arrays, correct our variables.
6333 
6334         if (Object.prototype.toString.call(rule[1][0]) === "[object Array]") {
6335           rule = rule[1];
6336           j = 0;
6337         }
6338 
6339         for (var pl = rule.length; j < pl; j++) {
6340           var prop = rule[j];
6341           propStr += prop[0] + ":" + prop[1] + (prop[2] ? " !important" : "") + ";\n";
6342         } // Insert CSS Rule
6343 
6344 
6345         styleSheet.insertRule(selector + "{" + propStr + "}", styleSheet.cssRules.length);
6346       }
6347     } else {
6348       const selectors = Object.keys(rules);
6349       selectors.forEach(selector => {
6350         const definition = rules[selector];
6351 
6352         if (Array.isArray(definition)) {
6353           definition.forEach(item => {
6354             const _rules = Object.keys(item);
6355 
6356             const result = _rules.map(rule => {
6357               return `${rule}:${item[rule]}`;
6358             }).join(';');
6359 
6360             styleSheet.insertRule(`${selector}{${result}}`, styleSheet.cssRules.length);
6361           });
6362         } else {
6363           const _rules = Object.keys(definition);
6364 
6365           const result = _rules.map(rule => {
6366             return `${rule}:${definition[rule]}`;
6367           }).join(';');
6368 
6369           styleSheet.insertRule(`${selector}{${result}}`, styleSheet.cssRules.length);
6370         }
6371       });
6372     }
6373   }
6374   /**
6375    * Append a script tag to the document head
6376    * @param {string} src url
6377    * @returns {Promise} loaded
6378    */
6379 
6380 
6381   addScript(src) {
6382     return new Promise(function (resolve, reject) {
6383       var $script;
6384       var ready = false;
6385 
6386       if (!this.document) {
6387         resolve(false);
6388         return;
6389       }
6390 
6391       $script = this.document.createElement("script");
6392       $script.type = "text/javascript";
6393       $script.async = true;
6394       $script.src = src;
6395 
6396       $script.onload = $script.onreadystatechange = function () {
6397         if (!ready && (!this.readyState || this.readyState == "complete")) {
6398           ready = true;
6399           setTimeout(function () {
6400             resolve(true);
6401           }, 1);
6402         }
6403       };
6404 
6405       this.document.head.appendChild($script);
6406     }.bind(this));
6407   }
6408   /**
6409    * Add a class to the contents container
6410    * @param {string} className
6411    */
6412 
6413 
6414   addClass(className) {
6415     var content;
6416     if (!this.document) return;
6417     content = this.content || this.document.body;
6418 
6419     if (content) {
6420       content.classList.add(className);
6421     }
6422   }
6423   /**
6424    * Remove a class from the contents container
6425    * @param {string} removeClass
6426    */
6427 
6428 
6429   removeClass(className) {
6430     var content;
6431     if (!this.document) return;
6432     content = this.content || this.document.body;
6433 
6434     if (content) {
6435       content.classList.remove(className);
6436     }
6437   }
6438   /**
6439    * Add DOM event listeners
6440    * @private
6441    */
6442 
6443 
6444   addEventListeners() {
6445     if (!this.document) {
6446       return;
6447     }
6448 
6449     this._triggerEvent = this.triggerEvent.bind(this);
6450     _utils_constants__WEBPACK_IMPORTED_MODULE_5__[/* DOM_EVENTS */ "a"].forEach(function (eventName) {
6451       this.document.addEventListener(eventName, this._triggerEvent, {
6452         passive: true
6453       });
6454     }, this);
6455   }
6456   /**
6457    * Remove DOM event listeners
6458    * @private
6459    */
6460 
6461 
6462   removeEventListeners() {
6463     if (!this.document) {
6464       return;
6465     }
6466 
6467     _utils_constants__WEBPACK_IMPORTED_MODULE_5__[/* DOM_EVENTS */ "a"].forEach(function (eventName) {
6468       this.document.removeEventListener(eventName, this._triggerEvent, {
6469         passive: true
6470       });
6471     }, this);
6472     this._triggerEvent = undefined;
6473   }
6474   /**
6475    * Emit passed browser events
6476    * @private
6477    */
6478 
6479 
6480   triggerEvent(e) {
6481     this.emit(e.type, e);
6482   }
6483   /**
6484    * Add listener for text selection
6485    * @private
6486    */
6487 
6488 
6489   addSelectionListeners() {
6490     if (!this.document) {
6491       return;
6492     }
6493 
6494     this._onSelectionChange = this.onSelectionChange.bind(this);
6495     this.document.addEventListener("selectionchange", this._onSelectionChange, {
6496       passive: true
6497     });
6498   }
6499   /**
6500    * Remove listener for text selection
6501    * @private
6502    */
6503 
6504 
6505   removeSelectionListeners() {
6506     if (!this.document) {
6507       return;
6508     }
6509 
6510     this.document.removeEventListener("selectionchange", this._onSelectionChange, {
6511       passive: true
6512     });
6513     this._onSelectionChange = undefined;
6514   }
6515   /**
6516    * Handle getting text on selection
6517    * @private
6518    */
6519 
6520 
6521   onSelectionChange(e) {
6522     if (this.selectionEndTimeout) {
6523       clearTimeout(this.selectionEndTimeout);
6524     }
6525 
6526     this.selectionEndTimeout = setTimeout(function () {
6527       var selection = this.window.getSelection();
6528       this.triggerSelectedEvent(selection);
6529     }.bind(this), 250);
6530   }
6531   /**
6532    * Emit event on text selection
6533    * @private
6534    */
6535 
6536 
6537   triggerSelectedEvent(selection) {
6538     var range, cfirange;
6539 
6540     if (selection && selection.rangeCount > 0) {
6541       range = selection.getRangeAt(0);
6542 
6543       if (!range.collapsed) {
6544         // cfirange = this.section.cfiFromRange(range);
6545         cfirange = new _epubcfi__WEBPACK_IMPORTED_MODULE_2__[/* default */ "a"](range, this.cfiBase).toString();
6546         this.emit(_utils_constants__WEBPACK_IMPORTED_MODULE_5__[/* EVENTS */ "c"].CONTENTS.SELECTED, cfirange);
6547         this.emit(_utils_constants__WEBPACK_IMPORTED_MODULE_5__[/* EVENTS */ "c"].CONTENTS.SELECTED_RANGE, range);
6548       }
6549     }
6550   }
6551   /**
6552    * Get a Dom Range from EpubCFI
6553    * @param {EpubCFI} _cfi
6554    * @param {string} [ignoreClass]
6555    * @returns {Range} range
6556    */
6557 
6558 
6559   range(_cfi, ignoreClass) {
6560     var cfi = new _epubcfi__WEBPACK_IMPORTED_MODULE_2__[/* default */ "a"](_cfi);
6561     return cfi.toRange(this.document, ignoreClass);
6562   }
6563   /**
6564    * Get an EpubCFI from a Dom Range
6565    * @param {Range} range
6566    * @param {string} [ignoreClass]
6567    * @returns {EpubCFI} cfi
6568    */
6569 
6570 
6571   cfiFromRange(range, ignoreClass) {
6572     return new _epubcfi__WEBPACK_IMPORTED_MODULE_2__[/* default */ "a"](range, this.cfiBase, ignoreClass).toString();
6573   }
6574   /**
6575    * Get an EpubCFI from a Dom node
6576    * @param {node} node
6577    * @param {string} [ignoreClass]
6578    * @returns {EpubCFI} cfi
6579    */
6580 
6581 
6582   cfiFromNode(node, ignoreClass) {
6583     return new _epubcfi__WEBPACK_IMPORTED_MODULE_2__[/* default */ "a"](node, this.cfiBase, ignoreClass).toString();
6584   } // TODO: find where this is used - remove?
6585 
6586 
6587   map(layout) {
6588     var map = new _mapping__WEBPACK_IMPORTED_MODULE_3__[/* default */ "a"](layout);
6589     return map.section();
6590   }
6591   /**
6592    * Size the contents to a given width and height
6593    * @param {number} [width]
6594    * @param {number} [height]
6595    */
6596 
6597 
6598   size(width, height) {
6599     var viewport = {
6600       scale: 1.0,
6601       scalable: "no"
6602     };
6603     this.layoutStyle("scrolling");
6604 
6605     if (width >= 0) {
6606       this.width(width);
6607       viewport.width = width;
6608       this.css("padding", "0 " + width / 12 + "px");
6609     }
6610 
6611     if (height >= 0) {
6612       this.height(height);
6613       viewport.height = height;
6614     }
6615 
6616     this.css("margin", "0");
6617     this.css("box-sizing", "border-box");
6618     this.viewport(viewport);
6619   }
6620   /**
6621    * Apply columns to the contents for pagination
6622    * @param {number} width
6623    * @param {number} height
6624    * @param {number} columnWidth
6625    * @param {number} gap
6626    */
6627 
6628 
6629   columns(width, height, columnWidth, gap, dir) {
6630     let COLUMN_AXIS = Object(_utils_core__WEBPACK_IMPORTED_MODULE_1__["prefixed"])("column-axis");
6631     let COLUMN_GAP = Object(_utils_core__WEBPACK_IMPORTED_MODULE_1__["prefixed"])("column-gap");
6632     let COLUMN_WIDTH = Object(_utils_core__WEBPACK_IMPORTED_MODULE_1__["prefixed"])("column-width");
6633     let COLUMN_FILL = Object(_utils_core__WEBPACK_IMPORTED_MODULE_1__["prefixed"])("column-fill");
6634     let writingMode = this.writingMode();
6635     let axis = writingMode.indexOf("vertical") === 0 ? "vertical" : "horizontal";
6636     this.layoutStyle("paginated");
6637 
6638     if (dir === "rtl" && axis === "horizontal") {
6639       this.direction(dir);
6640     }
6641 
6642     this.width(width);
6643     this.height(height); // Deal with Mobile trying to scale to viewport
6644 
6645     this.viewport({
6646       width: width,
6647       height: height,
6648       scale: 1.0,
6649       scalable: "no"
6650     }); // TODO: inline-block needs more testing
6651     // Fixes Safari column cut offs, but causes RTL issues
6652     // this.css("display", "inline-block");
6653 
6654     this.css("overflow-y", "hidden");
6655     this.css("margin", "0", true);
6656 
6657     if (axis === "vertical") {
6658       this.css("padding-top", gap / 2 + "px", true);
6659       this.css("padding-bottom", gap / 2 + "px", true);
6660       this.css("padding-left", "20px");
6661       this.css("padding-right", "20px");
6662       this.css(COLUMN_AXIS, "vertical");
6663     } else {
6664       this.css("padding-top", "20px");
6665       this.css("padding-bottom", "20px");
6666       this.css("padding-left", gap / 2 + "px", true);
6667       this.css("padding-right", gap / 2 + "px", true);
6668       this.css(COLUMN_AXIS, "horizontal");
6669     }
6670 
6671     this.css("box-sizing", "border-box");
6672     this.css("max-width", "inherit");
6673     this.css(COLUMN_FILL, "auto");
6674     this.css(COLUMN_GAP, gap + "px");
6675     this.css(COLUMN_WIDTH, columnWidth + "px"); // Fix glyph clipping in WebKit
6676     // https://github.com/futurepress/epub.js/issues/983
6677 
6678     this.css("-webkit-line-box-contain", "block glyphs replaced");
6679   }
6680   /**
6681    * Scale contents from center
6682    * @param {number} scale
6683    * @param {number} offsetX
6684    * @param {number} offsetY
6685    */
6686 
6687 
6688   scaler(scale, offsetX, offsetY) {
6689     var scaleStr = "scale(" + scale + ")";
6690     var translateStr = ""; // this.css("position", "absolute"));
6691 
6692     this.css("transform-origin", "top left");
6693 
6694     if (offsetX >= 0 || offsetY >= 0) {
6695       translateStr = " translate(" + (offsetX || 0) + "px, " + (offsetY || 0) + "px )";
6696     }
6697 
6698     this.css("transform", scaleStr + translateStr);
6699   }
6700   /**
6701    * Fit contents into a fixed width and height
6702    * @param {number} width
6703    * @param {number} height
6704    */
6705 
6706 
6707   fit(width, height, section) {
6708     var viewport = this.viewport();
6709     var viewportWidth = parseInt(viewport.width);
6710     var viewportHeight = parseInt(viewport.height);
6711     var widthScale = width / viewportWidth;
6712     var heightScale = height / viewportHeight;
6713     var scale = widthScale < heightScale ? widthScale : heightScale; // the translate does not work as intended, elements can end up unaligned
6714     // var offsetY = (height - (viewportHeight * scale)) / 2;
6715     // var offsetX = 0;
6716     // if (this.sectionIndex % 2 === 1) {
6717     //  offsetX = width - (viewportWidth * scale);
6718     // }
6719 
6720     this.layoutStyle("paginated"); // scale needs width and height to be set
6721 
6722     this.width(viewportWidth);
6723     this.height(viewportHeight);
6724     this.overflow("hidden"); // Scale to the correct size
6725 
6726     this.scaler(scale, 0, 0); // this.scaler(scale, offsetX > 0 ? offsetX : 0, offsetY);
6727     // background images are not scaled by transform
6728 
6729     this.css("background-size", viewportWidth * scale + "px " + viewportHeight * scale + "px");
6730     this.css("background-color", "transparent");
6731 
6732     if (section && section.properties.includes("page-spread-left")) {
6733       // set margin since scale is weird
6734       var marginLeft = width - viewportWidth * scale;
6735       this.css("margin-left", marginLeft + "px");
6736     }
6737   }
6738   /**
6739    * Set the direction of the text
6740    * @param {string} [dir="ltr"] "rtl" | "ltr"
6741    */
6742 
6743 
6744   direction(dir) {
6745     if (this.documentElement) {
6746       this.documentElement.style["direction"] = dir;
6747     }
6748   }
6749 
6750   mapPage(cfiBase, layout, start, end, dev) {
6751     var mapping = new _mapping__WEBPACK_IMPORTED_MODULE_3__[/* default */ "a"](layout, dev);
6752     return mapping.page(this, cfiBase, start, end);
6753   }
6754   /**
6755    * Emit event when link in content is clicked
6756    * @private
6757    */
6758 
6759 
6760   linksHandler() {
6761     Object(_utils_replacements__WEBPACK_IMPORTED_MODULE_4__[/* replaceLinks */ "c"])(this.content, href => {
6762       this.emit(_utils_constants__WEBPACK_IMPORTED_MODULE_5__[/* EVENTS */ "c"].CONTENTS.LINK_CLICKED, href);
6763     });
6764   }
6765   /**
6766    * Set the writingMode of the text
6767    * @param {string} [mode="horizontal-tb"] "horizontal-tb" | "vertical-rl" | "vertical-lr"
6768    */
6769 
6770 
6771   writingMode(mode) {
6772     let WRITING_MODE = Object(_utils_core__WEBPACK_IMPORTED_MODULE_1__["prefixed"])("writing-mode");
6773 
6774     if (mode && this.documentElement) {
6775       this.documentElement.style[WRITING_MODE] = mode;
6776     }
6777 
6778     return this.window.getComputedStyle(this.documentElement)[WRITING_MODE] || '';
6779   }
6780   /**
6781    * Set the layoutStyle of the content
6782    * @param {string} [style="paginated"] "scrolling" | "paginated"
6783    * @private
6784    */
6785 
6786 
6787   layoutStyle(style) {
6788     if (style) {
6789       this._layoutStyle = style;
6790       navigator.epubReadingSystem.layoutStyle = this._layoutStyle;
6791     }
6792 
6793     return this._layoutStyle || "paginated";
6794   }
6795   /**
6796    * Add the epubReadingSystem object to the navigator
6797    * @param {string} name
6798    * @param {string} version
6799    * @private
6800    */
6801 
6802 
6803   epubReadingSystem(name, version) {
6804     navigator.epubReadingSystem = {
6805       name: name,
6806       version: version,
6807       layoutStyle: this.layoutStyle(),
6808       hasFeature: function (feature) {
6809         switch (feature) {
6810           case "dom-manipulation":
6811             return true;
6812 
6813           case "layout-changes":
6814             return true;
6815 
6816           case "touch-events":
6817             return true;
6818 
6819           case "mouse-events":
6820             return true;
6821 
6822           case "keyboard-events":
6823             return true;
6824 
6825           case "spine-scripting":
6826             return false;
6827 
6828           default:
6829             return false;
6830         }
6831       }
6832     };
6833     return navigator.epubReadingSystem;
6834   }
6835 
6836   destroy() {
6837     // this.document.removeEventListener('transitionend', this._resizeCheck);
6838     this.removeListeners();
6839   }
6840 
6841 }
6842 
6843 event_emitter__WEBPACK_IMPORTED_MODULE_0___default()(Contents.prototype);
6844 /* harmony default export */ __webpack_exports__["a"] = (Contents);
6845 
6846 /***/ }),
6847 /* 13 */
6848 /***/ (function(module, exports, __webpack_require__) {
6849 
6850 "use strict";
6851 
6852 
6853 Object.defineProperty(exports, "__esModule", {
6854     value: true
6855 });
6856 exports.Underline = exports.Highlight = exports.Mark = exports.Pane = undefined;
6857 
6858 var _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } };
6859 
6860 var _createClass = function () { function 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
6861 
6862 var _svg = __webpack_require__(49);
6863 
6864 var _svg2 = _interopRequireDefault(_svg);
6865 
6866 var _events = __webpack_require__(50);
6867 
6868 var _events2 = _interopRequireDefault(_events);
6869 
6870 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
6871 
6872 function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
6873 
6874 function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
6875 
6876 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
6877 
6878 var Pane = exports.Pane = function () {
6879     function Pane(target) {
6880         var container = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : document.body;
6881 
6882         _classCallCheck(this, Pane);
6883 
6884         this.target = target;
6885         this.element = _svg2.default.createElement('svg');
6886         this.marks = [];
6887 
6888         // Match the coordinates of the target element
6889         this.element.style.position = 'absolute';
6890         // Disable pointer events
6891         this.element.setAttribute('pointer-events', 'none');
6892 
6893         // Set up mouse event proxying between the target element and the marks
6894         _events2.default.proxyMouse(this.target, this.marks);
6895 
6896         this.container = container;
6897         this.container.appendChild(this.element);
6898 
6899         this.render();
6900     }
6901 
6902     _createClass(Pane, [{
6903         key: 'addMark',
6904         value: function addMark(mark) {
6905             var g = _svg2.default.createElement('g');
6906             this.element.appendChild(g);
6907             mark.bind(g, this.container);
6908 
6909             this.marks.push(mark);
6910 
6911             mark.render();
6912             return mark;
6913         }
6914     }, {
6915         key: 'removeMark',
6916         value: function removeMark(mark) {
6917             var idx = this.marks.indexOf(mark);
6918             if (idx === -1) {
6919                 return;
6920             }
6921             var el = mark.unbind();
6922             this.element.removeChild(el);
6923             this.marks.splice(idx, 1);
6924         }
6925     }, {
6926         key: 'render',
6927         value: function render() {
6928             setCoords(this.element, coords(this.target, this.container));
6929             var _iteratorNormalCompletion = true;
6930             var _didIteratorError = false;
6931             var _iteratorError = undefined;
6932 
6933             try {
6934                 for (var _iterator = this.marks[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
6935                     var m = _step.value;
6936 
6937                     m.render();
6938                 }
6939             } catch (err) {
6940                 _didIteratorError = true;
6941                 _iteratorError = err;
6942             } finally {
6943                 try {
6944                     if (!_iteratorNormalCompletion && _iterator.return) {
6945                         _iterator.return();
6946                     }
6947                 } finally {
6948                     if (_didIteratorError) {
6949                         throw _iteratorError;
6950                     }
6951                 }
6952             }
6953         }
6954     }]);
6955 
6956     return Pane;
6957 }();
6958 
6959 var Mark = exports.Mark = function () {
6960     function Mark() {
6961         _classCallCheck(this, Mark);
6962 
6963         this.element = null;
6964     }
6965 
6966     _createClass(Mark, [{
6967         key: 'bind',
6968         value: function bind(element, container) {
6969             this.element = element;
6970             this.container = container;
6971         }
6972     }, {
6973         key: 'unbind',
6974         value: function unbind() {
6975             var el = this.element;
6976             this.element = null;
6977             return el;
6978         }
6979     }, {
6980         key: 'render',
6981         value: function render() {}
6982     }, {
6983         key: 'dispatchEvent',
6984         value: function dispatchEvent(e) {
6985             if (!this.element) return;
6986             this.element.dispatchEvent(e);
6987         }
6988     }, {
6989         key: 'getBoundingClientRect',
6990         value: function getBoundingClientRect() {
6991             return this.element.getBoundingClientRect();
6992         }
6993     }, {
6994         key: 'getClientRects',
6995         value: function getClientRects() {
6996             var rects = [];
6997             var el = this.element.firstChild;
6998             while (el) {
6999                 rects.push(el.getBoundingClientRect());
7000                 el = el.nextSibling;
7001             }
7002             return rects;
7003         }
7004     }, {
7005         key: 'filteredRanges',
7006         value: function filteredRanges() {
7007             var rects = Array.from(this.range.getClientRects());
7008 
7009             // De-duplicate the boxes
7010             return rects.filter(function (box) {
7011                 for (var i = 0; i < rects.length; i++) {
7012                     if (rects[i] === box) {
7013                         return true;
7014                     }
7015                     var contained = contains(rects[i], box);
7016                     if (contained) {
7017                         return false;
7018                     }
7019                 }
7020                 return true;
7021             });
7022         }
7023     }]);
7024 
7025     return Mark;
7026 }();
7027 
7028 var Highlight = exports.Highlight = function (_Mark) {
7029     _inherits(Highlight, _Mark);
7030 
7031     function Highlight(range, className, data, attributes) {
7032         _classCallCheck(this, Highlight);
7033 
7034         var _this = _possibleConstructorReturn(this, (Highlight.__proto__ || Object.getPrototypeOf(Highlight)).call(this));
7035 
7036         _this.range = range;
7037         _this.className = className;
7038         _this.data = data || {};
7039         _this.attributes = attributes || {};
7040         return _this;
7041     }
7042 
7043     _createClass(Highlight, [{
7044         key: 'bind',
7045         value: function bind(element, container) {
7046             _get(Highlight.prototype.__proto__ || Object.getPrototypeOf(Highlight.prototype), 'bind', this).call(this, element, container);
7047 
7048             for (var attr in this.data) {
7049                 if (this.data.hasOwnProperty(attr)) {
7050                     this.element.dataset[attr] = this.data[attr];
7051                 }
7052             }
7053 
7054             for (var attr in this.attributes) {
7055                 if (this.attributes.hasOwnProperty(attr)) {
7056                     this.element.setAttribute(attr, this.attributes[attr]);
7057                 }
7058             }
7059 
7060             if (this.className) {
7061                 this.element.classList.add(this.className);
7062             }
7063         }
7064     }, {
7065         key: 'render',
7066         value: function render() {
7067             // Empty element
7068             while (this.element.firstChild) {
7069                 this.element.removeChild(this.element.firstChild);
7070             }
7071 
7072             var docFrag = this.element.ownerDocument.createDocumentFragment();
7073             var filtered = this.filteredRanges();
7074             var offset = this.element.getBoundingClientRect();
7075             var container = this.container.getBoundingClientRect();
7076 
7077             for (var i = 0, len = filtered.length; i < len; i++) {
7078                 var r = filtered[i];
7079                 var el = _svg2.default.createElement('rect');
7080                 el.setAttribute('x', r.left - offset.left + container.left);
7081                 el.setAttribute('y', r.top - offset.top + container.top);
7082                 el.setAttribute('height', r.height);
7083                 el.setAttribute('width', r.width);
7084                 docFrag.appendChild(el);
7085             }
7086 
7087             this.element.appendChild(docFrag);
7088         }
7089     }]);
7090 
7091     return Highlight;
7092 }(Mark);
7093 
7094 var Underline = exports.Underline = function (_Highlight) {
7095     _inherits(Underline, _Highlight);
7096 
7097     function Underline(range, className, data, attributes) {
7098         _classCallCheck(this, Underline);
7099 
7100         return _possibleConstructorReturn(this, (Underline.__proto__ || Object.getPrototypeOf(Underline)).call(this, range, className, data, attributes));
7101     }
7102 
7103     _createClass(Underline, [{
7104         key: 'render',
7105         value: function render() {
7106             // Empty element
7107             while (this.element.firstChild) {
7108                 this.element.removeChild(this.element.firstChild);
7109             }
7110 
7111             var docFrag = this.element.ownerDocument.createDocumentFragment();
7112             var filtered = this.filteredRanges();
7113             var offset = this.element.getBoundingClientRect();
7114             var container = this.container.getBoundingClientRect();
7115 
7116             for (var i = 0, len = filtered.length; i < len; i++) {
7117                 var r = filtered[i];
7118 
7119                 var rect = _svg2.default.createElement('rect');
7120                 rect.setAttribute('x', r.left - offset.left + container.left);
7121                 rect.setAttribute('y', r.top - offset.top + container.top);
7122                 rect.setAttribute('height', r.height);
7123                 rect.setAttribute('width', r.width);
7124                 rect.setAttribute('fill', 'none');
7125 
7126                 var line = _svg2.default.createElement('line');
7127                 line.setAttribute('x1', r.left - offset.left + container.left);
7128                 line.setAttribute('x2', r.left - offset.left + container.left + r.width);
7129                 line.setAttribute('y1', r.top - offset.top + container.top + r.height - 1);
7130                 line.setAttribute('y2', r.top - offset.top + container.top + r.height - 1);
7131 
7132                 line.setAttribute('stroke-width', 1);
7133                 line.setAttribute('stroke', 'black'); //TODO: match text color?
7134                 line.setAttribute('stroke-linecap', 'square');
7135 
7136                 docFrag.appendChild(rect);
7137 
7138                 docFrag.appendChild(line);
7139             }
7140 
7141             this.element.appendChild(docFrag);
7142         }
7143     }]);
7144 
7145     return Underline;
7146 }(Highlight);
7147 
7148 function coords(el, container) {
7149     var offset = container.getBoundingClientRect();
7150     var rect = el.getBoundingClientRect();
7151 
7152     return {
7153         top: rect.top - offset.top,
7154         left: rect.left - offset.left,
7155         height: el.scrollHeight,
7156         width: el.scrollWidth
7157     };
7158 }
7159 
7160 function setCoords(el, coords) {
7161     el.style.setProperty('top', coords.top + 'px', 'important');
7162     el.style.setProperty('left', coords.left + 'px', 'important');
7163     el.style.setProperty('height', coords.height + 'px', 'important');
7164     el.style.setProperty('width', coords.width + 'px', 'important');
7165 }
7166 
7167 function contains(rect1, rect2) {
7168     return rect2.right <= rect1.right && rect2.left >= rect1.left && rect2.top >= rect1.top && rect2.bottom <= rect1.bottom;
7169 }
7170 
7171 
7172 /***/ }),
7173 /* 14 */
7174 /***/ (function(module, exports, __webpack_require__) {
7175 
7176 "use strict";
7177 
7178 
7179 /**
7180  * "Shallow freezes" an object to render it immutable.
7181  * Uses `Object.freeze` if available,
7182  * otherwise the immutability is only in the type.
7183  *
7184  * Is used to create "enum like" objects.
7185  *
7186  * @template T
7187  * @param {T} object the object to freeze
7188  * @param {Pick<ObjectConstructor, 'freeze'> = Object} oc `Object` by default,
7189  *                              allows to inject custom object constructor for tests
7190  * @returns {Readonly<T>}
7191  *
7192  * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze
7193  */
7194 function freeze(object, oc) {
7195         if (oc === undefined) {
7196                 oc = Object
7197         }
7198         return oc && typeof oc.freeze === 'function' ? oc.freeze(object) : object
7199 }
7200 
7201 /**
7202  * All mime types that are allowed as input to `DOMParser.parseFromString`
7203  *
7204  * @see https://developer.mozilla.org/en-US/docs/Web/API/DOMParser/parseFromString#Argument02 MDN
7205  * @see https://html.spec.whatwg.org/multipage/dynamic-markup-insertion.html#domparsersupportedtype WHATWG HTML Spec
7206  * @see DOMParser.prototype.parseFromString
7207  */
7208 var MIME_TYPE = freeze({
7209         /**
7210          * `text/html`, the only mime type that triggers treating an XML document as HTML.
7211          *
7212          * @see DOMParser.SupportedType.isHTML
7213          * @see https://www.iana.org/assignments/media-types/text/html IANA MimeType registration
7214          * @see https://en.wikipedia.org/wiki/HTML Wikipedia
7215          * @see https://developer.mozilla.org/en-US/docs/Web/API/DOMParser/parseFromString MDN
7216          * @see https://html.spec.whatwg.org/multipage/dynamic-markup-insertion.html#dom-domparser-parsefromstring WHATWG HTML Spec
7217          */
7218         HTML: 'text/html',
7219 
7220         /**
7221          * Helper method to check a mime type if it indicates an HTML document
7222          *
7223          * @param {string} [value]
7224          * @returns {boolean}
7225          *
7226          * @see https://www.iana.org/assignments/media-types/text/html IANA MimeType registration
7227          * @see https://en.wikipedia.org/wiki/HTML Wikipedia
7228          * @see https://developer.mozilla.org/en-US/docs/Web/API/DOMParser/parseFromString MDN
7229          * @see https://html.spec.whatwg.org/multipage/dynamic-markup-insertion.html#dom-domparser-parsefromstring       */
7230         isHTML: function (value) {
7231                 return value === MIME_TYPE.HTML
7232         },
7233 
7234         /**
7235          * `application/xml`, the standard mime type for XML documents.
7236          *
7237          * @see https://www.iana.org/assignments/media-types/application/xml IANA MimeType registration
7238          * @see https://tools.ietf.org/html/rfc7303#section-9.1 RFC 7303
7239          * @see https://en.wikipedia.org/wiki/XML_and_MIME Wikipedia
7240          */
7241         XML_APPLICATION: 'application/xml',
7242 
7243         /**
7244          * `text/html`, an alias for `application/xml`.
7245          *
7246          * @see https://tools.ietf.org/html/rfc7303#section-9.2 RFC 7303
7247          * @see https://www.iana.org/assignments/media-types/text/xml IANA MimeType registration
7248          * @see https://en.wikipedia.org/wiki/XML_and_MIME Wikipedia
7249          */
7250         XML_TEXT: 'text/xml',
7251 
7252         /**
7253          * `application/xhtml+xml`, indicates an XML document that has the default HTML namespace,
7254          * but is parsed as an XML document.
7255          *
7256          * @see https://www.iana.org/assignments/media-types/application/xhtml+xml IANA MimeType registration
7257          * @see https://dom.spec.whatwg.org/#dom-domimplementation-createdocument WHATWG DOM Spec
7258          * @see https://en.wikipedia.org/wiki/XHTML Wikipedia
7259          */
7260         XML_XHTML_APPLICATION: 'application/xhtml+xml',
7261 
7262         /**
7263          * `image/svg+xml`,
7264          *
7265          * @see https://www.iana.org/assignments/media-types/image/svg+xml IANA MimeType registration
7266          * @see https://www.w3.org/TR/SVG11/ W3C SVG 1.1
7267          * @see https://en.wikipedia.org/wiki/Scalable_Vector_Graphics Wikipedia
7268          */
7269         XML_SVG_IMAGE: 'image/svg+xml',
7270 })
7271 
7272 /**
7273  * Namespaces that are used in this code base.
7274  *
7275  * @see http://www.w3.org/TR/REC-xml-names
7276  */
7277 var NAMESPACE = freeze({
7278         /**
7279          * The XHTML namespace.
7280          *
7281          * @see http://www.w3.org/1999/xhtml
7282          */
7283         HTML: 'http://www.w3.org/1999/xhtml',
7284 
7285         /**
7286          * Checks if `uri` equals `NAMESPACE.HTML`.
7287          *
7288          * @param {string} [uri]
7289          *
7290          * @see NAMESPACE.HTML
7291          */
7292         isHTML: function (uri) {
7293                 return uri === NAMESPACE.HTML
7294         },
7295 
7296         /**
7297          * The SVG namespace.
7298          *
7299          * @see http://www.w3.org/2000/svg
7300          */
7301         SVG: 'http://www.w3.org/2000/svg',
7302 
7303         /**
7304          * The `xml:` namespace.
7305          *
7306          * @see http://www.w3.org/XML/1998/namespace
7307          */
7308         XML: 'http://www.w3.org/XML/1998/namespace',
7309 
7310         /**
7311          * The `xmlns:` namespace
7312          *
7313          * @see https://www.w3.org/2000/xmlns/
7314          */
7315         XMLNS: 'http://www.w3.org/2000/xmlns/',
7316 })
7317 
7318 exports.freeze = freeze;
7319 exports.MIME_TYPE = MIME_TYPE;
7320 exports.NAMESPACE = NAMESPACE;
7321 
7322 
7323 /***/ }),
7324 /* 15 */
7325 /***/ (function(module, exports, __webpack_require__) {
7326 
7327 var dom = __webpack_require__(25)
7328 exports.DOMImplementation = dom.DOMImplementation
7329 exports.XMLSerializer = dom.XMLSerializer
7330 exports.DOMParser = __webpack_require__(46).DOMParser
7331 
7332 
7333 /***/ }),
7334 /* 16 */
7335 /***/ (function(module, __webpack_exports__, __webpack_require__) {
7336 
7337 "use strict";
7338 
7339 // EXTERNAL MODULE: ./node_modules/event-emitter/index.js
7340 var event_emitter = __webpack_require__(3);
7341 var event_emitter_default = /*#__PURE__*/__webpack_require__.n(event_emitter);
7342 
7343 // EXTERNAL MODULE: ./src/utils/core.js
7344 var core = __webpack_require__(0);
7345 
7346 // EXTERNAL MODULE: ./src/utils/hook.js
7347 var hook = __webpack_require__(6);
7348 
7349 // EXTERNAL MODULE: ./src/epubcfi.js
7350 var src_epubcfi = __webpack_require__(2);
7351 
7352 // EXTERNAL MODULE: ./src/utils/queue.js
7353 var queue = __webpack_require__(9);
7354 
7355 // EXTERNAL MODULE: ./src/utils/constants.js
7356 var constants = __webpack_require__(1);
7357 
7358 // CONCATENATED MODULE: ./src/layout.js
7359 
7360 
7361 
7362 /**
7363  * Figures out the CSS values to apply for a layout
7364  * @class
7365  * @param {object} settings
7366  * @param {string} [settings.layout='reflowable']
7367  * @param {string} [settings.spread]
7368  * @param {number} [settings.minSpreadWidth=800]
7369  * @param {boolean} [settings.evenSpreads=false]
7370  */
7371 
7372 class layout_Layout {
7373   constructor(settings) {
7374     this.settings = settings;
7375     this.name = settings.layout || "reflowable";
7376     this._spread = settings.spread === "none" ? false : true;
7377     this._minSpreadWidth = settings.minSpreadWidth || 800;
7378     this._evenSpreads = settings.evenSpreads || false;
7379 
7380     if (settings.flow === "scrolled" || settings.flow === "scrolled-continuous" || settings.flow === "scrolled-doc") {
7381       this._flow = "scrolled";
7382     } else {
7383       this._flow = "paginated";
7384     }
7385 
7386     this.width = 0;
7387     this.height = 0;
7388     this.spreadWidth = 0;
7389     this.delta = 0;
7390     this.columnWidth = 0;
7391     this.gap = 0;
7392     this.divisor = 1;
7393     this.props = {
7394       name: this.name,
7395       spread: this._spread,
7396       flow: this._flow,
7397       width: 0,
7398       height: 0,
7399       spreadWidth: 0,
7400       delta: 0,
7401       columnWidth: 0,
7402       gap: 0,
7403       divisor: 1
7404     };
7405   }
7406   /**
7407    * Switch the flow between paginated and scrolled
7408    * @param  {string} flow paginated | scrolled
7409    * @return {string} simplified flow
7410    */
7411 
7412 
7413   flow(flow) {
7414     if (typeof flow != "undefined") {
7415       if (flow === "scrolled" || flow === "scrolled-continuous" || flow === "scrolled-doc") {
7416         this._flow = "scrolled";
7417       } else {
7418         this._flow = "paginated";
7419       } // this.props.flow = this._flow;
7420 
7421 
7422       this.update({
7423         flow: this._flow
7424       });
7425     }
7426 
7427     return this._flow;
7428   }
7429   /**
7430    * Switch between using spreads or not, and set the
7431    * width at which they switch to single.
7432    * @param  {string} spread "none" | "always" | "auto"
7433    * @param  {number} min integer in pixels
7434    * @return {boolean} spread true | false
7435    */
7436 
7437 
7438   spread(spread, min) {
7439     if (spread) {
7440       this._spread = spread === "none" ? false : true; // this.props.spread = this._spread;
7441 
7442       this.update({
7443         spread: this._spread
7444       });
7445     }
7446 
7447     if (min >= 0) {
7448       this._minSpreadWidth = min;
7449     }
7450 
7451     return this._spread;
7452   }
7453   /**
7454    * Calculate the dimensions of the pagination
7455    * @param  {number} _width  width of the rendering
7456    * @param  {number} _height height of the rendering
7457    * @param  {number} _gap    width of the gap between columns
7458    */
7459 
7460 
7461   calculate(_width, _height, _gap) {
7462     var divisor = 1;
7463     var gap = _gap || 0; //-- Check the width and create even width columns
7464     // var fullWidth = Math.floor(_width);
7465 
7466     var width = _width;
7467     var height = _height;
7468     var section = Math.floor(width / 12);
7469     var columnWidth;
7470     var spreadWidth;
7471     var pageWidth;
7472     var delta;
7473 
7474     if (this._spread && width >= this._minSpreadWidth) {
7475       divisor = 2;
7476     } else {
7477       divisor = 1;
7478     }
7479 
7480     if (this.name === "reflowable" && this._flow === "paginated" && !(_gap >= 0)) {
7481       gap = section % 2 === 0 ? section : section - 1;
7482     }
7483 
7484     if (this.name === "pre-paginated") {
7485       gap = 0;
7486     } //-- Double Page
7487 
7488 
7489     if (divisor > 1) {
7490       // width = width - gap;
7491       // columnWidth = (width - gap) / divisor;
7492       // gap = gap / divisor;
7493       columnWidth = width / divisor - gap;
7494       pageWidth = columnWidth + gap;
7495     } else {
7496       columnWidth = width;
7497       pageWidth = width;
7498     }
7499 
7500     if (this.name === "pre-paginated" && divisor > 1) {
7501       width = columnWidth;
7502     }
7503 
7504     spreadWidth = columnWidth * divisor + gap;
7505     delta = width;
7506     this.width = width;
7507     this.height = height;
7508     this.spreadWidth = spreadWidth;
7509     this.pageWidth = pageWidth;
7510     this.delta = delta;
7511     this.columnWidth = columnWidth;
7512     this.gap = gap;
7513     this.divisor = divisor; // this.props.width = width;
7514     // this.props.height = _height;
7515     // this.props.spreadWidth = spreadWidth;
7516     // this.props.pageWidth = pageWidth;
7517     // this.props.delta = delta;
7518     //
7519     // this.props.columnWidth = colWidth;
7520     // this.props.gap = gap;
7521     // this.props.divisor = divisor;
7522 
7523     this.update({
7524       width,
7525       height,
7526       spreadWidth,
7527       pageWidth,
7528       delta,
7529       columnWidth,
7530       gap,
7531       divisor
7532     });
7533   }
7534   /**
7535    * Apply Css to a Document
7536    * @param  {Contents} contents
7537    * @return {Promise}
7538    */
7539 
7540 
7541   format(contents, section, axis) {
7542     var formating;
7543 
7544     if (this.name === "pre-paginated") {
7545       formating = contents.fit(this.columnWidth, this.height, section);
7546     } else if (this._flow === "paginated") {
7547       formating = contents.columns(this.width, this.height, this.columnWidth, this.gap, this.settings.direction);
7548     } else if (axis && axis === "horizontal") {
7549       formating = contents.size(null, this.height);
7550     } else {
7551       formating = contents.size(this.width, null);
7552     }
7553 
7554     return formating; // might be a promise in some View Managers
7555   }
7556   /**
7557    * Count number of pages
7558    * @param  {number} totalLength
7559    * @param  {number} pageLength
7560    * @return {{spreads: Number, pages: Number}}
7561    */
7562 
7563 
7564   count(totalLength, pageLength) {
7565     let spreads, pages;
7566 
7567     if (this.name === "pre-paginated") {
7568       spreads = 1;
7569       pages = 1;
7570     } else if (this._flow === "paginated") {
7571       pageLength = pageLength || this.delta;
7572       spreads = Math.ceil(totalLength / pageLength);
7573       pages = spreads * this.divisor;
7574     } else {
7575       // scrolled
7576       pageLength = pageLength || this.height;
7577       spreads = Math.ceil(totalLength / pageLength);
7578       pages = spreads;
7579     }
7580 
7581     return {
7582       spreads,
7583       pages
7584     };
7585   }
7586   /**
7587    * Update props that have changed
7588    * @private
7589    * @param  {object} props
7590    */
7591 
7592 
7593   update(props) {
7594     // Remove props that haven't changed
7595     Object.keys(props).forEach(propName => {
7596       if (this.props[propName] === props[propName]) {
7597         delete props[propName];
7598       }
7599     });
7600 
7601     if (Object.keys(props).length > 0) {
7602       let newProps = Object(core["extend"])(this.props, props);
7603       this.emit(constants["c" /* EVENTS */].LAYOUT.UPDATED, newProps, props);
7604     }
7605   }
7606 
7607 }
7608 
7609 event_emitter_default()(layout_Layout.prototype);
7610 /* harmony default export */ var layout = (layout_Layout);
7611 // EXTERNAL MODULE: ./src/utils/url.js
7612 var utils_url = __webpack_require__(5);
7613 
7614 // CONCATENATED MODULE: ./src/themes.js
7615 
7616 /**
7617  * Themes to apply to displayed content
7618  * @class
7619  * @param {Rendition} rendition
7620  */
7621 
7622 class themes_Themes {
7623   constructor(rendition) {
7624     this.rendition = rendition;
7625     this._themes = {
7626       "default": {
7627         "rules": {},
7628         "url": "",
7629         "serialized": ""
7630       }
7631     };
7632     this._overrides = {};
7633     this._current = "default";
7634     this._injected = [];
7635     this.rendition.hooks.content.register(this.inject.bind(this));
7636     this.rendition.hooks.content.register(this.overrides.bind(this));
7637   }
7638   /**
7639    * Add themes to be used by a rendition
7640    * @param {object | Array<object> | string}
7641    * @example themes.register("light", "http://example.com/light.css")
7642    * @example themes.register("light", { "body": { "color": "purple"}})
7643    * @example themes.register({ "light" : {...}, "dark" : {...}})
7644    */
7645 
7646 
7647   register() {
7648     if (arguments.length === 0) {
7649       return;
7650     }
7651 
7652     if (arguments.length === 1 && typeof arguments[0] === "object") {
7653       return this.registerThemes(arguments[0]);
7654     }
7655 
7656     if (arguments.length === 1 && typeof arguments[0] === "string") {
7657       return this.default(arguments[0]);
7658     }
7659 
7660     if (arguments.length === 2 && typeof arguments[1] === "string") {
7661       return this.registerUrl(arguments[0], arguments[1]);
7662     }
7663 
7664     if (arguments.length === 2 && typeof arguments[1] === "object") {
7665       return this.registerRules(arguments[0], arguments[1]);
7666     }
7667   }
7668   /**
7669    * Add a default theme to be used by a rendition
7670    * @param {object | string} theme
7671    * @example themes.register("http://example.com/default.css")
7672    * @example themes.register({ "body": { "color": "purple"}})
7673    */
7674 
7675 
7676   default(theme) {
7677     if (!theme) {
7678       return;
7679     }
7680 
7681     if (typeof theme === "string") {
7682       return this.registerUrl("default", theme);
7683     }
7684 
7685     if (typeof theme === "object") {
7686       return this.registerRules("default", theme);
7687     }
7688   }
7689   /**
7690    * Register themes object
7691    * @param {object} themes
7692    */
7693 
7694 
7695   registerThemes(themes) {
7696     for (var theme in themes) {
7697       if (themes.hasOwnProperty(theme)) {
7698         if (typeof themes[theme] === "string") {
7699           this.registerUrl(theme, themes[theme]);
7700         } else {
7701           this.registerRules(theme, themes[theme]);
7702         }
7703       }
7704     }
7705   }
7706   /**
7707    * Register a theme by passing its css as string
7708    * @param {string} name 
7709    * @param {string} css 
7710    */
7711 
7712 
7713   registerCss(name, css) {
7714     this._themes[name] = {
7715       "serialized": css
7716     };
7717 
7718     if (this._injected[name] || name == 'default') {
7719       this.update(name);
7720     }
7721   }
7722   /**
7723    * Register a url
7724    * @param {string} name
7725    * @param {string} input
7726    */
7727 
7728 
7729   registerUrl(name, input) {
7730     var url = new utils_url["a" /* default */](input);
7731     this._themes[name] = {
7732       "url": url.toString()
7733     };
7734 
7735     if (this._injected[name] || name == 'default') {
7736       this.update(name);
7737     }
7738   }
7739   /**
7740    * Register rule
7741    * @param {string} name
7742    * @param {object} rules
7743    */
7744 
7745 
7746   registerRules(name, rules) {
7747     this._themes[name] = {
7748       "rules": rules
7749     }; // TODO: serialize css rules
7750 
7751     if (this._injected[name] || name == 'default') {
7752       this.update(name);
7753     }
7754   }
7755   /**
7756    * Select a theme
7757    * @param {string} name
7758    */
7759 
7760 
7761   select(name) {
7762     var prev = this._current;
7763     var contents;
7764     this._current = name;
7765     this.update(name);
7766     contents = this.rendition.getContents();
7767     contents.forEach(content => {
7768       content.removeClass(prev);
7769       content.addClass(name);
7770     });
7771   }
7772   /**
7773    * Update a theme
7774    * @param {string} name
7775    */
7776 
7777 
7778   update(name) {
7779     var contents = this.rendition.getContents();
7780     contents.forEach(content => {
7781       this.add(name, content);
7782     });
7783   }
7784   /**
7785    * Inject all themes into contents
7786    * @param {Contents} contents
7787    */
7788 
7789 
7790   inject(contents) {
7791     var links = [];
7792     var themes = this._themes;
7793     var theme;
7794 
7795     for (var name in themes) {
7796       if (themes.hasOwnProperty(name) && (name === this._current || name === "default")) {
7797         theme = themes[name];
7798 
7799         if (theme.rules && Object.keys(theme.rules).length > 0 || theme.url && links.indexOf(theme.url) === -1) {
7800           this.add(name, contents);
7801         }
7802 
7803         this._injected.push(name);
7804       }
7805     }
7806 
7807     if (this._current != "default") {
7808       contents.addClass(this._current);
7809     }
7810   }
7811   /**
7812    * Add Theme to contents
7813    * @param {string} name
7814    * @param {Contents} contents
7815    */
7816 
7817 
7818   add(name, contents) {
7819     var theme = this._themes[name];
7820 
7821     if (!theme || !contents) {
7822       return;
7823     }
7824 
7825     if (theme.url) {
7826       contents.addStylesheet(theme.url);
7827     } else if (theme.serialized) {
7828       contents.addStylesheetCss(theme.serialized, name);
7829       theme.injected = true;
7830     } else if (theme.rules) {
7831       contents.addStylesheetRules(theme.rules, name);
7832       theme.injected = true;
7833     }
7834   }
7835   /**
7836    * Add override
7837    * @param {string} name
7838    * @param {string} value
7839    * @param {boolean} priority
7840    */
7841 
7842 
7843   override(name, value, priority) {
7844     var contents = this.rendition.getContents();
7845     this._overrides[name] = {
7846       value: value,
7847       priority: priority === true
7848     };
7849     contents.forEach(content => {
7850       content.css(name, this._overrides[name].value, this._overrides[name].priority);
7851     });
7852   }
7853 
7854   removeOverride(name) {
7855     var contents = this.rendition.getContents();
7856     delete this._overrides[name];
7857     contents.forEach(content => {
7858       content.css(name);
7859     });
7860   }
7861   /**
7862    * Add all overrides
7863    * @param {Content} content
7864    */
7865 
7866 
7867   overrides(contents) {
7868     var overrides = this._overrides;
7869 
7870     for (var rule in overrides) {
7871       if (overrides.hasOwnProperty(rule)) {
7872         contents.css(rule, overrides[rule].value, overrides[rule].priority);
7873       }
7874     }
7875   }
7876   /**
7877    * Adjust the font size of a rendition
7878    * @param {number} size
7879    */
7880 
7881 
7882   fontSize(size) {
7883     this.override("font-size", size);
7884   }
7885   /**
7886    * Adjust the font-family of a rendition
7887    * @param {string} f
7888    */
7889 
7890 
7891   font(f) {
7892     this.override("font-family", f, true);
7893   }
7894 
7895   destroy() {
7896     this.rendition = undefined;
7897     this._themes = undefined;
7898     this._overrides = undefined;
7899     this._current = undefined;
7900     this._injected = undefined;
7901   }
7902 
7903 }
7904 
7905 /* harmony default export */ var themes = (themes_Themes);
7906 // EXTERNAL MODULE: ./src/contents.js
7907 var src_contents = __webpack_require__(12);
7908 
7909 // CONCATENATED MODULE: ./src/annotations.js
7910 
7911 
7912 
7913 /**
7914         * Handles managing adding & removing Annotations
7915         * @param {Rendition} rendition
7916         * @class
7917         */
7918 
7919 class annotations_Annotations {
7920   constructor(rendition) {
7921     this.rendition = rendition;
7922     this.highlights = [];
7923     this.underlines = [];
7924     this.marks = [];
7925     this._annotations = {};
7926     this._annotationsBySectionIndex = {};
7927     this.rendition.hooks.render.register(this.inject.bind(this));
7928     this.rendition.hooks.unloaded.register(this.clear.bind(this));
7929   }
7930   /**
7931    * Add an annotation to store
7932    * @param {string} type Type of annotation to add: "highlight", "underline", "mark"
7933    * @param {EpubCFI} cfiRange EpubCFI range to attach annotation to
7934    * @param {object} data Data to assign to annotation
7935    * @param {function} [cb] Callback after annotation is added
7936    * @param {string} className CSS class to assign to annotation
7937    * @param {object} styles CSS styles to assign to annotation
7938    * @returns {Annotation} annotation
7939    */
7940 
7941 
7942   add(type, cfiRange, data, cb, className, styles) {
7943     let hash = encodeURI(cfiRange + type);
7944     let cfi = new src_epubcfi["a" /* default */](cfiRange);
7945     let sectionIndex = cfi.spinePos;
7946     let annotation = new annotations_Annotation({
7947       type,
7948       cfiRange,
7949       data,
7950       sectionIndex,
7951       cb,
7952       className,
7953       styles
7954     });
7955     this._annotations[hash] = annotation;
7956 
7957     if (sectionIndex in this._annotationsBySectionIndex) {
7958       this._annotationsBySectionIndex[sectionIndex].push(hash);
7959     } else {
7960       this._annotationsBySectionIndex[sectionIndex] = [hash];
7961     }
7962 
7963     let views = this.rendition.views();
7964     views.forEach(view => {
7965       if (annotation.sectionIndex === view.index) {
7966         annotation.attach(view);
7967       }
7968     });
7969     return annotation;
7970   }
7971   /**
7972    * Remove an annotation from store
7973    * @param {EpubCFI} cfiRange EpubCFI range the annotation is attached to
7974    * @param {string} type Type of annotation to add: "highlight", "underline", "mark"
7975    */
7976 
7977 
7978   remove(cfiRange, type) {
7979     let hash = encodeURI(cfiRange + type);
7980 
7981     if (hash in this._annotations) {
7982       let annotation = this._annotations[hash];
7983 
7984       if (type && annotation.type !== type) {
7985         return;
7986       }
7987 
7988       let views = this.rendition.views();
7989       views.forEach(view => {
7990         this._removeFromAnnotationBySectionIndex(annotation.sectionIndex, hash);
7991 
7992         if (annotation.sectionIndex === view.index) {
7993           annotation.detach(view);
7994         }
7995       });
7996       delete this._annotations[hash];
7997     }
7998   }
7999   /**
8000    * Remove an annotations by Section Index
8001    * @private
8002    */
8003 
8004 
8005   _removeFromAnnotationBySectionIndex(sectionIndex, hash) {
8006     this._annotationsBySectionIndex[sectionIndex] = this._annotationsAt(sectionIndex).filter(h => h !== hash);
8007   }
8008   /**
8009    * Get annotations by Section Index
8010    * @private
8011    */
8012 
8013 
8014   _annotationsAt(index) {
8015     return this._annotationsBySectionIndex[index];
8016   }
8017   /**
8018    * Add a highlight to the store
8019    * @param {EpubCFI} cfiRange EpubCFI range to attach annotation to
8020    * @param {object} data Data to assign to annotation
8021    * @param {function} cb Callback after annotation is clicked
8022    * @param {string} className CSS class to assign to annotation
8023    * @param {object} styles CSS styles to assign to annotation
8024    */
8025 
8026 
8027   highlight(cfiRange, data, cb, className, styles) {
8028     return this.add("highlight", cfiRange, data, cb, className, styles);
8029   }
8030   /**
8031    * Add a underline to the store
8032    * @param {EpubCFI} cfiRange EpubCFI range to attach annotation to
8033    * @param {object} data Data to assign to annotation
8034    * @param {function} cb Callback after annotation is clicked
8035    * @param {string} className CSS class to assign to annotation
8036    * @param {object} styles CSS styles to assign to annotation
8037    */
8038 
8039 
8040   underline(cfiRange, data, cb, className, styles) {
8041     return this.add("underline", cfiRange, data, cb, className, styles);
8042   }
8043   /**
8044    * Add a mark to the store
8045    * @param {EpubCFI} cfiRange EpubCFI range to attach annotation to
8046    * @param {object} data Data to assign to annotation
8047    * @param {function} cb Callback after annotation is clicked
8048    */
8049 
8050 
8051   mark(cfiRange, data, cb) {
8052     return this.add("mark", cfiRange, data, cb);
8053   }
8054   /**
8055    * iterate over annotations in the store
8056    */
8057 
8058 
8059   each() {
8060     return this._annotations.forEach.apply(this._annotations, arguments);
8061   }
8062   /**
8063    * Hook for injecting annotation into a view
8064    * @param {View} view
8065    * @private
8066    */
8067 
8068 
8069   inject(view) {
8070     let sectionIndex = view.index;
8071 
8072     if (sectionIndex in this._annotationsBySectionIndex) {
8073       let annotations = this._annotationsBySectionIndex[sectionIndex];
8074       annotations.forEach(hash => {
8075         let annotation = this._annotations[hash];
8076         annotation.attach(view);
8077       });
8078     }
8079   }
8080   /**
8081    * Hook for removing annotation from a view
8082    * @param {View} view
8083    * @private
8084    */
8085 
8086 
8087   clear(view) {
8088     let sectionIndex = view.index;
8089 
8090     if (sectionIndex in this._annotationsBySectionIndex) {
8091       let annotations = this._annotationsBySectionIndex[sectionIndex];
8092       annotations.forEach(hash => {
8093         let annotation = this._annotations[hash];
8094         annotation.detach(view);
8095       });
8096     }
8097   }
8098   /**
8099    * [Not Implemented] Show annotations
8100    * @TODO: needs implementation in View
8101    */
8102 
8103 
8104   show() {}
8105   /**
8106    * [Not Implemented] Hide annotations
8107    * @TODO: needs implementation in View
8108    */
8109 
8110 
8111   hide() {}
8112 
8113 }
8114 /**
8115  * Annotation object
8116  * @class
8117  * @param {object} options
8118  * @param {string} options.type Type of annotation to add: "highlight", "underline", "mark"
8119  * @param {EpubCFI} options.cfiRange EpubCFI range to attach annotation to
8120  * @param {object} options.data Data to assign to annotation
8121  * @param {int} options.sectionIndex Index in the Spine of the Section annotation belongs to
8122  * @param {function} [options.cb] Callback after annotation is clicked
8123  * @param {string} className CSS class to assign to annotation
8124  * @param {object} styles CSS styles to assign to annotation
8125  * @returns {Annotation} annotation
8126  */
8127 
8128 
8129 class annotations_Annotation {
8130   constructor({
8131     type,
8132     cfiRange,
8133     data,
8134     sectionIndex,
8135     cb,
8136     className,
8137     styles
8138   }) {
8139     this.type = type;
8140     this.cfiRange = cfiRange;
8141     this.data = data;
8142     this.sectionIndex = sectionIndex;
8143     this.mark = undefined;
8144     this.cb = cb;
8145     this.className = className;
8146     this.styles = styles;
8147   }
8148   /**
8149    * Update stored data
8150    * @param {object} data
8151    */
8152 
8153 
8154   update(data) {
8155     this.data = data;
8156   }
8157   /**
8158    * Add to a view
8159    * @param {View} view
8160    */
8161 
8162 
8163   attach(view) {
8164     let {
8165       cfiRange,
8166       data,
8167       type,
8168       mark,
8169       cb,
8170       className,
8171       styles
8172     } = this;
8173     let result;
8174 
8175     if (type === "highlight") {
8176       result = view.highlight(cfiRange, data, cb, className, styles);
8177     } else if (type === "underline") {
8178       result = view.underline(cfiRange, data, cb, className, styles);
8179     } else if (type === "mark") {
8180       result = view.mark(cfiRange, data, cb);
8181     }
8182 
8183     this.mark = result;
8184     this.emit(constants["c" /* EVENTS */].ANNOTATION.ATTACH, result);
8185     return result;
8186   }
8187   /**
8188    * Remove from a view
8189    * @param {View} view
8190    */
8191 
8192 
8193   detach(view) {
8194     let {
8195       cfiRange,
8196       type
8197     } = this;
8198     let result;
8199 
8200     if (view) {
8201       if (type === "highlight") {
8202         result = view.unhighlight(cfiRange);
8203       } else if (type === "underline") {
8204         result = view.ununderline(cfiRange);
8205       } else if (type === "mark") {
8206         result = view.unmark(cfiRange);
8207       }
8208     }
8209 
8210     this.mark = undefined;
8211     this.emit(constants["c" /* EVENTS */].ANNOTATION.DETACH, result);
8212     return result;
8213   }
8214   /**
8215    * [Not Implemented] Get text of an annotation
8216    * @TODO: needs implementation in contents
8217    */
8218 
8219 
8220   text() {}
8221 
8222 }
8223 
8224 event_emitter_default()(annotations_Annotation.prototype);
8225 /* harmony default export */ var annotations = (annotations_Annotations);
8226 // EXTERNAL MODULE: ./src/managers/views/iframe.js
8227 var iframe = __webpack_require__(20);
8228 
8229 // EXTERNAL MODULE: ./src/managers/default/index.js + 3 modules
8230 var managers_default = __webpack_require__(10);
8231 
8232 // EXTERNAL MODULE: ./src/managers/continuous/index.js + 1 modules
8233 var continuous = __webpack_require__(22);
8234 
8235 // CONCATENATED MODULE: ./src/rendition.js
8236 
8237 
8238 
8239 
8240 
8241  // import Mapping from "./mapping";
8242 
8243 
8244 
8245 
8246  // Default Views
8247 
8248  // Default View Managers
8249 
8250 
8251 
8252 /**
8253  * Displays an Epub as a series of Views for each Section.
8254  * Requires Manager and View class to handle specifics of rendering
8255  * the section content.
8256  * @class
8257  * @param {Book} book
8258  * @param {object} [options]
8259  * @param {number} [options.width]
8260  * @param {number} [options.height]
8261  * @param {string} [options.ignoreClass] class for the cfi parser to ignore
8262  * @param {string | function | object} [options.manager='default']
8263  * @param {string | function} [options.view='iframe']
8264  * @param {string} [options.layout] layout to force
8265  * @param {string} [options.spread] force spread value
8266  * @param {number} [options.minSpreadWidth] overridden by spread: none (never) / both (always)
8267  * @param {string} [options.stylesheet] url of stylesheet to be injected
8268  * @param {boolean} [options.resizeOnOrientationChange] false to disable orientation events
8269  * @param {string} [options.script] url of script to be injected
8270  * @param {boolean | object} [options.snap=false] use snap scrolling
8271  * @param {string} [options.defaultDirection='ltr'] default text direction
8272  * @param {boolean} [options.allowScriptedContent=false] enable running scripts in content
8273  * @param {boolean} [options.allowPopups=false] enable opening popup in content
8274  */
8275 
8276 class rendition_Rendition {
8277   constructor(book, options) {
8278     this.settings = Object(core["extend"])(this.settings || {}, {
8279       width: null,
8280       height: null,
8281       ignoreClass: "",
8282       manager: "default",
8283       view: "iframe",
8284       flow: null,
8285       layout: null,
8286       spread: null,
8287       minSpreadWidth: 800,
8288       stylesheet: null,
8289       resizeOnOrientationChange: true,
8290       script: null,
8291       snap: false,
8292       defaultDirection: "ltr",
8293       allowScriptedContent: false,
8294       allowPopups: false
8295     });
8296     Object(core["extend"])(this.settings, options);
8297 
8298     if (typeof this.settings.manager === "object") {
8299       this.manager = this.settings.manager;
8300     }
8301 
8302     this.book = book;
8303     /**
8304      * Adds Hook methods to the Rendition prototype
8305      * @member {object} hooks
8306      * @property {Hook} hooks.content
8307      * @memberof Rendition
8308      */
8309 
8310     this.hooks = {};
8311     this.hooks.display = new hook["a" /* default */](this);
8312     this.hooks.serialize = new hook["a" /* default */](this);
8313     this.hooks.content = new hook["a" /* default */](this);
8314     this.hooks.unloaded = new hook["a" /* default */](this);
8315     this.hooks.layout = new hook["a" /* default */](this);
8316     this.hooks.render = new hook["a" /* default */](this);
8317     this.hooks.show = new hook["a" /* default */](this);
8318     this.hooks.content.register(this.handleLinks.bind(this));
8319     this.hooks.content.register(this.passEvents.bind(this));
8320     this.hooks.content.register(this.adjustImages.bind(this));
8321     this.book.spine.hooks.content.register(this.injectIdentifier.bind(this));
8322 
8323     if (this.settings.stylesheet) {
8324       this.book.spine.hooks.content.register(this.injectStylesheet.bind(this));
8325     }
8326 
8327     if (this.settings.script) {
8328       this.book.spine.hooks.content.register(this.injectScript.bind(this));
8329     }
8330     /**
8331      * @member {Themes} themes
8332      * @memberof Rendition
8333      */
8334 
8335 
8336     this.themes = new themes(this);
8337     /**
8338      * @member {Annotations} annotations
8339      * @memberof Rendition
8340      */
8341 
8342     this.annotations = new annotations(this);
8343     this.epubcfi = new src_epubcfi["a" /* default */]();
8344     this.q = new queue["a" /* default */](this);
8345     /**
8346      * A Rendered Location Range
8347      * @typedef location
8348      * @type {Object}
8349      * @property {object} start
8350      * @property {string} start.index
8351      * @property {string} start.href
8352      * @property {object} start.displayed
8353      * @property {EpubCFI} start.cfi
8354      * @property {number} start.location
8355      * @property {number} start.percentage
8356      * @property {number} start.displayed.page
8357      * @property {number} start.displayed.total
8358      * @property {object} end
8359      * @property {string} end.index
8360      * @property {string} end.href
8361      * @property {object} end.displayed
8362      * @property {EpubCFI} end.cfi
8363      * @property {number} end.location
8364      * @property {number} end.percentage
8365      * @property {number} end.displayed.page
8366      * @property {number} end.displayed.total
8367      * @property {boolean} atStart
8368      * @property {boolean} atEnd
8369      * @memberof Rendition
8370      */
8371 
8372     this.location = undefined; // Hold queue until book is opened
8373 
8374     this.q.enqueue(this.book.opened);
8375     this.starting = new core["defer"]();
8376     /**
8377      * @member {promise} started returns after the rendition has started
8378      * @memberof Rendition
8379      */
8380 
8381     this.started = this.starting.promise; // Block the queue until rendering is started
8382 
8383     this.q.enqueue(this.start);
8384   }
8385   /**
8386    * Set the manager function
8387    * @param {function} manager
8388    */
8389 
8390 
8391   setManager(manager) {
8392     this.manager = manager;
8393   }
8394   /**
8395    * Require the manager from passed string, or as a class function
8396    * @param  {string|object} manager [description]
8397    * @return {method}
8398    */
8399 
8400 
8401   requireManager(manager) {
8402     var viewManager; // If manager is a string, try to load from imported managers
8403 
8404     if (typeof manager === "string" && manager === "default") {
8405       viewManager = managers_default["a" /* default */];
8406     } else if (typeof manager === "string" && manager === "continuous") {
8407       viewManager = continuous["a" /* default */];
8408     } else {
8409       // otherwise, assume we were passed a class function
8410       viewManager = manager;
8411     }
8412 
8413     return viewManager;
8414   }
8415   /**
8416    * Require the view from passed string, or as a class function
8417    * @param  {string|object} view
8418    * @return {view}
8419    */
8420 
8421 
8422   requireView(view) {
8423     var View; // If view is a string, try to load from imported views,
8424 
8425     if (typeof view == "string" && view === "iframe") {
8426       View = iframe["a" /* default */];
8427     } else {
8428       // otherwise, assume we were passed a class function
8429       View = view;
8430     }
8431 
8432     return View;
8433   }
8434   /**
8435    * Start the rendering
8436    * @return {Promise} rendering has started
8437    */
8438 
8439 
8440   start() {
8441     if (!this.settings.layout && (this.book.package.metadata.layout === "pre-paginated" || this.book.displayOptions.fixedLayout === "true")) {
8442       this.settings.layout = "pre-paginated";
8443     }
8444 
8445     switch (this.book.package.metadata.spread) {
8446       case 'none':
8447         this.settings.spread = 'none';
8448         break;
8449 
8450       case 'both':
8451         this.settings.spread = true;
8452         break;
8453     }
8454 
8455     if (!this.manager) {
8456       this.ViewManager = this.requireManager(this.settings.manager);
8457       this.View = this.requireView(this.settings.view);
8458       this.manager = new this.ViewManager({
8459         view: this.View,
8460         queue: this.q,
8461         request: this.book.load.bind(this.book),
8462         settings: this.settings
8463       });
8464     }
8465 
8466     this.direction(this.book.package.metadata.direction || this.settings.defaultDirection); // Parse metadata to get layout props
8467 
8468     this.settings.globalLayoutProperties = this.determineLayoutProperties(this.book.package.metadata);
8469     this.flow(this.settings.globalLayoutProperties.flow);
8470     this.layout(this.settings.globalLayoutProperties); // Listen for displayed views
8471 
8472     this.manager.on(constants["c" /* EVENTS */].MANAGERS.ADDED, this.afterDisplayed.bind(this));
8473     this.manager.on(constants["c" /* EVENTS */].MANAGERS.REMOVED, this.afterRemoved.bind(this)); // Listen for resizing
8474 
8475     this.manager.on(constants["c" /* EVENTS */].MANAGERS.RESIZED, this.onResized.bind(this)); // Listen for rotation
8476 
8477     this.manager.on(constants["c" /* EVENTS */].MANAGERS.ORIENTATION_CHANGE, this.onOrientationChange.bind(this)); // Listen for scroll changes
8478 
8479     this.manager.on(constants["c" /* EVENTS */].MANAGERS.SCROLLED, this.reportLocation.bind(this));
8480     /**
8481      * Emit that rendering has started
8482      * @event started
8483      * @memberof Rendition
8484      */
8485 
8486     this.emit(constants["c" /* EVENTS */].RENDITION.STARTED); // Start processing queue
8487 
8488     this.starting.resolve();
8489   }
8490   /**
8491    * Call to attach the container to an element in the dom
8492    * Container must be attached before rendering can begin
8493    * @param  {element} element to attach to
8494    * @return {Promise}
8495    */
8496 
8497 
8498   attachTo(element) {
8499     return this.q.enqueue(function () {
8500       // Start rendering
8501       this.manager.render(element, {
8502         "width": this.settings.width,
8503         "height": this.settings.height
8504       });
8505       /**
8506        * Emit that rendering has attached to an element
8507        * @event attached
8508        * @memberof Rendition
8509        */
8510 
8511       this.emit(constants["c" /* EVENTS */].RENDITION.ATTACHED);
8512     }.bind(this));
8513   }
8514   /**
8515    * Display a point in the book
8516    * The request will be added to the rendering Queue,
8517    * so it will wait until book is opened, rendering started
8518    * and all other rendering tasks have finished to be called.
8519    * @param  {string} target Url or EpubCFI
8520    * @return {Promise}
8521    */
8522 
8523 
8524   display(target) {
8525     if (this.displaying) {
8526       this.displaying.resolve();
8527     }
8528 
8529     return this.q.enqueue(this._display, target);
8530   }
8531   /**
8532    * Tells the manager what to display immediately
8533    * @private
8534    * @param  {string} target Url or EpubCFI
8535    * @return {Promise}
8536    */
8537 
8538 
8539   _display(target) {
8540     if (!this.book) {
8541       return;
8542     }
8543 
8544     var isCfiString = this.epubcfi.isCfiString(target);
8545     var displaying = new core["defer"]();
8546     var displayed = displaying.promise;
8547     var section;
8548     var moveTo;
8549     this.displaying = displaying; // Check if this is a book percentage
8550 
8551     if (this.book.locations.length() && Object(core["isFloat"])(target)) {
8552       target = this.book.locations.cfiFromPercentage(parseFloat(target));
8553     }
8554 
8555     section = this.book.spine.get(target);
8556 
8557     if (!section) {
8558       displaying.reject(new Error("No Section Found"));
8559       return displayed;
8560     }
8561 
8562     this.manager.display(section, target).then(() => {
8563       displaying.resolve(section);
8564       this.displaying = undefined;
8565       /**
8566        * Emit that a section has been displayed
8567        * @event displayed
8568        * @param {Section} section
8569        * @memberof Rendition
8570        */
8571 
8572       this.emit(constants["c" /* EVENTS */].RENDITION.DISPLAYED, section);
8573       this.reportLocation();
8574     }, err => {
8575       /**
8576        * Emit that has been an error displaying
8577        * @event displayError
8578        * @param {Section} section
8579        * @memberof Rendition
8580        */
8581       this.emit(constants["c" /* EVENTS */].RENDITION.DISPLAY_ERROR, err);
8582     });
8583     return displayed;
8584   }
8585   /*
8586   render(view, show) {
8587                 // view.onLayout = this.layout.format.bind(this.layout);
8588         view.create();
8589                 // Fit to size of the container, apply padding
8590         this.manager.resizeView(view);
8591                 // Render Chain
8592         return view.section.render(this.book.request)
8593                 .then(function(contents){
8594                         return view.load(contents);
8595                 }.bind(this))
8596                 .then(function(doc){
8597                         return this.hooks.content.trigger(view, this);
8598                 }.bind(this))
8599                 .then(function(){
8600                         this.layout.format(view.contents);
8601                         return this.hooks.layout.trigger(view, this);
8602                 }.bind(this))
8603                 .then(function(){
8604                         return view.display();
8605                 }.bind(this))
8606                 .then(function(){
8607                         return this.hooks.render.trigger(view, this);
8608                 }.bind(this))
8609                 .then(function(){
8610                         if(show !== false) {
8611                                 this.q.enqueue(function(view){
8612                                         view.show();
8613                                 }, view);
8614                         }
8615                         // this.map = new Map(view, this.layout);
8616                         this.hooks.show.trigger(view, this);
8617                         this.trigger("rendered", view.section);
8618                         }.bind(this))
8619                 .catch(function(e){
8620                         this.trigger("loaderror", e);
8621                 }.bind(this));
8622         }
8623   */
8624 
8625   /**
8626    * Report what section has been displayed
8627    * @private
8628    * @param  {*} view
8629    */
8630 
8631 
8632   afterDisplayed(view) {
8633     view.on(constants["c" /* EVENTS */].VIEWS.MARK_CLICKED, (cfiRange, data) => this.triggerMarkEvent(cfiRange, data, view.contents));
8634     this.hooks.render.trigger(view, this).then(() => {
8635       if (view.contents) {
8636         this.hooks.content.trigger(view.contents, this).then(() => {
8637           /**
8638            * Emit that a section has been rendered
8639            * @event rendered
8640            * @param {Section} section
8641            * @param {View} view
8642            * @memberof Rendition
8643            */
8644           this.emit(constants["c" /* EVENTS */].RENDITION.RENDERED, view.section, view);
8645         });
8646       } else {
8647         this.emit(constants["c" /* EVENTS */].RENDITION.RENDERED, view.section, view);
8648       }
8649     });
8650   }
8651   /**
8652    * Report what has been removed
8653    * @private
8654    * @param  {*} view
8655    */
8656 
8657 
8658   afterRemoved(view) {
8659     this.hooks.unloaded.trigger(view, this).then(() => {
8660       /**
8661        * Emit that a section has been removed
8662        * @event removed
8663        * @param {Section} section
8664        * @param {View} view
8665        * @memberof Rendition
8666        */
8667       this.emit(constants["c" /* EVENTS */].RENDITION.REMOVED, view.section, view);
8668     });
8669   }
8670   /**
8671    * Report resize events and display the last seen location
8672    * @private
8673    */
8674 
8675 
8676   onResized(size, epubcfi) {
8677     /**
8678      * Emit that the rendition has been resized
8679      * @event resized
8680      * @param {number} width
8681      * @param {height} height
8682      * @param {string} epubcfi (optional)
8683      * @memberof Rendition
8684      */
8685     this.emit(constants["c" /* EVENTS */].RENDITION.RESIZED, {
8686       width: size.width,
8687       height: size.height
8688     }, epubcfi);
8689 
8690     if (this.location && this.location.start) {
8691       this.display(epubcfi || this.location.start.cfi);
8692     }
8693   }
8694   /**
8695    * Report orientation events and display the last seen location
8696    * @private
8697    */
8698 
8699 
8700   onOrientationChange(orientation) {
8701     /**
8702      * Emit that the rendition has been rotated
8703      * @event orientationchange
8704      * @param {string} orientation
8705      * @memberof Rendition
8706      */
8707     this.emit(constants["c" /* EVENTS */].RENDITION.ORIENTATION_CHANGE, orientation);
8708   }
8709   /**
8710    * Move the Rendition to a specific offset
8711    * Usually you would be better off calling display()
8712    * @param {object} offset
8713    */
8714 
8715 
8716   moveTo(offset) {
8717     this.manager.moveTo(offset);
8718   }
8719   /**
8720    * Trigger a resize of the views
8721    * @param {number} [width]
8722    * @param {number} [height]
8723    * @param {string} [epubcfi] (optional)
8724    */
8725 
8726 
8727   resize(width, height, epubcfi) {
8728     if (width) {
8729       this.settings.width = width;
8730     }
8731 
8732     if (height) {
8733       this.settings.height = height;
8734     }
8735 
8736     this.manager.resize(width, height, epubcfi);
8737   }
8738   /**
8739    * Clear all rendered views
8740    */
8741 
8742 
8743   clear() {
8744     this.manager.clear();
8745   }
8746   /**
8747    * Go to the next "page" in the rendition
8748    * @return {Promise}
8749    */
8750 
8751 
8752   next() {
8753     return this.q.enqueue(this.manager.next.bind(this.manager)).then(this.reportLocation.bind(this));
8754   }
8755   /**
8756    * Go to the previous "page" in the rendition
8757    * @return {Promise}
8758    */
8759 
8760 
8761   prev() {
8762     return this.q.enqueue(this.manager.prev.bind(this.manager)).then(this.reportLocation.bind(this));
8763   } //-- http://www.idpf.org/epub/301/spec/epub-publications.html#meta-properties-rendering
8764 
8765   /**
8766    * Determine the Layout properties from metadata and settings
8767    * @private
8768    * @param  {object} metadata
8769    * @return {object} properties
8770    */
8771 
8772 
8773   determineLayoutProperties(metadata) {
8774     var properties;
8775     var layout = this.settings.layout || metadata.layout || "reflowable";
8776     var spread = this.settings.spread || metadata.spread || "auto";
8777     var orientation = this.settings.orientation || metadata.orientation || "auto";
8778     var flow = this.settings.flow || metadata.flow || "auto";
8779     var viewport = metadata.viewport || "";
8780     var minSpreadWidth = this.settings.minSpreadWidth || metadata.minSpreadWidth || 800;
8781     var direction = this.settings.direction || metadata.direction || "ltr";
8782 
8783     if ((this.settings.width === 0 || this.settings.width > 0) && (this.settings.height === 0 || this.settings.height > 0)) {// viewport = "width="+this.settings.width+", height="+this.settings.height+"";
8784     }
8785 
8786     properties = {
8787       layout: layout,
8788       spread: spread,
8789       orientation: orientation,
8790       flow: flow,
8791       viewport: viewport,
8792       minSpreadWidth: minSpreadWidth,
8793       direction: direction
8794     };
8795     return properties;
8796   }
8797   /**
8798    * Adjust the flow of the rendition to paginated or scrolled
8799    * (scrolled-continuous vs scrolled-doc are handled by different view managers)
8800    * @param  {string} flow
8801    */
8802 
8803 
8804   flow(flow) {
8805     var _flow = flow;
8806 
8807     if (flow === "scrolled" || flow === "scrolled-doc" || flow === "scrolled-continuous") {
8808       _flow = "scrolled";
8809     }
8810 
8811     if (flow === "auto" || flow === "paginated") {
8812       _flow = "paginated";
8813     }
8814 
8815     this.settings.flow = flow;
8816 
8817     if (this._layout) {
8818       this._layout.flow(_flow);
8819     }
8820 
8821     if (this.manager && this._layout) {
8822       this.manager.applyLayout(this._layout);
8823     }
8824 
8825     if (this.manager) {
8826       this.manager.updateFlow(_flow);
8827     }
8828 
8829     if (this.manager && this.manager.isRendered() && this.location) {
8830       this.manager.clear();
8831       this.display(this.location.start.cfi);
8832     }
8833   }
8834   /**
8835    * Adjust the layout of the rendition to reflowable or pre-paginated
8836    * @param  {object} settings
8837    */
8838 
8839 
8840   layout(settings) {
8841     if (settings) {
8842       this._layout = new layout(settings);
8843 
8844       this._layout.spread(settings.spread, this.settings.minSpreadWidth); // this.mapping = new Mapping(this._layout.props);
8845 
8846 
8847       this._layout.on(constants["c" /* EVENTS */].LAYOUT.UPDATED, (props, changed) => {
8848         this.emit(constants["c" /* EVENTS */].RENDITION.LAYOUT, props, changed);
8849       });
8850     }
8851 
8852     if (this.manager && this._layout) {
8853       this.manager.applyLayout(this._layout);
8854     }
8855 
8856     return this._layout;
8857   }
8858   /**
8859    * Adjust if the rendition uses spreads
8860    * @param  {string} spread none | auto (TODO: implement landscape, portrait, both)
8861    * @param  {int} [min] min width to use spreads at
8862    */
8863 
8864 
8865   spread(spread, min) {
8866     this.settings.spread = spread;
8867 
8868     if (min) {
8869       this.settings.minSpreadWidth = min;
8870     }
8871 
8872     if (this._layout) {
8873       this._layout.spread(spread, min);
8874     }
8875 
8876     if (this.manager && this.manager.isRendered()) {
8877       this.manager.updateLayout();
8878     }
8879   }
8880   /**
8881    * Adjust the direction of the rendition
8882    * @param  {string} dir
8883    */
8884 
8885 
8886   direction(dir) {
8887     this.settings.direction = dir || "ltr";
8888 
8889     if (this.manager) {
8890       this.manager.direction(this.settings.direction);
8891     }
8892 
8893     if (this.manager && this.manager.isRendered() && this.location) {
8894       this.manager.clear();
8895       this.display(this.location.start.cfi);
8896     }
8897   }
8898   /**
8899    * Report the current location
8900    * @fires relocated
8901    * @fires locationChanged
8902    */
8903 
8904 
8905   reportLocation() {
8906     return this.q.enqueue(function reportedLocation() {
8907       requestAnimationFrame(function reportedLocationAfterRAF() {
8908         var location = this.manager.currentLocation();
8909 
8910         if (location && location.then && typeof location.then === "function") {
8911           location.then(function (result) {
8912             let located = this.located(result);
8913 
8914             if (!located || !located.start || !located.end) {
8915               return;
8916             }
8917 
8918             this.location = located;
8919             this.emit(constants["c" /* EVENTS */].RENDITION.LOCATION_CHANGED, {
8920               index: this.location.start.index,
8921               href: this.location.start.href,
8922               start: this.location.start.cfi,
8923               end: this.location.end.cfi,
8924               percentage: this.location.start.percentage
8925             });
8926             this.emit(constants["c" /* EVENTS */].RENDITION.RELOCATED, this.location);
8927           }.bind(this));
8928         } else if (location) {
8929           let located = this.located(location);
8930 
8931           if (!located || !located.start || !located.end) {
8932             return;
8933           }
8934 
8935           this.location = located;
8936           /**
8937            * @event locationChanged
8938            * @deprecated
8939            * @type {object}
8940            * @property {number} index
8941            * @property {string} href
8942            * @property {EpubCFI} start
8943            * @property {EpubCFI} end
8944            * @property {number} percentage
8945            * @memberof Rendition
8946            */
8947 
8948           this.emit(constants["c" /* EVENTS */].RENDITION.LOCATION_CHANGED, {
8949             index: this.location.start.index,
8950             href: this.location.start.href,
8951             start: this.location.start.cfi,
8952             end: this.location.end.cfi,
8953             percentage: this.location.start.percentage
8954           });
8955           /**
8956            * @event relocated
8957            * @type {displayedLocation}
8958            * @memberof Rendition
8959            */
8960 
8961           this.emit(constants["c" /* EVENTS */].RENDITION.RELOCATED, this.location);
8962         }
8963       }.bind(this));
8964     }.bind(this));
8965   }
8966   /**
8967    * Get the Current Location object
8968    * @return {displayedLocation | promise} location (may be a promise)
8969    */
8970 
8971 
8972   currentLocation() {
8973     var location = this.manager.currentLocation();
8974 
8975     if (location && location.then && typeof location.then === "function") {
8976       location.then(function (result) {
8977         let located = this.located(result);
8978         return located;
8979       }.bind(this));
8980     } else if (location) {
8981       let located = this.located(location);
8982       return located;
8983     }
8984   }
8985   /**
8986    * Creates a Rendition#locationRange from location
8987    * passed by the Manager
8988    * @returns {displayedLocation}
8989    * @private
8990    */
8991 
8992 
8993   located(location) {
8994     if (!location.length) {
8995       return {};
8996     }
8997 
8998     let start = location[0];
8999     let end = location[location.length - 1];
9000     let located = {
9001       start: {
9002         index: start.index,
9003         href: start.href,
9004         cfi: start.mapping.start,
9005         displayed: {
9006           page: start.pages[0] || 1,
9007           total: start.totalPages
9008         }
9009       },
9010       end: {
9011         index: end.index,
9012         href: end.href,
9013         cfi: end.mapping.end,
9014         displayed: {
9015           page: end.pages[end.pages.length - 1] || 1,
9016           total: end.totalPages
9017         }
9018       }
9019     };
9020     let locationStart = this.book.locations.locationFromCfi(start.mapping.start);
9021     let locationEnd = this.book.locations.locationFromCfi(end.mapping.end);
9022 
9023     if (locationStart != null) {
9024       located.start.location = locationStart;
9025       located.start.percentage = this.book.locations.percentageFromLocation(locationStart);
9026     }
9027 
9028     if (locationEnd != null) {
9029       located.end.location = locationEnd;
9030       located.end.percentage = this.book.locations.percentageFromLocation(locationEnd);
9031     }
9032 
9033     let pageStart = this.book.pageList.pageFromCfi(start.mapping.start);
9034     let pageEnd = this.book.pageList.pageFromCfi(end.mapping.end);
9035 
9036     if (pageStart != -1) {
9037       located.start.page = pageStart;
9038     }
9039 
9040     if (pageEnd != -1) {
9041       located.end.page = pageEnd;
9042     }
9043 
9044     if (end.index === this.book.spine.last().index && located.end.displayed.page >= located.end.displayed.total) {
9045       located.atEnd = true;
9046     }
9047 
9048     if (start.index === this.book.spine.first().index && located.start.displayed.page === 1) {
9049       located.atStart = true;
9050     }
9051 
9052     return located;
9053   }
9054   /**
9055    * Remove and Clean Up the Rendition
9056    */
9057 
9058 
9059   destroy() {
9060     // Clear the queue
9061     // this.q.clear();
9062     // this.q = undefined;
9063     this.manager && this.manager.destroy();
9064     this.book = undefined; // this.views = null;
9065     // this.hooks.display.clear();
9066     // this.hooks.serialize.clear();
9067     // this.hooks.content.clear();
9068     // this.hooks.layout.clear();
9069     // this.hooks.render.clear();
9070     // this.hooks.show.clear();
9071     // this.hooks = {};
9072     // this.themes.destroy();
9073     // this.themes = undefined;
9074     // this.epubcfi = undefined;
9075     // this.starting = undefined;
9076     // this.started = undefined;
9077   }
9078   /**
9079    * Pass the events from a view's Contents
9080    * @private
9081    * @param  {Contents} view contents
9082    */
9083 
9084 
9085   passEvents(contents) {
9086     constants["a" /* DOM_EVENTS */].forEach(e => {
9087       contents.on(e, ev => this.triggerViewEvent(ev, contents));
9088     });
9089     contents.on(constants["c" /* EVENTS */].CONTENTS.SELECTED, e => this.triggerSelectedEvent(e, contents));
9090   }
9091   /**
9092    * Emit events passed by a view
9093    * @private
9094    * @param  {event} e
9095    */
9096 
9097 
9098   triggerViewEvent(e, contents) {
9099     this.emit(e.type, e, contents);
9100   }
9101   /**
9102    * Emit a selection event's CFI Range passed from a a view
9103    * @private
9104    * @param  {string} cfirange
9105    */
9106 
9107 
9108   triggerSelectedEvent(cfirange, contents) {
9109     /**
9110      * Emit that a text selection has occurred
9111      * @event selected
9112      * @param {string} cfirange
9113      * @param {Contents} contents
9114      * @memberof Rendition
9115      */
9116     this.emit(constants["c" /* EVENTS */].RENDITION.SELECTED, cfirange, contents);
9117   }
9118   /**
9119    * Emit a markClicked event with the cfiRange and data from a mark
9120    * @private
9121    * @param  {EpubCFI} cfirange
9122    */
9123 
9124 
9125   triggerMarkEvent(cfiRange, data, contents) {
9126     /**
9127      * Emit that a mark was clicked
9128      * @event markClicked
9129      * @param {EpubCFI} cfirange
9130      * @param {object} data
9131      * @param {Contents} contents
9132      * @memberof Rendition
9133      */
9134     this.emit(constants["c" /* EVENTS */].RENDITION.MARK_CLICKED, cfiRange, data, contents);
9135   }
9136   /**
9137    * Get a Range from a Visible CFI
9138    * @param  {string} cfi EpubCfi String
9139    * @param  {string} ignoreClass
9140    * @return {range}
9141    */
9142 
9143 
9144   getRange(cfi, ignoreClass) {
9145     var _cfi = new src_epubcfi["a" /* default */](cfi);
9146 
9147     var found = this.manager.visible().filter(function (view) {
9148       if (_cfi.spinePos === view.index) return true;
9149     }); // Should only every return 1 item
9150 
9151     if (found.length) {
9152       return found[0].contents.range(_cfi, ignoreClass);
9153     }
9154   }
9155   /**
9156    * Hook to adjust images to fit in columns
9157    * @param  {Contents} contents
9158    * @private
9159    */
9160 
9161 
9162   adjustImages(contents) {
9163     if (this._layout.name === "pre-paginated") {
9164       return new Promise(function (resolve) {
9165         resolve();
9166       });
9167     }
9168 
9169     let computed = contents.window.getComputedStyle(contents.content, null);
9170     let height = (contents.content.offsetHeight - (parseFloat(computed.paddingTop) + parseFloat(computed.paddingBottom))) * .95;
9171     let horizontalPadding = parseFloat(computed.paddingLeft) + parseFloat(computed.paddingRight);
9172     contents.addStylesheetRules({
9173       "img": {
9174         "max-width": (this._layout.columnWidth ? this._layout.columnWidth - horizontalPadding + "px" : "100%") + "!important",
9175         "max-height": height + "px" + "!important",
9176         "object-fit": "contain",
9177         "page-break-inside": "avoid",
9178         "break-inside": "avoid",
9179         "box-sizing": "border-box"
9180       },
9181       "svg": {
9182         "max-width": (this._layout.columnWidth ? this._layout.columnWidth - horizontalPadding + "px" : "100%") + "!important",
9183         "max-height": height + "px" + "!important",
9184         "page-break-inside": "avoid",
9185         "break-inside": "avoid"
9186       }
9187     });
9188     return new Promise(function (resolve, reject) {
9189       // Wait to apply
9190       setTimeout(function () {
9191         resolve();
9192       }, 1);
9193     });
9194   }
9195   /**
9196    * Get the Contents object of each rendered view
9197    * @returns {Contents[]}
9198    */
9199 
9200 
9201   getContents() {
9202     return this.manager ? this.manager.getContents() : [];
9203   }
9204   /**
9205    * Get the views member from the manager
9206    * @returns {Views}
9207    */
9208 
9209 
9210   views() {
9211     let views = this.manager ? this.manager.views : undefined;
9212     return views || [];
9213   }
9214   /**
9215    * Hook to handle link clicks in rendered content
9216    * @param  {Contents} contents
9217    * @private
9218    */
9219 
9220 
9221   handleLinks(contents) {
9222     if (contents) {
9223       contents.on(constants["c" /* EVENTS */].CONTENTS.LINK_CLICKED, href => {
9224         let relative = this.book.path.relative(href);
9225         this.display(relative);
9226       });
9227     }
9228   }
9229   /**
9230    * Hook to handle injecting stylesheet before
9231    * a Section is serialized
9232    * @param  {document} doc
9233    * @param  {Section} section
9234    * @private
9235    */
9236 
9237 
9238   injectStylesheet(doc, section) {
9239     let style = doc.createElement("link");
9240     style.setAttribute("type", "text/css");
9241     style.setAttribute("rel", "stylesheet");
9242     style.setAttribute("href", this.settings.stylesheet);
9243     doc.getElementsByTagName("head")[0].appendChild(style);
9244   }
9245   /**
9246    * Hook to handle injecting scripts before
9247    * a Section is serialized
9248    * @param  {document} doc
9249    * @param  {Section} section
9250    * @private
9251    */
9252 
9253 
9254   injectScript(doc, section) {
9255     let script = doc.createElement("script");
9256     script.setAttribute("type", "text/javascript");
9257     script.setAttribute("src", this.settings.script);
9258     script.textContent = " "; // Needed to prevent self closing tag
9259 
9260     doc.getElementsByTagName("head")[0].appendChild(script);
9261   }
9262   /**
9263    * Hook to handle the document identifier before
9264    * a Section is serialized
9265    * @param  {document} doc
9266    * @param  {Section} section
9267    * @private
9268    */
9269 
9270 
9271   injectIdentifier(doc, section) {
9272     let ident = this.book.packaging.metadata.identifier;
9273     let meta = doc.createElement("meta");
9274     meta.setAttribute("name", "dc.relation.ispartof");
9275 
9276     if (ident) {
9277       meta.setAttribute("content", ident);
9278     }
9279 
9280     doc.getElementsByTagName("head")[0].appendChild(meta);
9281   }
9282 
9283 } //-- Enable binding events to Renderer
9284 
9285 
9286 event_emitter_default()(rendition_Rendition.prototype);
9287 /* harmony default export */ var rendition = __webpack_exports__["a"] = (rendition_Rendition);
9288 
9289 /***/ }),
9290 /* 17 */
9291 /***/ (function(module, exports) {
9292 
9293 var g;
9294 
9295 // This works in non-strict mode
9296 g = (function() {
9297         return this;
9298 })();
9299 
9300 try {
9301         // This works if eval is allowed (see CSP)
9302         g = g || new Function("return this")();
9303 } catch (e) {
9304         // This works if the window reference is available
9305         if (typeof window === "object") g = window;
9306 }
9307 
9308 // g can still be undefined, but nothing to do about it...
9309 // We return undefined, instead of nothing here, so it's
9310 // easier to handle this case. if(!global) { ...}
9311 
9312 module.exports = g;
9313 
9314 
9315 /***/ }),
9316 /* 18 */
9317 /***/ (function(module, exports, __webpack_require__) {
9318 
9319 "use strict";
9320 
9321 
9322 var _undefined = __webpack_require__(38)(); // Support ES3 engines
9323 
9324 module.exports = function (val) {
9325  return (val !== _undefined) && (val !== null);
9326 };
9327 
9328 
9329 /***/ }),
9330 /* 19 */
9331 /***/ (function(module, exports) {
9332 
9333 /**
9334  * Checks if `value` is the
9335  * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)
9336  * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
9337  *
9338  * @static
9339  * @memberOf _
9340  * @since 0.1.0
9341  * @category Lang
9342  * @param {*} value The value to check.
9343  * @returns {boolean} Returns `true` if `value` is an object, else `false`.
9344  * @example
9345  *
9346  * _.isObject({});
9347  * // => true
9348  *
9349  * _.isObject([1, 2, 3]);
9350  * // => true
9351  *
9352  * _.isObject(_.noop);
9353  * // => true
9354  *
9355  * _.isObject(null);
9356  * // => false
9357  */
9358 function isObject(value) {
9359   var type = typeof value;
9360   return value != null && (type == 'object' || type == 'function');
9361 }
9362 
9363 module.exports = isObject;
9364 
9365 
9366 /***/ }),
9367 /* 20 */
9368 /***/ (function(module, __webpack_exports__, __webpack_require__) {
9369 
9370 "use strict";
9371 /* harmony import */ var event_emitter__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(3);
9372 /* harmony import */ var event_emitter__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(event_emitter__WEBPACK_IMPORTED_MODULE_0__);
9373 /* harmony import */ var _utils_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(0);
9374 /* harmony import */ var _epubcfi__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(2);
9375 /* harmony import */ var _contents__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(12);
9376 /* harmony import */ var _utils_constants__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(1);
9377 /* harmony import */ var marks_pane__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(13);
9378 /* harmony import */ var marks_pane__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(marks_pane__WEBPACK_IMPORTED_MODULE_5__);
9379 
9380 
9381 
9382 
9383 
9384 
9385 
9386 class IframeView {
9387   constructor(section, options) {
9388     this.settings = Object(_utils_core__WEBPACK_IMPORTED_MODULE_1__["extend"])({
9389       ignoreClass: "",
9390       axis: undefined,
9391       //options.layout && options.layout.props.flow === "scrolled" ? "vertical" : "horizontal",
9392       direction: undefined,
9393       width: 0,
9394       height: 0,
9395       layout: undefined,
9396       globalLayoutProperties: {},
9397       method: undefined,
9398       forceRight: false,
9399       allowScriptedContent: false,
9400       allowPopups: false
9401     }, options || {});
9402     this.id = "epubjs-view-" + Object(_utils_core__WEBPACK_IMPORTED_MODULE_1__["uuid"])();
9403     this.section = section;
9404     this.index = section.index;
9405     this.element = this.container(this.settings.axis);
9406     this.added = false;
9407     this.displayed = false;
9408     this.rendered = false; // this.width  = this.settings.width;
9409     // this.height = this.settings.height;
9410 
9411     this.fixedWidth = 0;
9412     this.fixedHeight = 0; // Blank Cfi for Parsing
9413 
9414     this.epubcfi = new _epubcfi__WEBPACK_IMPORTED_MODULE_2__[/* default */ "a"]();
9415     this.layout = this.settings.layout; // Dom events to listen for
9416     // this.listenedEvents = ["keydown", "keyup", "keypressed", "mouseup", "mousedown", "click", "touchend", "touchstart"];
9417 
9418     this.pane = undefined;
9419     this.highlights = {};
9420     this.underlines = {};
9421     this.marks = {};
9422   }
9423 
9424   container(axis) {
9425     var element = document.createElement("div");
9426     element.classList.add("epub-view"); // this.element.style.minHeight = "100px";
9427 
9428     element.style.height = "0px";
9429     element.style.width = "0px";
9430     element.style.overflow = "hidden";
9431     element.style.position = "relative";
9432     element.style.display = "block";
9433 
9434     if (axis && axis == "horizontal") {
9435       element.style.flex = "none";
9436     } else {
9437       element.style.flex = "initial";
9438     }
9439 
9440     return element;
9441   }
9442 
9443   create() {
9444     if (this.iframe) {
9445       return this.iframe;
9446     }
9447 
9448     if (!this.element) {
9449       this.element = this.createContainer();
9450     }
9451 
9452     this.iframe = document.createElement("iframe");
9453     this.iframe.id = this.id;
9454     this.iframe.scrolling = "no"; // Might need to be removed: breaks ios width calculations
9455 
9456     this.iframe.style.overflow = "hidden";
9457     this.iframe.seamless = "seamless"; // Back up if seamless isn't supported
9458 
9459     this.iframe.style.border = "none"; // sandbox
9460 
9461     this.iframe.sandbox = "allow-same-origin";
9462 
9463     if (this.settings.allowScriptedContent) {
9464       this.iframe.sandbox += " allow-scripts";
9465     }
9466 
9467     if (this.settings.allowPopups) {
9468       this.iframe.sandbox += " allow-popups";
9469     }
9470 
9471     this.iframe.setAttribute("enable-annotation", "true");
9472     this.resizing = true; // this.iframe.style.display = "none";
9473 
9474     this.element.style.visibility = "hidden";
9475     this.iframe.style.visibility = "hidden";
9476     this.iframe.style.width = "0";
9477     this.iframe.style.height = "0";
9478     this._width = 0;
9479     this._height = 0;
9480     this.element.setAttribute("ref", this.index);
9481     this.added = true;
9482     this.elementBounds = Object(_utils_core__WEBPACK_IMPORTED_MODULE_1__["bounds"])(this.element); // if(width || height){
9483     //   this.resize(width, height);
9484     // } else if(this.width && this.height){
9485     //   this.resize(this.width, this.height);
9486     // } else {
9487     //   this.iframeBounds = bounds(this.iframe);
9488     // }
9489 
9490     if ("srcdoc" in this.iframe) {
9491       this.supportsSrcdoc = true;
9492     } else {
9493       this.supportsSrcdoc = false;
9494     }
9495 
9496     if (!this.settings.method) {
9497       this.settings.method = this.supportsSrcdoc ? "srcdoc" : "write";
9498     }
9499 
9500     return this.iframe;
9501   }
9502 
9503   render(request, show) {
9504     // view.onLayout = this.layout.format.bind(this.layout);
9505     this.create(); // Fit to size of the container, apply padding
9506 
9507     this.size();
9508 
9509     if (!this.sectionRender) {
9510       this.sectionRender = this.section.render(request);
9511     } // Render Chain
9512 
9513 
9514     return this.sectionRender.then(function (contents) {
9515       return this.load(contents);
9516     }.bind(this)).then(function () {
9517       // find and report the writingMode axis
9518       let writingMode = this.contents.writingMode(); // Set the axis based on the flow and writing mode
9519 
9520       let axis;
9521 
9522       if (this.settings.flow === "scrolled") {
9523         axis = writingMode.indexOf("vertical") === 0 ? "horizontal" : "vertical";
9524       } else {
9525         axis = writingMode.indexOf("vertical") === 0 ? "vertical" : "horizontal";
9526       }
9527 
9528       if (writingMode.indexOf("vertical") === 0 && this.settings.flow === "paginated") {
9529         this.layout.delta = this.layout.height;
9530       }
9531 
9532       this.setAxis(axis);
9533       this.emit(_utils_constants__WEBPACK_IMPORTED_MODULE_4__[/* EVENTS */ "c"].VIEWS.AXIS, axis);
9534       this.setWritingMode(writingMode);
9535       this.emit(_utils_constants__WEBPACK_IMPORTED_MODULE_4__[/* EVENTS */ "c"].VIEWS.WRITING_MODE, writingMode); // apply the layout function to the contents
9536 
9537       this.layout.format(this.contents, this.section, this.axis); // Listen for events that require an expansion of the iframe
9538 
9539       this.addListeners();
9540       return new Promise((resolve, reject) => {
9541         // Expand the iframe to the full size of the content
9542         this.expand();
9543 
9544         if (this.settings.forceRight) {
9545           this.element.style.marginLeft = this.width() + "px";
9546         }
9547 
9548         resolve();
9549       });
9550     }.bind(this), function (e) {
9551       this.emit(_utils_constants__WEBPACK_IMPORTED_MODULE_4__[/* EVENTS */ "c"].VIEWS.LOAD_ERROR, e);
9552       return new Promise((resolve, reject) => {
9553         reject(e);
9554       });
9555     }.bind(this)).then(function () {
9556       this.emit(_utils_constants__WEBPACK_IMPORTED_MODULE_4__[/* EVENTS */ "c"].VIEWS.RENDERED, this.section);
9557     }.bind(this));
9558   }
9559 
9560   reset() {
9561     if (this.iframe) {
9562       this.iframe.style.width = "0";
9563       this.iframe.style.height = "0";
9564       this._width = 0;
9565       this._height = 0;
9566       this._textWidth = undefined;
9567       this._contentWidth = undefined;
9568       this._textHeight = undefined;
9569       this._contentHeight = undefined;
9570     }
9571 
9572     this._needsReframe = true;
9573   } // Determine locks base on settings
9574 
9575 
9576   size(_width, _height) {
9577     var width = _width || this.settings.width;
9578     var height = _height || this.settings.height;
9579 
9580     if (this.layout.name === "pre-paginated") {
9581       this.lock("both", width, height);
9582     } else if (this.settings.axis === "horizontal") {
9583       this.lock("height", width, height);
9584     } else {
9585       this.lock("width", width, height);
9586     }
9587 
9588     this.settings.width = width;
9589     this.settings.height = height;
9590   } // Lock an axis to element dimensions, taking borders into account
9591 
9592 
9593   lock(what, width, height) {
9594     var elBorders = Object(_utils_core__WEBPACK_IMPORTED_MODULE_1__["borders"])(this.element);
9595     var iframeBorders;
9596 
9597     if (this.iframe) {
9598       iframeBorders = Object(_utils_core__WEBPACK_IMPORTED_MODULE_1__["borders"])(this.iframe);
9599     } else {
9600       iframeBorders = {
9601         width: 0,
9602         height: 0
9603       };
9604     }
9605 
9606     if (what == "width" && Object(_utils_core__WEBPACK_IMPORTED_MODULE_1__["isNumber"])(width)) {
9607       this.lockedWidth = width - elBorders.width - iframeBorders.width; // this.resize(this.lockedWidth, width); //  width keeps ratio correct
9608     }
9609 
9610     if (what == "height" && Object(_utils_core__WEBPACK_IMPORTED_MODULE_1__["isNumber"])(height)) {
9611       this.lockedHeight = height - elBorders.height - iframeBorders.height; // this.resize(width, this.lockedHeight);
9612     }
9613 
9614     if (what === "both" && Object(_utils_core__WEBPACK_IMPORTED_MODULE_1__["isNumber"])(width) && Object(_utils_core__WEBPACK_IMPORTED_MODULE_1__["isNumber"])(height)) {
9615       this.lockedWidth = width - elBorders.width - iframeBorders.width;
9616       this.lockedHeight = height - elBorders.height - iframeBorders.height; // this.resize(this.lockedWidth, this.lockedHeight);
9617     }
9618 
9619     if (this.displayed && this.iframe) {
9620       // this.contents.layout();
9621       this.expand();
9622     }
9623   } // Resize a single axis based on content dimensions
9624 
9625 
9626   expand(force) {
9627     var width = this.lockedWidth;
9628     var height = this.lockedHeight;
9629     var columns;
9630     var textWidth, textHeight;
9631     if (!this.iframe || this._expanding) return;
9632     this._expanding = true;
9633 
9634     if (this.layout.name === "pre-paginated") {
9635       width = this.layout.columnWidth;
9636       height = this.layout.height;
9637     } // Expand Horizontally
9638     else if (this.settings.axis === "horizontal") {
9639       // Get the width of the text
9640       width = this.contents.textWidth();
9641 
9642       if (width % this.layout.pageWidth > 0) {
9643         width = Math.ceil(width / this.layout.pageWidth) * this.layout.pageWidth;
9644       }
9645 
9646       if (this.settings.forceEvenPages) {
9647         columns = width / this.layout.pageWidth;
9648 
9649         if (this.layout.divisor > 1 && this.layout.name === "reflowable" && columns % 2 > 0) {
9650           // add a blank page
9651           width += this.layout.pageWidth;
9652         }
9653       }
9654     } // Expand Vertically
9655     else if (this.settings.axis === "vertical") {
9656       height = this.contents.textHeight();
9657 
9658       if (this.settings.flow === "paginated" && height % this.layout.height > 0) {
9659         height = Math.ceil(height / this.layout.height) * this.layout.height;
9660       }
9661     } // Only Resize if dimensions have changed or
9662     // if Frame is still hidden, so needs reframing
9663 
9664 
9665     if (this._needsReframe || width != this._width || height != this._height) {
9666       this.reframe(width, height);
9667     }
9668 
9669     this._expanding = false;
9670   }
9671 
9672   reframe(width, height) {
9673     var size;
9674 
9675     if (Object(_utils_core__WEBPACK_IMPORTED_MODULE_1__["isNumber"])(width)) {
9676       this.element.style.width = width + "px";
9677       this.iframe.style.width = width + "px";
9678       this._width = width;
9679     }
9680 
9681     if (Object(_utils_core__WEBPACK_IMPORTED_MODULE_1__["isNumber"])(height)) {
9682       this.element.style.height = height + "px";
9683       this.iframe.style.height = height + "px";
9684       this._height = height;
9685     }
9686 
9687     let widthDelta = this.prevBounds ? width - this.prevBounds.width : width;
9688     let heightDelta = this.prevBounds ? height - this.prevBounds.height : height;
9689     size = {
9690       width: width,
9691       height: height,
9692       widthDelta: widthDelta,
9693       heightDelta: heightDelta
9694     };
9695     this.pane && this.pane.render();
9696     requestAnimationFrame(() => {
9697       let mark;
9698 
9699       for (let m in this.marks) {
9700         if (this.marks.hasOwnProperty(m)) {
9701           mark = this.marks[m];
9702           this.placeMark(mark.element, mark.range);
9703         }
9704       }
9705     });
9706     this.onResize(this, size);
9707     this.emit(_utils_constants__WEBPACK_IMPORTED_MODULE_4__[/* EVENTS */ "c"].VIEWS.RESIZED, size);
9708     this.prevBounds = size;
9709     this.elementBounds = Object(_utils_core__WEBPACK_IMPORTED_MODULE_1__["bounds"])(this.element);
9710   }
9711 
9712   load(contents) {
9713     var loading = new _utils_core__WEBPACK_IMPORTED_MODULE_1__["defer"]();
9714     var loaded = loading.promise;
9715 
9716     if (!this.iframe) {
9717       loading.reject(new Error("No Iframe Available"));
9718       return loaded;
9719     }
9720 
9721     this.iframe.onload = function (event) {
9722       this.onLoad(event, loading);
9723     }.bind(this);
9724 
9725     if (this.settings.method === "blobUrl") {
9726       this.blobUrl = Object(_utils_core__WEBPACK_IMPORTED_MODULE_1__["createBlobUrl"])(contents, "application/xhtml+xml");
9727       this.iframe.src = this.blobUrl;
9728       this.element.appendChild(this.iframe);
9729     } else if (this.settings.method === "srcdoc") {
9730       this.iframe.srcdoc = contents;
9731       this.element.appendChild(this.iframe);
9732     } else {
9733       this.element.appendChild(this.iframe);
9734       this.document = this.iframe.contentDocument;
9735 
9736       if (!this.document) {
9737         loading.reject(new Error("No Document Available"));
9738         return loaded;
9739       }
9740 
9741       this.iframe.contentDocument.open(); // For Cordova windows platform
9742 
9743       if (window.MSApp && MSApp.execUnsafeLocalFunction) {
9744         var outerThis = this;
9745         MSApp.execUnsafeLocalFunction(function () {
9746           outerThis.iframe.contentDocument.write(contents);
9747         });
9748       } else {
9749         this.iframe.contentDocument.write(contents);
9750       }
9751 
9752       this.iframe.contentDocument.close();
9753     }
9754 
9755     return loaded;
9756   }
9757 
9758   onLoad(event, promise) {
9759     this.window = this.iframe.contentWindow;
9760     this.document = this.iframe.contentDocument;
9761     this.contents = new _contents__WEBPACK_IMPORTED_MODULE_3__[/* default */ "a"](this.document, this.document.body, this.section.cfiBase, this.section.index);
9762     this.rendering = false;
9763     var link = this.document.querySelector("link[rel='canonical']");
9764 
9765     if (link) {
9766       link.setAttribute("href", this.section.canonical);
9767     } else {
9768       link = this.document.createElement("link");
9769       link.setAttribute("rel", "canonical");
9770       link.setAttribute("href", this.section.canonical);
9771       this.document.querySelector("head").appendChild(link);
9772     }
9773 
9774     this.contents.on(_utils_constants__WEBPACK_IMPORTED_MODULE_4__[/* EVENTS */ "c"].CONTENTS.EXPAND, () => {
9775       if (this.displayed && this.iframe) {
9776         this.expand();
9777 
9778         if (this.contents) {
9779           this.layout.format(this.contents);
9780         }
9781       }
9782     });
9783     this.contents.on(_utils_constants__WEBPACK_IMPORTED_MODULE_4__[/* EVENTS */ "c"].CONTENTS.RESIZE, e => {
9784       if (this.displayed && this.iframe) {
9785         this.expand();
9786 
9787         if (this.contents) {
9788           this.layout.format(this.contents);
9789         }
9790       }
9791     });
9792     promise.resolve(this.contents);
9793   }
9794 
9795   setLayout(layout) {
9796     this.layout = layout;
9797 
9798     if (this.contents) {
9799       this.layout.format(this.contents);
9800       this.expand();
9801     }
9802   }
9803 
9804   setAxis(axis) {
9805     this.settings.axis = axis;
9806 
9807     if (axis == "horizontal") {
9808       this.element.style.flex = "none";
9809     } else {
9810       this.element.style.flex = "initial";
9811     }
9812 
9813     this.size();
9814   }
9815 
9816   setWritingMode(mode) {
9817     // this.element.style.writingMode = writingMode;
9818     this.writingMode = mode;
9819   }
9820 
9821   addListeners() {//TODO: Add content listeners for expanding
9822   }
9823 
9824   removeListeners(layoutFunc) {//TODO: remove content listeners for expanding
9825   }
9826 
9827   display(request) {
9828     var displayed = new _utils_core__WEBPACK_IMPORTED_MODULE_1__["defer"]();
9829 
9830     if (!this.displayed) {
9831       this.render(request).then(function () {
9832         this.emit(_utils_constants__WEBPACK_IMPORTED_MODULE_4__[/* EVENTS */ "c"].VIEWS.DISPLAYED, this);
9833         this.onDisplayed(this);
9834         this.displayed = true;
9835         displayed.resolve(this);
9836       }.bind(this), function (err) {
9837         displayed.reject(err, this);
9838       });
9839     } else {
9840       displayed.resolve(this);
9841     }
9842 
9843     return displayed.promise;
9844   }
9845 
9846   show() {
9847     this.element.style.visibility = "visible";
9848 
9849     if (this.iframe) {
9850       this.iframe.style.visibility = "visible"; // Remind Safari to redraw the iframe
9851 
9852       this.iframe.style.transform = "translateZ(0)";
9853       this.iframe.offsetWidth;
9854       this.iframe.style.transform = null;
9855     }
9856 
9857     this.emit(_utils_constants__WEBPACK_IMPORTED_MODULE_4__[/* EVENTS */ "c"].VIEWS.SHOWN, this);
9858   }
9859 
9860   hide() {
9861     // this.iframe.style.display = "none";
9862     this.element.style.visibility = "hidden";
9863     this.iframe.style.visibility = "hidden";
9864     this.stopExpanding = true;
9865     this.emit(_utils_constants__WEBPACK_IMPORTED_MODULE_4__[/* EVENTS */ "c"].VIEWS.HIDDEN, this);
9866   }
9867 
9868   offset() {
9869     return {
9870       top: this.element.offsetTop,
9871       left: this.element.offsetLeft
9872     };
9873   }
9874 
9875   width() {
9876     return this._width;
9877   }
9878 
9879   height() {
9880     return this._height;
9881   }
9882 
9883   position() {
9884     return this.element.getBoundingClientRect();
9885   }
9886 
9887   locationOf(target) {
9888     var parentPos = this.iframe.getBoundingClientRect();
9889     var targetPos = this.contents.locationOf(target, this.settings.ignoreClass);
9890     return {
9891       "left": targetPos.left,
9892       "top": targetPos.top
9893     };
9894   }
9895 
9896   onDisplayed(view) {// Stub, override with a custom functions
9897   }
9898 
9899   onResize(view, e) {// Stub, override with a custom functions
9900   }
9901 
9902   bounds(force) {
9903     if (force || !this.elementBounds) {
9904       this.elementBounds = Object(_utils_core__WEBPACK_IMPORTED_MODULE_1__["bounds"])(this.element);
9905     }
9906 
9907     return this.elementBounds;
9908   }
9909 
9910   highlight(cfiRange, data = {}, cb, className = "epubjs-hl", styles = {}) {
9911     if (!this.contents) {
9912       return;
9913     }
9914 
9915     const attributes = Object.assign({
9916       "fill": "yellow",
9917       "fill-opacity": "0.3",
9918       "mix-blend-mode": "multiply"
9919     }, styles);
9920     let range = this.contents.range(cfiRange);
9921 
9922     let emitter = () => {
9923       this.emit(_utils_constants__WEBPACK_IMPORTED_MODULE_4__[/* EVENTS */ "c"].VIEWS.MARK_CLICKED, cfiRange, data);
9924     };
9925 
9926     data["epubcfi"] = cfiRange;
9927 
9928     if (!this.pane) {
9929       this.pane = new marks_pane__WEBPACK_IMPORTED_MODULE_5__["Pane"](this.iframe, this.element);
9930     }
9931 
9932     let m = new marks_pane__WEBPACK_IMPORTED_MODULE_5__["Highlight"](range, className, data, attributes);
9933     let h = this.pane.addMark(m);
9934     this.highlights[cfiRange] = {
9935       "mark": h,
9936       "element": h.element,
9937       "listeners": [emitter, cb]
9938     };
9939     h.element.setAttribute("ref", className);
9940     h.element.addEventListener("click", emitter);
9941     h.element.addEventListener("touchstart", emitter);
9942 
9943     if (cb) {
9944       h.element.addEventListener("click", cb);
9945       h.element.addEventListener("touchstart", cb);
9946     }
9947 
9948     return h;
9949   }
9950 
9951   underline(cfiRange, data = {}, cb, className = "epubjs-ul", styles = {}) {
9952     if (!this.contents) {
9953       return;
9954     }
9955 
9956     const attributes = Object.assign({
9957       "stroke": "black",
9958       "stroke-opacity": "0.3",
9959       "mix-blend-mode": "multiply"
9960     }, styles);
9961     let range = this.contents.range(cfiRange);
9962 
9963     let emitter = () => {
9964       this.emit(_utils_constants__WEBPACK_IMPORTED_MODULE_4__[/* EVENTS */ "c"].VIEWS.MARK_CLICKED, cfiRange, data);
9965     };
9966 
9967     data["epubcfi"] = cfiRange;
9968 
9969     if (!this.pane) {
9970       this.pane = new marks_pane__WEBPACK_IMPORTED_MODULE_5__["Pane"](this.iframe, this.element);
9971     }
9972 
9973     let m = new marks_pane__WEBPACK_IMPORTED_MODULE_5__["Underline"](range, className, data, attributes);
9974     let h = this.pane.addMark(m);
9975     this.underlines[cfiRange] = {
9976       "mark": h,
9977       "element": h.element,
9978       "listeners": [emitter, cb]
9979     };
9980     h.element.setAttribute("ref", className);
9981     h.element.addEventListener("click", emitter);
9982     h.element.addEventListener("touchstart", emitter);
9983 
9984     if (cb) {
9985       h.element.addEventListener("click", cb);
9986       h.element.addEventListener("touchstart", cb);
9987     }
9988 
9989     return h;
9990   }
9991 
9992   mark(cfiRange, data = {}, cb) {
9993     if (!this.contents) {
9994       return;
9995     }
9996 
9997     if (cfiRange in this.marks) {
9998       let item = this.marks[cfiRange];
9999       return item;
10000     }
10001 
10002     let range = this.contents.range(cfiRange);
10003 
10004     if (!range) {
10005       return;
10006     }
10007 
10008     let container = range.commonAncestorContainer;
10009     let parent = container.nodeType === 1 ? container : container.parentNode;
10010 
10011     let emitter = e => {
10012       this.emit(_utils_constants__WEBPACK_IMPORTED_MODULE_4__[/* EVENTS */ "c"].VIEWS.MARK_CLICKED, cfiRange, data);
10013     };
10014 
10015     if (range.collapsed && container.nodeType === 1) {
10016       range = new Range();
10017       range.selectNodeContents(container);
10018     } else if (range.collapsed) {
10019       // Webkit doesn't like collapsed ranges
10020       range = new Range();
10021       range.selectNodeContents(parent);
10022     }
10023 
10024     let mark = this.document.createElement("a");
10025     mark.setAttribute("ref", "epubjs-mk");
10026     mark.style.position = "absolute";
10027     mark.dataset["epubcfi"] = cfiRange;
10028 
10029     if (data) {
10030       Object.keys(data).forEach(key => {
10031         mark.dataset[key] = data[key];
10032       });
10033     }
10034 
10035     if (cb) {
10036       mark.addEventListener("click", cb);
10037       mark.addEventListener("touchstart", cb);
10038     }
10039 
10040     mark.addEventListener("click", emitter);
10041     mark.addEventListener("touchstart", emitter);
10042     this.placeMark(mark, range);
10043     this.element.appendChild(mark);
10044     this.marks[cfiRange] = {
10045       "element": mark,
10046       "range": range,
10047       "listeners": [emitter, cb]
10048     };
10049     return parent;
10050   }
10051 
10052   placeMark(element, range) {
10053     let top, right, left;
10054 
10055     if (this.layout.name === "pre-paginated" || this.settings.axis !== "horizontal") {
10056       let pos = range.getBoundingClientRect();
10057       top = pos.top;
10058       right = pos.right;
10059     } else {
10060       // Element might break columns, so find the left most element
10061       let rects = range.getClientRects();
10062       let rect;
10063 
10064       for (var i = 0; i != rects.length; i++) {
10065         rect = rects[i];
10066 
10067         if (!left || rect.left < left) {
10068           left = rect.left; // right = rect.right;
10069 
10070           right = Math.ceil(left / this.layout.props.pageWidth) * this.layout.props.pageWidth - this.layout.gap / 2;
10071           top = rect.top;
10072         }
10073       }
10074     }
10075 
10076     element.style.top = `${top}px`;
10077     element.style.left = `${right}px`;
10078   }
10079 
10080   unhighlight(cfiRange) {
10081     let item;
10082 
10083     if (cfiRange in this.highlights) {
10084       item = this.highlights[cfiRange];
10085       this.pane.removeMark(item.mark);
10086       item.listeners.forEach(l => {
10087         if (l) {
10088           item.element.removeEventListener("click", l);
10089           item.element.removeEventListener("touchstart", l);
10090         }
10091 
10092         ;
10093       });
10094       delete this.highlights[cfiRange];
10095     }
10096   }
10097 
10098   ununderline(cfiRange) {
10099     let item;
10100 
10101     if (cfiRange in this.underlines) {
10102       item = this.underlines[cfiRange];
10103       this.pane.removeMark(item.mark);
10104       item.listeners.forEach(l => {
10105         if (l) {
10106           item.element.removeEventListener("click", l);
10107           item.element.removeEventListener("touchstart", l);
10108         }
10109 
10110         ;
10111       });
10112       delete this.underlines[cfiRange];
10113     }
10114   }
10115 
10116   unmark(cfiRange) {
10117     let item;
10118 
10119     if (cfiRange in this.marks) {
10120       item = this.marks[cfiRange];
10121       this.element.removeChild(item.element);
10122       item.listeners.forEach(l => {
10123         if (l) {
10124           item.element.removeEventListener("click", l);
10125           item.element.removeEventListener("touchstart", l);
10126         }
10127 
10128         ;
10129       });
10130       delete this.marks[cfiRange];
10131     }
10132   }
10133 
10134   destroy() {
10135     for (let cfiRange in this.highlights) {
10136       this.unhighlight(cfiRange);
10137     }
10138 
10139     for (let cfiRange in this.underlines) {
10140       this.ununderline(cfiRange);
10141     }
10142 
10143     for (let cfiRange in this.marks) {
10144       this.unmark(cfiRange);
10145     }
10146 
10147     if (this.blobUrl) {
10148       Object(_utils_core__WEBPACK_IMPORTED_MODULE_1__["revokeBlobUrl"])(this.blobUrl);
10149     }
10150 
10151     if (this.displayed) {
10152       this.displayed = false;
10153       this.removeListeners();
10154       this.contents.destroy();
10155       this.stopExpanding = true;
10156       this.element.removeChild(this.iframe);
10157 
10158       if (this.pane) {
10159         this.pane.element.remove();
10160         this.pane = undefined;
10161       }
10162 
10163       this.iframe = undefined;
10164       this.contents = undefined;
10165       this._textWidth = null;
10166       this._textHeight = null;
10167       this._width = null;
10168       this._height = null;
10169     } // this.element.style.height = "0px";
10170     // this.element.style.width = "0px";
10171 
10172   }
10173 
10174 }
10175 
10176 event_emitter__WEBPACK_IMPORTED_MODULE_0___default()(IframeView.prototype);
10177 /* harmony default export */ __webpack_exports__["a"] = (IframeView);
10178 
10179 /***/ }),
10180 /* 21 */
10181 /***/ (function(module, exports, __webpack_require__) {
10182 
10183 var isObject = __webpack_require__(19),
10184     now = __webpack_require__(51),
10185     toNumber = __webpack_require__(53);
10186 
10187 /** Error message constants. */
10188 var FUNC_ERROR_TEXT = 'Expected a function';
10189 
10190 /* Built-in method references for those with the same name as other `lodash` methods. */
10191 var nativeMax = Math.max,
10192     nativeMin = Math.min;
10193 
10194 /**
10195  * Creates a debounced function that delays invoking `func` until after `wait`
10196  * milliseconds have elapsed since the last time the debounced function was
10197  * invoked. The debounced function comes with a `cancel` method to cancel
10198  * delayed `func` invocations and a `flush` method to immediately invoke them.
10199  * Provide `options` to indicate whether `func` should be invoked on the
10200  * leading and/or trailing edge of the `wait` timeout. The `func` is invoked
10201  * with the last arguments provided to the debounced function. Subsequent
10202  * calls to the debounced function return the result of the last `func`
10203  * invocation.
10204  *
10205  * **Note:** If `leading` and `trailing` options are `true`, `func` is
10206  * invoked on the trailing edge of the timeout only if the debounced function
10207  * is invoked more than once during the `wait` timeout.
10208  *
10209  * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred
10210  * until to the next tick, similar to `setTimeout` with a timeout of `0`.
10211  *
10212  * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/)
10213  * for details over the differences between `_.debounce` and `_.throttle`.
10214  *
10215  * @static
10216  * @memberOf _
10217  * @since 0.1.0
10218  * @category Function
10219  * @param {Function} func The function to debounce.
10220  * @param {number} [wait=0] The number of milliseconds to delay.
10221  * @param {Object} [options={}] The options object.
10222  * @param {boolean} [options.leading=false]
10223  *  Specify invoking on the leading edge of the timeout.
10224  * @param {number} [options.maxWait]
10225  *  The maximum time `func` is allowed to be delayed before it's invoked.
10226  * @param {boolean} [options.trailing=true]
10227  *  Specify invoking on the trailing edge of the timeout.
10228  * @returns {Function} Returns the new debounced function.
10229  * @example
10230  *
10231  * // Avoid costly calculations while the window size is in flux.
10232  * jQuery(window).on('resize', _.debounce(calculateLayout, 150));
10233  *
10234  * // Invoke `sendMail` when clicked, debouncing subsequent calls.
10235  * jQuery(element).on('click', _.debounce(sendMail, 300, {
10236  *   'leading': true,
10237  *   'trailing': false
10238  * }));
10239  *
10240  * // Ensure `batchLog` is invoked once after 1 second of debounced calls.
10241  * var debounced = _.debounce(batchLog, 250, { 'maxWait': 1000 });
10242  * var source = new EventSource('/stream');
10243  * jQuery(source).on('message', debounced);
10244  *
10245  * // Cancel the trailing debounced invocation.
10246  * jQuery(window).on('popstate', debounced.cancel);
10247  */
10248 function debounce(func, wait, options) {
10249   var lastArgs,
10250       lastThis,
10251       maxWait,
10252       result,
10253       timerId,
10254       lastCallTime,
10255       lastInvokeTime = 0,
10256       leading = false,
10257       maxing = false,
10258       trailing = true;
10259 
10260   if (typeof func != 'function') {
10261     throw new TypeError(FUNC_ERROR_TEXT);
10262   }
10263   wait = toNumber(wait) || 0;
10264   if (isObject(options)) {
10265     leading = !!options.leading;
10266     maxing = 'maxWait' in options;
10267     maxWait = maxing ? nativeMax(toNumber(options.maxWait) || 0, wait) : maxWait;
10268     trailing = 'trailing' in options ? !!options.trailing : trailing;
10269   }
10270 
10271   function invokeFunc(time) {
10272     var args = lastArgs,
10273         thisArg = lastThis;
10274 
10275     lastArgs = lastThis = undefined;
10276     lastInvokeTime = time;
10277     result = func.apply(thisArg, args);
10278     return result;
10279   }
10280 
10281   function leadingEdge(time) {
10282     // Reset any `maxWait` timer.
10283     lastInvokeTime = time;
10284     // Start the timer for the trailing edge.
10285     timerId = setTimeout(timerExpired, wait);
10286     // Invoke the leading edge.
10287     return leading ? invokeFunc(time) : result;
10288   }
10289 
10290   function remainingWait(time) {
10291     var timeSinceLastCall = time - lastCallTime,
10292         timeSinceLastInvoke = time - lastInvokeTime,
10293         timeWaiting = wait - timeSinceLastCall;
10294 
10295     return maxing
10296       ? nativeMin(timeWaiting, maxWait - timeSinceLastInvoke)
10297       : timeWaiting;
10298   }
10299 
10300   function shouldInvoke(time) {
10301     var timeSinceLastCall = time - lastCallTime,
10302         timeSinceLastInvoke = time - lastInvokeTime;
10303 
10304     // Either this is the first call, activity has stopped and we're at the
10305     // trailing edge, the system time has gone backwards and we're treating
10306     // it as the trailing edge, or we've hit the `maxWait` limit.
10307     return (lastCallTime === undefined || (timeSinceLastCall >= wait) ||
10308       (timeSinceLastCall < 0) || (maxing && timeSinceLastInvoke >= maxWait));
10309   }
10310 
10311   function timerExpired() {
10312     var time = now();
10313     if (shouldInvoke(time)) {
10314       return trailingEdge(time);
10315     }
10316     // Restart the timer.
10317     timerId = setTimeout(timerExpired, remainingWait(time));
10318   }
10319 
10320   function trailingEdge(time) {
10321     timerId = undefined;
10322 
10323     // Only invoke if we have `lastArgs` which means `func` has been
10324     // debounced at least once.
10325     if (trailing && lastArgs) {
10326       return invokeFunc(time);
10327     }
10328     lastArgs = lastThis = undefined;
10329     return result;
10330   }
10331 
10332   function cancel() {
10333     if (timerId !== undefined) {
10334       clearTimeout(timerId);
10335     }
10336     lastInvokeTime = 0;
10337     lastArgs = lastCallTime = lastThis = timerId = undefined;
10338   }
10339 
10340   function flush() {
10341     return timerId === undefined ? result : trailingEdge(now());
10342   }
10343 
10344   function debounced() {
10345     var time = now(),
10346         isInvoking = shouldInvoke(time);
10347 
10348     lastArgs = arguments;
10349     lastThis = this;
10350     lastCallTime = time;
10351 
10352     if (isInvoking) {
10353       if (timerId === undefined) {
10354         return leadingEdge(lastCallTime);
10355       }
10356       if (maxing) {
10357         // Handle invocations in a tight loop.
10358         clearTimeout(timerId);
10359         timerId = setTimeout(timerExpired, wait);
10360         return invokeFunc(lastCallTime);
10361       }
10362     }
10363     if (timerId === undefined) {
10364       timerId = setTimeout(timerExpired, wait);
10365     }
10366     return result;
10367   }
10368   debounced.cancel = cancel;
10369   debounced.flush = flush;
10370   return debounced;
10371 }
10372 
10373 module.exports = debounce;
10374 
10375 
10376 /***/ }),
10377 /* 22 */
10378 /***/ (function(module, __webpack_exports__, __webpack_require__) {
10379 
10380 "use strict";
10381 
10382 // EXTERNAL MODULE: ./src/utils/core.js
10383 var core = __webpack_require__(0);
10384 
10385 // EXTERNAL MODULE: ./src/managers/default/index.js + 3 modules
10386 var managers_default = __webpack_require__(10);
10387 
10388 // EXTERNAL MODULE: ./src/utils/constants.js
10389 var constants = __webpack_require__(1);
10390 
10391 // EXTERNAL MODULE: ./node_modules/event-emitter/index.js
10392 var event_emitter = __webpack_require__(3);
10393 var event_emitter_default = /*#__PURE__*/__webpack_require__.n(event_emitter);
10394 
10395 // CONCATENATED MODULE: ./src/managers/helpers/snap.js
10396 
10397 
10398  // easing equations from https://github.com/danro/easing-js/blob/master/easing.js
10399 
10400 const PI_D2 = Math.PI / 2;
10401 const EASING_EQUATIONS = {
10402   easeOutSine: function (pos) {
10403     return Math.sin(pos * PI_D2);
10404   },
10405   easeInOutSine: function (pos) {
10406     return -0.5 * (Math.cos(Math.PI * pos) - 1);
10407   },
10408   easeInOutQuint: function (pos) {
10409     if ((pos /= 0.5) < 1) {
10410       return 0.5 * Math.pow(pos, 5);
10411     }
10412 
10413     return 0.5 * (Math.pow(pos - 2, 5) + 2);
10414   },
10415   easeInCubic: function (pos) {
10416     return Math.pow(pos, 3);
10417   }
10418 };
10419 
10420 class snap_Snap {
10421   constructor(manager, options) {
10422     this.settings = Object(core["extend"])({
10423       duration: 80,
10424       minVelocity: 0.2,
10425       minDistance: 10,
10426       easing: EASING_EQUATIONS['easeInCubic']
10427     }, options || {});
10428     this.supportsTouch = this.supportsTouch();
10429 
10430     if (this.supportsTouch) {
10431       this.setup(manager);
10432     }
10433   }
10434 
10435   setup(manager) {
10436     this.manager = manager;
10437     this.layout = this.manager.layout;
10438     this.fullsize = this.manager.settings.fullsize;
10439 
10440     if (this.fullsize) {
10441       this.element = this.manager.stage.element;
10442       this.scroller = window;
10443       this.disableScroll();
10444     } else {
10445       this.element = this.manager.stage.container;
10446       this.scroller = this.element;
10447       this.element.style["WebkitOverflowScrolling"] = "touch";
10448     } // this.overflow = this.manager.overflow;
10449     // set lookahead offset to page width
10450 
10451 
10452     this.manager.settings.offset = this.layout.width;
10453     this.manager.settings.afterScrolledTimeout = this.settings.duration * 2;
10454     this.isVertical = this.manager.settings.axis === "vertical"; // disable snapping if not paginated or axis in not horizontal
10455 
10456     if (!this.manager.isPaginated || this.isVertical) {
10457       return;
10458     }
10459 
10460     this.touchCanceler = false;
10461     this.resizeCanceler = false;
10462     this.snapping = false;
10463     this.scrollLeft;
10464     this.scrollTop;
10465     this.startTouchX = undefined;
10466     this.startTouchY = undefined;
10467     this.startTime = undefined;
10468     this.endTouchX = undefined;
10469     this.endTouchY = undefined;
10470     this.endTime = undefined;
10471     this.addListeners();
10472   }
10473 
10474   supportsTouch() {
10475     if ('ontouchstart' in window || window.DocumentTouch && document instanceof DocumentTouch) {
10476       return true;
10477     }
10478 
10479     return false;
10480   }
10481 
10482   disableScroll() {
10483     this.element.style.overflow = "hidden";
10484   }
10485 
10486   enableScroll() {
10487     this.element.style.overflow = "";
10488   }
10489 
10490   addListeners() {
10491     this._onResize = this.onResize.bind(this);
10492     window.addEventListener('resize', this._onResize);
10493     this._onScroll = this.onScroll.bind(this);
10494     this.scroller.addEventListener('scroll', this._onScroll);
10495     this._onTouchStart = this.onTouchStart.bind(this);
10496     this.scroller.addEventListener('touchstart', this._onTouchStart, {
10497       passive: true
10498     });
10499     this.on('touchstart', this._onTouchStart);
10500     this._onTouchMove = this.onTouchMove.bind(this);
10501     this.scroller.addEventListener('touchmove', this._onTouchMove, {
10502       passive: true
10503     });
10504     this.on('touchmove', this._onTouchMove);
10505     this._onTouchEnd = this.onTouchEnd.bind(this);
10506     this.scroller.addEventListener('touchend', this._onTouchEnd, {
10507       passive: true
10508     });
10509     this.on('touchend', this._onTouchEnd);
10510     this._afterDisplayed = this.afterDisplayed.bind(this);
10511     this.manager.on(constants["c" /* EVENTS */].MANAGERS.ADDED, this._afterDisplayed);
10512   }
10513 
10514   removeListeners() {
10515     window.removeEventListener('resize', this._onResize);
10516     this._onResize = undefined;
10517     this.scroller.removeEventListener('scroll', this._onScroll);
10518     this._onScroll = undefined;
10519     this.scroller.removeEventListener('touchstart', this._onTouchStart, {
10520       passive: true
10521     });
10522     this.off('touchstart', this._onTouchStart);
10523     this._onTouchStart = undefined;
10524     this.scroller.removeEventListener('touchmove', this._onTouchMove, {
10525       passive: true
10526     });
10527     this.off('touchmove', this._onTouchMove);
10528     this._onTouchMove = undefined;
10529     this.scroller.removeEventListener('touchend', this._onTouchEnd, {
10530       passive: true
10531     });
10532     this.off('touchend', this._onTouchEnd);
10533     this._onTouchEnd = undefined;
10534     this.manager.off(constants["c" /* EVENTS */].MANAGERS.ADDED, this._afterDisplayed);
10535     this._afterDisplayed = undefined;
10536   }
10537 
10538   afterDisplayed(view) {
10539     let contents = view.contents;
10540     ["touchstart", "touchmove", "touchend"].forEach(e => {
10541       contents.on(e, ev => this.triggerViewEvent(ev, contents));
10542     });
10543   }
10544 
10545   triggerViewEvent(e, contents) {
10546     this.emit(e.type, e, contents);
10547   }
10548 
10549   onScroll(e) {
10550     this.scrollLeft = this.fullsize ? window.scrollX : this.scroller.scrollLeft;
10551     this.scrollTop = this.fullsize ? window.scrollY : this.scroller.scrollTop;
10552   }
10553 
10554   onResize(e) {
10555     this.resizeCanceler = true;
10556   }
10557 
10558   onTouchStart(e) {
10559     let {
10560       screenX,
10561       screenY
10562     } = e.touches[0];
10563 
10564     if (this.fullsize) {
10565       this.enableScroll();
10566     }
10567 
10568     this.touchCanceler = true;
10569 
10570     if (!this.startTouchX) {
10571       this.startTouchX = screenX;
10572       this.startTouchY = screenY;
10573       this.startTime = this.now();
10574     }
10575 
10576     this.endTouchX = screenX;
10577     this.endTouchY = screenY;
10578     this.endTime = this.now();
10579   }
10580 
10581   onTouchMove(e) {
10582     let {
10583       screenX,
10584       screenY
10585     } = e.touches[0];
10586     let deltaY = Math.abs(screenY - this.endTouchY);
10587     this.touchCanceler = true;
10588 
10589     if (!this.fullsize && deltaY < 10) {
10590       this.element.scrollLeft -= screenX - this.endTouchX;
10591     }
10592 
10593     this.endTouchX = screenX;
10594     this.endTouchY = screenY;
10595     this.endTime = this.now();
10596   }
10597 
10598   onTouchEnd(e) {
10599     if (this.fullsize) {
10600       this.disableScroll();
10601     }
10602 
10603     this.touchCanceler = false;
10604     let swipped = this.wasSwiped();
10605 
10606     if (swipped !== 0) {
10607       this.snap(swipped);
10608     } else {
10609       this.snap();
10610     }
10611 
10612     this.startTouchX = undefined;
10613     this.startTouchY = undefined;
10614     this.startTime = undefined;
10615     this.endTouchX = undefined;
10616     this.endTouchY = undefined;
10617     this.endTime = undefined;
10618   }
10619 
10620   wasSwiped() {
10621     let snapWidth = this.layout.pageWidth * this.layout.divisor;
10622     let distance = this.endTouchX - this.startTouchX;
10623     let absolute = Math.abs(distance);
10624     let time = this.endTime - this.startTime;
10625     let velocity = distance / time;
10626     let minVelocity = this.settings.minVelocity;
10627 
10628     if (absolute <= this.settings.minDistance || absolute >= snapWidth) {
10629       return 0;
10630     }
10631 
10632     if (velocity > minVelocity) {
10633       // previous
10634       return -1;
10635     } else if (velocity < -minVelocity) {
10636       // next
10637       return 1;
10638     }
10639   }
10640 
10641   needsSnap() {
10642     let left = this.scrollLeft;
10643     let snapWidth = this.layout.pageWidth * this.layout.divisor;
10644     return left % snapWidth !== 0;
10645   }
10646 
10647   snap(howMany = 0) {
10648     let left = this.scrollLeft;
10649     let snapWidth = this.layout.pageWidth * this.layout.divisor;
10650     let snapTo = Math.round(left / snapWidth) * snapWidth;
10651 
10652     if (howMany) {
10653       snapTo += howMany * snapWidth;
10654     }
10655 
10656     return this.smoothScrollTo(snapTo);
10657   }
10658 
10659   smoothScrollTo(destination) {
10660     const deferred = new core["defer"]();
10661     const start = this.scrollLeft;
10662     const startTime = this.now();
10663     const duration = this.settings.duration;
10664     const easing = this.settings.easing;
10665     this.snapping = true; // add animation loop
10666 
10667     function tick() {
10668       const now = this.now();
10669       const time = Math.min(1, (now - startTime) / duration);
10670       const timeFunction = easing(time);
10671 
10672       if (this.touchCanceler || this.resizeCanceler) {
10673         this.resizeCanceler = false;
10674         this.snapping = false;
10675         deferred.resolve();
10676         return;
10677       }
10678 
10679       if (time < 1) {
10680         window.requestAnimationFrame(tick.bind(this));
10681         this.scrollTo(start + (destination - start) * time, 0);
10682       } else {
10683         this.scrollTo(destination, 0);
10684         this.snapping = false;
10685         deferred.resolve();
10686       }
10687     }
10688 
10689     tick.call(this);
10690     return deferred.promise;
10691   }
10692 
10693   scrollTo(left = 0, top = 0) {
10694     if (this.fullsize) {
10695       window.scroll(left, top);
10696     } else {
10697       this.scroller.scrollLeft = left;
10698       this.scroller.scrollTop = top;
10699     }
10700   }
10701 
10702   now() {
10703     return 'now' in window.performance ? performance.now() : new Date().getTime();
10704   }
10705 
10706   destroy() {
10707     if (!this.scroller) {
10708       return;
10709     }
10710 
10711     if (this.fullsize) {
10712       this.enableScroll();
10713     }
10714 
10715     this.removeListeners();
10716     this.scroller = undefined;
10717   }
10718 
10719 }
10720 
10721 event_emitter_default()(snap_Snap.prototype);
10722 /* harmony default export */ var snap = (snap_Snap);
10723 // EXTERNAL MODULE: ./node_modules/lodash/debounce.js
10724 var debounce = __webpack_require__(21);
10725 var debounce_default = /*#__PURE__*/__webpack_require__.n(debounce);
10726 
10727 // CONCATENATED MODULE: ./src/managers/continuous/index.js
10728 
10729 
10730 
10731 
10732 
10733 
10734 class continuous_ContinuousViewManager extends managers_default["a" /* default */] {
10735   constructor(options) {
10736     super(options);
10737     this.name = "continuous";
10738     this.settings = Object(core["extend"])(this.settings || {}, {
10739       infinite: true,
10740       overflow: undefined,
10741       axis: undefined,
10742       writingMode: undefined,
10743       flow: "scrolled",
10744       offset: 500,
10745       offsetDelta: 250,
10746       width: undefined,
10747       height: undefined,
10748       snap: false,
10749       afterScrolledTimeout: 10,
10750       allowScriptedContent: false,
10751       allowPopups: false
10752     });
10753     Object(core["extend"])(this.settings, options.settings || {}); // Gap can be 0, but defaults doesn't handle that
10754 
10755     if (options.settings.gap != "undefined" && options.settings.gap === 0) {
10756       this.settings.gap = options.settings.gap;
10757     }
10758 
10759     this.viewSettings = {
10760       ignoreClass: this.settings.ignoreClass,
10761       axis: this.settings.axis,
10762       flow: this.settings.flow,
10763       layout: this.layout,
10764       width: 0,
10765       height: 0,
10766       forceEvenPages: false,
10767       allowScriptedContent: this.settings.allowScriptedContent,
10768       allowPopups: this.settings.allowPopups
10769     };
10770     this.scrollTop = 0;
10771     this.scrollLeft = 0;
10772   }
10773 
10774   display(section, target) {
10775     return managers_default["a" /* default */].prototype.display.call(this, section, target).then(function () {
10776       return this.fill();
10777     }.bind(this));
10778   }
10779 
10780   fill(_full) {
10781     var full = _full || new core["defer"]();
10782     this.q.enqueue(() => {
10783       return this.check();
10784     }).then(result => {
10785       if (result) {
10786         this.fill(full);
10787       } else {
10788         full.resolve();
10789       }
10790     });
10791     return full.promise;
10792   }
10793 
10794   moveTo(offset) {
10795     // var bounds = this.stage.bounds();
10796     // var dist = Math.floor(offset.top / bounds.height) * bounds.height;
10797     var distX = 0,
10798         distY = 0;
10799     var offsetX = 0,
10800         offsetY = 0;
10801 
10802     if (!this.isPaginated) {
10803       distY = offset.top;
10804       offsetY = offset.top + this.settings.offsetDelta;
10805     } else {
10806       distX = Math.floor(offset.left / this.layout.delta) * this.layout.delta;
10807       offsetX = distX + this.settings.offsetDelta;
10808     }
10809 
10810     if (distX > 0 || distY > 0) {
10811       this.scrollBy(distX, distY, true);
10812     }
10813   }
10814 
10815   afterResized(view) {
10816     this.emit(constants["c" /* EVENTS */].MANAGERS.RESIZE, view.section);
10817   } // Remove Previous Listeners if present
10818 
10819 
10820   removeShownListeners(view) {
10821     // view.off("shown", this.afterDisplayed);
10822     // view.off("shown", this.afterDisplayedAbove);
10823     view.onDisplayed = function () {};
10824   }
10825 
10826   add(section) {
10827     var view = this.createView(section);
10828     this.views.append(view);
10829     view.on(constants["c" /* EVENTS */].VIEWS.RESIZED, bounds => {
10830       view.expanded = true;
10831     });
10832     view.on(constants["c" /* EVENTS */].VIEWS.AXIS, axis => {
10833       this.updateAxis(axis);
10834     });
10835     view.on(constants["c" /* EVENTS */].VIEWS.WRITING_MODE, mode => {
10836       this.updateWritingMode(mode);
10837     }); // view.on(EVENTS.VIEWS.SHOWN, this.afterDisplayed.bind(this));
10838 
10839     view.onDisplayed = this.afterDisplayed.bind(this);
10840     view.onResize = this.afterResized.bind(this);
10841     return view.display(this.request);
10842   }
10843 
10844   append(section) {
10845     var view = this.createView(section);
10846     view.on(constants["c" /* EVENTS */].VIEWS.RESIZED, bounds => {
10847       view.expanded = true;
10848     });
10849     view.on(constants["c" /* EVENTS */].VIEWS.AXIS, axis => {
10850       this.updateAxis(axis);
10851     });
10852     view.on(constants["c" /* EVENTS */].VIEWS.WRITING_MODE, mode => {
10853       this.updateWritingMode(mode);
10854     });
10855     this.views.append(view);
10856     view.onDisplayed = this.afterDisplayed.bind(this);
10857     return view;
10858   }
10859 
10860   prepend(section) {
10861     var view = this.createView(section);
10862     view.on(constants["c" /* EVENTS */].VIEWS.RESIZED, bounds => {
10863       this.counter(bounds);
10864       view.expanded = true;
10865     });
10866     view.on(constants["c" /* EVENTS */].VIEWS.AXIS, axis => {
10867       this.updateAxis(axis);
10868     });
10869     view.on(constants["c" /* EVENTS */].VIEWS.WRITING_MODE, mode => {
10870       this.updateWritingMode(mode);
10871     });
10872     this.views.prepend(view);
10873     view.onDisplayed = this.afterDisplayed.bind(this);
10874     return view;
10875   }
10876 
10877   counter(bounds) {
10878     if (this.settings.axis === "vertical") {
10879       this.scrollBy(0, bounds.heightDelta, true);
10880     } else {
10881       this.scrollBy(bounds.widthDelta, 0, true);
10882     }
10883   }
10884 
10885   update(_offset) {
10886     var container = this.bounds();
10887     var views = this.views.all();
10888     var viewsLength = views.length;
10889     var visible = [];
10890     var offset = typeof _offset != "undefined" ? _offset : this.settings.offset || 0;
10891     var isVisible;
10892     var view;
10893     var updating = new core["defer"]();
10894     var promises = [];
10895 
10896     for (var i = 0; i < viewsLength; i++) {
10897       view = views[i];
10898       isVisible = this.isVisible(view, offset, offset, container);
10899 
10900       if (isVisible === true) {
10901         // console.log("visible " + view.index, view.displayed);
10902         if (!view.displayed) {
10903           let displayed = view.display(this.request).then(function (view) {
10904             view.show();
10905           }, err => {
10906             view.hide();
10907           });
10908           promises.push(displayed);
10909         } else {
10910           view.show();
10911         }
10912 
10913         visible.push(view);
10914       } else {
10915         this.q.enqueue(view.destroy.bind(view)); // console.log("hidden " + view.index, view.displayed);
10916 
10917         clearTimeout(this.trimTimeout);
10918         this.trimTimeout = setTimeout(function () {
10919           this.q.enqueue(this.trim.bind(this));
10920         }.bind(this), 250);
10921       }
10922     }
10923 
10924     if (promises.length) {
10925       return Promise.all(promises).catch(err => {
10926         updating.reject(err);
10927       });
10928     } else {
10929       updating.resolve();
10930       return updating.promise;
10931     }
10932   }
10933 
10934   check(_offsetLeft, _offsetTop) {
10935     var checking = new core["defer"]();
10936     var newViews = [];
10937     var horizontal = this.settings.axis === "horizontal";
10938     var delta = this.settings.offset || 0;
10939 
10940     if (_offsetLeft && horizontal) {
10941       delta = _offsetLeft;
10942     }
10943 
10944     if (_offsetTop && !horizontal) {
10945       delta = _offsetTop;
10946     }
10947 
10948     var bounds = this._bounds; // bounds saved this until resize
10949 
10950     let offset = horizontal ? this.scrollLeft : this.scrollTop;
10951     let visibleLength = horizontal ? Math.floor(bounds.width) : bounds.height;
10952     let contentLength = horizontal ? this.container.scrollWidth : this.container.scrollHeight;
10953     let writingMode = this.writingMode && this.writingMode.indexOf("vertical") === 0 ? "vertical" : "horizontal";
10954     let rtlScrollType = this.settings.rtlScrollType;
10955     let rtl = this.settings.direction === "rtl";
10956 
10957     if (!this.settings.fullsize) {
10958       // Scroll offset starts at width of element
10959       if (rtl && rtlScrollType === "default" && writingMode === "horizontal") {
10960         offset = contentLength - visibleLength - offset;
10961       } // Scroll offset starts at 0 and goes negative
10962 
10963 
10964       if (rtl && rtlScrollType === "negative" && writingMode === "horizontal") {
10965         offset = offset * -1;
10966       }
10967     } else {
10968       // Scroll offset starts at 0 and goes negative
10969       if (horizontal && rtl && rtlScrollType === "negative" || !horizontal && rtl && rtlScrollType === "default") {
10970         offset = offset * -1;
10971       }
10972     }
10973 
10974     let prepend = () => {
10975       let first = this.views.first();
10976       let prev = first && first.section.prev();
10977 
10978       if (prev) {
10979         newViews.push(this.prepend(prev));
10980       }
10981     };
10982 
10983     let append = () => {
10984       let last = this.views.last();
10985       let next = last && last.section.next();
10986 
10987       if (next) {
10988         newViews.push(this.append(next));
10989       }
10990     };
10991 
10992     let end = offset + visibleLength + delta;
10993     let start = offset - delta;
10994 
10995     if (end >= contentLength) {
10996       append();
10997     }
10998 
10999     if (start < 0) {
11000       prepend();
11001     }
11002 
11003     let promises = newViews.map(view => {
11004       return view.display(this.request);
11005     });
11006 
11007     if (newViews.length) {
11008       return Promise.all(promises).then(() => {
11009         return this.check();
11010       }).then(() => {
11011         // Check to see if anything new is on screen after rendering
11012         return this.update(delta);
11013       }, err => {
11014         return err;
11015       });
11016     } else {
11017       this.q.enqueue(function () {
11018         this.update();
11019       }.bind(this));
11020       checking.resolve(false);
11021       return checking.promise;
11022     }
11023   }
11024 
11025   trim() {
11026     var task = new core["defer"]();
11027     var displayed = this.views.displayed();
11028     var first = displayed[0];
11029     var last = displayed[displayed.length - 1];
11030     var firstIndex = this.views.indexOf(first);
11031     var lastIndex = this.views.indexOf(last);
11032     var above = this.views.slice(0, firstIndex);
11033     var below = this.views.slice(lastIndex + 1); // Erase all but last above
11034 
11035     for (var i = 0; i < above.length - 1; i++) {
11036       this.erase(above[i], above);
11037     } // Erase all except first below
11038 
11039 
11040     for (var j = 1; j < below.length; j++) {
11041       this.erase(below[j]);
11042     }
11043 
11044     task.resolve();
11045     return task.promise;
11046   }
11047 
11048   erase(view, above) {
11049     //Trim
11050     var prevTop;
11051     var prevLeft;
11052 
11053     if (!this.settings.fullsize) {
11054       prevTop = this.container.scrollTop;
11055       prevLeft = this.container.scrollLeft;
11056     } else {
11057       prevTop = window.scrollY;
11058       prevLeft = window.scrollX;
11059     }
11060 
11061     var bounds = view.bounds();
11062     this.views.remove(view);
11063 
11064     if (above) {
11065       if (this.settings.axis === "vertical") {
11066         this.scrollTo(0, prevTop - bounds.height, true);
11067       } else {
11068         if (this.settings.direction === 'rtl') {
11069           if (!this.settings.fullsize) {
11070             this.scrollTo(prevLeft, 0, true);
11071           } else {
11072             this.scrollTo(prevLeft + Math.floor(bounds.width), 0, true);
11073           }
11074         } else {
11075           this.scrollTo(prevLeft - Math.floor(bounds.width), 0, true);
11076         }
11077       }
11078     }
11079   }
11080 
11081   addEventListeners(stage) {
11082     window.addEventListener("unload", function (e) {
11083       this.ignore = true; // this.scrollTo(0,0);
11084 
11085       this.destroy();
11086     }.bind(this));
11087     this.addScrollListeners();
11088 
11089     if (this.isPaginated && this.settings.snap) {
11090       this.snapper = new snap(this, this.settings.snap && typeof this.settings.snap === "object" && this.settings.snap);
11091     }
11092   }
11093 
11094   addScrollListeners() {
11095     var scroller;
11096     this.tick = core["requestAnimationFrame"];
11097     let dir = this.settings.direction === "rtl" && this.settings.rtlScrollType === "default" ? -1 : 1;
11098     this.scrollDeltaVert = 0;
11099     this.scrollDeltaHorz = 0;
11100 
11101     if (!this.settings.fullsize) {
11102       scroller = this.container;
11103       this.scrollTop = this.container.scrollTop;
11104       this.scrollLeft = this.container.scrollLeft;
11105     } else {
11106       scroller = window;
11107       this.scrollTop = window.scrollY * dir;
11108       this.scrollLeft = window.scrollX * dir;
11109     }
11110 
11111     this._onScroll = this.onScroll.bind(this);
11112     scroller.addEventListener("scroll", this._onScroll);
11113     this._scrolled = debounce_default()(this.scrolled.bind(this), 30); // this.tick.call(window, this.onScroll.bind(this));
11114 
11115     this.didScroll = false;
11116   }
11117 
11118   removeEventListeners() {
11119     var scroller;
11120 
11121     if (!this.settings.fullsize) {
11122       scroller = this.container;
11123     } else {
11124       scroller = window;
11125     }
11126 
11127     scroller.removeEventListener("scroll", this._onScroll);
11128     this._onScroll = undefined;
11129   }
11130 
11131   onScroll() {
11132     let scrollTop;
11133     let scrollLeft;
11134     let dir = this.settings.direction === "rtl" && this.settings.rtlScrollType === "default" ? -1 : 1;
11135 
11136     if (!this.settings.fullsize) {
11137       scrollTop = this.container.scrollTop;
11138       scrollLeft = this.container.scrollLeft;
11139     } else {
11140       scrollTop = window.scrollY * dir;
11141       scrollLeft = window.scrollX * dir;
11142     }
11143 
11144     this.scrollTop = scrollTop;
11145     this.scrollLeft = scrollLeft;
11146 
11147     if (!this.ignore) {
11148       this._scrolled();
11149     } else {
11150       this.ignore = false;
11151     }
11152 
11153     this.scrollDeltaVert += Math.abs(scrollTop - this.prevScrollTop);
11154     this.scrollDeltaHorz += Math.abs(scrollLeft - this.prevScrollLeft);
11155     this.prevScrollTop = scrollTop;
11156     this.prevScrollLeft = scrollLeft;
11157     clearTimeout(this.scrollTimeout);
11158     this.scrollTimeout = setTimeout(function () {
11159       this.scrollDeltaVert = 0;
11160       this.scrollDeltaHorz = 0;
11161     }.bind(this), 150);
11162     clearTimeout(this.afterScrolled);
11163     this.didScroll = false;
11164   }
11165 
11166   scrolled() {
11167     this.q.enqueue(function () {
11168       return this.check();
11169     }.bind(this));
11170     this.emit(constants["c" /* EVENTS */].MANAGERS.SCROLL, {
11171       top: this.scrollTop,
11172       left: this.scrollLeft
11173     });
11174     clearTimeout(this.afterScrolled);
11175     this.afterScrolled = setTimeout(function () {
11176       // Don't report scroll if we are about the snap
11177       if (this.snapper && this.snapper.supportsTouch && this.snapper.needsSnap()) {
11178         return;
11179       }
11180 
11181       this.emit(constants["c" /* EVENTS */].MANAGERS.SCROLLED, {
11182         top: this.scrollTop,
11183         left: this.scrollLeft
11184       });
11185     }.bind(this), this.settings.afterScrolledTimeout);
11186   }
11187 
11188   next() {
11189     let delta = this.layout.props.name === "pre-paginated" && this.layout.props.spread ? this.layout.props.delta * 2 : this.layout.props.delta;
11190     if (!this.views.length) return;
11191 
11192     if (this.isPaginated && this.settings.axis === "horizontal") {
11193       this.scrollBy(delta, 0, true);
11194     } else {
11195       this.scrollBy(0, this.layout.height, true);
11196     }
11197 
11198     this.q.enqueue(function () {
11199       return this.check();
11200     }.bind(this));
11201   }
11202 
11203   prev() {
11204     let delta = this.layout.props.name === "pre-paginated" && this.layout.props.spread ? this.layout.props.delta * 2 : this.layout.props.delta;
11205     if (!this.views.length) return;
11206 
11207     if (this.isPaginated && this.settings.axis === "horizontal") {
11208       this.scrollBy(-delta, 0, true);
11209     } else {
11210       this.scrollBy(0, -this.layout.height, true);
11211     }
11212 
11213     this.q.enqueue(function () {
11214       return this.check();
11215     }.bind(this));
11216   }
11217 
11218   updateFlow(flow) {
11219     if (this.rendered && this.snapper) {
11220       this.snapper.destroy();
11221       this.snapper = undefined;
11222     }
11223 
11224     super.updateFlow(flow, "scroll");
11225 
11226     if (this.rendered && this.isPaginated && this.settings.snap) {
11227       this.snapper = new snap(this, this.settings.snap && typeof this.settings.snap === "object" && this.settings.snap);
11228     }
11229   }
11230 
11231   destroy() {
11232     super.destroy();
11233 
11234     if (this.snapper) {
11235       this.snapper.destroy();
11236     }
11237   }
11238 
11239 }
11240 
11241 /* harmony default export */ var continuous = __webpack_exports__["a"] = (continuous_ContinuousViewManager);
11242 
11243 /***/ }),
11244 /* 23 */
11245 /***/ (function(module, exports, __webpack_require__) {
11246 
11247 /* WEBPACK VAR INJECTION */(function(global) {var require;var require;/*!
11248     localForage -- Offline Storage, Improved
11249     Version 1.10.0
11250     https://localforage.github.io/localForage
11251     (c) 2013-2017 Mozilla, Apache License 2.0
11252 */
11253 (function(f){if(true){module.exports=f()}else { var g; }})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return require(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw (f.code="MODULE_NOT_FOUND", f)}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(_dereq_,module,exports){
11254 (function (global){
11255 'use strict';
11256 var Mutation = global.MutationObserver || global.WebKitMutationObserver;
11257 
11258 var scheduleDrain;
11259 
11260 {
11261   if (Mutation) {
11262     var called = 0;
11263     var observer = new Mutation(nextTick);
11264     var element = global.document.createTextNode('');
11265     observer.observe(element, {
11266       characterData: true
11267     });
11268     scheduleDrain = function () {
11269       element.data = (called = ++called % 2);
11270     };
11271   } else if (!global.setImmediate && typeof global.MessageChannel !== 'undefined') {
11272     var channel = new global.MessageChannel();
11273     channel.port1.onmessage = nextTick;
11274     scheduleDrain = function () {
11275       channel.port2.postMessage(0);
11276     };
11277   } else if ('document' in global && 'onreadystatechange' in global.document.createElement('script')) {
11278     scheduleDrain = function () {
11279 
11280       // Create a <script> element; its readystatechange event will be fired asynchronously once it is inserted
11281       // into the document. Do so, thus queuing up the task. Remember to clean up once it's been called.
11282       var scriptEl = global.document.createElement('script');
11283       scriptEl.onreadystatechange = function () {
11284         nextTick();
11285 
11286         scriptEl.onreadystatechange = null;
11287         scriptEl.parentNode.removeChild(scriptEl);
11288         scriptEl = null;
11289       };
11290       global.document.documentElement.appendChild(scriptEl);
11291     };
11292   } else {
11293     scheduleDrain = function () {
11294       setTimeout(nextTick, 0);
11295     };
11296   }
11297 }
11298 
11299 var draining;
11300 var queue = [];
11301 //named nextTick for less confusing stack traces
11302 function nextTick() {
11303   draining = true;
11304   var i, oldQueue;
11305   var len = queue.length;
11306   while (len) {
11307     oldQueue = queue;
11308     queue = [];
11309     i = -1;
11310     while (++i < len) {
11311       oldQueue[i]();
11312     }
11313     len = queue.length;
11314   }
11315   draining = false;
11316 }
11317 
11318 module.exports = immediate;
11319 function immediate(task) {
11320   if (queue.push(task) === 1 && !draining) {
11321     scheduleDrain();
11322   }
11323 }
11324 
11325 }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
11326 },{}],2:[function(_dereq_,module,exports){
11327 'use strict';
11328 var immediate = _dereq_(1);
11329 
11330 /* istanbul ignore next */
11331 function INTERNAL() {}
11332 
11333 var handlers = {};
11334 
11335 var REJECTED = ['REJECTED'];
11336 var FULFILLED = ['FULFILLED'];
11337 var PENDING = ['PENDING'];
11338 
11339 module.exports = Promise;
11340 
11341 function Promise(resolver) {
11342   if (typeof resolver !== 'function') {
11343     throw new TypeError('resolver must be a function');
11344   }
11345   this.state = PENDING;
11346   this.queue = [];
11347   this.outcome = void 0;
11348   if (resolver !== INTERNAL) {
11349     safelyResolveThenable(this, resolver);
11350   }
11351 }
11352 
11353 Promise.prototype["catch"] = function (onRejected) {
11354   return this.then(null, onRejected);
11355 };
11356 Promise.prototype.then = function (onFulfilled, onRejected) {
11357   if (typeof onFulfilled !== 'function' && this.state === FULFILLED ||
11358     typeof onRejected !== 'function' && this.state === REJECTED) {
11359     return this;
11360   }
11361   var promise = new this.constructor(INTERNAL);
11362   if (this.state !== PENDING) {
11363     var resolver = this.state === FULFILLED ? onFulfilled : onRejected;
11364     unwrap(promise, resolver, this.outcome);
11365   } else {
11366     this.queue.push(new QueueItem(promise, onFulfilled, onRejected));
11367   }
11368 
11369   return promise;
11370 };
11371 function QueueItem(promise, onFulfilled, onRejected) {
11372   this.promise = promise;
11373   if (typeof onFulfilled === 'function') {
11374     this.onFulfilled = onFulfilled;
11375     this.callFulfilled = this.otherCallFulfilled;
11376   }
11377   if (typeof onRejected === 'function') {
11378     this.onRejected = onRejected;
11379     this.callRejected = this.otherCallRejected;
11380   }
11381 }
11382 QueueItem.prototype.callFulfilled = function (value) {
11383   handlers.resolve(this.promise, value);
11384 };
11385 QueueItem.prototype.otherCallFulfilled = function (value) {
11386   unwrap(this.promise, this.onFulfilled, value);
11387 };
11388 QueueItem.prototype.callRejected = function (value) {
11389   handlers.reject(this.promise, value);
11390 };
11391 QueueItem.prototype.otherCallRejected = function (value) {
11392   unwrap(this.promise, this.onRejected, value);
11393 };
11394 
11395 function unwrap(promise, func, value) {
11396   immediate(function () {
11397     var returnValue;
11398     try {
11399       returnValue = func(value);
11400     } catch (e) {
11401       return handlers.reject(promise, e);
11402     }
11403     if (returnValue === promise) {
11404       handlers.reject(promise, new TypeError('Cannot resolve promise with itself'));
11405     } else {
11406       handlers.resolve(promise, returnValue);
11407     }
11408   });
11409 }
11410 
11411 handlers.resolve = function (self, value) {
11412   var result = tryCatch(getThen, value);
11413   if (result.status === 'error') {
11414     return handlers.reject(self, result.value);
11415   }
11416   var thenable = result.value;
11417 
11418   if (thenable) {
11419     safelyResolveThenable(self, thenable);
11420   } else {
11421     self.state = FULFILLED;
11422     self.outcome = value;
11423     var i = -1;
11424     var len = self.queue.length;
11425     while (++i < len) {
11426       self.queue[i].callFulfilled(value);
11427     }
11428   }
11429   return self;
11430 };
11431 handlers.reject = function (self, error) {
11432   self.state = REJECTED;
11433   self.outcome = error;
11434   var i = -1;
11435   var len = self.queue.length;
11436   while (++i < len) {
11437     self.queue[i].callRejected(error);
11438   }
11439   return self;
11440 };
11441 
11442 function getThen(obj) {
11443   // Make sure we only access the accessor once as required by the spec
11444   var then = obj && obj.then;
11445   if (obj && (typeof obj === 'object' || typeof obj === 'function') && typeof then === 'function') {
11446     return function appyThen() {
11447       then.apply(obj, arguments);
11448     };
11449   }
11450 }
11451 
11452 function safelyResolveThenable(self, thenable) {
11453   // Either fulfill, reject or reject with error
11454   var called = false;
11455   function onError(value) {
11456     if (called) {
11457       return;
11458     }
11459     called = true;
11460     handlers.reject(self, value);
11461   }
11462 
11463   function onSuccess(value) {
11464     if (called) {
11465       return;
11466     }
11467     called = true;
11468     handlers.resolve(self, value);
11469   }
11470 
11471   function tryToUnwrap() {
11472     thenable(onSuccess, onError);
11473   }
11474 
11475   var result = tryCatch(tryToUnwrap);
11476   if (result.status === 'error') {
11477     onError(result.value);
11478   }
11479 }
11480 
11481 function tryCatch(func, value) {
11482   var out = {};
11483   try {
11484     out.value = func(value);
11485     out.status = 'success';
11486   } catch (e) {
11487     out.status = 'error';
11488     out.value = e;
11489   }
11490   return out;
11491 }
11492 
11493 Promise.resolve = resolve;
11494 function resolve(value) {
11495   if (value instanceof this) {
11496     return value;
11497   }
11498   return handlers.resolve(new this(INTERNAL), value);
11499 }
11500 
11501 Promise.reject = reject;
11502 function reject(reason) {
11503   var promise = new this(INTERNAL);
11504   return handlers.reject(promise, reason);
11505 }
11506 
11507 Promise.all = all;
11508 function all(iterable) {
11509   var self = this;
11510   if (Object.prototype.toString.call(iterable) !== '[object Array]') {
11511     return this.reject(new TypeError('must be an array'));
11512   }
11513 
11514   var len = iterable.length;
11515   var called = false;
11516   if (!len) {
11517     return this.resolve([]);
11518   }
11519 
11520   var values = new Array(len);
11521   var resolved = 0;
11522   var i = -1;
11523   var promise = new this(INTERNAL);
11524 
11525   while (++i < len) {
11526     allResolver(iterable[i], i);
11527   }
11528   return promise;
11529   function allResolver(value, i) {
11530     self.resolve(value).then(resolveFromAll, function (error) {
11531       if (!called) {
11532         called = true;
11533         handlers.reject(promise, error);
11534       }
11535     });
11536     function resolveFromAll(outValue) {
11537       values[i] = outValue;
11538       if (++resolved === len && !called) {
11539         called = true;
11540         handlers.resolve(promise, values);
11541       }
11542     }
11543   }
11544 }
11545 
11546 Promise.race = race;
11547 function race(iterable) {
11548   var self = this;
11549   if (Object.prototype.toString.call(iterable) !== '[object Array]') {
11550     return this.reject(new TypeError('must be an array'));
11551   }
11552 
11553   var len = iterable.length;
11554   var called = false;
11555   if (!len) {
11556     return this.resolve([]);
11557   }
11558 
11559   var i = -1;
11560   var promise = new this(INTERNAL);
11561 
11562   while (++i < len) {
11563     resolver(iterable[i]);
11564   }
11565   return promise;
11566   function resolver(value) {
11567     self.resolve(value).then(function (response) {
11568       if (!called) {
11569         called = true;
11570         handlers.resolve(promise, response);
11571       }
11572     }, function (error) {
11573       if (!called) {
11574         called = true;
11575         handlers.reject(promise, error);
11576       }
11577     });
11578   }
11579 }
11580 
11581 },{"1":1}],3:[function(_dereq_,module,exports){
11582 (function (global){
11583 'use strict';
11584 if (typeof global.Promise !== 'function') {
11585   global.Promise = _dereq_(2);
11586 }
11587 
11588 }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
11589 },{"2":2}],4:[function(_dereq_,module,exports){
11590 'use strict';
11591 
11592 var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
11593 
11594 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
11595 
11596 function getIDB() {
11597     /* global indexedDB,webkitIndexedDB,mozIndexedDB,OIndexedDB,msIndexedDB */
11598     try {
11599         if (typeof indexedDB !== 'undefined') {
11600             return indexedDB;
11601         }
11602         if (typeof webkitIndexedDB !== 'undefined') {
11603             return webkitIndexedDB;
11604         }
11605         if (typeof mozIndexedDB !== 'undefined') {
11606             return mozIndexedDB;
11607         }
11608         if (typeof OIndexedDB !== 'undefined') {
11609             return OIndexedDB;
11610         }
11611         if (typeof msIndexedDB !== 'undefined') {
11612             return msIndexedDB;
11613         }
11614     } catch (e) {
11615         return;
11616     }
11617 }
11618 
11619 var idb = getIDB();
11620 
11621 function isIndexedDBValid() {
11622     try {
11623         // Initialize IndexedDB; fall back to vendor-prefixed versions
11624         // if needed.
11625         if (!idb || !idb.open) {
11626             return false;
11627         }
11628         // We mimic PouchDB here;
11629         //
11630         // We test for openDatabase because IE Mobile identifies itself
11631         // as Safari. Oh the lulz...
11632         var isSafari = typeof openDatabase !== 'undefined' && /(Safari|iPhone|iPad|iPod)/.test(navigator.userAgent) && !/Chrome/.test(navigator.userAgent) && !/BlackBerry/.test(navigator.platform);
11633 
11634         var hasFetch = typeof fetch === 'function' && fetch.toString().indexOf('[native code') !== -1;
11635 
11636         // Safari <10.1 does not meet our requirements for IDB support
11637         // (see: https://github.com/pouchdb/pouchdb/issues/5572).
11638         // Safari 10.1 shipped with fetch, we can use that to detect it.
11639         // Note: this creates issues with `window.fetch` polyfills and
11640         // overrides; see:
11641         // https://github.com/localForage/localForage/issues/856
11642         return (!isSafari || hasFetch) && typeof indexedDB !== 'undefined' &&
11643         // some outdated implementations of IDB that appear on Samsung
11644         // and HTC Android devices <4.4 are missing IDBKeyRange
11645         // See: https://github.com/mozilla/localForage/issues/128
11646         // See: https://github.com/mozilla/localForage/issues/272
11647         typeof IDBKeyRange !== 'undefined';
11648     } catch (e) {
11649         return false;
11650     }
11651 }
11652 
11653 // Abstracts constructing a Blob object, so it also works in older
11654 // browsers that don't support the native Blob constructor. (i.e.
11655 // old QtWebKit versions, at least).
11656 // Abstracts constructing a Blob object, so it also works in older
11657 // browsers that don't support the native Blob constructor. (i.e.
11658 // old QtWebKit versions, at least).
11659 function createBlob(parts, properties) {
11660     /* global BlobBuilder,MSBlobBuilder,MozBlobBuilder,WebKitBlobBuilder */
11661     parts = parts || [];
11662     properties = properties || {};
11663     try {
11664         return new Blob(parts, properties);
11665     } catch (e) {
11666         if (e.name !== 'TypeError') {
11667             throw e;
11668         }
11669         var Builder = typeof BlobBuilder !== 'undefined' ? BlobBuilder : typeof MSBlobBuilder !== 'undefined' ? MSBlobBuilder : typeof MozBlobBuilder !== 'undefined' ? MozBlobBuilder : WebKitBlobBuilder;
11670         var builder = new Builder();
11671         for (var i = 0; i < parts.length; i += 1) {
11672             builder.append(parts[i]);
11673         }
11674         return builder.getBlob(properties.type);
11675     }
11676 }
11677 
11678 // This is CommonJS because lie is an external dependency, so Rollup
11679 // can just ignore it.
11680 if (typeof Promise === 'undefined') {
11681     // In the "nopromises" build this will just throw if you don't have
11682     // a global promise object, but it would throw anyway later.
11683     _dereq_(3);
11684 }
11685 var Promise$1 = Promise;
11686 
11687 function executeCallback(promise, callback) {
11688     if (callback) {
11689         promise.then(function (result) {
11690             callback(null, result);
11691         }, function (error) {
11692             callback(error);
11693         });
11694     }
11695 }
11696 
11697 function executeTwoCallbacks(promise, callback, errorCallback) {
11698     if (typeof callback === 'function') {
11699         promise.then(callback);
11700     }
11701 
11702     if (typeof errorCallback === 'function') {
11703         promise["catch"](errorCallback);
11704     }
11705 }
11706 
11707 function normalizeKey(key) {
11708     // Cast the key to a string, as that's all we can set as a key.
11709     if (typeof key !== 'string') {
11710         console.warn(key + ' used as a key, but it is not a string.');
11711         key = String(key);
11712     }
11713 
11714     return key;
11715 }
11716 
11717 function getCallback() {
11718     if (arguments.length && typeof arguments[arguments.length - 1] === 'function') {
11719         return arguments[arguments.length - 1];
11720     }
11721 }
11722 
11723 // Some code originally from async_storage.js in
11724 // [Gaia](https://github.com/mozilla-b2g/gaia).
11725 
11726 var DETECT_BLOB_SUPPORT_STORE = 'local-forage-detect-blob-support';
11727 var supportsBlobs = void 0;
11728 var dbContexts = {};
11729 var toString = Object.prototype.toString;
11730 
11731 // Transaction Modes
11732 var READ_ONLY = 'readonly';
11733 var READ_WRITE = 'readwrite';
11734 
11735 // Transform a binary string to an array buffer, because otherwise
11736 // weird stuff happens when you try to work with the binary string directly.
11737 // It is known.
11738 // From http://stackoverflow.com/questions/14967647/ (continues on next line)
11739 // encode-decode-image-with-base64-breaks-image (2013-04-21)
11740 function _binStringToArrayBuffer(bin) {
11741     var length = bin.length;
11742     var buf = new ArrayBuffer(length);
11743     var arr = new Uint8Array(buf);
11744     for (var i = 0; i < length; i++) {
11745         arr[i] = bin.charCodeAt(i);
11746     }
11747     return buf;
11748 }
11749 
11750 //
11751 // Blobs are not supported in all versions of IndexedDB, notably
11752 // Chrome <37 and Android <5. In those versions, storing a blob will throw.
11753 //
11754 // Various other blob bugs exist in Chrome v37-42 (inclusive).
11755 // Detecting them is expensive and confusing to users, and Chrome 37-42
11756 // is at very low usage worldwide, so we do a hacky userAgent check instead.
11757 //
11758 // content-type bug: https://code.google.com/p/chromium/issues/detail?id=408120
11759 // 404 bug: https://code.google.com/p/chromium/issues/detail?id=447916
11760 // FileReader bug: https://code.google.com/p/chromium/issues/detail?id=447836
11761 //
11762 // Code borrowed from PouchDB. See:
11763 // https://github.com/pouchdb/pouchdb/blob/master/packages/node_modules/pouchdb-adapter-idb/src/blobSupport.js
11764 //
11765 function _checkBlobSupportWithoutCaching(idb) {
11766     return new Promise$1(function (resolve) {
11767         var txn = idb.transaction(DETECT_BLOB_SUPPORT_STORE, READ_WRITE);
11768         var blob = createBlob(['']);
11769         txn.objectStore(DETECT_BLOB_SUPPORT_STORE).put(blob, 'key');
11770 
11771         txn.onabort = function (e) {
11772             // If the transaction aborts now its due to not being able to
11773             // write to the database, likely due to the disk being full
11774             e.preventDefault();
11775             e.stopPropagation();
11776             resolve(false);
11777         };
11778 
11779         txn.oncomplete = function () {
11780             var matchedChrome = navigator.userAgent.match(/Chrome\/(\d+)/);
11781             var matchedEdge = navigator.userAgent.match(/Edge\//);
11782             // MS Edge pretends to be Chrome 42:
11783             // https://msdn.microsoft.com/en-us/library/hh869301%28v=vs.85%29.aspx
11784             resolve(matchedEdge || !matchedChrome || parseInt(matchedChrome[1], 10) >= 43);
11785         };
11786     })["catch"](function () {
11787         return false; // error, so assume unsupported
11788     });
11789 }
11790 
11791 function _checkBlobSupport(idb) {
11792     if (typeof supportsBlobs === 'boolean') {
11793         return Promise$1.resolve(supportsBlobs);
11794     }
11795     return _checkBlobSupportWithoutCaching(idb).then(function (value) {
11796         supportsBlobs = value;
11797         return supportsBlobs;
11798     });
11799 }
11800 
11801 function _deferReadiness(dbInfo) {
11802     var dbContext = dbContexts[dbInfo.name];
11803 
11804     // Create a deferred object representing the current database operation.
11805     var deferredOperation = {};
11806 
11807     deferredOperation.promise = new Promise$1(function (resolve, reject) {
11808         deferredOperation.resolve = resolve;
11809         deferredOperation.reject = reject;
11810     });
11811 
11812     // Enqueue the deferred operation.
11813     dbContext.deferredOperations.push(deferredOperation);
11814 
11815     // Chain its promise to the database readiness.
11816     if (!dbContext.dbReady) {
11817         dbContext.dbReady = deferredOperation.promise;
11818     } else {
11819         dbContext.dbReady = dbContext.dbReady.then(function () {
11820             return deferredOperation.promise;
11821         });
11822     }
11823 }
11824 
11825 function _advanceReadiness(dbInfo) {
11826     var dbContext = dbContexts[dbInfo.name];
11827 
11828     // Dequeue a deferred operation.
11829     var deferredOperation = dbContext.deferredOperations.pop();
11830 
11831     // Resolve its promise (which is part of the database readiness
11832     // chain of promises).
11833     if (deferredOperation) {
11834         deferredOperation.resolve();
11835         return deferredOperation.promise;
11836     }
11837 }
11838 
11839 function _rejectReadiness(dbInfo, err) {
11840     var dbContext = dbContexts[dbInfo.name];
11841 
11842     // Dequeue a deferred operation.
11843     var deferredOperation = dbContext.deferredOperations.pop();
11844 
11845     // Reject its promise (which is part of the database readiness
11846     // chain of promises).
11847     if (deferredOperation) {
11848         deferredOperation.reject(err);
11849         return deferredOperation.promise;
11850     }
11851 }
11852 
11853 function _getConnection(dbInfo, upgradeNeeded) {
11854     return new Promise$1(function (resolve, reject) {
11855         dbContexts[dbInfo.name] = dbContexts[dbInfo.name] || createDbContext();
11856 
11857         if (dbInfo.db) {
11858             if (upgradeNeeded) {
11859                 _deferReadiness(dbInfo);
11860                 dbInfo.db.close();
11861             } else {
11862                 return resolve(dbInfo.db);
11863             }
11864         }
11865 
11866         var dbArgs = [dbInfo.name];
11867 
11868         if (upgradeNeeded) {
11869             dbArgs.push(dbInfo.version);
11870         }
11871 
11872         var openreq = idb.open.apply(idb, dbArgs);
11873 
11874         if (upgradeNeeded) {
11875             openreq.onupgradeneeded = function (e) {
11876                 var db = openreq.result;
11877                 try {
11878                     db.createObjectStore(dbInfo.storeName);
11879                     if (e.oldVersion <= 1) {
11880                         // Added when support for blob shims was added
11881                         db.createObjectStore(DETECT_BLOB_SUPPORT_STORE);
11882                     }
11883                 } catch (ex) {
11884                     if (ex.name === 'ConstraintError') {
11885                         console.warn('The database "' + dbInfo.name + '"' + ' has been upgraded from version ' + e.oldVersion + ' to version ' + e.newVersion + ', but the storage "' + dbInfo.storeName + '" already exists.');
11886                     } else {
11887                         throw ex;
11888                     }
11889                 }
11890             };
11891         }
11892 
11893         openreq.onerror = function (e) {
11894             e.preventDefault();
11895             reject(openreq.error);
11896         };
11897 
11898         openreq.onsuccess = function () {
11899             var db = openreq.result;
11900             db.onversionchange = function (e) {
11901                 // Triggered when the database is modified (e.g. adding an objectStore) or
11902                 // deleted (even when initiated by other sessions in different tabs).
11903                 // Closing the connection here prevents those operations from being blocked.
11904                 // If the database is accessed again later by this instance, the connection
11905                 // will be reopened or the database recreated as needed.
11906                 e.target.close();
11907             };
11908             resolve(db);
11909             _advanceReadiness(dbInfo);
11910         };
11911     });
11912 }
11913 
11914 function _getOriginalConnection(dbInfo) {
11915     return _getConnection(dbInfo, false);
11916 }
11917 
11918 function _getUpgradedConnection(dbInfo) {
11919     return _getConnection(dbInfo, true);
11920 }
11921 
11922 function _isUpgradeNeeded(dbInfo, defaultVersion) {
11923     if (!dbInfo.db) {
11924         return true;
11925     }
11926 
11927     var isNewStore = !dbInfo.db.objectStoreNames.contains(dbInfo.storeName);
11928     var isDowngrade = dbInfo.version < dbInfo.db.version;
11929     var isUpgrade = dbInfo.version > dbInfo.db.version;
11930 
11931     if (isDowngrade) {
11932         // If the version is not the default one
11933         // then warn for impossible downgrade.
11934         if (dbInfo.version !== defaultVersion) {
11935             console.warn('The database "' + dbInfo.name + '"' + " can't be downgraded from version " + dbInfo.db.version + ' to version ' + dbInfo.version + '.');
11936         }
11937         // Align the versions to prevent errors.
11938         dbInfo.version = dbInfo.db.version;
11939     }
11940 
11941     if (isUpgrade || isNewStore) {
11942         // If the store is new then increment the version (if needed).
11943         // This will trigger an "upgradeneeded" event which is required
11944         // for creating a store.
11945         if (isNewStore) {
11946             var incVersion = dbInfo.db.version + 1;
11947             if (incVersion > dbInfo.version) {
11948                 dbInfo.version = incVersion;
11949             }
11950         }
11951 
11952         return true;
11953     }
11954 
11955     return false;
11956 }
11957 
11958 // encode a blob for indexeddb engines that don't support blobs
11959 function _encodeBlob(blob) {
11960     return new Promise$1(function (resolve, reject) {
11961         var reader = new FileReader();
11962         reader.onerror = reject;
11963         reader.onloadend = function (e) {
11964             var base64 = btoa(e.target.result || '');
11965             resolve({
11966                 __local_forage_encoded_blob: true,
11967                 data: base64,
11968                 type: blob.type
11969             });
11970         };
11971         reader.readAsBinaryString(blob);
11972     });
11973 }
11974 
11975 // decode an encoded blob
11976 function _decodeBlob(encodedBlob) {
11977     var arrayBuff = _binStringToArrayBuffer(atob(encodedBlob.data));
11978     return createBlob([arrayBuff], { type: encodedBlob.type });
11979 }
11980 
11981 // is this one of our fancy encoded blobs?
11982 function _isEncodedBlob(value) {
11983     return value && value.__local_forage_encoded_blob;
11984 }
11985 
11986 // Specialize the default `ready()` function by making it dependent
11987 // on the current database operations. Thus, the driver will be actually
11988 // ready when it's been initialized (default) *and* there are no pending
11989 // operations on the database (initiated by some other instances).
11990 function _fullyReady(callback) {
11991     var self = this;
11992 
11993     var promise = self._initReady().then(function () {
11994         var dbContext = dbContexts[self._dbInfo.name];
11995 
11996         if (dbContext && dbContext.dbReady) {
11997             return dbContext.dbReady;
11998         }
11999     });
12000 
12001     executeTwoCallbacks(promise, callback, callback);
12002     return promise;
12003 }
12004 
12005 // Try to establish a new db connection to replace the
12006 // current one which is broken (i.e. experiencing
12007 // InvalidStateError while creating a transaction).
12008 function _tryReconnect(dbInfo) {
12009     _deferReadiness(dbInfo);
12010 
12011     var dbContext = dbContexts[dbInfo.name];
12012     var forages = dbContext.forages;
12013 
12014     for (var i = 0; i < forages.length; i++) {
12015         var forage = forages[i];
12016         if (forage._dbInfo.db) {
12017             forage._dbInfo.db.close();
12018             forage._dbInfo.db = null;
12019         }
12020     }
12021     dbInfo.db = null;
12022 
12023     return _getOriginalConnection(dbInfo).then(function (db) {
12024         dbInfo.db = db;
12025         if (_isUpgradeNeeded(dbInfo)) {
12026             // Reopen the database for upgrading.
12027             return _getUpgradedConnection(dbInfo);
12028         }
12029         return db;
12030     }).then(function (db) {
12031         // store the latest db reference
12032         // in case the db was upgraded
12033         dbInfo.db = dbContext.db = db;
12034         for (var i = 0; i < forages.length; i++) {
12035             forages[i]._dbInfo.db = db;
12036         }
12037     })["catch"](function (err) {
12038         _rejectReadiness(dbInfo, err);
12039         throw err;
12040     });
12041 }
12042 
12043 // FF doesn't like Promises (micro-tasks) and IDDB store operations,
12044 // so we have to do it with callbacks
12045 function createTransaction(dbInfo, mode, callback, retries) {
12046     if (retries === undefined) {
12047         retries = 1;
12048     }
12049 
12050     try {
12051         var tx = dbInfo.db.transaction(dbInfo.storeName, mode);
12052         callback(null, tx);
12053     } catch (err) {
12054         if (retries > 0 && (!dbInfo.db || err.name === 'InvalidStateError' || err.name === 'NotFoundError')) {
12055             return Promise$1.resolve().then(function () {
12056                 if (!dbInfo.db || err.name === 'NotFoundError' && !dbInfo.db.objectStoreNames.contains(dbInfo.storeName) && dbInfo.version <= dbInfo.db.version) {
12057                     // increase the db version, to create the new ObjectStore
12058                     if (dbInfo.db) {
12059                         dbInfo.version = dbInfo.db.version + 1;
12060                     }
12061                     // Reopen the database for upgrading.
12062                     return _getUpgradedConnection(dbInfo);
12063                 }
12064             }).then(function () {
12065                 return _tryReconnect(dbInfo).then(function () {
12066                     createTransaction(dbInfo, mode, callback, retries - 1);
12067                 });
12068             })["catch"](callback);
12069         }
12070 
12071         callback(err);
12072     }
12073 }
12074 
12075 function createDbContext() {
12076     return {
12077         // Running localForages sharing a database.
12078         forages: [],
12079         // Shared database.
12080         db: null,
12081         // Database readiness (promise).
12082         dbReady: null,
12083         // Deferred operations on the database.
12084         deferredOperations: []
12085     };
12086 }
12087 
12088 // Open the IndexedDB database (automatically creates one if one didn't
12089 // previously exist), using any options set in the config.
12090 function _initStorage(options) {
12091     var self = this;
12092     var dbInfo = {
12093         db: null
12094     };
12095 
12096     if (options) {
12097         for (var i in options) {
12098             dbInfo[i] = options[i];
12099         }
12100     }
12101 
12102     // Get the current context of the database;
12103     var dbContext = dbContexts[dbInfo.name];
12104 
12105     // ...or create a new context.
12106     if (!dbContext) {
12107         dbContext = createDbContext();
12108         // Register the new context in the global container.
12109         dbContexts[dbInfo.name] = dbContext;
12110     }
12111 
12112     // Register itself as a running localForage in the current context.
12113     dbContext.forages.push(self);
12114 
12115     // Replace the default `ready()` function with the specialized one.
12116     if (!self._initReady) {
12117         self._initReady = self.ready;
12118         self.ready = _fullyReady;
12119     }
12120 
12121     // Create an array of initialization states of the related localForages.
12122     var initPromises = [];
12123 
12124     function ignoreErrors() {
12125         // Don't handle errors here,
12126         // just makes sure related localForages aren't pending.
12127         return Promise$1.resolve();
12128     }
12129 
12130     for (var j = 0; j < dbContext.forages.length; j++) {
12131         var forage = dbContext.forages[j];
12132         if (forage !== self) {
12133             // Don't wait for itself...
12134             initPromises.push(forage._initReady()["catch"](ignoreErrors));
12135         }
12136     }
12137 
12138     // Take a snapshot of the related localForages.
12139     var forages = dbContext.forages.slice(0);
12140 
12141     // Initialize the connection process only when
12142     // all the related localForages aren't pending.
12143     return Promise$1.all(initPromises).then(function () {
12144         dbInfo.db = dbContext.db;
12145         // Get the connection or open a new one without upgrade.
12146         return _getOriginalConnection(dbInfo);
12147     }).then(function (db) {
12148         dbInfo.db = db;
12149         if (_isUpgradeNeeded(dbInfo, self._defaultConfig.version)) {
12150             // Reopen the database for upgrading.
12151             return _getUpgradedConnection(dbInfo);
12152         }
12153         return db;
12154     }).then(function (db) {
12155         dbInfo.db = dbContext.db = db;
12156         self._dbInfo = dbInfo;
12157         // Share the final connection amongst related localForages.
12158         for (var k = 0; k < forages.length; k++) {
12159             var forage = forages[k];
12160             if (forage !== self) {
12161                 // Self is already up-to-date.
12162                 forage._dbInfo.db = dbInfo.db;
12163                 forage._dbInfo.version = dbInfo.version;
12164             }
12165         }
12166     });
12167 }
12168 
12169 function getItem(key, callback) {
12170     var self = this;
12171 
12172     key = normalizeKey(key);
12173 
12174     var promise = new Promise$1(function (resolve, reject) {
12175         self.ready().then(function () {
12176             createTransaction(self._dbInfo, READ_ONLY, function (err, transaction) {
12177                 if (err) {
12178                     return reject(err);
12179                 }
12180 
12181                 try {
12182                     var store = transaction.objectStore(self._dbInfo.storeName);
12183                     var req = store.get(key);
12184 
12185                     req.onsuccess = function () {
12186                         var value = req.result;
12187                         if (value === undefined) {
12188                             value = null;
12189                         }
12190                         if (_isEncodedBlob(value)) {
12191                             value = _decodeBlob(value);
12192                         }
12193                         resolve(value);
12194                     };
12195 
12196                     req.onerror = function () {
12197                         reject(req.error);
12198                     };
12199                 } catch (e) {
12200                     reject(e);
12201                 }
12202             });
12203         })["catch"](reject);
12204     });
12205 
12206     executeCallback(promise, callback);
12207     return promise;
12208 }
12209 
12210 // Iterate over all items stored in database.
12211 function iterate(iterator, callback) {
12212     var self = this;
12213 
12214     var promise = new Promise$1(function (resolve, reject) {
12215         self.ready().then(function () {
12216             createTransaction(self._dbInfo, READ_ONLY, function (err, transaction) {
12217                 if (err) {
12218                     return reject(err);
12219                 }
12220 
12221                 try {
12222                     var store = transaction.objectStore(self._dbInfo.storeName);
12223                     var req = store.openCursor();
12224                     var iterationNumber = 1;
12225 
12226                     req.onsuccess = function () {
12227                         var cursor = req.result;
12228 
12229                         if (cursor) {
12230                             var value = cursor.value;
12231                             if (_isEncodedBlob(value)) {
12232                                 value = _decodeBlob(value);
12233                             }
12234                             var result = iterator(value, cursor.key, iterationNumber++);
12235 
12236                             // when the iterator callback returns any
12237                             // (non-`undefined`) value, then we stop
12238                             // the iteration immediately
12239                             if (result !== void 0) {
12240                                 resolve(result);
12241                             } else {
12242                                 cursor["continue"]();
12243                             }
12244                         } else {
12245                             resolve();
12246                         }
12247                     };
12248 
12249                     req.onerror = function () {
12250                         reject(req.error);
12251                     };
12252                 } catch (e) {
12253                     reject(e);
12254                 }
12255             });
12256         })["catch"](reject);
12257     });
12258 
12259     executeCallback(promise, callback);
12260 
12261     return promise;
12262 }
12263 
12264 function setItem(key, value, callback) {
12265     var self = this;
12266 
12267     key = normalizeKey(key);
12268 
12269     var promise = new Promise$1(function (resolve, reject) {
12270         var dbInfo;
12271         self.ready().then(function () {
12272             dbInfo = self._dbInfo;
12273             if (toString.call(value) === '[object Blob]') {
12274                 return _checkBlobSupport(dbInfo.db).then(function (blobSupport) {
12275                     if (blobSupport) {
12276                         return value;
12277                     }
12278                     return _encodeBlob(value);
12279                 });
12280             }
12281             return value;
12282         }).then(function (value) {
12283             createTransaction(self._dbInfo, READ_WRITE, function (err, transaction) {
12284                 if (err) {
12285                     return reject(err);
12286                 }
12287 
12288                 try {
12289                     var store = transaction.objectStore(self._dbInfo.storeName);
12290 
12291                     // The reason we don't _save_ null is because IE 10 does
12292                     // not support saving the `null` type in IndexedDB. How
12293                     // ironic, given the bug below!
12294                     // See: https://github.com/mozilla/localForage/issues/161
12295                     if (value === null) {
12296                         value = undefined;
12297                     }
12298 
12299                     var req = store.put(value, key);
12300 
12301                     transaction.oncomplete = function () {
12302                         // Cast to undefined so the value passed to
12303                         // callback/promise is the same as what one would get out
12304                         // of `getItem()` later. This leads to some weirdness
12305                         // (setItem('foo', undefined) will return `null`), but
12306                         // it's not my fault localStorage is our baseline and that
12307                         // it's weird.
12308                         if (value === undefined) {
12309                             value = null;
12310                         }
12311 
12312                         resolve(value);
12313                     };
12314                     transaction.onabort = transaction.onerror = function () {
12315                         var err = req.error ? req.error : req.transaction.error;
12316                         reject(err);
12317                     };
12318                 } catch (e) {
12319                     reject(e);
12320                 }
12321             });
12322         })["catch"](reject);
12323     });
12324 
12325     executeCallback(promise, callback);
12326     return promise;
12327 }
12328 
12329 function removeItem(key, callback) {
12330     var self = this;
12331 
12332     key = normalizeKey(key);
12333 
12334     var promise = new Promise$1(function (resolve, reject) {
12335         self.ready().then(function () {
12336             createTransaction(self._dbInfo, READ_WRITE, function (err, transaction) {
12337                 if (err) {
12338                     return reject(err);
12339                 }
12340 
12341                 try {
12342                     var store = transaction.objectStore(self._dbInfo.storeName);
12343                     // We use a Grunt task to make this safe for IE and some
12344                     // versions of Android (including those used by Cordova).
12345                     // Normally IE won't like `.delete()` and will insist on
12346                     // using `['delete']()`, but we have a build step that
12347                     // fixes this for us now.
12348                     var req = store["delete"](key);
12349                     transaction.oncomplete = function () {
12350                         resolve();
12351                     };
12352 
12353                     transaction.onerror = function () {
12354                         reject(req.error);
12355                     };
12356 
12357                     // The request will be also be aborted if we've exceeded our storage
12358                     // space.
12359                     transaction.onabort = function () {
12360                         var err = req.error ? req.error : req.transaction.error;
12361                         reject(err);
12362                     };
12363                 } catch (e) {
12364                     reject(e);
12365                 }
12366             });
12367         })["catch"](reject);
12368     });
12369 
12370     executeCallback(promise, callback);
12371     return promise;
12372 }
12373 
12374 function clear(callback) {
12375     var self = this;
12376 
12377     var promise = new Promise$1(function (resolve, reject) {
12378         self.ready().then(function () {
12379             createTransaction(self._dbInfo, READ_WRITE, function (err, transaction) {
12380                 if (err) {
12381                     return reject(err);
12382                 }
12383 
12384                 try {
12385                     var store = transaction.objectStore(self._dbInfo.storeName);
12386                     var req = store.clear();
12387 
12388                     transaction.oncomplete = function () {
12389                         resolve();
12390                     };
12391 
12392                     transaction.onabort = transaction.onerror = function () {
12393                         var err = req.error ? req.error : req.transaction.error;
12394                         reject(err);
12395                     };
12396                 } catch (e) {
12397                     reject(e);
12398                 }
12399             });
12400         })["catch"](reject);
12401     });
12402 
12403     executeCallback(promise, callback);
12404     return promise;
12405 }
12406 
12407 function length(callback) {
12408     var self = this;
12409 
12410     var promise = new Promise$1(function (resolve, reject) {
12411         self.ready().then(function () {
12412             createTransaction(self._dbInfo, READ_ONLY, function (err, transaction) {
12413                 if (err) {
12414                     return reject(err);
12415                 }
12416 
12417                 try {
12418                     var store = transaction.objectStore(self._dbInfo.storeName);
12419                     var req = store.count();
12420 
12421                     req.onsuccess = function () {
12422                         resolve(req.result);
12423                     };
12424 
12425                     req.onerror = function () {
12426                         reject(req.error);
12427                     };
12428                 } catch (e) {
12429                     reject(e);
12430                 }
12431             });
12432         })["catch"](reject);
12433     });
12434 
12435     executeCallback(promise, callback);
12436     return promise;
12437 }
12438 
12439 function key(n, callback) {
12440     var self = this;
12441 
12442     var promise = new Promise$1(function (resolve, reject) {
12443         if (n < 0) {
12444             resolve(null);
12445 
12446             return;
12447         }
12448 
12449         self.ready().then(function () {
12450             createTransaction(self._dbInfo, READ_ONLY, function (err, transaction) {
12451                 if (err) {
12452                     return reject(err);
12453                 }
12454 
12455                 try {
12456                     var store = transaction.objectStore(self._dbInfo.storeName);
12457                     var advanced = false;
12458                     var req = store.openKeyCursor();
12459 
12460                     req.onsuccess = function () {
12461                         var cursor = req.result;
12462                         if (!cursor) {
12463                             // this means there weren't enough keys
12464                             resolve(null);
12465 
12466                             return;
12467                         }
12468 
12469                         if (n === 0) {
12470                             // We have the first key, return it if that's what they
12471                             // wanted.
12472                             resolve(cursor.key);
12473                         } else {
12474                             if (!advanced) {
12475                                 // Otherwise, ask the cursor to skip ahead n
12476                                 // records.
12477                                 advanced = true;
12478                                 cursor.advance(n);
12479                             } else {
12480                                 // When we get here, we've got the nth key.
12481                                 resolve(cursor.key);
12482                             }
12483                         }
12484                     };
12485 
12486                     req.onerror = function () {
12487                         reject(req.error);
12488                     };
12489                 } catch (e) {
12490                     reject(e);
12491                 }
12492             });
12493         })["catch"](reject);
12494     });
12495 
12496     executeCallback(promise, callback);
12497     return promise;
12498 }
12499 
12500 function keys(callback) {
12501     var self = this;
12502 
12503     var promise = new Promise$1(function (resolve, reject) {
12504         self.ready().then(function () {
12505             createTransaction(self._dbInfo, READ_ONLY, function (err, transaction) {
12506                 if (err) {
12507                     return reject(err);
12508                 }
12509 
12510                 try {
12511                     var store = transaction.objectStore(self._dbInfo.storeName);
12512                     var req = store.openKeyCursor();
12513                     var keys = [];
12514 
12515                     req.onsuccess = function () {
12516                         var cursor = req.result;
12517 
12518                         if (!cursor) {
12519                             resolve(keys);
12520                             return;
12521                         }
12522 
12523                         keys.push(cursor.key);
12524                         cursor["continue"]();
12525                     };
12526 
12527                     req.onerror = function () {
12528                         reject(req.error);
12529                     };
12530                 } catch (e) {
12531                     reject(e);
12532                 }
12533             });
12534         })["catch"](reject);
12535     });
12536 
12537     executeCallback(promise, callback);
12538     return promise;
12539 }
12540 
12541 function dropInstance(options, callback) {
12542     callback = getCallback.apply(this, arguments);
12543 
12544     var currentConfig = this.config();
12545     options = typeof options !== 'function' && options || {};
12546     if (!options.name) {
12547         options.name = options.name || currentConfig.name;
12548         options.storeName = options.storeName || currentConfig.storeName;
12549     }
12550 
12551     var self = this;
12552     var promise;
12553     if (!options.name) {
12554         promise = Promise$1.reject('Invalid arguments');
12555     } else {
12556         var isCurrentDb = options.name === currentConfig.name && self._dbInfo.db;
12557 
12558         var dbPromise = isCurrentDb ? Promise$1.resolve(self._dbInfo.db) : _getOriginalConnection(options).then(function (db) {
12559             var dbContext = dbContexts[options.name];
12560             var forages = dbContext.forages;
12561             dbContext.db = db;
12562             for (var i = 0; i < forages.length; i++) {
12563                 forages[i]._dbInfo.db = db;
12564             }
12565             return db;
12566         });
12567 
12568         if (!options.storeName) {
12569             promise = dbPromise.then(function (db) {
12570                 _deferReadiness(options);
12571 
12572                 var dbContext = dbContexts[options.name];
12573                 var forages = dbContext.forages;
12574 
12575                 db.close();
12576                 for (var i = 0; i < forages.length; i++) {
12577                     var forage = forages[i];
12578                     forage._dbInfo.db = null;
12579                 }
12580 
12581                 var dropDBPromise = new Promise$1(function (resolve, reject) {
12582                     var req = idb.deleteDatabase(options.name);
12583 
12584                     req.onerror = function () {
12585                         var db = req.result;
12586                         if (db) {
12587                             db.close();
12588                         }
12589                         reject(req.error);
12590                     };
12591 
12592                     req.onblocked = function () {
12593                         // Closing all open connections in onversionchange handler should prevent this situation, but if
12594                         // we do get here, it just means the request remains pending - eventually it will succeed or error
12595                         console.warn('dropInstance blocked for database "' + options.name + '" until all open connections are closed');
12596                     };
12597 
12598                     req.onsuccess = function () {
12599                         var db = req.result;
12600                         if (db) {
12601                             db.close();
12602                         }
12603                         resolve(db);
12604                     };
12605                 });
12606 
12607                 return dropDBPromise.then(function (db) {
12608                     dbContext.db = db;
12609                     for (var i = 0; i < forages.length; i++) {
12610                         var _forage = forages[i];
12611                         _advanceReadiness(_forage._dbInfo);
12612                     }
12613                 })["catch"](function (err) {
12614                     (_rejectReadiness(options, err) || Promise$1.resolve())["catch"](function () {});
12615                     throw err;
12616                 });
12617             });
12618         } else {
12619             promise = dbPromise.then(function (db) {
12620                 if (!db.objectStoreNames.contains(options.storeName)) {
12621                     return;
12622                 }
12623 
12624                 var newVersion = db.version + 1;
12625 
12626                 _deferReadiness(options);
12627 
12628                 var dbContext = dbContexts[options.name];
12629                 var forages = dbContext.forages;
12630 
12631                 db.close();
12632                 for (var i = 0; i < forages.length; i++) {
12633                     var forage = forages[i];
12634                     forage._dbInfo.db = null;
12635                     forage._dbInfo.version = newVersion;
12636                 }
12637 
12638                 var dropObjectPromise = new Promise$1(function (resolve, reject) {
12639                     var req = idb.open(options.name, newVersion);
12640 
12641                     req.onerror = function (err) {
12642                         var db = req.result;
12643                         db.close();
12644                         reject(err);
12645                     };
12646 
12647                     req.onupgradeneeded = function () {
12648                         var db = req.result;
12649                         db.deleteObjectStore(options.storeName);
12650                     };
12651 
12652                     req.onsuccess = function () {
12653                         var db = req.result;
12654                         db.close();
12655                         resolve(db);
12656                     };
12657                 });
12658 
12659                 return dropObjectPromise.then(function (db) {
12660                     dbContext.db = db;
12661                     for (var j = 0; j < forages.length; j++) {
12662                         var _forage2 = forages[j];
12663                         _forage2._dbInfo.db = db;
12664                         _advanceReadiness(_forage2._dbInfo);
12665                     }
12666                 })["catch"](function (err) {
12667                     (_rejectReadiness(options, err) || Promise$1.resolve())["catch"](function () {});
12668                     throw err;
12669                 });
12670             });
12671         }
12672     }
12673 
12674     executeCallback(promise, callback);
12675     return promise;
12676 }
12677 
12678 var asyncStorage = {
12679     _driver: 'asyncStorage',
12680     _initStorage: _initStorage,
12681     _support: isIndexedDBValid(),
12682     iterate: iterate,
12683     getItem: getItem,
12684     setItem: setItem,
12685     removeItem: removeItem,
12686     clear: clear,
12687     length: length,
12688     key: key,
12689     keys: keys,
12690     dropInstance: dropInstance
12691 };
12692 
12693 function isWebSQLValid() {
12694     return typeof openDatabase === 'function';
12695 }
12696 
12697 // Sadly, the best way to save binary data in WebSQL/localStorage is serializing
12698 // it to Base64, so this is how we store it to prevent very strange errors with less
12699 // verbose ways of binary <-> string data storage.
12700 var BASE_CHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
12701 
12702 var BLOB_TYPE_PREFIX = '~~local_forage_type~';
12703 var BLOB_TYPE_PREFIX_REGEX = /^~~local_forage_type~([^~]+)~/;
12704 
12705 var SERIALIZED_MARKER = '__lfsc__:';
12706 var SERIALIZED_MARKER_LENGTH = SERIALIZED_MARKER.length;
12707 
12708 // OMG the serializations!
12709 var TYPE_ARRAYBUFFER = 'arbf';
12710 var TYPE_BLOB = 'blob';
12711 var TYPE_INT8ARRAY = 'si08';
12712 var TYPE_UINT8ARRAY = 'ui08';
12713 var TYPE_UINT8CLAMPEDARRAY = 'uic8';
12714 var TYPE_INT16ARRAY = 'si16';
12715 var TYPE_INT32ARRAY = 'si32';
12716 var TYPE_UINT16ARRAY = 'ur16';
12717 var TYPE_UINT32ARRAY = 'ui32';
12718 var TYPE_FLOAT32ARRAY = 'fl32';
12719 var TYPE_FLOAT64ARRAY = 'fl64';
12720 var TYPE_SERIALIZED_MARKER_LENGTH = SERIALIZED_MARKER_LENGTH + TYPE_ARRAYBUFFER.length;
12721 
12722 var toString$1 = Object.prototype.toString;
12723 
12724 function stringToBuffer(serializedString) {
12725     // Fill the string into a ArrayBuffer.
12726     var bufferLength = serializedString.length * 0.75;
12727     var len = serializedString.length;
12728     var i;
12729     var p = 0;
12730     var encoded1, encoded2, encoded3, encoded4;
12731 
12732     if (serializedString[serializedString.length - 1] === '=') {
12733         bufferLength--;
12734         if (serializedString[serializedString.length - 2] === '=') {
12735             bufferLength--;
12736         }
12737     }
12738 
12739     var buffer = new ArrayBuffer(bufferLength);
12740     var bytes = new Uint8Array(buffer);
12741 
12742     for (i = 0; i < len; i += 4) {
12743         encoded1 = BASE_CHARS.indexOf(serializedString[i]);
12744         encoded2 = BASE_CHARS.indexOf(serializedString[i + 1]);
12745         encoded3 = BASE_CHARS.indexOf(serializedString[i + 2]);
12746         encoded4 = BASE_CHARS.indexOf(serializedString[i + 3]);
12747 
12748         /*jslint bitwise: true */
12749         bytes[p++] = encoded1 << 2 | encoded2 >> 4;
12750         bytes[p++] = (encoded2 & 15) << 4 | encoded3 >> 2;
12751         bytes[p++] = (encoded3 & 3) << 6 | encoded4 & 63;
12752     }
12753     return buffer;
12754 }
12755 
12756 // Converts a buffer to a string to store, serialized, in the backend
12757 // storage library.
12758 function bufferToString(buffer) {
12759     // base64-arraybuffer
12760     var bytes = new Uint8Array(buffer);
12761     var base64String = '';
12762     var i;
12763 
12764     for (i = 0; i < bytes.length; i += 3) {
12765         /*jslint bitwise: true */
12766         base64String += BASE_CHARS[bytes[i] >> 2];
12767         base64String += BASE_CHARS[(bytes[i] & 3) << 4 | bytes[i + 1] >> 4];
12768         base64String += BASE_CHARS[(bytes[i + 1] & 15) << 2 | bytes[i + 2] >> 6];
12769         base64String += BASE_CHARS[bytes[i + 2] & 63];
12770     }
12771 
12772     if (bytes.length % 3 === 2) {
12773         base64String = base64String.substring(0, base64String.length - 1) + '=';
12774     } else if (bytes.length % 3 === 1) {
12775         base64String = base64String.substring(0, base64String.length - 2) + '==';
12776     }
12777 
12778     return base64String;
12779 }
12780 
12781 // Serialize a value, afterwards executing a callback (which usually
12782 // instructs the `setItem()` callback/promise to be executed). This is how
12783 // we store binary data with localStorage.
12784 function serialize(value, callback) {
12785     var valueType = '';
12786     if (value) {
12787         valueType = toString$1.call(value);
12788     }
12789 
12790     // Cannot use `value instanceof ArrayBuffer` or such here, as these
12791     // checks fail when running the tests using casper.js...
12792     //
12793     // TODO: See why those tests fail and use a better solution.
12794     if (value && (valueType === '[object ArrayBuffer]' || value.buffer && toString$1.call(value.buffer) === '[object ArrayBuffer]')) {
12795         // Convert binary arrays to a string and prefix the string with
12796         // a special marker.
12797         var buffer;
12798         var marker = SERIALIZED_MARKER;
12799 
12800         if (value instanceof ArrayBuffer) {
12801             buffer = value;
12802             marker += TYPE_ARRAYBUFFER;
12803         } else {
12804             buffer = value.buffer;
12805 
12806             if (valueType === '[object Int8Array]') {
12807                 marker += TYPE_INT8ARRAY;
12808             } else if (valueType === '[object Uint8Array]') {
12809                 marker += TYPE_UINT8ARRAY;
12810             } else if (valueType === '[object Uint8ClampedArray]') {
12811                 marker += TYPE_UINT8CLAMPEDARRAY;
12812             } else if (valueType === '[object Int16Array]') {
12813                 marker += TYPE_INT16ARRAY;
12814             } else if (valueType === '[object Uint16Array]') {
12815                 marker += TYPE_UINT16ARRAY;
12816             } else if (valueType === '[object Int32Array]') {
12817                 marker += TYPE_INT32ARRAY;
12818             } else if (valueType === '[object Uint32Array]') {
12819                 marker += TYPE_UINT32ARRAY;
12820             } else if (valueType === '[object Float32Array]') {
12821                 marker += TYPE_FLOAT32ARRAY;
12822             } else if (valueType === '[object Float64Array]') {
12823                 marker += TYPE_FLOAT64ARRAY;
12824             } else {
12825                 callback(new Error('Failed to get type for BinaryArray'));
12826             }
12827         }
12828 
12829         callback(marker + bufferToString(buffer));
12830     } else if (valueType === '[object Blob]') {
12831         // Conver the blob to a binaryArray and then to a string.
12832         var fileReader = new FileReader();
12833 
12834         fileReader.onload = function () {
12835             // Backwards-compatible prefix for the blob type.
12836             var str = BLOB_TYPE_PREFIX + value.type + '~' + bufferToString(this.result);
12837 
12838             callback(SERIALIZED_MARKER + TYPE_BLOB + str);
12839         };
12840 
12841         fileReader.readAsArrayBuffer(value);
12842     } else {
12843         try {
12844             callback(JSON.stringify(value));
12845         } catch (e) {
12846             console.error("Couldn't convert value into a JSON string: ", value);
12847 
12848             callback(null, e);
12849         }
12850     }
12851 }
12852 
12853 // Deserialize data we've inserted into a value column/field. We place
12854 // special markers into our strings to mark them as encoded; this isn't
12855 // as nice as a meta field, but it's the only sane thing we can do whilst
12856 // keeping localStorage support intact.
12857 //
12858 // Oftentimes this will just deserialize JSON content, but if we have a
12859 // special marker (SERIALIZED_MARKER, defined above), we will extract
12860 // some kind of arraybuffer/binary data/typed array out of the string.
12861 function deserialize(value) {
12862     // If we haven't marked this string as being specially serialized (i.e.
12863     // something other than serialized JSON), we can just return it and be
12864     // done with it.
12865     if (value.substring(0, SERIALIZED_MARKER_LENGTH) !== SERIALIZED_MARKER) {
12866         return JSON.parse(value);
12867     }
12868 
12869     // The following code deals with deserializing some kind of Blob or
12870     // TypedArray. First we separate out the type of data we're dealing
12871     // with from the data itself.
12872     var serializedString = value.substring(TYPE_SERIALIZED_MARKER_LENGTH);
12873     var type = value.substring(SERIALIZED_MARKER_LENGTH, TYPE_SERIALIZED_MARKER_LENGTH);
12874 
12875     var blobType;
12876     // Backwards-compatible blob type serialization strategy.
12877     // DBs created with older versions of localForage will simply not have the blob type.
12878     if (type === TYPE_BLOB && BLOB_TYPE_PREFIX_REGEX.test(serializedString)) {
12879         var matcher = serializedString.match(BLOB_TYPE_PREFIX_REGEX);
12880         blobType = matcher[1];
12881         serializedString = serializedString.substring(matcher[0].length);
12882     }
12883     var buffer = stringToBuffer(serializedString);
12884 
12885     // Return the right type based on the code/type set during
12886     // serialization.
12887     switch (type) {
12888         case TYPE_ARRAYBUFFER:
12889             return buffer;
12890         case TYPE_BLOB:
12891             return createBlob([buffer], { type: blobType });
12892         case TYPE_INT8ARRAY:
12893             return new Int8Array(buffer);
12894         case TYPE_UINT8ARRAY:
12895             return new Uint8Array(buffer);
12896         case TYPE_UINT8CLAMPEDARRAY:
12897             return new Uint8ClampedArray(buffer);
12898         case TYPE_INT16ARRAY:
12899             return new Int16Array(buffer);
12900         case TYPE_UINT16ARRAY:
12901             return new Uint16Array(buffer);
12902         case TYPE_INT32ARRAY:
12903             return new Int32Array(buffer);
12904         case TYPE_UINT32ARRAY:
12905             return new Uint32Array(buffer);
12906         case TYPE_FLOAT32ARRAY:
12907             return new Float32Array(buffer);
12908         case TYPE_FLOAT64ARRAY:
12909             return new Float64Array(buffer);
12910         default:
12911             throw new Error('Unkown type: ' + type);
12912     }
12913 }
12914 
12915 var localforageSerializer = {
12916     serialize: serialize,
12917     deserialize: deserialize,
12918     stringToBuffer: stringToBuffer,
12919     bufferToString: bufferToString
12920 };
12921 
12922 /*
12923  * Includes code from:
12924  *
12925  * base64-arraybuffer
12926  * https://github.com/niklasvh/base64-arraybuffer
12927  *
12928  * Copyright (c) 2012 Niklas von Hertzen
12929  * Licensed under the MIT license.
12930  */
12931 
12932 function createDbTable(t, dbInfo, callback, errorCallback) {
12933     t.executeSql('CREATE TABLE IF NOT EXISTS ' + dbInfo.storeName + ' ' + '(id INTEGER PRIMARY KEY, key unique, value)', [], callback, errorCallback);
12934 }
12935 
12936 // Open the WebSQL database (automatically creates one if one didn't
12937 // previously exist), using any options set in the config.
12938 function _initStorage$1(options) {
12939     var self = this;
12940     var dbInfo = {
12941         db: null
12942     };
12943 
12944     if (options) {
12945         for (var i in options) {
12946             dbInfo[i] = typeof options[i] !== 'string' ? options[i].toString() : options[i];
12947         }
12948     }
12949 
12950     var dbInfoPromise = new Promise$1(function (resolve, reject) {
12951         // Open the database; the openDatabase API will automatically
12952         // create it for us if it doesn't exist.
12953         try {
12954             dbInfo.db = openDatabase(dbInfo.name, String(dbInfo.version), dbInfo.description, dbInfo.size);
12955         } catch (e) {
12956             return reject(e);
12957         }
12958 
12959         // Create our key/value table if it doesn't exist.
12960         dbInfo.db.transaction(function (t) {
12961             createDbTable(t, dbInfo, function () {
12962                 self._dbInfo = dbInfo;
12963                 resolve();
12964             }, function (t, error) {
12965                 reject(error);
12966             });
12967         }, reject);
12968     });
12969 
12970     dbInfo.serializer = localforageSerializer;
12971     return dbInfoPromise;
12972 }
12973 
12974 function tryExecuteSql(t, dbInfo, sqlStatement, args, callback, errorCallback) {
12975     t.executeSql(sqlStatement, args, callback, function (t, error) {
12976         if (error.code === error.SYNTAX_ERR) {
12977             t.executeSql('SELECT name FROM sqlite_master ' + "WHERE type='table' AND name = ?", [dbInfo.storeName], function (t, results) {
12978                 if (!results.rows.length) {
12979                     // if the table is missing (was deleted)
12980                     // re-create it table and retry
12981                     createDbTable(t, dbInfo, function () {
12982                         t.executeSql(sqlStatement, args, callback, errorCallback);
12983                     }, errorCallback);
12984                 } else {
12985                     errorCallback(t, error);
12986                 }
12987             }, errorCallback);
12988         } else {
12989             errorCallback(t, error);
12990         }
12991     }, errorCallback);
12992 }
12993 
12994 function getItem$1(key, callback) {
12995     var self = this;
12996 
12997     key = normalizeKey(key);
12998 
12999     var promise = new Promise$1(function (resolve, reject) {
13000         self.ready().then(function () {
13001             var dbInfo = self._dbInfo;
13002             dbInfo.db.transaction(function (t) {
13003                 tryExecuteSql(t, dbInfo, 'SELECT * FROM ' + dbInfo.storeName + ' WHERE key = ? LIMIT 1', [key], function (t, results) {
13004                     var result = results.rows.length ? results.rows.item(0).value : null;
13005 
13006                     // Check to see if this is serialized content we need to
13007                     // unpack.
13008                     if (result) {
13009                         result = dbInfo.serializer.deserialize(result);
13010                     }
13011 
13012                     resolve(result);
13013                 }, function (t, error) {
13014                     reject(error);
13015                 });
13016             });
13017         })["catch"](reject);
13018     });
13019 
13020     executeCallback(promise, callback);
13021     return promise;
13022 }
13023 
13024 function iterate$1(iterator, callback) {
13025     var self = this;
13026 
13027     var promise = new Promise$1(function (resolve, reject) {
13028         self.ready().then(function () {
13029             var dbInfo = self._dbInfo;
13030 
13031             dbInfo.db.transaction(function (t) {
13032                 tryExecuteSql(t, dbInfo, 'SELECT * FROM ' + dbInfo.storeName, [], function (t, results) {
13033                     var rows = results.rows;
13034                     var length = rows.length;
13035 
13036                     for (var i = 0; i < length; i++) {
13037                         var item = rows.item(i);
13038                         var result = item.value;
13039 
13040                         // Check to see if this is serialized content
13041                         // we need to unpack.
13042                         if (result) {
13043                             result = dbInfo.serializer.deserialize(result);
13044                         }
13045 
13046                         result = iterator(result, item.key, i + 1);
13047 
13048                         // void(0) prevents problems with redefinition
13049                         // of `undefined`.
13050                         if (result !== void 0) {
13051                             resolve(result);
13052                             return;
13053                         }
13054                     }
13055 
13056                     resolve();
13057                 }, function (t, error) {
13058                     reject(error);
13059                 });
13060             });
13061         })["catch"](reject);
13062     });
13063 
13064     executeCallback(promise, callback);
13065     return promise;
13066 }
13067 
13068 function _setItem(key, value, callback, retriesLeft) {
13069     var self = this;
13070 
13071     key = normalizeKey(key);
13072 
13073     var promise = new Promise$1(function (resolve, reject) {
13074         self.ready().then(function () {
13075             // The localStorage API doesn't return undefined values in an
13076             // "expected" way, so undefined is always cast to null in all
13077             // drivers. See: https://github.com/mozilla/localForage/pull/42
13078             if (value === undefined) {
13079                 value = null;
13080             }
13081 
13082             // Save the original value to pass to the callback.
13083             var originalValue = value;
13084 
13085             var dbInfo = self._dbInfo;
13086             dbInfo.serializer.serialize(value, function (value, error) {
13087                 if (error) {
13088                     reject(error);
13089                 } else {
13090                     dbInfo.db.transaction(function (t) {
13091                         tryExecuteSql(t, dbInfo, 'INSERT OR REPLACE INTO ' + dbInfo.storeName + ' ' + '(key, value) VALUES (?, ?)', [key, value], function () {
13092                             resolve(originalValue);
13093                         }, function (t, error) {
13094                             reject(error);
13095                         });
13096                     }, function (sqlError) {
13097                         // The transaction failed; check
13098                         // to see if it's a quota error.
13099                         if (sqlError.code === sqlError.QUOTA_ERR) {
13100                             // We reject the callback outright for now, but
13101                             // it's worth trying to re-run the transaction.
13102                             // Even if the user accepts the prompt to use
13103                             // more storage on Safari, this error will
13104                             // be called.
13105                             //
13106                             // Try to re-run the transaction.
13107                             if (retriesLeft > 0) {
13108                                 resolve(_setItem.apply(self, [key, originalValue, callback, retriesLeft - 1]));
13109                                 return;
13110                             }
13111                             reject(sqlError);
13112                         }
13113                     });
13114                 }
13115             });
13116         })["catch"](reject);
13117     });
13118 
13119     executeCallback(promise, callback);
13120     return promise;
13121 }
13122 
13123 function setItem$1(key, value, callback) {
13124     return _setItem.apply(this, [key, value, callback, 1]);
13125 }
13126 
13127 function removeItem$1(key, callback) {
13128     var self = this;
13129 
13130     key = normalizeKey(key);
13131 
13132     var promise = new Promise$1(function (resolve, reject) {
13133         self.ready().then(function () {
13134             var dbInfo = self._dbInfo;
13135             dbInfo.db.transaction(function (t) {
13136                 tryExecuteSql(t, dbInfo, 'DELETE FROM ' + dbInfo.storeName + ' WHERE key = ?', [key], function () {
13137                     resolve();
13138                 }, function (t, error) {
13139                     reject(error);
13140                 });
13141             });
13142         })["catch"](reject);
13143     });
13144 
13145     executeCallback(promise, callback);
13146     return promise;
13147 }
13148 
13149 // Deletes every item in the table.
13150 // TODO: Find out if this resets the AUTO_INCREMENT number.
13151 function clear$1(callback) {
13152     var self = this;
13153 
13154     var promise = new Promise$1(function (resolve, reject) {
13155         self.ready().then(function () {
13156             var dbInfo = self._dbInfo;
13157             dbInfo.db.transaction(function (t) {
13158                 tryExecuteSql(t, dbInfo, 'DELETE FROM ' + dbInfo.storeName, [], function () {
13159                     resolve();
13160                 }, function (t, error) {
13161                     reject(error);
13162                 });
13163             });
13164         })["catch"](reject);
13165     });
13166 
13167     executeCallback(promise, callback);
13168     return promise;
13169 }
13170 
13171 // Does a simple `COUNT(key)` to get the number of items stored in
13172 // localForage.
13173 function length$1(callback) {
13174     var self = this;
13175 
13176     var promise = new Promise$1(function (resolve, reject) {
13177         self.ready().then(function () {
13178             var dbInfo = self._dbInfo;
13179             dbInfo.db.transaction(function (t) {
13180                 // Ahhh, SQL makes this one soooooo easy.
13181                 tryExecuteSql(t, dbInfo, 'SELECT COUNT(key) as c FROM ' + dbInfo.storeName, [], function (t, results) {
13182                     var result = results.rows.item(0).c;
13183                     resolve(result);
13184                 }, function (t, error) {
13185                     reject(error);
13186                 });
13187             });
13188         })["catch"](reject);
13189     });
13190 
13191     executeCallback(promise, callback);
13192     return promise;
13193 }
13194 
13195 // Return the key located at key index X; essentially gets the key from a
13196 // `WHERE id = ?`. This is the most efficient way I can think to implement
13197 // this rarely-used (in my experience) part of the API, but it can seem
13198 // inconsistent, because we do `INSERT OR REPLACE INTO` on `setItem()`, so
13199 // the ID of each key will change every time it's updated. Perhaps a stored
13200 // procedure for the `setItem()` SQL would solve this problem?
13201 // TODO: Don't change ID on `setItem()`.
13202 function key$1(n, callback) {
13203     var self = this;
13204 
13205     var promise = new Promise$1(function (resolve, reject) {
13206         self.ready().then(function () {
13207             var dbInfo = self._dbInfo;
13208             dbInfo.db.transaction(function (t) {
13209                 tryExecuteSql(t, dbInfo, 'SELECT key FROM ' + dbInfo.storeName + ' WHERE id = ? LIMIT 1', [n + 1], function (t, results) {
13210                     var result = results.rows.length ? results.rows.item(0).key : null;
13211                     resolve(result);
13212                 }, function (t, error) {
13213                     reject(error);
13214                 });
13215             });
13216         })["catch"](reject);
13217     });
13218 
13219     executeCallback(promise, callback);
13220     return promise;
13221 }
13222 
13223 function keys$1(callback) {
13224     var self = this;
13225 
13226     var promise = new Promise$1(function (resolve, reject) {
13227         self.ready().then(function () {
13228             var dbInfo = self._dbInfo;
13229             dbInfo.db.transaction(function (t) {
13230                 tryExecuteSql(t, dbInfo, 'SELECT key FROM ' + dbInfo.storeName, [], function (t, results) {
13231                     var keys = [];
13232 
13233                     for (var i = 0; i < results.rows.length; i++) {
13234                         keys.push(results.rows.item(i).key);
13235                     }
13236 
13237                     resolve(keys);
13238                 }, function (t, error) {
13239                     reject(error);
13240                 });
13241             });
13242         })["catch"](reject);
13243     });
13244 
13245     executeCallback(promise, callback);
13246     return promise;
13247 }
13248 
13249 // https://www.w3.org/TR/webdatabase/#databases
13250 // > There is no way to enumerate or delete the databases available for an origin from this API.
13251 function getAllStoreNames(db) {
13252     return new Promise$1(function (resolve, reject) {
13253         db.transaction(function (t) {
13254             t.executeSql('SELECT name FROM sqlite_master ' + "WHERE type='table' AND name <> '__WebKitDatabaseInfoTable__'", [], function (t, results) {
13255                 var storeNames = [];
13256 
13257                 for (var i = 0; i < results.rows.length; i++) {
13258                     storeNames.push(results.rows.item(i).name);
13259                 }
13260 
13261                 resolve({
13262                     db: db,
13263                     storeNames: storeNames
13264                 });
13265             }, function (t, error) {
13266                 reject(error);
13267             });
13268         }, function (sqlError) {
13269             reject(sqlError);
13270         });
13271     });
13272 }
13273 
13274 function dropInstance$1(options, callback) {
13275     callback = getCallback.apply(this, arguments);
13276 
13277     var currentConfig = this.config();
13278     options = typeof options !== 'function' && options || {};
13279     if (!options.name) {
13280         options.name = options.name || currentConfig.name;
13281         options.storeName = options.storeName || currentConfig.storeName;
13282     }
13283 
13284     var self = this;
13285     var promise;
13286     if (!options.name) {
13287         promise = Promise$1.reject('Invalid arguments');
13288     } else {
13289         promise = new Promise$1(function (resolve) {
13290             var db;
13291             if (options.name === currentConfig.name) {
13292                 // use the db reference of the current instance
13293                 db = self._dbInfo.db;
13294             } else {
13295                 db = openDatabase(options.name, '', '', 0);
13296             }
13297 
13298             if (!options.storeName) {
13299                 // drop all database tables
13300                 resolve(getAllStoreNames(db));
13301             } else {
13302                 resolve({
13303                     db: db,
13304                     storeNames: [options.storeName]
13305                 });
13306             }
13307         }).then(function (operationInfo) {
13308             return new Promise$1(function (resolve, reject) {
13309                 operationInfo.db.transaction(function (t) {
13310                     function dropTable(storeName) {
13311                         return new Promise$1(function (resolve, reject) {
13312                             t.executeSql('DROP TABLE IF EXISTS ' + storeName, [], function () {
13313                                 resolve();
13314                             }, function (t, error) {
13315                                 reject(error);
13316                             });
13317                         });
13318                     }
13319 
13320                     var operations = [];
13321                     for (var i = 0, len = operationInfo.storeNames.length; i < len; i++) {
13322                         operations.push(dropTable(operationInfo.storeNames[i]));
13323                     }
13324 
13325                     Promise$1.all(operations).then(function () {
13326                         resolve();
13327                     })["catch"](function (e) {
13328                         reject(e);
13329                     });
13330                 }, function (sqlError) {
13331                     reject(sqlError);
13332                 });
13333             });
13334         });
13335     }
13336 
13337     executeCallback(promise, callback);
13338     return promise;
13339 }
13340 
13341 var webSQLStorage = {
13342     _driver: 'webSQLStorage',
13343     _initStorage: _initStorage$1,
13344     _support: isWebSQLValid(),
13345     iterate: iterate$1,
13346     getItem: getItem$1,
13347     setItem: setItem$1,
13348     removeItem: removeItem$1,
13349     clear: clear$1,
13350     length: length$1,
13351     key: key$1,
13352     keys: keys$1,
13353     dropInstance: dropInstance$1
13354 };
13355 
13356 function isLocalStorageValid() {
13357     try {
13358         return typeof localStorage !== 'undefined' && 'setItem' in localStorage &&
13359         // in IE8 typeof localStorage.setItem === 'object'
13360         !!localStorage.setItem;
13361     } catch (e) {
13362         return false;
13363     }
13364 }
13365 
13366 function _getKeyPrefix(options, defaultConfig) {
13367     var keyPrefix = options.name + '/';
13368 
13369     if (options.storeName !== defaultConfig.storeName) {
13370         keyPrefix += options.storeName + '/';
13371     }
13372     return keyPrefix;
13373 }
13374 
13375 // Check if localStorage throws when saving an item
13376 function checkIfLocalStorageThrows() {
13377     var localStorageTestKey = '_localforage_support_test';
13378 
13379     try {
13380         localStorage.setItem(localStorageTestKey, true);
13381         localStorage.removeItem(localStorageTestKey);
13382 
13383         return false;
13384     } catch (e) {
13385         return true;
13386     }
13387 }
13388 
13389 // Check if localStorage is usable and allows to save an item
13390 // This method checks if localStorage is usable in Safari Private Browsing
13391 // mode, or in any other case where the available quota for localStorage
13392 // is 0 and there wasn't any saved items yet.
13393 function _isLocalStorageUsable() {
13394     return !checkIfLocalStorageThrows() || localStorage.length > 0;
13395 }
13396 
13397 // Config the localStorage backend, using options set in the config.
13398 function _initStorage$2(options) {
13399     var self = this;
13400     var dbInfo = {};
13401     if (options) {
13402         for (var i in options) {
13403             dbInfo[i] = options[i];
13404         }
13405     }
13406 
13407     dbInfo.keyPrefix = _getKeyPrefix(options, self._defaultConfig);
13408 
13409     if (!_isLocalStorageUsable()) {
13410         return Promise$1.reject();
13411     }
13412 
13413     self._dbInfo = dbInfo;
13414     dbInfo.serializer = localforageSerializer;
13415 
13416     return Promise$1.resolve();
13417 }
13418 
13419 // Remove all keys from the datastore, effectively destroying all data in
13420 // the app's key/value store!
13421 function clear$2(callback) {
13422     var self = this;
13423     var promise = self.ready().then(function () {
13424         var keyPrefix = self._dbInfo.keyPrefix;
13425 
13426         for (var i = localStorage.length - 1; i >= 0; i--) {
13427             var key = localStorage.key(i);
13428 
13429             if (key.indexOf(keyPrefix) === 0) {
13430                 localStorage.removeItem(key);
13431             }
13432         }
13433     });
13434 
13435     executeCallback(promise, callback);
13436     return promise;
13437 }
13438 
13439 // Retrieve an item from the store. Unlike the original async_storage
13440 // library in Gaia, we don't modify return values at all. If a key's value
13441 // is `undefined`, we pass that value to the callback function.
13442 function getItem$2(key, callback) {
13443     var self = this;
13444 
13445     key = normalizeKey(key);
13446 
13447     var promise = self.ready().then(function () {
13448         var dbInfo = self._dbInfo;
13449         var result = localStorage.getItem(dbInfo.keyPrefix + key);
13450 
13451         // If a result was found, parse it from the serialized
13452         // string into a JS object. If result isn't truthy, the key
13453         // is likely undefined and we'll pass it straight to the
13454         // callback.
13455         if (result) {
13456             result = dbInfo.serializer.deserialize(result);
13457         }
13458 
13459         return result;
13460     });
13461 
13462     executeCallback(promise, callback);
13463     return promise;
13464 }
13465 
13466 // Iterate over all items in the store.
13467 function iterate$2(iterator, callback) {
13468     var self = this;
13469 
13470     var promise = self.ready().then(function () {
13471         var dbInfo = self._dbInfo;
13472         var keyPrefix = dbInfo.keyPrefix;
13473         var keyPrefixLength = keyPrefix.length;
13474         var length = localStorage.length;
13475 
13476         // We use a dedicated iterator instead of the `i` variable below
13477         // so other keys we fetch in localStorage aren't counted in
13478         // the `iterationNumber` argument passed to the `iterate()`
13479         // callback.
13480         //
13481         // See: github.com/mozilla/localForage/pull/435#discussion_r38061530
13482         var iterationNumber = 1;
13483 
13484         for (var i = 0; i < length; i++) {
13485             var key = localStorage.key(i);
13486             if (key.indexOf(keyPrefix) !== 0) {
13487                 continue;
13488             }
13489             var value = localStorage.getItem(key);
13490 
13491             // If a result was found, parse it from the serialized
13492             // string into a JS object. If result isn't truthy, the
13493             // key is likely undefined and we'll pass it straight
13494             // to the iterator.
13495             if (value) {
13496                 value = dbInfo.serializer.deserialize(value);
13497             }
13498 
13499             value = iterator(value, key.substring(keyPrefixLength), iterationNumber++);
13500 
13501             if (value !== void 0) {
13502                 return value;
13503             }
13504         }
13505     });
13506 
13507     executeCallback(promise, callback);
13508     return promise;
13509 }
13510 
13511 // Same as localStorage's key() method, except takes a callback.
13512 function key$2(n, callback) {
13513     var self = this;
13514     var promise = self.ready().then(function () {
13515         var dbInfo = self._dbInfo;
13516         var result;
13517         try {
13518             result = localStorage.key(n);
13519         } catch (error) {
13520             result = null;
13521         }
13522 
13523         // Remove the prefix from the key, if a key is found.
13524         if (result) {
13525             result = result.substring(dbInfo.keyPrefix.length);
13526         }
13527 
13528         return result;
13529     });
13530 
13531     executeCallback(promise, callback);
13532     return promise;
13533 }
13534 
13535 function keys$2(callback) {
13536     var self = this;
13537     var promise = self.ready().then(function () {
13538         var dbInfo = self._dbInfo;
13539         var length = localStorage.length;
13540         var keys = [];
13541 
13542         for (var i = 0; i < length; i++) {
13543             var itemKey = localStorage.key(i);
13544             if (itemKey.indexOf(dbInfo.keyPrefix) === 0) {
13545                 keys.push(itemKey.substring(dbInfo.keyPrefix.length));
13546             }
13547         }
13548 
13549         return keys;
13550     });
13551 
13552     executeCallback(promise, callback);
13553     return promise;
13554 }
13555 
13556 // Supply the number of keys in the datastore to the callback function.
13557 function length$2(callback) {
13558     var self = this;
13559     var promise = self.keys().then(function (keys) {
13560         return keys.length;
13561     });
13562 
13563     executeCallback(promise, callback);
13564     return promise;
13565 }
13566 
13567 // Remove an item from the store, nice and simple.
13568 function removeItem$2(key, callback) {
13569     var self = this;
13570 
13571     key = normalizeKey(key);
13572 
13573     var promise = self.ready().then(function () {
13574         var dbInfo = self._dbInfo;
13575         localStorage.removeItem(dbInfo.keyPrefix + key);
13576     });
13577 
13578     executeCallback(promise, callback);
13579     return promise;
13580 }
13581 
13582 // Set a key's value and run an optional callback once the value is set.
13583 // Unlike Gaia's implementation, the callback function is passed the value,
13584 // in case you want to operate on that value only after you're sure it
13585 // saved, or something like that.
13586 function setItem$2(key, value, callback) {
13587     var self = this;
13588 
13589     key = normalizeKey(key);
13590 
13591     var promise = self.ready().then(function () {
13592         // Convert undefined values to null.
13593         // https://github.com/mozilla/localForage/pull/42
13594         if (value === undefined) {
13595             value = null;
13596         }
13597 
13598         // Save the original value to pass to the callback.
13599         var originalValue = value;
13600 
13601         return new Promise$1(function (resolve, reject) {
13602             var dbInfo = self._dbInfo;
13603             dbInfo.serializer.serialize(value, function (value, error) {
13604                 if (error) {
13605                     reject(error);
13606                 } else {
13607                     try {
13608                         localStorage.setItem(dbInfo.keyPrefix + key, value);
13609                         resolve(originalValue);
13610                     } catch (e) {
13611                         // localStorage capacity exceeded.
13612                         // TODO: Make this a specific error/event.
13613                         if (e.name === 'QuotaExceededError' || e.name === 'NS_ERROR_DOM_QUOTA_REACHED') {
13614                             reject(e);
13615                         }
13616                         reject(e);
13617                     }
13618                 }
13619             });
13620         });
13621     });
13622 
13623     executeCallback(promise, callback);
13624     return promise;
13625 }
13626 
13627 function dropInstance$2(options, callback) {
13628     callback = getCallback.apply(this, arguments);
13629 
13630     options = typeof options !== 'function' && options || {};
13631     if (!options.name) {
13632         var currentConfig = this.config();
13633         options.name = options.name || currentConfig.name;
13634         options.storeName = options.storeName || currentConfig.storeName;
13635     }
13636 
13637     var self = this;
13638     var promise;
13639     if (!options.name) {
13640         promise = Promise$1.reject('Invalid arguments');
13641     } else {
13642         promise = new Promise$1(function (resolve) {
13643             if (!options.storeName) {
13644                 resolve(options.name + '/');
13645             } else {
13646                 resolve(_getKeyPrefix(options, self._defaultConfig));
13647             }
13648         }).then(function (keyPrefix) {
13649             for (var i = localStorage.length - 1; i >= 0; i--) {
13650                 var key = localStorage.key(i);
13651 
13652                 if (key.indexOf(keyPrefix) === 0) {
13653                     localStorage.removeItem(key);
13654                 }
13655             }
13656         });
13657     }
13658 
13659     executeCallback(promise, callback);
13660     return promise;
13661 }
13662 
13663 var localStorageWrapper = {
13664     _driver: 'localStorageWrapper',
13665     _initStorage: _initStorage$2,
13666     _support: isLocalStorageValid(),
13667     iterate: iterate$2,
13668     getItem: getItem$2,
13669     setItem: setItem$2,
13670     removeItem: removeItem$2,
13671     clear: clear$2,
13672     length: length$2,
13673     key: key$2,
13674     keys: keys$2,
13675     dropInstance: dropInstance$2
13676 };
13677 
13678 var sameValue = function sameValue(x, y) {
13679     return x === y || typeof x === 'number' && typeof y === 'number' && isNaN(x) && isNaN(y);
13680 };
13681 
13682 var includes = function includes(array, searchElement) {
13683     var len = array.length;
13684     var i = 0;
13685     while (i < len) {
13686         if (sameValue(array[i], searchElement)) {
13687             return true;
13688         }
13689         i++;
13690     }
13691 
13692     return false;
13693 };
13694 
13695 var isArray = Array.isArray || function (arg) {
13696     return Object.prototype.toString.call(arg) === '[object Array]';
13697 };
13698 
13699 // Drivers are stored here when `defineDriver()` is called.
13700 // They are shared across all instances of localForage.
13701 var DefinedDrivers = {};
13702 
13703 var DriverSupport = {};
13704 
13705 var DefaultDrivers = {
13706     INDEXEDDB: asyncStorage,
13707     WEBSQL: webSQLStorage,
13708     LOCALSTORAGE: localStorageWrapper
13709 };
13710 
13711 var DefaultDriverOrder = [DefaultDrivers.INDEXEDDB._driver, DefaultDrivers.WEBSQL._driver, DefaultDrivers.LOCALSTORAGE._driver];
13712 
13713 var OptionalDriverMethods = ['dropInstance'];
13714 
13715 var LibraryMethods = ['clear', 'getItem', 'iterate', 'key', 'keys', 'length', 'removeItem', 'setItem'].concat(OptionalDriverMethods);
13716 
13717 var DefaultConfig = {
13718     description: '',
13719     driver: DefaultDriverOrder.slice(),
13720     name: 'localforage',
13721     // Default DB size is _JUST UNDER_ 5MB, as it's the highest size
13722     // we can use without a prompt.
13723     size: 4980736,
13724     storeName: 'keyvaluepairs',
13725     version: 1.0
13726 };
13727 
13728 function callWhenReady(localForageInstance, libraryMethod) {
13729     localForageInstance[libraryMethod] = function () {
13730         var _args = arguments;
13731         return localForageInstance.ready().then(function () {
13732             return localForageInstance[libraryMethod].apply(localForageInstance, _args);
13733         });
13734     };
13735 }
13736 
13737 function extend() {
13738     for (var i = 1; i < arguments.length; i++) {
13739         var arg = arguments[i];
13740 
13741         if (arg) {
13742             for (var _key in arg) {
13743                 if (arg.hasOwnProperty(_key)) {
13744                     if (isArray(arg[_key])) {
13745                         arguments[0][_key] = arg[_key].slice();
13746                     } else {
13747                         arguments[0][_key] = arg[_key];
13748                     }
13749                 }
13750             }
13751         }
13752     }
13753 
13754     return arguments[0];
13755 }
13756 
13757 var LocalForage = function () {
13758     function LocalForage(options) {
13759         _classCallCheck(this, LocalForage);
13760 
13761         for (var driverTypeKey in DefaultDrivers) {
13762             if (DefaultDrivers.hasOwnProperty(driverTypeKey)) {
13763                 var driver = DefaultDrivers[driverTypeKey];
13764                 var driverName = driver._driver;
13765                 this[driverTypeKey] = driverName;
13766 
13767                 if (!DefinedDrivers[driverName]) {
13768                     // we don't need to wait for the promise,
13769                     // since the default drivers can be defined
13770                     // in a blocking manner
13771                     this.defineDriver(driver);
13772                 }
13773             }
13774         }
13775 
13776         this._defaultConfig = extend({}, DefaultConfig);
13777         this._config = extend({}, this._defaultConfig, options);
13778         this._driverSet = null;
13779         this._initDriver = null;
13780         this._ready = false;
13781         this._dbInfo = null;
13782 
13783         this._wrapLibraryMethodsWithReady();
13784         this.setDriver(this._config.driver)["catch"](function () {});
13785     }
13786 
13787     // Set any config values for localForage; can be called anytime before
13788     // the first API call (e.g. `getItem`, `setItem`).
13789     // We loop through options so we don't overwrite existing config
13790     // values.
13791 
13792 
13793     LocalForage.prototype.config = function config(options) {
13794         // If the options argument is an object, we use it to set values.
13795         // Otherwise, we return either a specified config value or all
13796         // config values.
13797         if ((typeof options === 'undefined' ? 'undefined' : _typeof(options)) === 'object') {
13798             // If localforage is ready and fully initialized, we can't set
13799             // any new configuration values. Instead, we return an error.
13800             if (this._ready) {
13801                 return new Error("Can't call config() after localforage " + 'has been used.');
13802             }
13803 
13804             for (var i in options) {
13805                 if (i === 'storeName') {
13806                     options[i] = options[i].replace(/\W/g, '_');
13807                 }
13808 
13809                 if (i === 'version' && typeof options[i] !== 'number') {
13810                     return new Error('Database version must be a number.');
13811                 }
13812 
13813                 this._config[i] = options[i];
13814             }
13815 
13816             // after all config options are set and
13817             // the driver option is used, try setting it
13818             if ('driver' in options && options.driver) {
13819                 return this.setDriver(this._config.driver);
13820             }
13821 
13822             return true;
13823         } else if (typeof options === 'string') {
13824             return this._config[options];
13825         } else {
13826             return this._config;
13827         }
13828     };
13829 
13830     // Used to define a custom driver, shared across all instances of
13831     // localForage.
13832 
13833 
13834     LocalForage.prototype.defineDriver = function defineDriver(driverObject, callback, errorCallback) {
13835         var promise = new Promise$1(function (resolve, reject) {
13836             try {
13837                 var driverName = driverObject._driver;
13838                 var complianceError = new Error('Custom driver not compliant; see ' + 'https://mozilla.github.io/localForage/#definedriver');
13839 
13840                 // A driver name should be defined and not overlap with the
13841                 // library-defined, default drivers.
13842                 if (!driverObject._driver) {
13843                     reject(complianceError);
13844                     return;
13845                 }
13846 
13847                 var driverMethods = LibraryMethods.concat('_initStorage');
13848                 for (var i = 0, len = driverMethods.length; i < len; i++) {
13849                     var driverMethodName = driverMethods[i];
13850 
13851                     // when the property is there,
13852                     // it should be a method even when optional
13853                     var isRequired = !includes(OptionalDriverMethods, driverMethodName);
13854                     if ((isRequired || driverObject[driverMethodName]) && typeof driverObject[driverMethodName] !== 'function') {
13855                         reject(complianceError);
13856                         return;
13857                     }
13858                 }
13859 
13860                 var configureMissingMethods = function configureMissingMethods() {
13861                     var methodNotImplementedFactory = function methodNotImplementedFactory(methodName) {
13862                         return function () {
13863                             var error = new Error('Method ' + methodName + ' is not implemented by the current driver');
13864                             var promise = Promise$1.reject(error);
13865                             executeCallback(promise, arguments[arguments.length - 1]);
13866                             return promise;
13867                         };
13868                     };
13869 
13870                     for (var _i = 0, _len = OptionalDriverMethods.length; _i < _len; _i++) {
13871                         var optionalDriverMethod = OptionalDriverMethods[_i];
13872                         if (!driverObject[optionalDriverMethod]) {
13873                             driverObject[optionalDriverMethod] = methodNotImplementedFactory(optionalDriverMethod);
13874                         }
13875                     }
13876                 };
13877 
13878                 configureMissingMethods();
13879 
13880                 var setDriverSupport = function setDriverSupport(support) {
13881                     if (DefinedDrivers[driverName]) {
13882                         console.info('Redefining LocalForage driver: ' + driverName);
13883                     }
13884                     DefinedDrivers[driverName] = driverObject;
13885                     DriverSupport[driverName] = support;
13886                     // don't use a then, so that we can define
13887                     // drivers that have simple _support methods
13888                     // in a blocking manner
13889                     resolve();
13890                 };
13891 
13892                 if ('_support' in driverObject) {
13893                     if (driverObject._support && typeof driverObject._support === 'function') {
13894                         driverObject._support().then(setDriverSupport, reject);
13895                     } else {
13896                         setDriverSupport(!!driverObject._support);
13897                     }
13898                 } else {
13899                     setDriverSupport(true);
13900                 }
13901             } catch (e) {
13902                 reject(e);
13903             }
13904         });
13905 
13906         executeTwoCallbacks(promise, callback, errorCallback);
13907         return promise;
13908     };
13909 
13910     LocalForage.prototype.driver = function driver() {
13911         return this._driver || null;
13912     };
13913 
13914     LocalForage.prototype.getDriver = function getDriver(driverName, callback, errorCallback) {
13915         var getDriverPromise = DefinedDrivers[driverName] ? Promise$1.resolve(DefinedDrivers[driverName]) : Promise$1.reject(new Error('Driver not found.'));
13916 
13917         executeTwoCallbacks(getDriverPromise, callback, errorCallback);
13918         return getDriverPromise;
13919     };
13920 
13921     LocalForage.prototype.getSerializer = function getSerializer(callback) {
13922         var serializerPromise = Promise$1.resolve(localforageSerializer);
13923         executeTwoCallbacks(serializerPromise, callback);
13924         return serializerPromise;
13925     };
13926 
13927     LocalForage.prototype.ready = function ready(callback) {
13928         var self = this;
13929 
13930         var promise = self._driverSet.then(function () {
13931             if (self._ready === null) {
13932                 self._ready = self._initDriver();
13933             }
13934 
13935             return self._ready;
13936         });
13937 
13938         executeTwoCallbacks(promise, callback, callback);
13939         return promise;
13940     };
13941 
13942     LocalForage.prototype.setDriver = function setDriver(drivers, callback, errorCallback) {
13943         var self = this;
13944 
13945         if (!isArray(drivers)) {
13946             drivers = [drivers];
13947         }
13948 
13949         var supportedDrivers = this._getSupportedDrivers(drivers);
13950 
13951         function setDriverToConfig() {
13952             self._config.driver = self.driver();
13953         }
13954 
13955         function extendSelfWithDriver(driver) {
13956             self._extend(driver);
13957             setDriverToConfig();
13958 
13959             self._ready = self._initStorage(self._config);
13960             return self._ready;
13961         }
13962 
13963         function initDriver(supportedDrivers) {
13964             return function () {
13965                 var currentDriverIndex = 0;
13966 
13967                 function driverPromiseLoop() {
13968                     while (currentDriverIndex < supportedDrivers.length) {
13969                         var driverName = supportedDrivers[currentDriverIndex];
13970                         currentDriverIndex++;
13971 
13972                         self._dbInfo = null;
13973                         self._ready = null;
13974 
13975                         return self.getDriver(driverName).then(extendSelfWithDriver)["catch"](driverPromiseLoop);
13976                     }
13977 
13978                     setDriverToConfig();
13979                     var error = new Error('No available storage method found.');
13980                     self._driverSet = Promise$1.reject(error);
13981                     return self._driverSet;
13982                 }
13983 
13984                 return driverPromiseLoop();
13985             };
13986         }
13987 
13988         // There might be a driver initialization in progress
13989         // so wait for it to finish in order to avoid a possible
13990         // race condition to set _dbInfo
13991         var oldDriverSetDone = this._driverSet !== null ? this._driverSet["catch"](function () {
13992             return Promise$1.resolve();
13993         }) : Promise$1.resolve();
13994 
13995         this._driverSet = oldDriverSetDone.then(function () {
13996             var driverName = supportedDrivers[0];
13997             self._dbInfo = null;
13998             self._ready = null;
13999 
14000             return self.getDriver(driverName).then(function (driver) {
14001                 self._driver = driver._driver;
14002                 setDriverToConfig();
14003                 self._wrapLibraryMethodsWithReady();
14004                 self._initDriver = initDriver(supportedDrivers);
14005             });
14006         })["catch"](function () {
14007             setDriverToConfig();
14008             var error = new Error('No available storage method found.');
14009             self._driverSet = Promise$1.reject(error);
14010             return self._driverSet;
14011         });
14012 
14013         executeTwoCallbacks(this._driverSet, callback, errorCallback);
14014         return this._driverSet;
14015     };
14016 
14017     LocalForage.prototype.supports = function supports(driverName) {
14018         return !!DriverSupport[driverName];
14019     };
14020 
14021     LocalForage.prototype._extend = function _extend(libraryMethodsAndProperties) {
14022         extend(this, libraryMethodsAndProperties);
14023     };
14024 
14025     LocalForage.prototype._getSupportedDrivers = function _getSupportedDrivers(drivers) {
14026         var supportedDrivers = [];
14027         for (var i = 0, len = drivers.length; i < len; i++) {
14028             var driverName = drivers[i];
14029             if (this.supports(driverName)) {
14030                 supportedDrivers.push(driverName);
14031             }
14032         }
14033         return supportedDrivers;
14034     };
14035 
14036     LocalForage.prototype._wrapLibraryMethodsWithReady = function _wrapLibraryMethodsWithReady() {
14037         // Add a stub for each driver API method that delays the call to the
14038         // corresponding driver method until localForage is ready. These stubs
14039         // will be replaced by the driver methods as soon as the driver is
14040         // loaded, so there is no performance impact.
14041         for (var i = 0, len = LibraryMethods.length; i < len; i++) {
14042             callWhenReady(this, LibraryMethods[i]);
14043         }
14044     };
14045 
14046     LocalForage.prototype.createInstance = function createInstance(options) {
14047         return new LocalForage(options);
14048     };
14049 
14050     return LocalForage;
14051 }();
14052 
14053 // The actual localForage object that we expose as a module or via a
14054 // global. It's extended by pulling in one of our other libraries.
14055 
14056 
14057 var localforage_js = new LocalForage();
14058 
14059 module.exports = localforage_js;
14060 
14061 },{"3":3}]},{},[4])(4)
14062 });
14063 
14064 /* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(17)))
14065 
14066 /***/ }),
14067 /* 24 */
14068 /***/ (function(module, __webpack_exports__, __webpack_require__) {
14069 
14070 "use strict";
14071 
14072 // EXTERNAL MODULE: ./node_modules/event-emitter/index.js
14073 var event_emitter = __webpack_require__(3);
14074 var event_emitter_default = /*#__PURE__*/__webpack_require__.n(event_emitter);
14075 
14076 // EXTERNAL MODULE: ./src/utils/core.js
14077 var core = __webpack_require__(0);
14078 
14079 // EXTERNAL MODULE: ./src/utils/url.js
14080 var utils_url = __webpack_require__(5);
14081 
14082 // EXTERNAL MODULE: ./src/utils/path.js
14083 var utils_path = __webpack_require__(4);
14084 
14085 // EXTERNAL MODULE: ./src/epubcfi.js
14086 var epubcfi = __webpack_require__(2);
14087 
14088 // EXTERNAL MODULE: ./src/utils/hook.js
14089 var hook = __webpack_require__(6);
14090 
14091 // EXTERNAL MODULE: ./src/utils/replacements.js
14092 var replacements = __webpack_require__(8);
14093 
14094 // CONCATENATED MODULE: ./src/utils/request.js
14095 
14096 
14097 
14098 function request_request(url, type, withCredentials, headers) {
14099   var supportsURL = typeof window != "undefined" ? window.URL : false; // TODO: fallback for url if window isn't defined
14100 
14101   var BLOB_RESPONSE = supportsURL ? "blob" : "arraybuffer";
14102   var deferred = new core["defer"]();
14103   var xhr = new XMLHttpRequest(); //-- Check from PDF.js:
14104   //   https://github.com/mozilla/pdf.js/blob/master/web/compatibility.js
14105 
14106   var xhrPrototype = XMLHttpRequest.prototype;
14107   var header;
14108 
14109   if (!("overrideMimeType" in xhrPrototype)) {
14110     // IE10 might have response, but not overrideMimeType
14111     Object.defineProperty(xhrPrototype, "overrideMimeType", {
14112       value: function xmlHttpRequestOverrideMimeType() {}
14113     });
14114   }
14115 
14116   if (withCredentials) {
14117     xhr.withCredentials = true;
14118   }
14119 
14120   xhr.onreadystatechange = handler;
14121   xhr.onerror = err;
14122   xhr.open("GET", url, true);
14123 
14124   for (header in headers) {
14125     xhr.setRequestHeader(header, headers[header]);
14126   }
14127 
14128   if (type == "json") {
14129     xhr.setRequestHeader("Accept", "application/json");
14130   } // If type isn"t set, determine it from the file extension
14131 
14132 
14133   if (!type) {
14134     type = new utils_path["a" /* default */](url).extension;
14135   }
14136 
14137   if (type == "blob") {
14138     xhr.responseType = BLOB_RESPONSE;
14139   }
14140 
14141   if (Object(core["isXml"])(type)) {
14142     // xhr.responseType = "document";
14143     xhr.overrideMimeType("text/xml"); // for OPF parsing
14144   }
14145 
14146   if (type == "xhtml") {// xhr.responseType = "document";
14147   }
14148 
14149   if (type == "html" || type == "htm") {// xhr.responseType = "document";
14150   }
14151 
14152   if (type == "binary") {
14153     xhr.responseType = "arraybuffer";
14154   }
14155 
14156   xhr.send();
14157 
14158   function err(e) {
14159     deferred.reject(e);
14160   }
14161 
14162   function handler() {
14163     if (this.readyState === XMLHttpRequest.DONE) {
14164       var responseXML = false;
14165 
14166       if (this.responseType === "" || this.responseType === "document") {
14167         responseXML = this.responseXML;
14168       }
14169 
14170       if (this.status === 200 || this.status === 0 || responseXML) {
14171         //-- Firefox is reporting 0 for blob urls
14172         var r;
14173 
14174         if (!this.response && !responseXML) {
14175           deferred.reject({
14176             status: this.status,
14177             message: "Empty Response",
14178             stack: new Error().stack
14179           });
14180           return deferred.promise;
14181         }
14182 
14183         if (this.status === 403) {
14184           deferred.reject({
14185             status: this.status,
14186             response: this.response,
14187             message: "Forbidden",
14188             stack: new Error().stack
14189           });
14190           return deferred.promise;
14191         }
14192 
14193         if (responseXML) {
14194           r = this.responseXML;
14195         } else if (Object(core["isXml"])(type)) {
14196           // xhr.overrideMimeType("text/xml"); // for OPF parsing
14197           // If this.responseXML wasn't set, try to parse using a DOMParser from text
14198           r = Object(core["parse"])(this.response, "text/xml");
14199         } else if (type == "xhtml") {
14200           r = Object(core["parse"])(this.response, "application/xhtml+xml");
14201         } else if (type == "html" || type == "htm") {
14202           r = Object(core["parse"])(this.response, "text/html");
14203         } else if (type == "json") {
14204           r = JSON.parse(this.response);
14205         } else if (type == "blob") {
14206           if (supportsURL) {
14207             r = this.response;
14208           } else {
14209             //-- Safari doesn't support responseType blob, so create a blob from arraybuffer
14210             r = new Blob([this.response]);
14211           }
14212         } else {
14213           r = this.response;
14214         }
14215 
14216         deferred.resolve(r);
14217       } else {
14218         deferred.reject({
14219           status: this.status,
14220           message: this.response,
14221           stack: new Error().stack
14222         });
14223       }
14224     }
14225   }
14226 
14227   return deferred.promise;
14228 }
14229 
14230 /* harmony default export */ var utils_request = (request_request);
14231 // EXTERNAL MODULE: ./node_modules/@xmldom/xmldom/lib/index.js
14232 var lib = __webpack_require__(15);
14233 
14234 // CONCATENATED MODULE: ./src/section.js
14235 
14236 
14237 
14238 
14239 
14240 
14241 
14242 /**
14243  * Represents a Section of the Book
14244  *
14245  * In most books this is equivalent to a Chapter
14246  * @param {object} item  The spine item representing the section
14247  * @param {object} hooks hooks for serialize and content
14248  */
14249 
14250 class section_Section {
14251   constructor(item, hooks) {
14252     this.idref = item.idref;
14253     this.linear = item.linear === "yes";
14254     this.properties = item.properties;
14255     this.index = item.index;
14256     this.href = item.href;
14257     this.url = item.url;
14258     this.canonical = item.canonical;
14259     this.next = item.next;
14260     this.prev = item.prev;
14261     this.cfiBase = item.cfiBase;
14262 
14263     if (hooks) {
14264       this.hooks = hooks;
14265     } else {
14266       this.hooks = {};
14267       this.hooks.serialize = new hook["a" /* default */](this);
14268       this.hooks.content = new hook["a" /* default */](this);
14269     }
14270 
14271     this.document = undefined;
14272     this.contents = undefined;
14273     this.output = undefined;
14274   }
14275   /**
14276    * Load the section from its url
14277    * @param  {method} [_request] a request method to use for loading
14278    * @return {document} a promise with the xml document
14279    */
14280 
14281 
14282   load(_request) {
14283     var request = _request || this.request || utils_request;
14284     var loading = new core["defer"]();
14285     var loaded = loading.promise;
14286 
14287     if (this.contents) {
14288       loading.resolve(this.contents);
14289     } else {
14290       request(this.url).then(function (xml) {
14291         // var directory = new Url(this.url).directory;
14292         this.document = xml;
14293         this.contents = xml.documentElement;
14294         return this.hooks.content.trigger(this.document, this);
14295       }.bind(this)).then(function () {
14296         loading.resolve(this.contents);
14297       }.bind(this)).catch(function (error) {
14298         loading.reject(error);
14299       });
14300     }
14301 
14302     return loaded;
14303   }
14304   /**
14305    * Adds a base tag for resolving urls in the section
14306    * @private
14307    */
14308 
14309 
14310   base() {
14311     return Object(replacements["a" /* replaceBase */])(this.document, this);
14312   }
14313   /**
14314    * Render the contents of a section
14315    * @param  {method} [_request] a request method to use for loading
14316    * @return {string} output a serialized XML Document
14317    */
14318 
14319 
14320   render(_request) {
14321     var rendering = new core["defer"]();
14322     var rendered = rendering.promise;
14323     this.output; // TODO: better way to return this from hooks?
14324 
14325     this.load(_request).then(function (contents) {
14326       var userAgent = typeof navigator !== 'undefined' && navigator.userAgent || '';
14327       var isIE = userAgent.indexOf('Trident') >= 0;
14328       var Serializer;
14329 
14330       if (typeof XMLSerializer === "undefined" || isIE) {
14331         Serializer = lib["DOMParser"];
14332       } else {
14333         Serializer = XMLSerializer;
14334       }
14335 
14336       var serializer = new Serializer();
14337       this.output = serializer.serializeToString(contents);
14338       return this.output;
14339     }.bind(this)).then(function () {
14340       return this.hooks.serialize.trigger(this.output, this);
14341     }.bind(this)).then(function () {
14342       rendering.resolve(this.output);
14343     }.bind(this)).catch(function (error) {
14344       rendering.reject(error);
14345     });
14346     return rendered;
14347   }
14348   /**
14349    * Find a string in a section
14350    * @param  {string} _query The query string to find
14351    * @return {object[]} A list of matches, with form {cfi, excerpt}
14352    */
14353 
14354 
14355   find(_query) {
14356     var section = this;
14357     var matches = [];
14358 
14359     var query = _query.toLowerCase();
14360 
14361     var find = function (node) {
14362       var text = node.textContent.toLowerCase();
14363       var range = section.document.createRange();
14364       var cfi;
14365       var pos;
14366       var last = -1;
14367       var excerpt;
14368       var limit = 150;
14369 
14370       while (pos != -1) {
14371         // Search for the query
14372         pos = text.indexOf(query, last + 1);
14373 
14374         if (pos != -1) {
14375           // We found it! Generate a CFI
14376           range = section.document.createRange();
14377           range.setStart(node, pos);
14378           range.setEnd(node, pos + query.length);
14379           cfi = section.cfiFromRange(range); // Generate the excerpt
14380 
14381           if (node.textContent.length < limit) {
14382             excerpt = node.textContent;
14383           } else {
14384             excerpt = node.textContent.substring(pos - limit / 2, pos + limit / 2);
14385             excerpt = "..." + excerpt + "...";
14386           } // Add the CFI to the matches list
14387 
14388 
14389           matches.push({
14390             cfi: cfi,
14391             excerpt: excerpt
14392           });
14393         }
14394 
14395         last = pos;
14396       }
14397     };
14398 
14399     Object(core["sprint"])(section.document, function (node) {
14400       find(node);
14401     });
14402     return matches;
14403   }
14404 
14405   /**
14406    * Search a string in multiple sequential Element of the section. If the document.createTreeWalker api is missed(eg: IE8), use `find` as a fallback.
14407    * @param  {string} _query The query string to search
14408    * @param  {int} maxSeqEle The maximum number of Element that are combined for search, default value is 5.
14409    * @return {object[]} A list of matches, with form {cfi, excerpt}
14410    */
14411   search(_query, maxSeqEle = 5) {
14412     if (typeof document.createTreeWalker == "undefined") {
14413       return this.find(_query);
14414     }
14415 
14416     let matches = [];
14417     const excerptLimit = 150;
14418     const section = this;
14419 
14420     const query = _query.toLowerCase();
14421 
14422     const search = function (nodeList) {
14423       const textWithCase = nodeList.reduce((acc, current) => {
14424         return acc + current.textContent;
14425       }, "");
14426       const text = textWithCase.toLowerCase();
14427       const pos = text.indexOf(query);
14428 
14429       if (pos != -1) {
14430         const startNodeIndex = 0,
14431               endPos = pos + query.length;
14432         let endNodeIndex = 0,
14433             l = 0;
14434 
14435         if (pos < nodeList[startNodeIndex].length) {
14436           let cfi;
14437 
14438           while (endNodeIndex < nodeList.length - 1) {
14439             l += nodeList[endNodeIndex].length;
14440 
14441             if (endPos <= l) {
14442               break;
14443             }
14444 
14445             endNodeIndex += 1;
14446           }
14447 
14448           let startNode = nodeList[startNodeIndex],
14449               endNode = nodeList[endNodeIndex];
14450           let range = section.document.createRange();
14451           range.setStart(startNode, pos);
14452           let beforeEndLengthCount = nodeList.slice(0, endNodeIndex).reduce((acc, current) => {
14453             return acc + current.textContent.length;
14454           }, 0);
14455           range.setEnd(endNode, beforeEndLengthCount > endPos ? endPos : endPos - beforeEndLengthCount);
14456           cfi = section.cfiFromRange(range);
14457           let excerpt = nodeList.slice(0, endNodeIndex + 1).reduce((acc, current) => {
14458             return acc + current.textContent;
14459           }, "");
14460 
14461           if (excerpt.length > excerptLimit) {
14462             excerpt = excerpt.substring(pos - excerptLimit / 2, pos + excerptLimit / 2);
14463             excerpt = "..." + excerpt + "...";
14464           }
14465 
14466           matches.push({
14467             cfi: cfi,
14468             excerpt: excerpt
14469           });
14470         }
14471       }
14472     };
14473 
14474     const treeWalker = document.createTreeWalker(section.document, NodeFilter.SHOW_TEXT, null, false);
14475     let node,
14476         nodeList = [];
14477 
14478     while (node = treeWalker.nextNode()) {
14479       nodeList.push(node);
14480 
14481       if (nodeList.length == maxSeqEle) {
14482         search(nodeList.slice(0, maxSeqEle));
14483         nodeList = nodeList.slice(1, maxSeqEle);
14484       }
14485     }
14486 
14487     if (nodeList.length > 0) {
14488       search(nodeList);
14489     }
14490 
14491     return matches;
14492   }
14493   /**
14494   * Reconciles the current chapters layout properties with
14495   * the global layout properties.
14496   * @param {object} globalLayout  The global layout settings object, chapter properties string
14497   * @return {object} layoutProperties Object with layout properties
14498   */
14499 
14500 
14501   reconcileLayoutSettings(globalLayout) {
14502     //-- Get the global defaults
14503     var settings = {
14504       layout: globalLayout.layout,
14505       spread: globalLayout.spread,
14506       orientation: globalLayout.orientation
14507     }; //-- Get the chapter's display type
14508 
14509     this.properties.forEach(function (prop) {
14510       var rendition = prop.replace("rendition:", "");
14511       var split = rendition.indexOf("-");
14512       var property, value;
14513 
14514       if (split != -1) {
14515         property = rendition.slice(0, split);
14516         value = rendition.slice(split + 1);
14517         settings[property] = value;
14518       }
14519     });
14520     return settings;
14521   }
14522   /**
14523    * Get a CFI from a Range in the Section
14524    * @param  {range} _range
14525    * @return {string} cfi an EpubCFI string
14526    */
14527 
14528 
14529   cfiFromRange(_range) {
14530     return new epubcfi["a" /* default */](_range, this.cfiBase).toString();
14531   }
14532   /**
14533    * Get a CFI from an Element in the Section
14534    * @param  {element} el
14535    * @return {string} cfi an EpubCFI string
14536    */
14537 
14538 
14539   cfiFromElement(el) {
14540     return new epubcfi["a" /* default */](el, this.cfiBase).toString();
14541   }
14542   /**
14543    * Unload the section document
14544    */
14545 
14546 
14547   unload() {
14548     this.document = undefined;
14549     this.contents = undefined;
14550     this.output = undefined;
14551   }
14552 
14553   destroy() {
14554     this.unload();
14555     this.hooks.serialize.clear();
14556     this.hooks.content.clear();
14557     this.hooks = undefined;
14558     this.idref = undefined;
14559     this.linear = undefined;
14560     this.properties = undefined;
14561     this.index = undefined;
14562     this.href = undefined;
14563     this.url = undefined;
14564     this.next = undefined;
14565     this.prev = undefined;
14566     this.cfiBase = undefined;
14567   }
14568 
14569 }
14570 
14571 /* harmony default export */ var src_section = (section_Section);
14572 // CONCATENATED MODULE: ./src/spine.js
14573 
14574 
14575 
14576 
14577 /**
14578  * A collection of Spine Items
14579  */
14580 
14581 class spine_Spine {
14582   constructor() {
14583     this.spineItems = [];
14584     this.spineByHref = {};
14585     this.spineById = {};
14586     this.hooks = {};
14587     this.hooks.serialize = new hook["a" /* default */]();
14588     this.hooks.content = new hook["a" /* default */](); // Register replacements
14589 
14590     this.hooks.content.register(replacements["a" /* replaceBase */]);
14591     this.hooks.content.register(replacements["b" /* replaceCanonical */]);
14592     this.hooks.content.register(replacements["d" /* replaceMeta */]);
14593     this.epubcfi = new epubcfi["a" /* default */]();
14594     this.loaded = false;
14595     this.items = undefined;
14596     this.manifest = undefined;
14597     this.spineNodeIndex = undefined;
14598     this.baseUrl = undefined;
14599     this.length = undefined;
14600   }
14601   /**
14602    * Unpack items from a opf into spine items
14603    * @param  {Packaging} _package
14604    * @param  {method} resolver URL resolver
14605    * @param  {method} canonical Resolve canonical url
14606    */
14607 
14608 
14609   unpack(_package, resolver, canonical) {
14610     this.items = _package.spine;
14611     this.manifest = _package.manifest;
14612     this.spineNodeIndex = _package.spineNodeIndex;
14613     this.baseUrl = _package.baseUrl || _package.basePath || "";
14614     this.length = this.items.length;
14615     this.items.forEach((item, index) => {
14616       var manifestItem = this.manifest[item.idref];
14617       var spineItem;
14618       item.index = index;
14619       item.cfiBase = this.epubcfi.generateChapterComponent(this.spineNodeIndex, item.index, item.id);
14620 
14621       if (item.href) {
14622         item.url = resolver(item.href, true);
14623         item.canonical = canonical(item.href);
14624       }
14625 
14626       if (manifestItem) {
14627         item.href = manifestItem.href;
14628         item.url = resolver(item.href, true);
14629         item.canonical = canonical(item.href);
14630 
14631         if (manifestItem.properties.length) {
14632           item.properties.push.apply(item.properties, manifestItem.properties);
14633         }
14634       }
14635 
14636       if (item.linear === "yes") {
14637         item.prev = function () {
14638           let prevIndex = item.index;
14639 
14640           while (prevIndex > 0) {
14641             let prev = this.get(prevIndex - 1);
14642 
14643             if (prev && prev.linear) {
14644               return prev;
14645             }
14646 
14647             prevIndex -= 1;
14648           }
14649 
14650           return;
14651         }.bind(this);
14652 
14653         item.next = function () {
14654           let nextIndex = item.index;
14655 
14656           while (nextIndex < this.spineItems.length - 1) {
14657             let next = this.get(nextIndex + 1);
14658 
14659             if (next && next.linear) {
14660               return next;
14661             }
14662 
14663             nextIndex += 1;
14664           }
14665 
14666           return;
14667         }.bind(this);
14668       } else {
14669         item.prev = function () {
14670           return;
14671         };
14672 
14673         item.next = function () {
14674           return;
14675         };
14676       }
14677 
14678       spineItem = new src_section(item, this.hooks);
14679       this.append(spineItem);
14680     });
14681     this.loaded = true;
14682   }
14683   /**
14684    * Get an item from the spine
14685    * @param  {string|number} [target]
14686    * @return {Section} section
14687    * @example spine.get();
14688    * @example spine.get(1);
14689    * @example spine.get("chap1.html");
14690    * @example spine.get("#id1234");
14691    */
14692 
14693 
14694   get(target) {
14695     var index = 0;
14696 
14697     if (typeof target === "undefined") {
14698       while (index < this.spineItems.length) {
14699         let next = this.spineItems[index];
14700 
14701         if (next && next.linear) {
14702           break;
14703         }
14704 
14705         index += 1;
14706       }
14707     } else if (this.epubcfi.isCfiString(target)) {
14708       let cfi = new epubcfi["a" /* default */](target);
14709       index = cfi.spinePos;
14710     } else if (typeof target === "number" || isNaN(target) === false) {
14711       index = target;
14712     } else if (typeof target === "string" && target.indexOf("#") === 0) {
14713       index = this.spineById[target.substring(1)];
14714     } else if (typeof target === "string") {
14715       // Remove fragments
14716       target = target.split("#")[0];
14717       index = this.spineByHref[target] || this.spineByHref[encodeURI(target)];
14718     }
14719 
14720     return this.spineItems[index] || null;
14721   }
14722   /**
14723    * Append a Section to the Spine
14724    * @private
14725    * @param  {Section} section
14726    */
14727 
14728 
14729   append(section) {
14730     var index = this.spineItems.length;
14731     section.index = index;
14732     this.spineItems.push(section); // Encode and Decode href lookups
14733     // see pr for details: https://github.com/futurepress/epub.js/pull/358
14734 
14735     this.spineByHref[decodeURI(section.href)] = index;
14736     this.spineByHref[encodeURI(section.href)] = index;
14737     this.spineByHref[section.href] = index;
14738     this.spineById[section.idref] = index;
14739     return index;
14740   }
14741   /**
14742    * Prepend a Section to the Spine
14743    * @private
14744    * @param  {Section} section
14745    */
14746 
14747 
14748   prepend(section) {
14749     // var index = this.spineItems.unshift(section);
14750     this.spineByHref[section.href] = 0;
14751     this.spineById[section.idref] = 0; // Re-index
14752 
14753     this.spineItems.forEach(function (item, index) {
14754       item.index = index;
14755     });
14756     return 0;
14757   } // insert(section, index) {
14758   //
14759   // };
14760 
14761   /**
14762    * Remove a Section from the Spine
14763    * @private
14764    * @param  {Section} section
14765    */
14766 
14767 
14768   remove(section) {
14769     var index = this.spineItems.indexOf(section);
14770 
14771     if (index > -1) {
14772       delete this.spineByHref[section.href];
14773       delete this.spineById[section.idref];
14774       return this.spineItems.splice(index, 1);
14775     }
14776   }
14777   /**
14778    * Loop over the Sections in the Spine
14779    * @return {method} forEach
14780    */
14781 
14782 
14783   each() {
14784     return this.spineItems.forEach.apply(this.spineItems, arguments);
14785   }
14786   /**
14787    * Find the first Section in the Spine
14788    * @return {Section} first section
14789    */
14790 
14791 
14792   first() {
14793     let index = 0;
14794 
14795     do {
14796       let next = this.get(index);
14797 
14798       if (next && next.linear) {
14799         return next;
14800       }
14801 
14802       index += 1;
14803     } while (index < this.spineItems.length);
14804   }
14805   /**
14806    * Find the last Section in the Spine
14807    * @return {Section} last section
14808    */
14809 
14810 
14811   last() {
14812     let index = this.spineItems.length - 1;
14813 
14814     do {
14815       let prev = this.get(index);
14816 
14817       if (prev && prev.linear) {
14818         return prev;
14819       }
14820 
14821       index -= 1;
14822     } while (index >= 0);
14823   }
14824 
14825   destroy() {
14826     this.each(section => section.destroy());
14827     this.spineItems = undefined;
14828     this.spineByHref = undefined;
14829     this.spineById = undefined;
14830     this.hooks.serialize.clear();
14831     this.hooks.content.clear();
14832     this.hooks = undefined;
14833     this.epubcfi = undefined;
14834     this.loaded = false;
14835     this.items = undefined;
14836     this.manifest = undefined;
14837     this.spineNodeIndex = undefined;
14838     this.baseUrl = undefined;
14839     this.length = undefined;
14840   }
14841 
14842 }
14843 
14844 /* harmony default export */ var src_spine = (spine_Spine);
14845 // EXTERNAL MODULE: ./src/utils/queue.js
14846 var queue = __webpack_require__(9);
14847 
14848 // EXTERNAL MODULE: ./src/utils/constants.js
14849 var constants = __webpack_require__(1);
14850 
14851 // CONCATENATED MODULE: ./src/locations.js
14852 
14853 
14854 
14855 
14856 
14857 /**
14858  * Find Locations for a Book
14859  * @param {Spine} spine
14860  * @param {request} request
14861  * @param {number} [pause=100]
14862  */
14863 
14864 class locations_Locations {
14865   constructor(spine, request, pause) {
14866     this.spine = spine;
14867     this.request = request;
14868     this.pause = pause || 100;
14869     this.q = new queue["a" /* default */](this);
14870     this.epubcfi = new epubcfi["a" /* default */]();
14871     this._locations = [];
14872     this._locationsWords = [];
14873     this.total = 0;
14874     this.break = 150;
14875     this._current = 0;
14876     this._wordCounter = 0;
14877     this.currentLocation = '';
14878     this._currentCfi = '';
14879     this.processingTimeout = undefined;
14880   }
14881   /**
14882    * Load all of sections in the book to generate locations
14883    * @param  {int} chars how many chars to split on
14884    * @return {Promise<Array<string>>} locations
14885    */
14886 
14887 
14888   generate(chars) {
14889     if (chars) {
14890       this.break = chars;
14891     }
14892 
14893     this.q.pause();
14894     this.spine.each(function (section) {
14895       if (section.linear) {
14896         this.q.enqueue(this.process.bind(this), section);
14897       }
14898     }.bind(this));
14899     return this.q.run().then(function () {
14900       this.total = this._locations.length - 1;
14901 
14902       if (this._currentCfi) {
14903         this.currentLocation = this._currentCfi;
14904       }
14905 
14906       return this._locations; // console.log(this.percentage(this.book.rendition.location.start), this.percentage(this.book.rendition.location.end));
14907     }.bind(this));
14908   }
14909 
14910   createRange() {
14911     return {
14912       startContainer: undefined,
14913       startOffset: undefined,
14914       endContainer: undefined,
14915       endOffset: undefined
14916     };
14917   }
14918 
14919   process(section) {
14920     return section.load(this.request).then(function (contents) {
14921       var completed = new core["defer"]();
14922       var locations = this.parse(contents, section.cfiBase);
14923       this._locations = this._locations.concat(locations);
14924       section.unload();
14925       this.processingTimeout = setTimeout(() => completed.resolve(locations), this.pause);
14926       return completed.promise;
14927     }.bind(this));
14928   }
14929 
14930   parse(contents, cfiBase, chars) {
14931     var locations = [];
14932     var range;
14933     var doc = contents.ownerDocument;
14934     var body = Object(core["qs"])(doc, "body");
14935     var counter = 0;
14936     var prev;
14937 
14938     var _break = chars || this.break;
14939 
14940     var parser = function (node) {
14941       var len = node.length;
14942       var dist;
14943       var pos = 0;
14944 
14945       if (node.textContent.trim().length === 0) {
14946         return false; // continue
14947       } // Start range
14948 
14949 
14950       if (counter == 0) {
14951         range = this.createRange();
14952         range.startContainer = node;
14953         range.startOffset = 0;
14954       }
14955 
14956       dist = _break - counter; // Node is smaller than a break,
14957       // skip over it
14958 
14959       if (dist > len) {
14960         counter += len;
14961         pos = len;
14962       }
14963 
14964       while (pos < len) {
14965         dist = _break - counter;
14966 
14967         if (counter === 0) {
14968           // Start new range
14969           pos += 1;
14970           range = this.createRange();
14971           range.startContainer = node;
14972           range.startOffset = pos;
14973         } // pos += dist;
14974         // Gone over
14975 
14976 
14977         if (pos + dist >= len) {
14978           // Continue counter for next node
14979           counter += len - pos; // break
14980 
14981           pos = len; // At End
14982         } else {
14983           // Advance pos
14984           pos += dist; // End the previous range
14985 
14986           range.endContainer = node;
14987           range.endOffset = pos; // cfi = section.cfiFromRange(range);
14988 
14989           let cfi = new epubcfi["a" /* default */](range, cfiBase).toString();
14990           locations.push(cfi);
14991           counter = 0;
14992         }
14993       }
14994 
14995       prev = node;
14996     };
14997 
14998     Object(core["sprint"])(body, parser.bind(this)); // Close remaining
14999 
15000     if (range && range.startContainer && prev) {
15001       range.endContainer = prev;
15002       range.endOffset = prev.length;
15003       let cfi = new epubcfi["a" /* default */](range, cfiBase).toString();
15004       locations.push(cfi);
15005       counter = 0;
15006     }
15007 
15008     return locations;
15009   }
15010   /**
15011    * Load all of sections in the book to generate locations
15012    * @param  {string} startCfi start position
15013    * @param  {int} wordCount how many words to split on
15014    * @param  {int} count result count
15015    * @return {object} locations
15016    */
15017 
15018 
15019   generateFromWords(startCfi, wordCount, count) {
15020     var start = startCfi ? new epubcfi["a" /* default */](startCfi) : undefined;
15021     this.q.pause();
15022     this._locationsWords = [];
15023     this._wordCounter = 0;
15024     this.spine.each(function (section) {
15025       if (section.linear) {
15026         if (start) {
15027           if (section.index >= start.spinePos) {
15028             this.q.enqueue(this.processWords.bind(this), section, wordCount, start, count);
15029           }
15030         } else {
15031           this.q.enqueue(this.processWords.bind(this), section, wordCount, start, count);
15032         }
15033       }
15034     }.bind(this));
15035     return this.q.run().then(function () {
15036       if (this._currentCfi) {
15037         this.currentLocation = this._currentCfi;
15038       }
15039 
15040       return this._locationsWords;
15041     }.bind(this));
15042   }
15043 
15044   processWords(section, wordCount, startCfi, count) {
15045     if (count && this._locationsWords.length >= count) {
15046       return Promise.resolve();
15047     }
15048 
15049     return section.load(this.request).then(function (contents) {
15050       var completed = new core["defer"]();
15051       var locations = this.parseWords(contents, section, wordCount, startCfi);
15052       var remainingCount = count - this._locationsWords.length;
15053       this._locationsWords = this._locationsWords.concat(locations.length >= count ? locations.slice(0, remainingCount) : locations);
15054       section.unload();
15055       this.processingTimeout = setTimeout(() => completed.resolve(locations), this.pause);
15056       return completed.promise;
15057     }.bind(this));
15058   } //http://stackoverflow.com/questions/18679576/counting-words-in-string
15059 
15060 
15061   countWords(s) {
15062     s = s.replace(/(^\s*)|(\s*$)/gi, ""); //exclude  start and end white-space
15063 
15064     s = s.replace(/[ ]{2,}/gi, " "); //2 or more space to 1
15065 
15066     s = s.replace(/\n /, "\n"); // exclude newline with a start spacing
15067 
15068     return s.split(" ").length;
15069   }
15070 
15071   parseWords(contents, section, wordCount, startCfi) {
15072     var cfiBase = section.cfiBase;
15073     var locations = [];
15074     var doc = contents.ownerDocument;
15075     var body = Object(core["qs"])(doc, "body");
15076     var prev;
15077     var _break = wordCount;
15078     var foundStartNode = startCfi ? startCfi.spinePos !== section.index : true;
15079     var startNode;
15080 
15081     if (startCfi && section.index === startCfi.spinePos) {
15082       startNode = startCfi.findNode(startCfi.range ? startCfi.path.steps.concat(startCfi.start.steps) : startCfi.path.steps, contents.ownerDocument);
15083     }
15084 
15085     var parser = function (node) {
15086       if (!foundStartNode) {
15087         if (node === startNode) {
15088           foundStartNode = true;
15089         } else {
15090           return false;
15091         }
15092       }
15093 
15094       if (node.textContent.length < 10) {
15095         if (node.textContent.trim().length === 0) {
15096           return false;
15097         }
15098       }
15099 
15100       var len = this.countWords(node.textContent);
15101       var dist;
15102       var pos = 0;
15103 
15104       if (len === 0) {
15105         return false; // continue
15106       }
15107 
15108       dist = _break - this._wordCounter; // Node is smaller than a break,
15109       // skip over it
15110 
15111       if (dist > len) {
15112         this._wordCounter += len;
15113         pos = len;
15114       }
15115 
15116       while (pos < len) {
15117         dist = _break - this._wordCounter; // Gone over
15118 
15119         if (pos + dist >= len) {
15120           // Continue counter for next node
15121           this._wordCounter += len - pos; // break
15122 
15123           pos = len; // At End
15124         } else {
15125           // Advance pos
15126           pos += dist;
15127           let cfi = new epubcfi["a" /* default */](node, cfiBase);
15128           locations.push({
15129             cfi: cfi.toString(),
15130             wordCount: this._wordCounter
15131           });
15132           this._wordCounter = 0;
15133         }
15134       }
15135 
15136       prev = node;
15137     };
15138 
15139     Object(core["sprint"])(body, parser.bind(this));
15140     return locations;
15141   }
15142   /**
15143    * Get a location from an EpubCFI
15144    * @param {EpubCFI} cfi
15145    * @return {number}
15146    */
15147 
15148 
15149   locationFromCfi(cfi) {
15150     let loc;
15151 
15152     if (epubcfi["a" /* default */].prototype.isCfiString(cfi)) {
15153       cfi = new epubcfi["a" /* default */](cfi);
15154     } // Check if the location has not been set yet
15155 
15156 
15157     if (this._locations.length === 0) {
15158       return -1;
15159     }
15160 
15161     loc = Object(core["locationOf"])(cfi, this._locations, this.epubcfi.compare);
15162 
15163     if (loc > this.total) {
15164       return this.total;
15165     }
15166 
15167     return loc;
15168   }
15169   /**
15170    * Get a percentage position in locations from an EpubCFI
15171    * @param {EpubCFI} cfi
15172    * @return {number}
15173    */
15174 
15175 
15176   percentageFromCfi(cfi) {
15177     if (this._locations.length === 0) {
15178       return null;
15179     } // Find closest cfi
15180 
15181 
15182     var loc = this.locationFromCfi(cfi); // Get percentage in total
15183 
15184     return this.percentageFromLocation(loc);
15185   }
15186   /**
15187    * Get a percentage position from a location index
15188    * @param {number} location
15189    * @return {number}
15190    */
15191 
15192 
15193   percentageFromLocation(loc) {
15194     if (!loc || !this.total) {
15195       return 0;
15196     }
15197 
15198     return loc / this.total;
15199   }
15200   /**
15201    * Get an EpubCFI from location index
15202    * @param {number} loc
15203    * @return {EpubCFI} cfi
15204    */
15205 
15206 
15207   cfiFromLocation(loc) {
15208     var cfi = -1; // check that pg is an int
15209 
15210     if (typeof loc != "number") {
15211       loc = parseInt(loc);
15212     }
15213 
15214     if (loc >= 0 && loc < this._locations.length) {
15215       cfi = this._locations[loc];
15216     }
15217 
15218     return cfi;
15219   }
15220   /**
15221    * Get an EpubCFI from location percentage
15222    * @param {number} percentage
15223    * @return {EpubCFI} cfi
15224    */
15225 
15226 
15227   cfiFromPercentage(percentage) {
15228     let loc;
15229 
15230     if (percentage > 1) {
15231       console.warn("Normalize cfiFromPercentage value to between 0 - 1");
15232     } // Make sure 1 goes to very end
15233 
15234 
15235     if (percentage >= 1) {
15236       let cfi = new epubcfi["a" /* default */](this._locations[this.total]);
15237       cfi.collapse();
15238       return cfi.toString();
15239     }
15240 
15241     loc = Math.ceil(this.total * percentage);
15242     return this.cfiFromLocation(loc);
15243   }
15244   /**
15245    * Load locations from JSON
15246    * @param {json} locations
15247    */
15248 
15249 
15250   load(locations) {
15251     if (typeof locations === "string") {
15252       this._locations = JSON.parse(locations);
15253     } else {
15254       this._locations = locations;
15255     }
15256 
15257     this.total = this._locations.length - 1;
15258     return this._locations;
15259   }
15260   /**
15261    * Save locations to JSON
15262    * @return {json}
15263    */
15264 
15265 
15266   save() {
15267     return JSON.stringify(this._locations);
15268   }
15269 
15270   getCurrent() {
15271     return this._current;
15272   }
15273 
15274   setCurrent(curr) {
15275     var loc;
15276 
15277     if (typeof curr == "string") {
15278       this._currentCfi = curr;
15279     } else if (typeof curr == "number") {
15280       this._current = curr;
15281     } else {
15282       return;
15283     }
15284 
15285     if (this._locations.length === 0) {
15286       return;
15287     }
15288 
15289     if (typeof curr == "string") {
15290       loc = this.locationFromCfi(curr);
15291       this._current = loc;
15292     } else {
15293       loc = curr;
15294     }
15295 
15296     this.emit(constants["c" /* EVENTS */].LOCATIONS.CHANGED, {
15297       percentage: this.percentageFromLocation(loc)
15298     });
15299   }
15300   /**
15301    * Get the current location
15302    */
15303 
15304 
15305   get currentLocation() {
15306     return this._current;
15307   }
15308   /**
15309    * Set the current location
15310    */
15311 
15312 
15313   set currentLocation(curr) {
15314     this.setCurrent(curr);
15315   }
15316   /**
15317    * Locations length
15318    */
15319 
15320 
15321   length() {
15322     return this._locations.length;
15323   }
15324 
15325   destroy() {
15326     this.spine = undefined;
15327     this.request = undefined;
15328     this.pause = undefined;
15329     this.q.stop();
15330     this.q = undefined;
15331     this.epubcfi = undefined;
15332     this._locations = undefined;
15333     this.total = undefined;
15334     this.break = undefined;
15335     this._current = undefined;
15336     this.currentLocation = undefined;
15337     this._currentCfi = undefined;
15338     clearTimeout(this.processingTimeout);
15339   }
15340 
15341 }
15342 
15343 event_emitter_default()(locations_Locations.prototype);
15344 /* harmony default export */ var src_locations = (locations_Locations);
15345 // EXTERNAL MODULE: ./node_modules/path-webpack/path.js
15346 var path_webpack_path = __webpack_require__(7);
15347 var path_default = /*#__PURE__*/__webpack_require__.n(path_webpack_path);
15348 
15349 // CONCATENATED MODULE: ./src/container.js
15350 
15351 
15352 /**
15353  * Handles Parsing and Accessing an Epub Container
15354  * @class
15355  * @param {document} [containerDocument] xml document
15356  */
15357 
15358 class container_Container {
15359   constructor(containerDocument) {
15360     this.packagePath = '';
15361     this.directory = '';
15362     this.encoding = '';
15363 
15364     if (containerDocument) {
15365       this.parse(containerDocument);
15366     }
15367   }
15368   /**
15369    * Parse the Container XML
15370    * @param  {document} containerDocument
15371    */
15372 
15373 
15374   parse(containerDocument) {
15375     //-- <rootfile full-path="OPS/package.opf" media-type="application/oebps-package+xml"/>
15376     var rootfile;
15377 
15378     if (!containerDocument) {
15379       throw new Error("Container File Not Found");
15380     }
15381 
15382     rootfile = Object(core["qs"])(containerDocument, "rootfile");
15383 
15384     if (!rootfile) {
15385       throw new Error("No RootFile Found");
15386     }
15387 
15388     this.packagePath = rootfile.getAttribute("full-path");
15389     this.directory = path_default.a.dirname(this.packagePath);
15390     this.encoding = containerDocument.xmlEncoding;
15391   }
15392 
15393   destroy() {
15394     this.packagePath = undefined;
15395     this.directory = undefined;
15396     this.encoding = undefined;
15397   }
15398 
15399 }
15400 
15401 /* harmony default export */ var container = (container_Container);
15402 // CONCATENATED MODULE: ./src/packaging.js
15403 
15404 /**
15405  * Open Packaging Format Parser
15406  * @class
15407  * @param {document} packageDocument OPF XML
15408  */
15409 
15410 class packaging_Packaging {
15411   constructor(packageDocument) {
15412     this.manifest = {};
15413     this.navPath = '';
15414     this.ncxPath = '';
15415     this.coverPath = '';
15416     this.spineNodeIndex = 0;
15417     this.spine = [];
15418     this.metadata = {};
15419 
15420     if (packageDocument) {
15421       this.parse(packageDocument);
15422     }
15423   }
15424   /**
15425    * Parse OPF XML
15426    * @param  {document} packageDocument OPF XML
15427    * @return {object} parsed package parts
15428    */
15429 
15430 
15431   parse(packageDocument) {
15432     var metadataNode, manifestNode, spineNode;
15433 
15434     if (!packageDocument) {
15435       throw new Error("Package File Not Found");
15436     }
15437 
15438     metadataNode = Object(core["qs"])(packageDocument, "metadata");
15439 
15440     if (!metadataNode) {
15441       throw new Error("No Metadata Found");
15442     }
15443 
15444     manifestNode = Object(core["qs"])(packageDocument, "manifest");
15445 
15446     if (!manifestNode) {
15447       throw new Error("No Manifest Found");
15448     }
15449 
15450     spineNode = Object(core["qs"])(packageDocument, "spine");
15451 
15452     if (!spineNode) {
15453       throw new Error("No Spine Found");
15454     }
15455 
15456     this.manifest = this.parseManifest(manifestNode);
15457     this.navPath = this.findNavPath(manifestNode);
15458     this.ncxPath = this.findNcxPath(manifestNode, spineNode);
15459     this.coverPath = this.findCoverPath(packageDocument);
15460     this.spineNodeIndex = Object(core["indexOfElementNode"])(spineNode);
15461     this.spine = this.parseSpine(spineNode, this.manifest);
15462     this.uniqueIdentifier = this.findUniqueIdentifier(packageDocument);
15463     this.metadata = this.parseMetadata(metadataNode);
15464     this.metadata.direction = spineNode.getAttribute("page-progression-direction");
15465     return {
15466       "metadata": this.metadata,
15467       "spine": this.spine,
15468       "manifest": this.manifest,
15469       "navPath": this.navPath,
15470       "ncxPath": this.ncxPath,
15471       "coverPath": this.coverPath,
15472       "spineNodeIndex": this.spineNodeIndex
15473     };
15474   }
15475   /**
15476    * Parse Metadata
15477    * @private
15478    * @param  {node} xml
15479    * @return {object} metadata
15480    */
15481 
15482 
15483   parseMetadata(xml) {
15484     var metadata = {};
15485     metadata.title = this.getElementText(xml, "title");
15486     metadata.creator = this.getElementText(xml, "creator");
15487     metadata.description = this.getElementText(xml, "description");
15488     metadata.pubdate = this.getElementText(xml, "date");
15489     metadata.publisher = this.getElementText(xml, "publisher");
15490     metadata.identifier = this.getElementText(xml, "identifier");
15491     metadata.language = this.getElementText(xml, "language");
15492     metadata.rights = this.getElementText(xml, "rights");
15493     metadata.modified_date = this.getPropertyText(xml, "dcterms:modified");
15494     metadata.layout = this.getPropertyText(xml, "rendition:layout");
15495     metadata.orientation = this.getPropertyText(xml, "rendition:orientation");
15496     metadata.flow = this.getPropertyText(xml, "rendition:flow");
15497     metadata.viewport = this.getPropertyText(xml, "rendition:viewport");
15498     metadata.media_active_class = this.getPropertyText(xml, "media:active-class");
15499     metadata.spread = this.getPropertyText(xml, "rendition:spread"); // metadata.page_prog_dir = packageXml.querySelector("spine").getAttribute("page-progression-direction");
15500 
15501     return metadata;
15502   }
15503   /**
15504    * Parse Manifest
15505    * @private
15506    * @param  {node} manifestXml
15507    * @return {object} manifest
15508    */
15509 
15510 
15511   parseManifest(manifestXml) {
15512     var manifest = {}; //-- Turn items into an array
15513     // var selected = manifestXml.querySelectorAll("item");
15514 
15515     var selected = Object(core["qsa"])(manifestXml, "item");
15516     var items = Array.prototype.slice.call(selected); //-- Create an object with the id as key
15517 
15518     items.forEach(function (item) {
15519       var id = item.getAttribute("id"),
15520           href = item.getAttribute("href") || "",
15521           type = item.getAttribute("media-type") || "",
15522           overlay = item.getAttribute("media-overlay") || "",
15523           properties = item.getAttribute("properties") || "";
15524       manifest[id] = {
15525         "href": href,
15526         // "url" : href,
15527         "type": type,
15528         "overlay": overlay,
15529         "properties": properties.length ? properties.split(" ") : []
15530       };
15531     });
15532     return manifest;
15533   }
15534   /**
15535    * Parse Spine
15536    * @private
15537    * @param  {node} spineXml
15538    * @param  {Packaging.manifest} manifest
15539    * @return {object} spine
15540    */
15541 
15542 
15543   parseSpine(spineXml, manifest) {
15544     var spine = [];
15545     var selected = Object(core["qsa"])(spineXml, "itemref");
15546     var items = Array.prototype.slice.call(selected); // var epubcfi = new EpubCFI();
15547     //-- Add to array to maintain ordering and cross reference with manifest
15548 
15549     items.forEach(function (item, index) {
15550       var idref = item.getAttribute("idref"); // var cfiBase = epubcfi.generateChapterComponent(spineNodeIndex, index, Id);
15551 
15552       var props = item.getAttribute("properties") || "";
15553       var propArray = props.length ? props.split(" ") : []; // var manifestProps = manifest[Id].properties;
15554       // var manifestPropArray = manifestProps.length ? manifestProps.split(" ") : [];
15555 
15556       var itemref = {
15557         "id": item.getAttribute("id"),
15558         "idref": idref,
15559         "linear": item.getAttribute("linear") || "yes",
15560         "properties": propArray,
15561         // "href" : manifest[Id].href,
15562         // "url" :  manifest[Id].url,
15563         "index": index // "cfiBase" : cfiBase
15564 
15565       };
15566       spine.push(itemref);
15567     });
15568     return spine;
15569   }
15570   /**
15571    * Find Unique Identifier
15572    * @private
15573    * @param  {node} packageXml
15574    * @return {string} Unique Identifier text
15575    */
15576 
15577 
15578   findUniqueIdentifier(packageXml) {
15579     var uniqueIdentifierId = packageXml.documentElement.getAttribute("unique-identifier");
15580 
15581     if (!uniqueIdentifierId) {
15582       return "";
15583     }
15584 
15585     var identifier = packageXml.getElementById(uniqueIdentifierId);
15586 
15587     if (!identifier) {
15588       return "";
15589     }
15590 
15591     if (identifier.localName === "identifier" && identifier.namespaceURI === "http://purl.org/dc/elements/1.1/") {
15592       return identifier.childNodes.length > 0 ? identifier.childNodes[0].nodeValue.trim() : "";
15593     }
15594 
15595     return "";
15596   }
15597   /**
15598    * Find TOC NAV
15599    * @private
15600    * @param {element} manifestNode
15601    * @return {string}
15602    */
15603 
15604 
15605   findNavPath(manifestNode) {
15606     // Find item with property "nav"
15607     // Should catch nav regardless of order
15608     // var node = manifestNode.querySelector("item[properties$='nav'], item[properties^='nav '], item[properties*=' nav ']");
15609     var node = Object(core["qsp"])(manifestNode, "item", {
15610       "properties": "nav"
15611     });
15612     return node ? node.getAttribute("href") : false;
15613   }
15614   /**
15615    * Find TOC NCX
15616    * media-type="application/x-dtbncx+xml" href="toc.ncx"
15617    * @private
15618    * @param {element} manifestNode
15619    * @param {element} spineNode
15620    * @return {string}
15621    */
15622 
15623 
15624   findNcxPath(manifestNode, spineNode) {
15625     // var node = manifestNode.querySelector("item[media-type='application/x-dtbncx+xml']");
15626     var node = Object(core["qsp"])(manifestNode, "item", {
15627       "media-type": "application/x-dtbncx+xml"
15628     });
15629     var tocId; // If we can't find the toc by media-type then try to look for id of the item in the spine attributes as
15630     // according to http://www.idpf.org/epub/20/spec/OPF_2.0.1_draft.htm#Section2.4.1.2,
15631     // "The item that describes the NCX must be referenced by the spine toc attribute."
15632 
15633     if (!node) {
15634       tocId = spineNode.getAttribute("toc");
15635 
15636       if (tocId) {
15637         // node = manifestNode.querySelector("item[id='" + tocId + "']");
15638         node = manifestNode.querySelector(`#${tocId}`);
15639       }
15640     }
15641 
15642     return node ? node.getAttribute("href") : false;
15643   }
15644   /**
15645    * Find the Cover Path
15646    * <item properties="cover-image" id="ci" href="cover.svg" media-type="image/svg+xml" />
15647    * Fallback for Epub 2.0
15648    * @private
15649    * @param  {node} packageXml
15650    * @return {string} href
15651    */
15652 
15653 
15654   findCoverPath(packageXml) {
15655     var pkg = Object(core["qs"])(packageXml, "package");
15656     var epubVersion = pkg.getAttribute("version"); // Try parsing cover with epub 3.
15657     // var node = packageXml.querySelector("item[properties='cover-image']");
15658 
15659     var node = Object(core["qsp"])(packageXml, "item", {
15660       "properties": "cover-image"
15661     });
15662     if (node) return node.getAttribute("href"); // Fallback to epub 2.
15663 
15664     var metaCover = Object(core["qsp"])(packageXml, "meta", {
15665       "name": "cover"
15666     });
15667 
15668     if (metaCover) {
15669       var coverId = metaCover.getAttribute("content"); // var cover = packageXml.querySelector("item[id='" + coverId + "']");
15670 
15671       var cover = packageXml.getElementById(coverId);
15672       return cover ? cover.getAttribute("href") : "";
15673     } else {
15674       return false;
15675     }
15676   }
15677   /**
15678    * Get text of a namespaced element
15679    * @private
15680    * @param  {node} xml
15681    * @param  {string} tag
15682    * @return {string} text
15683    */
15684 
15685 
15686   getElementText(xml, tag) {
15687     var found = xml.getElementsByTagNameNS("http://purl.org/dc/elements/1.1/", tag);
15688     var el;
15689     if (!found || found.length === 0) return "";
15690     el = found[0];
15691 
15692     if (el.childNodes.length) {
15693       return el.childNodes[0].nodeValue;
15694     }
15695 
15696     return "";
15697   }
15698   /**
15699    * Get text by property
15700    * @private
15701    * @param  {node} xml
15702    * @param  {string} property
15703    * @return {string} text
15704    */
15705 
15706 
15707   getPropertyText(xml, property) {
15708     var el = Object(core["qsp"])(xml, "meta", {
15709       "property": property
15710     });
15711 
15712     if (el && el.childNodes.length) {
15713       return el.childNodes[0].nodeValue;
15714     }
15715 
15716     return "";
15717   }
15718   /**
15719    * Load JSON Manifest
15720    * @param  {document} packageDocument OPF XML
15721    * @return {object} parsed package parts
15722    */
15723 
15724 
15725   load(json) {
15726     this.metadata = json.metadata;
15727     let spine = json.readingOrder || json.spine;
15728     this.spine = spine.map((item, index) => {
15729       item.index = index;
15730       item.linear = item.linear || "yes";
15731       return item;
15732     });
15733     json.resources.forEach((item, index) => {
15734       this.manifest[index] = item;
15735 
15736       if (item.rel && item.rel[0] === "cover") {
15737         this.coverPath = item.href;
15738       }
15739     });
15740     this.spineNodeIndex = 0;
15741     this.toc = json.toc.map((item, index) => {
15742       item.label = item.title;
15743       return item;
15744     });
15745     return {
15746       "metadata": this.metadata,
15747       "spine": this.spine,
15748       "manifest": this.manifest,
15749       "navPath": this.navPath,
15750       "ncxPath": this.ncxPath,
15751       "coverPath": this.coverPath,
15752       "spineNodeIndex": this.spineNodeIndex,
15753       "toc": this.toc
15754     };
15755   }
15756 
15757   destroy() {
15758     this.manifest = undefined;
15759     this.navPath = undefined;
15760     this.ncxPath = undefined;
15761     this.coverPath = undefined;
15762     this.spineNodeIndex = undefined;
15763     this.spine = undefined;
15764     this.metadata = undefined;
15765   }
15766 
15767 }
15768 
15769 /* harmony default export */ var src_packaging = (packaging_Packaging);
15770 // CONCATENATED MODULE: ./src/navigation.js
15771 
15772 /**
15773  * Navigation Parser
15774  * @param {document} xml navigation html / xhtml / ncx
15775  */
15776 
15777 class navigation_Navigation {
15778   constructor(xml) {
15779     this.toc = [];
15780     this.tocByHref = {};
15781     this.tocById = {};
15782     this.landmarks = [];
15783     this.landmarksByType = {};
15784     this.length = 0;
15785 
15786     if (xml) {
15787       this.parse(xml);
15788     }
15789   }
15790   /**
15791    * Parse out the navigation items
15792    * @param {document} xml navigation html / xhtml / ncx
15793    */
15794 
15795 
15796   parse(xml) {
15797     let isXml = xml.nodeType;
15798     let html;
15799     let ncx;
15800 
15801     if (isXml) {
15802       html = Object(core["qs"])(xml, "html");
15803       ncx = Object(core["qs"])(xml, "ncx");
15804     }
15805 
15806     if (!isXml) {
15807       this.toc = this.load(xml);
15808     } else if (html) {
15809       this.toc = this.parseNav(xml);
15810       this.landmarks = this.parseLandmarks(xml);
15811     } else if (ncx) {
15812       this.toc = this.parseNcx(xml);
15813     }
15814 
15815     this.length = 0;
15816     this.unpack(this.toc);
15817   }
15818   /**
15819    * Unpack navigation items
15820    * @private
15821    * @param  {array} toc
15822    */
15823 
15824 
15825   unpack(toc) {
15826     var item;
15827 
15828     for (var i = 0; i < toc.length; i++) {
15829       item = toc[i];
15830 
15831       if (item.href) {
15832         this.tocByHref[item.href] = i;
15833       }
15834 
15835       if (item.id) {
15836         this.tocById[item.id] = i;
15837       }
15838 
15839       this.length++;
15840 
15841       if (item.subitems.length) {
15842         this.unpack(item.subitems);
15843       }
15844     }
15845   }
15846   /**
15847    * Get an item from the navigation
15848    * @param  {string} target
15849    * @return {object} navItem
15850    */
15851 
15852 
15853   get(target) {
15854     var index;
15855 
15856     if (!target) {
15857       return this.toc;
15858     }
15859 
15860     if (target.indexOf("#") === 0) {
15861       index = this.tocById[target.substring(1)];
15862     } else if (target in this.tocByHref) {
15863       index = this.tocByHref[target];
15864     }
15865 
15866     return this.getByIndex(target, index, this.toc);
15867   }
15868   /**
15869    * Get an item from navigation subitems recursively by index
15870    * @param  {string} target
15871    * @param  {number} index
15872    * @param  {array} navItems
15873    * @return {object} navItem
15874    */
15875 
15876 
15877   getByIndex(target, index, navItems) {
15878     if (navItems.length === 0) {
15879       return;
15880     }
15881 
15882     const item = navItems[index];
15883 
15884     if (item && (target === item.id || target === item.href)) {
15885       return item;
15886     } else {
15887       let result;
15888 
15889       for (let i = 0; i < navItems.length; ++i) {
15890         result = this.getByIndex(target, index, navItems[i].subitems);
15891 
15892         if (result) {
15893           break;
15894         }
15895       }
15896 
15897       return result;
15898     }
15899   }
15900   /**
15901    * Get a landmark by type
15902    * List of types: https://idpf.github.io/epub-vocabs/structure/
15903    * @param  {string} type
15904    * @return {object} landmarkItem
15905    */
15906 
15907 
15908   landmark(type) {
15909     var index;
15910 
15911     if (!type) {
15912       return this.landmarks;
15913     }
15914 
15915     index = this.landmarksByType[type];
15916     return this.landmarks[index];
15917   }
15918   /**
15919    * Parse toc from a Epub > 3.0 Nav
15920    * @private
15921    * @param  {document} navHtml
15922    * @return {array} navigation list
15923    */
15924 
15925 
15926   parseNav(navHtml) {
15927     var navElement = Object(core["querySelectorByType"])(navHtml, "nav", "toc");
15928     var list = [];
15929     if (!navElement) return list;
15930     let navList = Object(core["filterChildren"])(navElement, "ol", true);
15931     if (!navList) return list;
15932     list = this.parseNavList(navList);
15933     return list;
15934   }
15935   /**
15936    * Parses lists in the toc
15937    * @param  {document} navListHtml
15938    * @param  {string} parent id
15939    * @return {array} navigation list
15940    */
15941 
15942 
15943   parseNavList(navListHtml, parent) {
15944     const result = [];
15945     if (!navListHtml) return result;
15946     if (!navListHtml.children) return result;
15947 
15948     for (let i = 0; i < navListHtml.children.length; i++) {
15949       const item = this.navItem(navListHtml.children[i], parent);
15950 
15951       if (item) {
15952         result.push(item);
15953       }
15954     }
15955 
15956     return result;
15957   }
15958   /**
15959    * Create a navItem
15960    * @private
15961    * @param  {element} item
15962    * @return {object} navItem
15963    */
15964 
15965 
15966   navItem(item, parent) {
15967     let id = item.getAttribute("id") || undefined;
15968     let content = Object(core["filterChildren"])(item, "a", true) || Object(core["filterChildren"])(item, "span", true);
15969 
15970     if (!content) {
15971       return;
15972     }
15973 
15974     let src = content.getAttribute("href") || "";
15975 
15976     if (!id) {
15977       id = src;
15978     }
15979 
15980     let text = content.textContent || "";
15981     let subitems = [];
15982     let nested = Object(core["filterChildren"])(item, "ol", true);
15983 
15984     if (nested) {
15985       subitems = this.parseNavList(nested, id);
15986     }
15987 
15988     return {
15989       "id": id,
15990       "href": src,
15991       "label": text,
15992       "subitems": subitems,
15993       "parent": parent
15994     };
15995   }
15996   /**
15997    * Parse landmarks from a Epub > 3.0 Nav
15998    * @private
15999    * @param  {document} navHtml
16000    * @return {array} landmarks list
16001    */
16002 
16003 
16004   parseLandmarks(navHtml) {
16005     var navElement = Object(core["querySelectorByType"])(navHtml, "nav", "landmarks");
16006     var navItems = navElement ? Object(core["qsa"])(navElement, "li") : [];
16007     var length = navItems.length;
16008     var i;
16009     var list = [];
16010     var item;
16011     if (!navItems || length === 0) return list;
16012 
16013     for (i = 0; i < length; ++i) {
16014       item = this.landmarkItem(navItems[i]);
16015 
16016       if (item) {
16017         list.push(item);
16018         this.landmarksByType[item.type] = i;
16019       }
16020     }
16021 
16022     return list;
16023   }
16024   /**
16025    * Create a landmarkItem
16026    * @private
16027    * @param  {element} item
16028    * @return {object} landmarkItem
16029    */
16030 
16031 
16032   landmarkItem(item) {
16033     let content = Object(core["filterChildren"])(item, "a", true);
16034 
16035     if (!content) {
16036       return;
16037     }
16038 
16039     let type = content.getAttributeNS("http://www.idpf.org/2007/ops", "type") || undefined;
16040     let href = content.getAttribute("href") || "";
16041     let text = content.textContent || "";
16042     return {
16043       "href": href,
16044       "label": text,
16045       "type": type
16046     };
16047   }
16048   /**
16049    * Parse from a Epub > 3.0 NC
16050    * @private
16051    * @param  {document} navHtml
16052    * @return {array} navigation list
16053    */
16054 
16055 
16056   parseNcx(tocXml) {
16057     var navPoints = Object(core["qsa"])(tocXml, "navPoint");
16058     var length = navPoints.length;
16059     var i;
16060     var toc = {};
16061     var list = [];
16062     var item, parent;
16063     if (!navPoints || length === 0) return list;
16064 
16065     for (i = 0; i < length; ++i) {
16066       item = this.ncxItem(navPoints[i]);
16067       toc[item.id] = item;
16068 
16069       if (!item.parent) {
16070         list.push(item);
16071       } else {
16072         parent = toc[item.parent];
16073         parent.subitems.push(item);
16074       }
16075     }
16076 
16077     return list;
16078   }
16079   /**
16080    * Create a ncxItem
16081    * @private
16082    * @param  {element} item
16083    * @return {object} ncxItem
16084    */
16085 
16086 
16087   ncxItem(item) {
16088     var id = item.getAttribute("id") || false,
16089         content = Object(core["qs"])(item, "content"),
16090         src = content.getAttribute("src"),
16091         navLabel = Object(core["qs"])(item, "navLabel"),
16092         text = navLabel.textContent ? navLabel.textContent : "",
16093         subitems = [],
16094         parentNode = item.parentNode,
16095         parent;
16096 
16097     if (parentNode && (parentNode.nodeName === "navPoint" || parentNode.nodeName.split(':').slice(-1)[0] === "navPoint")) {
16098       parent = parentNode.getAttribute("id");
16099     }
16100 
16101     return {
16102       "id": id,
16103       "href": src,
16104       "label": text,
16105       "subitems": subitems,
16106       "parent": parent
16107     };
16108   }
16109   /**
16110    * Load Spine Items
16111    * @param  {object} json the items to be loaded
16112    * @return {Array} navItems
16113    */
16114 
16115 
16116   load(json) {
16117     return json.map(item => {
16118       item.label = item.title;
16119       item.subitems = item.children ? this.load(item.children) : [];
16120       return item;
16121     });
16122   }
16123   /**
16124    * forEach pass through
16125    * @param  {Function} fn function to run on each item
16126    * @return {method} forEach loop
16127    */
16128 
16129 
16130   forEach(fn) {
16131     return this.toc.forEach(fn);
16132   }
16133 
16134 }
16135 
16136 /* harmony default export */ var navigation = (navigation_Navigation);
16137 // CONCATENATED MODULE: ./src/utils/mime.js
16138 /*
16139  From Zip.js, by Gildas Lormeau
16140 edited down
16141  */
16142 var table = {
16143   "application": {
16144     "ecmascript": ["es", "ecma"],
16145     "javascript": "js",
16146     "ogg": "ogx",
16147     "pdf": "pdf",
16148     "postscript": ["ps", "ai", "eps", "epsi", "epsf", "eps2", "eps3"],
16149     "rdf+xml": "rdf",
16150     "smil": ["smi", "smil"],
16151     "xhtml+xml": ["xhtml", "xht"],
16152     "xml": ["xml", "xsl", "xsd", "opf", "ncx"],
16153     "zip": "zip",
16154     "x-httpd-eruby": "rhtml",
16155     "x-latex": "latex",
16156     "x-maker": ["frm", "maker", "frame", "fm", "fb", "book", "fbdoc"],
16157     "x-object": "o",
16158     "x-shockwave-flash": ["swf", "swfl"],
16159     "x-silverlight": "scr",
16160     "epub+zip": "epub",
16161     "font-tdpfr": "pfr",
16162     "inkml+xml": ["ink", "inkml"],
16163     "json": "json",
16164     "jsonml+json": "jsonml",
16165     "mathml+xml": "mathml",
16166     "metalink+xml": "metalink",
16167     "mp4": "mp4s",
16168     // "oebps-package+xml" : "opf",
16169     "omdoc+xml": "omdoc",
16170     "oxps": "oxps",
16171     "vnd.amazon.ebook": "azw",
16172     "widget": "wgt",
16173     // "x-dtbncx+xml" : "ncx",
16174     "x-dtbook+xml": "dtb",
16175     "x-dtbresource+xml": "res",
16176     "x-font-bdf": "bdf",
16177     "x-font-ghostscript": "gsf",
16178     "x-font-linux-psf": "psf",
16179     "x-font-otf": "otf",
16180     "x-font-pcf": "pcf",
16181     "x-font-snf": "snf",
16182     "x-font-ttf": ["ttf", "ttc"],
16183     "x-font-type1": ["pfa", "pfb", "pfm", "afm"],
16184     "x-font-woff": "woff",
16185     "x-mobipocket-ebook": ["prc", "mobi"],
16186     "x-mspublisher": "pub",
16187     "x-nzb": "nzb",
16188     "x-tgif": "obj",
16189     "xaml+xml": "xaml",
16190     "xml-dtd": "dtd",
16191     "xproc+xml": "xpl",
16192     "xslt+xml": "xslt",
16193     "internet-property-stream": "acx",
16194     "x-compress": "z",
16195     "x-compressed": "tgz",
16196     "x-gzip": "gz"
16197   },
16198   "audio": {
16199     "flac": "flac",
16200     "midi": ["mid", "midi", "kar", "rmi"],
16201     "mpeg": ["mpga", "mpega", "mp2", "mp3", "m4a", "mp2a", "m2a", "m3a"],
16202     "mpegurl": "m3u",
16203     "ogg": ["oga", "ogg", "spx"],
16204     "x-aiff": ["aif", "aiff", "aifc"],
16205     "x-ms-wma": "wma",
16206     "x-wav": "wav",
16207     "adpcm": "adp",
16208     "mp4": "mp4a",
16209     "webm": "weba",
16210     "x-aac": "aac",
16211     "x-caf": "caf",
16212     "x-matroska": "mka",
16213     "x-pn-realaudio-plugin": "rmp",
16214     "xm": "xm",
16215     "mid": ["mid", "rmi"]
16216   },
16217   "image": {
16218     "gif": "gif",
16219     "ief": "ief",
16220     "jpeg": ["jpeg", "jpg", "jpe"],
16221     "pcx": "pcx",
16222     "png": "png",
16223     "svg+xml": ["svg", "svgz"],
16224     "tiff": ["tiff", "tif"],
16225     "x-icon": "ico",
16226     "bmp": "bmp",
16227     "webp": "webp",
16228     "x-pict": ["pic", "pct"],
16229     "x-tga": "tga",
16230     "cis-cod": "cod"
16231   },
16232   "text": {
16233     "cache-manifest": ["manifest", "appcache"],
16234     "css": "css",
16235     "csv": "csv",
16236     "html": ["html", "htm", "shtml", "stm"],
16237     "mathml": "mml",
16238     "plain": ["txt", "text", "brf", "conf", "def", "list", "log", "in", "bas"],
16239     "richtext": "rtx",
16240     "tab-separated-values": "tsv",
16241     "x-bibtex": "bib"
16242   },
16243   "video": {
16244     "mpeg": ["mpeg", "mpg", "mpe", "m1v", "m2v", "mp2", "mpa", "mpv2"],
16245     "mp4": ["mp4", "mp4v", "mpg4"],
16246     "quicktime": ["qt", "mov"],
16247     "ogg": "ogv",
16248     "vnd.mpegurl": ["mxu", "m4u"],
16249     "x-flv": "flv",
16250     "x-la-asf": ["lsf", "lsx"],
16251     "x-mng": "mng",
16252     "x-ms-asf": ["asf", "asx", "asr"],
16253     "x-ms-wm": "wm",
16254     "x-ms-wmv": "wmv",
16255     "x-ms-wmx": "wmx",
16256     "x-ms-wvx": "wvx",
16257     "x-msvideo": "avi",
16258     "x-sgi-movie": "movie",
16259     "x-matroska": ["mpv", "mkv", "mk3d", "mks"],
16260     "3gpp2": "3g2",
16261     "h261": "h261",
16262     "h263": "h263",
16263     "h264": "h264",
16264     "jpeg": "jpgv",
16265     "jpm": ["jpm", "jpgm"],
16266     "mj2": ["mj2", "mjp2"],
16267     "vnd.ms-playready.media.pyv": "pyv",
16268     "vnd.uvvu.mp4": ["uvu", "uvvu"],
16269     "vnd.vivo": "viv",
16270     "webm": "webm",
16271     "x-f4v": "f4v",
16272     "x-m4v": "m4v",
16273     "x-ms-vob": "vob",
16274     "x-smv": "smv"
16275   }
16276 };
16277 
16278 var mime_mimeTypes = function () {
16279   var type,
16280       subtype,
16281       val,
16282       index,
16283       mimeTypes = {};
16284 
16285   for (type in table) {
16286     if (table.hasOwnProperty(type)) {
16287       for (subtype in table[type]) {
16288         if (table[type].hasOwnProperty(subtype)) {
16289           val = table[type][subtype];
16290 
16291           if (typeof val == "string") {
16292             mimeTypes[val] = type + "/" + subtype;
16293           } else {
16294             for (index = 0; index < val.length; index++) {
16295               mimeTypes[val[index]] = type + "/" + subtype;
16296             }
16297           }
16298         }
16299       }
16300     }
16301   }
16302 
16303   return mimeTypes;
16304 }();
16305 
16306 var defaultValue = "text/plain"; //"application/octet-stream";
16307 
16308 function lookup(filename) {
16309   return filename && mime_mimeTypes[filename.split(".").pop().toLowerCase()] || defaultValue;
16310 }
16311 
16312 ;
16313 /* harmony default export */ var mime = ({
16314   lookup
16315 });
16316 // CONCATENATED MODULE: ./src/resources.js
16317 
16318 
16319 
16320 
16321 
16322 
16323 /**
16324  * Handle Package Resources
16325  * @class
16326  * @param {Manifest} manifest
16327  * @param {object} [options]
16328  * @param {string} [options.replacements="base64"]
16329  * @param {Archive} [options.archive]
16330  * @param {method} [options.resolver]
16331  */
16332 
16333 class resources_Resources {
16334   constructor(manifest, options) {
16335     this.settings = {
16336       replacements: options && options.replacements || "base64",
16337       archive: options && options.archive,
16338       resolver: options && options.resolver,
16339       request: options && options.request
16340     };
16341     this.process(manifest);
16342   }
16343   /**
16344    * Process resources
16345    * @param {Manifest} manifest
16346    */
16347 
16348 
16349   process(manifest) {
16350     this.manifest = manifest;
16351     this.resources = Object.keys(manifest).map(function (key) {
16352       return manifest[key];
16353     });
16354     this.replacementUrls = [];
16355     this.html = [];
16356     this.assets = [];
16357     this.css = [];
16358     this.urls = [];
16359     this.cssUrls = [];
16360     this.split();
16361     this.splitUrls();
16362   }
16363   /**
16364    * Split resources by type
16365    * @private
16366    */
16367 
16368 
16369   split() {
16370     // HTML
16371     this.html = this.resources.filter(function (item) {
16372       if (item.type === "application/xhtml+xml" || item.type === "text/html") {
16373         return true;
16374       }
16375     }); // Exclude HTML
16376 
16377     this.assets = this.resources.filter(function (item) {
16378       if (item.type !== "application/xhtml+xml" && item.type !== "text/html") {
16379         return true;
16380       }
16381     }); // Only CSS
16382 
16383     this.css = this.resources.filter(function (item) {
16384       if (item.type === "text/css") {
16385         return true;
16386       }
16387     });
16388   }
16389   /**
16390    * Convert split resources into Urls
16391    * @private
16392    */
16393 
16394 
16395   splitUrls() {
16396     // All Assets Urls
16397     this.urls = this.assets.map(function (item) {
16398       return item.href;
16399     }.bind(this)); // Css Urls
16400 
16401     this.cssUrls = this.css.map(function (item) {
16402       return item.href;
16403     });
16404   }
16405   /**
16406    * Create a url to a resource
16407    * @param {string} url
16408    * @return {Promise<string>} Promise resolves with url string
16409    */
16410 
16411 
16412   createUrl(url) {
16413     var parsedUrl = new utils_url["a" /* default */](url);
16414     var mimeType = mime.lookup(parsedUrl.filename);
16415 
16416     if (this.settings.archive) {
16417       return this.settings.archive.createUrl(url, {
16418         "base64": this.settings.replacements === "base64"
16419       });
16420     } else {
16421       if (this.settings.replacements === "base64") {
16422         return this.settings.request(url, 'blob').then(blob => {
16423           return Object(core["blob2base64"])(blob);
16424         }).then(blob => {
16425           return Object(core["createBase64Url"])(blob, mimeType);
16426         });
16427       } else {
16428         return this.settings.request(url, 'blob').then(blob => {
16429           return Object(core["createBlobUrl"])(blob, mimeType);
16430         });
16431       }
16432     }
16433   }
16434   /**
16435    * Create blob urls for all the assets
16436    * @return {Promise}         returns replacement urls
16437    */
16438 
16439 
16440   replacements() {
16441     if (this.settings.replacements === "none") {
16442       return new Promise(function (resolve) {
16443         resolve(this.urls);
16444       }.bind(this));
16445     }
16446 
16447     var replacements = this.urls.map(url => {
16448       var absolute = this.settings.resolver(url);
16449       return this.createUrl(absolute).catch(err => {
16450         console.error(err);
16451         return null;
16452       });
16453     });
16454     return Promise.all(replacements).then(replacementUrls => {
16455       this.replacementUrls = replacementUrls.filter(url => {
16456         return typeof url === "string";
16457       });
16458       return replacementUrls;
16459     });
16460   }
16461   /**
16462    * Replace URLs in CSS resources
16463    * @private
16464    * @param  {Archive} [archive]
16465    * @param  {method} [resolver]
16466    * @return {Promise}
16467    */
16468 
16469 
16470   replaceCss(archive, resolver) {
16471     var replaced = [];
16472     archive = archive || this.settings.archive;
16473     resolver = resolver || this.settings.resolver;
16474     this.cssUrls.forEach(function (href) {
16475       var replacement = this.createCssFile(href, archive, resolver).then(function (replacementUrl) {
16476         // switch the url in the replacementUrls
16477         var indexInUrls = this.urls.indexOf(href);
16478 
16479         if (indexInUrls > -1) {
16480           this.replacementUrls[indexInUrls] = replacementUrl;
16481         }
16482       }.bind(this));
16483       replaced.push(replacement);
16484     }.bind(this));
16485     return Promise.all(replaced);
16486   }
16487   /**
16488    * Create a new CSS file with the replaced URLs
16489    * @private
16490    * @param  {string} href the original css file
16491    * @return {Promise}  returns a BlobUrl to the new CSS file or a data url
16492    */
16493 
16494 
16495   createCssFile(href) {
16496     var newUrl;
16497 
16498     if (path_default.a.isAbsolute(href)) {
16499       return new Promise(function (resolve) {
16500         resolve();
16501       });
16502     }
16503 
16504     var absolute = this.settings.resolver(href); // Get the text of the css file from the archive
16505 
16506     var textResponse;
16507 
16508     if (this.settings.archive) {
16509       textResponse = this.settings.archive.getText(absolute);
16510     } else {
16511       textResponse = this.settings.request(absolute, "text");
16512     } // Get asset links relative to css file
16513 
16514 
16515     var relUrls = this.urls.map(assetHref => {
16516       var resolved = this.settings.resolver(assetHref);
16517       var relative = new utils_path["a" /* default */](absolute).relative(resolved);
16518       return relative;
16519     });
16520 
16521     if (!textResponse) {
16522       // file not found, don't replace
16523       return new Promise(function (resolve) {
16524         resolve();
16525       });
16526     }
16527 
16528     return textResponse.then(text => {
16529       // Replacements in the css text
16530       text = Object(replacements["e" /* substitute */])(text, relUrls, this.replacementUrls); // Get the new url
16531 
16532       if (this.settings.replacements === "base64") {
16533         newUrl = Object(core["createBase64Url"])(text, "text/css");
16534       } else {
16535         newUrl = Object(core["createBlobUrl"])(text, "text/css");
16536       }
16537 
16538       return newUrl;
16539     }, err => {
16540       // handle response errors
16541       return new Promise(function (resolve) {
16542         resolve();
16543       });
16544     });
16545   }
16546   /**
16547    * Resolve all resources URLs relative to an absolute URL
16548    * @param  {string} absolute to be resolved to
16549    * @param  {resolver} [resolver]
16550    * @return {string[]} array with relative Urls
16551    */
16552 
16553 
16554   relativeTo(absolute, resolver) {
16555     resolver = resolver || this.settings.resolver; // Get Urls relative to current sections
16556 
16557     return this.urls.map(function (href) {
16558       var resolved = resolver(href);
16559       var relative = new utils_path["a" /* default */](absolute).relative(resolved);
16560       return relative;
16561     }.bind(this));
16562   }
16563   /**
16564    * Get a URL for a resource
16565    * @param  {string} path
16566    * @return {string} url
16567    */
16568 
16569 
16570   get(path) {
16571     var indexInUrls = this.urls.indexOf(path);
16572 
16573     if (indexInUrls === -1) {
16574       return;
16575     }
16576 
16577     if (this.replacementUrls.length) {
16578       return new Promise(function (resolve, reject) {
16579         resolve(this.replacementUrls[indexInUrls]);
16580       }.bind(this));
16581     } else {
16582       return this.createUrl(path);
16583     }
16584   }
16585   /**
16586    * Substitute urls in content, with replacements,
16587    * relative to a url if provided
16588    * @param  {string} content
16589    * @param  {string} [url]   url to resolve to
16590    * @return {string}         content with urls substituted
16591    */
16592 
16593 
16594   substitute(content, url) {
16595     var relUrls;
16596 
16597     if (url) {
16598       relUrls = this.relativeTo(url);
16599     } else {
16600       relUrls = this.urls;
16601     }
16602 
16603     return Object(replacements["e" /* substitute */])(content, relUrls, this.replacementUrls);
16604   }
16605 
16606   destroy() {
16607     this.settings = undefined;
16608     this.manifest = undefined;
16609     this.resources = undefined;
16610     this.replacementUrls = undefined;
16611     this.html = undefined;
16612     this.assets = undefined;
16613     this.css = undefined;
16614     this.urls = undefined;
16615     this.cssUrls = undefined;
16616   }
16617 
16618 }
16619 
16620 /* harmony default export */ var resources = (resources_Resources);
16621 // CONCATENATED MODULE: ./src/pagelist.js
16622 
16623 
16624 /**
16625  * Page List Parser
16626  * @param {document} [xml]
16627  */
16628 
16629 class pagelist_PageList {
16630   constructor(xml) {
16631     this.pages = [];
16632     this.locations = [];
16633     this.epubcfi = new epubcfi["a" /* default */]();
16634     this.firstPage = 0;
16635     this.lastPage = 0;
16636     this.totalPages = 0;
16637     this.toc = undefined;
16638     this.ncx = undefined;
16639 
16640     if (xml) {
16641       this.pageList = this.parse(xml);
16642     }
16643 
16644     if (this.pageList && this.pageList.length) {
16645       this.process(this.pageList);
16646     }
16647   }
16648   /**
16649    * Parse PageList Xml
16650    * @param  {document} xml
16651    */
16652 
16653 
16654   parse(xml) {
16655     var html = Object(core["qs"])(xml, "html");
16656     var ncx = Object(core["qs"])(xml, "ncx");
16657 
16658     if (html) {
16659       return this.parseNav(xml);
16660     } else if (ncx) {
16661       return this.parseNcx(xml);
16662     }
16663   }
16664   /**
16665    * Parse a Nav PageList
16666    * @private
16667    * @param  {node} navHtml
16668    * @return {PageList.item[]} list
16669    */
16670 
16671 
16672   parseNav(navHtml) {
16673     var navElement = Object(core["querySelectorByType"])(navHtml, "nav", "page-list");
16674     var navItems = navElement ? Object(core["qsa"])(navElement, "li") : [];
16675     var length = navItems.length;
16676     var i;
16677     var list = [];
16678     var item;
16679     if (!navItems || length === 0) return list;
16680 
16681     for (i = 0; i < length; ++i) {
16682       item = this.item(navItems[i]);
16683       list.push(item);
16684     }
16685 
16686     return list;
16687   }
16688 
16689   parseNcx(navXml) {
16690     var list = [];
16691     var i = 0;
16692     var item;
16693     var pageList;
16694     var pageTargets;
16695     var length = 0;
16696     pageList = Object(core["qs"])(navXml, "pageList");
16697     if (!pageList) return list;
16698     pageTargets = Object(core["qsa"])(pageList, "pageTarget");
16699     length = pageTargets.length;
16700 
16701     if (!pageTargets || pageTargets.length === 0) {
16702       return list;
16703     }
16704 
16705     for (i = 0; i < length; ++i) {
16706       item = this.ncxItem(pageTargets[i]);
16707       list.push(item);
16708     }
16709 
16710     return list;
16711   }
16712 
16713   ncxItem(item) {
16714     var navLabel = Object(core["qs"])(item, "navLabel");
16715     var navLabelText = Object(core["qs"])(navLabel, "text");
16716     var pageText = navLabelText.textContent;
16717     var content = Object(core["qs"])(item, "content");
16718     var href = content.getAttribute("src");
16719     var page = parseInt(pageText, 10);
16720     return {
16721       "href": href,
16722       "page": page
16723     };
16724   }
16725   /**
16726    * Page List Item
16727    * @private
16728    * @param  {node} item
16729    * @return {object} pageListItem
16730    */
16731 
16732 
16733   item(item) {
16734     var content = Object(core["qs"])(item, "a"),
16735         href = content.getAttribute("href") || "",
16736         text = content.textContent || "",
16737         page = parseInt(text),
16738         isCfi = href.indexOf("epubcfi"),
16739         split,
16740         packageUrl,
16741         cfi;
16742 
16743     if (isCfi != -1) {
16744       split = href.split("#");
16745       packageUrl = split[0];
16746       cfi = split.length > 1 ? split[1] : false;
16747       return {
16748         "cfi": cfi,
16749         "href": href,
16750         "packageUrl": packageUrl,
16751         "page": page
16752       };
16753     } else {
16754       return {
16755         "href": href,
16756         "page": page
16757       };
16758     }
16759   }
16760   /**
16761    * Process pageList items
16762    * @private
16763    * @param  {array} pageList
16764    */
16765 
16766 
16767   process(pageList) {
16768     pageList.forEach(function (item) {
16769       this.pages.push(item.page);
16770 
16771       if (item.cfi) {
16772         this.locations.push(item.cfi);
16773       }
16774     }, this);
16775     this.firstPage = parseInt(this.pages[0]);
16776     this.lastPage = parseInt(this.pages[this.pages.length - 1]);
16777     this.totalPages = this.lastPage - this.firstPage;
16778   }
16779   /**
16780    * Get a PageList result from a EpubCFI
16781    * @param  {string} cfi EpubCFI String
16782    * @return {number} page
16783    */
16784 
16785 
16786   pageFromCfi(cfi) {
16787     var pg = -1; // Check if the pageList has not been set yet
16788 
16789     if (this.locations.length === 0) {
16790       return -1;
16791     } // TODO: check if CFI is valid?
16792     // check if the cfi is in the location list
16793     // var index = this.locations.indexOf(cfi);
16794 
16795 
16796     var index = Object(core["indexOfSorted"])(cfi, this.locations, this.epubcfi.compare);
16797 
16798     if (index != -1) {
16799       pg = this.pages[index];
16800     } else {
16801       // Otherwise add it to the list of locations
16802       // Insert it in the correct position in the locations page
16803       //index = EPUBJS.core.insert(cfi, this.locations, this.epubcfi.compare);
16804       index = Object(core["locationOf"])(cfi, this.locations, this.epubcfi.compare); // Get the page at the location just before the new one, or return the first
16805 
16806       pg = index - 1 >= 0 ? this.pages[index - 1] : this.pages[0];
16807 
16808       if (pg !== undefined) {// Add the new page in so that the locations and page array match up
16809         //this.pages.splice(index, 0, pg);
16810       } else {
16811         pg = -1;
16812       }
16813     }
16814 
16815     return pg;
16816   }
16817   /**
16818    * Get an EpubCFI from a Page List Item
16819    * @param  {string | number} pg
16820    * @return {string} cfi
16821    */
16822 
16823 
16824   cfiFromPage(pg) {
16825     var cfi = -1; // check that pg is an int
16826 
16827     if (typeof pg != "number") {
16828       pg = parseInt(pg);
16829     } // check if the cfi is in the page list
16830     // Pages could be unsorted.
16831 
16832 
16833     var index = this.pages.indexOf(pg);
16834 
16835     if (index != -1) {
16836       cfi = this.locations[index];
16837     } // TODO: handle pages not in the list
16838 
16839 
16840     return cfi;
16841   }
16842   /**
16843    * Get a Page from Book percentage
16844    * @param  {number} percent
16845    * @return {number} page
16846    */
16847 
16848 
16849   pageFromPercentage(percent) {
16850     var pg = Math.round(this.totalPages * percent);
16851     return pg;
16852   }
16853   /**
16854    * Returns a value between 0 - 1 corresponding to the location of a page
16855    * @param  {number} pg the page
16856    * @return {number} percentage
16857    */
16858 
16859 
16860   percentageFromPage(pg) {
16861     var percentage = (pg - this.firstPage) / this.totalPages;
16862     return Math.round(percentage * 1000) / 1000;
16863   }
16864   /**
16865    * Returns a value between 0 - 1 corresponding to the location of a cfi
16866    * @param  {string} cfi EpubCFI String
16867    * @return {number} percentage
16868    */
16869 
16870 
16871   percentageFromCfi(cfi) {
16872     var pg = this.pageFromCfi(cfi);
16873     var percentage = this.percentageFromPage(pg);
16874     return percentage;
16875   }
16876   /**
16877    * Destroy
16878    */
16879 
16880 
16881   destroy() {
16882     this.pages = undefined;
16883     this.locations = undefined;
16884     this.epubcfi = undefined;
16885     this.pageList = undefined;
16886     this.toc = undefined;
16887     this.ncx = undefined;
16888   }
16889 
16890 }
16891 
16892 /* harmony default export */ var pagelist = (pagelist_PageList);
16893 // EXTERNAL MODULE: ./src/rendition.js + 3 modules
16894 var rendition = __webpack_require__(16);
16895 
16896 // EXTERNAL MODULE: external "JSZip"
16897 var external_JSZip_ = __webpack_require__(29);
16898 var external_JSZip_default = /*#__PURE__*/__webpack_require__.n(external_JSZip_);
16899 
16900 // CONCATENATED MODULE: ./src/archive.js
16901 
16902 
16903 
16904 
16905 
16906 /**
16907  * Handles Unzipping a requesting files from an Epub Archive
16908  * @class
16909  */
16910 
16911 class archive_Archive {
16912   constructor() {
16913     this.zip = undefined;
16914     this.urlCache = {};
16915     this.checkRequirements();
16916   }
16917   /**
16918    * Checks to see if JSZip exists in global namspace,
16919    * Requires JSZip if it isn't there
16920    * @private
16921    */
16922 
16923 
16924   checkRequirements() {
16925     try {
16926       this.zip = new external_JSZip_default.a();
16927     } catch (e) {
16928       throw new Error("JSZip lib not loaded");
16929     }
16930   }
16931   /**
16932    * Open an archive
16933    * @param  {binary} input
16934    * @param  {boolean} [isBase64] tells JSZip if the input data is base64 encoded
16935    * @return {Promise} zipfile
16936    */
16937 
16938 
16939   open(input, isBase64) {
16940     return this.zip.loadAsync(input, {
16941       "base64": isBase64
16942     });
16943   }
16944   /**
16945    * Load and Open an archive
16946    * @param  {string} zipUrl
16947    * @param  {boolean} [isBase64] tells JSZip if the input data is base64 encoded
16948    * @return {Promise} zipfile
16949    */
16950 
16951 
16952   openUrl(zipUrl, isBase64) {
16953     return utils_request(zipUrl, "binary").then(function (data) {
16954       return this.zip.loadAsync(data, {
16955         "base64": isBase64
16956       });
16957     }.bind(this));
16958   }
16959   /**
16960    * Request a url from the archive
16961    * @param  {string} url  a url to request from the archive
16962    * @param  {string} [type] specify the type of the returned result
16963    * @return {Promise<Blob | string | JSON | Document | XMLDocument>}
16964    */
16965 
16966 
16967   request(url, type) {
16968     var deferred = new core["defer"]();
16969     var response;
16970     var path = new utils_path["a" /* default */](url); // If type isn't set, determine it from the file extension
16971 
16972     if (!type) {
16973       type = path.extension;
16974     }
16975 
16976     if (type == "blob") {
16977       response = this.getBlob(url);
16978     } else {
16979       response = this.getText(url);
16980     }
16981 
16982     if (response) {
16983       response.then(function (r) {
16984         let result = this.handleResponse(r, type);
16985         deferred.resolve(result);
16986       }.bind(this));
16987     } else {
16988       deferred.reject({
16989         message: "File not found in the epub: " + url,
16990         stack: new Error().stack
16991       });
16992     }
16993 
16994     return deferred.promise;
16995   }
16996   /**
16997    * Handle the response from request
16998    * @private
16999    * @param  {any} response
17000    * @param  {string} [type]
17001    * @return {any} the parsed result
17002    */
17003 
17004 
17005   handleResponse(response, type) {
17006     var r;
17007 
17008     if (type == "json") {
17009       r = JSON.parse(response);
17010     } else if (Object(core["isXml"])(type)) {
17011       r = Object(core["parse"])(response, "text/xml");
17012     } else if (type == "xhtml") {
17013       r = Object(core["parse"])(response, "application/xhtml+xml");
17014     } else if (type == "html" || type == "htm") {
17015       r = Object(core["parse"])(response, "text/html");
17016     } else {
17017       r = response;
17018     }
17019 
17020     return r;
17021   }
17022   /**
17023    * Get a Blob from Archive by Url
17024    * @param  {string} url
17025    * @param  {string} [mimeType]
17026    * @return {Blob}
17027    */
17028 
17029 
17030   getBlob(url, mimeType) {
17031     var decodededUrl = window.decodeURIComponent(url.substr(1)); // Remove first slash
17032 
17033     var entry = this.zip.file(decodededUrl);
17034 
17035     if (entry) {
17036       mimeType = mimeType || mime.lookup(entry.name);
17037       return entry.async("uint8array").then(function (uint8array) {
17038         return new Blob([uint8array], {
17039           type: mimeType
17040         });
17041       });
17042     }
17043   }
17044   /**
17045    * Get Text from Archive by Url
17046    * @param  {string} url
17047    * @param  {string} [encoding]
17048    * @return {string}
17049    */
17050 
17051 
17052   getText(url, encoding) {
17053     var decodededUrl = window.decodeURIComponent(url.substr(1)); // Remove first slash
17054 
17055     var entry = this.zip.file(decodededUrl);
17056 
17057     if (entry) {
17058       return entry.async("string").then(function (text) {
17059         return text;
17060       });
17061     }
17062   }
17063   /**
17064    * Get a base64 encoded result from Archive by Url
17065    * @param  {string} url
17066    * @param  {string} [mimeType]
17067    * @return {string} base64 encoded
17068    */
17069 
17070 
17071   getBase64(url, mimeType) {
17072     var decodededUrl = window.decodeURIComponent(url.substr(1)); // Remove first slash
17073 
17074     var entry = this.zip.file(decodededUrl);
17075 
17076     if (entry) {
17077       mimeType = mimeType || mime.lookup(entry.name);
17078       return entry.async("base64").then(function (data) {
17079         return "data:" + mimeType + ";base64," + data;
17080       });
17081     }
17082   }
17083   /**
17084    * Create a Url from an unarchived item
17085    * @param  {string} url
17086    * @param  {object} [options.base64] use base64 encoding or blob url
17087    * @return {Promise} url promise with Url string
17088    */
17089 
17090 
17091   createUrl(url, options) {
17092     var deferred = new core["defer"]();
17093 
17094     var _URL = window.URL || window.webkitURL || window.mozURL;
17095 
17096     var tempUrl;
17097     var response;
17098     var useBase64 = options && options.base64;
17099 
17100     if (url in this.urlCache) {
17101       deferred.resolve(this.urlCache[url]);
17102       return deferred.promise;
17103     }
17104 
17105     if (useBase64) {
17106       response = this.getBase64(url);
17107 
17108       if (response) {
17109         response.then(function (tempUrl) {
17110           this.urlCache[url] = tempUrl;
17111           deferred.resolve(tempUrl);
17112         }.bind(this));
17113       }
17114     } else {
17115       response = this.getBlob(url);
17116 
17117       if (response) {
17118         response.then(function (blob) {
17119           tempUrl = _URL.createObjectURL(blob);
17120           this.urlCache[url] = tempUrl;
17121           deferred.resolve(tempUrl);
17122         }.bind(this));
17123       }
17124     }
17125 
17126     if (!response) {
17127       deferred.reject({
17128         message: "File not found in the epub: " + url,
17129         stack: new Error().stack
17130       });
17131     }
17132 
17133     return deferred.promise;
17134   }
17135   /**
17136    * Revoke Temp Url for a archive item
17137    * @param  {string} url url of the item in the archive
17138    */
17139 
17140 
17141   revokeUrl(url) {
17142     var _URL = window.URL || window.webkitURL || window.mozURL;
17143 
17144     var fromCache = this.urlCache[url];
17145     if (fromCache) _URL.revokeObjectURL(fromCache);
17146   }
17147 
17148   destroy() {
17149     var _URL = window.URL || window.webkitURL || window.mozURL;
17150 
17151     for (let fromCache in this.urlCache) {
17152       _URL.revokeObjectURL(fromCache);
17153     }
17154 
17155     this.zip = undefined;
17156     this.urlCache = {};
17157   }
17158 
17159 }
17160 
17161 /* harmony default export */ var archive = (archive_Archive);
17162 // EXTERNAL MODULE: ./node_modules/localforage/dist/localforage.js
17163 var localforage = __webpack_require__(23);
17164 var localforage_default = /*#__PURE__*/__webpack_require__.n(localforage);
17165 
17166 // CONCATENATED MODULE: ./src/store.js
17167 
17168 
17169 
17170 
17171 
17172 
17173 /**
17174  * Handles saving and requesting files from local storage
17175  * @class
17176  * @param {string} name This should be the name of the application for modals
17177  * @param {function} [requester]
17178  * @param {function} [resolver]
17179  */
17180 
17181 class store_Store {
17182   constructor(name, requester, resolver) {
17183     this.urlCache = {};
17184     this.storage = undefined;
17185     this.name = name;
17186     this.requester = requester || utils_request;
17187     this.resolver = resolver;
17188     this.online = true;
17189     this.checkRequirements();
17190     this.addListeners();
17191   }
17192   /**
17193    * Checks to see if localForage exists in global namspace,
17194    * Requires localForage if it isn't there
17195    * @private
17196    */
17197 
17198 
17199   checkRequirements() {
17200     try {
17201       let store;
17202 
17203       if (typeof localforage_default.a === "undefined") {
17204         store = localforage_default.a;
17205       }
17206 
17207       this.storage = store.createInstance({
17208         name: this.name
17209       });
17210     } catch (e) {
17211       throw new Error("localForage lib not loaded");
17212     }
17213   }
17214   /**
17215    * Add online and offline event listeners
17216    * @private
17217    */
17218 
17219 
17220   addListeners() {
17221     this._status = this.status.bind(this);
17222     window.addEventListener('online', this._status);
17223     window.addEventListener('offline', this._status);
17224   }
17225   /**
17226    * Remove online and offline event listeners
17227    * @private
17228    */
17229 
17230 
17231   removeListeners() {
17232     window.removeEventListener('online', this._status);
17233     window.removeEventListener('offline', this._status);
17234     this._status = undefined;
17235   }
17236   /**
17237    * Update the online / offline status
17238    * @private
17239    */
17240 
17241 
17242   status(event) {
17243     let online = navigator.onLine;
17244     this.online = online;
17245 
17246     if (online) {
17247       this.emit("online", this);
17248     } else {
17249       this.emit("offline", this);
17250     }
17251   }
17252   /**
17253    * Add all of a book resources to the store
17254    * @param  {Resources} resources  book resources
17255    * @param  {boolean} [force] force resaving resources
17256    * @return {Promise<object>} store objects
17257    */
17258 
17259 
17260   add(resources, force) {
17261     let mapped = resources.resources.map(item => {
17262       let {
17263         href
17264       } = item;
17265       let url = this.resolver(href);
17266       let encodedUrl = window.encodeURIComponent(url);
17267       return this.storage.getItem(encodedUrl).then(item => {
17268         if (!item || force) {
17269           return this.requester(url, "binary").then(data => {
17270             return this.storage.setItem(encodedUrl, data);
17271           });
17272         } else {
17273           return item;
17274         }
17275       });
17276     });
17277     return Promise.all(mapped);
17278   }
17279   /**
17280    * Put binary data from a url to storage
17281    * @param  {string} url  a url to request from storage
17282    * @param  {boolean} [withCredentials]
17283    * @param  {object} [headers]
17284    * @return {Promise<Blob>}
17285    */
17286 
17287 
17288   put(url, withCredentials, headers) {
17289     let encodedUrl = window.encodeURIComponent(url);
17290     return this.storage.getItem(encodedUrl).then(result => {
17291       if (!result) {
17292         return this.requester(url, "binary", withCredentials, headers).then(data => {
17293           return this.storage.setItem(encodedUrl, data);
17294         });
17295       }
17296 
17297       return result;
17298     });
17299   }
17300   /**
17301    * Request a url
17302    * @param  {string} url  a url to request from storage
17303    * @param  {string} [type] specify the type of the returned result
17304    * @param  {boolean} [withCredentials]
17305    * @param  {object} [headers]
17306    * @return {Promise<Blob | string | JSON | Document | XMLDocument>}
17307    */
17308 
17309 
17310   request(url, type, withCredentials, headers) {
17311     if (this.online) {
17312       // From network
17313       return this.requester(url, type, withCredentials, headers).then(data => {
17314         // save to store if not present
17315         this.put(url);
17316         return data;
17317       });
17318     } else {
17319       // From store
17320       return this.retrieve(url, type);
17321     }
17322   }
17323   /**
17324    * Request a url from storage
17325    * @param  {string} url  a url to request from storage
17326    * @param  {string} [type] specify the type of the returned result
17327    * @return {Promise<Blob | string | JSON | Document | XMLDocument>}
17328    */
17329 
17330 
17331   retrieve(url, type) {
17332     var deferred = new core["defer"]();
17333     var response;
17334     var path = new utils_path["a" /* default */](url); // If type isn't set, determine it from the file extension
17335 
17336     if (!type) {
17337       type = path.extension;
17338     }
17339 
17340     if (type == "blob") {
17341       response = this.getBlob(url);
17342     } else {
17343       response = this.getText(url);
17344     }
17345 
17346     return response.then(r => {
17347       var deferred = new core["defer"]();
17348       var result;
17349 
17350       if (r) {
17351         result = this.handleResponse(r, type);
17352         deferred.resolve(result);
17353       } else {
17354         deferred.reject({
17355           message: "File not found in storage: " + url,
17356           stack: new Error().stack
17357         });
17358       }
17359 
17360       return deferred.promise;
17361     });
17362   }
17363   /**
17364    * Handle the response from request
17365    * @private
17366    * @param  {any} response
17367    * @param  {string} [type]
17368    * @return {any} the parsed result
17369    */
17370 
17371 
17372   handleResponse(response, type) {
17373     var r;
17374 
17375     if (type == "json") {
17376       r = JSON.parse(response);
17377     } else if (Object(core["isXml"])(type)) {
17378       r = Object(core["parse"])(response, "text/xml");
17379     } else if (type == "xhtml") {
17380       r = Object(core["parse"])(response, "application/xhtml+xml");
17381     } else if (type == "html" || type == "htm") {
17382       r = Object(core["parse"])(response, "text/html");
17383     } else {
17384       r = response;
17385     }
17386 
17387     return r;
17388   }
17389   /**
17390    * Get a Blob from Storage by Url
17391    * @param  {string} url
17392    * @param  {string} [mimeType]
17393    * @return {Blob}
17394    */
17395 
17396 
17397   getBlob(url, mimeType) {
17398     let encodedUrl = window.encodeURIComponent(url);
17399     return this.storage.getItem(encodedUrl).then(function (uint8array) {
17400       if (!uint8array) return;
17401       mimeType = mimeType || mime.lookup(url);
17402       return new Blob([uint8array], {
17403         type: mimeType
17404       });
17405     });
17406   }
17407   /**
17408    * Get Text from Storage by Url
17409    * @param  {string} url
17410    * @param  {string} [mimeType]
17411    * @return {string}
17412    */
17413 
17414 
17415   getText(url, mimeType) {
17416     let encodedUrl = window.encodeURIComponent(url);
17417     mimeType = mimeType || mime.lookup(url);
17418     return this.storage.getItem(encodedUrl).then(function (uint8array) {
17419       var deferred = new core["defer"]();
17420       var reader = new FileReader();
17421       var blob;
17422       if (!uint8array) return;
17423       blob = new Blob([uint8array], {
17424         type: mimeType
17425       });
17426       reader.addEventListener("loadend", () => {
17427         deferred.resolve(reader.result);
17428       });
17429       reader.readAsText(blob, mimeType);
17430       return deferred.promise;
17431     });
17432   }
17433   /**
17434    * Get a base64 encoded result from Storage by Url
17435    * @param  {string} url
17436    * @param  {string} [mimeType]
17437    * @return {string} base64 encoded
17438    */
17439 
17440 
17441   getBase64(url, mimeType) {
17442     let encodedUrl = window.encodeURIComponent(url);
17443     mimeType = mimeType || mime.lookup(url);
17444     return this.storage.getItem(encodedUrl).then(uint8array => {
17445       var deferred = new core["defer"]();
17446       var reader = new FileReader();
17447       var blob;
17448       if (!uint8array) return;
17449       blob = new Blob([uint8array], {
17450         type: mimeType
17451       });
17452       reader.addEventListener("loadend", () => {
17453         deferred.resolve(reader.result);
17454       });
17455       reader.readAsDataURL(blob, mimeType);
17456       return deferred.promise;
17457     });
17458   }
17459   /**
17460    * Create a Url from a stored item
17461    * @param  {string} url
17462    * @param  {object} [options.base64] use base64 encoding or blob url
17463    * @return {Promise} url promise with Url string
17464    */
17465 
17466 
17467   createUrl(url, options) {
17468     var deferred = new core["defer"]();
17469 
17470     var _URL = window.URL || window.webkitURL || window.mozURL;
17471 
17472     var tempUrl;
17473     var response;
17474     var useBase64 = options && options.base64;
17475 
17476     if (url in this.urlCache) {
17477       deferred.resolve(this.urlCache[url]);
17478       return deferred.promise;
17479     }
17480 
17481     if (useBase64) {
17482       response = this.getBase64(url);
17483 
17484       if (response) {
17485         response.then(function (tempUrl) {
17486           this.urlCache[url] = tempUrl;
17487           deferred.resolve(tempUrl);
17488         }.bind(this));
17489       }
17490     } else {
17491       response = this.getBlob(url);
17492 
17493       if (response) {
17494         response.then(function (blob) {
17495           tempUrl = _URL.createObjectURL(blob);
17496           this.urlCache[url] = tempUrl;
17497           deferred.resolve(tempUrl);
17498         }.bind(this));
17499       }
17500     }
17501 
17502     if (!response) {
17503       deferred.reject({
17504         message: "File not found in storage: " + url,
17505         stack: new Error().stack
17506       });
17507     }
17508 
17509     return deferred.promise;
17510   }
17511   /**
17512    * Revoke Temp Url for a archive item
17513    * @param  {string} url url of the item in the store
17514    */
17515 
17516 
17517   revokeUrl(url) {
17518     var _URL = window.URL || window.webkitURL || window.mozURL;
17519 
17520     var fromCache = this.urlCache[url];
17521     if (fromCache) _URL.revokeObjectURL(fromCache);
17522   }
17523 
17524   destroy() {
17525     var _URL = window.URL || window.webkitURL || window.mozURL;
17526 
17527     for (let fromCache in this.urlCache) {
17528       _URL.revokeObjectURL(fromCache);
17529     }
17530 
17531     this.urlCache = {};
17532     this.removeListeners();
17533   }
17534 
17535 }
17536 
17537 event_emitter_default()(store_Store.prototype);
17538 /* harmony default export */ var src_store = (store_Store);
17539 // CONCATENATED MODULE: ./src/displayoptions.js
17540 
17541 /**
17542  * Open DisplayOptions Format Parser
17543  * @class
17544  * @param {document} displayOptionsDocument XML
17545  */
17546 
17547 class displayoptions_DisplayOptions {
17548   constructor(displayOptionsDocument) {
17549     this.interactive = "";
17550     this.fixedLayout = "";
17551     this.openToSpread = "";
17552     this.orientationLock = "";
17553 
17554     if (displayOptionsDocument) {
17555       this.parse(displayOptionsDocument);
17556     }
17557   }
17558   /**
17559    * Parse XML
17560    * @param  {document} displayOptionsDocument XML
17561    * @return {DisplayOptions} self
17562    */
17563 
17564 
17565   parse(displayOptionsDocument) {
17566     if (!displayOptionsDocument) {
17567       return this;
17568     }
17569 
17570     const displayOptionsNode = Object(core["qs"])(displayOptionsDocument, "display_options");
17571 
17572     if (!displayOptionsNode) {
17573       return this;
17574     }
17575 
17576     const options = Object(core["qsa"])(displayOptionsNode, "option");
17577     options.forEach(el => {
17578       let value = "";
17579 
17580       if (el.childNodes.length) {
17581         value = el.childNodes[0].nodeValue;
17582       }
17583 
17584       switch (el.attributes.name.value) {
17585         case "interactive":
17586           this.interactive = value;
17587           break;
17588 
17589         case "fixed-layout":
17590           this.fixedLayout = value;
17591           break;
17592 
17593         case "open-to-spread":
17594           this.openToSpread = value;
17595           break;
17596 
17597         case "orientation-lock":
17598           this.orientationLock = value;
17599           break;
17600       }
17601     });
17602     return this;
17603   }
17604 
17605   destroy() {
17606     this.interactive = undefined;
17607     this.fixedLayout = undefined;
17608     this.openToSpread = undefined;
17609     this.orientationLock = undefined;
17610   }
17611 
17612 }
17613 
17614 /* harmony default export */ var displayoptions = (displayoptions_DisplayOptions);
17615 // CONCATENATED MODULE: ./src/book.js
17616 
17617 
17618 
17619 
17620 
17621 
17622 
17623 
17624 
17625 
17626 
17627 
17628 
17629 
17630 
17631 
17632 
17633 
17634 const CONTAINER_PATH = "META-INF/container.xml";
17635 const IBOOKS_DISPLAY_OPTIONS_PATH = "META-INF/com.apple.ibooks.display-options.xml";
17636 const INPUT_TYPE = {
17637   BINARY: "binary",
17638   BASE64: "base64",
17639   EPUB: "epub",
17640   OPF: "opf",
17641   MANIFEST: "json",
17642   DIRECTORY: "directory"
17643 };
17644 /**
17645  * An Epub representation with methods for the loading, parsing and manipulation
17646  * of its contents.
17647  * @class
17648  * @param {string} [url]
17649  * @param {object} [options]
17650  * @param {method} [options.requestMethod] a request function to use instead of the default
17651  * @param {boolean} [options.requestCredentials=undefined] send the xhr request withCredentials
17652  * @param {object} [options.requestHeaders=undefined] send the xhr request headers
17653  * @param {string} [options.encoding=binary] optional to pass 'binary' or base64' for archived Epubs
17654  * @param {string} [options.replacements=none] use base64, blobUrl, or none for replacing assets in archived Epubs
17655  * @param {method} [options.canonical] optional function to determine canonical urls for a path
17656  * @param {string} [options.openAs] optional string to determine the input type
17657  * @param {string} [options.store=false] cache the contents in local storage, value should be the name of the reader
17658  * @returns {Book}
17659  * @example new Book("/path/to/book.epub", {})
17660  * @example new Book({ replacements: "blobUrl" })
17661  */
17662 
17663 class book_Book {
17664   constructor(url, options) {
17665     // Allow passing just options to the Book
17666     if (typeof options === "undefined" && typeof url !== "string" && url instanceof Blob === false && url instanceof ArrayBuffer === false) {
17667       options = url;
17668       url = undefined;
17669     }
17670 
17671     this.settings = Object(core["extend"])(this.settings || {}, {
17672       requestMethod: undefined,
17673       requestCredentials: undefined,
17674       requestHeaders: undefined,
17675       encoding: undefined,
17676       replacements: undefined,
17677       canonical: undefined,
17678       openAs: undefined,
17679       store: undefined
17680     });
17681     Object(core["extend"])(this.settings, options); // Promises
17682 
17683     this.opening = new core["defer"]();
17684     /**
17685      * @member {promise} opened returns after the book is loaded
17686      * @memberof Book
17687      */
17688 
17689     this.opened = this.opening.promise;
17690     this.isOpen = false;
17691     this.loading = {
17692       manifest: new core["defer"](),
17693       spine: new core["defer"](),
17694       metadata: new core["defer"](),
17695       cover: new core["defer"](),
17696       navigation: new core["defer"](),
17697       pageList: new core["defer"](),
17698       resources: new core["defer"](),
17699       displayOptions: new core["defer"]()
17700     };
17701     this.loaded = {
17702       manifest: this.loading.manifest.promise,
17703       spine: this.loading.spine.promise,
17704       metadata: this.loading.metadata.promise,
17705       cover: this.loading.cover.promise,
17706       navigation: this.loading.navigation.promise,
17707       pageList: this.loading.pageList.promise,
17708       resources: this.loading.resources.promise,
17709       displayOptions: this.loading.displayOptions.promise
17710     };
17711     /**
17712      * @member {promise} ready returns after the book is loaded and parsed
17713      * @memberof Book
17714      * @private
17715      */
17716 
17717     this.ready = Promise.all([this.loaded.manifest, this.loaded.spine, this.loaded.metadata, this.loaded.cover, this.loaded.navigation, this.loaded.resources, this.loaded.displayOptions]); // Queue for methods used before opening
17718 
17719     this.isRendered = false; // this._q = queue(this);
17720 
17721     /**
17722      * @member {method} request
17723      * @memberof Book
17724      * @private
17725      */
17726 
17727     this.request = this.settings.requestMethod || utils_request;
17728     /**
17729      * @member {Spine} spine
17730      * @memberof Book
17731      */
17732 
17733     this.spine = new src_spine();
17734     /**
17735      * @member {Locations} locations
17736      * @memberof Book
17737      */
17738 
17739     this.locations = new src_locations(this.spine, this.load.bind(this));
17740     /**
17741      * @member {Navigation} navigation
17742      * @memberof Book
17743      */
17744 
17745     this.navigation = undefined;
17746     /**
17747      * @member {PageList} pagelist
17748      * @memberof Book
17749      */
17750 
17751     this.pageList = undefined;
17752     /**
17753      * @member {Url} url
17754      * @memberof Book
17755      * @private
17756      */
17757 
17758     this.url = undefined;
17759     /**
17760      * @member {Path} path
17761      * @memberof Book
17762      * @private
17763      */
17764 
17765     this.path = undefined;
17766     /**
17767      * @member {boolean} archived
17768      * @memberof Book
17769      * @private
17770      */
17771 
17772     this.archived = false;
17773     /**
17774      * @member {Archive} archive
17775      * @memberof Book
17776      * @private
17777      */
17778 
17779     this.archive = undefined;
17780     /**
17781      * @member {Store} storage
17782      * @memberof Book
17783      * @private
17784      */
17785 
17786     this.storage = undefined;
17787     /**
17788      * @member {Resources} resources
17789      * @memberof Book
17790      * @private
17791      */
17792 
17793     this.resources = undefined;
17794     /**
17795      * @member {Rendition} rendition
17796      * @memberof Book
17797      * @private
17798      */
17799 
17800     this.rendition = undefined;
17801     /**
17802      * @member {Container} container
17803      * @memberof Book
17804      * @private
17805      */
17806 
17807     this.container = undefined;
17808     /**
17809      * @member {Packaging} packaging
17810      * @memberof Book
17811      * @private
17812      */
17813 
17814     this.packaging = undefined;
17815     /**
17816      * @member {DisplayOptions} displayOptions
17817      * @memberof DisplayOptions
17818      * @private
17819      */
17820 
17821     this.displayOptions = undefined; // this.toc = undefined;
17822 
17823     if (this.settings.store) {
17824       this.store(this.settings.store);
17825     }
17826 
17827     if (url) {
17828       this.open(url, this.settings.openAs).catch(error => {
17829         var err = new Error("Cannot load book at " + url);
17830         this.emit(constants["c" /* EVENTS */].BOOK.OPEN_FAILED, err);
17831       });
17832     }
17833   }
17834   /**
17835    * Open a epub or url
17836    * @param {string | ArrayBuffer} input Url, Path or ArrayBuffer
17837    * @param {string} [what="binary", "base64", "epub", "opf", "json", "directory"] force opening as a certain type
17838    * @returns {Promise} of when the book has been loaded
17839    * @example book.open("/path/to/book.epub")
17840    */
17841 
17842 
17843   open(input, what) {
17844     var opening;
17845     var type = what || this.determineType(input);
17846 
17847     if (type === INPUT_TYPE.BINARY) {
17848       this.archived = true;
17849       this.url = new utils_url["a" /* default */]("/", "");
17850       opening = this.openEpub(input);
17851     } else if (type === INPUT_TYPE.BASE64) {
17852       this.archived = true;
17853       this.url = new utils_url["a" /* default */]("/", "");
17854       opening = this.openEpub(input, type);
17855     } else if (type === INPUT_TYPE.EPUB) {
17856       this.archived = true;
17857       this.url = new utils_url["a" /* default */]("/", "");
17858       opening = this.request(input, "binary", this.settings.requestCredentials, this.settings.requestHeaders).then(this.openEpub.bind(this));
17859     } else if (type == INPUT_TYPE.OPF) {
17860       this.url = new utils_url["a" /* default */](input);
17861       opening = this.openPackaging(this.url.Path.toString());
17862     } else if (type == INPUT_TYPE.MANIFEST) {
17863       this.url = new utils_url["a" /* default */](input);
17864       opening = this.openManifest(this.url.Path.toString());
17865     } else {
17866       this.url = new utils_url["a" /* default */](input);
17867       opening = this.openContainer(CONTAINER_PATH).then(this.openPackaging.bind(this));
17868     }
17869 
17870     return opening;
17871   }
17872   /**
17873    * Open an archived epub
17874    * @private
17875    * @param  {binary} data
17876    * @param  {string} [encoding]
17877    * @return {Promise}
17878    */
17879 
17880 
17881   openEpub(data, encoding) {
17882     return this.unarchive(data, encoding || this.settings.encoding).then(() => {
17883       return this.openContainer(CONTAINER_PATH);
17884     }).then(packagePath => {
17885       return this.openPackaging(packagePath);
17886     });
17887   }
17888   /**
17889    * Open the epub container
17890    * @private
17891    * @param  {string} url
17892    * @return {string} packagePath
17893    */
17894 
17895 
17896   openContainer(url) {
17897     return this.load(url).then(xml => {
17898       this.container = new container(xml);
17899       return this.resolve(this.container.packagePath);
17900     });
17901   }
17902   /**
17903    * Open the Open Packaging Format Xml
17904    * @private
17905    * @param  {string} url
17906    * @return {Promise}
17907    */
17908 
17909 
17910   openPackaging(url) {
17911     this.path = new utils_path["a" /* default */](url);
17912     return this.load(url).then(xml => {
17913       this.packaging = new src_packaging(xml);
17914       return this.unpack(this.packaging);
17915     });
17916   }
17917   /**
17918    * Open the manifest JSON
17919    * @private
17920    * @param  {string} url
17921    * @return {Promise}
17922    */
17923 
17924 
17925   openManifest(url) {
17926     this.path = new utils_path["a" /* default */](url);
17927     return this.load(url).then(json => {
17928       this.packaging = new src_packaging();
17929       this.packaging.load(json);
17930       return this.unpack(this.packaging);
17931     });
17932   }
17933   /**
17934    * Load a resource from the Book
17935    * @param  {string} path path to the resource to load
17936    * @return {Promise}     returns a promise with the requested resource
17937    */
17938 
17939 
17940   load(path) {
17941     var resolved = this.resolve(path);
17942 
17943     if (this.archived) {
17944       return this.archive.request(resolved);
17945     } else {
17946       return this.request(resolved, null, this.settings.requestCredentials, this.settings.requestHeaders);
17947     }
17948   }
17949   /**
17950    * Resolve a path to it's absolute position in the Book
17951    * @param  {string} path
17952    * @param  {boolean} [absolute] force resolving the full URL
17953    * @return {string}          the resolved path string
17954    */
17955 
17956 
17957   resolve(path, absolute) {
17958     if (!path) {
17959       return;
17960     }
17961 
17962     var resolved = path;
17963     var isAbsolute = path.indexOf("://") > -1;
17964 
17965     if (isAbsolute) {
17966       return path;
17967     }
17968 
17969     if (this.path) {
17970       resolved = this.path.resolve(path);
17971     }
17972 
17973     if (absolute != false && this.url) {
17974       resolved = this.url.resolve(resolved);
17975     }
17976 
17977     return resolved;
17978   }
17979   /**
17980    * Get a canonical link to a path
17981    * @param  {string} path
17982    * @return {string} the canonical path string
17983    */
17984 
17985 
17986   canonical(path) {
17987     var url = path;
17988 
17989     if (!path) {
17990       return "";
17991     }
17992 
17993     if (this.settings.canonical) {
17994       url = this.settings.canonical(path);
17995     } else {
17996       url = this.resolve(path, true);
17997     }
17998 
17999     return url;
18000   }
18001   /**
18002    * Determine the type of they input passed to open
18003    * @private
18004    * @param  {string} input
18005    * @return {string}  binary | directory | epub | opf
18006    */
18007 
18008 
18009   determineType(input) {
18010     var url;
18011     var path;
18012     var extension;
18013 
18014     if (this.settings.encoding === "base64") {
18015       return INPUT_TYPE.BASE64;
18016     }
18017 
18018     if (typeof input != "string") {
18019       return INPUT_TYPE.BINARY;
18020     }
18021 
18022     url = new utils_url["a" /* default */](input);
18023     path = url.path();
18024     extension = path.extension; // If there's a search string, remove it before determining type
18025 
18026     if (extension) {
18027       extension = extension.replace(/\?.*$/, "");
18028     }
18029 
18030     if (!extension) {
18031       return INPUT_TYPE.DIRECTORY;
18032     }
18033 
18034     if (extension === "epub") {
18035       return INPUT_TYPE.EPUB;
18036     }
18037 
18038     if (extension === "opf") {
18039       return INPUT_TYPE.OPF;
18040     }
18041 
18042     if (extension === "json") {
18043       return INPUT_TYPE.MANIFEST;
18044     }
18045   }
18046   /**
18047    * unpack the contents of the Books packaging
18048    * @private
18049    * @param {Packaging} packaging object
18050    */
18051 
18052 
18053   unpack(packaging) {
18054     this.package = packaging; //TODO: deprecated this
18055 
18056     if (this.packaging.metadata.layout === "") {
18057       // rendition:layout not set - check display options if book is pre-paginated
18058       this.load(this.url.resolve(IBOOKS_DISPLAY_OPTIONS_PATH)).then(xml => {
18059         this.displayOptions = new displayoptions(xml);
18060         this.loading.displayOptions.resolve(this.displayOptions);
18061       }).catch(err => {
18062         this.displayOptions = new displayoptions();
18063         this.loading.displayOptions.resolve(this.displayOptions);
18064       });
18065     } else {
18066       this.displayOptions = new displayoptions();
18067       this.loading.displayOptions.resolve(this.displayOptions);
18068     }
18069 
18070     this.spine.unpack(this.packaging, this.resolve.bind(this), this.canonical.bind(this));
18071     this.resources = new resources(this.packaging.manifest, {
18072       archive: this.archive,
18073       resolver: this.resolve.bind(this),
18074       request: this.request.bind(this),
18075       replacements: this.settings.replacements || (this.archived ? "blobUrl" : "base64")
18076     });
18077     this.loadNavigation(this.packaging).then(() => {
18078       // this.toc = this.navigation.toc;
18079       this.loading.navigation.resolve(this.navigation);
18080     });
18081 
18082     if (this.packaging.coverPath) {
18083       this.cover = this.resolve(this.packaging.coverPath);
18084     } // Resolve promises
18085 
18086 
18087     this.loading.manifest.resolve(this.packaging.manifest);
18088     this.loading.metadata.resolve(this.packaging.metadata);
18089     this.loading.spine.resolve(this.spine);
18090     this.loading.cover.resolve(this.cover);
18091     this.loading.resources.resolve(this.resources);
18092     this.loading.pageList.resolve(this.pageList);
18093     this.isOpen = true;
18094 
18095     if (this.archived || this.settings.replacements && this.settings.replacements != "none") {
18096       this.replacements().then(() => {
18097         this.loaded.displayOptions.then(() => {
18098           this.opening.resolve(this);
18099         });
18100       }).catch(err => {
18101         console.error(err);
18102       });
18103     } else {
18104       // Resolve book opened promise
18105       this.loaded.displayOptions.then(() => {
18106         this.opening.resolve(this);
18107       });
18108     }
18109   }
18110   /**
18111    * Load Navigation and PageList from package
18112    * @private
18113    * @param {Packaging} packaging
18114    */
18115 
18116 
18117   loadNavigation(packaging) {
18118     let navPath = packaging.navPath || packaging.ncxPath;
18119     let toc = packaging.toc; // From json manifest
18120 
18121     if (toc) {
18122       return new Promise((resolve, reject) => {
18123         this.navigation = new navigation(toc);
18124 
18125         if (packaging.pageList) {
18126           this.pageList = new pagelist(packaging.pageList); // TODO: handle page lists from Manifest
18127         }
18128 
18129         resolve(this.navigation);
18130       });
18131     }
18132 
18133     if (!navPath) {
18134       return new Promise((resolve, reject) => {
18135         this.navigation = new navigation();
18136         this.pageList = new pagelist();
18137         resolve(this.navigation);
18138       });
18139     }
18140 
18141     return this.load(navPath, "xml").then(xml => {
18142       this.navigation = new navigation(xml);
18143       this.pageList = new pagelist(xml);
18144       return this.navigation;
18145     });
18146   }
18147   /**
18148    * Gets a Section of the Book from the Spine
18149    * Alias for `book.spine.get`
18150    * @param {string} target
18151    * @return {Section}
18152    */
18153 
18154 
18155   section(target) {
18156     return this.spine.get(target);
18157   }
18158   /**
18159    * Sugar to render a book to an element
18160    * @param  {element | string} element element or string to add a rendition to
18161    * @param  {object} [options]
18162    * @return {Rendition}
18163    */
18164 
18165 
18166   renderTo(element, options) {
18167     this.rendition = new rendition["a" /* default */](this, options);
18168     this.rendition.attachTo(element);
18169     return this.rendition;
18170   }
18171   /**
18172    * Set if request should use withCredentials
18173    * @param {boolean} credentials
18174    */
18175 
18176 
18177   setRequestCredentials(credentials) {
18178     this.settings.requestCredentials = credentials;
18179   }
18180   /**
18181    * Set headers request should use
18182    * @param {object} headers
18183    */
18184 
18185 
18186   setRequestHeaders(headers) {
18187     this.settings.requestHeaders = headers;
18188   }
18189   /**
18190    * Unarchive a zipped epub
18191    * @private
18192    * @param  {binary} input epub data
18193    * @param  {string} [encoding]
18194    * @return {Archive}
18195    */
18196 
18197 
18198   unarchive(input, encoding) {
18199     this.archive = new archive();
18200     return this.archive.open(input, encoding);
18201   }
18202   /**
18203    * Store the epubs contents
18204    * @private
18205    * @param  {binary} input epub data
18206    * @param  {string} [encoding]
18207    * @return {Store}
18208    */
18209 
18210 
18211   store(name) {
18212     // Use "blobUrl" or "base64" for replacements
18213     let replacementsSetting = this.settings.replacements && this.settings.replacements !== "none"; // Save original url
18214 
18215     let originalUrl = this.url; // Save original request method
18216 
18217     let requester = this.settings.requestMethod || utils_request.bind(this); // Create new Store
18218 
18219     this.storage = new src_store(name, requester, this.resolve.bind(this)); // Replace request method to go through store
18220 
18221     this.request = this.storage.request.bind(this.storage);
18222     this.opened.then(() => {
18223       if (this.archived) {
18224         this.storage.requester = this.archive.request.bind(this.archive);
18225       } // Substitute hook
18226 
18227 
18228       let substituteResources = (output, section) => {
18229         section.output = this.resources.substitute(output, section.url);
18230       }; // Set to use replacements
18231 
18232 
18233       this.resources.settings.replacements = replacementsSetting || "blobUrl"; // Create replacement urls
18234 
18235       this.resources.replacements().then(() => {
18236         return this.resources.replaceCss();
18237       });
18238       this.storage.on("offline", () => {
18239         // Remove url to use relative resolving for hrefs
18240         this.url = new utils_url["a" /* default */]("/", ""); // Add hook to replace resources in contents
18241 
18242         this.spine.hooks.serialize.register(substituteResources);
18243       });
18244       this.storage.on("online", () => {
18245         // Restore original url
18246         this.url = originalUrl; // Remove hook
18247 
18248         this.spine.hooks.serialize.deregister(substituteResources);
18249       });
18250     });
18251     return this.storage;
18252   }
18253   /**
18254    * Get the cover url
18255    * @return {Promise<?string>} coverUrl
18256    */
18257 
18258 
18259   coverUrl() {
18260     return this.loaded.cover.then(() => {
18261       if (!this.cover) {
18262         return null;
18263       }
18264 
18265       if (this.archived) {
18266         return this.archive.createUrl(this.cover);
18267       } else {
18268         return this.cover;
18269       }
18270     });
18271   }
18272   /**
18273    * Load replacement urls
18274    * @private
18275    * @return {Promise} completed loading urls
18276    */
18277 
18278 
18279   replacements() {
18280     this.spine.hooks.serialize.register((output, section) => {
18281       section.output = this.resources.substitute(output, section.url);
18282     });
18283     return this.resources.replacements().then(() => {
18284       return this.resources.replaceCss();
18285     });
18286   }
18287   /**
18288    * Find a DOM Range for a given CFI Range
18289    * @param  {EpubCFI} cfiRange a epub cfi range
18290    * @return {Promise}
18291    */
18292 
18293 
18294   getRange(cfiRange) {
18295     var cfi = new epubcfi["a" /* default */](cfiRange);
18296     var item = this.spine.get(cfi.spinePos);
18297 
18298     var _request = this.load.bind(this);
18299 
18300     if (!item) {
18301       return new Promise((resolve, reject) => {
18302         reject("CFI could not be found");
18303       });
18304     }
18305 
18306     return item.load(_request).then(function (contents) {
18307       var range = cfi.toRange(item.document);
18308       return range;
18309     });
18310   }
18311   /**
18312    * Generates the Book Key using the identifier in the manifest or other string provided
18313    * @param  {string} [identifier] to use instead of metadata identifier
18314    * @return {string} key
18315    */
18316 
18317 
18318   key(identifier) {
18319     var ident = identifier || this.packaging.metadata.identifier || this.url.filename;
18320     return `epubjs:${constants["b" /* EPUBJS_VERSION */]}:${ident}`;
18321   }
18322   /**
18323    * Destroy the Book and all associated objects
18324    */
18325 
18326 
18327   destroy() {
18328     this.opened = undefined;
18329     this.loading = undefined;
18330     this.loaded = undefined;
18331     this.ready = undefined;
18332     this.isOpen = false;
18333     this.isRendered = false;
18334     this.spine && this.spine.destroy();
18335     this.locations && this.locations.destroy();
18336     this.pageList && this.pageList.destroy();
18337     this.archive && this.archive.destroy();
18338     this.resources && this.resources.destroy();
18339     this.container && this.container.destroy();
18340     this.packaging && this.packaging.destroy();
18341     this.rendition && this.rendition.destroy();
18342     this.displayOptions && this.displayOptions.destroy();
18343     this.spine = undefined;
18344     this.locations = undefined;
18345     this.pageList = undefined;
18346     this.archive = undefined;
18347     this.resources = undefined;
18348     this.container = undefined;
18349     this.packaging = undefined;
18350     this.rendition = undefined;
18351     this.navigation = undefined;
18352     this.url = undefined;
18353     this.path = undefined;
18354     this.archived = false;
18355   }
18356 
18357 } //-- Enable binding events to book
18358 
18359 
18360 event_emitter_default()(book_Book.prototype);
18361 /* harmony default export */ var book = __webpack_exports__["a"] = (book_Book);
18362 
18363 /***/ }),
18364 /* 25 */
18365 /***/ (function(module, exports, __webpack_require__) {
18366 
18367 var conventions = __webpack_require__(14);
18368 
18369 var NAMESPACE = conventions.NAMESPACE;
18370 
18371 /**
18372  * A prerequisite for `[].filter`, to drop elements that are empty
18373  * @param {string} input
18374  * @returns {boolean}
18375  */
18376 function notEmptyString (input) {
18377         return input !== ''
18378 }
18379 /**
18380  * @see https://infra.spec.whatwg.org/#split-on-ascii-whitespace
18381  * @see https://infra.spec.whatwg.org/#ascii-whitespace
18382  *
18383  * @param {string} input
18384  * @returns {string[]} (can be empty)
18385  */
18386 function splitOnASCIIWhitespace(input) {
18387         // U+0009 TAB, U+000A LF, U+000C FF, U+000D CR, U+0020 SPACE
18388         return input ? input.split(/[\t\n\f\r ]+/).filter(notEmptyString) : []
18389 }
18390 
18391 /**
18392  * Adds element as a key to current if it is not already present.
18393  *
18394  * @param {Record<string, boolean | undefined>} current
18395  * @param {string} element
18396  * @returns {Record<string, boolean | undefined>}
18397  */
18398 function orderedSetReducer (current, element) {
18399         if (!current.hasOwnProperty(element)) {
18400                 current[element] = true;
18401         }
18402         return current;
18403 }
18404 
18405 /**
18406  * @see https://infra.spec.whatwg.org/#ordered-set
18407  * @param {string} input
18408  * @returns {string[]}
18409  */
18410 function toOrderedSet(input) {
18411         if (!input) return [];
18412         var list = splitOnASCIIWhitespace(input);
18413         return Object.keys(list.reduce(orderedSetReducer, {}))
18414 }
18415 
18416 /**
18417  * Uses `list.indexOf` to implement something like `Array.prototype.includes`,
18418  * which we can not rely on being available.
18419  *
18420  * @param {any[]} list
18421  * @returns {function(any): boolean}
18422  */
18423 function arrayIncludes (list) {
18424         return function(element) {
18425                 return list && list.indexOf(element) !== -1;
18426         }
18427 }
18428 
18429 function copy(src,dest){
18430         for(var p in src){
18431                 dest[p] = src[p];
18432         }
18433 }
18434 
18435 /**
18436 ^\w+\.prototype\.([_\w]+)\s*=\s*((?:.*\{\s*?[\r\n][\s\S]*?^})|\S.*?(?=[;\r\n]));?
18437 ^\w+\.prototype\.([_\w]+)\s*=\s*(\S.*?(?=[;\r\n]));?
18438  */
18439 function _extends(Class,Super){
18440         var pt = Class.prototype;
18441         if(!(pt instanceof Super)){
18442                 function t(){};
18443                 t.prototype = Super.prototype;
18444                 t = new t();
18445                 copy(pt,t);
18446                 Class.prototype = pt = t;
18447         }
18448         if(pt.constructor != Class){
18449                 if(typeof Class != 'function'){
18450                         console.error("unknown Class:"+Class)
18451                 }
18452                 pt.constructor = Class
18453         }
18454 }
18455 
18456 // Node Types
18457 var NodeType = {}
18458 var ELEMENT_NODE                = NodeType.ELEMENT_NODE                = 1;
18459 var ATTRIBUTE_NODE              = NodeType.ATTRIBUTE_NODE              = 2;
18460 var TEXT_NODE                   = NodeType.TEXT_NODE                   = 3;
18461 var CDATA_SECTION_NODE          = NodeType.CDATA_SECTION_NODE          = 4;
18462 var ENTITY_REFERENCE_NODE       = NodeType.ENTITY_REFERENCE_NODE       = 5;
18463 var ENTITY_NODE                 = NodeType.ENTITY_NODE                 = 6;
18464 var PROCESSING_INSTRUCTION_NODE = NodeType.PROCESSING_INSTRUCTION_NODE = 7;
18465 var COMMENT_NODE                = NodeType.COMMENT_NODE                = 8;
18466 var DOCUMENT_NODE               = NodeType.DOCUMENT_NODE               = 9;
18467 var DOCUMENT_TYPE_NODE          = NodeType.DOCUMENT_TYPE_NODE          = 10;
18468 var DOCUMENT_FRAGMENT_NODE      = NodeType.DOCUMENT_FRAGMENT_NODE      = 11;
18469 var NOTATION_NODE               = NodeType.NOTATION_NODE               = 12;
18470 
18471 // ExceptionCode
18472 var ExceptionCode = {}
18473 var ExceptionMessage = {};
18474 var INDEX_SIZE_ERR              = ExceptionCode.INDEX_SIZE_ERR              = ((ExceptionMessage[1]="Index size error"),1);
18475 var DOMSTRING_SIZE_ERR          = ExceptionCode.DOMSTRING_SIZE_ERR          = ((ExceptionMessage[2]="DOMString size error"),2);
18476 var HIERARCHY_REQUEST_ERR       = ExceptionCode.HIERARCHY_REQUEST_ERR       = ((ExceptionMessage[3]="Hierarchy request error"),3);
18477 var WRONG_DOCUMENT_ERR          = ExceptionCode.WRONG_DOCUMENT_ERR          = ((ExceptionMessage[4]="Wrong document"),4);
18478 var INVALID_CHARACTER_ERR       = ExceptionCode.INVALID_CHARACTER_ERR       = ((ExceptionMessage[5]="Invalid character"),5);
18479 var NO_DATA_ALLOWED_ERR         = ExceptionCode.NO_DATA_ALLOWED_ERR         = ((ExceptionMessage[6]="No data allowed"),6);
18480 var NO_MODIFICATION_ALLOWED_ERR = ExceptionCode.NO_MODIFICATION_ALLOWED_ERR = ((ExceptionMessage[7]="No modification allowed"),7);
18481 var NOT_FOUND_ERR               = ExceptionCode.NOT_FOUND_ERR               = ((ExceptionMessage[8]="Not found"),8);
18482 var NOT_SUPPORTED_ERR           = ExceptionCode.NOT_SUPPORTED_ERR           = ((ExceptionMessage[9]="Not supported"),9);
18483 var INUSE_ATTRIBUTE_ERR         = ExceptionCode.INUSE_ATTRIBUTE_ERR         = ((ExceptionMessage[10]="Attribute in use"),10);
18484 //level2
18485 var INVALID_STATE_ERR           = ExceptionCode.INVALID_STATE_ERR               = ((ExceptionMessage[11]="Invalid state"),11);
18486 var SYNTAX_ERR                  = ExceptionCode.SYNTAX_ERR                      = ((ExceptionMessage[12]="Syntax error"),12);
18487 var INVALID_MODIFICATION_ERR    = ExceptionCode.INVALID_MODIFICATION_ERR        = ((ExceptionMessage[13]="Invalid modification"),13);
18488 var NAMESPACE_ERR               = ExceptionCode.NAMESPACE_ERR                   = ((ExceptionMessage[14]="Invalid namespace"),14);
18489 var INVALID_ACCESS_ERR          = ExceptionCode.INVALID_ACCESS_ERR              = ((ExceptionMessage[15]="Invalid access"),15);
18490 
18491 /**
18492  * DOM Level 2
18493  * Object DOMException
18494  * @see http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/ecma-script-binding.html
18495  * @see http://www.w3.org/TR/REC-DOM-Level-1/ecma-script-language-binding.html
18496  */
18497 function DOMException(code, message) {
18498         if(message instanceof Error){
18499                 var error = message;
18500         }else{
18501                 error = this;
18502                 Error.call(this, ExceptionMessage[code]);
18503                 this.message = ExceptionMessage[code];
18504                 if(Error.captureStackTrace) Error.captureStackTrace(this, DOMException);
18505         }
18506         error.code = code;
18507         if(message) this.message = this.message + ": " + message;
18508         return error;
18509 };
18510 DOMException.prototype = Error.prototype;
18511 copy(ExceptionCode,DOMException)
18512 
18513 /**
18514  * @see http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-536297177
18515  * The NodeList interface provides the abstraction of an ordered collection of nodes, without defining or constraining how this collection is implemented. NodeList objects in the DOM are live.
18516  * The items in the NodeList are accessible via an integral index, starting from 0.
18517  */
18518 function NodeList() {
18519 };
18520 NodeList.prototype = {
18521         /**
18522          * The number of nodes in the list. The range of valid child node indices is 0 to length-1 inclusive.
18523          * @standard level1
18524          */
18525         length:0, 
18526         /**
18527          * Returns the indexth item in the collection. If index is greater than or equal to the number of nodes in the list, this returns null.
18528          * @standard level1
18529          * @param index  unsigned long 
18530          *   Index into the collection.
18531          * @return Node
18532          *      The node at the indexth position in the NodeList, or null if that is not a valid index. 
18533          */
18534         item: function(index) {
18535                 return this[index] || null;
18536         },
18537         toString:function(isHTML,nodeFilter){
18538                 for(var buf = [], i = 0;i<this.length;i++){
18539                         serializeToString(this[i],buf,isHTML,nodeFilter);
18540                 }
18541                 return buf.join('');
18542         }
18543 };
18544 
18545 function LiveNodeList(node,refresh){
18546         this._node = node;
18547         this._refresh = refresh
18548         _updateLiveList(this);
18549 }
18550 function _updateLiveList(list){
18551         var inc = list._node._inc || list._node.ownerDocument._inc;
18552         if(list._inc != inc){
18553                 var ls = list._refresh(list._node);
18554                 //console.log(ls.length)
18555                 __set__(list,'length',ls.length);
18556                 copy(ls,list);
18557                 list._inc = inc;
18558         }
18559 }
18560 LiveNodeList.prototype.item = function(i){
18561         _updateLiveList(this);
18562         return this[i];
18563 }
18564 
18565 _extends(LiveNodeList,NodeList);
18566 
18567 /**
18568  * Objects implementing the NamedNodeMap interface are used
18569  * to represent collections of nodes that can be accessed by name.
18570  * Note that NamedNodeMap does not inherit from NodeList;
18571  * NamedNodeMaps are not maintained in any particular order.
18572  * Objects contained in an object implementing NamedNodeMap may also be accessed by an ordinal index,
18573  * but this is simply to allow convenient enumeration of the contents of a NamedNodeMap,
18574  * and does not imply that the DOM specifies an order to these Nodes.
18575  * NamedNodeMap objects in the DOM are live.
18576  * used for attributes or DocumentType entities 
18577  */
18578 function NamedNodeMap() {
18579 };
18580 
18581 function _findNodeIndex(list,node){
18582         var i = list.length;
18583         while(i--){
18584                 if(list[i] === node){return i}
18585         }
18586 }
18587 
18588 function _addNamedNode(el,list,newAttr,oldAttr){
18589         if(oldAttr){
18590                 list[_findNodeIndex(list,oldAttr)] = newAttr;
18591         }else{
18592                 list[list.length++] = newAttr;
18593         }
18594         if(el){
18595                 newAttr.ownerElement = el;
18596                 var doc = el.ownerDocument;
18597                 if(doc){
18598                         oldAttr && _onRemoveAttribute(doc,el,oldAttr);
18599                         _onAddAttribute(doc,el,newAttr);
18600                 }
18601         }
18602 }
18603 function _removeNamedNode(el,list,attr){
18604         //console.log('remove attr:'+attr)
18605         var i = _findNodeIndex(list,attr);
18606         if(i>=0){
18607                 var lastIndex = list.length-1
18608                 while(i<lastIndex){
18609                         list[i] = list[++i]
18610                 }
18611                 list.length = lastIndex;
18612                 if(el){
18613                         var doc = el.ownerDocument;
18614                         if(doc){
18615                                 _onRemoveAttribute(doc,el,attr);
18616                                 attr.ownerElement = null;
18617                         }
18618                 }
18619         }else{
18620                 throw DOMException(NOT_FOUND_ERR,new Error(el.tagName+'@'+attr))
18621         }
18622 }
18623 NamedNodeMap.prototype = {
18624         length:0,
18625         item:NodeList.prototype.item,
18626         getNamedItem: function(key) {
18627 //              if(key.indexOf(':')>0 || key == 'xmlns'){
18628 //                      return null;
18629 //              }
18630                 //console.log()
18631                 var i = this.length;
18632                 while(i--){
18633                         var attr = this[i];
18634                         //console.log(attr.nodeName,key)
18635                         if(attr.nodeName == key){
18636                                 return attr;
18637                         }
18638                 }
18639         },
18640         setNamedItem: function(attr) {
18641                 var el = attr.ownerElement;
18642                 if(el && el!=this._ownerElement){
18643                         throw new DOMException(INUSE_ATTRIBUTE_ERR);
18644                 }
18645                 var oldAttr = this.getNamedItem(attr.nodeName);
18646                 _addNamedNode(this._ownerElement,this,attr,oldAttr);
18647                 return oldAttr;
18648         },
18649         /* returns Node */
18650         setNamedItemNS: function(attr) {// raises: WRONG_DOCUMENT_ERR,NO_MODIFICATION_ALLOWED_ERR,INUSE_ATTRIBUTE_ERR
18651                 var el = attr.ownerElement, oldAttr;
18652                 if(el && el!=this._ownerElement){
18653                         throw new DOMException(INUSE_ATTRIBUTE_ERR);
18654                 }
18655                 oldAttr = this.getNamedItemNS(attr.namespaceURI,attr.localName);
18656                 _addNamedNode(this._ownerElement,this,attr,oldAttr);
18657                 return oldAttr;
18658         },
18659 
18660         /* returns Node */
18661         removeNamedItem: function(key) {
18662                 var attr = this.getNamedItem(key);
18663                 _removeNamedNode(this._ownerElement,this,attr);
18664                 return attr;
18665                 
18666                 
18667         },// raises: NOT_FOUND_ERR,NO_MODIFICATION_ALLOWED_ERR
18668         
18669         //for level2
18670         removeNamedItemNS:function(namespaceURI,localName){
18671                 var attr = this.getNamedItemNS(namespaceURI,localName);
18672                 _removeNamedNode(this._ownerElement,this,attr);
18673                 return attr;
18674         },
18675         getNamedItemNS: function(namespaceURI, localName) {
18676                 var i = this.length;
18677                 while(i--){
18678                         var node = this[i];
18679                         if(node.localName == localName && node.namespaceURI == namespaceURI){
18680                                 return node;
18681                         }
18682                 }
18683                 return null;
18684         }
18685 };
18686 
18687 /**
18688  * The DOMImplementation interface represents an object providing methods
18689  * which are not dependent on any particular document.
18690  * Such an object is returned by the `Document.implementation` property.
18691  *
18692  * __The individual methods describe the differences compared to the specs.__
18693  *
18694  * @constructor
18695  *
18696  * @see https://developer.mozilla.org/en-US/docs/Web/API/DOMImplementation MDN
18697  * @see https://www.w3.org/TR/REC-DOM-Level-1/level-one-core.html#ID-102161490 DOM Level 1 Core (Initial)
18698  * @see https://www.w3.org/TR/DOM-Level-2-Core/core.html#ID-102161490 DOM Level 2 Core
18699  * @see https://www.w3.org/TR/DOM-Level-3-Core/core.html#ID-102161490 DOM Level 3 Core
18700  * @see https://dom.spec.whatwg.org/#domimplementation DOM Living Standard
18701  */
18702 function DOMImplementation() {
18703 }
18704 
18705 DOMImplementation.prototype = {
18706         /**
18707          * The DOMImplementation.hasFeature() method returns a Boolean flag indicating if a given feature is supported.
18708          * The different implementations fairly diverged in what kind of features were reported.
18709          * The latest version of the spec settled to force this method to always return true, where the functionality was accurate and in use.
18710          *
18711          * @deprecated It is deprecated and modern browsers return true in all cases.
18712          *
18713          * @param {string} feature
18714          * @param {string} [version]
18715          * @returns {boolean} always true
18716          *
18717          * @see https://developer.mozilla.org/en-US/docs/Web/API/DOMImplementation/hasFeature MDN
18718          * @see https://www.w3.org/TR/REC-DOM-Level-1/level-one-core.html#ID-5CED94D7 DOM Level 1 Core
18719          * @see https://dom.spec.whatwg.org/#dom-domimplementation-hasfeature DOM Living Standard
18720          */
18721         hasFeature: function(feature, version) {
18722                         return true;
18723         },
18724         /**
18725          * Creates an XML Document object of the specified type with its document element.
18726          *
18727          * __It behaves slightly different from the description in the living standard__:
18728          * - There is no interface/class `XMLDocument`, it returns a `Document` instance.
18729          * - `contentType`, `encoding`, `mode`, `origin`, `url` fields are currently not declared.
18730          * - this implementation is not validating names or qualified names
18731          *   (when parsing XML strings, the SAX parser takes care of that)
18732          *
18733          * @param {string|null} namespaceURI
18734          * @param {string} qualifiedName
18735          * @param {DocumentType=null} doctype
18736          * @returns {Document}
18737          *
18738          * @see https://developer.mozilla.org/en-US/docs/Web/API/DOMImplementation/createDocument MDN
18739          * @see https://www.w3.org/TR/DOM-Level-2-Core/core.html#Level-2-Core-DOM-createDocument DOM Level 2 Core (initial)
18740          * @see https://dom.spec.whatwg.org/#dom-domimplementation-createdocument  DOM Level 2 Core
18741          *
18742          * @see https://dom.spec.whatwg.org/#validate-and-extract DOM: Validate and extract
18743          * @see https://www.w3.org/TR/xml/#NT-NameStartChar XML Spec: Names
18744          * @see https://www.w3.org/TR/xml-names/#ns-qualnames XML Namespaces: Qualified names
18745          */
18746         createDocument: function(namespaceURI,  qualifiedName, doctype){
18747                 var doc = new Document();
18748                 doc.implementation = this;
18749                 doc.childNodes = new NodeList();
18750                 doc.doctype = doctype || null;
18751                 if (doctype){
18752                         doc.appendChild(doctype);
18753                 }
18754                 if (qualifiedName){
18755                         var root = doc.createElementNS(namespaceURI, qualifiedName);
18756                         doc.appendChild(root);
18757                 }
18758                 return doc;
18759         },
18760         /**
18761          * Returns a doctype, with the given `qualifiedName`, `publicId`, and `systemId`.
18762          *
18763          * __This behavior is slightly different from the in the specs__:
18764          * - this implementation is not validating names or qualified names
18765          *   (when parsing XML strings, the SAX parser takes care of that)
18766          *
18767          * @param {string} qualifiedName
18768          * @param {string} [publicId]
18769          * @param {string} [systemId]
18770          * @returns {DocumentType} which can either be used with `DOMImplementation.createDocument` upon document creation
18771          *                                or can be put into the document via methods like `Node.insertBefore()` or `Node.replaceChild()`
18772          *
18773          * @see https://developer.mozilla.org/en-US/docs/Web/API/DOMImplementation/createDocumentType MDN
18774          * @see https://www.w3.org/TR/DOM-Level-2-Core/core.html#Level-2-Core-DOM-createDocType DOM Level 2 Core
18775          * @see https://dom.spec.whatwg.org/#dom-domimplementation-createdocumenttype DOM Living Standard
18776          *
18777          * @see https://dom.spec.whatwg.org/#validate-and-extract DOM: Validate and extract
18778          * @see https://www.w3.org/TR/xml/#NT-NameStartChar XML Spec: Names
18779          * @see https://www.w3.org/TR/xml-names/#ns-qualnames XML Namespaces: Qualified names
18780          */
18781         createDocumentType: function(qualifiedName, publicId, systemId){
18782                 var node = new DocumentType();
18783                 node.name = qualifiedName;
18784                 node.nodeName = qualifiedName;
18785                 node.publicId = publicId || '';
18786                 node.systemId = systemId || '';
18787 
18788                 return node;
18789         }
18790 };
18791 
18792 
18793 /**
18794  * @see http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-1950641247
18795  */
18796 
18797 function Node() {
18798 };
18799 
18800 Node.prototype = {
18801         firstChild : null,
18802         lastChild : null,
18803         previousSibling : null,
18804         nextSibling : null,
18805         attributes : null,
18806         parentNode : null,
18807         childNodes : null,
18808         ownerDocument : null,
18809         nodeValue : null,
18810         namespaceURI : null,
18811         prefix : null,
18812         localName : null,
18813         // Modified in DOM Level 2:
18814         insertBefore:function(newChild, refChild){//raises 
18815                 return _insertBefore(this,newChild,refChild);
18816         },
18817         replaceChild:function(newChild, oldChild){//raises 
18818                 this.insertBefore(newChild,oldChild);
18819                 if(oldChild){
18820                         this.removeChild(oldChild);
18821                 }
18822         },
18823         removeChild:function(oldChild){
18824                 return _removeChild(this,oldChild);
18825         },
18826         appendChild:function(newChild){
18827                 return this.insertBefore(newChild,null);
18828         },
18829         hasChildNodes:function(){
18830                 return this.firstChild != null;
18831         },
18832         cloneNode:function(deep){
18833                 return cloneNode(this.ownerDocument||this,this,deep);
18834         },
18835         // Modified in DOM Level 2:
18836         normalize:function(){
18837                 var child = this.firstChild;
18838                 while(child){
18839                         var next = child.nextSibling;
18840                         if(next && next.nodeType == TEXT_NODE && child.nodeType == TEXT_NODE){
18841                                 this.removeChild(next);
18842                                 child.appendData(next.data);
18843                         }else{
18844                                 child.normalize();
18845                                 child = next;
18846                         }
18847                 }
18848         },
18849         // Introduced in DOM Level 2:
18850         isSupported:function(feature, version){
18851                 return this.ownerDocument.implementation.hasFeature(feature,version);
18852         },
18853     // Introduced in DOM Level 2:
18854     hasAttributes:function(){
18855         return this.attributes.length>0;
18856     },
18857         /**
18858          * Look up the prefix associated to the given namespace URI, starting from this node.
18859          * **The default namespace declarations are ignored by this method.**
18860          * See Namespace Prefix Lookup for details on the algorithm used by this method.
18861          *
18862          * _Note: The implementation seems to be incomplete when compared to the algorithm described in the specs._
18863          *
18864          * @param {string | null} namespaceURI
18865          * @returns {string | null}
18866          * @see https://www.w3.org/TR/DOM-Level-3-Core/core.html#Node3-lookupNamespacePrefix
18867          * @see https://www.w3.org/TR/DOM-Level-3-Core/namespaces-algorithms.html#lookupNamespacePrefixAlgo
18868          * @see https://dom.spec.whatwg.org/#dom-node-lookupprefix
18869          * @see https://github.com/xmldom/xmldom/issues/322
18870          */
18871     lookupPrefix:function(namespaceURI){
18872         var el = this;
18873         while(el){
18874                 var map = el._nsMap;
18875                 //console.dir(map)
18876                 if(map){
18877                         for(var n in map){
18878                                 if(map[n] == namespaceURI){
18879                                         return n;
18880                                 }
18881                         }
18882                 }
18883                 el = el.nodeType == ATTRIBUTE_NODE?el.ownerDocument : el.parentNode;
18884         }
18885         return null;
18886     },
18887     // Introduced in DOM Level 3:
18888     lookupNamespaceURI:function(prefix){
18889         var el = this;
18890         while(el){
18891                 var map = el._nsMap;
18892                 //console.dir(map)
18893                 if(map){
18894                         if(prefix in map){
18895                                 return map[prefix] ;
18896                         }
18897                 }
18898                 el = el.nodeType == ATTRIBUTE_NODE?el.ownerDocument : el.parentNode;
18899         }
18900         return null;
18901     },
18902     // Introduced in DOM Level 3:
18903     isDefaultNamespace:function(namespaceURI){
18904         var prefix = this.lookupPrefix(namespaceURI);
18905         return prefix == null;
18906     }
18907 };
18908 
18909 
18910 function _xmlEncoder(c){
18911         return c == '<' && '&lt;' ||
18912          c == '>' && '&gt;' ||
18913          c == '&' && '&amp;' ||
18914          c == '"' && '&quot;' ||
18915          '&#'+c.charCodeAt()+';'
18916 }
18917 
18918 
18919 copy(NodeType,Node);
18920 copy(NodeType,Node.prototype);
18921 
18922 /**
18923  * @param callback return true for continue,false for break
18924  * @return boolean true: break visit;
18925  */
18926 function _visitNode(node,callback){
18927         if(callback(node)){
18928                 return true;
18929         }
18930         if(node = node.firstChild){
18931                 do{
18932                         if(_visitNode(node,callback)){return true}
18933         }while(node=node.nextSibling)
18934     }
18935 }
18936 
18937 
18938 
18939 function Document(){
18940 }
18941 
18942 function _onAddAttribute(doc,el,newAttr){
18943         doc && doc._inc++;
18944         var ns = newAttr.namespaceURI ;
18945         if(ns === NAMESPACE.XMLNS){
18946                 //update namespace
18947                 el._nsMap[newAttr.prefix?newAttr.localName:''] = newAttr.value
18948         }
18949 }
18950 
18951 function _onRemoveAttribute(doc,el,newAttr,remove){
18952         doc && doc._inc++;
18953         var ns = newAttr.namespaceURI ;
18954         if(ns === NAMESPACE.XMLNS){
18955                 //update namespace
18956                 delete el._nsMap[newAttr.prefix?newAttr.localName:'']
18957         }
18958 }
18959 
18960 function _onUpdateChild(doc,el,newChild){
18961         if(doc && doc._inc){
18962                 doc._inc++;
18963                 //update childNodes
18964                 var cs = el.childNodes;
18965                 if(newChild){
18966                         cs[cs.length++] = newChild;
18967                 }else{
18968                         //console.log(1)
18969                         var child = el.firstChild;
18970                         var i = 0;
18971                         while(child){
18972                                 cs[i++] = child;
18973                                 child =child.nextSibling;
18974                         }
18975                         cs.length = i;
18976                 }
18977         }
18978 }
18979 
18980 /**
18981  * attributes;
18982  * children;
18983  * 
18984  * writeable properties:
18985  * nodeValue,Attr:value,CharacterData:data
18986  * prefix
18987  */
18988 function _removeChild(parentNode,child){
18989         var previous = child.previousSibling;
18990         var next = child.nextSibling;
18991         if(previous){
18992                 previous.nextSibling = next;
18993         }else{
18994                 parentNode.firstChild = next
18995         }
18996         if(next){
18997                 next.previousSibling = previous;
18998         }else{
18999                 parentNode.lastChild = previous;
19000         }
19001         _onUpdateChild(parentNode.ownerDocument,parentNode);
19002         return child;
19003 }
19004 /**
19005  * preformance key(refChild == null)
19006  */
19007 function _insertBefore(parentNode,newChild,nextChild){
19008         var cp = newChild.parentNode;
19009         if(cp){
19010                 cp.removeChild(newChild);//remove and update
19011         }
19012         if(newChild.nodeType === DOCUMENT_FRAGMENT_NODE){
19013                 var newFirst = newChild.firstChild;
19014                 if (newFirst == null) {
19015                         return newChild;
19016                 }
19017                 var newLast = newChild.lastChild;
19018         }else{
19019                 newFirst = newLast = newChild;
19020         }
19021         var pre = nextChild ? nextChild.previousSibling : parentNode.lastChild;
19022 
19023         newFirst.previousSibling = pre;
19024         newLast.nextSibling = nextChild;
19025         
19026         
19027         if(pre){
19028                 pre.nextSibling = newFirst;
19029         }else{
19030                 parentNode.firstChild = newFirst;
19031         }
19032         if(nextChild == null){
19033                 parentNode.lastChild = newLast;
19034         }else{
19035                 nextChild.previousSibling = newLast;
19036         }
19037         do{
19038                 newFirst.parentNode = parentNode;
19039         }while(newFirst !== newLast && (newFirst= newFirst.nextSibling))
19040         _onUpdateChild(parentNode.ownerDocument||parentNode,parentNode);
19041         //console.log(parentNode.lastChild.nextSibling == null)
19042         if (newChild.nodeType == DOCUMENT_FRAGMENT_NODE) {
19043                 newChild.firstChild = newChild.lastChild = null;
19044         }
19045         return newChild;
19046 }
19047 function _appendSingleChild(parentNode,newChild){
19048         var cp = newChild.parentNode;
19049         if(cp){
19050                 var pre = parentNode.lastChild;
19051                 cp.removeChild(newChild);//remove and update
19052                 var pre = parentNode.lastChild;
19053         }
19054         var pre = parentNode.lastChild;
19055         newChild.parentNode = parentNode;
19056         newChild.previousSibling = pre;
19057         newChild.nextSibling = null;
19058         if(pre){
19059                 pre.nextSibling = newChild;
19060         }else{
19061                 parentNode.firstChild = newChild;
19062         }
19063         parentNode.lastChild = newChild;
19064         _onUpdateChild(parentNode.ownerDocument,parentNode,newChild);
19065         return newChild;
19066         //console.log("__aa",parentNode.lastChild.nextSibling == null)
19067 }
19068 Document.prototype = {
19069         //implementation : null,
19070         nodeName :  '#document',
19071         nodeType :  DOCUMENT_NODE,
19072         /**
19073          * The DocumentType node of the document.
19074          *
19075          * @readonly
19076          * @type DocumentType
19077          */
19078         doctype :  null,
19079         documentElement :  null,
19080         _inc : 1,
19081 
19082         insertBefore :  function(newChild, refChild){//raises
19083                 if(newChild.nodeType == DOCUMENT_FRAGMENT_NODE){
19084                         var child = newChild.firstChild;
19085                         while(child){
19086                                 var next = child.nextSibling;
19087                                 this.insertBefore(child,refChild);
19088                                 child = next;
19089                         }
19090                         return newChild;
19091                 }
19092                 if(this.documentElement == null && newChild.nodeType == ELEMENT_NODE){
19093                         this.documentElement = newChild;
19094                 }
19095 
19096                 return _insertBefore(this,newChild,refChild),(newChild.ownerDocument = this),newChild;
19097         },
19098         removeChild :  function(oldChild){
19099                 if(this.documentElement == oldChild){
19100                         this.documentElement = null;
19101                 }
19102                 return _removeChild(this,oldChild);
19103         },
19104         // Introduced in DOM Level 2:
19105         importNode : function(importedNode,deep){
19106                 return importNode(this,importedNode,deep);
19107         },
19108         // Introduced in DOM Level 2:
19109         getElementById :        function(id){
19110                 var rtv = null;
19111                 _visitNode(this.documentElement,function(node){
19112                         if(node.nodeType == ELEMENT_NODE){
19113                                 if(node.getAttribute('id') == id){
19114                                         rtv = node;
19115                                         return true;
19116                                 }
19117                         }
19118                 })
19119                 return rtv;
19120         },
19121 
19122         /**
19123          * The `getElementsByClassName` method of `Document` interface returns an array-like object
19124          * of all child elements which have **all** of the given class name(s).
19125          *
19126          * Returns an empty list if `classeNames` is an empty string or only contains HTML white space characters.
19127          *
19128          *
19129          * Warning: This is a live LiveNodeList.
19130          * Changes in the DOM will reflect in the array as the changes occur.
19131          * If an element selected by this array no longer qualifies for the selector,
19132          * it will automatically be removed. Be aware of this for iteration purposes.
19133          *
19134          * @param {string} classNames is a string representing the class name(s) to match; multiple class names are separated by (ASCII-)whitespace
19135          *
19136          * @see https://developer.mozilla.org/en-US/docs/Web/API/Document/getElementsByClassName
19137          * @see https://dom.spec.whatwg.org/#concept-getelementsbyclassname
19138          */
19139         getElementsByClassName: function(classNames) {
19140                 var classNamesSet = toOrderedSet(classNames)
19141                 return new LiveNodeList(this, function(base) {
19142                         var ls = [];
19143                         if (classNamesSet.length > 0) {
19144                                 _visitNode(base.documentElement, function(node) {
19145                                         if(node !== base && node.nodeType === ELEMENT_NODE) {
19146                                                 var nodeClassNames = node.getAttribute('class')
19147                                                 // can be null if the attribute does not exist
19148                                                 if (nodeClassNames) {
19149                                                         // before splitting and iterating just compare them for the most common case
19150                                                         var matches = classNames === nodeClassNames;
19151                                                         if (!matches) {
19152                                                                 var nodeClassNamesSet = toOrderedSet(nodeClassNames)
19153                                                                 matches = classNamesSet.every(arrayIncludes(nodeClassNamesSet))
19154                                                         }
19155                                                         if(matches) {
19156                                                                 ls.push(node);
19157                                                         }
19158                                                 }
19159                                         }
19160                                 });
19161                         }
19162                         return ls;
19163                 });
19164         },
19165 
19166         //document factory method:
19167         createElement : function(tagName){
19168                 var node = new Element();
19169                 node.ownerDocument = this;
19170                 node.nodeName = tagName;
19171                 node.tagName = tagName;
19172                 node.localName = tagName;
19173                 node.childNodes = new NodeList();
19174                 var attrs       = node.attributes = new NamedNodeMap();
19175                 attrs._ownerElement = node;
19176                 return node;
19177         },
19178         createDocumentFragment :        function(){
19179                 var node = new DocumentFragment();
19180                 node.ownerDocument = this;
19181                 node.childNodes = new NodeList();
19182                 return node;
19183         },
19184         createTextNode :        function(data){
19185                 var node = new Text();
19186                 node.ownerDocument = this;
19187                 node.appendData(data)
19188                 return node;
19189         },
19190         createComment : function(data){
19191                 var node = new Comment();
19192                 node.ownerDocument = this;
19193                 node.appendData(data)
19194                 return node;
19195         },
19196         createCDATASection :    function(data){
19197                 var node = new CDATASection();
19198                 node.ownerDocument = this;
19199                 node.appendData(data)
19200                 return node;
19201         },
19202         createProcessingInstruction :   function(target,data){
19203                 var node = new ProcessingInstruction();
19204                 node.ownerDocument = this;
19205                 node.tagName = node.target = target;
19206                 node.nodeValue= node.data = data;
19207                 return node;
19208         },
19209         createAttribute :       function(name){
19210                 var node = new Attr();
19211                 node.ownerDocument      = this;
19212                 node.name = name;
19213                 node.nodeName   = name;
19214                 node.localName = name;
19215                 node.specified = true;
19216                 return node;
19217         },
19218         createEntityReference : function(name){
19219                 var node = new EntityReference();
19220                 node.ownerDocument      = this;
19221                 node.nodeName   = name;
19222                 return node;
19223         },
19224         // Introduced in DOM Level 2:
19225         createElementNS :       function(namespaceURI,qualifiedName){
19226                 var node = new Element();
19227                 var pl = qualifiedName.split(':');
19228                 var attrs       = node.attributes = new NamedNodeMap();
19229                 node.childNodes = new NodeList();
19230                 node.ownerDocument = this;
19231                 node.nodeName = qualifiedName;
19232                 node.tagName = qualifiedName;
19233                 node.namespaceURI = namespaceURI;
19234                 if(pl.length == 2){
19235                         node.prefix = pl[0];
19236                         node.localName = pl[1];
19237                 }else{
19238                         //el.prefix = null;
19239                         node.localName = qualifiedName;
19240                 }
19241                 attrs._ownerElement = node;
19242                 return node;
19243         },
19244         // Introduced in DOM Level 2:
19245         createAttributeNS :     function(namespaceURI,qualifiedName){
19246                 var node = new Attr();
19247                 var pl = qualifiedName.split(':');
19248                 node.ownerDocument = this;
19249                 node.nodeName = qualifiedName;
19250                 node.name = qualifiedName;
19251                 node.namespaceURI = namespaceURI;
19252                 node.specified = true;
19253                 if(pl.length == 2){
19254                         node.prefix = pl[0];
19255                         node.localName = pl[1];
19256                 }else{
19257                         //el.prefix = null;
19258                         node.localName = qualifiedName;
19259                 }
19260                 return node;
19261         }
19262 };
19263 _extends(Document,Node);
19264 
19265 
19266 function Element() {
19267         this._nsMap = {};
19268 };
19269 Element.prototype = {
19270         nodeType : ELEMENT_NODE,
19271         hasAttribute : function(name){
19272                 return this.getAttributeNode(name)!=null;
19273         },
19274         getAttribute : function(name){
19275                 var attr = this.getAttributeNode(name);
19276                 return attr && attr.value || '';
19277         },
19278         getAttributeNode : function(name){
19279                 return this.attributes.getNamedItem(name);
19280         },
19281         setAttribute : function(name, value){
19282                 var attr = this.ownerDocument.createAttribute(name);
19283                 attr.value = attr.nodeValue = "" + value;
19284                 this.setAttributeNode(attr)
19285         },
19286         removeAttribute : function(name){
19287                 var attr = this.getAttributeNode(name)
19288                 attr && this.removeAttributeNode(attr);
19289         },
19290         
19291         //four real opeartion method
19292         appendChild:function(newChild){
19293                 if(newChild.nodeType === DOCUMENT_FRAGMENT_NODE){
19294                         return this.insertBefore(newChild,null);
19295                 }else{
19296                         return _appendSingleChild(this,newChild);
19297                 }
19298         },
19299         setAttributeNode : function(newAttr){
19300                 return this.attributes.setNamedItem(newAttr);
19301         },
19302         setAttributeNodeNS : function(newAttr){
19303                 return this.attributes.setNamedItemNS(newAttr);
19304         },
19305         removeAttributeNode : function(oldAttr){
19306                 //console.log(this == oldAttr.ownerElement)
19307                 return this.attributes.removeNamedItem(oldAttr.nodeName);
19308         },
19309         //get real attribute name,and remove it by removeAttributeNode
19310         removeAttributeNS : function(namespaceURI, localName){
19311                 var old = this.getAttributeNodeNS(namespaceURI, localName);
19312                 old && this.removeAttributeNode(old);
19313         },
19314         
19315         hasAttributeNS : function(namespaceURI, localName){
19316                 return this.getAttributeNodeNS(namespaceURI, localName)!=null;
19317         },
19318         getAttributeNS : function(namespaceURI, localName){
19319                 var attr = this.getAttributeNodeNS(namespaceURI, localName);
19320                 return attr && attr.value || '';
19321         },
19322         setAttributeNS : function(namespaceURI, qualifiedName, value){
19323                 var attr = this.ownerDocument.createAttributeNS(namespaceURI, qualifiedName);
19324                 attr.value = attr.nodeValue = "" + value;
19325                 this.setAttributeNode(attr)
19326         },
19327         getAttributeNodeNS : function(namespaceURI, localName){
19328                 return this.attributes.getNamedItemNS(namespaceURI, localName);
19329         },
19330         
19331         getElementsByTagName : function(tagName){
19332                 return new LiveNodeList(this,function(base){
19333                         var ls = [];
19334                         _visitNode(base,function(node){
19335                                 if(node !== base && node.nodeType == ELEMENT_NODE && (tagName === '*' || node.tagName == tagName)){
19336                                         ls.push(node);
19337                                 }
19338                         });
19339                         return ls;
19340                 });
19341         },
19342         getElementsByTagNameNS : function(namespaceURI, localName){
19343                 return new LiveNodeList(this,function(base){
19344                         var ls = [];
19345                         _visitNode(base,function(node){
19346                                 if(node !== base && node.nodeType === ELEMENT_NODE && (namespaceURI === '*' || node.namespaceURI === namespaceURI) && (localName === '*' || node.localName == localName)){
19347                                         ls.push(node);
19348                                 }
19349                         });
19350                         return ls;
19351                         
19352                 });
19353         }
19354 };
19355 Document.prototype.getElementsByTagName = Element.prototype.getElementsByTagName;
19356 Document.prototype.getElementsByTagNameNS = Element.prototype.getElementsByTagNameNS;
19357 
19358 
19359 _extends(Element,Node);
19360 function Attr() {
19361 };
19362 Attr.prototype.nodeType = ATTRIBUTE_NODE;
19363 _extends(Attr,Node);
19364 
19365 
19366 function CharacterData() {
19367 };
19368 CharacterData.prototype = {
19369         data : '',
19370         substringData : function(offset, count) {
19371                 return this.data.substring(offset, offset+count);
19372         },
19373         appendData: function(text) {
19374                 text = this.data+text;
19375                 this.nodeValue = this.data = text;
19376                 this.length = text.length;
19377         },
19378         insertData: function(offset,text) {
19379                 this.replaceData(offset,0,text);
19380         
19381         },
19382         appendChild:function(newChild){
19383                 throw new Error(ExceptionMessage[HIERARCHY_REQUEST_ERR])
19384         },
19385         deleteData: function(offset, count) {
19386                 this.replaceData(offset,count,"");
19387         },
19388         replaceData: function(offset, count, text) {
19389                 var start = this.data.substring(0,offset);
19390                 var end = this.data.substring(offset+count);
19391                 text = start + text + end;
19392                 this.nodeValue = this.data = text;
19393                 this.length = text.length;
19394         }
19395 }
19396 _extends(CharacterData,Node);
19397 function Text() {
19398 };
19399 Text.prototype = {
19400         nodeName : "#text",
19401         nodeType : TEXT_NODE,
19402         splitText : function(offset) {
19403                 var text = this.data;
19404                 var newText = text.substring(offset);
19405                 text = text.substring(0, offset);
19406                 this.data = this.nodeValue = text;
19407                 this.length = text.length;
19408                 var newNode = this.ownerDocument.createTextNode(newText);
19409                 if(this.parentNode){
19410                         this.parentNode.insertBefore(newNode, this.nextSibling);
19411                 }
19412                 return newNode;
19413         }
19414 }
19415 _extends(Text,CharacterData);
19416 function Comment() {
19417 };
19418 Comment.prototype = {
19419         nodeName : "#comment",
19420         nodeType : COMMENT_NODE
19421 }
19422 _extends(Comment,CharacterData);
19423 
19424 function CDATASection() {
19425 };
19426 CDATASection.prototype = {
19427         nodeName : "#cdata-section",
19428         nodeType : CDATA_SECTION_NODE
19429 }
19430 _extends(CDATASection,CharacterData);
19431 
19432 
19433 function DocumentType() {
19434 };
19435 DocumentType.prototype.nodeType = DOCUMENT_TYPE_NODE;
19436 _extends(DocumentType,Node);
19437 
19438 function Notation() {
19439 };
19440 Notation.prototype.nodeType = NOTATION_NODE;
19441 _extends(Notation,Node);
19442 
19443 function Entity() {
19444 };
19445 Entity.prototype.nodeType = ENTITY_NODE;
19446 _extends(Entity,Node);
19447 
19448 function EntityReference() {
19449 };
19450 EntityReference.prototype.nodeType = ENTITY_REFERENCE_NODE;
19451 _extends(EntityReference,Node);
19452 
19453 function DocumentFragment() {
19454 };
19455 DocumentFragment.prototype.nodeName =   "#document-fragment";
19456 DocumentFragment.prototype.nodeType =   DOCUMENT_FRAGMENT_NODE;
19457 _extends(DocumentFragment,Node);
19458 
19459 
19460 function ProcessingInstruction() {
19461 }
19462 ProcessingInstruction.prototype.nodeType = PROCESSING_INSTRUCTION_NODE;
19463 _extends(ProcessingInstruction,Node);
19464 function XMLSerializer(){}
19465 XMLSerializer.prototype.serializeToString = function(node,isHtml,nodeFilter){
19466         return nodeSerializeToString.call(node,isHtml,nodeFilter);
19467 }
19468 Node.prototype.toString = nodeSerializeToString;
19469 function nodeSerializeToString(isHtml,nodeFilter){
19470         var buf = [];
19471         var refNode = this.nodeType == 9 && this.documentElement || this;
19472         var prefix = refNode.prefix;
19473         var uri = refNode.namespaceURI;
19474         
19475         if(uri && prefix == null){
19476                 //console.log(prefix)
19477                 var prefix = refNode.lookupPrefix(uri);
19478                 if(prefix == null){
19479                         //isHTML = true;
19480                         var visibleNamespaces=[
19481                         {namespace:uri,prefix:null}
19482                         //{namespace:uri,prefix:''}
19483                         ]
19484                 }
19485         }
19486         serializeToString(this,buf,isHtml,nodeFilter,visibleNamespaces);
19487         //console.log('###',this.nodeType,uri,prefix,buf.join(''))
19488         return buf.join('');
19489 }
19490 
19491 function needNamespaceDefine(node, isHTML, visibleNamespaces) {
19492         var prefix = node.prefix || '';
19493         var uri = node.namespaceURI;
19494         // According to [Namespaces in XML 1.0](https://www.w3.org/TR/REC-xml-names/#ns-using) ,
19495         // and more specifically https://www.w3.org/TR/REC-xml-names/#nsc-NoPrefixUndecl :
19496         // > In a namespace declaration for a prefix [...], the attribute value MUST NOT be empty.
19497         // in a similar manner [Namespaces in XML 1.1](https://www.w3.org/TR/xml-names11/#ns-using)
19498         // and more specifically https://www.w3.org/TR/xml-names11/#nsc-NSDeclared :
19499         // > [...] Furthermore, the attribute value [...] must not be an empty string.
19500         // so serializing empty namespace value like xmlns:ds="" would produce an invalid XML document.
19501         if (!uri) {
19502                 return false;
19503         }
19504         if (prefix === "xml" && uri === NAMESPACE.XML || uri === NAMESPACE.XMLNS) {
19505                 return false;
19506         }
19507         
19508         var i = visibleNamespaces.length 
19509         while (i--) {
19510                 var ns = visibleNamespaces[i];
19511                 // get namespace prefix
19512                 if (ns.prefix === prefix) {
19513                         return ns.namespace !== uri;
19514                 }
19515         }
19516         return true;
19517 }
19518 /**
19519  * Well-formed constraint: No < in Attribute Values
19520  * The replacement text of any entity referred to directly or indirectly in an attribute value must not contain a <.
19521  * @see https://www.w3.org/TR/xml/#CleanAttrVals
19522  * @see https://www.w3.org/TR/xml/#NT-AttValue
19523  */
19524 function addSerializedAttribute(buf, qualifiedName, value) {
19525         buf.push(' ', qualifiedName, '="', value.replace(/[<&"]/g,_xmlEncoder), '"')
19526 }
19527 
19528 function serializeToString(node,buf,isHTML,nodeFilter,visibleNamespaces){
19529         if (!visibleNamespaces) {
19530                 visibleNamespaces = [];
19531         }
19532 
19533         if(nodeFilter){
19534                 node = nodeFilter(node);
19535                 if(node){
19536                         if(typeof node == 'string'){
19537                                 buf.push(node);
19538                                 return;
19539                         }
19540                 }else{
19541                         return;
19542                 }
19543                 //buf.sort.apply(attrs, attributeSorter);
19544         }
19545 
19546         switch(node.nodeType){
19547         case ELEMENT_NODE:
19548                 var attrs = node.attributes;
19549                 var len = attrs.length;
19550                 var child = node.firstChild;
19551                 var nodeName = node.tagName;
19552                 
19553                 isHTML = NAMESPACE.isHTML(node.namespaceURI) || isHTML
19554 
19555                 var prefixedNodeName = nodeName
19556                 if (!isHTML && !node.prefix && node.namespaceURI) {
19557                         var defaultNS
19558                         // lookup current default ns from `xmlns` attribute
19559                         for (var ai = 0; ai < attrs.length; ai++) {
19560                                 if (attrs.item(ai).name === 'xmlns') {
19561                                         defaultNS = attrs.item(ai).value
19562                                         break
19563                                 }
19564                         }
19565                         if (!defaultNS) {
19566                                 // lookup current default ns in visibleNamespaces
19567                                 for (var nsi = visibleNamespaces.length - 1; nsi >= 0; nsi--) {
19568                                         var namespace = visibleNamespaces[nsi]
19569                                         if (namespace.prefix === '' && namespace.namespace === node.namespaceURI) {
19570                                                 defaultNS = namespace.namespace
19571                                                 break
19572                                         }
19573                                 }
19574                         }
19575                         if (defaultNS !== node.namespaceURI) {
19576                                 for (var nsi = visibleNamespaces.length - 1; nsi >= 0; nsi--) {
19577                                         var namespace = visibleNamespaces[nsi]
19578                                         if (namespace.namespace === node.namespaceURI) {
19579                                                 if (namespace.prefix) {
19580                                                         prefixedNodeName = namespace.prefix + ':' + nodeName
19581                                                 }
19582                                                 break
19583                                         }
19584                                 }
19585                         }
19586                 }
19587 
19588                 buf.push('<', prefixedNodeName);
19589 
19590                 for(var i=0;i<len;i++){
19591                         // add namespaces for attributes
19592                         var attr = attrs.item(i);
19593                         if (attr.prefix == 'xmlns') {
19594                                 visibleNamespaces.push({ prefix: attr.localName, namespace: attr.value });
19595                         }else if(attr.nodeName == 'xmlns'){
19596                                 visibleNamespaces.push({ prefix: '', namespace: attr.value });
19597                         }
19598                 }
19599 
19600                 for(var i=0;i<len;i++){
19601                         var attr = attrs.item(i);
19602                         if (needNamespaceDefine(attr,isHTML, visibleNamespaces)) {
19603                                 var prefix = attr.prefix||'';
19604                                 var uri = attr.namespaceURI;
19605                                 addSerializedAttribute(buf, prefix ? 'xmlns:' + prefix : "xmlns", uri);
19606                                 visibleNamespaces.push({ prefix: prefix, namespace:uri });
19607                         }
19608                         serializeToString(attr,buf,isHTML,nodeFilter,visibleNamespaces);
19609                 }
19610 
19611                 // add namespace for current node               
19612                 if (nodeName === prefixedNodeName && needNamespaceDefine(node, isHTML, visibleNamespaces)) {
19613                         var prefix = node.prefix||'';
19614                         var uri = node.namespaceURI;
19615                         addSerializedAttribute(buf, prefix ? 'xmlns:' + prefix : "xmlns", uri);
19616                         visibleNamespaces.push({ prefix: prefix, namespace:uri });
19617                 }
19618                 
19619                 if(child || isHTML && !/^(?:meta|link|img|br|hr|input)$/i.test(nodeName)){
19620                         buf.push('>');
19621                         //if is cdata child node
19622                         if(isHTML && /^script$/i.test(nodeName)){
19623                                 while(child){
19624                                         if(child.data){
19625                                                 buf.push(child.data);
19626                                         }else{
19627                                                 serializeToString(child, buf, isHTML, nodeFilter, visibleNamespaces.slice());
19628                                         }
19629                                         child = child.nextSibling;
19630                                 }
19631                         }else
19632                         {
19633                                 while(child){
19634                                         serializeToString(child, buf, isHTML, nodeFilter, visibleNamespaces.slice());
19635                                         child = child.nextSibling;
19636                                 }
19637                         }
19638                         buf.push('</',prefixedNodeName,'>');
19639                 }else{
19640                         buf.push('/>');
19641                 }
19642                 // remove added visible namespaces
19643                 //visibleNamespaces.length = startVisibleNamespaces;
19644                 return;
19645         case DOCUMENT_NODE:
19646         case DOCUMENT_FRAGMENT_NODE:
19647                 var child = node.firstChild;
19648                 while(child){
19649                         serializeToString(child, buf, isHTML, nodeFilter, visibleNamespaces.slice());
19650                         child = child.nextSibling;
19651                 }
19652                 return;
19653         case ATTRIBUTE_NODE:
19654                 return addSerializedAttribute(buf, node.name, node.value);
19655         case TEXT_NODE:
19656                 /**
19657                  * The ampersand character (&) and the left angle bracket (<) must not appear in their literal form,
19658                  * except when used as markup delimiters, or within a comment, a processing instruction, or a CDATA section.
19659                  * If they are needed elsewhere, they must be escaped using either numeric character references or the strings
19660                  * `&amp;` and `&lt;` respectively.
19661                  * The right angle bracket (>) may be represented using the string " &gt; ", and must, for compatibility,
19662                  * be escaped using either `&gt;` or a character reference when it appears in the string `]]>` in content,
19663                  * when that string is not marking the end of a CDATA section.
19664                  *
19665                  * In the content of elements, character data is any string of characters
19666                  * which does not contain the start-delimiter of any markup
19667                  * and does not include the CDATA-section-close delimiter, `]]>`.
19668                  *
19669                  * @see https://www.w3.org/TR/xml/#NT-CharData
19670                  */
19671                 return buf.push(node.data
19672                         .replace(/[<&]/g,_xmlEncoder)
19673                         .replace(/]]>/g, ']]&gt;')
19674                 );
19675         case CDATA_SECTION_NODE:
19676                 return buf.push( '<![CDATA[',node.data,']]>');
19677         case COMMENT_NODE:
19678                 return buf.push( "<!--",node.data,"-->");
19679         case DOCUMENT_TYPE_NODE:
19680                 var pubid = node.publicId;
19681                 var sysid = node.systemId;
19682                 buf.push('<!DOCTYPE ',node.name);
19683                 if(pubid){
19684                         buf.push(' PUBLIC ', pubid);
19685                         if (sysid && sysid!='.') {
19686                                 buf.push(' ', sysid);
19687                         }
19688                         buf.push('>');
19689                 }else if(sysid && sysid!='.'){
19690                         buf.push(' SYSTEM ', sysid, '>');
19691                 }else{
19692                         var sub = node.internalSubset;
19693                         if(sub){
19694                                 buf.push(" [",sub,"]");
19695                         }
19696                         buf.push(">");
19697                 }
19698                 return;
19699         case PROCESSING_INSTRUCTION_NODE:
19700                 return buf.push( "<?",node.target," ",node.data,"?>");
19701         case ENTITY_REFERENCE_NODE:
19702                 return buf.push( '&',node.nodeName,';');
19703         //case ENTITY_NODE:
19704         //case NOTATION_NODE:
19705         default:
19706                 buf.push('??',node.nodeName);
19707         }
19708 }
19709 function importNode(doc,node,deep){
19710         var node2;
19711         switch (node.nodeType) {
19712         case ELEMENT_NODE:
19713                 node2 = node.cloneNode(false);
19714                 node2.ownerDocument = doc;
19715                 //var attrs = node2.attributes;
19716                 //var len = attrs.length;
19717                 //for(var i=0;i<len;i++){
19718                         //node2.setAttributeNodeNS(importNode(doc,attrs.item(i),deep));
19719                 //}
19720         case DOCUMENT_FRAGMENT_NODE:
19721                 break;
19722         case ATTRIBUTE_NODE:
19723                 deep = true;
19724                 break;
19725         //case ENTITY_REFERENCE_NODE:
19726         //case PROCESSING_INSTRUCTION_NODE:
19727         ////case TEXT_NODE:
19728         //case CDATA_SECTION_NODE:
19729         //case COMMENT_NODE:
19730         //      deep = false;
19731         //      break;
19732         //case DOCUMENT_NODE:
19733         //case DOCUMENT_TYPE_NODE:
19734         //cannot be imported.
19735         //case ENTITY_NODE:
19736         //case NOTATION_NODE:
19737         //can not hit in level3
19738         //default:throw e;
19739         }
19740         if(!node2){
19741                 node2 = node.cloneNode(false);//false
19742         }
19743         node2.ownerDocument = doc;
19744         node2.parentNode = null;
19745         if(deep){
19746                 var child = node.firstChild;
19747                 while(child){
19748                         node2.appendChild(importNode(doc,child,deep));
19749                         child = child.nextSibling;
19750                 }
19751         }
19752         return node2;
19753 }
19754 //
19755 //var _relationMap = {firstChild:1,lastChild:1,previousSibling:1,nextSibling:1,
19756 //                                      attributes:1,childNodes:1,parentNode:1,documentElement:1,doctype,};
19757 function cloneNode(doc,node,deep){
19758         var node2 = new node.constructor();
19759         for(var n in node){
19760                 var v = node[n];
19761                 if(typeof v != 'object' ){
19762                         if(v != node2[n]){
19763                                 node2[n] = v;
19764                         }
19765                 }
19766         }
19767         if(node.childNodes){
19768                 node2.childNodes = new NodeList();
19769         }
19770         node2.ownerDocument = doc;
19771         switch (node2.nodeType) {
19772         case ELEMENT_NODE:
19773                 var attrs       = node.attributes;
19774                 var attrs2      = node2.attributes = new NamedNodeMap();
19775                 var len = attrs.length
19776                 attrs2._ownerElement = node2;
19777                 for(var i=0;i<len;i++){
19778                         node2.setAttributeNode(cloneNode(doc,attrs.item(i),true));
19779                 }
19780                 break;;
19781         case ATTRIBUTE_NODE:
19782                 deep = true;
19783         }
19784         if(deep){
19785                 var child = node.firstChild;
19786                 while(child){
19787                         node2.appendChild(cloneNode(doc,child,deep));
19788                         child = child.nextSibling;
19789                 }
19790         }
19791         return node2;
19792 }
19793 
19794 function __set__(object,key,value){
19795         object[key] = value
19796 }
19797 //do dynamic
19798 try{
19799         if(Object.defineProperty){
19800                 Object.defineProperty(LiveNodeList.prototype,'length',{
19801                         get:function(){
19802                                 _updateLiveList(this);
19803                                 return this.$$length;
19804                         }
19805                 });
19806 
19807                 Object.defineProperty(Node.prototype,'textContent',{
19808                         get:function(){
19809                                 return getTextContent(this);
19810                         },
19811 
19812                         set:function(data){
19813                                 switch(this.nodeType){
19814                                 case ELEMENT_NODE:
19815                                 case DOCUMENT_FRAGMENT_NODE:
19816                                         while(this.firstChild){
19817                                                 this.removeChild(this.firstChild);
19818                                         }
19819                                         if(data || String(data)){
19820                                                 this.appendChild(this.ownerDocument.createTextNode(data));
19821                                         }
19822                                         break;
19823 
19824                                 default:
19825                                         this.data = data;
19826                                         this.value = data;
19827                                         this.nodeValue = data;
19828                                 }
19829                         }
19830                 })
19831                 
19832                 function getTextContent(node){
19833                         switch(node.nodeType){
19834                         case ELEMENT_NODE:
19835                         case DOCUMENT_FRAGMENT_NODE:
19836                                 var buf = [];
19837                                 node = node.firstChild;
19838                                 while(node){
19839                                         if(node.nodeType!==7 && node.nodeType !==8){
19840                                                 buf.push(getTextContent(node));
19841                                         }
19842                                         node = node.nextSibling;
19843                                 }
19844                                 return buf.join('');
19845                         default:
19846                                 return node.nodeValue;
19847                         }
19848                 }
19849 
19850                 __set__ = function(object,key,value){
19851                         //console.log(value)
19852                         object['$$'+key] = value
19853                 }
19854         }
19855 }catch(e){//ie8
19856 }
19857 
19858 //if(typeof require == 'function'){
19859         exports.DocumentType = DocumentType;
19860         exports.DOMException = DOMException;
19861         exports.DOMImplementation = DOMImplementation;
19862         exports.Element = Element;
19863         exports.Node = Node;
19864         exports.NodeList = NodeList;
19865         exports.XMLSerializer = XMLSerializer;
19866 //}
19867 
19868 
19869 /***/ }),
19870 /* 26 */
19871 /***/ (function(module, exports, __webpack_require__) {
19872 
19873 var freeGlobal = __webpack_require__(52);
19874 
19875 /** Detect free variable `self`. */
19876 var freeSelf = typeof self == 'object' && self && self.Object === Object && self;
19877 
19878 /** Used as a reference to the global object. */
19879 var root = freeGlobal || freeSelf || Function('return this')();
19880 
19881 module.exports = root;
19882 
19883 
19884 /***/ }),
19885 /* 27 */
19886 /***/ (function(module, exports, __webpack_require__) {
19887 
19888 var root = __webpack_require__(26);
19889 
19890 /** Built-in value references. */
19891 var Symbol = root.Symbol;
19892 
19893 module.exports = Symbol;
19894 
19895 
19896 /***/ }),
19897 /* 28 */
19898 /***/ (function(module, exports, __webpack_require__) {
19899 
19900 var debounce = __webpack_require__(21),
19901     isObject = __webpack_require__(19);
19902 
19903 /** Error message constants. */
19904 var FUNC_ERROR_TEXT = 'Expected a function';
19905 
19906 /**
19907  * Creates a throttled function that only invokes `func` at most once per
19908  * every `wait` milliseconds. The throttled function comes with a `cancel`
19909  * method to cancel delayed `func` invocations and a `flush` method to
19910  * immediately invoke them. Provide `options` to indicate whether `func`
19911  * should be invoked on the leading and/or trailing edge of the `wait`
19912  * timeout. The `func` is invoked with the last arguments provided to the
19913  * throttled function. Subsequent calls to the throttled function return the
19914  * result of the last `func` invocation.
19915  *
19916  * **Note:** If `leading` and `trailing` options are `true`, `func` is
19917  * invoked on the trailing edge of the timeout only if the throttled function
19918  * is invoked more than once during the `wait` timeout.
19919  *
19920  * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred
19921  * until to the next tick, similar to `setTimeout` with a timeout of `0`.
19922  *
19923  * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/)
19924  * for details over the differences between `_.throttle` and `_.debounce`.
19925  *
19926  * @static
19927  * @memberOf _
19928  * @since 0.1.0
19929  * @category Function
19930  * @param {Function} func The function to throttle.
19931  * @param {number} [wait=0] The number of milliseconds to throttle invocations to.
19932  * @param {Object} [options={}] The options object.
19933  * @param {boolean} [options.leading=true]
19934  *  Specify invoking on the leading edge of the timeout.
19935  * @param {boolean} [options.trailing=true]
19936  *  Specify invoking on the trailing edge of the timeout.
19937  * @returns {Function} Returns the new throttled function.
19938  * @example
19939  *
19940  * // Avoid excessively updating the position while scrolling.
19941  * jQuery(window).on('scroll', _.throttle(updatePosition, 100));
19942  *
19943  * // Invoke `renewToken` when the click event is fired, but not more than once every 5 minutes.
19944  * var throttled = _.throttle(renewToken, 300000, { 'trailing': false });
19945  * jQuery(element).on('click', throttled);
19946  *
19947  * // Cancel the trailing throttled invocation.
19948  * jQuery(window).on('popstate', throttled.cancel);
19949  */
19950 function throttle(func, wait, options) {
19951   var leading = true,
19952       trailing = true;
19953 
19954   if (typeof func != 'function') {
19955     throw new TypeError(FUNC_ERROR_TEXT);
19956   }
19957   if (isObject(options)) {
19958     leading = 'leading' in options ? !!options.leading : leading;
19959     trailing = 'trailing' in options ? !!options.trailing : trailing;
19960   }
19961   return debounce(func, wait, {
19962     'leading': leading,
19963     'maxWait': wait,
19964     'trailing': trailing
19965   });
19966 }
19967 
19968 module.exports = throttle;
19969 
19970 
19971 /***/ }),
19972 /* 29 */
19973 /***/ (function(module, exports) {
19974 
19975 module.exports = __WEBPACK_EXTERNAL_MODULE__29__;
19976 
19977 /***/ }),
19978 /* 30 */
19979 /***/ (function(module, __webpack_exports__, __webpack_require__) {
19980 
19981 "use strict";
19982 __webpack_require__.r(__webpack_exports__);
19983 /* WEBPACK VAR INJECTION */(function(global) {/* harmony import */ var _book__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(24);
19984 /* harmony import */ var _rendition__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(16);
19985 /* harmony import */ var _epubcfi__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(2);
19986 /* harmony import */ var _contents__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(12);
19987 /* harmony import */ var _utils_core__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(0);
19988 /* harmony import */ var _utils_constants__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(1);
19989 /* harmony import */ var _managers_views_iframe__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(20);
19990 /* harmony import */ var _managers_default__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(10);
19991 /* harmony import */ var _managers_continuous__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(22);
19992 
19993 
19994 
19995 
19996 
19997 
19998 
19999 
20000 
20001 /**
20002  * Creates a new Book
20003  * @param {string|ArrayBuffer} url URL, Path or ArrayBuffer
20004  * @param {object} options to pass to the book
20005  * @returns {Book} a new Book object
20006  * @example ePub("/path/to/book.epub", {})
20007  */
20008 
20009 function ePub(url, options) {
20010   return new _book__WEBPACK_IMPORTED_MODULE_0__[/* default */ "a"](url, options);
20011 }
20012 
20013 ePub.VERSION = _utils_constants__WEBPACK_IMPORTED_MODULE_5__[/* EPUBJS_VERSION */ "b"];
20014 
20015 if (typeof global !== "undefined") {
20016   global.EPUBJS_VERSION = _utils_constants__WEBPACK_IMPORTED_MODULE_5__[/* EPUBJS_VERSION */ "b"];
20017 }
20018 
20019 ePub.Book = _book__WEBPACK_IMPORTED_MODULE_0__[/* default */ "a"];
20020 ePub.Rendition = _rendition__WEBPACK_IMPORTED_MODULE_1__[/* default */ "a"];
20021 ePub.Contents = _contents__WEBPACK_IMPORTED_MODULE_3__[/* default */ "a"];
20022 ePub.CFI = _epubcfi__WEBPACK_IMPORTED_MODULE_2__[/* default */ "a"];
20023 ePub.utils = _utils_core__WEBPACK_IMPORTED_MODULE_4__;
20024 /* harmony default export */ __webpack_exports__["default"] = (ePub);
20025 /* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(17)))
20026 
20027 /***/ }),
20028 /* 31 */
20029 /***/ (function(module, exports, __webpack_require__) {
20030 
20031 "use strict";
20032 
20033 
20034 var assign        = __webpack_require__(32)
20035   , normalizeOpts = __webpack_require__(40)
20036   , isCallable    = __webpack_require__(41)
20037   , contains      = __webpack_require__(42)
20038 
20039   , d;
20040 
20041 d = module.exports = function (dscr, value/*, options*/) {
20042         var c, e, w, options, desc;
20043         if ((arguments.length < 2) || (typeof dscr !== 'string')) {
20044                 options = value;
20045                 value = dscr;
20046                 dscr = null;
20047         } else {
20048                 options = arguments[2];
20049         }
20050         if (dscr == null) {
20051                 c = w = true;
20052                 e = false;
20053         } else {
20054                 c = contains.call(dscr, 'c');
20055                 e = contains.call(dscr, 'e');
20056                 w = contains.call(dscr, 'w');
20057         }
20058 
20059         desc = { value: value, configurable: c, enumerable: e, writable: w };
20060         return !options ? desc : assign(normalizeOpts(options), desc);
20061 };
20062 
20063 d.gs = function (dscr, get, set/*, options*/) {
20064         var c, e, options, desc;
20065         if (typeof dscr !== 'string') {
20066                 options = set;
20067                 set = get;
20068                 get = dscr;
20069                 dscr = null;
20070         } else {
20071                 options = arguments[3];
20072         }
20073         if (get == null) {
20074                 get = undefined;
20075         } else if (!isCallable(get)) {
20076                 options = get;
20077                 get = set = undefined;
20078         } else if (set == null) {
20079                 set = undefined;
20080         } else if (!isCallable(set)) {
20081                 options = set;
20082                 set = undefined;
20083         }
20084         if (dscr == null) {
20085                 c = true;
20086                 e = false;
20087         } else {
20088                 c = contains.call(dscr, 'c');
20089                 e = contains.call(dscr, 'e');
20090         }
20091 
20092         desc = { get: get, set: set, configurable: c, enumerable: e };
20093         return !options ? desc : assign(normalizeOpts(options), desc);
20094 };
20095 
20096 
20097 /***/ }),
20098 /* 32 */
20099 /***/ (function(module, exports, __webpack_require__) {
20100 
20101 "use strict";
20102 
20103 
20104 module.exports = __webpack_require__(33)()
20105         ? Object.assign
20106         : __webpack_require__(34);
20107 
20108 
20109 /***/ }),
20110 /* 33 */
20111 /***/ (function(module, exports, __webpack_require__) {
20112 
20113 "use strict";
20114 
20115 
20116 module.exports = function () {
20117         var assign = Object.assign, obj;
20118         if (typeof assign !== "function") return false;
20119         obj = { foo: "raz" };
20120         assign(obj, { bar: "dwa" }, { trzy: "trzy" });
20121         return (obj.foo + obj.bar + obj.trzy) === "razdwatrzy";
20122 };
20123 
20124 
20125 /***/ }),
20126 /* 34 */
20127 /***/ (function(module, exports, __webpack_require__) {
20128 
20129 "use strict";
20130 
20131 
20132 var keys  = __webpack_require__(35)
20133   , value = __webpack_require__(39)
20134   , max   = Math.max;
20135 
20136 module.exports = function (dest, src /*, …srcn*/) {
20137         var error, i, length = max(arguments.length, 2), assign;
20138         dest = Object(value(dest));
20139         assign = function (key) {
20140                 try {
20141                         dest[key] = src[key];
20142                 } catch (e) {
20143                         if (!error) error = e;
20144                 }
20145         };
20146         for (i = 1; i < length; ++i) {
20147                 src = arguments[i];
20148                 keys(src).forEach(assign);
20149         }
20150         if (error !== undefined) throw error;
20151         return dest;
20152 };
20153 
20154 
20155 /***/ }),
20156 /* 35 */
20157 /***/ (function(module, exports, __webpack_require__) {
20158 
20159 "use strict";
20160 
20161 
20162 module.exports = __webpack_require__(36)()
20163         ? Object.keys
20164         : __webpack_require__(37);
20165 
20166 
20167 /***/ }),
20168 /* 36 */
20169 /***/ (function(module, exports, __webpack_require__) {
20170 
20171 "use strict";
20172 
20173 
20174 module.exports = function () {
20175         try {
20176                 Object.keys("primitive");
20177                 return true;
20178         } catch (e) {
20179  return false;
20180 }
20181 };
20182 
20183 
20184 /***/ }),
20185 /* 37 */
20186 /***/ (function(module, exports, __webpack_require__) {
20187 
20188 "use strict";
20189 
20190 
20191 var isValue = __webpack_require__(18);
20192 
20193 var keys = Object.keys;
20194 
20195 module.exports = function (object) {
20196         return keys(isValue(object) ? Object(object) : object);
20197 };
20198 
20199 
20200 /***/ }),
20201 /* 38 */
20202 /***/ (function(module, exports, __webpack_require__) {
20203 
20204 "use strict";
20205 
20206 
20207 // eslint-disable-next-line no-empty-function
20208 module.exports = function () {};
20209 
20210 
20211 /***/ }),
20212 /* 39 */
20213 /***/ (function(module, exports, __webpack_require__) {
20214 
20215 "use strict";
20216 
20217 
20218 var isValue = __webpack_require__(18);
20219 
20220 module.exports = function (value) {
20221         if (!isValue(value)) throw new TypeError("Cannot use null or undefined");
20222         return value;
20223 };
20224 
20225 
20226 /***/ }),
20227 /* 40 */
20228 /***/ (function(module, exports, __webpack_require__) {
20229 
20230 "use strict";
20231 
20232 
20233 var isValue = __webpack_require__(18);
20234 
20235 var forEach = Array.prototype.forEach, create = Object.create;
20236 
20237 var process = function (src, obj) {
20238         var key;
20239         for (key in src) obj[key] = src[key];
20240 };
20241 
20242 // eslint-disable-next-line no-unused-vars
20243 module.exports = function (opts1 /*, …options*/) {
20244         var result = create(null);
20245         forEach.call(arguments, function (options) {
20246                 if (!isValue(options)) return;
20247                 process(Object(options), result);
20248         });
20249         return result;
20250 };
20251 
20252 
20253 /***/ }),
20254 /* 41 */
20255 /***/ (function(module, exports, __webpack_require__) {
20256 
20257 "use strict";
20258 // Deprecated
20259 
20260 
20261 
20262 module.exports = function (obj) {
20263  return typeof obj === "function";
20264 };
20265 
20266 
20267 /***/ }),
20268 /* 42 */
20269 /***/ (function(module, exports, __webpack_require__) {
20270 
20271 "use strict";
20272 
20273 
20274 module.exports = __webpack_require__(43)()
20275         ? String.prototype.contains
20276         : __webpack_require__(44);
20277 
20278 
20279 /***/ }),
20280 /* 43 */
20281 /***/ (function(module, exports, __webpack_require__) {
20282 
20283 "use strict";
20284 
20285 
20286 var str = "razdwatrzy";
20287 
20288 module.exports = function () {
20289         if (typeof str.contains !== "function") return false;
20290         return (str.contains("dwa") === true) && (str.contains("foo") === false);
20291 };
20292 
20293 
20294 /***/ }),
20295 /* 44 */
20296 /***/ (function(module, exports, __webpack_require__) {
20297 
20298 "use strict";
20299 
20300 
20301 var indexOf = String.prototype.indexOf;
20302 
20303 module.exports = function (searchString/*, position*/) {
20304         return indexOf.call(this, searchString, arguments[1]) > -1;
20305 };
20306 
20307 
20308 /***/ }),
20309 /* 45 */
20310 /***/ (function(module, exports, __webpack_require__) {
20311 
20312 "use strict";
20313 
20314 
20315 module.exports = function (fn) {
20316         if (typeof fn !== "function") throw new TypeError(fn + " is not a function");
20317         return fn;
20318 };
20319 
20320 
20321 /***/ }),
20322 /* 46 */
20323 /***/ (function(module, exports, __webpack_require__) {
20324 
20325 var conventions = __webpack_require__(14);
20326 var dom = __webpack_require__(25)
20327 var entities = __webpack_require__(47);
20328 var sax = __webpack_require__(48);
20329 
20330 var DOMImplementation = dom.DOMImplementation;
20331 
20332 var NAMESPACE = conventions.NAMESPACE;
20333 
20334 var ParseError = sax.ParseError;
20335 var XMLReader = sax.XMLReader;
20336 
20337 function DOMParser(options){
20338         this.options = options ||{locator:{}};
20339 }
20340 
20341 DOMParser.prototype.parseFromString = function(source,mimeType){
20342         var options = this.options;
20343         var sax =  new XMLReader();
20344         var domBuilder = options.domBuilder || new DOMHandler();//contentHandler and LexicalHandler
20345         var errorHandler = options.errorHandler;
20346         var locator = options.locator;
20347         var defaultNSMap = options.xmlns||{};
20348         var isHTML = /\/x?html?$/.test(mimeType);//mimeType.toLowerCase().indexOf('html') > -1;
20349         var entityMap = isHTML ? entities.HTML_ENTITIES : entities.XML_ENTITIES;
20350         if(locator){
20351                 domBuilder.setDocumentLocator(locator)
20352         }
20353 
20354         sax.errorHandler = buildErrorHandler(errorHandler,domBuilder,locator);
20355         sax.domBuilder = options.domBuilder || domBuilder;
20356         if(isHTML){
20357                 defaultNSMap[''] = NAMESPACE.HTML;
20358         }
20359         defaultNSMap.xml = defaultNSMap.xml || NAMESPACE.XML;
20360         if(source && typeof source === 'string'){
20361                 sax.parse(source,defaultNSMap,entityMap);
20362         }else{
20363                 sax.errorHandler.error("invalid doc source");
20364         }
20365         return domBuilder.doc;
20366 }
20367 function buildErrorHandler(errorImpl,domBuilder,locator){
20368         if(!errorImpl){
20369                 if(domBuilder instanceof DOMHandler){
20370                         return domBuilder;
20371                 }
20372                 errorImpl = domBuilder ;
20373         }
20374         var errorHandler = {}
20375         var isCallback = errorImpl instanceof Function;
20376         locator = locator||{}
20377         function build(key){
20378                 var fn = errorImpl[key];
20379                 if(!fn && isCallback){
20380                         fn = errorImpl.length == 2?function(msg){errorImpl(key,msg)}:errorImpl;
20381                 }
20382                 errorHandler[key] = fn && function(msg){
20383                         fn('[xmldom '+key+']\t'+msg+_locator(locator));
20384                 }||function(){};
20385         }
20386         build('warning');
20387         build('error');
20388         build('fatalError');
20389         return errorHandler;
20390 }
20391 
20392 //console.log('#\n\n\n\n\n\n\n####')
20393 /**
20394  * +ContentHandler+ErrorHandler
20395  * +LexicalHandler+EntityResolver2
20396  * -DeclHandler-DTDHandler
20397  *
20398  * DefaultHandler:EntityResolver, DTDHandler, ContentHandler, ErrorHandler
20399  * DefaultHandler2:DefaultHandler,LexicalHandler, DeclHandler, EntityResolver2
20400  * @link http://www.saxproject.org/apidoc/org/xml/sax/helpers/DefaultHandler.html
20401  */
20402 function DOMHandler() {
20403     this.cdata = false;
20404 }
20405 function position(locator,node){
20406         node.lineNumber = locator.lineNumber;
20407         node.columnNumber = locator.columnNumber;
20408 }
20409 /**
20410  * @see org.xml.sax.ContentHandler#startDocument
20411  * @link http://www.saxproject.org/apidoc/org/xml/sax/ContentHandler.html
20412  */
20413 DOMHandler.prototype = {
20414         startDocument : function() {
20415         this.doc = new DOMImplementation().createDocument(null, null, null);
20416         if (this.locator) {
20417                 this.doc.documentURI = this.locator.systemId;
20418         }
20419         },
20420         startElement:function(namespaceURI, localName, qName, attrs) {
20421                 var doc = this.doc;
20422             var el = doc.createElementNS(namespaceURI, qName||localName);
20423             var len = attrs.length;
20424             appendElement(this, el);
20425             this.currentElement = el;
20426 
20427                 this.locator && position(this.locator,el)
20428             for (var i = 0 ; i < len; i++) {
20429                 var namespaceURI = attrs.getURI(i);
20430                 var value = attrs.getValue(i);
20431                 var qName = attrs.getQName(i);
20432                         var attr = doc.createAttributeNS(namespaceURI, qName);
20433                         this.locator &&position(attrs.getLocator(i),attr);
20434                         attr.value = attr.nodeValue = value;
20435                         el.setAttributeNode(attr)
20436             }
20437         },
20438         endElement:function(namespaceURI, localName, qName) {
20439                 var current = this.currentElement
20440                 var tagName = current.tagName;
20441                 this.currentElement = current.parentNode;
20442         },
20443         startPrefixMapping:function(prefix, uri) {
20444         },
20445         endPrefixMapping:function(prefix) {
20446         },
20447         processingInstruction:function(target, data) {
20448             var ins = this.doc.createProcessingInstruction(target, data);
20449             this.locator && position(this.locator,ins)
20450             appendElement(this, ins);
20451         },
20452         ignorableWhitespace:function(ch, start, length) {
20453         },
20454         characters:function(chars, start, length) {
20455                 chars = _toString.apply(this,arguments)
20456                 //console.log(chars)
20457                 if(chars){
20458                         if (this.cdata) {
20459                                 var charNode = this.doc.createCDATASection(chars);
20460                         } else {
20461                                 var charNode = this.doc.createTextNode(chars);
20462                         }
20463                         if(this.currentElement){
20464                                 this.currentElement.appendChild(charNode);
20465                         }else if(/^\s*$/.test(chars)){
20466                                 this.doc.appendChild(charNode);
20467                                 //process xml
20468                         }
20469                         this.locator && position(this.locator,charNode)
20470                 }
20471         },
20472         skippedEntity:function(name) {
20473         },
20474         endDocument:function() {
20475                 this.doc.normalize();
20476         },
20477         setDocumentLocator:function (locator) {
20478             if(this.locator = locator){// && !('lineNumber' in locator)){
20479                 locator.lineNumber = 0;
20480             }
20481         },
20482         //LexicalHandler
20483         comment:function(chars, start, length) {
20484                 chars = _toString.apply(this,arguments)
20485             var comm = this.doc.createComment(chars);
20486             this.locator && position(this.locator,comm)
20487             appendElement(this, comm);
20488         },
20489 
20490         startCDATA:function() {
20491             //used in characters() methods
20492             this.cdata = true;
20493         },
20494         endCDATA:function() {
20495             this.cdata = false;
20496         },
20497 
20498         startDTD:function(name, publicId, systemId) {
20499                 var impl = this.doc.implementation;
20500             if (impl && impl.createDocumentType) {
20501                 var dt = impl.createDocumentType(name, publicId, systemId);
20502                 this.locator && position(this.locator,dt)
20503                 appendElement(this, dt);
20504                                         this.doc.doctype = dt;
20505             }
20506         },
20507         /**
20508          * @see org.xml.sax.ErrorHandler
20509          * @link http://www.saxproject.org/apidoc/org/xml/sax/ErrorHandler.html
20510          */
20511         warning:function(error) {
20512                 console.warn('[xmldom warning]\t'+error,_locator(this.locator));
20513         },
20514         error:function(error) {
20515                 console.error('[xmldom error]\t'+error,_locator(this.locator));
20516         },
20517         fatalError:function(error) {
20518                 throw new ParseError(error, this.locator);
20519         }
20520 }
20521 function _locator(l){
20522         if(l){
20523                 return '\n@'+(l.systemId ||'')+'#[line:'+l.lineNumber+',col:'+l.columnNumber+']'
20524         }
20525 }
20526 function _toString(chars,start,length){
20527         if(typeof chars == 'string'){
20528                 return chars.substr(start,length)
20529         }else{//java sax connect width xmldom on rhino(what about: "? && !(chars instanceof String)")
20530                 if(chars.length >= start+length || start){
20531                         return new java.lang.String(chars,start,length)+'';
20532                 }
20533                 return chars;
20534         }
20535 }
20536 
20537 /*
20538  * @link http://www.saxproject.org/apidoc/org/xml/sax/ext/LexicalHandler.html
20539  * used method of org.xml.sax.ext.LexicalHandler:
20540  *  #comment(chars, start, length)
20541  *  #startCDATA()
20542  *  #endCDATA()
20543  *  #startDTD(name, publicId, systemId)
20544  *
20545  *
20546  * IGNORED method of org.xml.sax.ext.LexicalHandler:
20547  *  #endDTD()
20548  *  #startEntity(name)
20549  *  #endEntity(name)
20550  *
20551  *
20552  * @link http://www.saxproject.org/apidoc/org/xml/sax/ext/DeclHandler.html
20553  * IGNORED method of org.xml.sax.ext.DeclHandler
20554  *      #attributeDecl(eName, aName, type, mode, value)
20555  *  #elementDecl(name, model)
20556  *  #externalEntityDecl(name, publicId, systemId)
20557  *  #internalEntityDecl(name, value)
20558  * @link http://www.saxproject.org/apidoc/org/xml/sax/ext/EntityResolver2.html
20559  * IGNORED method of org.xml.sax.EntityResolver2
20560  *  #resolveEntity(String name,String publicId,String baseURI,String systemId)
20561  *  #resolveEntity(publicId, systemId)
20562  *  #getExternalSubset(name, baseURI)
20563  * @link http://www.saxproject.org/apidoc/org/xml/sax/DTDHandler.html
20564  * IGNORED method of org.xml.sax.DTDHandler
20565  *  #notationDecl(name, publicId, systemId) {};
20566  *  #unparsedEntityDecl(name, publicId, systemId, notationName) {};
20567  */
20568 "endDTD,startEntity,endEntity,attributeDecl,elementDecl,externalEntityDecl,internalEntityDecl,resolveEntity,getExternalSubset,notationDecl,unparsedEntityDecl".replace(/\w+/g,function(key){
20569         DOMHandler.prototype[key] = function(){return null}
20570 })
20571 
20572 /* Private static helpers treated below as private instance methods, so don't need to add these to the public API; we might use a Relator to also get rid of non-standard public properties */
20573 function appendElement (hander,node) {
20574     if (!hander.currentElement) {
20575         hander.doc.appendChild(node);
20576     } else {
20577         hander.currentElement.appendChild(node);
20578     }
20579 }//appendChild and setAttributeNS are preformance key
20580 
20581 exports.__DOMHandler = DOMHandler;
20582 exports.DOMParser = DOMParser;
20583 
20584 /**
20585  * @deprecated Import/require from main entry point instead
20586  */
20587 exports.DOMImplementation = dom.DOMImplementation;
20588 
20589 /**
20590  * @deprecated Import/require from main entry point instead
20591  */
20592 exports.XMLSerializer = dom.XMLSerializer;
20593 
20594 
20595 /***/ }),
20596 /* 47 */
20597 /***/ (function(module, exports, __webpack_require__) {
20598 
20599 var freeze = __webpack_require__(14).freeze;
20600 
20601 /**
20602  * The entities that are predefined in every XML document.
20603  *
20604  * @see https://www.w3.org/TR/2006/REC-xml11-20060816/#sec-predefined-ent W3C XML 1.1
20605  * @see https://www.w3.org/TR/2008/REC-xml-20081126/#sec-predefined-ent W3C XML 1.0
20606  * @see https://en.wikipedia.org/wiki/List_of_XML_and_HTML_character_entity_references#Predefined_entities_in_XML Wikipedia
20607  */
20608 exports.XML_ENTITIES = freeze({amp:'&', apos:"'", gt:'>', lt:'<', quot:'"'})
20609 
20610 /**
20611  * A map of currently 241 entities that are detected in an HTML document.
20612  * They contain all entries from `XML_ENTITIES`.
20613  *
20614  * @see XML_ENTITIES
20615  * @see DOMParser.parseFromString
20616  * @see DOMImplementation.prototype.createHTMLDocument
20617  * @see https://html.spec.whatwg.org/#named-character-references WHATWG HTML(5) Spec
20618  * @see https://www.w3.org/TR/xml-entity-names/ W3C XML Entity Names
20619  * @see https://www.w3.org/TR/html4/sgml/entities.html W3C HTML4/SGML
20620  * @see https://en.wikipedia.org/wiki/List_of_XML_and_HTML_character_entity_references#Character_entity_references_in_HTML Wikipedia (HTML)
20621  * @see https://en.wikipedia.org/wiki/List_of_XML_and_HTML_character_entity_references#Entities_representing_special_characters_in_XHTML Wikpedia (XHTML)
20622  */
20623 exports.HTML_ENTITIES = freeze({
20624        lt: '<',
20625        gt: '>',
20626        amp: '&',
20627        quot: '"',
20628        apos: "'",
20629        Agrave: "À",
20630        Aacute: "Á",
20631        Acirc: "Â",
20632        Atilde: "Ã",
20633        Auml: "Ä",
20634        Aring: "Å",
20635        AElig: "Æ",
20636        Ccedil: "Ç",
20637        Egrave: "È",
20638        Eacute: "É",
20639        Ecirc: "Ê",
20640        Euml: "Ë",
20641        Igrave: "Ì",
20642        Iacute: "Í",
20643        Icirc: "Î",
20644        Iuml: "Ï",
20645        ETH: "Ð",
20646        Ntilde: "Ñ",
20647        Ograve: "Ò",
20648        Oacute: "Ó",
20649        Ocirc: "Ô",
20650        Otilde: "Õ",
20651        Ouml: "Ö",
20652        Oslash: "Ø",
20653        Ugrave: "Ù",
20654        Uacute: "Ú",
20655        Ucirc: "Û",
20656        Uuml: "Ü",
20657        Yacute: "Ý",
20658        THORN: "Þ",
20659        szlig: "ß",
20660        agrave: "à",
20661        aacute: "á",
20662        acirc: "â",
20663        atilde: "ã",
20664        auml: "ä",
20665        aring: "å",
20666        aelig: "æ",
20667        ccedil: "ç",
20668        egrave: "è",
20669        eacute: "é",
20670        ecirc: "ê",
20671        euml: "ë",
20672        igrave: "ì",
20673        iacute: "í",
20674        icirc: "î",
20675        iuml: "ï",
20676        eth: "ð",
20677        ntilde: "ñ",
20678        ograve: "ò",
20679        oacute: "ó",
20680        ocirc: "ô",
20681        otilde: "õ",
20682        ouml: "ö",
20683        oslash: "ø",
20684        ugrave: "ù",
20685        uacute: "ú",
20686        ucirc: "û",
20687        uuml: "ü",
20688        yacute: "ý",
20689        thorn: "þ",
20690        yuml: "ÿ",
20691        nbsp: "\u00a0",
20692        iexcl: "¡",
20693        cent: "¢",
20694        pound: "£",
20695        curren: "¤",
20696        yen: "¥",
20697        brvbar: "¦",
20698        sect: "§",
20699        uml: "¨",
20700        copy: "©",
20701        ordf: "ª",
20702        laquo: "«",
20703        not: "¬",
20704        shy: "­­",
20705        reg: "®",
20706        macr: "¯",
20707        deg: "°",
20708        plusmn: "±",
20709        sup2: "²",
20710        sup3: "³",
20711        acute: "´",
20712        micro: "µ",
20713        para: "¶",
20714        middot: "·",
20715        cedil: "¸",
20716        sup1: "¹",
20717        ordm: "º",
20718        raquo: "»",
20719        frac14: "¼",
20720        frac12: "½",
20721        frac34: "¾",
20722        iquest: "¿",
20723        times: "×",
20724        divide: "÷",
20725        forall: "∀",
20726        part: "∂",
20727        exist: "∃",
20728        empty: "∅",
20729        nabla: "∇",
20730        isin: "∈",
20731        notin: "∉",
20732        ni: "∋",
20733        prod: "∏",
20734        sum: "∑",
20735        minus: "−",
20736        lowast: "∗",
20737        radic: "√",
20738        prop: "∝",
20739        infin: "∞",
20740        ang: "∠",
20741        and: "∧",
20742        or: "∨",
20743        cap: "∩",
20744        cup: "∪",
20745        'int': "∫",
20746        there4: "∴",
20747        sim: "∼",
20748        cong: "≅",
20749        asymp: "≈",
20750        ne: "≠",
20751        equiv: "≡",
20752        le: "≤",
20753        ge: "≥",
20754        sub: "⊂",
20755        sup: "⊃",
20756        nsub: "⊄",
20757        sube: "⊆",
20758        supe: "⊇",
20759        oplus: "⊕",
20760        otimes: "⊗",
20761        perp: "⊥",
20762        sdot: "⋅",
20763        Alpha: "Α",
20764        Beta: "Β",
20765        Gamma: "Γ",
20766        Delta: "Δ",
20767        Epsilon: "Ε",
20768        Zeta: "Ζ",
20769        Eta: "Η",
20770        Theta: "Θ",
20771        Iota: "Ι",
20772        Kappa: "Κ",
20773        Lambda: "Λ",
20774        Mu: "Μ",
20775        Nu: "Ν",
20776        Xi: "Ξ",
20777        Omicron: "Ο",
20778        Pi: "Π",
20779        Rho: "Ρ",
20780        Sigma: "Σ",
20781        Tau: "Τ",
20782        Upsilon: "Υ",
20783        Phi: "Φ",
20784        Chi: "Χ",
20785        Psi: "Ψ",
20786        Omega: "Ω",
20787        alpha: "α",
20788        beta: "β",
20789        gamma: "γ",
20790        delta: "δ",
20791        epsilon: "ε",
20792        zeta: "ζ",
20793        eta: "η",
20794        theta: "θ",
20795        iota: "ι",
20796        kappa: "κ",
20797        lambda: "λ",
20798        mu: "μ",
20799        nu: "ν",
20800        xi: "ξ",
20801        omicron: "ο",
20802        pi: "π",
20803        rho: "ρ",
20804        sigmaf: "ς",
20805        sigma: "σ",
20806        tau: "τ",
20807        upsilon: "υ",
20808        phi: "φ",
20809        chi: "χ",
20810        psi: "ψ",
20811        omega: "ω",
20812        thetasym: "ϑ",
20813        upsih: "ϒ",
20814        piv: "ϖ",
20815        OElig: "Œ",
20816        oelig: "œ",
20817        Scaron: "Š",
20818        scaron: "š",
20819        Yuml: "Ÿ",
20820        fnof: "ƒ",
20821        circ: "ˆ",
20822        tilde: "˜",
20823        ensp: " ",
20824        emsp: " ",
20825        thinsp: " ",
20826        zwnj: "‌",
20827        zwj: "‍",
20828        lrm: "‎",
20829        rlm: "‏",
20830        ndash: "–",
20831        mdash: "—",
20832        lsquo: "‘",
20833        rsquo: "’",
20834        sbquo: "‚",
20835        ldquo: "“",
20836        rdquo: "”",
20837        bdquo: "„",
20838        dagger: "†",
20839        Dagger: "‡",
20840        bull: "•",
20841        hellip: "…",
20842        permil: "‰",
20843        prime: "′",
20844        Prime: "″",
20845        lsaquo: "‹",
20846        rsaquo: "›",
20847        oline: "‾",
20848        euro: "€",
20849        trade: "™",
20850        larr: "←",
20851        uarr: "↑",
20852        rarr: "→",
20853        darr: "↓",
20854        harr: "↔",
20855        crarr: "↵",
20856        lceil: "⌈",
20857        rceil: "⌉",
20858        lfloor: "⌊",
20859        rfloor: "⌋",
20860        loz: "◊",
20861        spades: "♠",
20862        clubs: "♣",
20863        hearts: "♥",
20864        diams: "♦"
20865 });
20866 
20867 /**
20868  * @deprecated use `HTML_ENTITIES` instead
20869  * @see HTML_ENTITIES
20870  */
20871 exports.entityMap = exports.HTML_ENTITIES
20872 
20873 
20874 /***/ }),
20875 /* 48 */
20876 /***/ (function(module, exports, __webpack_require__) {
20877 
20878 var NAMESPACE = __webpack_require__(14).NAMESPACE;
20879 
20880 //[4]           NameStartChar      ::=          ":" | [A-Z] | "_" | [a-z] | [#xC0-#xD6] | [#xD8-#xF6] | [#xF8-#x2FF] | [#x370-#x37D] | [#x37F-#x1FFF] | [#x200C-#x200D] | [#x2070-#x218F] | [#x2C00-#x2FEF] | [#x3001-#xD7FF] | [#xF900-#xFDCF] | [#xFDF0-#xFFFD] | [#x10000-#xEFFFF]
20881 //[4a]          NameChar           ::=          NameStartChar | "-" | "." | [0-9] | #xB7 | [#x0300-#x036F] | [#x203F-#x2040]
20882 //[5]           Name       ::=          NameStartChar (NameChar)*
20883 var nameStartChar = /[A-Z_a-z\xC0-\xD6\xD8-\xF6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD]///\u10000-\uEFFFF
20884 var nameChar = new RegExp("[\\-\\.0-9"+nameStartChar.source.slice(1,-1)+"\\u00B7\\u0300-\\u036F\\u203F-\\u2040]");
20885 var tagNamePattern = new RegExp('^'+nameStartChar.source+nameChar.source+'*(?:\:'+nameStartChar.source+nameChar.source+'*)?$');
20886 //var tagNamePattern = /^[a-zA-Z_][\w\-\.]*(?:\:[a-zA-Z_][\w\-\.]*)?$/
20887 //var handlers = 'resolveEntity,getExternalSubset,characters,endDocument,endElement,endPrefixMapping,ignorableWhitespace,processingInstruction,setDocumentLocator,skippedEntity,startDocument,startElement,startPrefixMapping,notationDecl,unparsedEntityDecl,error,fatalError,warning,attributeDecl,elementDecl,externalEntityDecl,internalEntityDecl,comment,endCDATA,endDTD,endEntity,startCDATA,startDTD,startEntity'.split(',')
20888 
20889 //S_TAG,        S_ATTR, S_EQ,   S_ATTR_NOQUOT_VALUE
20890 //S_ATTR_SPACE, S_ATTR_END,     S_TAG_SPACE, S_TAG_CLOSE
20891 var S_TAG = 0;//tag name offerring
20892 var S_ATTR = 1;//attr name offerring 
20893 var S_ATTR_SPACE=2;//attr name end and space offer
20894 var S_EQ = 3;//=space?
20895 var S_ATTR_NOQUOT_VALUE = 4;//attr value(no quot value only)
20896 var S_ATTR_END = 5;//attr value end and no space(quot end)
20897 var S_TAG_SPACE = 6;//(attr value end || tag end ) && (space offer)
20898 var S_TAG_CLOSE = 7;//closed el<el />
20899 
20900 /**
20901  * Creates an error that will not be caught by XMLReader aka the SAX parser.
20902  *
20903  * @param {string} message
20904  * @param {any?} locator Optional, can provide details about the location in the source
20905  * @constructor
20906  */
20907 function ParseError(message, locator) {
20908         this.message = message
20909         this.locator = locator
20910         if(Error.captureStackTrace) Error.captureStackTrace(this, ParseError);
20911 }
20912 ParseError.prototype = new Error();
20913 ParseError.prototype.name = ParseError.name
20914 
20915 function XMLReader(){
20916         
20917 }
20918 
20919 XMLReader.prototype = {
20920         parse:function(source,defaultNSMap,entityMap){
20921                 var domBuilder = this.domBuilder;
20922                 domBuilder.startDocument();
20923                 _copy(defaultNSMap ,defaultNSMap = {})
20924                 parse(source,defaultNSMap,entityMap,
20925                                 domBuilder,this.errorHandler);
20926                 domBuilder.endDocument();
20927         }
20928 }
20929 function parse(source,defaultNSMapCopy,entityMap,domBuilder,errorHandler){
20930         function fixedFromCharCode(code) {
20931                 // String.prototype.fromCharCode does not supports
20932                 // > 2 bytes unicode chars directly
20933                 if (code > 0xffff) {
20934                         code -= 0x10000;
20935                         var surrogate1 = 0xd800 + (code >> 10)
20936                                 , surrogate2 = 0xdc00 + (code & 0x3ff);
20937 
20938                         return String.fromCharCode(surrogate1, surrogate2);
20939                 } else {
20940                         return String.fromCharCode(code);
20941                 }
20942         }
20943         function entityReplacer(a){
20944                 var k = a.slice(1,-1);
20945                 if(k in entityMap){
20946                         return entityMap[k]; 
20947                 }else if(k.charAt(0) === '#'){
20948                         return fixedFromCharCode(parseInt(k.substr(1).replace('x','0x')))
20949                 }else{
20950                         errorHandler.error('entity not found:'+a);
20951                         return a;
20952                 }
20953         }
20954         function appendText(end){//has some bugs
20955                 if(end>start){
20956                         var xt = source.substring(start,end).replace(/&#?\w+;/g,entityReplacer);
20957                         locator&&position(start);
20958                         domBuilder.characters(xt,0,end-start);
20959                         start = end
20960                 }
20961         }
20962         function position(p,m){
20963                 while(p>=lineEnd && (m = linePattern.exec(source))){
20964                         lineStart = m.index;
20965                         lineEnd = lineStart + m[0].length;
20966                         locator.lineNumber++;
20967                         //console.log('line++:',locator,startPos,endPos)
20968                 }
20969                 locator.columnNumber = p-lineStart+1;
20970         }
20971         var lineStart = 0;
20972         var lineEnd = 0;
20973         var linePattern = /.*(?:\r\n?|\n)|.*$/g
20974         var locator = domBuilder.locator;
20975         
20976         var parseStack = [{currentNSMap:defaultNSMapCopy}]
20977         var closeMap = {};
20978         var start = 0;
20979         while(true){
20980                 try{
20981                         var tagStart = source.indexOf('<',start);
20982                         if(tagStart<0){
20983                                 if(!source.substr(start).match(/^\s*$/)){
20984                                         var doc = domBuilder.doc;
20985                                 var text = doc.createTextNode(source.substr(start));
20986                                 doc.appendChild(text);
20987                                 domBuilder.currentElement = text;
20988                                 }
20989                                 return;
20990                         }
20991                         if(tagStart>start){
20992                                 appendText(tagStart);
20993                         }
20994                         switch(source.charAt(tagStart+1)){
20995                         case '/':
20996                                 var end = source.indexOf('>',tagStart+3);
20997                                 var tagName = source.substring(tagStart + 2, end).replace(/[ \t\n\r]+$/g, '');
20998                                 var config = parseStack.pop();
20999                                 if(end<0){
21000                                         
21001                                 tagName = source.substring(tagStart+2).replace(/[\s<].*/,'');
21002                                 errorHandler.error("end tag name: "+tagName+' is not complete:'+config.tagName);
21003                                 end = tagStart+1+tagName.length;
21004                         }else if(tagName.match(/\s</)){
21005                                 tagName = tagName.replace(/[\s<].*/,'');
21006                                 errorHandler.error("end tag name: "+tagName+' maybe not complete');
21007                                 end = tagStart+1+tagName.length;
21008                                 }
21009                                 var localNSMap = config.localNSMap;
21010                                 var endMatch = config.tagName == tagName;
21011                                 var endIgnoreCaseMach = endMatch || config.tagName&&config.tagName.toLowerCase() == tagName.toLowerCase()
21012                         if(endIgnoreCaseMach){
21013                                 domBuilder.endElement(config.uri,config.localName,tagName);
21014                                         if(localNSMap){
21015                                                 for(var prefix in localNSMap){
21016                                                         domBuilder.endPrefixMapping(prefix) ;
21017                                                 }
21018                                         }
21019                                         if(!endMatch){
21020                                 errorHandler.fatalError("end tag name: "+tagName+' is not match the current start tagName:'+config.tagName ); // No known test case
21021                                         }
21022                         }else{
21023                                 parseStack.push(config)
21024                         }
21025                                 
21026                                 end++;
21027                                 break;
21028                                 // end elment
21029                         case '?':// <?...?>
21030                                 locator&&position(tagStart);
21031                                 end = parseInstruction(source,tagStart,domBuilder);
21032                                 break;
21033                         case '!':// <!doctype,<![CDATA,<!--
21034                                 locator&&position(tagStart);
21035                                 end = parseDCC(source,tagStart,domBuilder,errorHandler);
21036                                 break;
21037                         default:
21038                                 locator&&position(tagStart);
21039                                 var el = new ElementAttributes();
21040                                 var currentNSMap = parseStack[parseStack.length-1].currentNSMap;
21041                                 //elStartEnd
21042                                 var end = parseElementStartPart(source,tagStart,el,currentNSMap,entityReplacer,errorHandler);
21043                                 var len = el.length;
21044                                 
21045                                 
21046                                 if(!el.closed && fixSelfClosed(source,end,el.tagName,closeMap)){
21047                                         el.closed = true;
21048                                         if(!entityMap.nbsp){
21049                                                 errorHandler.warning('unclosed xml attribute');
21050                                         }
21051                                 }
21052                                 if(locator && len){
21053                                         var locator2 = copyLocator(locator,{});
21054                                         //try{//attribute position fixed
21055                                         for(var i = 0;i<len;i++){
21056                                                 var a = el[i];
21057                                                 position(a.offset);
21058                                                 a.locator = copyLocator(locator,{});
21059                                         }
21060                                         domBuilder.locator = locator2
21061                                         if(appendElement(el,domBuilder,currentNSMap)){
21062                                                 parseStack.push(el)
21063                                         }
21064                                         domBuilder.locator = locator;
21065                                 }else{
21066                                         if(appendElement(el,domBuilder,currentNSMap)){
21067                                                 parseStack.push(el)
21068                                         }
21069                                 }
21070 
21071                                 if (NAMESPACE.isHTML(el.uri) && !el.closed) {
21072                                         end = parseHtmlSpecialContent(source,end,el.tagName,entityReplacer,domBuilder)
21073                                 } else {
21074                                         end++;
21075                                 }
21076                         }
21077                 }catch(e){
21078                         if (e instanceof ParseError) {
21079                                 throw e;
21080                         }
21081                         errorHandler.error('element parse error: '+e)
21082                         end = -1;
21083                 }
21084                 if(end>start){
21085                         start = end;
21086                 }else{
21087                         //TODO: 这里有可能sax回退,有位置错误风险
21088                         appendText(Math.max(tagStart,start)+1);
21089                 }
21090         }
21091 }
21092 function copyLocator(f,t){
21093         t.lineNumber = f.lineNumber;
21094         t.columnNumber = f.columnNumber;
21095         return t;
21096 }
21097 
21098 /**
21099  * @see #appendElement(source,elStartEnd,el,selfClosed,entityReplacer,domBuilder,parseStack);
21100  * @return end of the elementStartPart(end of elementEndPart for selfClosed el)
21101  */
21102 function parseElementStartPart(source,start,el,currentNSMap,entityReplacer,errorHandler){
21103 
21104         /**
21105          * @param {string} qname
21106          * @param {string} value
21107          * @param {number} startIndex
21108          */
21109         function addAttribute(qname, value, startIndex) {
21110                 if (el.attributeNames.hasOwnProperty(qname)) {
21111                         errorHandler.fatalError('Attribute ' + qname + ' redefined')
21112                 }
21113                 el.addValue(qname, value, startIndex)
21114         }
21115         var attrName;
21116         var value;
21117         var p = ++start;
21118         var s = S_TAG;//status
21119         while(true){
21120                 var c = source.charAt(p);
21121                 switch(c){
21122                 case '=':
21123                         if(s === S_ATTR){//attrName
21124                                 attrName = source.slice(start,p);
21125                                 s = S_EQ;
21126                         }else if(s === S_ATTR_SPACE){
21127                                 s = S_EQ;
21128                         }else{
21129                                 //fatalError: equal must after attrName or space after attrName
21130                                 throw new Error('attribute equal must after attrName'); // No known test case
21131                         }
21132                         break;
21133                 case '\'':
21134                 case '"':
21135                         if(s === S_EQ || s === S_ATTR //|| s == S_ATTR_SPACE
21136                                 ){//equal
21137                                 if(s === S_ATTR){
21138                                         errorHandler.warning('attribute value must after "="')
21139                                         attrName = source.slice(start,p)
21140                                 }
21141                                 start = p+1;
21142                                 p = source.indexOf(c,start)
21143                                 if(p>0){
21144                                         value = source.slice(start,p).replace(/&#?\w+;/g,entityReplacer);
21145                                         addAttribute(attrName, value, start-1);
21146                                         s = S_ATTR_END;
21147                                 }else{
21148                                         //fatalError: no end quot match
21149                                         throw new Error('attribute value no end \''+c+'\' match');
21150                                 }
21151                         }else if(s == S_ATTR_NOQUOT_VALUE){
21152                                 value = source.slice(start,p).replace(/&#?\w+;/g,entityReplacer);
21153                                 //console.log(attrName,value,start,p)
21154                                 addAttribute(attrName, value, start);
21155                                 //console.dir(el)
21156                                 errorHandler.warning('attribute "'+attrName+'" missed start quot('+c+')!!');
21157                                 start = p+1;
21158                                 s = S_ATTR_END
21159                         }else{
21160                                 //fatalError: no equal before
21161                                 throw new Error('attribute value must after "="'); // No known test case
21162                         }
21163                         break;
21164                 case '/':
21165                         switch(s){
21166                         case S_TAG:
21167                                 el.setTagName(source.slice(start,p));
21168                         case S_ATTR_END:
21169                         case S_TAG_SPACE:
21170                         case S_TAG_CLOSE:
21171                                 s =S_TAG_CLOSE;
21172                                 el.closed = true;
21173                         case S_ATTR_NOQUOT_VALUE:
21174                         case S_ATTR:
21175                         case S_ATTR_SPACE:
21176                                 break;
21177                         //case S_EQ:
21178                         default:
21179                                 throw new Error("attribute invalid close char('/')") // No known test case
21180                         }
21181                         break;
21182                 case ''://end document
21183                         errorHandler.error('unexpected end of input');
21184                         if(s == S_TAG){
21185                                 el.setTagName(source.slice(start,p));
21186                         }
21187                         return p;
21188                 case '>':
21189                         switch(s){
21190                         case S_TAG:
21191                                 el.setTagName(source.slice(start,p));
21192                         case S_ATTR_END:
21193                         case S_TAG_SPACE:
21194                         case S_TAG_CLOSE:
21195                                 break;//normal
21196                         case S_ATTR_NOQUOT_VALUE://Compatible state
21197                         case S_ATTR:
21198                                 value = source.slice(start,p);
21199                                 if(value.slice(-1) === '/'){
21200                                         el.closed  = true;
21201                                         value = value.slice(0,-1)
21202                                 }
21203                         case S_ATTR_SPACE:
21204                                 if(s === S_ATTR_SPACE){
21205                                         value = attrName;
21206                                 }
21207                                 if(s == S_ATTR_NOQUOT_VALUE){
21208                                         errorHandler.warning('attribute "'+value+'" missed quot(")!');
21209                                         addAttribute(attrName, value.replace(/&#?\w+;/g,entityReplacer), start)
21210                                 }else{
21211                                         if(!NAMESPACE.isHTML(currentNSMap['']) || !value.match(/^(?:disabled|checked|selected)$/i)){
21212                                                 errorHandler.warning('attribute "'+value+'" missed value!! "'+value+'" instead!!')
21213                                         }
21214                                         addAttribute(value, value, start)
21215                                 }
21216                                 break;
21217                         case S_EQ:
21218                                 throw new Error('attribute value missed!!');
21219                         }
21220 //                      console.log(tagName,tagNamePattern,tagNamePattern.test(tagName))
21221                         return p;
21222                 /*xml space '\x20' | #x9 | #xD | #xA; */
21223                 case '\u0080':
21224                         c = ' ';
21225                 default:
21226                         if(c<= ' '){//space
21227                                 switch(s){
21228                                 case S_TAG:
21229                                         el.setTagName(source.slice(start,p));//tagName
21230                                         s = S_TAG_SPACE;
21231                                         break;
21232                                 case S_ATTR:
21233                                         attrName = source.slice(start,p)
21234                                         s = S_ATTR_SPACE;
21235                                         break;
21236                                 case S_ATTR_NOQUOT_VALUE:
21237                                         var value = source.slice(start,p).replace(/&#?\w+;/g,entityReplacer);
21238                                         errorHandler.warning('attribute "'+value+'" missed quot(")!!');
21239                                         addAttribute(attrName, value, start)
21240                                 case S_ATTR_END:
21241                                         s = S_TAG_SPACE;
21242                                         break;
21243                                 //case S_TAG_SPACE:
21244                                 //case S_EQ:
21245                                 //case S_ATTR_SPACE:
21246                                 //      void();break;
21247                                 //case S_TAG_CLOSE:
21248                                         //ignore warning
21249                                 }
21250                         }else{//not space
21251 //S_TAG,        S_ATTR, S_EQ,   S_ATTR_NOQUOT_VALUE
21252 //S_ATTR_SPACE, S_ATTR_END,     S_TAG_SPACE, S_TAG_CLOSE
21253                                 switch(s){
21254                                 //case S_TAG:void();break;
21255                                 //case S_ATTR:void();break;
21256                                 //case S_ATTR_NOQUOT_VALUE:void();break;
21257                                 case S_ATTR_SPACE:
21258                                         var tagName =  el.tagName;
21259                                         if (!NAMESPACE.isHTML(currentNSMap['']) || !attrName.match(/^(?:disabled|checked|selected)$/i)) {
21260                                                 errorHandler.warning('attribute "'+attrName+'" missed value!! "'+attrName+'" instead2!!')
21261                                         }
21262                                         addAttribute(attrName, attrName, start);
21263                                         start = p;
21264                                         s = S_ATTR;
21265                                         break;
21266                                 case S_ATTR_END:
21267                                         errorHandler.warning('attribute space is required"'+attrName+'"!!')
21268                                 case S_TAG_SPACE:
21269                                         s = S_ATTR;
21270                                         start = p;
21271                                         break;
21272                                 case S_EQ:
21273                                         s = S_ATTR_NOQUOT_VALUE;
21274                                         start = p;
21275                                         break;
21276                                 case S_TAG_CLOSE:
21277                                         throw new Error("elements closed character '/' and '>' must be connected to");
21278                                 }
21279                         }
21280                 }//end outer switch
21281                 //console.log('p++',p)
21282                 p++;
21283         }
21284 }
21285 /**
21286  * @return true if has new namespace define
21287  */
21288 function appendElement(el,domBuilder,currentNSMap){
21289         var tagName = el.tagName;
21290         var localNSMap = null;
21291         //var currentNSMap = parseStack[parseStack.length-1].currentNSMap;
21292         var i = el.length;
21293         while(i--){
21294                 var a = el[i];
21295                 var qName = a.qName;
21296                 var value = a.value;
21297                 var nsp = qName.indexOf(':');
21298                 if(nsp>0){
21299                         var prefix = a.prefix = qName.slice(0,nsp);
21300                         var localName = qName.slice(nsp+1);
21301                         var nsPrefix = prefix === 'xmlns' && localName
21302                 }else{
21303                         localName = qName;
21304                         prefix = null
21305                         nsPrefix = qName === 'xmlns' && ''
21306                 }
21307                 //can not set prefix,because prefix !== ''
21308                 a.localName = localName ;
21309                 //prefix == null for no ns prefix attribute 
21310                 if(nsPrefix !== false){//hack!!
21311                         if(localNSMap == null){
21312                                 localNSMap = {}
21313                                 //console.log(currentNSMap,0)
21314                                 _copy(currentNSMap,currentNSMap={})
21315                                 //console.log(currentNSMap,1)
21316                         }
21317                         currentNSMap[nsPrefix] = localNSMap[nsPrefix] = value;
21318                         a.uri = NAMESPACE.XMLNS
21319                         domBuilder.startPrefixMapping(nsPrefix, value) 
21320                 }
21321         }
21322         var i = el.length;
21323         while(i--){
21324                 a = el[i];
21325                 var prefix = a.prefix;
21326                 if(prefix){//no prefix attribute has no namespace
21327                         if(prefix === 'xml'){
21328                                 a.uri = NAMESPACE.XML;
21329                         }if(prefix !== 'xmlns'){
21330                                 a.uri = currentNSMap[prefix || '']
21331                                 
21332                                 //{console.log('###'+a.qName,domBuilder.locator.systemId+'',currentNSMap,a.uri)}
21333                         }
21334                 }
21335         }
21336         var nsp = tagName.indexOf(':');
21337         if(nsp>0){
21338                 prefix = el.prefix = tagName.slice(0,nsp);
21339                 localName = el.localName = tagName.slice(nsp+1);
21340         }else{
21341                 prefix = null;//important!!
21342                 localName = el.localName = tagName;
21343         }
21344         //no prefix element has default namespace
21345         var ns = el.uri = currentNSMap[prefix || ''];
21346         domBuilder.startElement(ns,localName,tagName,el);
21347         //endPrefixMapping and startPrefixMapping have not any help for dom builder
21348         //localNSMap = null
21349         if(el.closed){
21350                 domBuilder.endElement(ns,localName,tagName);
21351                 if(localNSMap){
21352                         for(prefix in localNSMap){
21353                                 domBuilder.endPrefixMapping(prefix) 
21354                         }
21355                 }
21356         }else{
21357                 el.currentNSMap = currentNSMap;
21358                 el.localNSMap = localNSMap;
21359                 //parseStack.push(el);
21360                 return true;
21361         }
21362 }
21363 function parseHtmlSpecialContent(source,elStartEnd,tagName,entityReplacer,domBuilder){
21364         if(/^(?:script|textarea)$/i.test(tagName)){
21365                 var elEndStart =  source.indexOf('</'+tagName+'>',elStartEnd);
21366                 var text = source.substring(elStartEnd+1,elEndStart);
21367                 if(/[&<]/.test(text)){
21368                         if(/^script$/i.test(tagName)){
21369                                 //if(!/\]\]>/.test(text)){
21370                                         //lexHandler.startCDATA();
21371                                         domBuilder.characters(text,0,text.length);
21372                                         //lexHandler.endCDATA();
21373                                         return elEndStart;
21374                                 //}
21375                         }//}else{//text area
21376                                 text = text.replace(/&#?\w+;/g,entityReplacer);
21377                                 domBuilder.characters(text,0,text.length);
21378                                 return elEndStart;
21379                         //}
21380                         
21381                 }
21382         }
21383         return elStartEnd+1;
21384 }
21385 function fixSelfClosed(source,elStartEnd,tagName,closeMap){
21386         //if(tagName in closeMap){
21387         var pos = closeMap[tagName];
21388         if(pos == null){
21389                 //console.log(tagName)
21390                 pos =  source.lastIndexOf('</'+tagName+'>')
21391                 if(pos<elStartEnd){//忘记闭合
21392                         pos = source.lastIndexOf('</'+tagName)
21393                 }
21394                 closeMap[tagName] =pos
21395         }
21396         return pos<elStartEnd;
21397         //} 
21398 }
21399 function _copy(source,target){
21400         for(var n in source){target[n] = source[n]}
21401 }
21402 function parseDCC(source,start,domBuilder,errorHandler){//sure start with '<!'
21403         var next= source.charAt(start+2)
21404         switch(next){
21405         case '-':
21406                 if(source.charAt(start + 3) === '-'){
21407                         var end = source.indexOf('-->',start+4);
21408                         //append comment source.substring(4,end)//<!--
21409                         if(end>start){
21410                                 domBuilder.comment(source,start+4,end-start-4);
21411                                 return end+3;
21412                         }else{
21413                                 errorHandler.error("Unclosed comment");
21414                                 return -1;
21415                         }
21416                 }else{
21417                         //error
21418                         return -1;
21419                 }
21420         default:
21421                 if(source.substr(start+3,6) == 'CDATA['){
21422                         var end = source.indexOf(']]>',start+9);
21423                         domBuilder.startCDATA();
21424                         domBuilder.characters(source,start+9,end-start-9);
21425                         domBuilder.endCDATA() 
21426                         return end+3;
21427                 }
21428                 //<!DOCTYPE
21429                 //startDTD(java.lang.String name, java.lang.String publicId, java.lang.String systemId) 
21430                 var matchs = split(source,start);
21431                 var len = matchs.length;
21432                 if(len>1 && /!doctype/i.test(matchs[0][0])){
21433                         var name = matchs[1][0];
21434                         var pubid = false;
21435                         var sysid = false;
21436                         if(len>3){
21437                                 if(/^public$/i.test(matchs[2][0])){
21438                                         pubid = matchs[3][0];
21439                                         sysid = len>4 && matchs[4][0];
21440                                 }else if(/^system$/i.test(matchs[2][0])){
21441                                         sysid = matchs[3][0];
21442                                 }
21443                         }
21444                         var lastMatch = matchs[len-1]
21445                         domBuilder.startDTD(name, pubid, sysid);
21446                         domBuilder.endDTD();
21447                         
21448                         return lastMatch.index+lastMatch[0].length
21449                 }
21450         }
21451         return -1;
21452 }
21453 
21454 
21455 
21456 function parseInstruction(source,start,domBuilder){
21457         var end = source.indexOf('?>',start);
21458         if(end){
21459                 var match = source.substring(start,end).match(/^<\?(\S*)\s*([\s\S]*?)\s*$/);
21460                 if(match){
21461                         var len = match[0].length;
21462                         domBuilder.processingInstruction(match[1], match[2]) ;
21463                         return end+2;
21464                 }else{//error
21465                         return -1;
21466                 }
21467         }
21468         return -1;
21469 }
21470 
21471 function ElementAttributes(){
21472         this.attributeNames = {}
21473 }
21474 ElementAttributes.prototype = {
21475         setTagName:function(tagName){
21476                 if(!tagNamePattern.test(tagName)){
21477                         throw new Error('invalid tagName:'+tagName)
21478                 }
21479                 this.tagName = tagName
21480         },
21481         addValue:function(qName, value, offset) {
21482                 if(!tagNamePattern.test(qName)){
21483                         throw new Error('invalid attribute:'+qName)
21484                 }
21485                 this.attributeNames[qName] = this.length;
21486                 this[this.length++] = {qName:qName,value:value,offset:offset}
21487         },
21488         length:0,
21489         getLocalName:function(i){return this[i].localName},
21490         getLocator:function(i){return this[i].locator},
21491         getQName:function(i){return this[i].qName},
21492         getURI:function(i){return this[i].uri},
21493         getValue:function(i){return this[i].value}
21494 //      ,getIndex:function(uri, localName)){
21495 //              if(localName){
21496 //                      
21497 //              }else{
21498 //                      var qName = uri
21499 //              }
21500 //      },
21501 //      getValue:function(){return this.getValue(this.getIndex.apply(this,arguments))},
21502 //      getType:function(uri,localName){}
21503 //      getType:function(i){},
21504 }
21505 
21506 
21507 
21508 function split(source,start){
21509         var match;
21510         var buf = [];
21511         var reg = /'[^']+'|"[^"]+"|[^\s<>\/=]+=?|(\/?\s*>|<)/g;
21512         reg.lastIndex = start;
21513         reg.exec(source);//skip <
21514         while(match = reg.exec(source)){
21515                 buf.push(match);
21516                 if(match[1])return buf;
21517         }
21518 }
21519 
21520 exports.XMLReader = XMLReader;
21521 exports.ParseError = ParseError;
21522 
21523 
21524 /***/ }),
21525 /* 49 */
21526 /***/ (function(module, exports, __webpack_require__) {
21527 
21528 "use strict";
21529 
21530 
21531 Object.defineProperty(exports, "__esModule", {
21532     value: true
21533 });
21534 exports.createElement = createElement;
21535 function createElement(name) {
21536     return document.createElementNS('http://www.w3.org/2000/svg', name);
21537 }
21538 
21539 exports.default = {
21540     createElement: createElement
21541 };
21542 
21543 
21544 /***/ }),
21545 /* 50 */
21546 /***/ (function(module, exports, __webpack_require__) {
21547 
21548 "use strict";
21549 
21550 
21551 Object.defineProperty(exports, "__esModule", {
21552     value: true
21553 });
21554 exports.proxyMouse = proxyMouse;
21555 exports.clone = clone;
21556 // import 'babelify/polyfill'; // needed for Object.assign
21557 
21558 exports.default = {
21559     proxyMouse: proxyMouse
21560 };
21561 
21562 /**
21563  * Start proxying all mouse events that occur on the target node to each node in
21564  * a set of tracked nodes.
21565  *
21566  * The items in tracked do not strictly have to be DOM Nodes, but they do have
21567  * to have dispatchEvent, getBoundingClientRect, and getClientRects methods.
21568  *
21569  * @param target {Node} The node on which to listen for mouse events.
21570  * @param tracked {Node[]} A (possibly mutable) array of nodes to which to proxy
21571  *                         events.
21572  */
21573 
21574 function proxyMouse(target, tracked) {
21575     function dispatch(e) {
21576         // We walk through the set of tracked elements in reverse order so that
21577         // events are sent to those most recently added first.
21578         //
21579         // This is the least surprising behaviour as it simulates the way the
21580         // browser would work if items added later were drawn "on top of"
21581         // earlier ones.
21582         for (var i = tracked.length - 1; i >= 0; i--) {
21583             var t = tracked[i];
21584             var x = e.clientX;
21585             var y = e.clientY;
21586 
21587             if (e.touches && e.touches.length) {
21588                 x = e.touches[0].clientX;
21589                 y = e.touches[0].clientY;
21590             }
21591 
21592             if (!contains(t, target, x, y)) {
21593                 continue;
21594             }
21595 
21596             // The event targets this mark, so dispatch a cloned event:
21597             t.dispatchEvent(clone(e));
21598             // We only dispatch the cloned event to the first matching mark.
21599             break;
21600         }
21601     }
21602 
21603     if (target.nodeName === "iframe" || target.nodeName === "IFRAME") {
21604 
21605         try {
21606             // Try to get the contents if same domain
21607             this.target = target.contentDocument;
21608         } catch (err) {
21609             this.target = target;
21610         }
21611     } else {
21612         this.target = target;
21613     }
21614 
21615     var _arr = ['mouseup', 'mousedown', 'click', 'touchstart'];
21616     for (var _i = 0; _i < _arr.length; _i++) {
21617         var ev = _arr[_i];
21618         this.target.addEventListener(ev, function (e) {
21619             return dispatch(e);
21620         }, false);
21621     }
21622 }
21623 
21624 /**
21625  * Clone a mouse event object.
21626  *
21627  * @param e {MouseEvent} A mouse event object to clone.
21628  * @returns {MouseEvent}
21629  */
21630 function clone(e) {
21631     var opts = Object.assign({}, e, { bubbles: false });
21632     try {
21633         return new MouseEvent(e.type, opts);
21634     } catch (err) {
21635         // compat: webkit
21636         var copy = document.createEvent('MouseEvents');
21637         copy.initMouseEvent(e.type, false, opts.cancelable, opts.view, opts.detail, opts.screenX, opts.screenY, opts.clientX, opts.clientY, opts.ctrlKey, opts.altKey, opts.shiftKey, opts.metaKey, opts.button, opts.relatedTarget);
21638         return copy;
21639     }
21640 }
21641 
21642 /**
21643  * Check if the item contains the point denoted by the passed coordinates
21644  * @param item {Object} An object with getBoundingClientRect and getClientRects
21645  *                      methods.
21646  * @param x {Number}
21647  * @param y {Number}
21648  * @returns {Boolean}
21649  */
21650 function contains(item, target, x, y) {
21651     // offset
21652     var offset = target.getBoundingClientRect();
21653 
21654     function rectContains(r, x, y) {
21655         var top = r.top - offset.top;
21656         var left = r.left - offset.left;
21657         var bottom = top + r.height;
21658         var right = left + r.width;
21659         return top <= y && left <= x && bottom > y && right > x;
21660     }
21661 
21662     // Check overall bounding box first
21663     var rect = item.getBoundingClientRect();
21664     if (!rectContains(rect, x, y)) {
21665         return false;
21666     }
21667 
21668     // Then continue to check each child rect
21669     var rects = item.getClientRects();
21670     for (var i = 0, len = rects.length; i < len; i++) {
21671         if (rectContains(rects[i], x, y)) {
21672             return true;
21673         }
21674     }
21675     return false;
21676 }
21677 
21678 
21679 /***/ }),
21680 /* 51 */
21681 /***/ (function(module, exports, __webpack_require__) {
21682 
21683 var root = __webpack_require__(26);
21684 
21685 /**
21686  * Gets the timestamp of the number of milliseconds that have elapsed since
21687  * the Unix epoch (1 January 1970 00:00:00 UTC).
21688  *
21689  * @static
21690  * @memberOf _
21691  * @since 2.4.0
21692  * @category Date
21693  * @returns {number} Returns the timestamp.
21694  * @example
21695  *
21696  * _.defer(function(stamp) {
21697  *   console.log(_.now() - stamp);
21698  * }, _.now());
21699  * // => Logs the number of milliseconds it took for the deferred invocation.
21700  */
21701 var now = function() {
21702   return root.Date.now();
21703 };
21704 
21705 module.exports = now;
21706 
21707 
21708 /***/ }),
21709 /* 52 */
21710 /***/ (function(module, exports, __webpack_require__) {
21711 
21712 /* WEBPACK VAR INJECTION */(function(global) {/** Detect free variable `global` from Node.js. */
21713 var freeGlobal = typeof global == 'object' && global && global.Object === Object && global;
21714 
21715 module.exports = freeGlobal;
21716 
21717 /* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(17)))
21718 
21719 /***/ }),
21720 /* 53 */
21721 /***/ (function(module, exports, __webpack_require__) {
21722 
21723 var baseTrim = __webpack_require__(54),
21724     isObject = __webpack_require__(19),
21725     isSymbol = __webpack_require__(56);
21726 
21727 /** Used as references for various `Number` constants. */
21728 var NAN = 0 / 0;
21729 
21730 /** Used to detect bad signed hexadecimal string values. */
21731 var reIsBadHex = /^[-+]0x[0-9a-f]+$/i;
21732 
21733 /** Used to detect binary string values. */
21734 var reIsBinary = /^0b[01]+$/i;
21735 
21736 /** Used to detect octal string values. */
21737 var reIsOctal = /^0o[0-7]+$/i;
21738 
21739 /** Built-in method references without a dependency on `root`. */
21740 var freeParseInt = parseInt;
21741 
21742 /**
21743  * Converts `value` to a number.
21744  *
21745  * @static
21746  * @memberOf _
21747  * @since 4.0.0
21748  * @category Lang
21749  * @param {*} value The value to process.
21750  * @returns {number} Returns the number.
21751  * @example
21752  *
21753  * _.toNumber(3.2);
21754  * // => 3.2
21755  *
21756  * _.toNumber(Number.MIN_VALUE);
21757  * // => 5e-324
21758  *
21759  * _.toNumber(Infinity);
21760  * // => Infinity
21761  *
21762  * _.toNumber('3.2');
21763  * // => 3.2
21764  */
21765 function toNumber(value) {
21766   if (typeof value == 'number') {
21767     return value;
21768   }
21769   if (isSymbol(value)) {
21770     return NAN;
21771   }
21772   if (isObject(value)) {
21773     var other = typeof value.valueOf == 'function' ? value.valueOf() : value;
21774     value = isObject(other) ? (other + '') : other;
21775   }
21776   if (typeof value != 'string') {
21777     return value === 0 ? value : +value;
21778   }
21779   value = baseTrim(value);
21780   var isBinary = reIsBinary.test(value);
21781   return (isBinary || reIsOctal.test(value))
21782     ? freeParseInt(value.slice(2), isBinary ? 2 : 8)
21783     : (reIsBadHex.test(value) ? NAN : +value);
21784 }
21785 
21786 module.exports = toNumber;
21787 
21788 
21789 /***/ }),
21790 /* 54 */
21791 /***/ (function(module, exports, __webpack_require__) {
21792 
21793 var trimmedEndIndex = __webpack_require__(55);
21794 
21795 /** Used to match leading whitespace. */
21796 var reTrimStart = /^\s+/;
21797 
21798 /**
21799  * The base implementation of `_.trim`.
21800  *
21801  * @private
21802  * @param {string} string The string to trim.
21803  * @returns {string} Returns the trimmed string.
21804  */
21805 function baseTrim(string) {
21806   return string
21807     ? string.slice(0, trimmedEndIndex(string) + 1).replace(reTrimStart, '')
21808     : string;
21809 }
21810 
21811 module.exports = baseTrim;
21812 
21813 
21814 /***/ }),
21815 /* 55 */
21816 /***/ (function(module, exports) {
21817 
21818 /** Used to match a single whitespace character. */
21819 var reWhitespace = /\s/;
21820 
21821 /**
21822  * Used by `_.trim` and `_.trimEnd` to get the index of the last non-whitespace
21823  * character of `string`.
21824  *
21825  * @private
21826  * @param {string} string The string to inspect.
21827  * @returns {number} Returns the index of the last non-whitespace character.
21828  */
21829 function trimmedEndIndex(string) {
21830   var index = string.length;
21831 
21832   while (index-- && reWhitespace.test(string.charAt(index))) {}
21833   return index;
21834 }
21835 
21836 module.exports = trimmedEndIndex;
21837 
21838 
21839 /***/ }),
21840 /* 56 */
21841 /***/ (function(module, exports, __webpack_require__) {
21842 
21843 var baseGetTag = __webpack_require__(57),
21844     isObjectLike = __webpack_require__(60);
21845 
21846 /** `Object#toString` result references. */
21847 var symbolTag = '[object Symbol]';
21848 
21849 /**
21850  * Checks if `value` is classified as a `Symbol` primitive or object.
21851  *
21852  * @static
21853  * @memberOf _
21854  * @since 4.0.0
21855  * @category Lang
21856  * @param {*} value The value to check.
21857  * @returns {boolean} Returns `true` if `value` is a symbol, else `false`.
21858  * @example
21859  *
21860  * _.isSymbol(Symbol.iterator);
21861  * // => true
21862  *
21863  * _.isSymbol('abc');
21864  * // => false
21865  */
21866 function isSymbol(value) {
21867   return typeof value == 'symbol' ||
21868     (isObjectLike(value) && baseGetTag(value) == symbolTag);
21869 }
21870 
21871 module.exports = isSymbol;
21872 
21873 
21874 /***/ }),
21875 /* 57 */
21876 /***/ (function(module, exports, __webpack_require__) {
21877 
21878 var Symbol = __webpack_require__(27),
21879     getRawTag = __webpack_require__(58),
21880     objectToString = __webpack_require__(59);
21881 
21882 /** `Object#toString` result references. */
21883 var nullTag = '[object Null]',
21884     undefinedTag = '[object Undefined]';
21885 
21886 /** Built-in value references. */
21887 var symToStringTag = Symbol ? Symbol.toStringTag : undefined;
21888 
21889 /**
21890  * The base implementation of `getTag` without fallbacks for buggy environments.
21891  *
21892  * @private
21893  * @param {*} value The value to query.
21894  * @returns {string} Returns the `toStringTag`.
21895  */
21896 function baseGetTag(value) {
21897   if (value == null) {
21898     return value === undefined ? undefinedTag : nullTag;
21899   }
21900   return (symToStringTag && symToStringTag in Object(value))
21901     ? getRawTag(value)
21902     : objectToString(value);
21903 }
21904 
21905 module.exports = baseGetTag;
21906 
21907 
21908 /***/ }),
21909 /* 58 */
21910 /***/ (function(module, exports, __webpack_require__) {
21911 
21912 var Symbol = __webpack_require__(27);
21913 
21914 /** Used for built-in method references. */
21915 var objectProto = Object.prototype;
21916 
21917 /** Used to check objects for own properties. */
21918 var hasOwnProperty = objectProto.hasOwnProperty;
21919 
21920 /**
21921  * Used to resolve the
21922  * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
21923  * of values.
21924  */
21925 var nativeObjectToString = objectProto.toString;
21926 
21927 /** Built-in value references. */
21928 var symToStringTag = Symbol ? Symbol.toStringTag : undefined;
21929 
21930 /**
21931  * A specialized version of `baseGetTag` which ignores `Symbol.toStringTag` values.
21932  *
21933  * @private
21934  * @param {*} value The value to query.
21935  * @returns {string} Returns the raw `toStringTag`.
21936  */
21937 function getRawTag(value) {
21938   var isOwn = hasOwnProperty.call(value, symToStringTag),
21939       tag = value[symToStringTag];
21940 
21941   try {
21942     value[symToStringTag] = undefined;
21943     var unmasked = true;
21944   } catch (e) {}
21945 
21946   var result = nativeObjectToString.call(value);
21947   if (unmasked) {
21948     if (isOwn) {
21949       value[symToStringTag] = tag;
21950     } else {
21951       delete value[symToStringTag];
21952     }
21953   }
21954   return result;
21955 }
21956 
21957 module.exports = getRawTag;
21958 
21959 
21960 /***/ }),
21961 /* 59 */
21962 /***/ (function(module, exports) {
21963 
21964 /** Used for built-in method references. */
21965 var objectProto = Object.prototype;
21966 
21967 /**
21968  * Used to resolve the
21969  * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
21970  * of values.
21971  */
21972 var nativeObjectToString = objectProto.toString;
21973 
21974 /**
21975  * Converts `value` to a string using `Object.prototype.toString`.
21976  *
21977  * @private
21978  * @param {*} value The value to convert.
21979  * @returns {string} Returns the converted string.
21980  */
21981 function objectToString(value) {
21982   return nativeObjectToString.call(value);
21983 }
21984 
21985 module.exports = objectToString;
21986 
21987 
21988 /***/ }),
21989 /* 60 */
21990 /***/ (function(module, exports) {
21991 
21992 /**
21993  * Checks if `value` is object-like. A value is object-like if it's not `null`
21994  * and has a `typeof` result of "object".
21995  *
21996  * @static
21997  * @memberOf _
21998  * @since 4.0.0
21999  * @category Lang
22000  * @param {*} value The value to check.
22001  * @returns {boolean} Returns `true` if `value` is object-like, else `false`.
22002  * @example
22003  *
22004  * _.isObjectLike({});
22005  * // => true
22006  *
22007  * _.isObjectLike([1, 2, 3]);
22008  * // => true
22009  *
22010  * _.isObjectLike(_.noop);
22011  * // => false
22012  *
22013  * _.isObjectLike(null);
22014  * // => false
22015  */
22016 function isObjectLike(value) {
22017   return value != null && typeof value == 'object';
22018 }
22019 
22020 module.exports = isObjectLike;
22021 
22022 
22023 /***/ })
22024 /******/ ])["default"];
22025 });