diff --git "a/scripts/epub.orig.js" "b/scripts/epub.orig.js"
new file mode 100644--- /dev/null
+++ "b/scripts/epub.orig.js"
@@ -0,0 +1,16784 @@
+(function webpackUniversalModuleDefinition(root, factory) {
+ if(typeof exports === 'object' && typeof module === 'object')
+ module.exports = factory(require("xmldom"), (function webpackLoadOptionalExternalModule() { try { return require("jszip"); } catch(e) {} }()));
+ else if(typeof define === 'function' && define.amd)
+ define(["xmldom", "jszip"], factory);
+ else if(typeof exports === 'object')
+ exports["ePub"] = factory(require("xmldom"), (function webpackLoadOptionalExternalModule() { try { return require("jszip"); } catch(e) {} }()));
+ else
+ root["ePub"] = factory(root["xmldom"], root["jszip"]);
+})(typeof self !== 'undefined' ? self : this, function(__WEBPACK_EXTERNAL_MODULE_16__, __WEBPACK_EXTERNAL_MODULE_68__) {
+return /******/ (function(modules) { // webpackBootstrap
+/******/ // The module cache
+/******/ var installedModules = {};
+/******/
+/******/ // The require function
+/******/ function __webpack_require__(moduleId) {
+/******/
+/******/ // Check if module is in cache
+/******/ if(installedModules[moduleId]) {
+/******/ return installedModules[moduleId].exports;
+/******/ }
+/******/ // Create a new module (and put it into the cache)
+/******/ var module = installedModules[moduleId] = {
+/******/ i: moduleId,
+/******/ l: false,
+/******/ exports: {}
+/******/ };
+/******/
+/******/ // Execute the module function
+/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
+/******/
+/******/ // Flag the module as loaded
+/******/ module.l = true;
+/******/
+/******/ // Return the exports of the module
+/******/ return module.exports;
+/******/ }
+/******/
+/******/
+/******/ // expose the modules object (__webpack_modules__)
+/******/ __webpack_require__.m = modules;
+/******/
+/******/ // expose the module cache
+/******/ __webpack_require__.c = installedModules;
+/******/
+/******/ // define getter function for harmony exports
+/******/ __webpack_require__.d = function(exports, name, getter) {
+/******/ if(!__webpack_require__.o(exports, name)) {
+/******/ Object.defineProperty(exports, name, {
+/******/ configurable: false,
+/******/ enumerable: true,
+/******/ get: getter
+/******/ });
+/******/ }
+/******/ };
+/******/
+/******/ // getDefaultExport function for compatibility with non-harmony modules
+/******/ __webpack_require__.n = function(module) {
+/******/ var getter = module && module.__esModule ?
+/******/ function getDefault() { return module['default']; } :
+/******/ function getModuleExports() { return module; };
+/******/ __webpack_require__.d(getter, 'a', getter);
+/******/ return getter;
+/******/ };
+/******/
+/******/ // Object.prototype.hasOwnProperty.call
+/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
+/******/
+/******/ // __webpack_public_path__
+/******/ __webpack_require__.p = "/dist/";
+/******/
+/******/ // Load entry module and return exports
+/******/ return __webpack_require__(__webpack_require__.s = 25);
+/******/ })
+/************************************************************************/
+/******/ ([
+/* 0 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+
+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; }; }();
+
+exports.uuid = uuid;
+exports.documentHeight = documentHeight;
+exports.isElement = isElement;
+exports.isNumber = isNumber;
+exports.isFloat = isFloat;
+exports.prefixed = prefixed;
+exports.defaults = defaults;
+exports.extend = extend;
+exports.insert = insert;
+exports.locationOf = locationOf;
+exports.indexOfSorted = indexOfSorted;
+exports.bounds = bounds;
+exports.borders = borders;
+exports.windowBounds = windowBounds;
+exports.indexOfNode = indexOfNode;
+exports.indexOfTextNode = indexOfTextNode;
+exports.indexOfElementNode = indexOfElementNode;
+exports.isXml = isXml;
+exports.createBlob = createBlob;
+exports.createBlobUrl = createBlobUrl;
+exports.revokeBlobUrl = revokeBlobUrl;
+exports.createBase64Url = createBase64Url;
+exports.type = type;
+exports.parse = parse;
+exports.qs = qs;
+exports.qsa = qsa;
+exports.qsp = qsp;
+exports.sprint = sprint;
+exports.treeWalker = treeWalker;
+exports.walk = walk;
+exports.blob2base64 = blob2base64;
+exports.defer = defer;
+exports.querySelectorByType = querySelectorByType;
+exports.findChildren = findChildren;
+exports.parents = parents;
+exports.filterChildren = filterChildren;
+exports.getParentByTagName = getParentByTagName;
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+/**
+ * Core Utilities and Helpers
+ * @module Core
+*/
+
+/**
+ * Vendor prefixed requestAnimationFrame
+ * @returns {function} requestAnimationFrame
+ * @memberof Core
+ */
+var requestAnimationFrame = exports.requestAnimationFrame = typeof window != "undefined" ? window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame : false;
+var ELEMENT_NODE = 1;
+var TEXT_NODE = 3;
+var COMMENT_NODE = 8;
+var DOCUMENT_NODE = 9;
+var _URL = typeof URL != "undefined" ? URL : typeof window != "undefined" ? window.URL || window.webkitURL || window.mozURL : undefined;
+
+/**
+ * Generates a UUID
+ * based on: http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript
+ * @returns {string} uuid
+ * @memberof Core
+ */
+function uuid() {
+ var d = new Date().getTime();
+ var uuid = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function (c) {
+ var r = (d + Math.random() * 16) % 16 | 0;
+ d = Math.floor(d / 16);
+ return (c == "x" ? r : r & 0x7 | 0x8).toString(16);
+ });
+ return uuid;
+}
+
+/**
+ * Gets the height of a document
+ * @returns {number} height
+ * @memberof Core
+ */
+function documentHeight() {
+ return Math.max(document.documentElement.clientHeight, document.body.scrollHeight, document.documentElement.scrollHeight, document.body.offsetHeight, document.documentElement.offsetHeight);
+}
+
+/**
+ * Checks if a node is an element
+ * @returns {boolean}
+ * @memberof Core
+ */
+function isElement(obj) {
+ return !!(obj && obj.nodeType == 1);
+}
+
+/**
+ * @returns {boolean}
+ * @memberof Core
+ */
+function isNumber(n) {
+ return !isNaN(parseFloat(n)) && isFinite(n);
+}
+
+/**
+ * @returns {boolean}
+ * @memberof Core
+ */
+function isFloat(n) {
+ var f = parseFloat(n);
+ return f === n && isNumber(n) && Math.floor(f) !== n;
+}
+
+/**
+ * Get a prefixed css property
+ * @returns {string}
+ * @memberof Core
+ */
+function prefixed(unprefixed) {
+ var vendors = ["Webkit", "webkit", "Moz", "O", "ms"];
+ var prefixes = ["-webkit-", "-webkit-", "-moz-", "-o-", "-ms-"];
+ var upper = unprefixed[0].toUpperCase() + unprefixed.slice(1);
+ var length = vendors.length;
+
+ if (typeof document === "undefined" || typeof document.body.style[unprefixed] != "undefined") {
+ return unprefixed;
+ }
+
+ for (var i = 0; i < length; i++) {
+ if (typeof document.body.style[vendors[i] + upper] != "undefined") {
+ return prefixes[i] + unprefixed;
+ }
+ }
+
+ return unprefixed;
+}
+
+/**
+ * Apply defaults to an object
+ * @param {object} obj
+ * @returns {object}
+ * @memberof Core
+ */
+function defaults(obj) {
+ for (var i = 1, length = arguments.length; i < length; i++) {
+ var source = arguments[i];
+ for (var prop in source) {
+ if (obj[prop] === void 0) obj[prop] = source[prop];
+ }
+ }
+ return obj;
+}
+
+/**
+ * Extend properties of an object
+ * @param {object} target
+ * @returns {object}
+ * @memberof Core
+ */
+function extend(target) {
+ var sources = [].slice.call(arguments, 1);
+ sources.forEach(function (source) {
+ if (!source) return;
+ Object.getOwnPropertyNames(source).forEach(function (propName) {
+ Object.defineProperty(target, propName, Object.getOwnPropertyDescriptor(source, propName));
+ });
+ });
+ return target;
+}
+
+/**
+ * Fast quicksort insert for sorted array -- based on:
+ * http://stackoverflow.com/questions/1344500/efficient-way-to-insert-a-number-into-a-sorted-array-of-numbers
+ * @param {any} item
+ * @param {array} array
+ * @param {function} [compareFunction]
+ * @returns {number} location (in array)
+ * @memberof Core
+ */
+function insert(item, array, compareFunction) {
+ var location = locationOf(item, array, compareFunction);
+ array.splice(location, 0, item);
+
+ return location;
+}
+
+/**
+ * Finds where something would fit into a sorted array
+ * @param {any} item
+ * @param {array} array
+ * @param {function} [compareFunction]
+ * @param {function} [_start]
+ * @param {function} [_end]
+ * @returns {number} location (in array)
+ * @memberof Core
+ */
+function locationOf(item, array, compareFunction, _start, _end) {
+ var start = _start || 0;
+ var end = _end || array.length;
+ var pivot = parseInt(start + (end - start) / 2);
+ var compared;
+ if (!compareFunction) {
+ compareFunction = function compareFunction(a, b) {
+ if (a > b) return 1;
+ if (a < b) return -1;
+ if (a == b) return 0;
+ };
+ }
+ if (end - start <= 0) {
+ return pivot;
+ }
+
+ compared = compareFunction(array[pivot], item);
+ if (end - start === 1) {
+ return compared >= 0 ? pivot : pivot + 1;
+ }
+ if (compared === 0) {
+ return pivot;
+ }
+ if (compared === -1) {
+ return locationOf(item, array, compareFunction, pivot, end);
+ } else {
+ return locationOf(item, array, compareFunction, start, pivot);
+ }
+}
+
+/**
+ * Finds index of something in a sorted array
+ * Returns -1 if not found
+ * @param {any} item
+ * @param {array} array
+ * @param {function} [compareFunction]
+ * @param {function} [_start]
+ * @param {function} [_end]
+ * @returns {number} index (in array) or -1
+ * @memberof Core
+ */
+function indexOfSorted(item, array, compareFunction, _start, _end) {
+ var start = _start || 0;
+ var end = _end || array.length;
+ var pivot = parseInt(start + (end - start) / 2);
+ var compared;
+ if (!compareFunction) {
+ compareFunction = function compareFunction(a, b) {
+ if (a > b) return 1;
+ if (a < b) return -1;
+ if (a == b) return 0;
+ };
+ }
+ if (end - start <= 0) {
+ return -1; // Not found
+ }
+
+ compared = compareFunction(array[pivot], item);
+ if (end - start === 1) {
+ return compared === 0 ? pivot : -1;
+ }
+ if (compared === 0) {
+ return pivot; // Found
+ }
+ if (compared === -1) {
+ return indexOfSorted(item, array, compareFunction, pivot, end);
+ } else {
+ return indexOfSorted(item, array, compareFunction, start, pivot);
+ }
+}
+/**
+ * Find the bounds of an element
+ * taking padding and margin into account
+ * @param {element} el
+ * @returns {{ width: Number, height: Number}}
+ * @memberof Core
+ */
+function bounds(el) {
+
+ var style = window.getComputedStyle(el);
+ var widthProps = ["width", "paddingRight", "paddingLeft", "marginRight", "marginLeft", "borderRightWidth", "borderLeftWidth"];
+ var heightProps = ["height", "paddingTop", "paddingBottom", "marginTop", "marginBottom", "borderTopWidth", "borderBottomWidth"];
+
+ var width = 0;
+ var height = 0;
+
+ widthProps.forEach(function (prop) {
+ width += parseFloat(style[prop]) || 0;
+ });
+
+ heightProps.forEach(function (prop) {
+ height += parseFloat(style[prop]) || 0;
+ });
+
+ return {
+ height: height,
+ width: width
+ };
+}
+
+/**
+ * Find the bounds of an element
+ * taking padding, margin and borders into account
+ * @param {element} el
+ * @returns {{ width: Number, height: Number}}
+ * @memberof Core
+ */
+function borders(el) {
+
+ var style = window.getComputedStyle(el);
+ var widthProps = ["paddingRight", "paddingLeft", "marginRight", "marginLeft", "borderRightWidth", "borderLeftWidth"];
+ var heightProps = ["paddingTop", "paddingBottom", "marginTop", "marginBottom", "borderTopWidth", "borderBottomWidth"];
+
+ var width = 0;
+ var height = 0;
+
+ widthProps.forEach(function (prop) {
+ width += parseFloat(style[prop]) || 0;
+ });
+
+ heightProps.forEach(function (prop) {
+ height += parseFloat(style[prop]) || 0;
+ });
+
+ return {
+ height: height,
+ width: width
+ };
+}
+
+/**
+ * Find the equivelent of getBoundingClientRect of a browser window
+ * @returns {{ width: Number, height: Number, top: Number, left: Number, right: Number, bottom: Number }}
+ * @memberof Core
+ */
+function windowBounds() {
+
+ var width = window.innerWidth;
+ var height = window.innerHeight;
+
+ return {
+ top: 0,
+ left: 0,
+ right: width,
+ bottom: height,
+ width: width,
+ height: height
+ };
+}
+
+/**
+ * Gets the index of a node in its parent
+ * @private
+ * @memberof Core
+ */
+function indexOfNode(node, typeId) {
+ var parent = node.parentNode;
+ var children = parent.childNodes;
+ var sib;
+ var index = -1;
+ for (var i = 0; i < children.length; i++) {
+ sib = children[i];
+ if (sib.nodeType === typeId) {
+ index++;
+ }
+ if (sib == node) break;
+ }
+
+ return index;
+}
+
+/**
+ * Gets the index of a text node in its parent
+ * @param {node} textNode
+ * @returns {number} index
+ * @memberof Core
+ */
+function indexOfTextNode(textNode) {
+ return indexOfNode(textNode, TEXT_NODE);
+}
+
+/**
+ * Gets the index of an element node in its parent
+ * @param {element} elementNode
+ * @returns {number} index
+ * @memberof Core
+ */
+function indexOfElementNode(elementNode) {
+ return indexOfNode(elementNode, ELEMENT_NODE);
+}
+
+/**
+ * Check if extension is xml
+ * @param {string} ext
+ * @returns {boolean}
+ * @memberof Core
+ */
+function isXml(ext) {
+ return ["xml", "opf", "ncx"].indexOf(ext) > -1;
+}
+
+/**
+ * Create a new blob
+ * @param {any} content
+ * @param {string} mime
+ * @returns {Blob}
+ * @memberof Core
+ */
+function createBlob(content, mime) {
+ return new Blob([content], { type: mime });
+}
+
+/**
+ * Create a new blob url
+ * @param {any} content
+ * @param {string} mime
+ * @returns {string} url
+ * @memberof Core
+ */
+function createBlobUrl(content, mime) {
+ var tempUrl;
+ var blob = createBlob(content, mime);
+
+ tempUrl = _URL.createObjectURL(blob);
+
+ return tempUrl;
+}
+
+/**
+ * Remove a blob url
+ * @param {string} url
+ * @memberof Core
+ */
+function revokeBlobUrl(url) {
+ return _URL.revokeObjectURL(url);
+}
+
+/**
+ * Create a new base64 encoded url
+ * @param {any} content
+ * @param {string} mime
+ * @returns {string} url
+ * @memberof Core
+ */
+function createBase64Url(content, mime) {
+ var data;
+ var datauri;
+
+ if (typeof content !== "string") {
+ // Only handles strings
+ return;
+ }
+
+ data = btoa(encodeURIComponent(content));
+
+ datauri = "data:" + mime + ";base64," + data;
+
+ return datauri;
+}
+
+/**
+ * Get type of an object
+ * @param {object} obj
+ * @returns {string} type
+ * @memberof Core
+ */
+function type(obj) {
+ return Object.prototype.toString.call(obj).slice(8, -1);
+}
+
+/**
+ * Parse xml (or html) markup
+ * @param {string} markup
+ * @param {string} mime
+ * @param {boolean} forceXMLDom force using xmlDom to parse instead of native parser
+ * @returns {document} document
+ * @memberof Core
+ */
+function parse(markup, mime, forceXMLDom) {
+ var doc;
+ var Parser;
+
+ if (typeof DOMParser === "undefined" || forceXMLDom) {
+ Parser = __webpack_require__(16).DOMParser;
+ } else {
+ Parser = DOMParser;
+ }
+
+ // Remove byte order mark before parsing
+ // https://www.w3.org/International/questions/qa-byte-order-mark
+ if (markup.charCodeAt(0) === 0xFEFF) {
+ markup = markup.slice(1);
+ }
+
+ doc = new Parser().parseFromString(markup, mime);
+
+ return doc;
+}
+
+/**
+ * querySelector polyfill
+ * @param {element} el
+ * @param {string} sel selector string
+ * @returns {element} element
+ * @memberof Core
+ */
+function qs(el, sel) {
+ var elements;
+ if (!el) {
+ throw new Error("No Element Provided");
+ }
+
+ if (typeof el.querySelector != "undefined") {
+ return el.querySelector(sel);
+ } else {
+ elements = el.getElementsByTagName(sel);
+ if (elements.length) {
+ return elements[0];
+ }
+ }
+}
+
+/**
+ * querySelectorAll polyfill
+ * @param {element} el
+ * @param {string} sel selector string
+ * @returns {element[]} elements
+ * @memberof Core
+ */
+function qsa(el, sel) {
+
+ if (typeof el.querySelector != "undefined") {
+ return el.querySelectorAll(sel);
+ } else {
+ return el.getElementsByTagName(sel);
+ }
+}
+
+/**
+ * querySelector by property
+ * @param {element} el
+ * @param {string} sel selector string
+ * @param {props[]} props
+ * @returns {element[]} elements
+ * @memberof Core
+ */
+function qsp(el, sel, props) {
+ var q, filtered;
+ if (typeof el.querySelector != "undefined") {
+ sel += "[";
+ for (var prop in props) {
+ sel += prop + "~='" + props[prop] + "'";
+ }
+ sel += "]";
+ return el.querySelector(sel);
+ } else {
+ q = el.getElementsByTagName(sel);
+ filtered = Array.prototype.slice.call(q, 0).filter(function (el) {
+ for (var prop in props) {
+ if (el.getAttribute(prop) === props[prop]) {
+ return true;
+ }
+ }
+ return false;
+ });
+
+ if (filtered) {
+ return filtered[0];
+ }
+ }
+}
+
+/**
+ * Sprint through all text nodes in a document
+ * @memberof Core
+ * @param {element} root element to start with
+ * @param {function} func function to run on each element
+ */
+function sprint(root, func) {
+ var doc = root.ownerDocument || root;
+ if (typeof doc.createTreeWalker !== "undefined") {
+ treeWalker(root, func, NodeFilter.SHOW_TEXT);
+ } else {
+ walk(root, function (node) {
+ if (node && node.nodeType === 3) {
+ // Node.TEXT_NODE
+ func(node);
+ }
+ }, true);
+ }
+}
+
+function treeWalker(root, func, filter) {
+ var treeWalker = document.createTreeWalker(root, filter, null, false);
+ var node = void 0;
+ while (node = treeWalker.nextNode()) {
+ func(node);
+ }
+}
+
+/**
+ * @memberof Core
+ * @param {node} node
+ * @param {callback} return false for continue,true for break inside callback
+ */
+function walk(node, callback) {
+ if (callback(node)) {
+ return true;
+ }
+ node = node.firstChild;
+ if (node) {
+ do {
+ var walked = walk(node, callback);
+ if (walked) {
+ return true;
+ }
+ node = node.nextSibling;
+ } while (node);
+ }
+}
+
+/**
+ * Convert a blob to a base64 encoded string
+ * @param {Blog} blob
+ * @returns {string}
+ * @memberof Core
+ */
+function blob2base64(blob) {
+ return new Promise(function (resolve, reject) {
+ var reader = new FileReader();
+ reader.readAsDataURL(blob);
+ reader.onloadend = function () {
+ resolve(reader.result);
+ };
+ });
+}
+
+/**
+ * Creates a new pending promise and provides methods to resolve or reject it.
+ * From: https://developer.mozilla.org/en-US/docs/Mozilla/JavaScript_code_modules/Promise.jsm/Deferred#backwards_forwards_compatible
+ * @memberof Core
+ */
+function defer() {
+ var _this = this;
+
+ /* A method to resolve the associated Promise with the value passed.
+ * If the promise is already settled it does nothing.
+ *
+ * @param {anything} value : This value is used to resolve the promise
+ * If the value is a Promise then the associated promise assumes the state
+ * of Promise passed as value.
+ */
+ this.resolve = null;
+
+ /* A method to reject the assocaited Promise with the value passed.
+ * If the promise is already settled it does nothing.
+ *
+ * @param {anything} reason: The reason for the rejection of the Promise.
+ * Generally its an Error object. If however a Promise is passed, then the Promise
+ * itself will be the reason for rejection no matter the state of the Promise.
+ */
+ this.reject = null;
+
+ this.id = uuid();
+
+ /* A newly created Pomise object.
+ * Initially in pending state.
+ */
+ this.promise = new Promise(function (resolve, reject) {
+ _this.resolve = resolve;
+ _this.reject = reject;
+ });
+ Object.freeze(this);
+}
+
+/**
+ * querySelector with filter by epub type
+ * @param {element} html
+ * @param {string} element element type to find
+ * @param {string} type epub type to find
+ * @returns {element[]} elements
+ * @memberof Core
+ */
+function querySelectorByType(html, element, type) {
+ var query;
+ if (typeof html.querySelector != "undefined") {
+ query = html.querySelector(element + "[*|type=\"" + type + "\"]");
+ }
+ // Handle IE not supporting namespaced epub:type in querySelector
+ if (!query || query.length === 0) {
+ query = qsa(html, element);
+ for (var i = 0; i < query.length; i++) {
+ if (query[i].getAttributeNS("http://www.idpf.org/2007/ops", "type") === type || query[i].getAttribute("epub:type") === type) {
+ return query[i];
+ }
+ }
+ } else {
+ return query;
+ }
+}
+
+/**
+ * Find direct decendents of an element
+ * @param {element} el
+ * @returns {element[]} children
+ * @memberof Core
+ */
+function findChildren(el) {
+ var result = [];
+ var childNodes = el.childNodes;
+ for (var i = 0; i < childNodes.length; i++) {
+ var node = childNodes[i];
+ if (node.nodeType === 1) {
+ result.push(node);
+ }
+ }
+ return result;
+}
+
+/**
+ * Find all parents (ancestors) of an element
+ * @param {element} node
+ * @returns {element[]} parents
+ * @memberof Core
+ */
+function parents(node) {
+ var nodes = [node];
+ for (; node; node = node.parentNode) {
+ nodes.unshift(node);
+ }
+ return nodes;
+}
+
+/**
+ * Find all direct decendents of a specific type
+ * @param {element} el
+ * @param {string} nodeName
+ * @param {boolean} [single]
+ * @returns {element[]} children
+ * @memberof Core
+ */
+function filterChildren(el, nodeName, single) {
+ var result = [];
+ var childNodes = el.childNodes;
+ for (var i = 0; i < childNodes.length; i++) {
+ var node = childNodes[i];
+ if (node.nodeType === 1 && node.nodeName.toLowerCase() === nodeName) {
+ if (single) {
+ return node;
+ } else {
+ result.push(node);
+ }
+ }
+ }
+ if (!single) {
+ return result;
+ }
+}
+
+/**
+ * Filter all parents (ancestors) with tag name
+ * @param {element} node
+ * @param {string} tagname
+ * @returns {element[]} parents
+ * @memberof Core
+ */
+function getParentByTagName(node, tagname) {
+ var parent = void 0;
+ if (node === null || tagname === '') return;
+ parent = node.parentNode;
+ while (parent.nodeType === 1) {
+ if (parent.tagName.toLowerCase() === tagname) {
+ return parent;
+ }
+ parent = parent.parentNode;
+ }
+}
+
+/**
+ * Lightweight Polyfill for DOM Range
+ * @class
+ * @memberof Core
+ */
+
+var RangeObject = exports.RangeObject = function () {
+ function RangeObject() {
+ _classCallCheck(this, RangeObject);
+
+ this.collapsed = false;
+ this.commonAncestorContainer = undefined;
+ this.endContainer = undefined;
+ this.endOffset = undefined;
+ this.startContainer = undefined;
+ this.startOffset = undefined;
+ }
+
+ _createClass(RangeObject, [{
+ key: "setStart",
+ value: function setStart(startNode, startOffset) {
+ this.startContainer = startNode;
+ this.startOffset = startOffset;
+
+ if (!this.endContainer) {
+ this.collapse(true);
+ } else {
+ this.commonAncestorContainer = this._commonAncestorContainer();
+ }
+
+ this._checkCollapsed();
+ }
+ }, {
+ key: "setEnd",
+ value: function setEnd(endNode, endOffset) {
+ this.endContainer = endNode;
+ this.endOffset = endOffset;
+
+ if (!this.startContainer) {
+ this.collapse(false);
+ } else {
+ this.collapsed = false;
+ this.commonAncestorContainer = this._commonAncestorContainer();
+ }
+
+ this._checkCollapsed();
+ }
+ }, {
+ key: "collapse",
+ value: function collapse(toStart) {
+ this.collapsed = true;
+ if (toStart) {
+ this.endContainer = this.startContainer;
+ this.endOffset = this.startOffset;
+ this.commonAncestorContainer = this.startContainer.parentNode;
+ } else {
+ this.startContainer = this.endContainer;
+ this.startOffset = this.endOffset;
+ this.commonAncestorContainer = this.endOffset.parentNode;
+ }
+ }
+ }, {
+ key: "selectNode",
+ value: function selectNode(referenceNode) {
+ var parent = referenceNode.parentNode;
+ var index = Array.prototype.indexOf.call(parent.childNodes, referenceNode);
+ this.setStart(parent, index);
+ this.setEnd(parent, index + 1);
+ }
+ }, {
+ key: "selectNodeContents",
+ value: function selectNodeContents(referenceNode) {
+ var end = referenceNode.childNodes[referenceNode.childNodes - 1];
+ var endIndex = referenceNode.nodeType === 3 ? referenceNode.textContent.length : parent.childNodes.length;
+ this.setStart(referenceNode, 0);
+ this.setEnd(referenceNode, endIndex);
+ }
+ }, {
+ key: "_commonAncestorContainer",
+ value: function _commonAncestorContainer(startContainer, endContainer) {
+ var startParents = parents(startContainer || this.startContainer);
+ var endParents = parents(endContainer || this.endContainer);
+
+ if (startParents[0] != endParents[0]) return undefined;
+
+ for (var i = 0; i < startParents.length; i++) {
+ if (startParents[i] != endParents[i]) {
+ return startParents[i - 1];
+ }
+ }
+ }
+ }, {
+ key: "_checkCollapsed",
+ value: function _checkCollapsed() {
+ if (this.startContainer === this.endContainer && this.startOffset === this.endOffset) {
+ this.collapsed = true;
+ } else {
+ this.collapsed = false;
+ }
+ }
+ }, {
+ key: "toString",
+ value: function toString() {
+ // TODO: implement walking between start and end to find text
+ }
+ }]);
+
+ return RangeObject;
+}();
+
+/***/ }),
+/* 1 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+
+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; };
+
+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; }; }();
+
+var _core = __webpack_require__(0);
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+var ELEMENT_NODE = 1;
+var TEXT_NODE = 3;
+var COMMENT_NODE = 8;
+var DOCUMENT_NODE = 9;
+
+/**
+ * Parsing and creation of EpubCFIs: http://www.idpf.org/epub/linking/cfi/epub-cfi.html
+
+ * Implements:
+ * - Character Offset: epubcfi(/6/4[chap01ref]!/4[body01]/10[para05]/2/1:3)
+ * - Simple Ranges : epubcfi(/6/4[chap01ref]!/4[body01]/10[para05],/2/1:1,/3:4)
+
+ * Does Not Implement:
+ * - Temporal Offset (~)
+ * - Spatial Offset (@)
+ * - Temporal-Spatial Offset (~ + @)
+ * - Text Location Assertion ([)
+ * @class
+ @param {string | Range | Node } [cfiFrom]
+ @param {string | object} [base]
+ @param {string} [ignoreClass] class to ignore when parsing DOM
+*/
+
+var EpubCFI = function () {
+ function EpubCFI(cfiFrom, base, ignoreClass) {
+ _classCallCheck(this, EpubCFI);
+
+ var type;
+
+ this.str = "";
+
+ this.base = {};
+ this.spinePos = 0; // For compatibility
+
+ this.range = false; // true || false;
+
+ this.path = {};
+ this.start = null;
+ this.end = null;
+
+ // Allow instantiation without the "new" keyword
+ if (!(this instanceof EpubCFI)) {
+ return new EpubCFI(cfiFrom, base, ignoreClass);
+ }
+
+ if (typeof base === "string") {
+ this.base = this.parseComponent(base);
+ } else if ((typeof base === "undefined" ? "undefined" : _typeof(base)) === "object" && base.steps) {
+ this.base = base;
+ }
+
+ type = this.checkType(cfiFrom);
+
+ if (type === "string") {
+ this.str = cfiFrom;
+ return (0, _core.extend)(this, this.parse(cfiFrom));
+ } else if (type === "range") {
+ return (0, _core.extend)(this, this.fromRange(cfiFrom, this.base, ignoreClass));
+ } else if (type === "node") {
+ return (0, _core.extend)(this, this.fromNode(cfiFrom, this.base, ignoreClass));
+ } else if (type === "EpubCFI" && cfiFrom.path) {
+ return cfiFrom;
+ } else if (!cfiFrom) {
+ return this;
+ } else {
+ throw new TypeError("not a valid argument for EpubCFI");
+ }
+ }
+
+ /**
+ * Check the type of constructor input
+ * @private
+ */
+
+
+ _createClass(EpubCFI, [{
+ key: "checkType",
+ value: function checkType(cfi) {
+
+ if (this.isCfiString(cfi)) {
+ return "string";
+ // Is a range object
+ } else if ((typeof cfi === "undefined" ? "undefined" : _typeof(cfi)) === "object" && ((0, _core.type)(cfi) === "Range" || typeof cfi.startContainer != "undefined")) {
+ return "range";
+ } else if ((typeof cfi === "undefined" ? "undefined" : _typeof(cfi)) === "object" && typeof cfi.nodeType != "undefined") {
+ // || typeof cfi === "function"
+ return "node";
+ } else if ((typeof cfi === "undefined" ? "undefined" : _typeof(cfi)) === "object" && cfi instanceof EpubCFI) {
+ return "EpubCFI";
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Parse a cfi string to a CFI object representation
+ * @param {string} cfiStr
+ * @returns {object} cfi
+ */
+
+ }, {
+ key: "parse",
+ value: function parse(cfiStr) {
+ var cfi = {
+ spinePos: -1,
+ range: false,
+ base: {},
+ path: {},
+ start: null,
+ end: null
+ };
+ var baseComponent, pathComponent, range;
+
+ if (typeof cfiStr !== "string") {
+ return { spinePos: -1 };
+ }
+
+ if (cfiStr.indexOf("epubcfi(") === 0 && cfiStr[cfiStr.length - 1] === ")") {
+ // Remove intial epubcfi( and ending )
+ cfiStr = cfiStr.slice(8, cfiStr.length - 1);
+ }
+
+ baseComponent = this.getChapterComponent(cfiStr);
+
+ // Make sure this is a valid cfi or return
+ if (!baseComponent) {
+ return { spinePos: -1 };
+ }
+
+ cfi.base = this.parseComponent(baseComponent);
+
+ pathComponent = this.getPathComponent(cfiStr);
+ cfi.path = this.parseComponent(pathComponent);
+
+ range = this.getRange(cfiStr);
+
+ if (range) {
+ cfi.range = true;
+ cfi.start = this.parseComponent(range[0]);
+ cfi.end = this.parseComponent(range[1]);
+ }
+
+ // Get spine node position
+ // cfi.spineSegment = cfi.base.steps[1];
+
+ // Chapter segment is always the second step
+ cfi.spinePos = cfi.base.steps[1].index;
+
+ return cfi;
+ }
+ }, {
+ key: "parseComponent",
+ value: function parseComponent(componentStr) {
+ var component = {
+ steps: [],
+ terminal: {
+ offset: null,
+ assertion: null
+ }
+ };
+ var parts = componentStr.split(":");
+ var steps = parts[0].split("/");
+ var terminal;
+
+ if (parts.length > 1) {
+ terminal = parts[1];
+ component.terminal = this.parseTerminal(terminal);
+ }
+
+ if (steps[0] === "") {
+ steps.shift(); // Ignore the first slash
+ }
+
+ component.steps = steps.map(function (step) {
+ return this.parseStep(step);
+ }.bind(this));
+
+ return component;
+ }
+ }, {
+ key: "parseStep",
+ value: function parseStep(stepStr) {
+ var type, num, index, has_brackets, id;
+
+ has_brackets = stepStr.match(/\[(.*)\]/);
+ if (has_brackets && has_brackets[1]) {
+ id = has_brackets[1];
+ }
+
+ //-- Check if step is a text node or element
+ num = parseInt(stepStr);
+
+ if (isNaN(num)) {
+ return;
+ }
+
+ if (num % 2 === 0) {
+ // Even = is an element
+ type = "element";
+ index = num / 2 - 1;
+ } else {
+ type = "text";
+ index = (num - 1) / 2;
+ }
+
+ return {
+ "type": type,
+ "index": index,
+ "id": id || null
+ };
+ }
+ }, {
+ key: "parseTerminal",
+ value: function parseTerminal(termialStr) {
+ var characterOffset, textLocationAssertion;
+ var assertion = termialStr.match(/\[(.*)\]/);
+
+ if (assertion && assertion[1]) {
+ characterOffset = parseInt(termialStr.split("[")[0]);
+ textLocationAssertion = assertion[1];
+ } else {
+ characterOffset = parseInt(termialStr);
+ }
+
+ if (!(0, _core.isNumber)(characterOffset)) {
+ characterOffset = null;
+ }
+
+ return {
+ "offset": characterOffset,
+ "assertion": textLocationAssertion
+ };
+ }
+ }, {
+ key: "getChapterComponent",
+ value: function getChapterComponent(cfiStr) {
+
+ var indirection = cfiStr.split("!");
+
+ return indirection[0];
+ }
+ }, {
+ key: "getPathComponent",
+ value: function getPathComponent(cfiStr) {
+
+ var indirection = cfiStr.split("!");
+
+ if (indirection[1]) {
+ var ranges = indirection[1].split(",");
+ return ranges[0];
+ }
+ }
+ }, {
+ key: "getRange",
+ value: function getRange(cfiStr) {
+
+ var ranges = cfiStr.split(",");
+
+ if (ranges.length === 3) {
+ return [ranges[1], ranges[2]];
+ }
+
+ return false;
+ }
+ }, {
+ key: "getCharecterOffsetComponent",
+ value: function getCharecterOffsetComponent(cfiStr) {
+ var splitStr = cfiStr.split(":");
+ return splitStr[1] || "";
+ }
+ }, {
+ key: "joinSteps",
+ value: function joinSteps(steps) {
+ if (!steps) {
+ return "";
+ }
+
+ return steps.map(function (part) {
+ var segment = "";
+
+ if (part.type === "element") {
+ segment += (part.index + 1) * 2;
+ }
+
+ if (part.type === "text") {
+ segment += 1 + 2 * part.index; // TODO: double check that this is odd
+ }
+
+ if (part.id) {
+ segment += "[" + part.id + "]";
+ }
+
+ return segment;
+ }).join("/");
+ }
+ }, {
+ key: "segmentString",
+ value: function segmentString(segment) {
+ var segmentString = "/";
+
+ segmentString += this.joinSteps(segment.steps);
+
+ if (segment.terminal && segment.terminal.offset != null) {
+ segmentString += ":" + segment.terminal.offset;
+ }
+
+ if (segment.terminal && segment.terminal.assertion != null) {
+ segmentString += "[" + segment.terminal.assertion + "]";
+ }
+
+ return segmentString;
+ }
+
+ /**
+ * Convert CFI to a epubcfi(...) string
+ * @returns {string} epubcfi
+ */
+
+ }, {
+ key: "toString",
+ value: function toString() {
+ var cfiString = "epubcfi(";
+
+ cfiString += this.segmentString(this.base);
+
+ cfiString += "!";
+ cfiString += this.segmentString(this.path);
+
+ // Add Range, if present
+ if (this.range && this.start) {
+ cfiString += ",";
+ cfiString += this.segmentString(this.start);
+ }
+
+ if (this.range && this.end) {
+ cfiString += ",";
+ cfiString += this.segmentString(this.end);
+ }
+
+ cfiString += ")";
+
+ return cfiString;
+ }
+
+ /**
+ * Compare which of two CFIs is earlier in the text
+ * @returns {number} First is earlier = 1, Second is earlier = -1, They are equal = 0
+ */
+
+ }, {
+ key: "compare",
+ value: function compare(cfiOne, cfiTwo) {
+ var stepsA, stepsB;
+ var terminalA, terminalB;
+
+ var rangeAStartSteps, rangeAEndSteps;
+ var rangeBEndSteps, rangeBEndSteps;
+ var rangeAStartTerminal, rangeAEndTerminal;
+ var rangeBStartTerminal, rangeBEndTerminal;
+
+ if (typeof cfiOne === "string") {
+ cfiOne = new EpubCFI(cfiOne);
+ }
+ if (typeof cfiTwo === "string") {
+ cfiTwo = new EpubCFI(cfiTwo);
+ }
+ // Compare Spine Positions
+ if (cfiOne.spinePos > cfiTwo.spinePos) {
+ return 1;
+ }
+ if (cfiOne.spinePos < cfiTwo.spinePos) {
+ return -1;
+ }
+
+ if (cfiOne.range) {
+ stepsA = cfiOne.path.steps.concat(cfiOne.start.steps);
+ terminalA = cfiOne.start.terminal;
+ } else {
+ stepsA = cfiOne.path.steps;
+ terminalA = cfiOne.path.terminal;
+ }
+
+ if (cfiTwo.range) {
+ stepsB = cfiTwo.path.steps.concat(cfiTwo.start.steps);
+ terminalB = cfiTwo.start.terminal;
+ } else {
+ stepsB = cfiTwo.path.steps;
+ terminalB = cfiTwo.path.terminal;
+ }
+
+ // Compare Each Step in the First item
+ for (var i = 0; i < stepsA.length; i++) {
+ if (!stepsA[i]) {
+ return -1;
+ }
+ if (!stepsB[i]) {
+ return 1;
+ }
+ if (stepsA[i].index > stepsB[i].index) {
+ return 1;
+ }
+ if (stepsA[i].index < stepsB[i].index) {
+ return -1;
+ }
+ // Otherwise continue checking
+ }
+
+ // All steps in First equal to Second and First is Less Specific
+ if (stepsA.length < stepsB.length) {
+ return 1;
+ }
+
+ // Compare the charecter offset of the text node
+ if (terminalA.offset > terminalB.offset) {
+ return 1;
+ }
+ if (terminalA.offset < terminalB.offset) {
+ return -1;
+ }
+
+ // CFI's are equal
+ return 0;
+ }
+ }, {
+ key: "step",
+ value: function step(node) {
+ var nodeType = node.nodeType === TEXT_NODE ? "text" : "element";
+
+ return {
+ "id": node.id,
+ "tagName": node.tagName,
+ "type": nodeType,
+ "index": this.position(node)
+ };
+ }
+ }, {
+ key: "filteredStep",
+ value: function filteredStep(node, ignoreClass) {
+ var filteredNode = this.filter(node, ignoreClass);
+ var nodeType;
+
+ // Node filtered, so ignore
+ if (!filteredNode) {
+ return;
+ }
+
+ // Otherwise add the filter node in
+ nodeType = filteredNode.nodeType === TEXT_NODE ? "text" : "element";
+
+ return {
+ "id": filteredNode.id,
+ "tagName": filteredNode.tagName,
+ "type": nodeType,
+ "index": this.filteredPosition(filteredNode, ignoreClass)
+ };
+ }
+ }, {
+ key: "pathTo",
+ value: function pathTo(node, offset, ignoreClass) {
+ var segment = {
+ steps: [],
+ terminal: {
+ offset: null,
+ assertion: null
+ }
+ };
+ var currentNode = node;
+ var step;
+
+ while (currentNode && currentNode.parentNode && currentNode.parentNode.nodeType != DOCUMENT_NODE) {
+
+ if (ignoreClass) {
+ step = this.filteredStep(currentNode, ignoreClass);
+ } else {
+ step = this.step(currentNode);
+ }
+
+ if (step) {
+ segment.steps.unshift(step);
+ }
+
+ currentNode = currentNode.parentNode;
+ }
+
+ if (offset != null && offset >= 0) {
+
+ segment.terminal.offset = offset;
+
+ // Make sure we are getting to a textNode if there is an offset
+ if (segment.steps[segment.steps.length - 1].type != "text") {
+ segment.steps.push({
+ "type": "text",
+ "index": 0
+ });
+ }
+ }
+
+ return segment;
+ }
+ }, {
+ key: "equalStep",
+ value: function equalStep(stepA, stepB) {
+ if (!stepA || !stepB) {
+ return false;
+ }
+
+ if (stepA.index === stepB.index && stepA.id === stepB.id && stepA.type === stepB.type) {
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Create a CFI object from a Range
+ * @param {Range} range
+ * @param {string | object} base
+ * @param {string} [ignoreClass]
+ * @returns {object} cfi
+ */
+
+ }, {
+ key: "fromRange",
+ value: function fromRange(range, base, ignoreClass) {
+ var cfi = {
+ range: false,
+ base: {},
+ path: {},
+ start: null,
+ end: null
+ };
+
+ var start = range.startContainer;
+ var end = range.endContainer;
+
+ var startOffset = range.startOffset;
+ var endOffset = range.endOffset;
+
+ var needsIgnoring = false;
+
+ if (ignoreClass) {
+ // Tell pathTo if / what to ignore
+ needsIgnoring = start.ownerDocument.querySelector("." + ignoreClass) != null;
+ }
+
+ if (typeof base === "string") {
+ cfi.base = this.parseComponent(base);
+ cfi.spinePos = cfi.base.steps[1].index;
+ } else if ((typeof base === "undefined" ? "undefined" : _typeof(base)) === "object") {
+ cfi.base = base;
+ }
+
+ if (range.collapsed) {
+ if (needsIgnoring) {
+ startOffset = this.patchOffset(start, startOffset, ignoreClass);
+ }
+ cfi.path = this.pathTo(start, startOffset, ignoreClass);
+ } else {
+ cfi.range = true;
+
+ if (needsIgnoring) {
+ startOffset = this.patchOffset(start, startOffset, ignoreClass);
+ }
+
+ cfi.start = this.pathTo(start, startOffset, ignoreClass);
+ if (needsIgnoring) {
+ endOffset = this.patchOffset(end, endOffset, ignoreClass);
+ }
+
+ cfi.end = this.pathTo(end, endOffset, ignoreClass);
+
+ // Create a new empty path
+ cfi.path = {
+ steps: [],
+ terminal: null
+ };
+
+ // Push steps that are shared between start and end to the common path
+ var len = cfi.start.steps.length;
+ var i;
+
+ for (i = 0; i < len; i++) {
+ if (this.equalStep(cfi.start.steps[i], cfi.end.steps[i])) {
+ if (i === len - 1) {
+ // Last step is equal, check terminals
+ if (cfi.start.terminal === cfi.end.terminal) {
+ // CFI's are equal
+ cfi.path.steps.push(cfi.start.steps[i]);
+ // Not a range
+ cfi.range = false;
+ }
+ } else {
+ cfi.path.steps.push(cfi.start.steps[i]);
+ }
+ } else {
+ break;
+ }
+ }
+
+ cfi.start.steps = cfi.start.steps.slice(cfi.path.steps.length);
+ 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
+ }
+
+ return cfi;
+ }
+
+ /**
+ * Create a CFI object from a Node
+ * @param {Node} anchor
+ * @param {string | object} base
+ * @param {string} [ignoreClass]
+ * @returns {object} cfi
+ */
+
+ }, {
+ key: "fromNode",
+ value: function fromNode(anchor, base, ignoreClass) {
+ var cfi = {
+ range: false,
+ base: {},
+ path: {},
+ start: null,
+ end: null
+ };
+
+ if (typeof base === "string") {
+ cfi.base = this.parseComponent(base);
+ cfi.spinePos = cfi.base.steps[1].index;
+ } else if ((typeof base === "undefined" ? "undefined" : _typeof(base)) === "object") {
+ cfi.base = base;
+ }
+
+ cfi.path = this.pathTo(anchor, null, ignoreClass);
+
+ return cfi;
+ }
+ }, {
+ key: "filter",
+ value: function filter(anchor, ignoreClass) {
+ var needsIgnoring;
+ var sibling; // to join with
+ var parent, previousSibling, nextSibling;
+ var isText = false;
+
+ if (anchor.nodeType === TEXT_NODE) {
+ isText = true;
+ parent = anchor.parentNode;
+ needsIgnoring = anchor.parentNode.classList.contains(ignoreClass);
+ } else {
+ isText = false;
+ needsIgnoring = anchor.classList.contains(ignoreClass);
+ }
+
+ if (needsIgnoring && isText) {
+ previousSibling = parent.previousSibling;
+ nextSibling = parent.nextSibling;
+
+ // If the sibling is a text node, join the nodes
+ if (previousSibling && previousSibling.nodeType === TEXT_NODE) {
+ sibling = previousSibling;
+ } else if (nextSibling && nextSibling.nodeType === TEXT_NODE) {
+ sibling = nextSibling;
+ }
+
+ if (sibling) {
+ return sibling;
+ } else {
+ // Parent will be ignored on next step
+ return anchor;
+ }
+ } else if (needsIgnoring && !isText) {
+ // Otherwise just skip the element node
+ return false;
+ } else {
+ // No need to filter
+ return anchor;
+ }
+ }
+ }, {
+ key: "patchOffset",
+ value: function patchOffset(anchor, offset, ignoreClass) {
+ if (anchor.nodeType != TEXT_NODE) {
+ throw new Error("Anchor must be a text node");
+ }
+
+ var curr = anchor;
+ var totalOffset = offset;
+
+ // If the parent is a ignored node, get offset from it's start
+ if (anchor.parentNode.classList.contains(ignoreClass)) {
+ curr = anchor.parentNode;
+ }
+
+ while (curr.previousSibling) {
+ if (curr.previousSibling.nodeType === ELEMENT_NODE) {
+ // Originally a text node, so join
+ if (curr.previousSibling.classList.contains(ignoreClass)) {
+ totalOffset += curr.previousSibling.textContent.length;
+ } else {
+ break; // Normal node, dont join
+ }
+ } else {
+ // If the previous sibling is a text node, join the nodes
+ totalOffset += curr.previousSibling.textContent.length;
+ }
+
+ curr = curr.previousSibling;
+ }
+
+ return totalOffset;
+ }
+ }, {
+ key: "normalizedMap",
+ value: function normalizedMap(children, nodeType, ignoreClass) {
+ var output = {};
+ var prevIndex = -1;
+ var i,
+ len = children.length;
+ var currNodeType;
+ var prevNodeType;
+
+ for (i = 0; i < len; i++) {
+
+ currNodeType = children[i].nodeType;
+
+ // Check if needs ignoring
+ if (currNodeType === ELEMENT_NODE && children[i].classList.contains(ignoreClass)) {
+ currNodeType = TEXT_NODE;
+ }
+
+ if (i > 0 && currNodeType === TEXT_NODE && prevNodeType === TEXT_NODE) {
+ // join text nodes
+ output[i] = prevIndex;
+ } else if (nodeType === currNodeType) {
+ prevIndex = prevIndex + 1;
+ output[i] = prevIndex;
+ }
+
+ prevNodeType = currNodeType;
+ }
+
+ return output;
+ }
+ }, {
+ key: "position",
+ value: function position(anchor) {
+ var children, index;
+ if (anchor.nodeType === ELEMENT_NODE) {
+ children = anchor.parentNode.children;
+ if (!children) {
+ children = (0, _core.findChildren)(anchor.parentNode);
+ }
+ index = Array.prototype.indexOf.call(children, anchor);
+ } else {
+ children = this.textNodes(anchor.parentNode);
+ index = children.indexOf(anchor);
+ }
+
+ return index;
+ }
+ }, {
+ key: "filteredPosition",
+ value: function filteredPosition(anchor, ignoreClass) {
+ var children, index, map;
+
+ if (anchor.nodeType === ELEMENT_NODE) {
+ children = anchor.parentNode.children;
+ map = this.normalizedMap(children, ELEMENT_NODE, ignoreClass);
+ } else {
+ children = anchor.parentNode.childNodes;
+ // Inside an ignored node
+ if (anchor.parentNode.classList.contains(ignoreClass)) {
+ anchor = anchor.parentNode;
+ children = anchor.parentNode.childNodes;
+ }
+ map = this.normalizedMap(children, TEXT_NODE, ignoreClass);
+ }
+
+ index = Array.prototype.indexOf.call(children, anchor);
+
+ return map[index];
+ }
+ }, {
+ key: "stepsToXpath",
+ value: function stepsToXpath(steps) {
+ var xpath = [".", "*"];
+
+ steps.forEach(function (step) {
+ var position = step.index + 1;
+
+ if (step.id) {
+ xpath.push("*[position()=" + position + " and @id='" + step.id + "']");
+ } else if (step.type === "text") {
+ xpath.push("text()[" + position + "]");
+ } else {
+ xpath.push("*[" + position + "]");
+ }
+ });
+
+ return xpath.join("/");
+ }
+
+ /*
+ To get the last step if needed:
+ // Get the terminal step
+ lastStep = steps[steps.length-1];
+ // Get the query string
+ query = this.stepsToQuery(steps);
+ // Find the containing element
+ startContainerParent = doc.querySelector(query);
+ // Find the text node within that element
+ if(startContainerParent && lastStep.type == "text") {
+ container = startContainerParent.childNodes[lastStep.index];
+ }
+ */
+
+ }, {
+ key: "stepsToQuerySelector",
+ value: function stepsToQuerySelector(steps) {
+ var query = ["html"];
+
+ steps.forEach(function (step) {
+ var position = step.index + 1;
+
+ if (step.id) {
+ query.push("#" + step.id);
+ } else if (step.type === "text") {
+ // unsupported in querySelector
+ // query.push("text()[" + position + "]");
+ } else {
+ query.push("*:nth-child(" + position + ")");
+ }
+ });
+
+ return query.join(">");
+ }
+ }, {
+ key: "textNodes",
+ value: function textNodes(container, ignoreClass) {
+ return Array.prototype.slice.call(container.childNodes).filter(function (node) {
+ if (node.nodeType === TEXT_NODE) {
+ return true;
+ } else if (ignoreClass && node.classList.contains(ignoreClass)) {
+ return true;
+ }
+ return false;
+ });
+ }
+ }, {
+ key: "walkToNode",
+ value: function walkToNode(steps, _doc, ignoreClass) {
+ var doc = _doc || document;
+ var container = doc.documentElement;
+ var children;
+ var step;
+ var len = steps.length;
+ var i;
+
+ for (i = 0; i < len; i++) {
+ step = steps[i];
+
+ if (step.type === "element") {
+ //better to get a container using id as some times step.index may not be correct
+ //For ex.https://github.com/futurepress/epub.js/issues/561
+ if (step.id) {
+ container = doc.getElementById(step.id);
+ } else {
+ children = container.children || (0, _core.findChildren)(container);
+ container = children[step.index];
+ }
+ } else if (step.type === "text") {
+ container = this.textNodes(container, ignoreClass)[step.index];
+ }
+ if (!container) {
+ //Break the for loop as due to incorrect index we can get error if
+ //container is undefined so that other functionailties works fine
+ //like navigation
+ break;
+ }
+ }
+
+ return container;
+ }
+ }, {
+ key: "findNode",
+ value: function findNode(steps, _doc, ignoreClass) {
+ var doc = _doc || document;
+ var container;
+ var xpath;
+
+ if (!ignoreClass && typeof doc.evaluate != "undefined") {
+ xpath = this.stepsToXpath(steps);
+ container = doc.evaluate(xpath, doc, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
+ } else if (ignoreClass) {
+ container = this.walkToNode(steps, doc, ignoreClass);
+ } else {
+ container = this.walkToNode(steps, doc);
+ }
+
+ return container;
+ }
+ }, {
+ key: "fixMiss",
+ value: function fixMiss(steps, offset, _doc, ignoreClass) {
+ var container = this.findNode(steps.slice(0, -1), _doc, ignoreClass);
+ var children = container.childNodes;
+ var map = this.normalizedMap(children, TEXT_NODE, ignoreClass);
+ var child;
+ var len;
+ var lastStepIndex = steps[steps.length - 1].index;
+
+ for (var childIndex in map) {
+ if (!map.hasOwnProperty(childIndex)) return;
+
+ if (map[childIndex] === lastStepIndex) {
+ child = children[childIndex];
+ len = child.textContent.length;
+ if (offset > len) {
+ offset = offset - len;
+ } else {
+ if (child.nodeType === ELEMENT_NODE) {
+ container = child.childNodes[0];
+ } else {
+ container = child;
+ }
+ break;
+ }
+ }
+ }
+
+ return {
+ container: container,
+ offset: offset
+ };
+ }
+
+ /**
+ * Creates a DOM range representing a CFI
+ * @param {document} _doc document referenced in the base
+ * @param {string} [ignoreClass]
+ * @return {Range}
+ */
+
+ }, {
+ key: "toRange",
+ value: function toRange(_doc, ignoreClass) {
+ var doc = _doc || document;
+ var range;
+ var start, end, startContainer, endContainer;
+ var cfi = this;
+ var startSteps, endSteps;
+ var needsIgnoring = ignoreClass ? doc.querySelector("." + ignoreClass) != null : false;
+ var missed;
+
+ if (typeof doc.createRange !== "undefined") {
+ range = doc.createRange();
+ } else {
+ range = new _core.RangeObject();
+ }
+
+ if (cfi.range) {
+ start = cfi.start;
+ startSteps = cfi.path.steps.concat(start.steps);
+ startContainer = this.findNode(startSteps, doc, needsIgnoring ? ignoreClass : null);
+ end = cfi.end;
+ endSteps = cfi.path.steps.concat(end.steps);
+ endContainer = this.findNode(endSteps, doc, needsIgnoring ? ignoreClass : null);
+ } else {
+ start = cfi.path;
+ startSteps = cfi.path.steps;
+ startContainer = this.findNode(cfi.path.steps, doc, needsIgnoring ? ignoreClass : null);
+ }
+
+ if (startContainer) {
+ try {
+
+ if (start.terminal.offset != null) {
+ range.setStart(startContainer, start.terminal.offset);
+ } else {
+ range.setStart(startContainer, 0);
+ }
+ } catch (e) {
+ missed = this.fixMiss(startSteps, start.terminal.offset, doc, needsIgnoring ? ignoreClass : null);
+ range.setStart(missed.container, missed.offset);
+ }
+ } else {
+ console.log("No startContainer found for", this.toString());
+ // No start found
+ return null;
+ }
+
+ if (endContainer) {
+ try {
+
+ if (end.terminal.offset != null) {
+ range.setEnd(endContainer, end.terminal.offset);
+ } else {
+ range.setEnd(endContainer, 0);
+ }
+ } catch (e) {
+ missed = this.fixMiss(endSteps, cfi.end.terminal.offset, doc, needsIgnoring ? ignoreClass : null);
+ range.setEnd(missed.container, missed.offset);
+ }
+ }
+
+ // doc.defaultView.getSelection().addRange(range);
+ return range;
+ }
+
+ /**
+ * Check if a string is wrapped with "epubcfi()"
+ * @param {string} str
+ * @returns {boolean}
+ */
+
+ }, {
+ key: "isCfiString",
+ value: function isCfiString(str) {
+ if (typeof str === "string" && str.indexOf("epubcfi(") === 0 && str[str.length - 1] === ")") {
+ return true;
+ }
+
+ return false;
+ }
+ }, {
+ key: "generateChapterComponent",
+ value: function generateChapterComponent(_spineNodeIndex, _pos, id) {
+ var pos = parseInt(_pos),
+ spineNodeIndex = (_spineNodeIndex + 1) * 2,
+ cfi = "/" + spineNodeIndex + "/";
+
+ cfi += (pos + 1) * 2;
+
+ if (id) {
+ cfi += "[" + id + "]";
+ }
+
+ return cfi;
+ }
+
+ /**
+ * Collapse a CFI Range to a single CFI Position
+ * @param {boolean} [toStart=false]
+ */
+
+ }, {
+ key: "collapse",
+ value: function collapse(toStart) {
+ if (!this.range) {
+ return;
+ }
+
+ this.range = false;
+
+ if (toStart) {
+ this.path.steps = this.path.steps.concat(this.start.steps);
+ this.path.terminal = this.start.terminal;
+ } else {
+ this.path.steps = this.path.steps.concat(this.end.steps);
+ this.path.terminal = this.end.terminal;
+ }
+ }
+ }]);
+
+ return EpubCFI;
+}();
+
+exports.default = EpubCFI;
+module.exports = exports["default"];
+
+/***/ }),
+/* 2 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+var d = __webpack_require__(27)
+ , callable = __webpack_require__(41)
+
+ , apply = Function.prototype.apply, call = Function.prototype.call
+ , create = Object.create, defineProperty = Object.defineProperty
+ , defineProperties = Object.defineProperties
+ , hasOwnProperty = Object.prototype.hasOwnProperty
+ , descriptor = { configurable: true, enumerable: false, writable: true }
+
+ , on, once, off, emit, methods, descriptors, base;
+
+on = function (type, listener) {
+ var data;
+
+ callable(listener);
+
+ if (!hasOwnProperty.call(this, '__ee__')) {
+ data = descriptor.value = create(null);
+ defineProperty(this, '__ee__', descriptor);
+ descriptor.value = null;
+ } else {
+ data = this.__ee__;
+ }
+ if (!data[type]) data[type] = listener;
+ else if (typeof data[type] === 'object') data[type].push(listener);
+ else data[type] = [data[type], listener];
+
+ return this;
+};
+
+once = function (type, listener) {
+ var once, self;
+
+ callable(listener);
+ self = this;
+ on.call(this, type, once = function () {
+ off.call(self, type, once);
+ apply.call(listener, this, arguments);
+ });
+
+ once.__eeOnceListener__ = listener;
+ return this;
+};
+
+off = function (type, listener) {
+ var data, listeners, candidate, i;
+
+ callable(listener);
+
+ if (!hasOwnProperty.call(this, '__ee__')) return this;
+ data = this.__ee__;
+ if (!data[type]) return this;
+ listeners = data[type];
+
+ if (typeof listeners === 'object') {
+ for (i = 0; (candidate = listeners[i]); ++i) {
+ if ((candidate === listener) ||
+ (candidate.__eeOnceListener__ === listener)) {
+ if (listeners.length === 2) data[type] = listeners[i ? 0 : 1];
+ else listeners.splice(i, 1);
+ }
+ }
+ } else {
+ if ((listeners === listener) ||
+ (listeners.__eeOnceListener__ === listener)) {
+ delete data[type];
+ }
+ }
+
+ return this;
+};
+
+emit = function (type) {
+ var i, l, listener, listeners, args;
+
+ if (!hasOwnProperty.call(this, '__ee__')) return;
+ listeners = this.__ee__[type];
+ if (!listeners) return;
+
+ if (typeof listeners === 'object') {
+ l = arguments.length;
+ args = new Array(l - 1);
+ for (i = 1; i < l; ++i) args[i - 1] = arguments[i];
+
+ listeners = listeners.slice();
+ for (i = 0; (listener = listeners[i]); ++i) {
+ apply.call(listener, this, args);
+ }
+ } else {
+ switch (arguments.length) {
+ case 1:
+ call.call(listeners, this);
+ break;
+ case 2:
+ call.call(listeners, this, arguments[1]);
+ break;
+ case 3:
+ call.call(listeners, this, arguments[1], arguments[2]);
+ break;
+ default:
+ l = arguments.length;
+ args = new Array(l - 1);
+ for (i = 1; i < l; ++i) {
+ args[i - 1] = arguments[i];
+ }
+ apply.call(listeners, this, args);
+ }
+ }
+};
+
+methods = {
+ on: on,
+ once: once,
+ off: off,
+ emit: emit
+};
+
+descriptors = {
+ on: d(on),
+ once: d(once),
+ off: d(off),
+ emit: d(emit)
+};
+
+base = defineProperties({}, descriptors);
+
+module.exports = exports = function (o) {
+ return (o == null) ? create(base) : defineProperties(Object(o), descriptors);
+};
+exports.methods = methods;
+
+
+/***/ }),
+/* 3 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+// Dom events to listen for
+var DOM_EVENTS = exports.DOM_EVENTS = ["keydown", "keyup", "keypressed", "mouseup", "mousedown", "click", "touchend", "touchstart"];
+
+var EVENTS = exports.EVENTS = {
+ BOOK: {
+ OPEN_FAILED: "openFailed"
+ },
+ CONTENTS: {
+ EXPAND: "expand",
+ RESIZE: "resize",
+ SELECTED: "selected",
+ SELECTED_RANGE: "selectedRange",
+ LINK_CLICKED: "linkClicked"
+ },
+ LOCATIONS: {
+ CHANGED: "changed"
+ },
+ MANAGERS: {
+ RESIZE: "resize",
+ RESIZED: "resized",
+ ORIENTATION_CHANGE: "orientationchange",
+ ADDED: "added",
+ SCROLL: "scroll",
+ SCROLLED: "scrolled"
+ },
+ VIEWS: {
+ AXIS: "axis",
+ LOAD_ERROR: "loaderror",
+ RENDERED: "rendered",
+ RESIZED: "resized",
+ DISPLAYED: "displayed",
+ SHOWN: "shown",
+ HIDDEN: "hidden",
+ MARK_CLICKED: "markClicked"
+ },
+ RENDITION: {
+ STARTED: "started",
+ ATTACHED: "attached",
+ DISPLAYED: "displayed",
+ DISPLAY_ERROR: "displayerror",
+ RENDERED: "rendered",
+ REMOVED: "removed",
+ RESIZED: "resized",
+ ORIENTATION_CHANGE: "orientationchange",
+ LOCATION_CHANGED: "locationChanged",
+ RELOCATED: "relocated",
+ MARK_CLICKED: "markClicked",
+ SELECTED: "selected",
+ LAYOUT: "layout"
+ },
+ LAYOUT: {
+ UPDATED: "updated"
+ }
+};
+
+/***/ }),
+/* 4 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+
+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; }; }();
+
+var _pathWebpack = __webpack_require__(6);
+
+var _pathWebpack2 = _interopRequireDefault(_pathWebpack);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+/**
+ * Creates a Path object for parsing and manipulation of a path strings
+ *
+ * Uses a polyfill for Nodejs path: https://nodejs.org/api/path.html
+ * @param {string} pathString a url string (relative or absolute)
+ * @class
+ */
+var Path = function () {
+ function Path(pathString) {
+ _classCallCheck(this, Path);
+
+ var protocol;
+ var parsed;
+
+ protocol = pathString.indexOf("://");
+ if (protocol > -1) {
+ pathString = new URL(pathString).pathname;
+ }
+
+ parsed = this.parse(pathString);
+
+ this.path = pathString;
+
+ if (this.isDirectory(pathString)) {
+ this.directory = pathString;
+ } else {
+ this.directory = parsed.dir + "/";
+ }
+
+ this.filename = parsed.base;
+ this.extension = parsed.ext.slice(1);
+ }
+
+ /**
+ * Parse the path: https://nodejs.org/api/path.html#path_path_parse_path
+ * @param {string} what
+ * @returns {object}
+ */
+
+
+ _createClass(Path, [{
+ key: "parse",
+ value: function parse(what) {
+ return _pathWebpack2.default.parse(what);
+ }
+
+ /**
+ * @param {string} what
+ * @returns {boolean}
+ */
+
+ }, {
+ key: "isAbsolute",
+ value: function isAbsolute(what) {
+ return _pathWebpack2.default.isAbsolute(what || this.path);
+ }
+
+ /**
+ * Check if path ends with a directory
+ * @param {string} what
+ * @returns {boolean}
+ */
+
+ }, {
+ key: "isDirectory",
+ value: function isDirectory(what) {
+ return what.charAt(what.length - 1) === "/";
+ }
+
+ /**
+ * Resolve a path against the directory of the Path
+ *
+ * https://nodejs.org/api/path.html#path_path_resolve_paths
+ * @param {string} what
+ * @returns {string} resolved
+ */
+
+ }, {
+ key: "resolve",
+ value: function resolve(what) {
+ return _pathWebpack2.default.resolve(this.directory, what);
+ }
+
+ /**
+ * Resolve a path relative to the directory of the Path
+ *
+ * https://nodejs.org/api/path.html#path_path_relative_from_to
+ * @param {string} what
+ * @returns {string} relative
+ */
+
+ }, {
+ key: "relative",
+ value: function relative(what) {
+ return _pathWebpack2.default.relative(this.directory, what);
+ }
+ }, {
+ key: "splitPath",
+ value: function splitPath(filename) {
+ return this.splitPathRe.exec(filename).slice(1);
+ }
+
+ /**
+ * Return the path string
+ * @returns {string} path
+ */
+
+ }, {
+ key: "toString",
+ value: function toString() {
+ return this.path;
+ }
+ }]);
+
+ return Path;
+}();
+
+exports.default = Path;
+module.exports = exports["default"];
+
+/***/ }),
+/* 5 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+
+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; }; }();
+
+var _path = __webpack_require__(4);
+
+var _path2 = _interopRequireDefault(_path);
+
+var _pathWebpack = __webpack_require__(6);
+
+var _pathWebpack2 = _interopRequireDefault(_pathWebpack);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+/**
+ * creates a Url object for parsing and manipulation of a url string
+ * @param {string} urlString a url string (relative or absolute)
+ * @param {string} [baseString] optional base for the url,
+ * default to window.location.href
+ */
+var Url = function () {
+ function Url(urlString, baseString) {
+ _classCallCheck(this, Url);
+
+ var absolute = urlString.indexOf("://") > -1;
+ var pathname = urlString;
+ var basePath;
+
+ this.Url = undefined;
+ this.href = urlString;
+ this.protocol = "";
+ this.origin = "";
+ this.hash = "";
+ this.hash = "";
+ this.search = "";
+ this.base = baseString;
+
+ if (!absolute && baseString !== false && typeof baseString !== "string" && window && window.location) {
+ this.base = window.location.href;
+ }
+
+ // URL Polyfill doesn't throw an error if base is empty
+ if (absolute || this.base) {
+ try {
+ if (this.base) {
+ // Safari doesn't like an undefined base
+ this.Url = new URL(urlString, this.base);
+ } else {
+ this.Url = new URL(urlString);
+ }
+ this.href = this.Url.href;
+
+ this.protocol = this.Url.protocol;
+ this.origin = this.Url.origin;
+ this.hash = this.Url.hash;
+ this.search = this.Url.search;
+
+ pathname = this.Url.pathname;
+ } catch (e) {
+ // Skip URL parsing
+ this.Url = undefined;
+ // resolve the pathname from the base
+ if (this.base) {
+ basePath = new _path2.default(this.base);
+ pathname = basePath.resolve(pathname);
+ }
+ }
+ }
+
+ this.Path = new _path2.default(pathname);
+
+ this.directory = this.Path.directory;
+ this.filename = this.Path.filename;
+ this.extension = this.Path.extension;
+ }
+
+ /**
+ * @returns {Path}
+ */
+
+
+ _createClass(Url, [{
+ key: "path",
+ value: function path() {
+ return this.Path;
+ }
+
+ /**
+ * Resolves a relative path to a absolute url
+ * @returns {string} url
+ */
+
+ }, {
+ key: "resolve",
+ value: function resolve(what) {
+ var isAbsolute = what.indexOf("://") > -1;
+ var fullpath;
+
+ if (isAbsolute) {
+ return what;
+ }
+
+ fullpath = _pathWebpack2.default.resolve(this.directory, what);
+ return this.origin + fullpath;
+ }
+
+ /**
+ * Resolve a path relative to the url
+ * @returns {string} path
+ */
+
+ }, {
+ key: "relative",
+ value: function relative(what) {
+ return _pathWebpack2.default.relative(what, this.directory);
+ }
+
+ /**
+ * @returns {string}
+ */
+
+ }, {
+ key: "toString",
+ value: function toString() {
+ return this.href;
+ }
+ }]);
+
+ return Url;
+}();
+
+exports.default = Url;
+module.exports = exports["default"];
+
+/***/ }),
+/* 6 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+if (!process) {
+ var process = {
+ "cwd" : function () { return '/' }
+ };
+}
+
+function assertPath(path) {
+ if (typeof path !== 'string') {
+ throw new TypeError('Path must be a string. Received ' + path);
+ }
+}
+
+// Resolves . and .. elements in a path with directory names
+function normalizeStringPosix(path, allowAboveRoot) {
+ var res = '';
+ var lastSlash = -1;
+ var dots = 0;
+ var code;
+ for (var i = 0; i <= path.length; ++i) {
+ if (i < path.length)
+ code = path.charCodeAt(i);
+ else if (code === 47/*/*/)
+ break;
+ else
+ code = 47/*/*/;
+ if (code === 47/*/*/) {
+ if (lastSlash === i - 1 || dots === 1) {
+ // NOOP
+ } else if (lastSlash !== i - 1 && dots === 2) {
+ if (res.length < 2 ||
+ res.charCodeAt(res.length - 1) !== 46/*.*/ ||
+ res.charCodeAt(res.length - 2) !== 46/*.*/) {
+ if (res.length > 2) {
+ var start = res.length - 1;
+ var j = start;
+ for (; j >= 0; --j) {
+ if (res.charCodeAt(j) === 47/*/*/)
+ break;
+ }
+ if (j !== start) {
+ if (j === -1)
+ res = '';
+ else
+ res = res.slice(0, j);
+ lastSlash = i;
+ dots = 0;
+ continue;
+ }
+ } else if (res.length === 2 || res.length === 1) {
+ res = '';
+ lastSlash = i;
+ dots = 0;
+ continue;
+ }
+ }
+ if (allowAboveRoot) {
+ if (res.length > 0)
+ res += '/..';
+ else
+ res = '..';
+ }
+ } else {
+ if (res.length > 0)
+ res += '/' + path.slice(lastSlash + 1, i);
+ else
+ res = path.slice(lastSlash + 1, i);
+ }
+ lastSlash = i;
+ dots = 0;
+ } else if (code === 46/*.*/ && dots !== -1) {
+ ++dots;
+ } else {
+ dots = -1;
+ }
+ }
+ return res;
+}
+
+function _format(sep, pathObject) {
+ var dir = pathObject.dir || pathObject.root;
+ var base = pathObject.base ||
+ ((pathObject.name || '') + (pathObject.ext || ''));
+ if (!dir) {
+ return base;
+ }
+ if (dir === pathObject.root) {
+ return dir + base;
+ }
+ return dir + sep + base;
+}
+
+var posix = {
+ // path.resolve([from ...], to)
+ resolve: function resolve() {
+ var resolvedPath = '';
+ var resolvedAbsolute = false;
+ var cwd;
+
+ for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {
+ var path;
+ if (i >= 0)
+ path = arguments[i];
+ else {
+ if (cwd === undefined)
+ cwd = process.cwd();
+ path = cwd;
+ }
+
+ assertPath(path);
+
+ // Skip empty entries
+ if (path.length === 0) {
+ continue;
+ }
+
+ resolvedPath = path + '/' + resolvedPath;
+ resolvedAbsolute = path.charCodeAt(0) === 47/*/*/;
+ }
+
+ // At this point the path should be resolved to a full absolute path, but
+ // handle relative paths to be safe (might happen when process.cwd() fails)
+
+ // Normalize the path
+ resolvedPath = normalizeStringPosix(resolvedPath, !resolvedAbsolute);
+
+ if (resolvedAbsolute) {
+ if (resolvedPath.length > 0)
+ return '/' + resolvedPath;
+ else
+ return '/';
+ } else if (resolvedPath.length > 0) {
+ return resolvedPath;
+ } else {
+ return '.';
+ }
+ },
+
+
+ normalize: function normalize(path) {
+ assertPath(path);
+
+ if (path.length === 0)
+ return '.';
+
+ var isAbsolute = path.charCodeAt(0) === 47/*/*/;
+ var trailingSeparator = path.charCodeAt(path.length - 1) === 47/*/*/;
+
+ // Normalize the path
+ path = normalizeStringPosix(path, !isAbsolute);
+
+ if (path.length === 0 && !isAbsolute)
+ path = '.';
+ if (path.length > 0 && trailingSeparator)
+ path += '/';
+
+ if (isAbsolute)
+ return '/' + path;
+ return path;
+ },
+
+
+ isAbsolute: function isAbsolute(path) {
+ assertPath(path);
+ return path.length > 0 && path.charCodeAt(0) === 47/*/*/;
+ },
+
+
+ join: function join() {
+ if (arguments.length === 0)
+ return '.';
+ var joined;
+ for (var i = 0; i < arguments.length; ++i) {
+ var arg = arguments[i];
+ assertPath(arg);
+ if (arg.length > 0) {
+ if (joined === undefined)
+ joined = arg;
+ else
+ joined += '/' + arg;
+ }
+ }
+ if (joined === undefined)
+ return '.';
+ return posix.normalize(joined);
+ },
+
+
+ relative: function relative(from, to) {
+ assertPath(from);
+ assertPath(to);
+
+ if (from === to)
+ return '';
+
+ from = posix.resolve(from);
+ to = posix.resolve(to);
+
+ if (from === to)
+ return '';
+
+ // Trim any leading backslashes
+ var fromStart = 1;
+ for (; fromStart < from.length; ++fromStart) {
+ if (from.charCodeAt(fromStart) !== 47/*/*/)
+ break;
+ }
+ var fromEnd = from.length;
+ var fromLen = (fromEnd - fromStart);
+
+ // Trim any leading backslashes
+ var toStart = 1;
+ for (; toStart < to.length; ++toStart) {
+ if (to.charCodeAt(toStart) !== 47/*/*/)
+ break;
+ }
+ var toEnd = to.length;
+ var toLen = (toEnd - toStart);
+
+ // Compare paths to find the longest common path from root
+ var length = (fromLen < toLen ? fromLen : toLen);
+ var lastCommonSep = -1;
+ var i = 0;
+ for (; i <= length; ++i) {
+ if (i === length) {
+ if (toLen > length) {
+ if (to.charCodeAt(toStart + i) === 47/*/*/) {
+ // We get here if `from` is the exact base path for `to`.
+ // For example: from='/foo/bar'; to='/foo/bar/baz'
+ return to.slice(toStart + i + 1);
+ } else if (i === 0) {
+ // We get here if `from` is the root
+ // For example: from='/'; to='/foo'
+ return to.slice(toStart + i);
+ }
+ } else if (fromLen > length) {
+ if (from.charCodeAt(fromStart + i) === 47/*/*/) {
+ // We get here if `to` is the exact base path for `from`.
+ // For example: from='/foo/bar/baz'; to='/foo/bar'
+ lastCommonSep = i;
+ } else if (i === 0) {
+ // We get here if `to` is the root.
+ // For example: from='/foo'; to='/'
+ lastCommonSep = 0;
+ }
+ }
+ break;
+ }
+ var fromCode = from.charCodeAt(fromStart + i);
+ var toCode = to.charCodeAt(toStart + i);
+ if (fromCode !== toCode)
+ break;
+ else if (fromCode === 47/*/*/)
+ lastCommonSep = i;
+ }
+
+ var out = '';
+ // Generate the relative path based on the path difference between `to`
+ // and `from`
+ for (i = fromStart + lastCommonSep + 1; i <= fromEnd; ++i) {
+ if (i === fromEnd || from.charCodeAt(i) === 47/*/*/) {
+ if (out.length === 0)
+ out += '..';
+ else
+ out += '/..';
+ }
+ }
+
+ // Lastly, append the rest of the destination (`to`) path that comes after
+ // the common path parts
+ if (out.length > 0)
+ return out + to.slice(toStart + lastCommonSep);
+ else {
+ toStart += lastCommonSep;
+ if (to.charCodeAt(toStart) === 47/*/*/)
+ ++toStart;
+ return to.slice(toStart);
+ }
+ },
+
+
+ _makeLong: function _makeLong(path) {
+ return path;
+ },
+
+
+ dirname: function dirname(path) {
+ assertPath(path);
+ if (path.length === 0)
+ return '.';
+ var code = path.charCodeAt(0);
+ var hasRoot = (code === 47/*/*/);
+ var end = -1;
+ var matchedSlash = true;
+ for (var i = path.length - 1; i >= 1; --i) {
+ code = path.charCodeAt(i);
+ if (code === 47/*/*/) {
+ if (!matchedSlash) {
+ end = i;
+ break;
+ }
+ } else {
+ // We saw the first non-path separator
+ matchedSlash = false;
+ }
+ }
+
+ if (end === -1)
+ return hasRoot ? '/' : '.';
+ if (hasRoot && end === 1)
+ return '//';
+ return path.slice(0, end);
+ },
+
+
+ basename: function basename(path, ext) {
+ if (ext !== undefined && typeof ext !== 'string')
+ throw new TypeError('"ext" argument must be a string');
+ assertPath(path);
+
+ var start = 0;
+ var end = -1;
+ var matchedSlash = true;
+ var i;
+
+ if (ext !== undefined && ext.length > 0 && ext.length <= path.length) {
+ if (ext.length === path.length && ext === path)
+ return '';
+ var extIdx = ext.length - 1;
+ var firstNonSlashEnd = -1;
+ for (i = path.length - 1; i >= 0; --i) {
+ var code = path.charCodeAt(i);
+ if (code === 47/*/*/) {
+ // If we reached a path separator that was not part of a set of path
+ // separators at the end of the string, stop now
+ if (!matchedSlash) {
+ start = i + 1;
+ break;
+ }
+ } else {
+ if (firstNonSlashEnd === -1) {
+ // We saw the first non-path separator, remember this index in case
+ // we need it if the extension ends up not matching
+ matchedSlash = false;
+ firstNonSlashEnd = i + 1;
+ }
+ if (extIdx >= 0) {
+ // Try to match the explicit extension
+ if (code === ext.charCodeAt(extIdx)) {
+ if (--extIdx === -1) {
+ // We matched the extension, so mark this as the end of our path
+ // component
+ end = i;
+ }
+ } else {
+ // Extension does not match, so our result is the entire path
+ // component
+ extIdx = -1;
+ end = firstNonSlashEnd;
+ }
+ }
+ }
+ }
+
+ if (start === end)
+ end = firstNonSlashEnd;
+ else if (end === -1)
+ end = path.length;
+ return path.slice(start, end);
+ } else {
+ for (i = path.length - 1; i >= 0; --i) {
+ if (path.charCodeAt(i) === 47/*/*/) {
+ // If we reached a path separator that was not part of a set of path
+ // separators at the end of the string, stop now
+ if (!matchedSlash) {
+ start = i + 1;
+ break;
+ }
+ } else if (end === -1) {
+ // We saw the first non-path separator, mark this as the end of our
+ // path component
+ matchedSlash = false;
+ end = i + 1;
+ }
+ }
+
+ if (end === -1)
+ return '';
+ return path.slice(start, end);
+ }
+ },
+
+
+ extname: function extname(path) {
+ assertPath(path);
+ var startDot = -1;
+ var startPart = 0;
+ var end = -1;
+ var matchedSlash = true;
+ // Track the state of characters (if any) we see before our first dot and
+ // after any path separator we find
+ var preDotState = 0;
+ for (var i = path.length - 1; i >= 0; --i) {
+ var code = path.charCodeAt(i);
+ if (code === 47/*/*/) {
+ // If we reached a path separator that was not part of a set of path
+ // separators at the end of the string, stop now
+ if (!matchedSlash) {
+ startPart = i + 1;
+ break;
+ }
+ continue;
+ }
+ if (end === -1) {
+ // We saw the first non-path separator, mark this as the end of our
+ // extension
+ matchedSlash = false;
+ end = i + 1;
+ }
+ if (code === 46/*.*/) {
+ // If this is our first dot, mark it as the start of our extension
+ if (startDot === -1)
+ startDot = i;
+ else if (preDotState !== 1)
+ preDotState = 1;
+ } else if (startDot !== -1) {
+ // We saw a non-dot and non-path separator before our dot, so we should
+ // have a good chance at having a non-empty extension
+ preDotState = -1;
+ }
+ }
+
+ if (startDot === -1 ||
+ end === -1 ||
+ // We saw a non-dot character immediately before the dot
+ preDotState === 0 ||
+ // The (right-most) trimmed path component is exactly '..'
+ (preDotState === 1 &&
+ startDot === end - 1 &&
+ startDot === startPart + 1)) {
+ return '';
+ }
+ return path.slice(startDot, end);
+ },
+
+
+ format: function format(pathObject) {
+ if (pathObject === null || typeof pathObject !== 'object') {
+ throw new TypeError(
+ 'Parameter "pathObject" must be an object, not ' + typeof(pathObject)
+ );
+ }
+ return _format('/', pathObject);
+ },
+
+
+ parse: function parse(path) {
+ assertPath(path);
+
+ var ret = { root: '', dir: '', base: '', ext: '', name: '' };
+ if (path.length === 0)
+ return ret;
+ var code = path.charCodeAt(0);
+ var isAbsolute = (code === 47/*/*/);
+ var start;
+ if (isAbsolute) {
+ ret.root = '/';
+ start = 1;
+ } else {
+ start = 0;
+ }
+ var startDot = -1;
+ var startPart = 0;
+ var end = -1;
+ var matchedSlash = true;
+ var i = path.length - 1;
+
+ // Track the state of characters (if any) we see before our first dot and
+ // after any path separator we find
+ var preDotState = 0;
+
+ // Get non-dir info
+ for (; i >= start; --i) {
+ code = path.charCodeAt(i);
+ if (code === 47/*/*/) {
+ // If we reached a path separator that was not part of a set of path
+ // separators at the end of the string, stop now
+ if (!matchedSlash) {
+ startPart = i + 1;
+ break;
+ }
+ continue;
+ }
+ if (end === -1) {
+ // We saw the first non-path separator, mark this as the end of our
+ // extension
+ matchedSlash = false;
+ end = i + 1;
+ }
+ if (code === 46/*.*/) {
+ // If this is our first dot, mark it as the start of our extension
+ if (startDot === -1)
+ startDot = i;
+ else if (preDotState !== 1)
+ preDotState = 1;
+ } else if (startDot !== -1) {
+ // We saw a non-dot and non-path separator before our dot, so we should
+ // have a good chance at having a non-empty extension
+ preDotState = -1;
+ }
+ }
+
+ if (startDot === -1 ||
+ end === -1 ||
+ // We saw a non-dot character immediately before the dot
+ preDotState === 0 ||
+ // The (right-most) trimmed path component is exactly '..'
+ (preDotState === 1 &&
+ startDot === end - 1 &&
+ startDot === startPart + 1)) {
+ if (end !== -1) {
+ if (startPart === 0 && isAbsolute)
+ ret.base = ret.name = path.slice(1, end);
+ else
+ ret.base = ret.name = path.slice(startPart, end);
+ }
+ } else {
+ if (startPart === 0 && isAbsolute) {
+ ret.name = path.slice(1, startDot);
+ ret.base = path.slice(1, end);
+ } else {
+ ret.name = path.slice(startPart, startDot);
+ ret.base = path.slice(startPart, end);
+ }
+ ret.ext = path.slice(startDot, end);
+ }
+
+ if (startPart > 0)
+ ret.dir = path.slice(0, startPart - 1);
+ else if (isAbsolute)
+ ret.dir = '/';
+
+ return ret;
+ },
+
+
+ sep: '/',
+ delimiter: ':',
+ posix: null
+};
+
+
+module.exports = posix;
+
+
+/***/ }),
+/* 7 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.replaceBase = replaceBase;
+exports.replaceCanonical = replaceCanonical;
+exports.replaceMeta = replaceMeta;
+exports.replaceLinks = replaceLinks;
+exports.substitute = substitute;
+
+var _core = __webpack_require__(0);
+
+var _url = __webpack_require__(5);
+
+var _url2 = _interopRequireDefault(_url);
+
+var _path = __webpack_require__(4);
+
+var _path2 = _interopRequireDefault(_path);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function replaceBase(doc, section) {
+ var base;
+ var head;
+ var url = section.url;
+ var absolute = url.indexOf("://") > -1;
+
+ if (!doc) {
+ return;
+ }
+
+ head = (0, _core.qs)(doc, "head");
+ base = (0, _core.qs)(head, "base");
+
+ if (!base) {
+ base = doc.createElement("base");
+ head.insertBefore(base, head.firstChild);
+ }
+
+ // Fix for Safari crashing if the url doesn't have an origin
+ if (!absolute && window && window.location) {
+ url = window.location.origin + url;
+ }
+
+ base.setAttribute("href", url);
+}
+
+function replaceCanonical(doc, section) {
+ var head;
+ var link;
+ var url = section.canonical;
+
+ if (!doc) {
+ return;
+ }
+
+ head = (0, _core.qs)(doc, "head");
+ link = (0, _core.qs)(head, "link[rel='canonical']");
+
+ if (link) {
+ link.setAttribute("href", url);
+ } else {
+ link = doc.createElement("link");
+ link.setAttribute("rel", "canonical");
+ link.setAttribute("href", url);
+ head.appendChild(link);
+ }
+}
+
+function replaceMeta(doc, section) {
+ var head;
+ var meta;
+ var id = section.idref;
+ if (!doc) {
+ return;
+ }
+
+ head = (0, _core.qs)(doc, "head");
+ meta = (0, _core.qs)(head, "link[property='dc.identifier']");
+
+ if (meta) {
+ meta.setAttribute("content", id);
+ } else {
+ meta = doc.createElement("meta");
+ meta.setAttribute("name", "dc.identifier");
+ meta.setAttribute("content", id);
+ head.appendChild(meta);
+ }
+}
+
+// TODO: move me to Contents
+function replaceLinks(contents, fn) {
+
+ var links = contents.querySelectorAll("a[href]");
+
+ if (!links.length) {
+ return;
+ }
+
+ var base = (0, _core.qs)(contents.ownerDocument, "base");
+ var location = base ? base.getAttribute("href") : undefined;
+ var replaceLink = function (link) {
+ var href = link.getAttribute("href");
+
+ if (href.indexOf("mailto:") === 0) {
+ return;
+ }
+
+ var absolute = href.indexOf("://") > -1;
+ var linkUrl = new _url2.default(href, location);
+
+ if (absolute) {
+
+ link.setAttribute("target", "_blank");
+ } else {
+ link.onclick = function () {
+
+ if (linkUrl && linkUrl.hash) {
+ fn(linkUrl.Path.path + linkUrl.hash);
+ } else if (linkUrl) {
+ fn(linkUrl.Path.path);
+ } else {
+ fn(href);
+ }
+
+ return false;
+ };
+ }
+ }.bind(this);
+
+ for (var i = 0; i < links.length; i++) {
+ replaceLink(links[i]);
+ }
+}
+
+function substitute(content, urls, replacements) {
+ urls.forEach(function (url, i) {
+ if (url && replacements[i]) {
+ content = content.replace(new RegExp(url, "g"), replacements[i]);
+ }
+ });
+ return content;
+}
+
+/***/ }),
+/* 8 */
+/***/ (function(module, exports) {
+
+var g;
+
+// This works in non-strict mode
+g = (function() {
+ return this;
+})();
+
+try {
+ // This works if eval is allowed (see CSP)
+ g = g || Function("return this")() || (1,eval)("this");
+} catch(e) {
+ // This works if the window reference is available
+ if(typeof window === "object")
+ g = window;
+}
+
+// g can still be undefined, but nothing to do about it...
+// We return undefined, instead of nothing here, so it's
+// easier to handle this case. if(!global) { ...}
+
+module.exports = g;
+
+
+/***/ }),
+/* 9 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+var _undefined = __webpack_require__(34)(); // Support ES3 engines
+
+module.exports = function (val) {
+ return (val !== _undefined) && (val !== null);
+};
+
+
+/***/ }),
+/* 10 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+
+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; }; }();
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+/**
+ * Hooks allow for injecting functions that must all complete in order before finishing
+ * They will execute in parallel but all must finish before continuing
+ * Functions may return a promise if they are asycn.
+ * @param {any} context scope of this
+ * @example this.content = new EPUBJS.Hook(this);
+ */
+var Hook = function () {
+ function Hook(context) {
+ _classCallCheck(this, Hook);
+
+ this.context = context || this;
+ this.hooks = [];
+ }
+
+ /**
+ * Adds a function to be run before a hook completes
+ * @example this.content.register(function(){...});
+ */
+
+
+ _createClass(Hook, [{
+ key: "register",
+ value: function register() {
+ for (var i = 0; i < arguments.length; ++i) {
+ if (typeof arguments[i] === "function") {
+ this.hooks.push(arguments[i]);
+ } else {
+ // unpack array
+ for (var j = 0; j < arguments[i].length; ++j) {
+ this.hooks.push(arguments[i][j]);
+ }
+ }
+ }
+ }
+
+ /**
+ * Triggers a hook to run all functions
+ * @example this.content.trigger(args).then(function(){...});
+ */
+
+ }, {
+ key: "trigger",
+ value: function trigger() {
+ var args = arguments;
+ var context = this.context;
+ var promises = [];
+
+ this.hooks.forEach(function (task) {
+ var executing = task.apply(context, args);
+
+ if (executing && typeof executing["then"] === "function") {
+ // Task is a function that returns a promise
+ promises.push(executing);
+ }
+ // Otherwise Task resolves immediately, continue
+ });
+
+ return Promise.all(promises);
+ }
+
+ // Adds a function to be run before a hook completes
+
+ }, {
+ key: "list",
+ value: function list() {
+ return this.hooks;
+ }
+ }, {
+ key: "clear",
+ value: function clear() {
+ return this.hooks = [];
+ }
+ }]);
+
+ return Hook;
+}();
+
+exports.default = Hook;
+module.exports = exports["default"];
+
+/***/ }),
+/* 11 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+
+var _core = __webpack_require__(0);
+
+var _path = __webpack_require__(4);
+
+var _path2 = _interopRequireDefault(_path);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function request(url, type, withCredentials, headers) {
+ var supportsURL = typeof window != "undefined" ? window.URL : false; // TODO: fallback for url if window isn't defined
+ var BLOB_RESPONSE = supportsURL ? "blob" : "arraybuffer";
+
+ var deferred = new _core.defer();
+
+ var xhr = new XMLHttpRequest();
+
+ //-- Check from PDF.js:
+ // https://github.com/mozilla/pdf.js/blob/master/web/compatibility.js
+ var xhrPrototype = XMLHttpRequest.prototype;
+
+ var header;
+
+ if (!("overrideMimeType" in xhrPrototype)) {
+ // IE10 might have response, but not overrideMimeType
+ Object.defineProperty(xhrPrototype, "overrideMimeType", {
+ value: function xmlHttpRequestOverrideMimeType() {}
+ });
+ }
+
+ if (withCredentials) {
+ xhr.withCredentials = true;
+ }
+
+ xhr.onreadystatechange = handler;
+ xhr.onerror = err;
+
+ xhr.open("GET", url, true);
+
+ for (header in headers) {
+ xhr.setRequestHeader(header, headers[header]);
+ }
+
+ if (type == "json") {
+ xhr.setRequestHeader("Accept", "application/json");
+ }
+
+ // If type isn"t set, determine it from the file extension
+ if (!type) {
+ type = new _path2.default(url).extension;
+ }
+
+ if (type == "blob") {
+ xhr.responseType = BLOB_RESPONSE;
+ }
+
+ if ((0, _core.isXml)(type)) {
+ // xhr.responseType = "document";
+ xhr.overrideMimeType("text/xml"); // for OPF parsing
+ }
+
+ if (type == "xhtml") {
+ // xhr.responseType = "document";
+ }
+
+ if (type == "html" || type == "htm") {
+ // xhr.responseType = "document";
+ }
+
+ if (type == "binary") {
+ xhr.responseType = "arraybuffer";
+ }
+
+ xhr.send();
+
+ function err(e) {
+ deferred.reject(e);
+ }
+
+ function handler() {
+ if (this.readyState === XMLHttpRequest.DONE) {
+ var responseXML = false;
+
+ if (this.responseType === "" || this.responseType === "document") {
+ responseXML = this.responseXML;
+ }
+
+ if (this.status === 200 || responseXML) {
+ //-- Firefox is reporting 0 for blob urls
+ var r;
+
+ if (!this.response && !responseXML) {
+ deferred.reject({
+ status: this.status,
+ message: "Empty Response",
+ stack: new Error().stack
+ });
+ return deferred.promise;
+ }
+
+ if (this.status === 403) {
+ deferred.reject({
+ status: this.status,
+ response: this.response,
+ message: "Forbidden",
+ stack: new Error().stack
+ });
+ return deferred.promise;
+ }
+ if (responseXML) {
+ r = this.responseXML;
+ } else if ((0, _core.isXml)(type)) {
+ // xhr.overrideMimeType("text/xml"); // for OPF parsing
+ // If this.responseXML wasn't set, try to parse using a DOMParser from text
+ r = (0, _core.parse)(this.response, "text/xml");
+ } else if (type == "xhtml") {
+ r = (0, _core.parse)(this.response, "application/xhtml+xml");
+ } else if (type == "html" || type == "htm") {
+ r = (0, _core.parse)(this.response, "text/html");
+ } else if (type == "json") {
+ r = JSON.parse(this.response);
+ } else if (type == "blob") {
+
+ if (supportsURL) {
+ r = this.response;
+ } else {
+ //-- Safari doesn't support responseType blob, so create a blob from arraybuffer
+ r = new Blob([this.response]);
+ }
+ } else {
+ r = this.response;
+ }
+
+ deferred.resolve(r);
+ } else {
+
+ deferred.reject({
+ status: this.status,
+ message: this.response,
+ stack: new Error().stack
+ });
+ }
+ }
+ }
+
+ return deferred.promise;
+}
+
+exports.default = request;
+module.exports = exports["default"];
+
+/***/ }),
+/* 12 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.Task = undefined;
+
+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; }; }();
+
+var _core = __webpack_require__(0);
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+/**
+ * Queue for handling tasks one at a time
+ * @class
+ * @param {scope} context what this will resolve to in the tasks
+ */
+var Queue = function () {
+ function Queue(context) {
+ _classCallCheck(this, Queue);
+
+ this._q = [];
+ this.context = context;
+ this.tick = _core.requestAnimationFrame;
+ this.running = false;
+ this.paused = false;
+ }
+
+ /**
+ * Add an item to the queue
+ * @return {Promise}
+ */
+
+
+ _createClass(Queue, [{
+ key: "enqueue",
+ value: function enqueue() {
+ var deferred, promise;
+ var queued;
+ var task = [].shift.call(arguments);
+ var args = arguments;
+
+ // Handle single args without context
+ // if(args && !Array.isArray(args)) {
+ // args = [args];
+ // }
+ if (!task) {
+ throw new Error("No Task Provided");
+ }
+
+ if (typeof task === "function") {
+
+ deferred = new _core.defer();
+ promise = deferred.promise;
+
+ queued = {
+ "task": task,
+ "args": args,
+ //"context" : context,
+ "deferred": deferred,
+ "promise": promise
+ };
+ } else {
+ // Task is a promise
+ queued = {
+ "promise": task
+ };
+ }
+
+ this._q.push(queued);
+
+ // Wait to start queue flush
+ if (this.paused == false && !this.running) {
+ // setTimeout(this.flush.bind(this), 0);
+ // this.tick.call(window, this.run.bind(this));
+ this.run();
+ }
+
+ return queued.promise;
+ }
+
+ /**
+ * Run one item
+ * @return {Promise}
+ */
+
+ }, {
+ key: "dequeue",
+ value: function dequeue() {
+ var inwait, task, result;
+
+ if (this._q.length && !this.paused) {
+ inwait = this._q.shift();
+ task = inwait.task;
+ if (task) {
+ // console.log(task)
+
+ result = task.apply(this.context, inwait.args);
+
+ if (result && typeof result["then"] === "function") {
+ // Task is a function that returns a promise
+ return result.then(function () {
+ inwait.deferred.resolve.apply(this.context, arguments);
+ }.bind(this), function () {
+ inwait.deferred.reject.apply(this.context, arguments);
+ }.bind(this));
+ } else {
+ // Task resolves immediately
+ inwait.deferred.resolve.apply(this.context, result);
+ return inwait.promise;
+ }
+ } else if (inwait.promise) {
+ // Task is a promise
+ return inwait.promise;
+ }
+ } else {
+ inwait = new _core.defer();
+ inwait.deferred.resolve();
+ return inwait.promise;
+ }
+ }
+
+ // Run All Immediately
+
+ }, {
+ key: "dump",
+ value: function dump() {
+ while (this._q.length) {
+ this.dequeue();
+ }
+ }
+
+ /**
+ * Run all tasks sequentially, at convince
+ * @return {Promise}
+ */
+
+ }, {
+ key: "run",
+ value: function run() {
+ var _this = this;
+
+ if (!this.running) {
+ this.running = true;
+ this.defered = new _core.defer();
+ }
+
+ this.tick.call(window, function () {
+
+ if (_this._q.length) {
+
+ _this.dequeue().then(function () {
+ this.run();
+ }.bind(_this));
+ } else {
+ _this.defered.resolve();
+ _this.running = undefined;
+ }
+ });
+
+ // Unpause
+ if (this.paused == true) {
+ this.paused = false;
+ }
+
+ return this.defered.promise;
+ }
+
+ /**
+ * Flush all, as quickly as possible
+ * @return {Promise}
+ */
+
+ }, {
+ key: "flush",
+ value: function flush() {
+
+ if (this.running) {
+ return this.running;
+ }
+
+ if (this._q.length) {
+ this.running = this.dequeue().then(function () {
+ this.running = undefined;
+ return this.flush();
+ }.bind(this));
+
+ return this.running;
+ }
+ }
+
+ /**
+ * Clear all items in wait
+ */
+
+ }, {
+ key: "clear",
+ value: function clear() {
+ this._q = [];
+ }
+
+ /**
+ * Get the number of tasks in the queue
+ * @return {int} tasks
+ */
+
+ }, {
+ key: "length",
+ value: function length() {
+ return this._q.length;
+ }
+
+ /**
+ * Pause a running queue
+ */
+
+ }, {
+ key: "pause",
+ value: function pause() {
+ this.paused = true;
+ }
+
+ /**
+ * End the queue
+ */
+
+ }, {
+ key: "stop",
+ value: function stop() {
+ this._q = [];
+ this.running = false;
+ this.paused = true;
+ }
+ }]);
+
+ return Queue;
+}();
+
+/**
+ * Create a new task from a callback
+ * @class
+ * @private
+ * @param {function} task
+ * @param {array} args
+ * @param {scope} context
+ * @return {function} task
+ */
+
+
+var Task = function Task(task, args, context) {
+ _classCallCheck(this, Task);
+
+ return function () {
+ var _this2 = this;
+
+ var toApply = arguments || [];
+
+ return new Promise(function (resolve, reject) {
+ var callback = function callback(value, err) {
+ if (!value && err) {
+ reject(err);
+ } else {
+ resolve(value);
+ }
+ };
+ // Add the callback to the arguments list
+ toApply.push(callback);
+
+ // Apply all arguments to the functions
+ task.apply(context || _this2, toApply);
+ });
+ };
+};
+
+exports.default = Queue;
+exports.Task = Task;
+
+/***/ }),
+/* 13 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+
+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; }; }();
+
+var _eventEmitter = __webpack_require__(2);
+
+var _eventEmitter2 = _interopRequireDefault(_eventEmitter);
+
+var _core = __webpack_require__(0);
+
+var _epubcfi = __webpack_require__(1);
+
+var _epubcfi2 = _interopRequireDefault(_epubcfi);
+
+var _mapping = __webpack_require__(19);
+
+var _mapping2 = _interopRequireDefault(_mapping);
+
+var _replacements = __webpack_require__(7);
+
+var _constants = __webpack_require__(3);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+var isChrome = /Chrome/.test(navigator.userAgent);
+var isWebkit = !isChrome && /AppleWebKit/.test(navigator.userAgent);
+
+var ELEMENT_NODE = 1;
+var TEXT_NODE = 3;
+
+/**
+ * Handles DOM manipulation, queries and events for View contents
+ * @class
+ * @param {document} doc Document
+ * @param {element} content Parent Element (typically Body)
+ * @param {string} cfiBase Section component of CFIs
+ * @param {number} sectionIndex Index in Spine of Conntent's Section
+ */
+
+var Contents = function () {
+ function Contents(doc, content, cfiBase, sectionIndex) {
+ _classCallCheck(this, Contents);
+
+ // Blank Cfi for Parsing
+ this.epubcfi = new _epubcfi2.default();
+
+ this.document = doc;
+ this.documentElement = this.document.documentElement;
+ this.content = content || this.document.body;
+ this.window = this.document.defaultView;
+
+ this._size = {
+ width: 0,
+ height: 0
+ };
+
+ this.sectionIndex = sectionIndex || 0;
+ this.cfiBase = cfiBase || "";
+
+ this.epubReadingSystem("epub.js", ePub.VERSION);
+
+ this.listeners();
+ }
+
+ /**
+ * Get DOM events that are listened for and passed along
+ */
+
+
+ _createClass(Contents, [{
+ key: "width",
+
+
+ /**
+ * Get or Set width
+ * @param {number} [w]
+ * @returns {number} width
+ */
+ value: function width(w) {
+ // var frame = this.documentElement;
+ var frame = this.content;
+
+ if (w && (0, _core.isNumber)(w)) {
+ w = w + "px";
+ }
+
+ if (w) {
+ frame.style.width = w;
+ // this.content.style.width = w;
+ }
+
+ return this.window.getComputedStyle(frame)["width"];
+ }
+
+ /**
+ * Get or Set height
+ * @param {number} [h]
+ * @returns {number} height
+ */
+
+ }, {
+ key: "height",
+ value: function height(h) {
+ // var frame = this.documentElement;
+ var frame = this.content;
+
+ if (h && (0, _core.isNumber)(h)) {
+ h = h + "px";
+ }
+
+ if (h) {
+ frame.style.height = h;
+ // this.content.style.height = h;
+ }
+
+ return this.window.getComputedStyle(frame)["height"];
+ }
+
+ /**
+ * Get or Set width of the contents
+ * @param {number} [w]
+ * @returns {number} width
+ */
+
+ }, {
+ key: "contentWidth",
+ value: function contentWidth(w) {
+
+ var content = this.content || this.document.body;
+
+ if (w && (0, _core.isNumber)(w)) {
+ w = w + "px";
+ }
+
+ if (w) {
+ content.style.width = w;
+ }
+
+ return this.window.getComputedStyle(content)["width"];
+ }
+
+ /**
+ * Get or Set height of the contents
+ * @param {number} [h]
+ * @returns {number} height
+ */
+
+ }, {
+ key: "contentHeight",
+ value: function contentHeight(h) {
+
+ var content = this.content || this.document.body;
+
+ if (h && (0, _core.isNumber)(h)) {
+ h = h + "px";
+ }
+
+ if (h) {
+ content.style.height = h;
+ }
+
+ return this.window.getComputedStyle(content)["height"];
+ }
+
+ /**
+ * Get the width of the text using Range
+ * @returns {number} width
+ */
+
+ }, {
+ key: "textWidth",
+ value: function textWidth() {
+ var width = void 0;
+ var range = this.document.createRange();
+ var content = this.content || this.document.body;
+ var border = (0, _core.borders)(content);
+
+ // Select the contents of frame
+ range.selectNodeContents(content);
+
+ // get the width of the text content
+ width = range.getBoundingClientRect().width;
+
+ if (border && border.width) {
+ width += border.width;
+ }
+
+ return Math.round(width);
+ }
+
+ /**
+ * Get the height of the text using Range
+ * @returns {number} height
+ */
+
+ }, {
+ key: "textHeight",
+ value: function textHeight() {
+ var height = void 0;
+ var range = this.document.createRange();
+ var content = this.content || this.document.body;
+ var border = (0, _core.borders)(content);
+
+ range.selectNodeContents(content);
+
+ height = range.getBoundingClientRect().height;
+
+ if (height && border.height) {
+ height += border.height;
+ }
+
+ return Math.round(height);
+ }
+
+ /**
+ * Get documentElement scrollWidth
+ * @returns {number} width
+ */
+
+ }, {
+ key: "scrollWidth",
+ value: function scrollWidth() {
+ var width = this.documentElement.scrollWidth;
+
+ return width;
+ }
+
+ /**
+ * Get documentElement scrollHeight
+ * @returns {number} height
+ */
+
+ }, {
+ key: "scrollHeight",
+ value: function scrollHeight() {
+ var height = this.documentElement.scrollHeight;
+
+ return height;
+ }
+
+ /**
+ * Set overflow css style of the contents
+ * @param {string} [overflow]
+ */
+
+ }, {
+ key: "overflow",
+ value: function overflow(_overflow) {
+
+ if (_overflow) {
+ this.documentElement.style.overflow = _overflow;
+ }
+
+ return this.window.getComputedStyle(this.documentElement)["overflow"];
+ }
+
+ /**
+ * Set overflowX css style of the documentElement
+ * @param {string} [overflow]
+ */
+
+ }, {
+ key: "overflowX",
+ value: function overflowX(overflow) {
+
+ if (overflow) {
+ this.documentElement.style.overflowX = overflow;
+ }
+
+ return this.window.getComputedStyle(this.documentElement)["overflowX"];
+ }
+
+ /**
+ * Set overflowY css style of the documentElement
+ * @param {string} [overflow]
+ */
+
+ }, {
+ key: "overflowY",
+ value: function overflowY(overflow) {
+
+ if (overflow) {
+ this.documentElement.style.overflowY = overflow;
+ }
+
+ return this.window.getComputedStyle(this.documentElement)["overflowY"];
+ }
+
+ /**
+ * Set Css styles on the contents element (typically Body)
+ * @param {string} property
+ * @param {string} value
+ * @param {boolean} [priority] set as "important"
+ */
+
+ }, {
+ key: "css",
+ value: function css(property, value, priority) {
+ var content = this.content || this.document.body;
+
+ if (value) {
+ content.style.setProperty(property, value, priority ? "important" : "");
+ }
+
+ return this.window.getComputedStyle(content)[property];
+ }
+
+ /**
+ * Get or Set the viewport element
+ * @param {object} [options]
+ * @param {string} [options.width]
+ * @param {string} [options.height]
+ * @param {string} [options.scale]
+ * @param {string} [options.minimum]
+ * @param {string} [options.maximum]
+ * @param {string} [options.scalable]
+ */
+
+ }, {
+ key: "viewport",
+ value: function viewport(options) {
+ var _width, _height, _scale, _minimum, _maximum, _scalable;
+ // var width, height, scale, minimum, maximum, scalable;
+ var $viewport = this.document.querySelector("meta[name='viewport']");
+ var parsed = {
+ "width": undefined,
+ "height": undefined,
+ "scale": undefined,
+ "minimum": undefined,
+ "maximum": undefined,
+ "scalable": undefined
+ };
+ var newContent = [];
+ var settings = {};
+
+ /*
+ * check for the viewport size
+ *
+ */
+ if ($viewport && $viewport.hasAttribute("content")) {
+ var content = $viewport.getAttribute("content");
+ var _width2 = content.match(/width\s*=\s*([^,]*)/);
+ var _height2 = content.match(/height\s*=\s*([^,]*)/);
+ var _scale2 = content.match(/initial-scale\s*=\s*([^,]*)/);
+ var _minimum2 = content.match(/minimum-scale\s*=\s*([^,]*)/);
+ var _maximum2 = content.match(/maximum-scale\s*=\s*([^,]*)/);
+ var _scalable2 = content.match(/user-scalable\s*=\s*([^,]*)/);
+
+ if (_width2 && _width2.length && typeof _width2[1] !== "undefined") {
+ parsed.width = _width2[1];
+ }
+ if (_height2 && _height2.length && typeof _height2[1] !== "undefined") {
+ parsed.height = _height2[1];
+ }
+ if (_scale2 && _scale2.length && typeof _scale2[1] !== "undefined") {
+ parsed.scale = _scale2[1];
+ }
+ if (_minimum2 && _minimum2.length && typeof _minimum2[1] !== "undefined") {
+ parsed.minimum = _minimum2[1];
+ }
+ if (_maximum2 && _maximum2.length && typeof _maximum2[1] !== "undefined") {
+ parsed.maximum = _maximum2[1];
+ }
+ if (_scalable2 && _scalable2.length && typeof _scalable2[1] !== "undefined") {
+ parsed.scalable = _scalable2[1];
+ }
+ }
+
+ settings = (0, _core.defaults)(options || {}, parsed);
+
+ if (options) {
+ if (settings.width) {
+ newContent.push("width=" + settings.width);
+ }
+
+ if (settings.height) {
+ newContent.push("height=" + settings.height);
+ }
+
+ if (settings.scale) {
+ newContent.push("initial-scale=" + settings.scale);
+ }
+
+ if (settings.scalable === "no") {
+ newContent.push("minimum-scale=" + settings.scale);
+ newContent.push("maximum-scale=" + settings.scale);
+ newContent.push("user-scalable=" + settings.scalable);
+ } else {
+
+ if (settings.scalable) {
+ newContent.push("user-scalable=" + settings.scalable);
+ }
+
+ if (settings.minimum) {
+ newContent.push("minimum-scale=" + settings.minimum);
+ }
+
+ if (settings.maximum) {
+ newContent.push("minimum-scale=" + settings.maximum);
+ }
+ }
+
+ if (!$viewport) {
+ $viewport = this.document.createElement("meta");
+ $viewport.setAttribute("name", "viewport");
+ this.document.querySelector("head").appendChild($viewport);
+ }
+
+ $viewport.setAttribute("content", newContent.join(", "));
+
+ this.window.scrollTo(0, 0);
+ }
+
+ return settings;
+ }
+
+ /**
+ * Event emitter for when the contents has expanded
+ * @private
+ */
+
+ }, {
+ key: "expand",
+ value: function expand() {
+ this.emit(_constants.EVENTS.CONTENTS.EXPAND);
+ }
+
+ /**
+ * Add DOM listeners
+ * @private
+ */
+
+ }, {
+ key: "listeners",
+ value: function listeners() {
+
+ this.imageLoadListeners();
+
+ this.mediaQueryListeners();
+
+ // this.fontLoadListeners();
+
+ this.addEventListeners();
+
+ this.addSelectionListeners();
+
+ // this.transitionListeners();
+
+ this.resizeListeners();
+
+ // this.resizeObservers();
+
+ this.linksHandler();
+ }
+
+ /**
+ * Remove DOM listeners
+ * @private
+ */
+
+ }, {
+ key: "removeListeners",
+ value: function removeListeners() {
+
+ this.removeEventListeners();
+
+ this.removeSelectionListeners();
+
+ clearTimeout(this.expanding);
+ }
+
+ /**
+ * Check if size of contents has changed and
+ * emit 'resize' event if it has.
+ * @private
+ */
+
+ }, {
+ key: "resizeCheck",
+ value: function resizeCheck() {
+ var width = this.textWidth();
+ var height = this.textHeight();
+
+ if (width != this._size.width || height != this._size.height) {
+
+ this._size = {
+ width: width,
+ height: height
+ };
+
+ this.onResize && this.onResize(this._size);
+ this.emit(_constants.EVENTS.CONTENTS.RESIZE, this._size);
+ }
+ }
+
+ /**
+ * Poll for resize detection
+ * @private
+ */
+
+ }, {
+ key: "resizeListeners",
+ value: function resizeListeners() {
+ var width, height;
+ // Test size again
+ clearTimeout(this.expanding);
+
+ requestAnimationFrame(this.resizeCheck.bind(this));
+
+ this.expanding = setTimeout(this.resizeListeners.bind(this), 350);
+ }
+
+ /**
+ * Use css transitions to detect resize
+ * @private
+ */
+
+ }, {
+ key: "transitionListeners",
+ value: function transitionListeners() {
+ var body = this.content;
+
+ body.style['transitionProperty'] = "font, font-size, font-size-adjust, font-stretch, font-variation-settings, font-weight, width, height";
+ body.style['transitionDuration'] = "0.001ms";
+ body.style['transitionTimingFunction'] = "linear";
+ body.style['transitionDelay'] = "0";
+
+ this.document.addEventListener('transitionend', this.resizeCheck.bind(this));
+ }
+
+ /**
+ * Listen for media query changes and emit 'expand' event
+ * Adapted from: https://github.com/tylergaw/media-query-events/blob/master/js/mq-events.js
+ * @private
+ */
+
+ }, {
+ key: "mediaQueryListeners",
+ value: function mediaQueryListeners() {
+ var sheets = this.document.styleSheets;
+ var mediaChangeHandler = function (m) {
+ if (m.matches && !this._expanding) {
+ setTimeout(this.expand.bind(this), 1);
+ }
+ }.bind(this);
+
+ for (var i = 0; i < sheets.length; i += 1) {
+ var rules;
+ // Firefox errors if we access cssRules cross-domain
+ try {
+ rules = sheets[i].cssRules;
+ } catch (e) {
+ return;
+ }
+ if (!rules) return; // Stylesheets changed
+ for (var j = 0; j < rules.length; j += 1) {
+ //if (rules[j].constructor === CSSMediaRule) {
+ if (rules[j].media) {
+ var mql = this.window.matchMedia(rules[j].media.mediaText);
+ mql.addListener(mediaChangeHandler);
+ //mql.onchange = mediaChangeHandler;
+ }
+ }
+ }
+ }
+
+ /**
+ * Use MutationObserver to listen for changes in the DOM and check for resize
+ * @private
+ */
+
+ }, {
+ key: "resizeObservers",
+ value: function resizeObservers() {
+ var _this = this;
+
+ // create an observer instance
+ this.observer = new MutationObserver(function (mutations) {
+ _this.resizeCheck();
+ });
+
+ // configuration of the observer:
+ var config = { attributes: true, childList: true, characterData: true, subtree: true };
+
+ // pass in the target node, as well as the observer options
+ this.observer.observe(this.document, config);
+ }
+ }, {
+ key: "imageLoadListeners",
+ value: function imageLoadListeners(target) {
+ var images = this.document.querySelectorAll("img");
+ var img;
+ for (var i = 0; i < images.length; i++) {
+ img = images[i];
+
+ if (typeof img.naturalWidth !== "undefined" && img.naturalWidth === 0) {
+ img.onload = this.expand.bind(this);
+ }
+ }
+ }
+
+ /**
+ * Listen for font load and check for resize when loaded
+ * @private
+ */
+
+ }, {
+ key: "fontLoadListeners",
+ value: function fontLoadListeners(target) {
+ if (!this.document || !this.document.fonts) {
+ return;
+ }
+
+ this.document.fonts.ready.then(function () {
+ this.resizeCheck();
+ }.bind(this));
+ }
+
+ /**
+ * Get the documentElement
+ * @returns {element} documentElement
+ */
+
+ }, {
+ key: "root",
+ value: function root() {
+ if (!this.document) return null;
+ return this.document.documentElement;
+ }
+
+ /**
+ * Get the location offset of a EpubCFI or an #id
+ * @param {string | EpubCFI} target
+ * @param {string} [ignoreClass] for the cfi
+ * @returns { {left: Number, top: Number }
+ */
+
+ }, {
+ key: "locationOf",
+ value: function locationOf(target, ignoreClass) {
+ var position;
+ var targetPos = { "left": 0, "top": 0 };
+
+ if (!this.document) return targetPos;
+
+ if (this.epubcfi.isCfiString(target)) {
+ var range = new _epubcfi2.default(target).toRange(this.document, ignoreClass);
+
+ if (range) {
+ if (range.startContainer.nodeType === Node.ELEMENT_NODE) {
+ position = range.startContainer.getBoundingClientRect();
+ targetPos.left = position.left;
+ targetPos.top = position.top;
+ } else {
+ // Webkit does not handle collapsed range bounds correctly
+ // https://bugs.webkit.org/show_bug.cgi?id=138949
+
+ // Construct a new non-collapsed range
+ if (isWebkit) {
+ var container = range.startContainer;
+ var newRange = new Range();
+ try {
+ if (container.nodeType === ELEMENT_NODE) {
+ position = container.getBoundingClientRect();
+ } else if (range.startOffset + 2 < container.length) {
+ newRange.setStart(container, range.startOffset);
+ newRange.setEnd(container, range.startOffset + 2);
+ position = newRange.getBoundingClientRect();
+ } else if (range.startOffset - 2 > 0) {
+ newRange.setStart(container, range.startOffset - 2);
+ newRange.setEnd(container, range.startOffset);
+ position = newRange.getBoundingClientRect();
+ } else {
+ // empty, return the parent element
+ position = container.parentNode.getBoundingClientRect();
+ }
+ } catch (e) {
+ console.error(e, e.stack);
+ }
+ } else {
+ position = range.getBoundingClientRect();
+ }
+ }
+ }
+ } else if (typeof target === "string" && target.indexOf("#") > -1) {
+
+ var id = target.substring(target.indexOf("#") + 1);
+ var el = this.document.getElementById(id);
+
+ if (el) {
+ position = el.getBoundingClientRect();
+ }
+ }
+
+ if (position) {
+ targetPos.left = position.left;
+ targetPos.top = position.top;
+ }
+
+ return targetPos;
+ }
+
+ /**
+ * Append a stylesheet link to the document head
+ * @param {string} src url
+ */
+
+ }, {
+ key: "addStylesheet",
+ value: function addStylesheet(src) {
+ return new Promise(function (resolve, reject) {
+ var $stylesheet;
+ var ready = false;
+
+ if (!this.document) {
+ resolve(false);
+ return;
+ }
+
+ // Check if link already exists
+ $stylesheet = this.document.querySelector("link[href='" + src + "']");
+ if ($stylesheet) {
+ resolve(true);
+ return; // already present
+ }
+
+ $stylesheet = this.document.createElement("link");
+ $stylesheet.type = "text/css";
+ $stylesheet.rel = "stylesheet";
+ $stylesheet.href = src;
+ $stylesheet.onload = $stylesheet.onreadystatechange = function () {
+ if (!ready && (!this.readyState || this.readyState == "complete")) {
+ ready = true;
+ // Let apply
+ setTimeout(function () {
+ resolve(true);
+ }, 1);
+ }
+ };
+
+ this.document.head.appendChild($stylesheet);
+ }.bind(this));
+ }
+
+ /**
+ * Append stylesheet rules to a generate stylesheet
+ * Array: https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleSheet/insertRule
+ * Object: https://github.com/desirable-objects/json-to-css
+ * @param {array | object} rules
+ */
+
+ }, {
+ key: "addStylesheetRules",
+ value: function addStylesheetRules(rules) {
+ var styleEl;
+ var styleSheet;
+ var key = "epubjs-inserted-css";
+
+ if (!this.document || !rules || rules.length === 0) return;
+
+ // Check if link already exists
+ styleEl = this.document.getElementById("#" + key);
+ if (!styleEl) {
+ styleEl = this.document.createElement("style");
+ styleEl.id = key;
+ }
+
+ // Append style element to head
+ this.document.head.appendChild(styleEl);
+
+ // Grab style sheet
+ styleSheet = styleEl.sheet;
+
+ if (Object.prototype.toString.call(rules) === "[object Array]") {
+ for (var i = 0, rl = rules.length; i < rl; i++) {
+ var j = 1,
+ rule = rules[i],
+ selector = rules[i][0],
+ propStr = "";
+ // If the second argument of a rule is an array of arrays, correct our variables.
+ if (Object.prototype.toString.call(rule[1][0]) === "[object Array]") {
+ rule = rule[1];
+ j = 0;
+ }
+
+ for (var pl = rule.length; j < pl; j++) {
+ var prop = rule[j];
+ propStr += prop[0] + ":" + prop[1] + (prop[2] ? " !important" : "") + ";\n";
+ }
+
+ // Insert CSS Rule
+ styleSheet.insertRule(selector + "{" + propStr + "}", styleSheet.cssRules.length);
+ }
+ } else {
+ var selectors = Object.keys(rules);
+ selectors.forEach(function (selector) {
+ var definition = rules[selector];
+ if (Array.isArray(definition)) {
+ definition.forEach(function (item) {
+ var _rules = Object.keys(item);
+ var result = _rules.map(function (rule) {
+ return rule + ":" + item[rule];
+ }).join(';');
+ styleSheet.insertRule(selector + "{" + result + "}", styleSheet.cssRules.length);
+ });
+ } else {
+ var _rules = Object.keys(definition);
+ var result = _rules.map(function (rule) {
+ return rule + ":" + definition[rule];
+ }).join(';');
+ styleSheet.insertRule(selector + "{" + result + "}", styleSheet.cssRules.length);
+ }
+ });
+ }
+ }
+
+ /**
+ * Append a script tag to the document head
+ * @param {string} src url
+ * @returns {Promise} loaded
+ */
+
+ }, {
+ key: "addScript",
+ value: function addScript(src) {
+
+ return new Promise(function (resolve, reject) {
+ var $script;
+ var ready = false;
+
+ if (!this.document) {
+ resolve(false);
+ return;
+ }
+
+ $script = this.document.createElement("script");
+ $script.type = "text/javascript";
+ $script.async = true;
+ $script.src = src;
+ $script.onload = $script.onreadystatechange = function () {
+ if (!ready && (!this.readyState || this.readyState == "complete")) {
+ ready = true;
+ setTimeout(function () {
+ resolve(true);
+ }, 1);
+ }
+ };
+
+ this.document.head.appendChild($script);
+ }.bind(this));
+ }
+
+ /**
+ * Add a class to the contents container
+ * @param {string} className
+ */
+
+ }, {
+ key: "addClass",
+ value: function addClass(className) {
+ var content;
+
+ if (!this.document) return;
+
+ content = this.content || this.document.body;
+
+ if (content) {
+ content.classList.add(className);
+ }
+ }
+
+ /**
+ * Remove a class from the contents container
+ * @param {string} removeClass
+ */
+
+ }, {
+ key: "removeClass",
+ value: function removeClass(className) {
+ var content;
+
+ if (!this.document) return;
+
+ content = this.content || this.document.body;
+
+ if (content) {
+ content.classList.remove(className);
+ }
+ }
+
+ /**
+ * Add DOM event listeners
+ * @private
+ */
+
+ }, {
+ key: "addEventListeners",
+ value: function addEventListeners() {
+ if (!this.document) {
+ return;
+ }
+
+ _constants.DOM_EVENTS.forEach(function (eventName) {
+ this.document.addEventListener(eventName, this.triggerEvent.bind(this), false);
+ }, this);
+ }
+
+ /**
+ * Remove DOM event listeners
+ * @private
+ */
+
+ }, {
+ key: "removeEventListeners",
+ value: function removeEventListeners() {
+ if (!this.document) {
+ return;
+ }
+ _constants.DOM_EVENTS.forEach(function (eventName) {
+ this.document.removeEventListener(eventName, this.triggerEvent, false);
+ }, this);
+ }
+
+ /**
+ * Emit passed browser events
+ * @private
+ */
+
+ }, {
+ key: "triggerEvent",
+ value: function triggerEvent(e) {
+ this.emit(e.type, e);
+ }
+
+ /**
+ * Add listener for text selection
+ * @private
+ */
+
+ }, {
+ key: "addSelectionListeners",
+ value: function addSelectionListeners() {
+ if (!this.document) {
+ return;
+ }
+ this.document.addEventListener("selectionchange", this.onSelectionChange.bind(this), false);
+ }
+
+ /**
+ * Remove listener for text selection
+ * @private
+ */
+
+ }, {
+ key: "removeSelectionListeners",
+ value: function removeSelectionListeners() {
+ if (!this.document) {
+ return;
+ }
+ this.document.removeEventListener("selectionchange", this.onSelectionChange, false);
+ }
+
+ /**
+ * Handle getting text on selection
+ * @private
+ */
+
+ }, {
+ key: "onSelectionChange",
+ value: function onSelectionChange(e) {
+ if (this.selectionEndTimeout) {
+ clearTimeout(this.selectionEndTimeout);
+ }
+ this.selectionEndTimeout = setTimeout(function () {
+ var selection = this.window.getSelection();
+ this.triggerSelectedEvent(selection);
+ }.bind(this), 250);
+ }
+
+ /**
+ * Emit event on text selection
+ * @private
+ */
+
+ }, {
+ key: "triggerSelectedEvent",
+ value: function triggerSelectedEvent(selection) {
+ var range, cfirange;
+
+ if (selection && selection.rangeCount > 0) {
+ range = selection.getRangeAt(0);
+ if (!range.collapsed) {
+ // cfirange = this.section.cfiFromRange(range);
+ cfirange = new _epubcfi2.default(range, this.cfiBase).toString();
+ this.emit(_constants.EVENTS.CONTENTS.SELECTED, cfirange);
+ this.emit(_constants.EVENTS.CONTENTS.SELECTED_RANGE, range);
+ }
+ }
+ }
+
+ /**
+ * Get a Dom Range from EpubCFI
+ * @param {EpubCFI} _cfi
+ * @param {string} [ignoreClass]
+ * @returns {Range} range
+ */
+
+ }, {
+ key: "range",
+ value: function range(_cfi, ignoreClass) {
+ var cfi = new _epubcfi2.default(_cfi);
+ return cfi.toRange(this.document, ignoreClass);
+ }
+
+ /**
+ * Get an EpubCFI from a Dom Range
+ * @param {Range} range
+ * @param {string} [ignoreClass]
+ * @returns {EpubCFI} cfi
+ */
+
+ }, {
+ key: "cfiFromRange",
+ value: function cfiFromRange(range, ignoreClass) {
+ return new _epubcfi2.default(range, this.cfiBase, ignoreClass).toString();
+ }
+
+ /**
+ * Get an EpubCFI from a Dom node
+ * @param {node} node
+ * @param {string} [ignoreClass]
+ * @returns {EpubCFI} cfi
+ */
+
+ }, {
+ key: "cfiFromNode",
+ value: function cfiFromNode(node, ignoreClass) {
+ return new _epubcfi2.default(node, this.cfiBase, ignoreClass).toString();
+ }
+
+ // TODO: find where this is used - remove?
+
+ }, {
+ key: "map",
+ value: function map(layout) {
+ var map = new _mapping2.default(layout);
+ return map.section();
+ }
+
+ /**
+ * Size the contents to a given width and height
+ * @param {number} [width]
+ * @param {number} [height]
+ */
+
+ }, {
+ key: "size",
+ value: function size(width, height) {
+ var viewport = { scale: 1.0, scalable: "no" };
+
+ this.layoutStyle("scrolling");
+
+ if (width >= 0) {
+ this.width(width);
+ viewport.width = width;
+ this.css("padding", "0 " + width / 12 + "px", true);
+ }
+
+ if (height >= 0) {
+ this.height(height);
+ viewport.height = height;
+ }
+
+ this.css("margin", "0");
+ this.css("box-sizing", "border-box");
+
+ this.viewport(viewport);
+ }
+
+ /**
+ * Apply columns to the contents for pagination
+ * @param {number} width
+ * @param {number} height
+ * @param {number} columnWidth
+ * @param {number} gap
+ */
+
+ }, {
+ key: "columns",
+ value: function columns(width, height, columnWidth, gap) {
+ var COLUMN_AXIS = (0, _core.prefixed)("column-axis");
+ var COLUMN_GAP = (0, _core.prefixed)("column-gap");
+ var COLUMN_WIDTH = (0, _core.prefixed)("column-width");
+ var COLUMN_FILL = (0, _core.prefixed)("column-fill");
+
+ var writingMode = this.writingMode();
+ var axis = writingMode.indexOf("vertical") === 0 ? "vertical" : "horizontal";
+
+ this.layoutStyle("paginated");
+
+ // Fix body width issues if rtl is only set on body element
+ if (this.content.dir === "rtl") {
+ this.direction("rtl");
+ }
+
+ this.width(width);
+ this.height(height);
+
+ // Deal with Mobile trying to scale to viewport
+ this.viewport({ width: width, height: height, scale: 1.0, scalable: "no" });
+
+ // TODO: inline-block needs more testing
+ // Fixes Safari column cut offs, but causes RTL issues
+ // this.css("display", "inline-block");
+
+ this.css("overflow-y", "hidden");
+ this.css("margin", "0", true);
+
+ if (axis === "vertical") {
+ this.css("padding", gap / 2 + "px 20px", true);
+ } else {
+ this.css("padding", "20px " + gap / 2 + "px", true);
+ }
+
+ this.css("box-sizing", "border-box");
+ this.css("max-width", "inherit");
+
+ this.css(COLUMN_AXIS, "horizontal");
+ this.css(COLUMN_FILL, "auto");
+
+ this.css(COLUMN_GAP, gap + "px");
+ this.css(COLUMN_WIDTH, columnWidth + "px");
+ }
+
+ /**
+ * Scale contents from center
+ * @param {number} scale
+ * @param {number} offsetX
+ * @param {number} offsetY
+ */
+
+ }, {
+ key: "scaler",
+ value: function scaler(scale, offsetX, offsetY) {
+ var scaleStr = "scale(" + scale + ")";
+ var translateStr = "";
+ // this.css("position", "absolute"));
+ this.css("transform-origin", "top left");
+
+ if (offsetX >= 0 || offsetY >= 0) {
+ translateStr = " translate(" + (offsetX || 0) + "px, " + (offsetY || 0) + "px )";
+ }
+
+ this.css("transform", scaleStr + translateStr);
+ }
+
+ /**
+ * Fit contents into a fixed width and height
+ * @param {number} width
+ * @param {number} height
+ */
+
+ }, {
+ key: "fit",
+ value: function fit(width, height) {
+ var viewport = this.viewport();
+ var widthScale = width / parseInt(viewport.width);
+ var heightScale = height / parseInt(viewport.height);
+ var scale = widthScale < heightScale ? widthScale : heightScale;
+
+ var offsetY = (height - viewport.height * scale) / 2;
+
+ this.layoutStyle("paginated");
+
+ this.width(width);
+ this.height(height);
+ this.overflow("hidden");
+
+ // Scale to the correct size
+ this.scaler(scale, 0, offsetY);
+
+ this.css("background-color", "transparent");
+ }
+
+ /**
+ * Set the direction of the text
+ * @param {string} [dir="ltr"] "rtl" | "ltr"
+ */
+
+ }, {
+ key: "direction",
+ value: function direction(dir) {
+ if (this.documentElement) {
+ this.documentElement.style["direction"] = dir;
+ }
+ }
+ }, {
+ key: "mapPage",
+ value: function mapPage(cfiBase, layout, start, end, dev) {
+ var mapping = new _mapping2.default(layout, dev);
+
+ return mapping.page(this, cfiBase, start, end);
+ }
+
+ /**
+ * Emit event when link in content is clicked
+ * @private
+ */
+
+ }, {
+ key: "linksHandler",
+ value: function linksHandler() {
+ var _this2 = this;
+
+ (0, _replacements.replaceLinks)(this.content, function (href) {
+ _this2.emit(_constants.EVENTS.CONTENTS.LINK_CLICKED, href);
+ });
+ }
+
+ /**
+ * Set the writingMode of the text
+ * @param {string} [mode="horizontal-tb"] "horizontal-tb" | "vertical-rl" | "vertical-lr"
+ */
+
+ }, {
+ key: "writingMode",
+ value: function writingMode(mode) {
+ var WRITING_MODE = (0, _core.prefixed)("writing-mode");
+
+ if (mode && this.documentElement) {
+ this.documentElement.style[WRITING_MODE] = mode;
+ }
+
+ return this.window.getComputedStyle(this.documentElement)[WRITING_MODE] || '';
+ }
+
+ /**
+ * Set the layoutStyle of the content
+ * @param {string} [style="paginated"] "scrolling" | "paginated"
+ * @private
+ */
+
+ }, {
+ key: "layoutStyle",
+ value: function layoutStyle(style) {
+
+ if (style) {
+ this._layoutStyle = style;
+ navigator.epubReadingSystem.layoutStyle = this._layoutStyle;
+ }
+
+ return this._layoutStyle || "paginated";
+ }
+
+ /**
+ * Add the epubReadingSystem object to the navigator
+ * @param {string} name
+ * @param {string} version
+ * @private
+ */
+
+ }, {
+ key: "epubReadingSystem",
+ value: function epubReadingSystem(name, version) {
+ navigator.epubReadingSystem = {
+ name: name,
+ version: version,
+ layoutStyle: this.layoutStyle(),
+ hasFeature: function hasFeature(feature) {
+ switch (feature) {
+ case "dom-manipulation":
+ return true;
+ case "layout-changes":
+ return true;
+ case "touch-events":
+ return true;
+ case "mouse-events":
+ return true;
+ case "keyboard-events":
+ return true;
+ case "spine-scripting":
+ return false;
+ default:
+ return false;
+ }
+ }
+ };
+ return navigator.epubReadingSystem;
+ }
+ }, {
+ key: "destroy",
+ value: function destroy() {
+ // Stop observing
+ if (this.observer) {
+ this.observer.disconnect();
+ }
+
+ this.document.removeEventListener('transitionend', this.resizeCheck);
+
+ this.removeListeners();
+ }
+ }], [{
+ key: "listenedEvents",
+ get: function get() {
+ return _constants.DOM_EVENTS;
+ }
+ }]);
+
+ return Contents;
+}();
+
+(0, _eventEmitter2.default)(Contents.prototype);
+
+exports.default = Contents;
+module.exports = exports["default"];
+
+/***/ }),
+/* 14 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+
+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; }; }();
+
+var _eventEmitter = __webpack_require__(2);
+
+var _eventEmitter2 = _interopRequireDefault(_eventEmitter);
+
+var _core = __webpack_require__(0);
+
+var _mapping = __webpack_require__(19);
+
+var _mapping2 = _interopRequireDefault(_mapping);
+
+var _queue = __webpack_require__(12);
+
+var _queue2 = _interopRequireDefault(_queue);
+
+var _stage = __webpack_require__(56);
+
+var _stage2 = _interopRequireDefault(_stage);
+
+var _views = __webpack_require__(66);
+
+var _views2 = _interopRequireDefault(_views);
+
+var _constants = __webpack_require__(3);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+var DefaultViewManager = function () {
+ function DefaultViewManager(options) {
+ _classCallCheck(this, DefaultViewManager);
+
+ this.name = "default";
+ this.View = options.view;
+ this.request = options.request;
+ this.renditionQueue = options.queue;
+ this.q = new _queue2.default(this);
+
+ this.settings = (0, _core.extend)(this.settings || {}, {
+ infinite: true,
+ hidden: false,
+ width: undefined,
+ height: undefined,
+ axis: undefined,
+ flow: "scrolled",
+ ignoreClass: ""
+ });
+
+ (0, _core.extend)(this.settings, options.settings || {});
+
+ this.viewSettings = {
+ ignoreClass: this.settings.ignoreClass,
+ axis: this.settings.axis,
+ flow: this.settings.flow,
+ layout: this.layout,
+ method: this.settings.method, // srcdoc, blobUrl, write
+ width: 0,
+ height: 0,
+ forceEvenPages: true
+ };
+
+ this.rendered = false;
+ }
+
+ _createClass(DefaultViewManager, [{
+ key: "render",
+ value: function render(element, size) {
+ var tag = element.tagName;
+
+ if (tag && (tag.toLowerCase() == "body" || tag.toLowerCase() == "html")) {
+ this.fullsize = true;
+ }
+
+ if (this.fullsize) {
+ this.settings.overflow = "visible";
+ this.overflow = this.settings.overflow;
+ }
+
+ this.settings.size = size;
+
+ // Save the stage
+ this.stage = new _stage2.default({
+ width: size.width,
+ height: size.height,
+ overflow: this.overflow,
+ hidden: this.settings.hidden,
+ axis: this.settings.axis,
+ fullsize: this.fullsize,
+ direction: this.settings.direction
+ });
+
+ this.stage.attachTo(element);
+
+ // Get this stage container div
+ this.container = this.stage.getContainer();
+
+ // Views array methods
+ this.views = new _views2.default(this.container);
+
+ // Calculate Stage Size
+ this._bounds = this.bounds();
+ this._stageSize = this.stage.size();
+
+ // Set the dimensions for views
+ this.viewSettings.width = this._stageSize.width;
+ this.viewSettings.height = this._stageSize.height;
+
+ // Function to handle a resize event.
+ // Will only attach if width and height are both fixed.
+ this.stage.onResize(this.onResized.bind(this));
+
+ this.stage.onOrientationChange(this.onOrientationChange.bind(this));
+
+ // Add Event Listeners
+ this.addEventListeners();
+
+ // Add Layout method
+ // this.applyLayoutMethod();
+ if (this.layout) {
+ this.updateLayout();
+ }
+
+ this.rendered = true;
+ }
+ }, {
+ key: "addEventListeners",
+ value: function addEventListeners() {
+ var scroller;
+
+ window.addEventListener("unload", function (e) {
+ this.destroy();
+ }.bind(this));
+
+ if (!this.fullsize) {
+ scroller = this.container;
+ } else {
+ scroller = window;
+ }
+
+ scroller.addEventListener("scroll", this.onScroll.bind(this));
+ }
+ }, {
+ key: "removeEventListeners",
+ value: function removeEventListeners() {
+ var scroller;
+
+ if (!this.fullsize) {
+ scroller = this.container;
+ } else {
+ scroller = window;
+ }
+
+ scroller.removeEventListener("scroll", this.onScroll.bind(this));
+ }
+ }, {
+ key: "destroy",
+ value: function destroy() {
+ clearTimeout(this.orientationTimeout);
+ clearTimeout(this.resizeTimeout);
+ clearTimeout(this.afterScrolled);
+
+ this.clear();
+
+ this.removeEventListeners();
+
+ this.stage.destroy();
+
+ this.rendered = false;
+
+ /*
+ clearTimeout(this.trimTimeout);
+ if(this.settings.hidden) {
+ this.element.removeChild(this.wrapper);
+ } else {
+ this.element.removeChild(this.container);
+ }
+ */
+ }
+ }, {
+ key: "onOrientationChange",
+ value: function onOrientationChange(e) {
+ var _window = window,
+ orientation = _window.orientation;
+
+
+ this.resize();
+
+ // Per ampproject:
+ // In IOS 10.3, the measured size of an element is incorrect if the
+ // element size depends on window size directly and the measurement
+ // happens in window.resize event. Adding a timeout for correct
+ // measurement. See https://github.com/ampproject/amphtml/issues/8479
+ clearTimeout(this.orientationTimeout);
+ this.orientationTimeout = setTimeout(function () {
+ this.orientationTimeout = undefined;
+ this.resize();
+ this.emit(_constants.EVENTS.MANAGERS.ORIENTATION_CHANGE, orientation);
+ }.bind(this), 500);
+ }
+ }, {
+ key: "onResized",
+ value: function onResized(e) {
+ this.resize();
+ }
+ }, {
+ key: "resize",
+ value: function resize(width, height) {
+ var stageSize = this.stage.size(width, height);
+
+ // For Safari, wait for orientation to catch up
+ // if the window is a square
+ this.winBounds = (0, _core.windowBounds)();
+ if (this.orientationTimeout && this.winBounds.width === this.winBounds.height) {
+ // reset the stage size for next resize
+ this._stageSize = undefined;
+ return;
+ }
+
+ if (this._stageSize && this._stageSize.width === stageSize.width && this._stageSize.height === stageSize.height) {
+ // Size is the same, no need to resize
+ return;
+ }
+
+ this._stageSize = stageSize;
+
+ this._bounds = this.bounds();
+
+ // Clear current views
+ this.clear();
+
+ // Update for new views
+ this.viewSettings.width = this._stageSize.width;
+ this.viewSettings.height = this._stageSize.height;
+
+ this.updateLayout();
+
+ this.emit(_constants.EVENTS.MANAGERS.RESIZED, {
+ width: this._stageSize.width,
+ height: this._stageSize.height
+ });
+ }
+ }, {
+ key: "createView",
+ value: function createView(section) {
+ return new this.View(section, this.viewSettings);
+ }
+ }, {
+ key: "display",
+ value: function display(section, target) {
+
+ var displaying = new _core.defer();
+ var displayed = displaying.promise;
+
+ // Check if moving to target is needed
+ if (target === section.href || (0, _core.isNumber)(target)) {
+ target = undefined;
+ }
+
+ // Check to make sure the section we want isn't already shown
+ var visible = this.views.find(section);
+
+ // View is already shown, just move to correct location in view
+ if (visible && section) {
+ var offset = visible.offset();
+
+ if (this.settings.direction === "ltr") {
+ this.scrollTo(offset.left, offset.top, true);
+ } else {
+ var width = visible.width();
+ this.scrollTo(offset.left + width, offset.top, true);
+ }
+
+ if (target) {
+ var _offset = visible.locationOf(target);
+ this.moveTo(_offset);
+ }
+
+ displaying.resolve();
+ return displayed;
+ }
+
+ // Hide all current views
+ this.clear();
+
+ this.add(section).then(function (view) {
+
+ // Move to correct place within the section, if needed
+ if (target) {
+ var _offset2 = view.locationOf(target);
+ this.moveTo(_offset2);
+ }
+ }.bind(this), function (err) {
+ displaying.reject(err);
+ }).then(function () {
+ var next;
+ if (this.layout.name === "pre-paginated" && this.layout.divisor > 1) {
+ next = section.next();
+ if (next) {
+ return this.add(next);
+ }
+ }
+ }.bind(this)).then(function () {
+
+ this.views.show();
+
+ displaying.resolve();
+ }.bind(this));
+ // .then(function(){
+ // return this.hooks.display.trigger(view);
+ // }.bind(this))
+ // .then(function(){
+ // this.views.show();
+ // }.bind(this));
+ return displayed;
+ }
+ }, {
+ key: "afterDisplayed",
+ value: function afterDisplayed(view) {
+ this.emit(_constants.EVENTS.MANAGERS.ADDED, view);
+ }
+ }, {
+ key: "afterResized",
+ value: function afterResized(view) {
+ this.emit(_constants.EVENTS.MANAGERS.RESIZE, view.section);
+ }
+ }, {
+ key: "moveTo",
+ value: function moveTo(offset) {
+ var distX = 0,
+ distY = 0;
+
+ if (!this.isPaginated) {
+ distY = offset.top;
+ } else {
+ distX = Math.floor(offset.left / this.layout.delta) * this.layout.delta;
+
+ if (distX + this.layout.delta > this.container.scrollWidth) {
+ distX = this.container.scrollWidth - this.layout.delta;
+ }
+ }
+ this.scrollTo(distX, distY, true);
+ }
+ }, {
+ key: "add",
+ value: function add(section) {
+ var _this = this;
+
+ var view = this.createView(section);
+
+ this.views.append(view);
+
+ // view.on(EVENTS.VIEWS.SHOWN, this.afterDisplayed.bind(this));
+ view.onDisplayed = this.afterDisplayed.bind(this);
+ view.onResize = this.afterResized.bind(this);
+
+ view.on(_constants.EVENTS.VIEWS.AXIS, function (axis) {
+ _this.updateAxis(axis);
+ });
+
+ return view.display(this.request);
+ }
+ }, {
+ key: "append",
+ value: function append(section) {
+ var _this2 = this;
+
+ var view = this.createView(section);
+ this.views.append(view);
+
+ view.onDisplayed = this.afterDisplayed.bind(this);
+ view.onResize = this.afterResized.bind(this);
+
+ view.on(_constants.EVENTS.VIEWS.AXIS, function (axis) {
+ _this2.updateAxis(axis);
+ });
+
+ return view.display(this.request);
+ }
+ }, {
+ key: "prepend",
+ value: function prepend(section) {
+ var _this3 = this;
+
+ var view = this.createView(section);
+
+ view.on(_constants.EVENTS.VIEWS.RESIZED, function (bounds) {
+ _this3.counter(bounds);
+ });
+
+ this.views.prepend(view);
+
+ view.onDisplayed = this.afterDisplayed.bind(this);
+ view.onResize = this.afterResized.bind(this);
+
+ view.on(_constants.EVENTS.VIEWS.AXIS, function (axis) {
+ _this3.updateAxis(axis);
+ });
+
+ return view.display(this.request);
+ }
+ }, {
+ key: "counter",
+ value: function counter(bounds) {
+ if (this.settings.axis === "vertical") {
+ this.scrollBy(0, bounds.heightDelta, true);
+ } else {
+ this.scrollBy(bounds.widthDelta, 0, true);
+ }
+ }
+
+ // resizeView(view) {
+ //
+ // if(this.settings.globalLayoutProperties.layout === "pre-paginated") {
+ // view.lock("both", this.bounds.width, this.bounds.height);
+ // } else {
+ // view.lock("width", this.bounds.width, this.bounds.height);
+ // }
+ //
+ // };
+
+ }, {
+ key: "next",
+ value: function next() {
+ var next;
+ var left;
+
+ var dir = this.settings.direction;
+
+ if (!this.views.length) return;
+
+ if (this.isPaginated && this.settings.axis === "horizontal" && (!dir || dir === "ltr")) {
+
+ this.scrollLeft = this.container.scrollLeft;
+
+ left = this.container.scrollLeft + this.container.offsetWidth + this.layout.delta;
+
+ if (left <= this.container.scrollWidth) {
+ this.scrollBy(this.layout.delta, 0, true);
+ } else {
+ next = this.views.last().section.next();
+ }
+ } else if (this.isPaginated && this.settings.axis === "horizontal" && dir === "rtl") {
+
+ this.scrollLeft = this.container.scrollLeft;
+
+ left = this.container.scrollLeft;
+
+ if (left > 0) {
+ this.scrollBy(this.layout.delta, 0, true);
+ } else {
+ next = this.views.last().section.next();
+ }
+ } else if (this.isPaginated && this.settings.axis === "vertical") {
+
+ this.scrollTop = this.container.scrollTop;
+
+ var top = this.container.scrollTop + this.container.offsetHeight;
+
+ if (top < this.container.scrollHeight) {
+ this.scrollBy(0, this.layout.height, true);
+ } else {
+ next = this.views.last().section.next();
+ }
+ } else {
+ next = this.views.last().section.next();
+ }
+
+ if (next) {
+ this.clear();
+
+ return this.append(next).then(function () {
+ var right;
+ if (this.layout.name === "pre-paginated" && this.layout.divisor > 1) {
+ right = next.next();
+ if (right) {
+ return this.append(right);
+ }
+ }
+ }.bind(this), function (err) {
+ displaying.reject(err);
+ }).then(function () {
+ this.views.show();
+ }.bind(this));
+ }
+ }
+ }, {
+ key: "prev",
+ value: function prev() {
+ var prev;
+ var left;
+ var dir = this.settings.direction;
+
+ if (!this.views.length) return;
+
+ if (this.isPaginated && this.settings.axis === "horizontal" && (!dir || dir === "ltr")) {
+
+ this.scrollLeft = this.container.scrollLeft;
+
+ left = this.container.scrollLeft;
+
+ if (left > 0) {
+ this.scrollBy(-this.layout.delta, 0, true);
+ } else {
+ prev = this.views.first().section.prev();
+ }
+ } else if (this.isPaginated && this.settings.axis === "horizontal" && dir === "rtl") {
+
+ this.scrollLeft = this.container.scrollLeft;
+
+ left = this.container.scrollLeft + this.container.offsetWidth + this.layout.delta;
+
+ if (left <= this.container.scrollWidth) {
+ this.scrollBy(-this.layout.delta, 0, true);
+ } else {
+ prev = this.views.first().section.prev();
+ }
+ } else if (this.isPaginated && this.settings.axis === "vertical") {
+
+ this.scrollTop = this.container.scrollTop;
+
+ var top = this.container.scrollTop;
+
+ if (top > 0) {
+ this.scrollBy(0, -this.layout.height, true);
+ } else {
+ prev = this.views.first().section.prev();
+ }
+ } else {
+
+ prev = this.views.first().section.prev();
+ }
+
+ if (prev) {
+ this.clear();
+
+ return this.prepend(prev).then(function () {
+ var left;
+ if (this.layout.name === "pre-paginated" && this.layout.divisor > 1) {
+ left = prev.prev();
+ if (left) {
+ return this.prepend(left);
+ }
+ }
+ }.bind(this), function (err) {
+ displaying.reject(err);
+ }).then(function () {
+ if (this.isPaginated && this.settings.axis === "horizontal") {
+ if (this.settings.direction === "rtl") {
+ this.scrollTo(0, 0, true);
+ } else {
+ this.scrollTo(this.container.scrollWidth - this.layout.delta, 0, true);
+ }
+ }
+ this.views.show();
+ }.bind(this));
+ }
+ }
+ }, {
+ key: "current",
+ value: function current() {
+ var visible = this.visible();
+ if (visible.length) {
+ // Current is the last visible view
+ return visible[visible.length - 1];
+ }
+ return null;
+ }
+ }, {
+ key: "clear",
+ value: function clear() {
+
+ // this.q.clear();
+
+ if (this.views) {
+ this.views.hide();
+ this.scrollTo(0, 0, true);
+ this.views.clear();
+ }
+ }
+ }, {
+ key: "currentLocation",
+ value: function currentLocation() {
+
+ if (this.settings.axis === "vertical") {
+ this.location = this.scrolledLocation();
+ } else {
+ this.location = this.paginatedLocation();
+ }
+ return this.location;
+ }
+ }, {
+ key: "scrolledLocation",
+ value: function scrolledLocation() {
+ var _this4 = this;
+
+ var visible = this.visible();
+ var container = this.container.getBoundingClientRect();
+ var pageHeight = container.height < window.innerHeight ? container.height : window.innerHeight;
+
+ var offset = 0;
+ var used = 0;
+
+ if (this.fullsize) {
+ offset = window.scrollY;
+ }
+
+ var sections = visible.map(function (view) {
+ var _view$section = view.section,
+ index = _view$section.index,
+ href = _view$section.href;
+
+ var position = view.position();
+ var height = view.height();
+
+ var startPos = offset + container.top - position.top + used;
+ var endPos = startPos + pageHeight - used;
+ if (endPos > height) {
+ endPos = height;
+ used = endPos - startPos;
+ }
+
+ var totalPages = _this4.layout.count(height, pageHeight).pages;
+
+ var currPage = Math.ceil(startPos / pageHeight);
+ var pages = [];
+ var endPage = Math.ceil(endPos / pageHeight);
+
+ pages = [];
+ for (var i = currPage; i <= endPage; i++) {
+ var pg = i + 1;
+ pages.push(pg);
+ }
+
+ var mapping = _this4.mapping.page(view.contents, view.section.cfiBase, startPos, endPos);
+
+ return {
+ index: index,
+ href: href,
+ pages: pages,
+ totalPages: totalPages,
+ mapping: mapping
+ };
+ });
+
+ return sections;
+ }
+ }, {
+ key: "paginatedLocation",
+ value: function paginatedLocation() {
+ var _this5 = this;
+
+ var visible = this.visible();
+ var container = this.container.getBoundingClientRect();
+
+ var left = 0;
+ var used = 0;
+
+ if (this.fullsize) {
+ left = window.scrollX;
+ }
+
+ var sections = visible.map(function (view) {
+ var _view$section2 = view.section,
+ index = _view$section2.index,
+ href = _view$section2.href;
+
+ var offset = view.offset().left;
+ var position = view.position().left;
+ var width = view.width();
+
+ // Find mapping
+ var start = left + container.left - position + used;
+ var end = start + _this5.layout.width - used;
+
+ var mapping = _this5.mapping.page(view.contents, view.section.cfiBase, start, end);
+
+ // Find displayed pages
+ //console.log("pre", end, offset + width);
+ // if (end > offset + width) {
+ // end = offset + width;
+ // used = this.layout.pageWidth;
+ // }
+ // console.log("post", end);
+
+ var totalPages = _this5.layout.count(width).pages;
+ var startPage = Math.floor(start / _this5.layout.pageWidth);
+ var pages = [];
+ var endPage = Math.floor(end / _this5.layout.pageWidth);
+
+ // start page should not be negative
+ if (startPage < 0) {
+ startPage = 0;
+ endPage = endPage + 1;
+ }
+
+ // Reverse page counts for rtl
+ if (_this5.settings.direction === "rtl") {
+ var tempStartPage = startPage;
+ startPage = totalPages - endPage;
+ endPage = totalPages - tempStartPage;
+ }
+
+ for (var i = startPage + 1; i <= endPage; i++) {
+ var pg = i;
+ pages.push(pg);
+ }
+
+ return {
+ index: index,
+ href: href,
+ pages: pages,
+ totalPages: totalPages,
+ mapping: mapping
+ };
+ });
+
+ return sections;
+ }
+ }, {
+ key: "isVisible",
+ value: function isVisible(view, offsetPrev, offsetNext, _container) {
+ var position = view.position();
+ var container = _container || this.bounds();
+
+ if (this.settings.axis === "horizontal" && position.right > container.left - offsetPrev && position.left < container.right + offsetNext) {
+
+ return true;
+ } else if (this.settings.axis === "vertical" && position.bottom > container.top - offsetPrev && position.top < container.bottom + offsetNext) {
+
+ return true;
+ }
+
+ return false;
+ }
+ }, {
+ key: "visible",
+ value: function visible() {
+ var container = this.bounds();
+ var views = this.views.displayed();
+ var viewsLength = views.length;
+ var visible = [];
+ var isVisible;
+ var view;
+
+ for (var i = 0; i < viewsLength; i++) {
+ view = views[i];
+ isVisible = this.isVisible(view, 0, 0, container);
+
+ if (isVisible === true) {
+ visible.push(view);
+ }
+ }
+ return visible;
+ }
+ }, {
+ key: "scrollBy",
+ value: function scrollBy(x, y, silent) {
+ var dir = this.settings.direction === "rtl" ? -1 : 1;
+
+ if (silent) {
+ this.ignore = true;
+ }
+
+ if (!this.fullsize) {
+ if (x) this.container.scrollLeft += x * dir;
+ if (y) this.container.scrollTop += y;
+ } else {
+ window.scrollBy(x * dir, y * dir);
+ }
+ this.scrolled = true;
+ }
+ }, {
+ key: "scrollTo",
+ value: function scrollTo(x, y, silent) {
+ if (silent) {
+ this.ignore = true;
+ }
+
+ if (!this.fullsize) {
+ this.container.scrollLeft = x;
+ this.container.scrollTop = y;
+ } else {
+ window.scrollTo(x, y);
+ }
+ this.scrolled = true;
+ }
+ }, {
+ key: "onScroll",
+ value: function onScroll() {
+ var scrollTop = void 0;
+ var scrollLeft = void 0;
+
+ if (!this.fullsize) {
+ scrollTop = this.container.scrollTop;
+ scrollLeft = this.container.scrollLeft;
+ } else {
+ scrollTop = window.scrollY;
+ scrollLeft = window.scrollX;
+ }
+
+ this.scrollTop = scrollTop;
+ this.scrollLeft = scrollLeft;
+
+ if (!this.ignore) {
+ this.emit(_constants.EVENTS.MANAGERS.SCROLL, {
+ top: scrollTop,
+ left: scrollLeft
+ });
+
+ clearTimeout(this.afterScrolled);
+ this.afterScrolled = setTimeout(function () {
+ this.emit(_constants.EVENTS.MANAGERS.SCROLLED, {
+ top: this.scrollTop,
+ left: this.scrollLeft
+ });
+ }.bind(this), 20);
+ } else {
+ this.ignore = false;
+ }
+ }
+ }, {
+ key: "bounds",
+ value: function bounds() {
+ var bounds;
+
+ bounds = this.stage.bounds();
+
+ return bounds;
+ }
+ }, {
+ key: "applyLayout",
+ value: function applyLayout(layout) {
+
+ this.layout = layout;
+ this.updateLayout();
+ // this.manager.layout(this.layout.format);
+ }
+ }, {
+ key: "updateLayout",
+ value: function updateLayout() {
+
+ if (!this.stage) {
+ return;
+ }
+
+ this._stageSize = this.stage.size();
+
+ if (!this.isPaginated) {
+ this.layout.calculate(this._stageSize.width, this._stageSize.height);
+ } else {
+ this.layout.calculate(this._stageSize.width, this._stageSize.height, this.settings.gap);
+
+ // Set the look ahead offset for what is visible
+ this.settings.offset = this.layout.delta;
+
+ // this.stage.addStyleRules("iframe", [{"margin-right" : this.layout.gap + "px"}]);
+ }
+
+ // Set the dimensions for views
+ this.viewSettings.width = this.layout.width;
+ this.viewSettings.height = this.layout.height;
+
+ this.setLayout(this.layout);
+ }
+ }, {
+ key: "setLayout",
+ value: function setLayout(layout) {
+
+ this.viewSettings.layout = layout;
+
+ this.mapping = new _mapping2.default(layout.props, this.settings.direction, this.settings.axis);
+
+ if (this.views) {
+
+ this.views.forEach(function (view) {
+ if (view) {
+ view.setLayout(layout);
+ }
+ });
+ }
+ }
+ }, {
+ key: "updateAxis",
+ value: function updateAxis(axis, forceUpdate) {
+
+ if (!this.isPaginated) {
+ axis = "vertical";
+ }
+
+ if (!forceUpdate && axis === this.settings.axis) {
+ return;
+ }
+
+ this.settings.axis = axis;
+
+ this.stage && this.stage.axis(axis);
+
+ this.viewSettings.axis = axis;
+
+ if (this.mapping) {
+ this.mapping = new _mapping2.default(this.layout.props, this.settings.direction, this.settings.axis);
+ }
+
+ if (this.layout) {
+ if (axis === "vertical") {
+ this.layout.spread("none");
+ } else {
+ this.layout.spread(this.layout.settings.spread);
+ }
+ }
+ }
+ }, {
+ key: "updateFlow",
+ value: function updateFlow(flow) {
+ var isPaginated = flow === "paginated" || flow === "auto";
+
+ this.isPaginated = isPaginated;
+
+ if (flow === "scrolled-doc" || flow === "scrolled-continuous" || flow === "scrolled") {
+ this.updateAxis("vertical");
+ }
+
+ this.viewSettings.flow = flow;
+
+ if (!this.settings.overflow) {
+ this.overflow = isPaginated ? "hidden" : "auto";
+ } else {
+ this.overflow = this.settings.overflow;
+ }
+ // this.views.forEach(function(view){
+ // view.setAxis(axis);
+ // });
+
+ this.updateLayout();
+ }
+ }, {
+ key: "getContents",
+ value: function getContents() {
+ var contents = [];
+ if (!this.views) {
+ return contents;
+ }
+ this.views.forEach(function (view) {
+ var viewContents = view && view.contents;
+ if (viewContents) {
+ contents.push(viewContents);
+ }
+ });
+ return contents;
+ }
+ }, {
+ key: "direction",
+ value: function direction() {
+ var dir = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : "ltr";
+
+ this.settings.direction = dir;
+
+ this.stage && this.stage.direction(dir);
+
+ this.viewSettings.direction = dir;
+
+ this.updateLayout();
+ }
+ }, {
+ key: "isRendered",
+ value: function isRendered() {
+ return this.rendered;
+ }
+ }]);
+
+ return DefaultViewManager;
+}();
+
+//-- Enable binding events to Manager
+
+
+(0, _eventEmitter2.default)(DefaultViewManager.prototype);
+
+exports.default = DefaultViewManager;
+module.exports = exports["default"];
+
+/***/ }),
+/* 15 */
+/***/ (function(module, exports) {
+
+/**
+ * Checks if `value` is the
+ * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)
+ * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is an object, else `false`.
+ * @example
+ *
+ * _.isObject({});
+ * // => true
+ *
+ * _.isObject([1, 2, 3]);
+ * // => true
+ *
+ * _.isObject(_.noop);
+ * // => true
+ *
+ * _.isObject(null);
+ * // => false
+ */
+function isObject(value) {
+ var type = typeof value;
+ return value != null && (type == 'object' || type == 'function');
+}
+
+module.exports = isObject;
+
+
+/***/ }),
+/* 16 */
+/***/ (function(module, exports) {
+
+module.exports = __WEBPACK_EXTERNAL_MODULE_16__;
+
+/***/ }),
+/* 17 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+/*
+ From Zip.js, by Gildas Lormeau
+edited down
+ */
+
+var table = {
+ "application": {
+ "ecmascript": ["es", "ecma"],
+ "javascript": "js",
+ "ogg": "ogx",
+ "pdf": "pdf",
+ "postscript": ["ps", "ai", "eps", "epsi", "epsf", "eps2", "eps3"],
+ "rdf+xml": "rdf",
+ "smil": ["smi", "smil"],
+ "xhtml+xml": ["xhtml", "xht"],
+ "xml": ["xml", "xsl", "xsd", "opf", "ncx"],
+ "zip": "zip",
+ "x-httpd-eruby": "rhtml",
+ "x-latex": "latex",
+ "x-maker": ["frm", "maker", "frame", "fm", "fb", "book", "fbdoc"],
+ "x-object": "o",
+ "x-shockwave-flash": ["swf", "swfl"],
+ "x-silverlight": "scr",
+ "epub+zip": "epub",
+ "font-tdpfr": "pfr",
+ "inkml+xml": ["ink", "inkml"],
+ "json": "json",
+ "jsonml+json": "jsonml",
+ "mathml+xml": "mathml",
+ "metalink+xml": "metalink",
+ "mp4": "mp4s",
+ // "oebps-package+xml" : "opf",
+ "omdoc+xml": "omdoc",
+ "oxps": "oxps",
+ "vnd.amazon.ebook": "azw",
+ "widget": "wgt",
+ // "x-dtbncx+xml" : "ncx",
+ "x-dtbook+xml": "dtb",
+ "x-dtbresource+xml": "res",
+ "x-font-bdf": "bdf",
+ "x-font-ghostscript": "gsf",
+ "x-font-linux-psf": "psf",
+ "x-font-otf": "otf",
+ "x-font-pcf": "pcf",
+ "x-font-snf": "snf",
+ "x-font-ttf": ["ttf", "ttc"],
+ "x-font-type1": ["pfa", "pfb", "pfm", "afm"],
+ "x-font-woff": "woff",
+ "x-mobipocket-ebook": ["prc", "mobi"],
+ "x-mspublisher": "pub",
+ "x-nzb": "nzb",
+ "x-tgif": "obj",
+ "xaml+xml": "xaml",
+ "xml-dtd": "dtd",
+ "xproc+xml": "xpl",
+ "xslt+xml": "xslt",
+ "internet-property-stream": "acx",
+ "x-compress": "z",
+ "x-compressed": "tgz",
+ "x-gzip": "gz"
+ },
+ "audio": {
+ "flac": "flac",
+ "midi": ["mid", "midi", "kar", "rmi"],
+ "mpeg": ["mpga", "mpega", "mp2", "mp3", "m4a", "mp2a", "m2a", "m3a"],
+ "mpegurl": "m3u",
+ "ogg": ["oga", "ogg", "spx"],
+ "x-aiff": ["aif", "aiff", "aifc"],
+ "x-ms-wma": "wma",
+ "x-wav": "wav",
+ "adpcm": "adp",
+ "mp4": "mp4a",
+ "webm": "weba",
+ "x-aac": "aac",
+ "x-caf": "caf",
+ "x-matroska": "mka",
+ "x-pn-realaudio-plugin": "rmp",
+ "xm": "xm",
+ "mid": ["mid", "rmi"]
+ },
+ "image": {
+ "gif": "gif",
+ "ief": "ief",
+ "jpeg": ["jpeg", "jpg", "jpe"],
+ "pcx": "pcx",
+ "png": "png",
+ "svg+xml": ["svg", "svgz"],
+ "tiff": ["tiff", "tif"],
+ "x-icon": "ico",
+ "bmp": "bmp",
+ "webp": "webp",
+ "x-pict": ["pic", "pct"],
+ "x-tga": "tga",
+ "cis-cod": "cod"
+ },
+ "text": {
+ "cache-manifest": ["manifest", "appcache"],
+ "css": "css",
+ "csv": "csv",
+ "html": ["html", "htm", "shtml", "stm"],
+ "mathml": "mml",
+ "plain": ["txt", "text", "brf", "conf", "def", "list", "log", "in", "bas"],
+ "richtext": "rtx",
+ "tab-separated-values": "tsv",
+ "x-bibtex": "bib"
+ },
+ "video": {
+ "mpeg": ["mpeg", "mpg", "mpe", "m1v", "m2v", "mp2", "mpa", "mpv2"],
+ "mp4": ["mp4", "mp4v", "mpg4"],
+ "quicktime": ["qt", "mov"],
+ "ogg": "ogv",
+ "vnd.mpegurl": ["mxu", "m4u"],
+ "x-flv": "flv",
+ "x-la-asf": ["lsf", "lsx"],
+ "x-mng": "mng",
+ "x-ms-asf": ["asf", "asx", "asr"],
+ "x-ms-wm": "wm",
+ "x-ms-wmv": "wmv",
+ "x-ms-wmx": "wmx",
+ "x-ms-wvx": "wvx",
+ "x-msvideo": "avi",
+ "x-sgi-movie": "movie",
+ "x-matroska": ["mpv", "mkv", "mk3d", "mks"],
+ "3gpp2": "3g2",
+ "h261": "h261",
+ "h263": "h263",
+ "h264": "h264",
+ "jpeg": "jpgv",
+ "jpm": ["jpm", "jpgm"],
+ "mj2": ["mj2", "mjp2"],
+ "vnd.ms-playready.media.pyv": "pyv",
+ "vnd.uvvu.mp4": ["uvu", "uvvu"],
+ "vnd.vivo": "viv",
+ "webm": "webm",
+ "x-f4v": "f4v",
+ "x-m4v": "m4v",
+ "x-ms-vob": "vob",
+ "x-smv": "smv"
+ }
+};
+
+var mimeTypes = function () {
+ var type,
+ subtype,
+ val,
+ index,
+ mimeTypes = {};
+ for (type in table) {
+ if (table.hasOwnProperty(type)) {
+ for (subtype in table[type]) {
+ if (table[type].hasOwnProperty(subtype)) {
+ val = table[type][subtype];
+ if (typeof val == "string") {
+ mimeTypes[val] = type + "/" + subtype;
+ } else {
+ for (index = 0; index < val.length; index++) {
+ mimeTypes[val[index]] = type + "/" + subtype;
+ }
+ }
+ }
+ }
+ }
+ }
+ return mimeTypes;
+}();
+
+var defaultValue = "text/plain"; //"application/octet-stream";
+
+function lookup(filename) {
+ return filename && mimeTypes[filename.split(".").pop().toLowerCase()] || defaultValue;
+};
+
+module.exports = {
+ 'lookup': lookup
+};
+
+/***/ }),
+/* 18 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+
+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; };
+
+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; }; }();
+// import Mapping from "./mapping";
+
+
+// Default Views
+
+
+// Default View Managers
+
+
+var _eventEmitter = __webpack_require__(2);
+
+var _eventEmitter2 = _interopRequireDefault(_eventEmitter);
+
+var _core = __webpack_require__(0);
+
+var _hook = __webpack_require__(10);
+
+var _hook2 = _interopRequireDefault(_hook);
+
+var _epubcfi = __webpack_require__(1);
+
+var _epubcfi2 = _interopRequireDefault(_epubcfi);
+
+var _queue = __webpack_require__(12);
+
+var _queue2 = _interopRequireDefault(_queue);
+
+var _layout = __webpack_require__(50);
+
+var _layout2 = _interopRequireDefault(_layout);
+
+var _themes = __webpack_require__(51);
+
+var _themes2 = _interopRequireDefault(_themes);
+
+var _contents = __webpack_require__(13);
+
+var _contents2 = _interopRequireDefault(_contents);
+
+var _annotations = __webpack_require__(52);
+
+var _annotations2 = _interopRequireDefault(_annotations);
+
+var _constants = __webpack_require__(3);
+
+var _iframe = __webpack_require__(20);
+
+var _iframe2 = _interopRequireDefault(_iframe);
+
+var _index = __webpack_require__(14);
+
+var _index2 = _interopRequireDefault(_index);
+
+var _index3 = __webpack_require__(24);
+
+var _index4 = _interopRequireDefault(_index3);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+/**
+ * Displays an Epub as a series of Views for each Section.
+ * Requires Manager and View class to handle specifics of rendering
+ * the section contetn.
+ * @class
+ * @param {Book} book
+ * @param {object} [options]
+ * @param {number} [options.width]
+ * @param {number} [options.height]
+ * @param {string} [options.ignoreClass] class for the cfi parser to ignore
+ * @param {string | function | object} [options.manager='default']
+ * @param {string | function} [options.view='iframe']
+ * @param {string} [options.layout] layout to force
+ * @param {string} [options.spread] force spread value
+ * @param {number} [options.minSpreadWidth] overridden by spread: none (never) / both (always)
+ * @param {string} [options.stylesheet] url of stylesheet to be injected
+ * @param {string} [options.script] url of script to be injected
+ */
+var Rendition = function () {
+ function Rendition(book, options) {
+ _classCallCheck(this, Rendition);
+
+ this.settings = (0, _core.extend)(this.settings || {}, {
+ width: null,
+ height: null,
+ ignoreClass: "",
+ manager: "default",
+ view: "iframe",
+ flow: null,
+ layout: null,
+ spread: null,
+ minSpreadWidth: 800,
+ stylesheet: null,
+ script: null
+ });
+
+ (0, _core.extend)(this.settings, options);
+
+ if (_typeof(this.settings.manager) === "object") {
+ this.manager = this.settings.manager;
+ }
+
+ this.book = book;
+
+ /**
+ * Adds Hook methods to the Rendition prototype
+ * @member {object} hooks
+ * @property {Hook} hooks.content
+ * @memberof Rendition
+ */
+ this.hooks = {};
+ this.hooks.display = new _hook2.default(this);
+ this.hooks.serialize = new _hook2.default(this);
+ this.hooks.content = new _hook2.default(this);
+ this.hooks.unloaded = new _hook2.default(this);
+ this.hooks.layout = new _hook2.default(this);
+ this.hooks.render = new _hook2.default(this);
+ this.hooks.show = new _hook2.default(this);
+
+ this.hooks.content.register(this.handleLinks.bind(this));
+ this.hooks.content.register(this.passEvents.bind(this));
+ this.hooks.content.register(this.adjustImages.bind(this));
+
+ this.book.spine.hooks.content.register(this.injectIdentifier.bind(this));
+
+ if (this.settings.stylesheet) {
+ this.book.spine.hooks.content.register(this.injectStylesheet.bind(this));
+ }
+
+ if (this.settings.script) {
+ this.book.spine.hooks.content.register(this.injectScript.bind(this));
+ }
+
+ /**
+ * @member {Themes} themes
+ * @memberof Rendition
+ */
+ this.themes = new _themes2.default(this);
+
+ /**
+ * @member {Annotations} annotations
+ * @memberof Rendition
+ */
+ this.annotations = new _annotations2.default(this);
+
+ this.epubcfi = new _epubcfi2.default();
+
+ this.q = new _queue2.default(this);
+
+ /**
+ * A Rendered Location Range
+ * @typedef location
+ * @type {Object}
+ * @property {object} start
+ * @property {string} start.index
+ * @property {string} start.href
+ * @property {object} start.displayed
+ * @property {EpubCFI} start.cfi
+ * @property {number} start.location
+ * @property {number} start.percentage
+ * @property {number} start.displayed.page
+ * @property {number} start.displayed.total
+ * @property {object} end
+ * @property {string} end.index
+ * @property {string} end.href
+ * @property {object} end.displayed
+ * @property {EpubCFI} end.cfi
+ * @property {number} end.location
+ * @property {number} end.percentage
+ * @property {number} end.displayed.page
+ * @property {number} end.displayed.total
+ * @property {boolean} atStart
+ * @property {boolean} atEnd
+ * @memberof Rendition
+ */
+ this.location = undefined;
+
+ // Hold queue until book is opened
+ this.q.enqueue(this.book.opened);
+
+ this.starting = new _core.defer();
+ /**
+ * @member {promise} started returns after the rendition has started
+ * @memberof Rendition
+ */
+ this.started = this.starting.promise;
+ // Block the queue until rendering is started
+ this.q.enqueue(this.start);
+ }
+
+ /**
+ * Set the manager function
+ * @param {function} manager
+ */
+
+
+ _createClass(Rendition, [{
+ key: "setManager",
+ value: function setManager(manager) {
+ this.manager = manager;
+ }
+
+ /**
+ * Require the manager from passed string, or as a class function
+ * @param {string|object} manager [description]
+ * @return {method}
+ */
+
+ }, {
+ key: "requireManager",
+ value: function requireManager(manager) {
+ var viewManager;
+
+ // If manager is a string, try to load from imported managers
+ if (typeof manager === "string" && manager === "default") {
+ viewManager = _index2.default;
+ } else if (typeof manager === "string" && manager === "continuous") {
+ viewManager = _index4.default;
+ } else {
+ // otherwise, assume we were passed a class function
+ viewManager = manager;
+ }
+
+ return viewManager;
+ }
+
+ /**
+ * Require the view from passed string, or as a class function
+ * @param {string|object} view
+ * @return {view}
+ */
+
+ }, {
+ key: "requireView",
+ value: function requireView(view) {
+ var View;
+
+ // If view is a string, try to load from imported views,
+ if (typeof view == "string" && view === "iframe") {
+ View = _iframe2.default;
+ } else {
+ // otherwise, assume we were passed a class function
+ View = view;
+ }
+
+ return View;
+ }
+
+ /**
+ * Start the rendering
+ * @return {Promise} rendering has started
+ */
+
+ }, {
+ key: "start",
+ value: function start() {
+
+ if (!this.manager) {
+ this.ViewManager = this.requireManager(this.settings.manager);
+ this.View = this.requireView(this.settings.view);
+
+ this.manager = new this.ViewManager({
+ view: this.View,
+ queue: this.q,
+ request: this.book.load.bind(this.book),
+ settings: this.settings
+ });
+ }
+
+ this.direction(this.book.package.metadata.direction);
+
+ // Parse metadata to get layout props
+ this.settings.globalLayoutProperties = this.determineLayoutProperties(this.book.package.metadata);
+
+ this.flow(this.settings.globalLayoutProperties.flow);
+
+ this.layout(this.settings.globalLayoutProperties);
+
+ // Listen for displayed views
+ this.manager.on(_constants.EVENTS.MANAGERS.ADDED, this.afterDisplayed.bind(this));
+ this.manager.on(_constants.EVENTS.MANAGERS.REMOVED, this.afterRemoved.bind(this));
+
+ // Listen for resizing
+ this.manager.on(_constants.EVENTS.MANAGERS.RESIZED, this.onResized.bind(this));
+
+ // Listen for rotation
+ this.manager.on(_constants.EVENTS.MANAGERS.ORIENTATION_CHANGE, this.onOrientationChange.bind(this));
+
+ // Listen for scroll changes
+ this.manager.on(_constants.EVENTS.MANAGERS.SCROLLED, this.reportLocation.bind(this));
+
+ /**
+ * Emit that rendering has started
+ * @event started
+ * @memberof Rendition
+ */
+ this.emit(_constants.EVENTS.RENDITION.STARTED);
+
+ // Start processing queue
+ this.starting.resolve();
+ }
+
+ /**
+ * Call to attach the container to an element in the dom
+ * Container must be attached before rendering can begin
+ * @param {element} element to attach to
+ * @return {Promise}
+ */
+
+ }, {
+ key: "attachTo",
+ value: function attachTo(element) {
+
+ return this.q.enqueue(function () {
+
+ // Start rendering
+ this.manager.render(element, {
+ "width": this.settings.width,
+ "height": this.settings.height
+ });
+
+ /**
+ * Emit that rendering has attached to an element
+ * @event attached
+ * @memberof Rendition
+ */
+ this.emit(_constants.EVENTS.RENDITION.ATTACHED);
+ }.bind(this));
+ }
+
+ /**
+ * Display a point in the book
+ * The request will be added to the rendering Queue,
+ * so it will wait until book is opened, rendering started
+ * and all other rendering tasks have finished to be called.
+ * @param {string} target Url or EpubCFI
+ * @return {Promise}
+ */
+
+ }, {
+ key: "display",
+ value: function display(target) {
+ if (this.displaying) {
+ this.displaying.resolve();
+ }
+ return this.q.enqueue(this._display, target);
+ }
+
+ /**
+ * Tells the manager what to display immediately
+ * @private
+ * @param {string} target Url or EpubCFI
+ * @return {Promise}
+ */
+
+ }, {
+ key: "_display",
+ value: function _display(target) {
+ var _this = this;
+
+ if (!this.book) {
+ return;
+ }
+ var isCfiString = this.epubcfi.isCfiString(target);
+ var displaying = new _core.defer();
+ var displayed = displaying.promise;
+ var section;
+ var moveTo;
+
+ this.displaying = displaying;
+
+ // Check if this is a book percentage
+ if (this.book.locations.length() && ((0, _core.isFloat)(target) || target === "1.0") // Handle 1.0
+ ) {
+ target = this.book.locations.cfiFromPercentage(parseFloat(target));
+ }
+
+ section = this.book.spine.get(target);
+
+ if (!section) {
+ displaying.reject(new Error("No Section Found"));
+ return displayed;
+ }
+
+ this.manager.display(section, target).then(function () {
+ displaying.resolve(section);
+ _this.displaying = undefined;
+
+ /**
+ * Emit that a section has been displayed
+ * @event displayed
+ * @param {Section} section
+ * @memberof Rendition
+ */
+ _this.emit(_constants.EVENTS.RENDITION.DISPLAYED, section);
+ _this.reportLocation();
+ }, function (err) {
+ /**
+ * Emit that has been an error displaying
+ * @event displayError
+ * @param {Section} section
+ * @memberof Rendition
+ */
+ _this.emit(_constants.EVENTS.RENDITION.DISPLAY_ERROR, err);
+ });
+
+ return displayed;
+ }
+
+ /*
+ render(view, show) {
+ // view.onLayout = this.layout.format.bind(this.layout);
+ view.create();
+ // Fit to size of the container, apply padding
+ this.manager.resizeView(view);
+ // Render Chain
+ return view.section.render(this.book.request)
+ .then(function(contents){
+ return view.load(contents);
+ }.bind(this))
+ .then(function(doc){
+ return this.hooks.content.trigger(view, this);
+ }.bind(this))
+ .then(function(){
+ this.layout.format(view.contents);
+ return this.hooks.layout.trigger(view, this);
+ }.bind(this))
+ .then(function(){
+ return view.display();
+ }.bind(this))
+ .then(function(){
+ return this.hooks.render.trigger(view, this);
+ }.bind(this))
+ .then(function(){
+ if(show !== false) {
+ this.q.enqueue(function(view){
+ view.show();
+ }, view);
+ }
+ // this.map = new Map(view, this.layout);
+ this.hooks.show.trigger(view, this);
+ this.trigger("rendered", view.section);
+ }.bind(this))
+ .catch(function(e){
+ this.trigger("loaderror", e);
+ }.bind(this));
+ }
+ */
+
+ /**
+ * Report what section has been displayed
+ * @private
+ * @param {*} view
+ */
+
+ }, {
+ key: "afterDisplayed",
+ value: function afterDisplayed(view) {
+ var _this2 = this;
+
+ view.on(_constants.EVENTS.VIEWS.MARK_CLICKED, function (cfiRange, data) {
+ return _this2.triggerMarkEvent(cfiRange, data, view);
+ });
+
+ this.hooks.render.trigger(view, this).then(function () {
+ if (view.contents) {
+ _this2.hooks.content.trigger(view.contents, _this2).then(function () {
+ /**
+ * Emit that a section has been rendered
+ * @event rendered
+ * @param {Section} section
+ * @param {View} view
+ * @memberof Rendition
+ */
+ _this2.emit(_constants.EVENTS.RENDITION.RENDERED, view.section, view);
+ });
+ } else {
+ _this2.emit(_constants.EVENTS.RENDITION.RENDERED, view.section, view);
+ }
+ });
+ }
+
+ /**
+ * Report what has been removed
+ * @private
+ * @param {*} view
+ */
+
+ }, {
+ key: "afterRemoved",
+ value: function afterRemoved(view) {
+ var _this3 = this;
+
+ this.hooks.unloaded.trigger(view, this).then(function () {
+ /**
+ * Emit that a section has been removed
+ * @event removed
+ * @param {Section} section
+ * @param {View} view
+ * @memberof Rendition
+ */
+ _this3.emit(_constants.EVENTS.RENDITION.REMOVED, view.section, view);
+ });
+ }
+
+ /**
+ * Report resize events and display the last seen location
+ * @private
+ */
+
+ }, {
+ key: "onResized",
+ value: function onResized(size) {
+
+ /**
+ * Emit that the rendition has been resized
+ * @event resized
+ * @param {number} width
+ * @param {height} height
+ * @memberof Rendition
+ */
+ this.emit(_constants.EVENTS.RENDITION.RESIZED, {
+ width: size.width,
+ height: size.height
+ });
+
+ if (this.location && this.location.start) {
+ this.display(this.location.start.cfi);
+ }
+ }
+
+ /**
+ * Report orientation events and display the last seen location
+ * @private
+ */
+
+ }, {
+ key: "onOrientationChange",
+ value: function onOrientationChange(orientation) {
+ /**
+ * Emit that the rendition has been rotated
+ * @event orientationchange
+ * @param {string} orientation
+ * @memberof Rendition
+ */
+ this.emit(_constants.EVENTS.RENDITION.ORIENTATION_CHANGE, orientation);
+ }
+
+ /**
+ * Move the Rendition to a specific offset
+ * Usually you would be better off calling display()
+ * @param {object} offset
+ */
+
+ }, {
+ key: "moveTo",
+ value: function moveTo(offset) {
+ this.manager.moveTo(offset);
+ }
+
+ /**
+ * Trigger a resize of the views
+ * @param {number} [width]
+ * @param {number} [height]
+ */
+
+ }, {
+ key: "resize",
+ value: function resize(width, height) {
+ if (width) {
+ this.settings.width = width;
+ }
+ if (height) {
+ this.settings.height = height;
+ }
+ this.manager.resize(width, height);
+ }
+
+ /**
+ * Clear all rendered views
+ */
+
+ }, {
+ key: "clear",
+ value: function clear() {
+ this.manager.clear();
+ }
+
+ /**
+ * Go to the next "page" in the rendition
+ * @return {Promise}
+ */
+
+ }, {
+ key: "next",
+ value: function next() {
+ return this.q.enqueue(this.manager.next.bind(this.manager)).then(this.reportLocation.bind(this));
+ }
+
+ /**
+ * Go to the previous "page" in the rendition
+ * @return {Promise}
+ */
+
+ }, {
+ key: "prev",
+ value: function prev() {
+ return this.q.enqueue(this.manager.prev.bind(this.manager)).then(this.reportLocation.bind(this));
+ }
+
+ //-- http://www.idpf.org/epub/301/spec/epub-publications.html#meta-properties-rendering
+ /**
+ * Determine the Layout properties from metadata and settings
+ * @private
+ * @param {object} metadata
+ * @return {object} properties
+ */
+
+ }, {
+ key: "determineLayoutProperties",
+ value: function determineLayoutProperties(metadata) {
+ var properties;
+ var layout = this.settings.layout || metadata.layout || "reflowable";
+ var spread = this.settings.spread || metadata.spread || "auto";
+ var orientation = this.settings.orientation || metadata.orientation || "auto";
+ var flow = this.settings.flow || metadata.flow || "auto";
+ var viewport = metadata.viewport || "";
+ var minSpreadWidth = this.settings.minSpreadWidth || metadata.minSpreadWidth || 800;
+ var direction = this.settings.direction || metadata.direction || "ltr";
+
+ 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+"";
+ }
+
+ properties = {
+ layout: layout,
+ spread: spread,
+ orientation: orientation,
+ flow: flow,
+ viewport: viewport,
+ minSpreadWidth: minSpreadWidth,
+ direction: direction
+ };
+
+ return properties;
+ }
+
+ /**
+ * Adjust the flow of the rendition to paginated or scrolled
+ * (scrolled-continuous vs scrolled-doc are handled by different view managers)
+ * @param {string} flow
+ */
+
+ }, {
+ key: "flow",
+ value: function flow(_flow2) {
+ var _flow = _flow2;
+ if (_flow2 === "scrolled" || _flow2 === "scrolled-doc" || _flow2 === "scrolled-continuous") {
+ _flow = "scrolled";
+ }
+
+ if (_flow2 === "auto" || _flow2 === "paginated") {
+ _flow = "paginated";
+ }
+
+ this.settings.flow = _flow2;
+
+ if (this._layout) {
+ this._layout.flow(_flow);
+ }
+
+ if (this.manager && this._layout) {
+ this.manager.applyLayout(this._layout);
+ }
+
+ if (this.manager) {
+ this.manager.updateFlow(_flow);
+ }
+
+ if (this.manager && this.manager.isRendered() && this.location) {
+ this.manager.clear();
+ this.display(this.location.start.cfi);
+ }
+ }
+
+ /**
+ * Adjust the layout of the rendition to reflowable or pre-paginated
+ * @param {object} settings
+ */
+
+ }, {
+ key: "layout",
+ value: function layout(settings) {
+ var _this4 = this;
+
+ if (settings) {
+ this._layout = new _layout2.default(settings);
+ this._layout.spread(settings.spread, this.settings.minSpreadWidth);
+
+ // this.mapping = new Mapping(this._layout.props);
+
+ this._layout.on(_constants.EVENTS.LAYOUT.UPDATED, function (props, changed) {
+ _this4.emit(_constants.EVENTS.RENDITION.LAYOUT, props, changed);
+ });
+ }
+
+ if (this.manager && this._layout) {
+ this.manager.applyLayout(this._layout);
+ }
+
+ return this._layout;
+ }
+
+ /**
+ * Adjust if the rendition uses spreads
+ * @param {string} spread none | auto (TODO: implement landscape, portrait, both)
+ * @param {int} min min width to use spreads at
+ */
+
+ }, {
+ key: "spread",
+ value: function spread(_spread, min) {
+
+ this._layout.spread(_spread, min);
+
+ if (this.manager.isRendered()) {
+ this.manager.updateLayout();
+ }
+ }
+
+ /**
+ * Adjust the direction of the rendition
+ * @param {string} dir
+ */
+
+ }, {
+ key: "direction",
+ value: function direction(dir) {
+
+ this.settings.direction = dir || "ltr";
+
+ if (this.manager) {
+ this.manager.direction(this.settings.direction);
+ }
+
+ if (this.manager && this.manager.isRendered() && this.location) {
+ this.manager.clear();
+ this.display(this.location.start.cfi);
+ }
+ }
+
+ /**
+ * Report the current location
+ * @fires relocated
+ * @fires locationChanged
+ */
+
+ }, {
+ key: "reportLocation",
+ value: function reportLocation() {
+ return this.q.enqueue(function reportedLocation() {
+ requestAnimationFrame(function reportedLocationAfterRAF() {
+ var location = this.manager.currentLocation();
+ if (location && location.then && typeof location.then === "function") {
+ location.then(function (result) {
+ var located = this.located(result);
+
+ if (!located || !located.start || !located.end) {
+ return;
+ }
+
+ this.location = located;
+
+ this.emit(_constants.EVENTS.RENDITION.LOCATION_CHANGED, {
+ index: this.location.start.index,
+ href: this.location.start.href,
+ start: this.location.start.cfi,
+ end: this.location.end.cfi,
+ percentage: this.location.start.percentage
+ });
+
+ this.emit(_constants.EVENTS.RENDITION.RELOCATED, this.location);
+ }.bind(this));
+ } else if (location) {
+ var located = this.located(location);
+
+ if (!located || !located.start || !located.end) {
+ return;
+ }
+
+ this.location = located;
+
+ /**
+ * @event locationChanged
+ * @deprecated
+ * @type {object}
+ * @property {number} index
+ * @property {string} href
+ * @property {EpubCFI} start
+ * @property {EpubCFI} end
+ * @property {number} percentage
+ * @memberof Rendition
+ */
+ this.emit(_constants.EVENTS.RENDITION.LOCATION_CHANGED, {
+ index: this.location.start.index,
+ href: this.location.start.href,
+ start: this.location.start.cfi,
+ end: this.location.end.cfi,
+ percentage: this.location.start.percentage
+ });
+
+ /**
+ * @event relocated
+ * @type {displayedLocation}
+ * @memberof Rendition
+ */
+ this.emit(_constants.EVENTS.RENDITION.RELOCATED, this.location);
+ }
+ }.bind(this));
+ }.bind(this));
+ }
+
+ /**
+ * Get the Current Location object
+ * @return {displayedLocation | promise} location (may be a promise)
+ */
+
+ }, {
+ key: "currentLocation",
+ value: function currentLocation() {
+ var location = this.manager.currentLocation();
+ if (location && location.then && typeof location.then === "function") {
+ location.then(function (result) {
+ var located = this.located(result);
+ return located;
+ }.bind(this));
+ } else if (location) {
+ var located = this.located(location);
+ return located;
+ }
+ }
+
+ /**
+ * Creates a Rendition#locationRange from location
+ * passed by the Manager
+ * @returns {displayedLocation}
+ * @private
+ */
+
+ }, {
+ key: "located",
+ value: function located(location) {
+ if (!location.length) {
+ return {};
+ }
+ var start = location[0];
+ var end = location[location.length - 1];
+
+ var located = {
+ start: {
+ index: start.index,
+ href: start.href,
+ cfi: start.mapping.start,
+ displayed: {
+ page: start.pages[0] || 1,
+ total: start.totalPages
+ }
+ },
+ end: {
+ index: end.index,
+ href: end.href,
+ cfi: end.mapping.end,
+ displayed: {
+ page: end.pages[end.pages.length - 1] || 1,
+ total: end.totalPages
+ }
+ }
+ };
+
+ var locationStart = this.book.locations.locationFromCfi(start.mapping.start);
+ var locationEnd = this.book.locations.locationFromCfi(end.mapping.end);
+
+ if (locationStart != null) {
+ located.start.location = locationStart;
+ located.start.percentage = this.book.locations.percentageFromLocation(locationStart);
+ }
+ if (locationEnd != null) {
+ located.end.location = locationEnd;
+ located.end.percentage = this.book.locations.percentageFromLocation(locationEnd);
+ }
+
+ var pageStart = this.book.pageList.pageFromCfi(start.mapping.start);
+ var pageEnd = this.book.pageList.pageFromCfi(end.mapping.end);
+
+ if (pageStart != -1) {
+ located.start.page = pageStart;
+ }
+ if (pageEnd != -1) {
+ located.end.page = pageEnd;
+ }
+
+ if (end.index === this.book.spine.last().index && located.end.displayed.page >= located.end.displayed.total) {
+ located.atEnd = true;
+ }
+
+ if (start.index === this.book.spine.first().index && located.start.displayed.page === 1) {
+ located.atStart = true;
+ }
+
+ return located;
+ }
+
+ /**
+ * Remove and Clean Up the Rendition
+ */
+
+ }, {
+ key: "destroy",
+ value: function destroy() {
+ // Clear the queue
+ // this.q.clear();
+ // this.q = undefined;
+
+ this.manager && this.manager.destroy();
+
+ this.book = undefined;
+
+ // this.views = null;
+
+ // this.hooks.display.clear();
+ // this.hooks.serialize.clear();
+ // this.hooks.content.clear();
+ // this.hooks.layout.clear();
+ // this.hooks.render.clear();
+ // this.hooks.show.clear();
+ // this.hooks = {};
+
+ // this.themes.destroy();
+ // this.themes = undefined;
+
+ // this.epubcfi = undefined;
+
+ // this.starting = undefined;
+ // this.started = undefined;
+
+ }
+
+ /**
+ * Pass the events from a view's Contents
+ * @private
+ * @param {View} view
+ */
+
+ }, {
+ key: "passEvents",
+ value: function passEvents(contents) {
+ var _this5 = this;
+
+ var listenedEvents = _contents2.default.listenedEvents;
+
+ listenedEvents.forEach(function (e) {
+ contents.on(e, function (ev) {
+ return _this5.triggerViewEvent(ev, contents);
+ });
+ });
+
+ contents.on(_constants.EVENTS.CONTENTS.SELECTED, function (e) {
+ return _this5.triggerSelectedEvent(e, contents);
+ });
+ }
+
+ /**
+ * Emit events passed by a view
+ * @private
+ * @param {event} e
+ */
+
+ }, {
+ key: "triggerViewEvent",
+ value: function triggerViewEvent(e, contents) {
+ this.emit(e.type, e, contents);
+ }
+
+ /**
+ * Emit a selection event's CFI Range passed from a a view
+ * @private
+ * @param {EpubCFI} cfirange
+ */
+
+ }, {
+ key: "triggerSelectedEvent",
+ value: function triggerSelectedEvent(cfirange, contents) {
+ /**
+ * Emit that a text selection has occured
+ * @event selected
+ * @param {EpubCFI} cfirange
+ * @param {Contents} contents
+ * @memberof Rendition
+ */
+ this.emit(_constants.EVENTS.RENDITION.SELECTED, cfirange, contents);
+ }
+
+ /**
+ * Emit a markClicked event with the cfiRange and data from a mark
+ * @private
+ * @param {EpubCFI} cfirange
+ */
+
+ }, {
+ key: "triggerMarkEvent",
+ value: function triggerMarkEvent(cfiRange, data, contents) {
+ /**
+ * Emit that a mark was clicked
+ * @event markClicked
+ * @param {EpubCFI} cfirange
+ * @param {object} data
+ * @param {Contents} contents
+ * @memberof Rendition
+ */
+ this.emit(_constants.EVENTS.RENDITION.MARK_CLICKED, cfiRange, data, contents);
+ }
+
+ /**
+ * Get a Range from a Visible CFI
+ * @param {string} cfi EpubCfi String
+ * @param {string} ignoreClass
+ * @return {range}
+ */
+
+ }, {
+ key: "getRange",
+ value: function getRange(cfi, ignoreClass) {
+ var _cfi = new _epubcfi2.default(cfi);
+ var found = this.manager.visible().filter(function (view) {
+ if (_cfi.spinePos === view.index) return true;
+ });
+
+ // Should only every return 1 item
+ if (found.length) {
+ return found[0].contents.range(_cfi, ignoreClass);
+ }
+ }
+
+ /**
+ * Hook to adjust images to fit in columns
+ * @param {Contents} contents
+ * @private
+ */
+
+ }, {
+ key: "adjustImages",
+ value: function adjustImages(contents) {
+
+ if (this._layout.name === "pre-paginated") {
+ return new Promise(function (resolve) {
+ resolve();
+ });
+ }
+
+ contents.addStylesheetRules({
+ "img": {
+ "max-width": (this._layout.columnWidth ? this._layout.columnWidth + "px" : "100%") + "!important",
+ "max-height": (this._layout.height ? this._layout.height * 0.6 + "px" : "60%") + "!important",
+ "object-fit": "contain",
+ "page-break-inside": "avoid"
+ },
+ "svg": {
+ "max-width": (this._layout.columnWidth ? this._layout.columnWidth + "px" : "100%") + "!important",
+ "max-height": (this._layout.height ? this._layout.height * 0.6 + "px" : "60%") + "!important",
+ "page-break-inside": "avoid"
+ }
+ });
+
+ return new Promise(function (resolve, reject) {
+ // Wait to apply
+ setTimeout(function () {
+ resolve();
+ }, 1);
+ });
+ }
+
+ /**
+ * Get the Contents object of each rendered view
+ * @returns {Contents[]}
+ */
+
+ }, {
+ key: "getContents",
+ value: function getContents() {
+ return this.manager ? this.manager.getContents() : [];
+ }
+
+ /**
+ * Get the views member from the manager
+ * @returns {Views}
+ */
+
+ }, {
+ key: "views",
+ value: function views() {
+ var views = this.manager ? this.manager.views : undefined;
+ return views || [];
+ }
+
+ /**
+ * Hook to handle link clicks in rendered content
+ * @param {Contents} contents
+ * @private
+ */
+
+ }, {
+ key: "handleLinks",
+ value: function handleLinks(contents) {
+ var _this6 = this;
+
+ if (contents) {
+ contents.on(_constants.EVENTS.CONTENTS.LINK_CLICKED, function (href) {
+ var relative = _this6.book.path.relative(href);
+ _this6.display(relative);
+ });
+ }
+ }
+
+ /**
+ * Hook to handle injecting stylesheet before
+ * a Section is serialized
+ * @param {document} doc
+ * @param {Section} section
+ * @private
+ */
+
+ }, {
+ key: "injectStylesheet",
+ value: function injectStylesheet(doc, section) {
+ var style = doc.createElement("link");
+ style.setAttribute("type", "text/css");
+ style.setAttribute("rel", "stylesheet");
+ style.setAttribute("href", this.settings.stylesheet);
+ doc.getElementsByTagName("head")[0].appendChild(style);
+ }
+
+ /**
+ * Hook to handle injecting scripts before
+ * a Section is serialized
+ * @param {document} doc
+ * @param {Section} section
+ * @private
+ */
+
+ }, {
+ key: "injectScript",
+ value: function injectScript(doc, section) {
+ var script = doc.createElement("script");
+ script.setAttribute("type", "text/javascript");
+ script.setAttribute("src", this.settings.script);
+ script.textContent = " "; // Needed to prevent self closing tag
+ doc.getElementsByTagName("head")[0].appendChild(script);
+ }
+
+ /**
+ * Hook to handle the document identifier before
+ * a Section is serialized
+ * @param {document} doc
+ * @param {Section} section
+ * @private
+ */
+
+ }, {
+ key: "injectIdentifier",
+ value: function injectIdentifier(doc, section) {
+ var ident = this.book.package.metadata.identifier;
+ var meta = doc.createElement("meta");
+ meta.setAttribute("name", "dc.relation.ispartof");
+ if (ident) {
+ meta.setAttribute("content", ident);
+ }
+ doc.getElementsByTagName("head")[0].appendChild(meta);
+ }
+ }]);
+
+ return Rendition;
+}();
+
+//-- Enable binding events to Renderer
+
+
+(0, _eventEmitter2.default)(Rendition.prototype);
+
+exports.default = Rendition;
+module.exports = exports["default"];
+
+/***/ }),
+/* 19 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+
+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; }; }();
+
+var _epubcfi = __webpack_require__(1);
+
+var _epubcfi2 = _interopRequireDefault(_epubcfi);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+/**
+ * Map text locations to CFI ranges
+ * @class
+ */
+var Mapping = function () {
+ function Mapping(layout, direction, axis, dev) {
+ _classCallCheck(this, Mapping);
+
+ this.layout = layout;
+ this.horizontal = axis === "horizontal" ? true : false;
+ this.direction = direction || "ltr";
+ this._dev = dev;
+ }
+
+ /**
+ * Find CFI pairs for entire section at once
+ */
+
+
+ _createClass(Mapping, [{
+ key: "section",
+ value: function section(view) {
+ var ranges = this.findRanges(view);
+ var map = this.rangeListToCfiList(view.section.cfiBase, ranges);
+
+ return map;
+ }
+
+ /**
+ * Find CFI pairs for a page
+ */
+
+ }, {
+ key: "page",
+ value: function page(contents, cfiBase, start, end) {
+ var root = contents && contents.document ? contents.document.body : false;
+ var result;
+
+ if (!root) {
+ return;
+ }
+
+ result = this.rangePairToCfiPair(cfiBase, {
+ start: this.findStart(root, start, end),
+ end: this.findEnd(root, start, end)
+ });
+
+ if (this._dev === true) {
+ var doc = contents.document;
+ var startRange = new _epubcfi2.default(result.start).toRange(doc);
+ var endRange = new _epubcfi2.default(result.end).toRange(doc);
+
+ var selection = doc.defaultView.getSelection();
+ var r = doc.createRange();
+ selection.removeAllRanges();
+ r.setStart(startRange.startContainer, startRange.startOffset);
+ r.setEnd(endRange.endContainer, endRange.endOffset);
+ selection.addRange(r);
+ }
+
+ return result;
+ }
+ }, {
+ key: "walk",
+ value: function walk(root, func) {
+ // IE11 has strange issue, if root is text node IE throws exception on
+ // calling treeWalker.nextNode(), saying
+ // Unexpected call to method or property access instead of returing null value
+ if (root && root.nodeType === Node.TEXT_NODE) {
+ return;
+ }
+ // safeFilter is required so that it can work in IE as filter is a function for IE
+ // and for other browser filter is an object.
+ var filter = {
+ acceptNode: function acceptNode(node) {
+ if (node.data.trim().length > 0) {
+ return NodeFilter.FILTER_ACCEPT;
+ } else {
+ return NodeFilter.FILTER_REJECT;
+ }
+ }
+ };
+ var safeFilter = filter.acceptNode;
+ safeFilter.acceptNode = filter.acceptNode;
+
+ var treeWalker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT, safeFilter, false);
+ var node;
+ var result;
+ while (node = treeWalker.nextNode()) {
+ result = func(node);
+ if (result) break;
+ }
+
+ return result;
+ }
+ }, {
+ key: "findRanges",
+ value: function findRanges(view) {
+ var columns = [];
+ var scrollWidth = view.contents.scrollWidth();
+ var spreads = Math.ceil(scrollWidth / this.layout.spreadWidth);
+ var count = spreads * this.layout.divisor;
+ var columnWidth = this.layout.columnWidth;
+ var gap = this.layout.gap;
+ var start, end;
+
+ for (var i = 0; i < count.pages; i++) {
+ start = (columnWidth + gap) * i;
+ end = columnWidth * (i + 1) + gap * i;
+ columns.push({
+ start: this.findStart(view.document.body, start, end),
+ end: this.findEnd(view.document.body, start, end)
+ });
+ }
+
+ return columns;
+ }
+ }, {
+ key: "findStart",
+ value: function findStart(root, start, end) {
+ var _this = this;
+
+ var stack = [root];
+ var $el;
+ var found;
+ var $prev = root;
+
+ while (stack.length) {
+
+ $el = stack.shift();
+
+ found = this.walk($el, function (node) {
+ var left, right, top, bottom;
+ var elPos;
+ var elRange;
+
+ elPos = _this.getBounds(node);
+
+ if (_this.horizontal && _this.direction === "ltr") {
+
+ left = _this.horizontal ? elPos.left : elPos.top;
+ right = _this.horizontal ? elPos.right : elPos.bottom;
+
+ if (left >= start && left <= end) {
+ return node;
+ } else if (right > start) {
+ return node;
+ } else {
+ $prev = node;
+ stack.push(node);
+ }
+ } else if (_this.horizontal && _this.direction === "rtl") {
+
+ left = elPos.left;
+ right = elPos.right;
+
+ if (right <= end && right >= start) {
+ return node;
+ } else if (left < end) {
+ return node;
+ } else {
+ $prev = node;
+ stack.push(node);
+ }
+ } else {
+
+ top = elPos.top;
+ bottom = elPos.bottom;
+
+ if (top >= start && top <= end) {
+ return node;
+ } else if (bottom > start) {
+ return node;
+ } else {
+ $prev = node;
+ stack.push(node);
+ }
+ }
+ });
+
+ if (found) {
+ return this.findTextStartRange(found, start, end);
+ }
+ }
+
+ // Return last element
+ return this.findTextStartRange($prev, start, end);
+ }
+ }, {
+ key: "findEnd",
+ value: function findEnd(root, start, end) {
+ var _this2 = this;
+
+ var stack = [root];
+ var $el;
+ var $prev = root;
+ var found;
+
+ while (stack.length) {
+
+ $el = stack.shift();
+
+ found = this.walk($el, function (node) {
+
+ var left, right, top, bottom;
+ var elPos;
+ var elRange;
+
+ elPos = _this2.getBounds(node);
+
+ if (_this2.horizontal && _this2.direction === "ltr") {
+
+ left = Math.round(elPos.left);
+ right = Math.round(elPos.right);
+
+ if (left > end && $prev) {
+ return $prev;
+ } else if (right > end) {
+ return node;
+ } else {
+ $prev = node;
+ stack.push(node);
+ }
+ } else if (_this2.horizontal && _this2.direction === "rtl") {
+
+ left = Math.round(_this2.horizontal ? elPos.left : elPos.top);
+ right = Math.round(_this2.horizontal ? elPos.right : elPos.bottom);
+
+ if (right < start && $prev) {
+ return $prev;
+ } else if (left < start) {
+ return node;
+ } else {
+ $prev = node;
+ stack.push(node);
+ }
+ } else {
+
+ top = Math.round(elPos.top);
+ bottom = Math.round(elPos.bottom);
+
+ if (top > end && $prev) {
+ return $prev;
+ } else if (bottom > end) {
+ return node;
+ } else {
+ $prev = node;
+ stack.push(node);
+ }
+ }
+ });
+
+ if (found) {
+ return this.findTextEndRange(found, start, end);
+ }
+ }
+
+ // end of chapter
+ return this.findTextEndRange($prev, start, end);
+ }
+ }, {
+ key: "findTextStartRange",
+ value: function findTextStartRange(node, start, end) {
+ var ranges = this.splitTextNodeIntoRanges(node);
+ var range;
+ var pos;
+ var left, top, right;
+
+ for (var i = 0; i < ranges.length; i++) {
+ range = ranges[i];
+
+ pos = range.getBoundingClientRect();
+
+ if (this.horizontal && this.direction === "ltr") {
+
+ left = pos.left;
+ if (left >= start) {
+ return range;
+ }
+ } else if (this.horizontal && this.direction === "rtl") {
+
+ right = pos.right;
+ if (right <= end) {
+ return range;
+ }
+ } else {
+
+ top = pos.top;
+ if (top >= start) {
+ return range;
+ }
+ }
+
+ // prev = range;
+ }
+
+ return ranges[0];
+ }
+ }, {
+ key: "findTextEndRange",
+ value: function findTextEndRange(node, start, end) {
+ var ranges = this.splitTextNodeIntoRanges(node);
+ var prev;
+ var range;
+ var pos;
+ var left, right, top, bottom;
+
+ for (var i = 0; i < ranges.length; i++) {
+ range = ranges[i];
+
+ pos = range.getBoundingClientRect();
+
+ if (this.horizontal && this.direction === "ltr") {
+
+ left = pos.left;
+ right = pos.right;
+
+ if (left > end && prev) {
+ return prev;
+ } else if (right > end) {
+ return range;
+ }
+ } else if (this.horizontal && this.direction === "rtl") {
+
+ left = pos.left;
+ right = pos.right;
+
+ if (right < start && prev) {
+ return prev;
+ } else if (left < start) {
+ return range;
+ }
+ } else {
+
+ top = pos.top;
+ bottom = pos.bottom;
+
+ if (top > end && prev) {
+ return prev;
+ } else if (bottom > end) {
+ return range;
+ }
+ }
+
+ prev = range;
+ }
+
+ // Ends before limit
+ return ranges[ranges.length - 1];
+ }
+ }, {
+ key: "splitTextNodeIntoRanges",
+ value: function splitTextNodeIntoRanges(node, _splitter) {
+ var ranges = [];
+ var textContent = node.textContent || "";
+ var text = textContent.trim();
+ var range;
+ var doc = node.ownerDocument;
+ var splitter = _splitter || " ";
+
+ var pos = text.indexOf(splitter);
+
+ if (pos === -1 || node.nodeType != Node.TEXT_NODE) {
+ range = doc.createRange();
+ range.selectNodeContents(node);
+ return [range];
+ }
+
+ range = doc.createRange();
+ range.setStart(node, 0);
+ range.setEnd(node, pos);
+ ranges.push(range);
+ range = false;
+
+ while (pos != -1) {
+
+ pos = text.indexOf(splitter, pos + 1);
+ if (pos > 0) {
+
+ if (range) {
+ range.setEnd(node, pos);
+ ranges.push(range);
+ }
+
+ range = doc.createRange();
+ range.setStart(node, pos + 1);
+ }
+ }
+
+ if (range) {
+ range.setEnd(node, text.length);
+ ranges.push(range);
+ }
+
+ return ranges;
+ }
+ }, {
+ key: "rangePairToCfiPair",
+ value: function rangePairToCfiPair(cfiBase, rangePair) {
+
+ var startRange = rangePair.start;
+ var endRange = rangePair.end;
+
+ startRange.collapse(true);
+ endRange.collapse(false);
+
+ var startCfi = new _epubcfi2.default(startRange, cfiBase).toString();
+ var endCfi = new _epubcfi2.default(endRange, cfiBase).toString();
+
+ return {
+ start: startCfi,
+ end: endCfi
+ };
+ }
+ }, {
+ key: "rangeListToCfiList",
+ value: function rangeListToCfiList(cfiBase, columns) {
+ var map = [];
+ var cifPair;
+
+ for (var i = 0; i < columns.length; i++) {
+ cifPair = this.rangePairToCfiPair(cfiBase, columns[i]);
+
+ map.push(cifPair);
+ }
+
+ return map;
+ }
+ }, {
+ key: "getBounds",
+ value: function getBounds(node) {
+ var elPos = void 0;
+ if (node.nodeType == Node.TEXT_NODE) {
+ var elRange = document.createRange();
+ elRange.selectNodeContents(node);
+ elPos = elRange.getBoundingClientRect();
+ } else {
+ elPos = node.getBoundingClientRect();
+ }
+ return elPos;
+ }
+ }, {
+ key: "axis",
+ value: function axis(_axis) {
+ if (_axis) {
+ this.horizontal = _axis === "horizontal" ? true : false;
+ }
+ return this.horizontal;
+ }
+ }]);
+
+ return Mapping;
+}();
+
+exports.default = Mapping;
+module.exports = exports["default"];
+
+/***/ }),
+/* 20 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+
+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; }; }();
+
+var _eventEmitter = __webpack_require__(2);
+
+var _eventEmitter2 = _interopRequireDefault(_eventEmitter);
+
+var _core = __webpack_require__(0);
+
+var _epubcfi = __webpack_require__(1);
+
+var _epubcfi2 = _interopRequireDefault(_epubcfi);
+
+var _contents = __webpack_require__(13);
+
+var _contents2 = _interopRequireDefault(_contents);
+
+var _constants = __webpack_require__(3);
+
+var _marksPane = __webpack_require__(53);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+var IframeView = function () {
+ function IframeView(section, options) {
+ _classCallCheck(this, IframeView);
+
+ this.settings = (0, _core.extend)({
+ ignoreClass: "",
+ axis: options.layout && options.layout.props.flow === "scrolled" ? "vertical" : "horizontal",
+ direction: undefined,
+ width: 0,
+ height: 0,
+ layout: undefined,
+ globalLayoutProperties: {},
+ method: undefined
+ }, options || {});
+
+ this.id = "epubjs-view-" + (0, _core.uuid)();
+ this.section = section;
+ this.index = section.index;
+
+ this.element = this.container(this.settings.axis);
+
+ this.added = false;
+ this.displayed = false;
+ this.rendered = false;
+
+ // this.width = this.settings.width;
+ // this.height = this.settings.height;
+
+ this.fixedWidth = 0;
+ this.fixedHeight = 0;
+
+ // Blank Cfi for Parsing
+ this.epubcfi = new _epubcfi2.default();
+
+ this.layout = this.settings.layout;
+ // Dom events to listen for
+ // this.listenedEvents = ["keydown", "keyup", "keypressed", "mouseup", "mousedown", "click", "touchend", "touchstart"];
+
+ this.pane = undefined;
+ this.highlights = {};
+ this.underlines = {};
+ this.marks = {};
+ }
+
+ _createClass(IframeView, [{
+ key: "container",
+ value: function container(axis) {
+ var element = document.createElement("div");
+
+ element.classList.add("epub-view");
+
+ // this.element.style.minHeight = "100px";
+ element.style.height = "0px";
+ element.style.width = "0px";
+ element.style.overflow = "hidden";
+ element.style.position = "relative";
+ element.style.display = "block";
+
+ if (axis && axis == "horizontal") {
+ element.style.flex = "none";
+ } else {
+ element.style.flex = "initial";
+ }
+
+ return element;
+ }
+ }, {
+ key: "create",
+ value: function create() {
+
+ if (this.iframe) {
+ return this.iframe;
+ }
+
+ if (!this.element) {
+ this.element = this.createContainer();
+ }
+
+ this.iframe = document.createElement("iframe");
+ this.iframe.id = this.id;
+ this.iframe.scrolling = "no"; // Might need to be removed: breaks ios width calculations
+ this.iframe.style.overflow = "hidden";
+ this.iframe.seamless = "seamless";
+ // Back up if seamless isn't supported
+ this.iframe.style.border = "none";
+
+ this.iframe.setAttribute("enable-annotation", "true");
+
+ this.resizing = true;
+
+ // this.iframe.style.display = "none";
+ this.element.style.visibility = "hidden";
+ this.iframe.style.visibility = "hidden";
+
+ this.iframe.style.width = "0";
+ this.iframe.style.height = "0";
+ this._width = 0;
+ this._height = 0;
+
+ this.element.setAttribute("ref", this.index);
+
+ this.element.appendChild(this.iframe);
+ this.added = true;
+
+ this.elementBounds = (0, _core.bounds)(this.element);
+
+ // if(width || height){
+ // this.resize(width, height);
+ // } else if(this.width && this.height){
+ // this.resize(this.width, this.height);
+ // } else {
+ // this.iframeBounds = bounds(this.iframe);
+ // }
+
+
+ if ("srcdoc" in this.iframe) {
+ this.supportsSrcdoc = true;
+ } else {
+ this.supportsSrcdoc = false;
+ }
+
+ if (!this.settings.method) {
+ this.settings.method = this.supportsSrcdoc ? "srcdoc" : "write";
+ }
+
+ return this.iframe;
+ }
+ }, {
+ key: "render",
+ value: function render(request, show) {
+
+ // view.onLayout = this.layout.format.bind(this.layout);
+ this.create();
+
+ // Fit to size of the container, apply padding
+ this.size();
+
+ if (!this.sectionRender) {
+ this.sectionRender = this.section.render(request);
+ }
+
+ // Render Chain
+ return this.sectionRender.then(function (contents) {
+ return this.load(contents);
+ }.bind(this)).then(function () {
+ var _this = this;
+
+ // apply the layout function to the contents
+ this.layout.format(this.contents);
+
+ // find and report the writingMode axis
+ var writingMode = this.contents.writingMode();
+ var axis = writingMode.indexOf("vertical") === 0 ? "vertical" : "horizontal";
+
+ this.setAxis(axis);
+ this.emit(_constants.EVENTS.VIEWS.AXIS, axis);
+
+ // Listen for events that require an expansion of the iframe
+ this.addListeners();
+
+ return new Promise(function (resolve, reject) {
+ // Expand the iframe to the full size of the content
+ _this.expand();
+ resolve();
+ });
+ }.bind(this), function (e) {
+ this.emit(_constants.EVENTS.VIEWS.LOAD_ERROR, e);
+ return new Promise(function (resolve, reject) {
+ reject(e);
+ });
+ }.bind(this)).then(function () {
+ this.emit(_constants.EVENTS.VIEWS.RENDERED, this.section);
+ }.bind(this));
+ }
+ }, {
+ key: "reset",
+ value: function reset() {
+ if (this.iframe) {
+ this.iframe.style.width = "0";
+ this.iframe.style.height = "0";
+ this._width = 0;
+ this._height = 0;
+ this._textWidth = undefined;
+ this._contentWidth = undefined;
+ this._textHeight = undefined;
+ this._contentHeight = undefined;
+ }
+ this._needsReframe = true;
+ }
+
+ // Determine locks base on settings
+
+ }, {
+ key: "size",
+ value: function size(_width, _height) {
+ var width = _width || this.settings.width;
+ var height = _height || this.settings.height;
+
+ if (this.layout.name === "pre-paginated") {
+ this.lock("both", width, height);
+ } else if (this.settings.axis === "horizontal") {
+ this.lock("height", width, height);
+ } else {
+ this.lock("width", width, height);
+ }
+
+ this.settings.width = width;
+ this.settings.height = height;
+ }
+
+ // Lock an axis to element dimensions, taking borders into account
+
+ }, {
+ key: "lock",
+ value: function lock(what, width, height) {
+ var elBorders = (0, _core.borders)(this.element);
+ var iframeBorders;
+
+ if (this.iframe) {
+ iframeBorders = (0, _core.borders)(this.iframe);
+ } else {
+ iframeBorders = { width: 0, height: 0 };
+ }
+
+ if (what == "width" && (0, _core.isNumber)(width)) {
+ this.lockedWidth = width - elBorders.width - iframeBorders.width;
+ // this.resize(this.lockedWidth, width); // width keeps ratio correct
+ }
+
+ if (what == "height" && (0, _core.isNumber)(height)) {
+ this.lockedHeight = height - elBorders.height - iframeBorders.height;
+ // this.resize(width, this.lockedHeight);
+ }
+
+ if (what === "both" && (0, _core.isNumber)(width) && (0, _core.isNumber)(height)) {
+
+ this.lockedWidth = width - elBorders.width - iframeBorders.width;
+ this.lockedHeight = height - elBorders.height - iframeBorders.height;
+ // this.resize(this.lockedWidth, this.lockedHeight);
+ }
+
+ if (this.displayed && this.iframe) {
+
+ // this.contents.layout();
+ this.expand();
+ }
+ }
+
+ // Resize a single axis based on content dimensions
+
+ }, {
+ key: "expand",
+ value: function expand(force) {
+ var width = this.lockedWidth;
+ var height = this.lockedHeight;
+ var columns;
+
+ var textWidth, textHeight;
+
+ if (!this.iframe || this._expanding) return;
+
+ this._expanding = true;
+
+ if (this.layout.name === "pre-paginated") {
+ width = this.layout.columnWidth;
+ height = this.layout.height;
+ }
+ // Expand Horizontally
+ else if (this.settings.axis === "horizontal") {
+ // Get the width of the text
+ width = this.contents.textWidth();
+
+ if (width % this.layout.pageWidth > 0) {
+ width = Math.ceil(width / this.layout.pageWidth) * this.layout.pageWidth;
+ }
+
+ if (this.settings.forceEvenPages) {
+ columns = width / this.layout.delta;
+ if (this.layout.divisor > 1 && this.layout.name === "reflowable" && columns % 2 > 0) {
+ // add a blank page
+ width += this.layout.gap + this.layout.columnWidth;
+ }
+ }
+ } // Expand Vertically
+ else if (this.settings.axis === "vertical") {
+ height = this.contents.textHeight();
+ }
+
+ // Only Resize if dimensions have changed or
+ // if Frame is still hidden, so needs reframing
+ if (this._needsReframe || width != this._width || height != this._height) {
+ this.reframe(width, height);
+ }
+
+ this._expanding = false;
+ }
+ }, {
+ key: "reframe",
+ value: function reframe(width, height) {
+ var size;
+
+ if ((0, _core.isNumber)(width)) {
+ this.element.style.width = width + "px";
+ this.iframe.style.width = width + "px";
+ this._width = width;
+ }
+
+ if ((0, _core.isNumber)(height)) {
+ this.element.style.height = height + "px";
+ this.iframe.style.height = height + "px";
+ this._height = height;
+ }
+
+ var widthDelta = this.prevBounds ? width - this.prevBounds.width : width;
+ var heightDelta = this.prevBounds ? height - this.prevBounds.height : height;
+
+ size = {
+ width: width,
+ height: height,
+ widthDelta: widthDelta,
+ heightDelta: heightDelta
+ };
+
+ this.pane && this.pane.render();
+
+ this.onResize(this, size);
+
+ this.emit(_constants.EVENTS.VIEWS.RESIZED, size);
+
+ this.prevBounds = size;
+
+ this.elementBounds = (0, _core.bounds)(this.element);
+ }
+ }, {
+ key: "load",
+ value: function load(contents) {
+ var loading = new _core.defer();
+ var loaded = loading.promise;
+
+ if (!this.iframe) {
+ loading.reject(new Error("No Iframe Available"));
+ return loaded;
+ }
+
+ this.iframe.onload = function (event) {
+
+ this.onLoad(event, loading);
+ }.bind(this);
+
+ if (this.settings.method === "blobUrl") {
+ this.blobUrl = (0, _core.createBlobUrl)(contents, "application/xhtml+xml");
+ this.iframe.src = this.blobUrl;
+ } else if (this.settings.method === "srcdoc") {
+ this.iframe.srcdoc = contents;
+ } else {
+
+ this.document = this.iframe.contentDocument;
+
+ if (!this.document) {
+ loading.reject(new Error("No Document Available"));
+ return loaded;
+ }
+
+ this.iframe.contentDocument.open();
+ this.iframe.contentDocument.write(contents);
+ this.iframe.contentDocument.close();
+ }
+
+ return loaded;
+ }
+ }, {
+ key: "onLoad",
+ value: function onLoad(event, promise) {
+ var _this2 = this;
+
+ this.window = this.iframe.contentWindow;
+ this.document = this.iframe.contentDocument;
+
+ this.contents = new _contents2.default(this.document, this.document.body, this.section.cfiBase, this.section.index);
+
+ this.rendering = false;
+
+ var link = this.document.querySelector("link[rel='canonical']");
+ if (link) {
+ link.setAttribute("href", this.section.canonical);
+ } else {
+ link = this.document.createElement("link");
+ link.setAttribute("rel", "canonical");
+ link.setAttribute("href", this.section.canonical);
+ this.document.querySelector("head").appendChild(link);
+ }
+
+ this.contents.on(_constants.EVENTS.CONTENTS.EXPAND, function () {
+ if (_this2.displayed && _this2.iframe) {
+ _this2.expand();
+ if (_this2.contents) {
+ _this2.layout.format(_this2.contents);
+ }
+ }
+ });
+
+ this.contents.on(_constants.EVENTS.CONTENTS.RESIZE, function (e) {
+ if (_this2.displayed && _this2.iframe) {
+ _this2.expand();
+ if (_this2.contents) {
+ _this2.layout.format(_this2.contents);
+ }
+ }
+ });
+
+ promise.resolve(this.contents);
+ }
+ }, {
+ key: "setLayout",
+ value: function setLayout(layout) {
+ this.layout = layout;
+
+ if (this.contents) {
+ this.layout.format(this.contents);
+ this.expand();
+ }
+ }
+ }, {
+ key: "setAxis",
+ value: function setAxis(axis) {
+
+ // Force vertical for scrolled
+ if (this.layout.props.flow === "scrolled") {
+ axis = "vertical";
+ }
+
+ this.settings.axis = axis;
+
+ if (axis == "horizontal") {
+ this.element.style.flex = "none";
+ } else {
+ this.element.style.flex = "initial";
+ }
+
+ this.size();
+ }
+ }, {
+ key: "addListeners",
+ value: function addListeners() {
+ //TODO: Add content listeners for expanding
+ }
+ }, {
+ key: "removeListeners",
+ value: function removeListeners(layoutFunc) {
+ //TODO: remove content listeners for expanding
+ }
+ }, {
+ key: "display",
+ value: function display(request) {
+ var displayed = new _core.defer();
+
+ if (!this.displayed) {
+
+ this.render(request).then(function () {
+
+ this.emit(_constants.EVENTS.VIEWS.DISPLAYED, this);
+ this.onDisplayed(this);
+
+ this.displayed = true;
+ displayed.resolve(this);
+ }.bind(this), function (err) {
+ displayed.reject(err, this);
+ });
+ } else {
+ displayed.resolve(this);
+ }
+
+ return displayed.promise;
+ }
+ }, {
+ key: "show",
+ value: function show() {
+
+ this.element.style.visibility = "visible";
+
+ if (this.iframe) {
+ this.iframe.style.visibility = "visible";
+ }
+
+ this.emit(_constants.EVENTS.VIEWS.SHOWN, this);
+ }
+ }, {
+ key: "hide",
+ value: function hide() {
+ // this.iframe.style.display = "none";
+ this.element.style.visibility = "hidden";
+ this.iframe.style.visibility = "hidden";
+
+ this.stopExpanding = true;
+ this.emit(_constants.EVENTS.VIEWS.HIDDEN, this);
+ }
+ }, {
+ key: "offset",
+ value: function offset() {
+ return {
+ top: this.element.offsetTop,
+ left: this.element.offsetLeft
+ };
+ }
+ }, {
+ key: "width",
+ value: function width() {
+ return this._width;
+ }
+ }, {
+ key: "height",
+ value: function height() {
+ return this._height;
+ }
+ }, {
+ key: "position",
+ value: function position() {
+ return this.element.getBoundingClientRect();
+ }
+ }, {
+ key: "locationOf",
+ value: function locationOf(target) {
+ var parentPos = this.iframe.getBoundingClientRect();
+ var targetPos = this.contents.locationOf(target, this.settings.ignoreClass);
+
+ return {
+ "left": targetPos.left,
+ "top": targetPos.top
+ };
+ }
+ }, {
+ key: "onDisplayed",
+ value: function onDisplayed(view) {
+ // Stub, override with a custom functions
+ }
+ }, {
+ key: "onResize",
+ value: function onResize(view, e) {
+ // Stub, override with a custom functions
+ }
+ }, {
+ key: "bounds",
+ value: function bounds(force) {
+ if (force || !this.elementBounds) {
+ this.elementBounds = (0, _core.bounds)(this.element);
+ }
+
+ return this.elementBounds;
+ }
+ }, {
+ key: "highlight",
+ value: function highlight(cfiRange) {
+ var _this3 = this;
+
+ var data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
+ var cb = arguments[2];
+
+ if (!this.contents) {
+ return;
+ }
+ var range = this.contents.range(cfiRange);
+
+ var emitter = function emitter() {
+ _this3.emit(_constants.EVENTS.VIEWS.MARK_CLICKED, cfiRange, data);
+ };
+
+ data["epubcfi"] = cfiRange;
+
+ if (!this.pane) {
+ this.pane = new _marksPane.Pane(this.iframe, this.element);
+ }
+
+ var m = new _marksPane.Highlight(range, "epubjs-hl", data, { 'fill': 'yellow', 'fill-opacity': '0.3', 'mix-blend-mode': 'multiply' });
+ var h = this.pane.addMark(m);
+
+ this.highlights[cfiRange] = { "mark": h, "element": h.element, "listeners": [emitter, cb] };
+
+ h.element.setAttribute("ref", "epubjs-hl");
+ h.element.addEventListener("click", emitter);
+ h.element.addEventListener("touchstart", emitter);
+
+ if (cb) {
+ h.element.addEventListener("click", cb);
+ h.element.addEventListener("touchstart", cb);
+ }
+ return h;
+ }
+ }, {
+ key: "underline",
+ value: function underline(cfiRange) {
+ var _this4 = this;
+
+ var data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
+ var cb = arguments[2];
+
+ if (!this.contents) {
+ return;
+ }
+ var range = this.contents.range(cfiRange);
+ var emitter = function emitter() {
+ _this4.emit(_constants.EVENTS.VIEWS.MARK_CLICKED, cfiRange, data);
+ };
+
+ data["epubcfi"] = cfiRange;
+
+ if (!this.pane) {
+ this.pane = new _marksPane.Pane(this.iframe, this.element);
+ }
+
+ var m = new _marksPane.Underline(range, "epubjs-ul", data, { 'stroke': 'black', 'stroke-opacity': '0.3', 'mix-blend-mode': 'multiply' });
+ var h = this.pane.addMark(m);
+
+ this.underlines[cfiRange] = { "mark": h, "element": h.element, "listeners": [emitter, cb] };
+
+ h.element.setAttribute("ref", "epubjs-ul");
+ h.element.addEventListener("click", emitter);
+ h.element.addEventListener("touchstart", emitter);
+
+ if (cb) {
+ h.element.addEventListener("click", cb);
+ h.element.addEventListener("touchstart", cb);
+ }
+ return h;
+ }
+ }, {
+ key: "mark",
+ value: function mark(cfiRange) {
+ var _this5 = this;
+
+ var data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
+ var cb = arguments[2];
+
+
+ if (!this.contents) {
+ return;
+ }
+
+ if (cfiRange in this.marks) {
+ var item = this.marks[cfiRange];
+ return item;
+ }
+
+ var range = this.contents.range(cfiRange);
+ if (!range) {
+ return;
+ }
+ var container = range.commonAncestorContainer;
+ var parent = container.nodeType === 1 ? container : container.parentNode;
+
+ var emitter = function emitter(e) {
+ _this5.emit(_constants.EVENTS.VIEWS.MARK_CLICKED, cfiRange, data);
+ };
+
+ if (range.collapsed && container.nodeType === 1) {
+ range = new Range();
+ range.selectNodeContents(container);
+ } else if (range.collapsed) {
+ // Webkit doesn't like collapsed ranges
+ range = new Range();
+ range.selectNodeContents(parent);
+ }
+
+ var top = void 0,
+ right = void 0,
+ left = void 0;
+
+ if (this.layout.name === "pre-paginated" || this.settings.axis !== "horizontal") {
+ var pos = range.getBoundingClientRect();
+ top = pos.top;
+ right = pos.right;
+ } else {
+ // Element might break columns, so find the left most element
+ var rects = range.getClientRects();
+ var rect = void 0;
+ for (var i = 0; i != rects.length; i++) {
+ rect = rects[i];
+ if (!left || rect.left < left) {
+ left = rect.left;
+ right = left + this.layout.columnWidth - this.layout.gap;
+ top = rect.top;
+ }
+ }
+ }
+
+ var mark = this.document.createElement('a');
+ mark.setAttribute("ref", "epubjs-mk");
+ mark.style.position = "absolute";
+ mark.style.top = top + "px";
+ mark.style.left = right + "px";
+
+ mark.dataset["epubcfi"] = cfiRange;
+
+ if (data) {
+ Object.keys(data).forEach(function (key) {
+ mark.dataset[key] = data[key];
+ });
+ }
+
+ if (cb) {
+ mark.addEventListener("click", cb);
+ mark.addEventListener("touchstart", cb);
+ }
+
+ mark.addEventListener("click", emitter);
+ mark.addEventListener("touchstart", emitter);
+
+ this.element.appendChild(mark);
+
+ this.marks[cfiRange] = { "element": mark, "listeners": [emitter, cb] };
+
+ return parent;
+ }
+ }, {
+ key: "unhighlight",
+ value: function unhighlight(cfiRange) {
+ var item = void 0;
+ if (cfiRange in this.highlights) {
+ item = this.highlights[cfiRange];
+
+ this.pane.removeMark(item.mark);
+ item.listeners.forEach(function (l) {
+ if (l) {
+ item.element.removeEventListener("click", l);
+ };
+ });
+ delete this.highlights[cfiRange];
+ }
+ }
+ }, {
+ key: "ununderline",
+ value: function ununderline(cfiRange) {
+ var item = void 0;
+ if (cfiRange in this.underlines) {
+ item = this.underlines[cfiRange];
+ this.pane.removeMark(item.mark);
+ item.listeners.forEach(function (l) {
+ if (l) {
+ item.element.removeEventListener("click", l);
+ };
+ });
+ delete this.underlines[cfiRange];
+ }
+ }
+ }, {
+ key: "unmark",
+ value: function unmark(cfiRange) {
+ var item = void 0;
+ if (cfiRange in this.marks) {
+ item = this.marks[cfiRange];
+ this.element.removeChild(item.element);
+ item.listeners.forEach(function (l) {
+ if (l) {
+ item.element.removeEventListener("click", l);
+ };
+ });
+ delete this.marks[cfiRange];
+ }
+ }
+ }, {
+ key: "destroy",
+ value: function destroy() {
+
+ for (var cfiRange in this.highlights) {
+ this.unhighlight(cfiRange);
+ }
+
+ for (var _cfiRange in this.underlines) {
+ this.ununderline(_cfiRange);
+ }
+
+ for (var _cfiRange2 in this.marks) {
+ this.unmark(_cfiRange2);
+ }
+
+ if (this.blobUrl) {
+ (0, _core.revokeBlobUrl)(this.blobUrl);
+ }
+
+ if (this.displayed) {
+ this.displayed = false;
+
+ this.removeListeners();
+
+ this.stopExpanding = true;
+ this.element.removeChild(this.iframe);
+
+ this.iframe = undefined;
+ this.contents = undefined;
+
+ this._textWidth = null;
+ this._textHeight = null;
+ this._width = null;
+ this._height = null;
+ }
+
+ // this.element.style.height = "0px";
+ // this.element.style.width = "0px";
+ }
+ }]);
+
+ return IframeView;
+}();
+
+(0, _eventEmitter2.default)(IframeView.prototype);
+
+exports.default = IframeView;
+module.exports = exports["default"];
+
+/***/ }),
+/* 21 */
+/***/ (function(module, exports, __webpack_require__) {
+
+var isObject = __webpack_require__(15),
+ now = __webpack_require__(58),
+ toNumber = __webpack_require__(60);
+
+/** Error message constants. */
+var FUNC_ERROR_TEXT = 'Expected a function';
+
+/* Built-in method references for those with the same name as other `lodash` methods. */
+var nativeMax = Math.max,
+ nativeMin = Math.min;
+
+/**
+ * Creates a debounced function that delays invoking `func` until after `wait`
+ * milliseconds have elapsed since the last time the debounced function was
+ * invoked. The debounced function comes with a `cancel` method to cancel
+ * delayed `func` invocations and a `flush` method to immediately invoke them.
+ * Provide `options` to indicate whether `func` should be invoked on the
+ * leading and/or trailing edge of the `wait` timeout. The `func` is invoked
+ * with the last arguments provided to the debounced function. Subsequent
+ * calls to the debounced function return the result of the last `func`
+ * invocation.
+ *
+ * **Note:** If `leading` and `trailing` options are `true`, `func` is
+ * invoked on the trailing edge of the timeout only if the debounced function
+ * is invoked more than once during the `wait` timeout.
+ *
+ * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred
+ * until to the next tick, similar to `setTimeout` with a timeout of `0`.
+ *
+ * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/)
+ * for details over the differences between `_.debounce` and `_.throttle`.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Function
+ * @param {Function} func The function to debounce.
+ * @param {number} [wait=0] The number of milliseconds to delay.
+ * @param {Object} [options={}] The options object.
+ * @param {boolean} [options.leading=false]
+ * Specify invoking on the leading edge of the timeout.
+ * @param {number} [options.maxWait]
+ * The maximum time `func` is allowed to be delayed before it's invoked.
+ * @param {boolean} [options.trailing=true]
+ * Specify invoking on the trailing edge of the timeout.
+ * @returns {Function} Returns the new debounced function.
+ * @example
+ *
+ * // Avoid costly calculations while the window size is in flux.
+ * jQuery(window).on('resize', _.debounce(calculateLayout, 150));
+ *
+ * // Invoke `sendMail` when clicked, debouncing subsequent calls.
+ * jQuery(element).on('click', _.debounce(sendMail, 300, {
+ * 'leading': true,
+ * 'trailing': false
+ * }));
+ *
+ * // Ensure `batchLog` is invoked once after 1 second of debounced calls.
+ * var debounced = _.debounce(batchLog, 250, { 'maxWait': 1000 });
+ * var source = new EventSource('/stream');
+ * jQuery(source).on('message', debounced);
+ *
+ * // Cancel the trailing debounced invocation.
+ * jQuery(window).on('popstate', debounced.cancel);
+ */
+function debounce(func, wait, options) {
+ var lastArgs,
+ lastThis,
+ maxWait,
+ result,
+ timerId,
+ lastCallTime,
+ lastInvokeTime = 0,
+ leading = false,
+ maxing = false,
+ trailing = true;
+
+ if (typeof func != 'function') {
+ throw new TypeError(FUNC_ERROR_TEXT);
+ }
+ wait = toNumber(wait) || 0;
+ if (isObject(options)) {
+ leading = !!options.leading;
+ maxing = 'maxWait' in options;
+ maxWait = maxing ? nativeMax(toNumber(options.maxWait) || 0, wait) : maxWait;
+ trailing = 'trailing' in options ? !!options.trailing : trailing;
+ }
+
+ function invokeFunc(time) {
+ var args = lastArgs,
+ thisArg = lastThis;
+
+ lastArgs = lastThis = undefined;
+ lastInvokeTime = time;
+ result = func.apply(thisArg, args);
+ return result;
+ }
+
+ function leadingEdge(time) {
+ // Reset any `maxWait` timer.
+ lastInvokeTime = time;
+ // Start the timer for the trailing edge.
+ timerId = setTimeout(timerExpired, wait);
+ // Invoke the leading edge.
+ return leading ? invokeFunc(time) : result;
+ }
+
+ function remainingWait(time) {
+ var timeSinceLastCall = time - lastCallTime,
+ timeSinceLastInvoke = time - lastInvokeTime,
+ timeWaiting = wait - timeSinceLastCall;
+
+ return maxing
+ ? nativeMin(timeWaiting, maxWait - timeSinceLastInvoke)
+ : timeWaiting;
+ }
+
+ function shouldInvoke(time) {
+ var timeSinceLastCall = time - lastCallTime,
+ timeSinceLastInvoke = time - lastInvokeTime;
+
+ // Either this is the first call, activity has stopped and we're at the
+ // trailing edge, the system time has gone backwards and we're treating
+ // it as the trailing edge, or we've hit the `maxWait` limit.
+ return (lastCallTime === undefined || (timeSinceLastCall >= wait) ||
+ (timeSinceLastCall < 0) || (maxing && timeSinceLastInvoke >= maxWait));
+ }
+
+ function timerExpired() {
+ var time = now();
+ if (shouldInvoke(time)) {
+ return trailingEdge(time);
+ }
+ // Restart the timer.
+ timerId = setTimeout(timerExpired, remainingWait(time));
+ }
+
+ function trailingEdge(time) {
+ timerId = undefined;
+
+ // Only invoke if we have `lastArgs` which means `func` has been
+ // debounced at least once.
+ if (trailing && lastArgs) {
+ return invokeFunc(time);
+ }
+ lastArgs = lastThis = undefined;
+ return result;
+ }
+
+ function cancel() {
+ if (timerId !== undefined) {
+ clearTimeout(timerId);
+ }
+ lastInvokeTime = 0;
+ lastArgs = lastCallTime = lastThis = timerId = undefined;
+ }
+
+ function flush() {
+ return timerId === undefined ? result : trailingEdge(now());
+ }
+
+ function debounced() {
+ var time = now(),
+ isInvoking = shouldInvoke(time);
+
+ lastArgs = arguments;
+ lastThis = this;
+ lastCallTime = time;
+
+ if (isInvoking) {
+ if (timerId === undefined) {
+ return leadingEdge(lastCallTime);
+ }
+ if (maxing) {
+ // Handle invocations in a tight loop.
+ timerId = setTimeout(timerExpired, wait);
+ return invokeFunc(lastCallTime);
+ }
+ }
+ if (timerId === undefined) {
+ timerId = setTimeout(timerExpired, wait);
+ }
+ return result;
+ }
+ debounced.cancel = cancel;
+ debounced.flush = flush;
+ return debounced;
+}
+
+module.exports = debounce;
+
+
+/***/ }),
+/* 22 */
+/***/ (function(module, exports, __webpack_require__) {
+
+var freeGlobal = __webpack_require__(59);
+
+/** Detect free variable `self`. */
+var freeSelf = typeof self == 'object' && self && self.Object === Object && self;
+
+/** Used as a reference to the global object. */
+var root = freeGlobal || freeSelf || Function('return this')();
+
+module.exports = root;
+
+
+/***/ }),
+/* 23 */
+/***/ (function(module, exports, __webpack_require__) {
+
+var root = __webpack_require__(22);
+
+/** Built-in value references. */
+var Symbol = root.Symbol;
+
+module.exports = Symbol;
+
+
+/***/ }),
+/* 24 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+
+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; }; }();
+
+var _core = __webpack_require__(0);
+
+var _default = __webpack_require__(14);
+
+var _default2 = _interopRequireDefault(_default);
+
+var _constants = __webpack_require__(3);
+
+var _debounce = __webpack_require__(21);
+
+var _debounce2 = _interopRequireDefault(_debounce);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+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; }
+
+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; }
+
+var ContinuousViewManager = function (_DefaultViewManager) {
+ _inherits(ContinuousViewManager, _DefaultViewManager);
+
+ function ContinuousViewManager(options) {
+ _classCallCheck(this, ContinuousViewManager);
+
+ var _this = _possibleConstructorReturn(this, (ContinuousViewManager.__proto__ || Object.getPrototypeOf(ContinuousViewManager)).call(this, options));
+
+ _this.name = "continuous";
+
+ _this.settings = (0, _core.extend)(_this.settings || {}, {
+ infinite: true,
+ overflow: undefined,
+ axis: undefined,
+ flow: "scrolled",
+ offset: 500,
+ offsetDelta: 250,
+ width: undefined,
+ height: undefined
+ });
+
+ (0, _core.extend)(_this.settings, options.settings || {});
+
+ // Gap can be 0, but defaults doesn't handle that
+ if (options.settings.gap != "undefined" && options.settings.gap === 0) {
+ _this.settings.gap = options.settings.gap;
+ }
+
+ _this.viewSettings = {
+ ignoreClass: _this.settings.ignoreClass,
+ axis: _this.settings.axis,
+ flow: _this.settings.flow,
+ layout: _this.layout,
+ width: 0,
+ height: 0,
+ forceEvenPages: false
+ };
+
+ _this.scrollTop = 0;
+ _this.scrollLeft = 0;
+ return _this;
+ }
+
+ _createClass(ContinuousViewManager, [{
+ key: "display",
+ value: function display(section, target) {
+ return _default2.default.prototype.display.call(this, section, target).then(function () {
+ return this.fill();
+ }.bind(this));
+ }
+ }, {
+ key: "fill",
+ value: function fill(_full) {
+ var _this2 = this;
+
+ var full = _full || new _core.defer();
+
+ this.q.enqueue(function () {
+ return _this2.check();
+ }).then(function (result) {
+ if (result) {
+ _this2.fill(full);
+ } else {
+ full.resolve();
+ }
+ });
+
+ return full.promise;
+ }
+ }, {
+ key: "moveTo",
+ value: function moveTo(offset) {
+ // var bounds = this.stage.bounds();
+ // var dist = Math.floor(offset.top / bounds.height) * bounds.height;
+ var distX = 0,
+ distY = 0;
+
+ var offsetX = 0,
+ offsetY = 0;
+
+ if (!this.isPaginated) {
+ distY = offset.top;
+ offsetY = offset.top + this.settings.offset;
+ } else {
+ distX = Math.floor(offset.left / this.layout.delta) * this.layout.delta;
+ offsetX = distX + this.settings.offset;
+ }
+
+ if (distX > 0 || distY > 0) {
+ this.scrollBy(distX, distY, true);
+ }
+ }
+ }, {
+ key: "afterResized",
+ value: function afterResized(view) {
+ this.emit(_constants.EVENTS.MANAGERS.RESIZE, view.section);
+ }
+
+ // Remove Previous Listeners if present
+
+ }, {
+ key: "removeShownListeners",
+ value: function removeShownListeners(view) {
+
+ // view.off("shown", this.afterDisplayed);
+ // view.off("shown", this.afterDisplayedAbove);
+ view.onDisplayed = function () {};
+ }
+ }, {
+ key: "add",
+ value: function add(section) {
+ var _this3 = this;
+
+ var view = this.createView(section);
+
+ this.views.append(view);
+
+ view.on(_constants.EVENTS.VIEWS.RESIZED, function (bounds) {
+ view.expanded = true;
+ });
+
+ view.on(_constants.EVENTS.VIEWS.AXIS, function (axis) {
+ _this3.updateAxis(axis);
+ });
+
+ // view.on(EVENTS.VIEWS.SHOWN, this.afterDisplayed.bind(this));
+ view.onDisplayed = this.afterDisplayed.bind(this);
+ view.onResize = this.afterResized.bind(this);
+
+ return view.display(this.request);
+ }
+ }, {
+ key: "append",
+ value: function append(section) {
+ var view = this.createView(section);
+
+ view.on(_constants.EVENTS.VIEWS.RESIZED, function (bounds) {
+ view.expanded = true;
+ });
+
+ /*
+ view.on(EVENTS.VIEWS.AXIS, (axis) => {
+ this.updateAxis(axis);
+ });
+ */
+
+ this.views.append(view);
+
+ view.onDisplayed = this.afterDisplayed.bind(this);
+
+ return view;
+ }
+ }, {
+ key: "prepend",
+ value: function prepend(section) {
+ var _this4 = this;
+
+ var view = this.createView(section);
+
+ view.on(_constants.EVENTS.VIEWS.RESIZED, function (bounds) {
+ _this4.counter(bounds);
+ view.expanded = true;
+ });
+
+ /*
+ view.on(EVENTS.VIEWS.AXIS, (axis) => {
+ this.updateAxis(axis);
+ });
+ */
+
+ this.views.prepend(view);
+
+ view.onDisplayed = this.afterDisplayed.bind(this);
+
+ return view;
+ }
+ }, {
+ key: "counter",
+ value: function counter(bounds) {
+ if (this.settings.axis === "vertical") {
+ this.scrollBy(0, bounds.heightDelta, true);
+ } else {
+ this.scrollBy(bounds.widthDelta, 0, true);
+ }
+ }
+ }, {
+ key: "update",
+ value: function update(_offset) {
+ var container = this.bounds();
+ var views = this.views.all();
+ var viewsLength = views.length;
+ var visible = [];
+ var offset = typeof _offset != "undefined" ? _offset : this.settings.offset || 0;
+ var isVisible;
+ var view;
+
+ var updating = new _core.defer();
+ var promises = [];
+ for (var i = 0; i < viewsLength; i++) {
+ view = views[i];
+
+ isVisible = this.isVisible(view, offset, offset, container);
+
+ if (isVisible === true) {
+ // console.log("visible " + view.index);
+
+ if (!view.displayed) {
+ var displayed = view.display(this.request).then(function (view) {
+ view.show();
+ }, function (err) {
+ view.hide();
+ });
+ promises.push(displayed);
+ } else {
+ view.show();
+ }
+ visible.push(view);
+ } else {
+ this.q.enqueue(view.destroy.bind(view));
+ // console.log("hidden " + view.index);
+
+ clearTimeout(this.trimTimeout);
+ this.trimTimeout = setTimeout(function () {
+ this.q.enqueue(this.trim.bind(this));
+ }.bind(this), 250);
+ }
+ }
+
+ if (promises.length) {
+ return Promise.all(promises).catch(function (err) {
+ updating.reject(err);
+ });
+ } else {
+ updating.resolve();
+ return updating.promise;
+ }
+ }
+ }, {
+ key: "check",
+ value: function check(_offsetLeft, _offsetTop) {
+ var _this5 = this;
+
+ var checking = new _core.defer();
+ var newViews = [];
+
+ var horizontal = this.settings.axis === "horizontal";
+ var delta = this.settings.offset || 0;
+
+ if (_offsetLeft && horizontal) {
+ delta = _offsetLeft;
+ }
+
+ if (_offsetTop && !horizontal) {
+ delta = _offsetTop;
+ }
+
+ var bounds = this._bounds; // bounds saved this until resize
+
+ var rtl = this.settings.direction === "rtl";
+ var dir = horizontal && rtl ? -1 : 1; //RTL reverses scrollTop
+
+ var offset = horizontal ? this.scrollLeft : this.scrollTop * dir;
+ var visibleLength = horizontal ? bounds.width : bounds.height;
+ var contentLength = horizontal ? this.container.scrollWidth : this.container.scrollHeight;
+
+ var prepend = function prepend() {
+ var first = _this5.views.first();
+ var prev = first && first.section.prev();
+
+ if (prev) {
+ newViews.push(_this5.prepend(prev));
+ }
+ };
+
+ var append = function append() {
+ var last = _this5.views.last();
+ var next = last && last.section.next();
+
+ if (next) {
+ newViews.push(_this5.append(next));
+ }
+ };
+
+ if (offset + visibleLength + delta >= contentLength) {
+ if (horizontal && rtl) {
+ prepend();
+ } else {
+ append();
+ }
+ }
+
+ if (offset - delta < 0) {
+ if (horizontal && rtl) {
+ append();
+ } else {
+ prepend();
+ }
+ }
+
+ var promises = newViews.map(function (view) {
+ return view.displayed;
+ });
+
+ if (newViews.length) {
+ return Promise.all(promises).then(function () {
+ if (_this5.layout.name === "pre-paginated" && _this5.layout.props.spread) {
+ return _this5.check();
+ }
+ }).then(function () {
+ // Check to see if anything new is on screen after rendering
+ return _this5.update(delta);
+ }, function (err) {
+ return err;
+ });
+ } else {
+ this.q.enqueue(function () {
+ this.update();
+ }.bind(this));
+ checking.resolve(false);
+ return checking.promise;
+ }
+ }
+ }, {
+ key: "trim",
+ value: function trim() {
+ var task = new _core.defer();
+ var displayed = this.views.displayed();
+ var first = displayed[0];
+ var last = displayed[displayed.length - 1];
+ var firstIndex = this.views.indexOf(first);
+ var lastIndex = this.views.indexOf(last);
+ var above = this.views.slice(0, firstIndex);
+ var below = this.views.slice(lastIndex + 1);
+
+ // Erase all but last above
+ for (var i = 0; i < above.length - 1; i++) {
+ this.erase(above[i], above);
+ }
+
+ // Erase all except first below
+ for (var j = 1; j < below.length; j++) {
+ this.erase(below[j]);
+ }
+
+ task.resolve();
+ return task.promise;
+ }
+ }, {
+ key: "erase",
+ value: function erase(view, above) {
+ //Trim
+
+ var prevTop;
+ var prevLeft;
+
+ if (this.settings.height) {
+ prevTop = this.container.scrollTop;
+ prevLeft = this.container.scrollLeft;
+ } else {
+ prevTop = window.scrollY;
+ prevLeft = window.scrollX;
+ }
+
+ var bounds = view.bounds();
+
+ this.views.remove(view);
+
+ if (above) {
+ if (this.settings.axis === "vertical") {
+ this.scrollTo(0, prevTop - bounds.height, true);
+ } else {
+ this.scrollTo(prevLeft - bounds.width, 0, true);
+ }
+ }
+ }
+ }, {
+ key: "addEventListeners",
+ value: function addEventListeners(stage) {
+
+ window.addEventListener("unload", function (e) {
+ this.ignore = true;
+ // this.scrollTo(0,0);
+ this.destroy();
+ }.bind(this));
+
+ this.addScrollListeners();
+ }
+ }, {
+ key: "addScrollListeners",
+ value: function addScrollListeners() {
+ var scroller;
+
+ this.tick = _core.requestAnimationFrame;
+
+ if (this.settings.height) {
+ this.prevScrollTop = this.container.scrollTop;
+ this.prevScrollLeft = this.container.scrollLeft;
+ } else {
+ this.prevScrollTop = window.scrollY;
+ this.prevScrollLeft = window.scrollX;
+ }
+
+ this.scrollDeltaVert = 0;
+ this.scrollDeltaHorz = 0;
+
+ if (this.settings.height) {
+ scroller = this.container;
+ this.scrollTop = this.container.scrollTop;
+ this.scrollLeft = this.container.scrollLeft;
+ } else {
+ scroller = window;
+ this.scrollTop = window.scrollY;
+ this.scrollLeft = window.scrollX;
+ }
+
+ scroller.addEventListener("scroll", this.onScroll.bind(this));
+ this._scrolled = (0, _debounce2.default)(this.scrolled.bind(this), 30);
+ // this.tick.call(window, this.onScroll.bind(this));
+
+ this.didScroll = false;
+ }
+ }, {
+ key: "removeEventListeners",
+ value: function removeEventListeners() {
+ var scroller;
+
+ if (this.settings.height) {
+ scroller = this.container;
+ } else {
+ scroller = window;
+ }
+
+ scroller.removeEventListener("scroll", this.onScroll.bind(this));
+ }
+ }, {
+ key: "onScroll",
+ value: function onScroll() {
+ var scrollTop = void 0;
+ var scrollLeft = void 0;
+ var dir = this.settings.direction === "rtl" ? -1 : 1;
+
+ if (this.settings.height) {
+ scrollTop = this.container.scrollTop;
+ scrollLeft = this.container.scrollLeft;
+ } else {
+ scrollTop = window.scrollY * dir;
+ scrollLeft = window.scrollX * dir;
+ }
+
+ this.scrollTop = scrollTop;
+ this.scrollLeft = scrollLeft;
+
+ if (!this.ignore) {
+
+ this._scrolled();
+ } else {
+ this.ignore = false;
+ }
+
+ this.scrollDeltaVert += Math.abs(scrollTop - this.prevScrollTop);
+ this.scrollDeltaHorz += Math.abs(scrollLeft - this.prevScrollLeft);
+
+ this.prevScrollTop = scrollTop;
+ this.prevScrollLeft = scrollLeft;
+
+ clearTimeout(this.scrollTimeout);
+ this.scrollTimeout = setTimeout(function () {
+ this.scrollDeltaVert = 0;
+ this.scrollDeltaHorz = 0;
+ }.bind(this), 150);
+
+ this.didScroll = false;
+ }
+ }, {
+ key: "scrolled",
+ value: function scrolled() {
+ this.q.enqueue(function () {
+ this.check();
+ }.bind(this));
+
+ this.emit(_constants.EVENTS.MANAGERS.SCROLL, {
+ top: this.scrollTop,
+ left: this.scrollLeft
+ });
+
+ clearTimeout(this.afterScrolled);
+ this.afterScrolled = setTimeout(function () {
+ this.emit(_constants.EVENTS.MANAGERS.SCROLLED, {
+ top: this.scrollTop,
+ left: this.scrollLeft
+ });
+ }.bind(this));
+ }
+ }, {
+ key: "next",
+ value: function next() {
+
+ var dir = this.settings.direction;
+ var delta = this.layout.props.name === "pre-paginated" && this.layout.props.spread ? this.layout.props.delta * 2 : this.layout.props.delta;
+
+ if (!this.views.length) return;
+
+ if (this.isPaginated && this.settings.axis === "horizontal") {
+
+ this.scrollBy(delta, 0, true);
+ } else {
+
+ this.scrollBy(0, this.layout.height, true);
+ }
+
+ this.q.enqueue(function () {
+ this.check();
+ }.bind(this));
+ }
+ }, {
+ key: "prev",
+ value: function prev() {
+
+ var dir = this.settings.direction;
+ var delta = this.layout.props.name === "pre-paginated" && this.layout.props.spread ? this.layout.props.delta * 2 : this.layout.props.delta;
+
+ if (!this.views.length) return;
+
+ if (this.isPaginated && this.settings.axis === "horizontal") {
+
+ this.scrollBy(-delta, 0, true);
+ } else {
+
+ this.scrollBy(0, -this.layout.height, true);
+ }
+
+ this.q.enqueue(function () {
+ this.check();
+ }.bind(this));
+ }
+ }, {
+ key: "updateAxis",
+ value: function updateAxis(axis, forceUpdate) {
+
+ if (!this.isPaginated) {
+ axis = "vertical";
+ }
+
+ if (!forceUpdate && axis === this.settings.axis) {
+ return;
+ }
+
+ this.settings.axis = axis;
+
+ this.stage && this.stage.axis(axis);
+
+ this.viewSettings.axis = axis;
+
+ if (this.mapping) {
+ this.mapping.axis(axis);
+ }
+
+ if (this.layout) {
+ if (axis === "vertical") {
+ this.layout.spread("none");
+ } else {
+ this.layout.spread(this.layout.settings.spread);
+ }
+ }
+
+ if (axis === "vertical") {
+ this.settings.infinite = true;
+ } else {
+ this.settings.infinite = false;
+ }
+ }
+ }]);
+
+ return ContinuousViewManager;
+}(_default2.default);
+
+exports.default = ContinuousViewManager;
+module.exports = exports["default"];
+
+/***/ }),
+/* 25 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+/* WEBPACK VAR INJECTION */(function(global) {
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+
+var _book = __webpack_require__(26);
+
+var _book2 = _interopRequireDefault(_book);
+
+var _rendition = __webpack_require__(18);
+
+var _rendition2 = _interopRequireDefault(_rendition);
+
+var _epubcfi = __webpack_require__(1);
+
+var _epubcfi2 = _interopRequireDefault(_epubcfi);
+
+var _contents = __webpack_require__(13);
+
+var _contents2 = _interopRequireDefault(_contents);
+
+var _core = __webpack_require__(0);
+
+var utils = _interopRequireWildcard(_core);
+
+__webpack_require__(69);
+
+var _iframe = __webpack_require__(20);
+
+var _iframe2 = _interopRequireDefault(_iframe);
+
+var _default = __webpack_require__(14);
+
+var _default2 = _interopRequireDefault(_default);
+
+var _continuous = __webpack_require__(24);
+
+var _continuous2 = _interopRequireDefault(_continuous);
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * Creates a new Book
+ * @param {string|ArrayBuffer} url URL, Path or ArrayBuffer
+ * @param {object} options to pass to the book
+ * @returns {Book} a new Book object
+ * @example ePub("/path/to/book.epub", {})
+ */
+function ePub(url, options) {
+ return new _book2.default(url, options);
+}
+
+ePub.VERSION = "0.3";
+
+if (typeof global !== "undefined") {
+ global.EPUBJS_VERSION = ePub.VERSION;
+}
+
+ePub.Book = _book2.default;
+ePub.Rendition = _rendition2.default;
+ePub.Contents = _contents2.default;
+ePub.CFI = _epubcfi2.default;
+ePub.utils = utils;
+
+exports.default = ePub;
+module.exports = exports["default"];
+/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(8)))
+
+/***/ }),
+/* 26 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+
+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; };
+
+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; }; }();
+
+var _eventEmitter = __webpack_require__(2);
+
+var _eventEmitter2 = _interopRequireDefault(_eventEmitter);
+
+var _core = __webpack_require__(0);
+
+var _url = __webpack_require__(5);
+
+var _url2 = _interopRequireDefault(_url);
+
+var _path = __webpack_require__(4);
+
+var _path2 = _interopRequireDefault(_path);
+
+var _spine = __webpack_require__(42);
+
+var _spine2 = _interopRequireDefault(_spine);
+
+var _locations = __webpack_require__(44);
+
+var _locations2 = _interopRequireDefault(_locations);
+
+var _container = __webpack_require__(45);
+
+var _container2 = _interopRequireDefault(_container);
+
+var _packaging = __webpack_require__(46);
+
+var _packaging2 = _interopRequireDefault(_packaging);
+
+var _navigation = __webpack_require__(47);
+
+var _navigation2 = _interopRequireDefault(_navigation);
+
+var _resources = __webpack_require__(48);
+
+var _resources2 = _interopRequireDefault(_resources);
+
+var _pagelist = __webpack_require__(49);
+
+var _pagelist2 = _interopRequireDefault(_pagelist);
+
+var _rendition = __webpack_require__(18);
+
+var _rendition2 = _interopRequireDefault(_rendition);
+
+var _archive = __webpack_require__(67);
+
+var _archive2 = _interopRequireDefault(_archive);
+
+var _request2 = __webpack_require__(11);
+
+var _request3 = _interopRequireDefault(_request2);
+
+var _epubcfi = __webpack_require__(1);
+
+var _epubcfi2 = _interopRequireDefault(_epubcfi);
+
+var _constants = __webpack_require__(3);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+var CONTAINER_PATH = "META-INF/container.xml";
+var EPUBJS_VERSION = "0.3";
+
+var INPUT_TYPE = {
+ BINARY: "binary",
+ BASE64: "base64",
+ EPUB: "epub",
+ OPF: "opf",
+ MANIFEST: "json",
+ DIRECTORY: "directory"
+};
+
+/**
+ * An Epub representation with methods for the loading, parsing and manipulation
+ * of its contents.
+ * @class
+ * @param {string} [url]
+ * @param {object} [options]
+ * @param {method} [options.requestMethod] a request function to use instead of the default
+ * @param {boolean} [options.requestCredentials=undefined] send the xhr request withCredentials
+ * @param {object} [options.requestHeaders=undefined] send the xhr request headers
+ * @param {string} [options.encoding=binary] optional to pass 'binary' or base64' for archived Epubs
+ * @param {string} [options.replacements=none] use base64, blobUrl, or none for replacing assets in archived Epubs
+ * @param {method} [options.canonical] optional function to determine canonical urls for a path
+ * @returns {Book}
+ * @example new Book("/path/to/book.epub", {})
+ * @example new Book({ replacements: "blobUrl" })
+ */
+
+var Book = function () {
+ function Book(url, options) {
+ var _this = this;
+
+ _classCallCheck(this, Book);
+
+ // Allow passing just options to the Book
+ if (typeof options === "undefined" && (typeof url === "undefined" ? "undefined" : _typeof(url)) === "object") {
+ options = url;
+ url = undefined;
+ }
+
+ this.settings = (0, _core.extend)(this.settings || {}, {
+ requestMethod: undefined,
+ requestCredentials: undefined,
+ requestHeaders: undefined,
+ encoding: undefined,
+ replacements: undefined,
+ canonical: undefined
+ });
+
+ (0, _core.extend)(this.settings, options);
+
+ // Promises
+ this.opening = new _core.defer();
+ /**
+ * @member {promise} opened returns after the book is loaded
+ * @memberof Book
+ */
+ this.opened = this.opening.promise;
+ this.isOpen = false;
+
+ this.loading = {
+ manifest: new _core.defer(),
+ spine: new _core.defer(),
+ metadata: new _core.defer(),
+ cover: new _core.defer(),
+ navigation: new _core.defer(),
+ pageList: new _core.defer(),
+ resources: new _core.defer()
+ };
+
+ this.loaded = {
+ manifest: this.loading.manifest.promise,
+ spine: this.loading.spine.promise,
+ metadata: this.loading.metadata.promise,
+ cover: this.loading.cover.promise,
+ navigation: this.loading.navigation.promise,
+ pageList: this.loading.pageList.promise,
+ resources: this.loading.resources.promise
+ };
+
+ /**
+ * @member {promise} ready returns after the book is loaded and parsed
+ * @memberof Book
+ * @private
+ */
+ this.ready = Promise.all([this.loaded.manifest, this.loaded.spine, this.loaded.metadata, this.loaded.cover, this.loaded.navigation, this.loaded.resources]);
+
+ // Queue for methods used before opening
+ this.isRendered = false;
+ // this._q = queue(this);
+
+ /**
+ * @member {method} request
+ * @memberof Book
+ * @private
+ */
+ this.request = this.settings.requestMethod || _request3.default;
+
+ /**
+ * @member {Spine} spine
+ * @memberof Book
+ */
+ this.spine = new _spine2.default();
+
+ /**
+ * @member {Locations} locations
+ * @memberof Book
+ */
+ this.locations = new _locations2.default(this.spine, this.load.bind(this));
+
+ /**
+ * @member {Navigation} navigation
+ * @memberof Book
+ */
+ this.navigation = undefined;
+
+ /**
+ * @member {PageList} pagelist
+ * @memberof Book
+ */
+ this.pageList = undefined;
+
+ /**
+ * @member {Url} url
+ * @memberof Book
+ * @private
+ */
+ this.url = undefined;
+
+ /**
+ * @member {Path} path
+ * @memberof Book
+ * @private
+ */
+ this.path = undefined;
+
+ /**
+ * @member {boolean} archived
+ * @memberof Book
+ * @private
+ */
+ this.archived = false;
+
+ /**
+ * @member {Archive} archive
+ * @memberof Book
+ * @private
+ */
+ this.archive = undefined;
+
+ /**
+ * @member {Resources} resources
+ * @memberof Book
+ * @private
+ */
+ this.resources = undefined;
+
+ /**
+ * @member {Rendition} rendition
+ * @memberof Book
+ * @private
+ */
+ this.rendition = undefined;
+
+ /**
+ * @member {Container} container
+ * @memberof Book
+ * @private
+ */
+ this.container = undefined;
+
+ /**
+ * @member {Packaging} packaging
+ * @memberof Book
+ * @private
+ */
+ this.packaging = undefined;
+
+ // this.toc = undefined;
+
+ if (url) {
+ this.open(url).catch(function (error) {
+ var err = new Error("Cannot load book at " + url);
+ _this.emit(_constants.EVENTS.BOOK.OPEN_FAILED, err);
+ });
+ }
+ }
+
+ /**
+ * Open a epub or url
+ * @param {string | ArrayBuffer} input Url, Path or ArrayBuffer
+ * @param {string} [what="binary", "base64", "epub", "opf", "json", "directory"] force opening as a certain type
+ * @returns {Promise} of when the book has been loaded
+ * @example book.open("/path/to/book.epub")
+ */
+
+
+ _createClass(Book, [{
+ key: "open",
+ value: function open(input, what) {
+ var opening;
+ var type = what || this.determineType(input);
+
+ if (type === INPUT_TYPE.BINARY) {
+ this.archived = true;
+ this.url = new _url2.default("/", "");
+ opening = this.openEpub(input);
+ } else if (type === INPUT_TYPE.BASE64) {
+ this.archived = true;
+ this.url = new _url2.default("/", "");
+ opening = this.openEpub(input, type);
+ } else if (type === INPUT_TYPE.EPUB) {
+ this.archived = true;
+ this.url = new _url2.default("/", "");
+ opening = this.request(input, "binary").then(this.openEpub.bind(this));
+ } else if (type == INPUT_TYPE.OPF) {
+ this.url = new _url2.default(input);
+ opening = this.openPackaging(this.url.Path.toString());
+ } else if (type == INPUT_TYPE.MANIFEST) {
+ this.url = new _url2.default(input);
+ opening = this.openManifest(this.url.Path.toString());
+ } else {
+ this.url = new _url2.default(input);
+ opening = this.openContainer(CONTAINER_PATH).then(this.openPackaging.bind(this));
+ }
+
+ return opening;
+ }
+
+ /**
+ * Open an archived epub
+ * @private
+ * @param {binary} data
+ * @param {string} [encoding]
+ * @return {Promise}
+ */
+
+ }, {
+ key: "openEpub",
+ value: function openEpub(data, encoding) {
+ var _this2 = this;
+
+ return this.unarchive(data, encoding || this.settings.encoding).then(function () {
+ return _this2.openContainer(CONTAINER_PATH);
+ }).then(function (packagePath) {
+ return _this2.openPackaging(packagePath);
+ });
+ }
+
+ /**
+ * Open the epub container
+ * @private
+ * @param {string} url
+ * @return {string} packagePath
+ */
+
+ }, {
+ key: "openContainer",
+ value: function openContainer(url) {
+ var _this3 = this;
+
+ return this.load(url).then(function (xml) {
+ _this3.container = new _container2.default(xml);
+ return _this3.resolve(_this3.container.packagePath);
+ });
+ }
+
+ /**
+ * Open the Open Packaging Format Xml
+ * @private
+ * @param {string} url
+ * @return {Promise}
+ */
+
+ }, {
+ key: "openPackaging",
+ value: function openPackaging(url) {
+ var _this4 = this;
+
+ this.path = new _path2.default(url);
+ return this.load(url).then(function (xml) {
+ _this4.packaging = new _packaging2.default(xml);
+ return _this4.unpack(_this4.packaging);
+ });
+ }
+
+ /**
+ * Open the manifest JSON
+ * @private
+ * @param {string} url
+ * @return {Promise}
+ */
+
+ }, {
+ key: "openManifest",
+ value: function openManifest(url) {
+ var _this5 = this;
+
+ this.path = new _path2.default(url);
+ return this.load(url).then(function (json) {
+ _this5.packaging = new _packaging2.default();
+ _this5.packaging.load(json);
+ return _this5.unpack(_this5.packaging);
+ });
+ }
+
+ /**
+ * Load a resource from the Book
+ * @param {string} path path to the resource to load
+ * @return {Promise} returns a promise with the requested resource
+ */
+
+ }, {
+ key: "load",
+ value: function load(path) {
+ var resolved;
+
+ if (this.archived) {
+ resolved = this.resolve(path);
+ return this.archive.request(resolved);
+ } else {
+ resolved = this.resolve(path);
+ return this.request(resolved, null, this.settings.requestCredentials, this.settings.requestHeaders);
+ }
+ }
+
+ /**
+ * Resolve a path to it's absolute position in the Book
+ * @param {string} path
+ * @param {boolean} [absolute] force resolving the full URL
+ * @return {string} the resolved path string
+ */
+
+ }, {
+ key: "resolve",
+ value: function resolve(path, absolute) {
+ if (!path) {
+ return;
+ }
+ var resolved = path;
+ var isAbsolute = path.indexOf("://") > -1;
+
+ if (isAbsolute) {
+ return path;
+ }
+
+ if (this.path) {
+ resolved = this.path.resolve(path);
+ }
+
+ if (absolute != false && this.url) {
+ resolved = this.url.resolve(resolved);
+ }
+
+ return resolved;
+ }
+
+ /**
+ * Get a canonical link to a path
+ * @param {string} path
+ * @return {string} the canonical path string
+ */
+
+ }, {
+ key: "canonical",
+ value: function canonical(path) {
+ var url = path;
+
+ if (!path) {
+ return "";
+ }
+
+ if (this.settings.canonical) {
+ url = this.settings.canonical(path);
+ } else {
+ url = this.resolve(path, true);
+ }
+
+ return url;
+ }
+
+ /**
+ * Determine the type of they input passed to open
+ * @private
+ * @param {string} input
+ * @return {string} binary | directory | epub | opf
+ */
+
+ }, {
+ key: "determineType",
+ value: function determineType(input) {
+ var url;
+ var path;
+ var extension;
+
+ if (this.settings.encoding === "base64") {
+ return INPUT_TYPE.BASE64;
+ }
+
+ if (typeof input != "string") {
+ return INPUT_TYPE.BINARY;
+ }
+
+ url = new _url2.default(input);
+ path = url.path();
+ extension = path.extension;
+
+ if (!extension) {
+ return INPUT_TYPE.DIRECTORY;
+ }
+
+ if (extension === "epub") {
+ return INPUT_TYPE.EPUB;
+ }
+
+ if (extension === "opf") {
+ return INPUT_TYPE.OPF;
+ }
+
+ if (extension === "json") {
+ return INPUT_TYPE.MANIFEST;
+ }
+ }
+
+ /**
+ * unpack the contents of the Books packageXml
+ * @private
+ * @param {document} packageXml XML Document
+ */
+
+ }, {
+ key: "unpack",
+ value: function unpack(opf) {
+ var _this6 = this;
+
+ this.package = opf;
+
+ this.spine.unpack(this.package, this.resolve.bind(this), this.canonical.bind(this));
+
+ this.resources = new _resources2.default(this.package.manifest, {
+ archive: this.archive,
+ resolver: this.resolve.bind(this),
+ request: this.request.bind(this),
+ replacements: this.settings.replacements || (this.archived ? "blobUrl" : "base64")
+ });
+
+ this.loadNavigation(this.package).then(function () {
+ // this.toc = this.navigation.toc;
+ _this6.loading.navigation.resolve(_this6.navigation);
+ });
+
+ if (this.package.coverPath) {
+ this.cover = this.resolve(this.package.coverPath);
+ }
+ // Resolve promises
+ this.loading.manifest.resolve(this.package.manifest);
+ this.loading.metadata.resolve(this.package.metadata);
+ this.loading.spine.resolve(this.spine);
+ this.loading.cover.resolve(this.cover);
+ this.loading.resources.resolve(this.resources);
+ this.loading.pageList.resolve(this.pageList);
+
+ this.isOpen = true;
+
+ if (this.archived || this.settings.replacements && this.settings.replacements != "none") {
+ this.replacements().then(function () {
+ _this6.opening.resolve(_this6);
+ }).catch(function (err) {
+ console.error(err);
+ });
+ } else {
+ // Resolve book opened promise
+ this.opening.resolve(this);
+ }
+ }
+
+ /**
+ * Load Navigation and PageList from package
+ * @private
+ * @param {document} opf XML Document
+ */
+
+ }, {
+ key: "loadNavigation",
+ value: function loadNavigation(opf) {
+ var _this7 = this;
+
+ var navPath = opf.navPath || opf.ncxPath;
+ var toc = opf.toc;
+
+ // From json manifest
+ if (toc) {
+ return new Promise(function (resolve, reject) {
+ _this7.navigation = new _navigation2.default(toc);
+
+ if (opf.pageList) {
+ _this7.pageList = new _pagelist2.default(opf.pageList); // TODO: handle page lists from Manifest
+ }
+
+ resolve(_this7.navigation);
+ });
+ }
+
+ if (!navPath) {
+ return new Promise(function (resolve, reject) {
+ _this7.navigation = new _navigation2.default();
+ _this7.pageList = new _pagelist2.default();
+
+ resolve(_this7.navigation);
+ });
+ }
+
+ return this.load(navPath, "xml").then(function (xml) {
+ _this7.navigation = new _navigation2.default(xml);
+ _this7.pageList = new _pagelist2.default(xml);
+ return _this7.navigation;
+ });
+ }
+
+ /**
+ * Gets a Section of the Book from the Spine
+ * Alias for `book.spine.get`
+ * @param {string} target
+ * @return {Section}
+ */
+
+ }, {
+ key: "section",
+ value: function section(target) {
+ return this.spine.get(target);
+ }
+
+ /**
+ * Sugar to render a book to an element
+ * @param {element | string} element element or string to add a rendition to
+ * @param {object} [options]
+ * @return {Rendition}
+ */
+
+ }, {
+ key: "renderTo",
+ value: function renderTo(element, options) {
+ this.rendition = new _rendition2.default(this, options);
+ this.rendition.attachTo(element);
+
+ return this.rendition;
+ }
+
+ /**
+ * Set if request should use withCredentials
+ * @param {boolean} credentials
+ */
+
+ }, {
+ key: "setRequestCredentials",
+ value: function setRequestCredentials(credentials) {
+ this.settings.requestCredentials = credentials;
+ }
+
+ /**
+ * Set headers request should use
+ * @param {object} headers
+ */
+
+ }, {
+ key: "setRequestHeaders",
+ value: function setRequestHeaders(headers) {
+ this.settings.requestHeaders = headers;
+ }
+
+ /**
+ * Unarchive a zipped epub
+ * @private
+ * @param {binary} input epub data
+ * @param {string} [encoding]
+ * @return {Archive}
+ */
+
+ }, {
+ key: "unarchive",
+ value: function unarchive(input, encoding) {
+ this.archive = new _archive2.default();
+ return this.archive.open(input, encoding);
+ }
+
+ /**
+ * Get the cover url
+ * @return {string} coverUrl
+ */
+
+ }, {
+ key: "coverUrl",
+ value: function coverUrl() {
+ var _this8 = this;
+
+ var retrieved = this.loaded.cover.then(function (url) {
+ if (_this8.archived) {
+ // return this.archive.createUrl(this.cover);
+ return _this8.resources.get(_this8.cover);
+ } else {
+ return _this8.cover;
+ }
+ });
+
+ return retrieved;
+ }
+
+ /**
+ * Load replacement urls
+ * @private
+ * @return {Promise} completed loading urls
+ */
+
+ }, {
+ key: "replacements",
+ value: function replacements() {
+ var _this9 = this;
+
+ this.spine.hooks.serialize.register(function (output, section) {
+ section.output = _this9.resources.substitute(output, section.url);
+ });
+
+ return this.resources.replacements().then(function () {
+ return _this9.resources.replaceCss();
+ });
+ }
+
+ /**
+ * Find a DOM Range for a given CFI Range
+ * @param {EpubCFI} cfiRange a epub cfi range
+ * @return {Range}
+ */
+
+ }, {
+ key: "getRange",
+ value: function getRange(cfiRange) {
+ var cfi = new _epubcfi2.default(cfiRange);
+ var item = this.spine.get(cfi.spinePos);
+ var _request = this.load.bind(this);
+ if (!item) {
+ return new Promise(function (resolve, reject) {
+ reject("CFI could not be found");
+ });
+ }
+ return item.load(_request).then(function (contents) {
+ var range = cfi.toRange(item.document);
+ return range;
+ });
+ }
+
+ /**
+ * Generates the Book Key using the identifer in the manifest or other string provided
+ * @param {string} [identifier] to use instead of metadata identifier
+ * @return {string} key
+ */
+
+ }, {
+ key: "key",
+ value: function key(identifier) {
+ var ident = identifier || this.package.metadata.identifier || this.url.filename;
+ return "epubjs:" + EPUBJS_VERSION + ":" + ident;
+ }
+
+ /**
+ * Destroy the Book and all associated objects
+ */
+
+ }, {
+ key: "destroy",
+ value: function destroy() {
+ this.opened = undefined;
+ this.loading = undefined;
+ this.loaded = undefined;
+ this.ready = undefined;
+
+ this.isOpen = false;
+ this.isRendered = false;
+
+ this.spine && this.spine.destroy();
+ this.locations && this.locations.destroy();
+ this.pageList && this.pageList.destroy();
+ this.archive && this.archive.destroy();
+ this.resources && this.resources.destroy();
+ this.container && this.container.destroy();
+ this.packaging && this.packaging.destroy();
+ this.rendition && this.rendition.destroy();
+
+ this.spine = undefined;
+ this.locations = undefined;
+ this.pageList = undefined;
+ this.archive = undefined;
+ this.resources = undefined;
+ this.container = undefined;
+ this.packaging = undefined;
+ this.rendition = undefined;
+
+ this.navigation = undefined;
+ this.url = undefined;
+ this.path = undefined;
+ this.archived = false;
+ }
+ }]);
+
+ return Book;
+}();
+
+//-- Enable binding events to book
+
+
+(0, _eventEmitter2.default)(Book.prototype);
+
+exports.default = Book;
+module.exports = exports["default"];
+
+/***/ }),
+/* 27 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+var assign = __webpack_require__(28)
+ , normalizeOpts = __webpack_require__(36)
+ , isCallable = __webpack_require__(37)
+ , contains = __webpack_require__(38)
+
+ , d;
+
+d = module.exports = function (dscr, value/*, options*/) {
+ var c, e, w, options, desc;
+ if ((arguments.length < 2) || (typeof dscr !== 'string')) {
+ options = value;
+ value = dscr;
+ dscr = null;
+ } else {
+ options = arguments[2];
+ }
+ if (dscr == null) {
+ c = w = true;
+ e = false;
+ } else {
+ c = contains.call(dscr, 'c');
+ e = contains.call(dscr, 'e');
+ w = contains.call(dscr, 'w');
+ }
+
+ desc = { value: value, configurable: c, enumerable: e, writable: w };
+ return !options ? desc : assign(normalizeOpts(options), desc);
+};
+
+d.gs = function (dscr, get, set/*, options*/) {
+ var c, e, options, desc;
+ if (typeof dscr !== 'string') {
+ options = set;
+ set = get;
+ get = dscr;
+ dscr = null;
+ } else {
+ options = arguments[3];
+ }
+ if (get == null) {
+ get = undefined;
+ } else if (!isCallable(get)) {
+ options = get;
+ get = set = undefined;
+ } else if (set == null) {
+ set = undefined;
+ } else if (!isCallable(set)) {
+ options = set;
+ set = undefined;
+ }
+ if (dscr == null) {
+ c = true;
+ e = false;
+ } else {
+ c = contains.call(dscr, 'c');
+ e = contains.call(dscr, 'e');
+ }
+
+ desc = { get: get, set: set, configurable: c, enumerable: e };
+ return !options ? desc : assign(normalizeOpts(options), desc);
+};
+
+
+/***/ }),
+/* 28 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+module.exports = __webpack_require__(29)()
+ ? Object.assign
+ : __webpack_require__(30);
+
+
+/***/ }),
+/* 29 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+module.exports = function () {
+ var assign = Object.assign, obj;
+ if (typeof assign !== "function") return false;
+ obj = { foo: "raz" };
+ assign(obj, { bar: "dwa" }, { trzy: "trzy" });
+ return (obj.foo + obj.bar + obj.trzy) === "razdwatrzy";
+};
+
+
+/***/ }),
+/* 30 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+var keys = __webpack_require__(31)
+ , value = __webpack_require__(35)
+ , max = Math.max;
+
+module.exports = function (dest, src /*, …srcn*/) {
+ var error, i, length = max(arguments.length, 2), assign;
+ dest = Object(value(dest));
+ assign = function (key) {
+ try {
+ dest[key] = src[key];
+ } catch (e) {
+ if (!error) error = e;
+ }
+ };
+ for (i = 1; i < length; ++i) {
+ src = arguments[i];
+ keys(src).forEach(assign);
+ }
+ if (error !== undefined) throw error;
+ return dest;
+};
+
+
+/***/ }),
+/* 31 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+module.exports = __webpack_require__(32)()
+ ? Object.keys
+ : __webpack_require__(33);
+
+
+/***/ }),
+/* 32 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+module.exports = function () {
+ try {
+ Object.keys("primitive");
+ return true;
+ } catch (e) {
+ return false;
+}
+};
+
+
+/***/ }),
+/* 33 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+var isValue = __webpack_require__(9);
+
+var keys = Object.keys;
+
+module.exports = function (object) {
+ return keys(isValue(object) ? Object(object) : object);
+};
+
+
+/***/ }),
+/* 34 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+// eslint-disable-next-line no-empty-function
+module.exports = function () {};
+
+
+/***/ }),
+/* 35 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+var isValue = __webpack_require__(9);
+
+module.exports = function (value) {
+ if (!isValue(value)) throw new TypeError("Cannot use null or undefined");
+ return value;
+};
+
+
+/***/ }),
+/* 36 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+var isValue = __webpack_require__(9);
+
+var forEach = Array.prototype.forEach, create = Object.create;
+
+var process = function (src, obj) {
+ var key;
+ for (key in src) obj[key] = src[key];
+};
+
+// eslint-disable-next-line no-unused-vars
+module.exports = function (opts1 /*, …options*/) {
+ var result = create(null);
+ forEach.call(arguments, function (options) {
+ if (!isValue(options)) return;
+ process(Object(options), result);
+ });
+ return result;
+};
+
+
+/***/ }),
+/* 37 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+// Deprecated
+
+
+
+module.exports = function (obj) {
+ return typeof obj === "function";
+};
+
+
+/***/ }),
+/* 38 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+module.exports = __webpack_require__(39)()
+ ? String.prototype.contains
+ : __webpack_require__(40);
+
+
+/***/ }),
+/* 39 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+var str = "razdwatrzy";
+
+module.exports = function () {
+ if (typeof str.contains !== "function") return false;
+ return (str.contains("dwa") === true) && (str.contains("foo") === false);
+};
+
+
+/***/ }),
+/* 40 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+var indexOf = String.prototype.indexOf;
+
+module.exports = function (searchString/*, position*/) {
+ return indexOf.call(this, searchString, arguments[1]) > -1;
+};
+
+
+/***/ }),
+/* 41 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+module.exports = function (fn) {
+ if (typeof fn !== "function") throw new TypeError(fn + " is not a function");
+ return fn;
+};
+
+
+/***/ }),
+/* 42 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+
+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; }; }();
+
+var _epubcfi = __webpack_require__(1);
+
+var _epubcfi2 = _interopRequireDefault(_epubcfi);
+
+var _hook = __webpack_require__(10);
+
+var _hook2 = _interopRequireDefault(_hook);
+
+var _section = __webpack_require__(43);
+
+var _section2 = _interopRequireDefault(_section);
+
+var _replacements = __webpack_require__(7);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+/**
+ * A collection of Spine Items
+ */
+var Spine = function () {
+ function Spine() {
+ _classCallCheck(this, Spine);
+
+ this.spineItems = [];
+ this.spineByHref = {};
+ this.spineById = {};
+
+ this.hooks = {};
+ this.hooks.serialize = new _hook2.default();
+ this.hooks.content = new _hook2.default();
+
+ // Register replacements
+ this.hooks.content.register(_replacements.replaceBase);
+ this.hooks.content.register(_replacements.replaceCanonical);
+ this.hooks.content.register(_replacements.replaceMeta);
+
+ this.epubcfi = new _epubcfi2.default();
+
+ this.loaded = false;
+
+ this.items = undefined;
+ this.manifest = undefined;
+ this.spineNodeIndex = undefined;
+ this.baseUrl = undefined;
+ this.length = undefined;
+ }
+
+ /**
+ * Unpack items from a opf into spine items
+ * @param {Package} _package
+ * @param {method} resolver URL resolver
+ */
+
+
+ _createClass(Spine, [{
+ key: "unpack",
+ value: function unpack(_package, resolver, canonical) {
+ var _this = this;
+
+ this.items = _package.spine;
+ this.manifest = _package.manifest;
+ this.spineNodeIndex = _package.spineNodeIndex;
+ this.baseUrl = _package.baseUrl || _package.basePath || "";
+ this.length = this.items.length;
+
+ this.items.forEach(function (item, index) {
+ var manifestItem = _this.manifest[item.idref];
+ var spineItem;
+
+ item.index = index;
+ item.cfiBase = _this.epubcfi.generateChapterComponent(_this.spineNodeIndex, item.index, item.idref);
+
+ if (item.href) {
+ item.url = resolver(item.href, true);
+ item.canonical = canonical(item.href);
+ }
+
+ if (manifestItem) {
+ item.href = manifestItem.href;
+ item.url = resolver(item.href, true);
+ item.canonical = canonical(item.href);
+
+ if (manifestItem.properties.length) {
+ item.properties.push.apply(item.properties, manifestItem.properties);
+ }
+ }
+
+ if (item.linear === "yes") {
+ item.prev = function () {
+ var prevIndex = item.index;
+ while (prevIndex > 0) {
+ var prev = this.get(prevIndex - 1);
+ if (prev && prev.linear) {
+ return prev;
+ }
+ prevIndex -= 1;
+ }
+ return;
+ }.bind(_this);
+ item.next = function () {
+ var nextIndex = item.index;
+ while (nextIndex < this.spineItems.length - 1) {
+ var next = this.get(nextIndex + 1);
+ if (next && next.linear) {
+ return next;
+ }
+ nextIndex += 1;
+ }
+ return;
+ }.bind(_this);
+ } else {
+ item.prev = function () {
+ return;
+ };
+ item.next = function () {
+ return;
+ };
+ }
+
+ spineItem = new _section2.default(item, _this.hooks);
+
+ _this.append(spineItem);
+ });
+
+ this.loaded = true;
+ }
+
+ /**
+ * Get an item from the spine
+ * @param {string|int} [target]
+ * @return {Section} section
+ * @example spine.get();
+ * @example spine.get(1);
+ * @example spine.get("chap1.html");
+ * @example spine.get("#id1234");
+ */
+
+ }, {
+ key: "get",
+ value: function get(target) {
+ var index = 0;
+
+ if (typeof target === "undefined") {
+ while (index < this.spineItems.length) {
+ var next = this.spineItems[index];
+ if (next && next.linear) {
+ break;
+ }
+ index += 1;
+ }
+ } else if (this.epubcfi.isCfiString(target)) {
+ var cfi = new _epubcfi2.default(target);
+ index = cfi.spinePos;
+ } else if (typeof target === "number" || isNaN(target) === false) {
+ index = target;
+ } else if (typeof target === "string" && target.indexOf("#") === 0) {
+ index = this.spineById[target.substring(1)];
+ } else if (typeof target === "string") {
+ // Remove fragments
+ target = target.split("#")[0];
+ index = this.spineByHref[target] || this.spineByHref[encodeURI(target)];
+ }
+
+ return this.spineItems[index] || null;
+ }
+
+ /**
+ * Append a Section to the Spine
+ * @private
+ * @param {Section} section
+ */
+
+ }, {
+ key: "append",
+ value: function append(section) {
+ var index = this.spineItems.length;
+ section.index = index;
+
+ this.spineItems.push(section);
+
+ // Encode and Decode href lookups
+ // see pr for details: https://github.com/futurepress/epub.js/pull/358
+ this.spineByHref[decodeURI(section.href)] = index;
+ this.spineByHref[encodeURI(section.href)] = index;
+ this.spineByHref[section.href] = index;
+
+ this.spineById[section.idref] = index;
+
+ return index;
+ }
+
+ /**
+ * Prepend a Section to the Spine
+ * @private
+ * @param {Section} section
+ */
+
+ }, {
+ key: "prepend",
+ value: function prepend(section) {
+ // var index = this.spineItems.unshift(section);
+ this.spineByHref[section.href] = 0;
+ this.spineById[section.idref] = 0;
+
+ // Re-index
+ this.spineItems.forEach(function (item, index) {
+ item.index = index;
+ });
+
+ return 0;
+ }
+
+ // insert(section, index) {
+ //
+ // };
+
+ /**
+ * Remove a Section from the Spine
+ * @private
+ * @param {Section} section
+ */
+
+ }, {
+ key: "remove",
+ value: function remove(section) {
+ var index = this.spineItems.indexOf(section);
+
+ if (index > -1) {
+ delete this.spineByHref[section.href];
+ delete this.spineById[section.idref];
+
+ return this.spineItems.splice(index, 1);
+ }
+ }
+
+ /**
+ * Loop over the Sections in the Spine
+ * @return {method} forEach
+ */
+
+ }, {
+ key: "each",
+ value: function each() {
+ return this.spineItems.forEach.apply(this.spineItems, arguments);
+ }
+ }, {
+ key: "first",
+ value: function first() {
+ var index = 0;
+
+ do {
+ var next = this.get(index);
+
+ if (next && next.linear) {
+ return next;
+ }
+ index += 1;
+ } while (index < this.spineItems.length);
+ }
+ }, {
+ key: "last",
+ value: function last() {
+ var index = this.spineItems.length - 1;
+
+ do {
+ var prev = this.get(index);
+ if (prev && prev.linear) {
+ return prev;
+ }
+ index -= 1;
+ } while (index >= 0);
+ }
+ }, {
+ key: "destroy",
+ value: function destroy() {
+ this.each(function (section) {
+ return section.destroy();
+ });
+
+ this.spineItems = undefined;
+ this.spineByHref = undefined;
+ this.spineById = undefined;
+
+ this.hooks.serialize.clear();
+ this.hooks.content.clear();
+ this.hooks = undefined;
+
+ this.epubcfi = undefined;
+
+ this.loaded = false;
+
+ this.items = undefined;
+ this.manifest = undefined;
+ this.spineNodeIndex = undefined;
+ this.baseUrl = undefined;
+ this.length = undefined;
+ }
+ }]);
+
+ return Spine;
+}();
+
+exports.default = Spine;
+module.exports = exports["default"];
+
+/***/ }),
+/* 43 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+
+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; }; }();
+
+var _core = __webpack_require__(0);
+
+var _epubcfi = __webpack_require__(1);
+
+var _epubcfi2 = _interopRequireDefault(_epubcfi);
+
+var _hook = __webpack_require__(10);
+
+var _hook2 = _interopRequireDefault(_hook);
+
+var _replacements = __webpack_require__(7);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+/**
+ * Represents a Section of the Book
+ *
+ * In most books this is equivelent to a Chapter
+ * @param {object} item The spine item representing the section
+ * @param {object} hooks hooks for serialize and content
+ */
+var Section = function () {
+ function Section(item, hooks) {
+ _classCallCheck(this, Section);
+
+ this.idref = item.idref;
+ this.linear = item.linear === "yes";
+ this.properties = item.properties;
+ this.index = item.index;
+ this.href = item.href;
+ this.url = item.url;
+ this.canonical = item.canonical;
+ this.next = item.next;
+ this.prev = item.prev;
+
+ this.cfiBase = item.cfiBase;
+
+ if (hooks) {
+ this.hooks = hooks;
+ } else {
+ this.hooks = {};
+ this.hooks.serialize = new _hook2.default(this);
+ this.hooks.content = new _hook2.default(this);
+ }
+
+ this.document = undefined;
+ this.contents = undefined;
+ this.output = undefined;
+ }
+
+ /**
+ * Load the section from its url
+ * @param {method} _request a request method to use for loading
+ * @return {document} a promise with the xml document
+ */
+
+
+ _createClass(Section, [{
+ key: "load",
+ value: function load(_request) {
+ var request = _request || this.request || __webpack_require__(11);
+ var loading = new _core.defer();
+ var loaded = loading.promise;
+
+ if (this.contents) {
+ loading.resolve(this.contents);
+ } else {
+ request(this.url).then(function (xml) {
+ // var directory = new Url(this.url).directory;
+
+ this.document = xml;
+ this.contents = xml.documentElement;
+
+ return this.hooks.content.trigger(this.document, this);
+ }.bind(this)).then(function () {
+ loading.resolve(this.contents);
+ }.bind(this)).catch(function (error) {
+ loading.reject(error);
+ });
+ }
+
+ return loaded;
+ }
+
+ /**
+ * Adds a base tag for resolving urls in the section
+ * @private
+ */
+
+ }, {
+ key: "base",
+ value: function base() {
+ return (0, _replacements.replaceBase)(this.document, this);
+ }
+
+ /**
+ * Render the contents of a section
+ * @param {method} _request a request method to use for loading
+ * @return {string} output a serialized XML Document
+ */
+
+ }, {
+ key: "render",
+ value: function render(_request) {
+ var rendering = new _core.defer();
+ var rendered = rendering.promise;
+ this.output; // TODO: better way to return this from hooks?
+
+ this.load(_request).then(function (contents) {
+ var userAgent = typeof navigator !== 'undefined' && navigator.userAgent || '';
+ var isIE = userAgent.indexOf('Trident') >= 0;
+ var Serializer;
+ if (typeof XMLSerializer === "undefined" || isIE) {
+ Serializer = __webpack_require__(16).XMLSerializer;
+ } else {
+ Serializer = XMLSerializer;
+ }
+ var serializer = new Serializer();
+ this.output = serializer.serializeToString(contents);
+ return this.output;
+ }.bind(this)).then(function () {
+ return this.hooks.serialize.trigger(this.output, this);
+ }.bind(this)).then(function () {
+ rendering.resolve(this.output);
+ }.bind(this)).catch(function (error) {
+ rendering.reject(error);
+ });
+
+ return rendered;
+ }
+
+ /**
+ * Find a string in a section
+ * @param {string} _query The query string to find
+ * @return {object[]} A list of matches, with form {cfi, excerpt}
+ */
+
+ }, {
+ key: "find",
+ value: function find(_query) {
+ var section = this;
+ var matches = [];
+ var query = _query.toLowerCase();
+ var find = function find(node) {
+ var text = node.textContent.toLowerCase();
+ var range = section.document.createRange();
+ var cfi;
+ var pos;
+ var last = -1;
+ var excerpt;
+ var limit = 150;
+
+ while (pos != -1) {
+ // Search for the query
+ pos = text.indexOf(query, last + 1);
+
+ if (pos != -1) {
+ // We found it! Generate a CFI
+ range = section.document.createRange();
+ range.setStart(node, pos);
+ range.setEnd(node, pos + query.length);
+
+ cfi = section.cfiFromRange(range);
+
+ // Generate the excerpt
+ if (node.textContent.length < limit) {
+ excerpt = node.textContent;
+ } else {
+ excerpt = node.textContent.substring(pos - limit / 2, pos + limit / 2);
+ excerpt = "..." + excerpt + "...";
+ }
+
+ // Add the CFI to the matches list
+ matches.push({
+ cfi: cfi,
+ excerpt: excerpt
+ });
+ }
+
+ last = pos;
+ }
+ };
+
+ (0, _core.sprint)(section.document, function (node) {
+ find(node);
+ });
+
+ return matches;
+ }
+ }, {
+ key: "reconcileLayoutSettings",
+
+
+ /**
+ * Reconciles the current chapters layout properies with
+ * the global layout properities.
+ * @param {object} global The globa layout settings object, chapter properties string
+ * @return {object} layoutProperties Object with layout properties
+ */
+ value: function reconcileLayoutSettings(global) {
+ //-- Get the global defaults
+ var settings = {
+ layout: global.layout,
+ spread: global.spread,
+ orientation: global.orientation
+ };
+
+ //-- Get the chapter's display type
+ this.properties.forEach(function (prop) {
+ var rendition = prop.replace("rendition:", "");
+ var split = rendition.indexOf("-");
+ var property, value;
+
+ if (split != -1) {
+ property = rendition.slice(0, split);
+ value = rendition.slice(split + 1);
+
+ settings[property] = value;
+ }
+ });
+ return settings;
+ }
+
+ /**
+ * Get a CFI from a Range in the Section
+ * @param {range} _range
+ * @return {string} cfi an EpubCFI string
+ */
+
+ }, {
+ key: "cfiFromRange",
+ value: function cfiFromRange(_range) {
+ return new _epubcfi2.default(_range, this.cfiBase).toString();
+ }
+
+ /**
+ * Get a CFI from an Element in the Section
+ * @param {element} el
+ * @return {string} cfi an EpubCFI string
+ */
+
+ }, {
+ key: "cfiFromElement",
+ value: function cfiFromElement(el) {
+ return new _epubcfi2.default(el, this.cfiBase).toString();
+ }
+
+ /**
+ * Unload the section document
+ */
+
+ }, {
+ key: "unload",
+ value: function unload() {
+ this.document = undefined;
+ this.contents = undefined;
+ this.output = undefined;
+ }
+ }, {
+ key: "destroy",
+ value: function destroy() {
+ this.unload();
+ this.hooks.serialize.clear();
+ this.hooks.content.clear();
+
+ this.hooks = undefined;
+ this.idref = undefined;
+ this.linear = undefined;
+ this.properties = undefined;
+ this.index = undefined;
+ this.href = undefined;
+ this.url = undefined;
+ this.next = undefined;
+ this.prev = undefined;
+
+ this.cfiBase = undefined;
+ }
+ }]);
+
+ return Section;
+}();
+
+exports.default = Section;
+module.exports = exports["default"];
+
+/***/ }),
+/* 44 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+
+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; }; }();
+
+var _core = __webpack_require__(0);
+
+var _queue = __webpack_require__(12);
+
+var _queue2 = _interopRequireDefault(_queue);
+
+var _epubcfi = __webpack_require__(1);
+
+var _epubcfi2 = _interopRequireDefault(_epubcfi);
+
+var _constants = __webpack_require__(3);
+
+var _eventEmitter = __webpack_require__(2);
+
+var _eventEmitter2 = _interopRequireDefault(_eventEmitter);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+/**
+ * Find Locations for a Book
+ * @param {Spine} spine
+ * @param {request} request
+ */
+var Locations = function () {
+ function Locations(spine, request, pause) {
+ _classCallCheck(this, Locations);
+
+ this.spine = spine;
+ this.request = request;
+ this.pause = pause || 100;
+
+ this.q = new _queue2.default(this);
+ this.epubcfi = new _epubcfi2.default();
+
+ this._locations = [];
+ this.total = 0;
+
+ this.break = 150;
+
+ this._current = 0;
+
+ this.currentLocation = '';
+ this._currentCfi = '';
+ this.processingTimeout = undefined;
+ }
+
+ /**
+ * Load all of sections in the book to generate locations
+ * @param {int} chars how many chars to split on
+ * @return {object} locations
+ */
+
+
+ _createClass(Locations, [{
+ key: "generate",
+ value: function generate(chars) {
+
+ if (chars) {
+ this.break = chars;
+ }
+
+ this.q.pause();
+
+ this.spine.each(function (section) {
+ if (section.linear) {
+ this.q.enqueue(this.process.bind(this), section);
+ }
+ }.bind(this));
+
+ return this.q.run().then(function () {
+ this.total = this._locations.length - 1;
+
+ if (this._currentCfi) {
+ this.currentLocation = this._currentCfi;
+ }
+
+ return this._locations;
+ // console.log(this.percentage(this.book.rendition.location.start), this.percentage(this.book.rendition.location.end));
+ }.bind(this));
+ }
+ }, {
+ key: "createRange",
+ value: function createRange() {
+ return {
+ startContainer: undefined,
+ startOffset: undefined,
+ endContainer: undefined,
+ endOffset: undefined
+ };
+ }
+ }, {
+ key: "process",
+ value: function process(section) {
+
+ return section.load(this.request).then(function (contents) {
+ var completed = new _core.defer();
+ var locations = this.parse(contents, section.cfiBase);
+ this._locations = this._locations.concat(locations);
+
+ section.unload();
+
+ this.processingTimeout = setTimeout(function () {
+ return completed.resolve(locations);
+ }, this.pause);
+ return completed.promise;
+ }.bind(this));
+ }
+ }, {
+ key: "parse",
+ value: function parse(contents, cfiBase, chars) {
+ var locations = [];
+ var range;
+ var doc = contents.ownerDocument;
+ var body = (0, _core.qs)(doc, "body");
+ var counter = 0;
+ var prev;
+ var _break = chars || this.break;
+ var parser = function parser(node) {
+ var len = node.length;
+ var dist;
+ var pos = 0;
+
+ if (node.textContent.trim().length === 0) {
+ return false; // continue
+ }
+
+ // Start range
+ if (counter == 0) {
+ range = this.createRange();
+ range.startContainer = node;
+ range.startOffset = 0;
+ }
+
+ dist = _break - counter;
+
+ // Node is smaller than a break,
+ // skip over it
+ if (dist > len) {
+ counter += len;
+ pos = len;
+ }
+
+ while (pos < len) {
+ dist = _break - counter;
+
+ if (counter === 0) {
+ // Start new range
+ pos += 1;
+ range = this.createRange();
+ range.startContainer = node;
+ range.startOffset = pos;
+ }
+
+ // pos += dist;
+
+ // Gone over
+ if (pos + dist >= len) {
+ // Continue counter for next node
+ counter += len - pos;
+ // break
+ pos = len;
+ // At End
+ } else {
+ // Advance pos
+ pos += dist;
+
+ // End the previous range
+ range.endContainer = node;
+ range.endOffset = pos;
+ // cfi = section.cfiFromRange(range);
+ var cfi = new _epubcfi2.default(range, cfiBase).toString();
+ locations.push(cfi);
+ counter = 0;
+ }
+ }
+ prev = node;
+ };
+
+ (0, _core.sprint)(body, parser.bind(this));
+
+ // Close remaining
+ if (range && range.startContainer && prev) {
+ range.endContainer = prev;
+ range.endOffset = prev.length;
+ var cfi = new _epubcfi2.default(range, cfiBase).toString();
+ locations.push(cfi);
+ counter = 0;
+ }
+
+ return locations;
+ }
+
+ /**
+ * Get a location from an EpubCFI
+ * @param {EpubCFI} cfi
+ * @return {number}
+ */
+
+ }, {
+ key: "locationFromCfi",
+ value: function locationFromCfi(cfi) {
+ var loc = void 0;
+ if (_epubcfi2.default.prototype.isCfiString(cfi)) {
+ cfi = new _epubcfi2.default(cfi);
+ }
+ // Check if the location has not been set yet
+ if (this._locations.length === 0) {
+ return -1;
+ }
+
+ loc = (0, _core.locationOf)(cfi, this._locations, this.epubcfi.compare);
+
+ if (loc > this.total) {
+ return this.total;
+ }
+
+ return loc;
+ }
+
+ /**
+ * Get a percentage position in locations from an EpubCFI
+ * @param {EpubCFI} cfi
+ * @return {number}
+ */
+
+ }, {
+ key: "percentageFromCfi",
+ value: function percentageFromCfi(cfi) {
+ if (this._locations.length === 0) {
+ return null;
+ }
+ // Find closest cfi
+ var loc = this.locationFromCfi(cfi);
+ // Get percentage in total
+ return this.percentageFromLocation(loc);
+ }
+
+ /**
+ * Get a percentage position from a location index
+ * @param {number} location
+ * @return {number}
+ */
+
+ }, {
+ key: "percentageFromLocation",
+ value: function percentageFromLocation(loc) {
+ if (!loc || !this.total) {
+ return 0;
+ }
+
+ return loc / this.total;
+ }
+
+ /**
+ * Get an EpubCFI from location index
+ * @param {number} loc
+ * @return {EpubCFI} cfi
+ */
+
+ }, {
+ key: "cfiFromLocation",
+ value: function cfiFromLocation(loc) {
+ var cfi = -1;
+ // check that pg is an int
+ if (typeof loc != "number") {
+ loc = parseInt(loc);
+ }
+
+ if (loc >= 0 && loc < this._locations.length) {
+ cfi = this._locations[loc];
+ }
+
+ return cfi;
+ }
+
+ /**
+ * Get an EpubCFI from location percentage
+ * @param {number} percentage
+ * @return {EpubCFI} cfi
+ */
+
+ }, {
+ key: "cfiFromPercentage",
+ value: function cfiFromPercentage(percentage) {
+ var loc = void 0;
+ if (percentage > 1) {
+ console.warn("Normalize cfiFromPercentage value to between 0 - 1");
+ }
+
+ // Make sure 1 goes to very end
+ if (percentage >= 1) {
+ var cfi = new _epubcfi2.default(this._locations[this.total]);
+ cfi.collapse();
+ return cfi.toString();
+ }
+
+ loc = Math.ceil(this.total * percentage);
+ return this.cfiFromLocation(loc);
+ }
+
+ /**
+ * Load locations from JSON
+ * @param {json} locations
+ */
+
+ }, {
+ key: "load",
+ value: function load(locations) {
+ if (typeof locations === "string") {
+ this._locations = JSON.parse(locations);
+ } else {
+ this._locations = locations;
+ }
+ this.total = this._locations.length - 1;
+ return this._locations;
+ }
+
+ /**
+ * Save locations to JSON
+ * @return {json}
+ */
+
+ }, {
+ key: "save",
+ value: function save() {
+ return JSON.stringify(this._locations);
+ }
+ }, {
+ key: "getCurrent",
+ value: function getCurrent() {
+ return this._current;
+ }
+ }, {
+ key: "setCurrent",
+ value: function setCurrent(curr) {
+ var loc;
+
+ if (typeof curr == "string") {
+ this._currentCfi = curr;
+ } else if (typeof curr == "number") {
+ this._current = curr;
+ } else {
+ return;
+ }
+
+ if (this._locations.length === 0) {
+ return;
+ }
+
+ if (typeof curr == "string") {
+ loc = this.locationFromCfi(curr);
+ this._current = loc;
+ } else {
+ loc = curr;
+ }
+
+ this.emit(_constants.EVENTS.LOCATIONS.CHANGED, {
+ percentage: this.percentageFromLocation(loc)
+ });
+ }
+
+ /**
+ * Get the current location
+ */
+
+ }, {
+ key: "length",
+
+
+ /**
+ * Locations length
+ */
+ value: function length() {
+ return this._locations.length;
+ }
+ }, {
+ key: "destroy",
+ value: function destroy() {
+ this.spine = undefined;
+ this.request = undefined;
+ this.pause = undefined;
+
+ this.q.stop();
+ this.q = undefined;
+ this.epubcfi = undefined;
+
+ this._locations = undefined;
+ this.total = undefined;
+
+ this.break = undefined;
+ this._current = undefined;
+
+ this.currentLocation = undefined;
+ this._currentCfi = undefined;
+ clearTimeout(this.processingTimeout);
+ }
+ }, {
+ key: "currentLocation",
+ get: function get() {
+ return this._current;
+ }
+
+ /**
+ * Set the current location
+ */
+ ,
+ set: function set(curr) {
+ this.setCurrent(curr);
+ }
+ }]);
+
+ return Locations;
+}();
+
+(0, _eventEmitter2.default)(Locations.prototype);
+
+exports.default = Locations;
+module.exports = exports["default"];
+
+/***/ }),
+/* 45 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+
+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; }; }();
+
+var _pathWebpack = __webpack_require__(6);
+
+var _pathWebpack2 = _interopRequireDefault(_pathWebpack);
+
+var _core = __webpack_require__(0);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+/**
+ * Handles Parsing and Accessing an Epub Container
+ * @class
+ * @param {document} [containerDocument] xml document
+ */
+var Container = function () {
+ function Container(containerDocument) {
+ _classCallCheck(this, Container);
+
+ this.packagePath = '';
+ this.directory = '';
+ this.encoding = '';
+
+ if (containerDocument) {
+ this.parse(containerDocument);
+ }
+ }
+
+ /**
+ * Parse the Container XML
+ * @param {document} containerDocument
+ */
+
+
+ _createClass(Container, [{
+ key: "parse",
+ value: function parse(containerDocument) {
+ //--
+ var rootfile;
+
+ if (!containerDocument) {
+ throw new Error("Container File Not Found");
+ }
+
+ rootfile = (0, _core.qs)(containerDocument, "rootfile");
+
+ if (!rootfile) {
+ throw new Error("No RootFile Found");
+ }
+
+ this.packagePath = rootfile.getAttribute("full-path");
+ this.directory = _pathWebpack2.default.dirname(this.packagePath);
+ this.encoding = containerDocument.xmlEncoding;
+ }
+ }, {
+ key: "destroy",
+ value: function destroy() {
+ this.packagePath = undefined;
+ this.directory = undefined;
+ this.encoding = undefined;
+ }
+ }]);
+
+ return Container;
+}();
+
+exports.default = Container;
+module.exports = exports["default"];
+
+/***/ }),
+/* 46 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+
+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; }; }();
+
+var _core = __webpack_require__(0);
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+/**
+ * Open Packaging Format Parser
+ * @class
+ * @param {document} packageDocument OPF XML
+ */
+var Packaging = function () {
+ function Packaging(packageDocument) {
+ _classCallCheck(this, Packaging);
+
+ this.manifest = {};
+ this.navPath = '';
+ this.ncxPath = '';
+ this.coverPath = '';
+ this.spineNodeIndex = 0;
+ this.spine = [];
+ this.metadata = {};
+
+ if (packageDocument) {
+ this.parse(packageDocument);
+ }
+ }
+
+ /**
+ * Parse OPF XML
+ * @param {document} packageDocument OPF XML
+ * @return {object} parsed package parts
+ */
+
+
+ _createClass(Packaging, [{
+ key: 'parse',
+ value: function parse(packageDocument) {
+ var metadataNode, manifestNode, spineNode;
+
+ if (!packageDocument) {
+ throw new Error("Package File Not Found");
+ }
+
+ metadataNode = (0, _core.qs)(packageDocument, "metadata");
+ if (!metadataNode) {
+ throw new Error("No Metadata Found");
+ }
+
+ manifestNode = (0, _core.qs)(packageDocument, "manifest");
+ if (!manifestNode) {
+ throw new Error("No Manifest Found");
+ }
+
+ spineNode = (0, _core.qs)(packageDocument, "spine");
+ if (!spineNode) {
+ throw new Error("No Spine Found");
+ }
+
+ this.manifest = this.parseManifest(manifestNode);
+ this.navPath = this.findNavPath(manifestNode);
+ this.ncxPath = this.findNcxPath(manifestNode, spineNode);
+ this.coverPath = this.findCoverPath(packageDocument);
+
+ this.spineNodeIndex = (0, _core.indexOfElementNode)(spineNode);
+
+ this.spine = this.parseSpine(spineNode, this.manifest);
+
+ this.metadata = this.parseMetadata(metadataNode);
+
+ this.metadata.direction = spineNode.getAttribute("page-progression-direction");
+
+ return {
+ "metadata": this.metadata,
+ "spine": this.spine,
+ "manifest": this.manifest,
+ "navPath": this.navPath,
+ "ncxPath": this.ncxPath,
+ "coverPath": this.coverPath,
+ "spineNodeIndex": this.spineNodeIndex
+ };
+ }
+
+ /**
+ * Parse Metadata
+ * @private
+ * @param {document} xml
+ * @return {object} metadata
+ */
+
+ }, {
+ key: 'parseMetadata',
+ value: function parseMetadata(xml) {
+ var metadata = {};
+
+ metadata.title = this.getElementText(xml, "title");
+ metadata.creator = this.getElementText(xml, "creator");
+ metadata.description = this.getElementText(xml, "description");
+
+ metadata.pubdate = this.getElementText(xml, "date");
+
+ metadata.publisher = this.getElementText(xml, "publisher");
+
+ metadata.identifier = this.getElementText(xml, "identifier");
+ metadata.language = this.getElementText(xml, "language");
+ metadata.rights = this.getElementText(xml, "rights");
+
+ metadata.modified_date = this.getPropertyText(xml, "dcterms:modified");
+
+ metadata.layout = this.getPropertyText(xml, "rendition:layout");
+ metadata.orientation = this.getPropertyText(xml, "rendition:orientation");
+ metadata.flow = this.getPropertyText(xml, "rendition:flow");
+ metadata.viewport = this.getPropertyText(xml, "rendition:viewport");
+ // metadata.page_prog_dir = packageXml.querySelector("spine").getAttribute("page-progression-direction");
+
+ return metadata;
+ }
+
+ /**
+ * Parse Manifest
+ * @private
+ * @param {document} manifestXml
+ * @return {object} manifest
+ */
+
+ }, {
+ key: 'parseManifest',
+ value: function parseManifest(manifestXml) {
+ var manifest = {};
+
+ //-- Turn items into an array
+ // var selected = manifestXml.querySelectorAll("item");
+ var selected = (0, _core.qsa)(manifestXml, "item");
+ var items = Array.prototype.slice.call(selected);
+
+ //-- Create an object with the id as key
+ items.forEach(function (item) {
+ var id = item.getAttribute("id"),
+ href = item.getAttribute("href") || "",
+ type = item.getAttribute("media-type") || "",
+ properties = item.getAttribute("properties") || "";
+
+ manifest[id] = {
+ "href": href,
+ // "url" : href,
+ "type": type,
+ "properties": properties.length ? properties.split(" ") : []
+ };
+ });
+
+ return manifest;
+ }
+
+ /**
+ * Parse Spine
+ * @param {document} spineXml
+ * @param {Packaging.manifest} manifest
+ * @return {object} spine
+ */
+
+ }, {
+ key: 'parseSpine',
+ value: function parseSpine(spineXml, manifest) {
+ var spine = [];
+
+ var selected = (0, _core.qsa)(spineXml, "itemref");
+ var items = Array.prototype.slice.call(selected);
+
+ // var epubcfi = new EpubCFI();
+
+ //-- Add to array to mantain ordering and cross reference with manifest
+ items.forEach(function (item, index) {
+ var idref = item.getAttribute("idref");
+ // var cfiBase = epubcfi.generateChapterComponent(spineNodeIndex, index, Id);
+ var props = item.getAttribute("properties") || "";
+ var propArray = props.length ? props.split(" ") : [];
+ // var manifestProps = manifest[Id].properties;
+ // var manifestPropArray = manifestProps.length ? manifestProps.split(" ") : [];
+
+ var itemref = {
+ "idref": idref,
+ "linear": item.getAttribute("linear") || "yes",
+ "properties": propArray,
+ // "href" : manifest[Id].href,
+ // "url" : manifest[Id].url,
+ "index": index
+ // "cfiBase" : cfiBase
+ };
+ spine.push(itemref);
+ });
+
+ return spine;
+ }
+
+ /**
+ * Find TOC NAV
+ * @private
+ */
+
+ }, {
+ key: 'findNavPath',
+ value: function findNavPath(manifestNode) {
+ // Find item with property "nav"
+ // Should catch nav irregardless of order
+ // var node = manifestNode.querySelector("item[properties$='nav'], item[properties^='nav '], item[properties*=' nav ']");
+ var node = (0, _core.qsp)(manifestNode, "item", { "properties": "nav" });
+ return node ? node.getAttribute("href") : false;
+ }
+
+ /**
+ * Find TOC NCX
+ * media-type="application/x-dtbncx+xml" href="toc.ncx"
+ * @private
+ */
+
+ }, {
+ key: 'findNcxPath',
+ value: function findNcxPath(manifestNode, spineNode) {
+ // var node = manifestNode.querySelector("item[media-type='application/x-dtbncx+xml']");
+ var node = (0, _core.qsp)(manifestNode, "item", { "media-type": "application/x-dtbncx+xml" });
+ 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
+ // according to http://www.idpf.org/epub/20/spec/OPF_2.0.1_draft.htm#Section2.4.1.2,
+ // "The item that describes the NCX must be referenced by the spine toc attribute."
+ if (!node) {
+ tocId = spineNode.getAttribute("toc");
+ if (tocId) {
+ // node = manifestNode.querySelector("item[id='" + tocId + "']");
+ node = manifestNode.getElementById(tocId);
+ }
+ }
+
+ return node ? node.getAttribute("href") : false;
+ }
+
+ /**
+ * Find the Cover Path
+ *
+ * Fallback for Epub 2.0
+ * @param {document} packageXml
+ * @return {string} href
+ */
+
+ }, {
+ key: 'findCoverPath',
+ value: function findCoverPath(packageXml) {
+ var pkg = (0, _core.qs)(packageXml, "package");
+ var epubVersion = pkg.getAttribute("version");
+
+ if (epubVersion === "2.0") {
+ var metaCover = (0, _core.qsp)(packageXml, "meta", { "name": "cover" });
+ if (metaCover) {
+ var coverId = metaCover.getAttribute("content");
+ // var cover = packageXml.querySelector("item[id='" + coverId + "']");
+ var cover = packageXml.getElementById(coverId);
+ return cover ? cover.getAttribute("href") : "";
+ } else {
+ return false;
+ }
+ } else {
+ // var node = packageXml.querySelector("item[properties='cover-image']");
+ var node = (0, _core.qsp)(packageXml, "item", { "properties": "cover-image" });
+ return node ? node.getAttribute("href") : "";
+ }
+ }
+
+ /**
+ * Get text of a namespaced element
+ * @private
+ * @param {document} xml
+ * @param {string} tag
+ * @return {string} text
+ */
+
+ }, {
+ key: 'getElementText',
+ value: function getElementText(xml, tag) {
+ var found = xml.getElementsByTagNameNS("http://purl.org/dc/elements/1.1/", tag);
+ var el;
+
+ if (!found || found.length === 0) return "";
+
+ el = found[0];
+
+ if (el.childNodes.length) {
+ return el.childNodes[0].nodeValue;
+ }
+
+ return "";
+ }
+
+ /**
+ * Get text by property
+ * @private
+ * @param {document} xml
+ * @param {string} property
+ * @return {string} text
+ */
+
+ }, {
+ key: 'getPropertyText',
+ value: function getPropertyText(xml, property) {
+ var el = (0, _core.qsp)(xml, "meta", { "property": property });
+
+ if (el && el.childNodes.length) {
+ return el.childNodes[0].nodeValue;
+ }
+
+ return "";
+ }
+
+ /**
+ * Load JSON Manifest
+ * @param {document} packageDocument OPF XML
+ * @return {object} parsed package parts
+ */
+
+ }, {
+ key: 'load',
+ value: function load(json) {
+ var _this = this;
+
+ this.metadata = json.metadata;
+
+ this.spine = json.spine.map(function (item, index) {
+ item.index = index;
+ return item;
+ });
+
+ json.resources.forEach(function (item, index) {
+ _this.manifest[index] = item;
+
+ if (item.rel && item.rel[0] === "cover") {
+ _this.coverPath = item.href;
+ }
+ });
+
+ this.spineNodeIndex = 0;
+
+ this.toc = json.toc.map(function (item, index) {
+ item.label = item.title;
+ return item;
+ });
+
+ return {
+ "metadata": this.metadata,
+ "spine": this.spine,
+ "manifest": this.manifest,
+ "navPath": this.navPath,
+ "ncxPath": this.ncxPath,
+ "coverPath": this.coverPath,
+ "spineNodeIndex": this.spineNodeIndex,
+ "toc": this.toc
+ };
+ }
+ }, {
+ key: 'destroy',
+ value: function destroy() {
+ this.manifest = undefined;
+ this.navPath = undefined;
+ this.ncxPath = undefined;
+ this.coverPath = undefined;
+ this.spineNodeIndex = undefined;
+ this.spine = undefined;
+ this.metadata = undefined;
+ }
+ }]);
+
+ return Packaging;
+}();
+
+exports.default = Packaging;
+module.exports = exports['default'];
+
+/***/ }),
+/* 47 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+
+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; }; }();
+
+var _core = __webpack_require__(0);
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+/**
+ * Navigation Parser
+ * @param {document} xml navigation html / xhtml / ncx
+ */
+var Navigation = function () {
+ function Navigation(xml) {
+ _classCallCheck(this, Navigation);
+
+ this.toc = [];
+ this.tocByHref = {};
+ this.tocById = {};
+
+ this.landmarks = [];
+ this.landmarksByType = {};
+
+ this.length = 0;
+ if (xml) {
+ this.parse(xml);
+ }
+ }
+
+ /**
+ * Parse out the navigation items
+ * @param {document} xml navigation html / xhtml / ncx
+ */
+
+
+ _createClass(Navigation, [{
+ key: "parse",
+ value: function parse(xml) {
+ var isXml = xml.nodeType;
+ var html = void 0;
+ var ncx = void 0;
+
+ if (isXml) {
+ html = (0, _core.qs)(xml, "html");
+ ncx = (0, _core.qs)(xml, "ncx");
+ }
+
+ if (!isXml) {
+ this.toc = this.load(xml);
+ } else if (html) {
+ this.toc = this.parseNav(xml);
+ this.landmarks = this.parseLandmarks(xml);
+ } else if (ncx) {
+ this.toc = this.parseNcx(xml);
+ }
+
+ this.length = 0;
+
+ this.unpack(this.toc);
+ }
+
+ /**
+ * Unpack navigation items
+ * @private
+ * @param {array} toc
+ */
+
+ }, {
+ key: "unpack",
+ value: function unpack(toc) {
+ var item;
+
+ for (var i = 0; i < toc.length; i++) {
+ item = toc[i];
+
+ if (item.href) {
+ this.tocByHref[item.href] = i;
+ }
+
+ if (item.id) {
+ this.tocById[item.id] = i;
+ }
+
+ this.length++;
+
+ if (item.subitems.length) {
+ this.unpack(item.subitems);
+ }
+ }
+ }
+
+ /**
+ * Get an item from the navigation
+ * @param {string} target
+ * @return {object} navItems
+ */
+
+ }, {
+ key: "get",
+ value: function get(target) {
+ var index;
+
+ if (!target) {
+ return this.toc;
+ }
+
+ if (target.indexOf("#") === 0) {
+ index = this.tocById[target.substring(1)];
+ } else if (target in this.tocByHref) {
+ index = this.tocByHref[target];
+ }
+
+ return this.toc[index];
+ }
+
+ /**
+ * Get a landmark by type
+ * List of types: https://idpf.github.io/epub-vocabs/structure/
+ * @param {string} type
+ * @return {object} landmarkItems
+ */
+
+ }, {
+ key: "landmark",
+ value: function landmark(type) {
+ var index;
+
+ if (!type) {
+ return this.landmarks;
+ }
+
+ index = this.landmarksByType[type];
+
+ return this.landmarks[index];
+ }
+
+ /**
+ * Parse toc from a Epub > 3.0 Nav
+ * @private
+ * @param {document} navHtml
+ * @return {array} navigation list
+ */
+
+ }, {
+ key: "parseNav",
+ value: function parseNav(navHtml) {
+ var navElement = (0, _core.querySelectorByType)(navHtml, "nav", "toc");
+ var navItems = navElement ? (0, _core.qsa)(navElement, "li") : [];
+ var length = navItems.length;
+ var i;
+ var toc = {};
+ var list = [];
+ var item, parent;
+
+ if (!navItems || length === 0) return list;
+
+ for (i = 0; i < length; ++i) {
+ item = this.navItem(navItems[i]);
+ if (item) {
+ toc[item.id] = item;
+ if (!item.parent) {
+ list.push(item);
+ } else {
+ parent = toc[item.parent];
+ parent.subitems.push(item);
+ }
+ }
+ }
+
+ return list;
+ }
+
+ /**
+ * Create a navItem
+ * @private
+ * @param {element} item
+ * @return {object} navItem
+ */
+
+ }, {
+ key: "navItem",
+ value: function navItem(item) {
+ var id = item.getAttribute("id") || undefined;
+ var content = (0, _core.filterChildren)(item, "a", true);
+
+ if (!content) {
+ return;
+ }
+
+ var src = content.getAttribute("href") || "";
+ var text = content.textContent || "";
+ var subitems = [];
+ var parentItem = (0, _core.getParentByTagName)(item, "li");
+ var parent = void 0;
+
+ if (parentItem) {
+ parent = parentItem.getAttribute("id");
+ }
+
+ while (!parent && parentItem) {
+ parentItem = (0, _core.getParentByTagName)(parentItem, "li");
+ if (parentItem) {
+ parent = parentItem.getAttribute("id");
+ }
+ }
+
+ return {
+ "id": id,
+ "href": src,
+ "label": text,
+ "subitems": subitems,
+ "parent": parent
+ };
+ }
+
+ /**
+ * Parse landmarks from a Epub > 3.0 Nav
+ * @private
+ * @param {document} navHtml
+ * @return {array} landmarks list
+ */
+
+ }, {
+ key: "parseLandmarks",
+ value: function parseLandmarks(navHtml) {
+ var navElement = (0, _core.querySelectorByType)(navHtml, "nav", "landmarks");
+ var navItems = navElement ? (0, _core.qsa)(navElement, "li") : [];
+ var length = navItems.length;
+ var i;
+ var list = [];
+ var item;
+
+ if (!navItems || length === 0) return list;
+
+ for (i = 0; i < length; ++i) {
+ item = this.landmarkItem(navItems[i]);
+ if (item) {
+ list.push(item);
+ this.landmarksByType[item.type] = i;
+ }
+ }
+
+ return list;
+ }
+
+ /**
+ * Create a landmarkItem
+ * @private
+ * @param {element} item
+ * @return {object} landmarkItem
+ */
+
+ }, {
+ key: "landmarkItem",
+ value: function landmarkItem(item) {
+ var content = (0, _core.filterChildren)(item, "a", true);
+
+ if (!content) {
+ return;
+ }
+
+ var type = content.getAttributeNS("http://www.idpf.org/2007/ops", "type") || undefined;
+ var href = content.getAttribute("href") || "";
+ var text = content.textContent || "";
+
+ return {
+ "href": href,
+ "label": text,
+ "type": type
+ };
+ }
+
+ /**
+ * Parse from a Epub > 3.0 NC
+ * @private
+ * @param {document} navHtml
+ * @return {array} navigation list
+ */
+
+ }, {
+ key: "parseNcx",
+ value: function parseNcx(tocXml) {
+ var navPoints = (0, _core.qsa)(tocXml, "navPoint");
+ var length = navPoints.length;
+ var i;
+ var toc = {};
+ var list = [];
+ var item, parent;
+
+ if (!navPoints || length === 0) return list;
+
+ for (i = 0; i < length; ++i) {
+ item = this.ncxItem(navPoints[i]);
+ toc[item.id] = item;
+ if (!item.parent) {
+ list.push(item);
+ } else {
+ parent = toc[item.parent];
+ parent.subitems.push(item);
+ }
+ }
+
+ return list;
+ }
+
+ /**
+ * Create a ncxItem
+ * @private
+ * @param {element} item
+ * @return {object} ncxItem
+ */
+
+ }, {
+ key: "ncxItem",
+ value: function ncxItem(item) {
+ var id = item.getAttribute("id") || false,
+ content = (0, _core.qs)(item, "content"),
+ src = content.getAttribute("src"),
+ navLabel = (0, _core.qs)(item, "navLabel"),
+ text = navLabel.textContent ? navLabel.textContent : "",
+ subitems = [],
+ parentNode = item.parentNode,
+ parent;
+
+ if (parentNode && parentNode.nodeName === "navPoint") {
+ parent = parentNode.getAttribute("id");
+ }
+
+ return {
+ "id": id,
+ "href": src,
+ "label": text,
+ "subitems": subitems,
+ "parent": parent
+ };
+ }
+
+ /**
+ * Load Spine Items
+ * @param {object} json the items to be loaded
+ */
+
+ }, {
+ key: "load",
+ value: function load(json) {
+ var _this = this;
+
+ return json.map(function (item) {
+ item.label = item.title;
+ if (item.children) {
+ item.subitems = _this.load(item.children);
+ }
+ return item;
+ });
+ }
+
+ /**
+ * forEach pass through
+ * @param {Function} fn function to run on each item
+ * @return {method} forEach loop
+ */
+
+ }, {
+ key: "forEach",
+ value: function forEach(fn) {
+ return this.toc.forEach(fn);
+ }
+ }]);
+
+ return Navigation;
+}();
+
+exports.default = Navigation;
+module.exports = exports["default"];
+
+/***/ }),
+/* 48 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+
+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; }; }();
+
+var _replacements = __webpack_require__(7);
+
+var _core = __webpack_require__(0);
+
+var _url = __webpack_require__(5);
+
+var _url2 = _interopRequireDefault(_url);
+
+var _mime = __webpack_require__(17);
+
+var _mime2 = _interopRequireDefault(_mime);
+
+var _path = __webpack_require__(4);
+
+var _path2 = _interopRequireDefault(_path);
+
+var _pathWebpack = __webpack_require__(6);
+
+var _pathWebpack2 = _interopRequireDefault(_pathWebpack);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+/**
+ * Handle Package Resources
+ * @class
+ * @param {Manifest} manifest
+ * @param {[object]} options
+ * @param {[string="base64"]} options.replacements
+ * @param {[Archive]} options.archive
+ * @param {[method]} options.resolver
+ */
+var Resources = function () {
+ function Resources(manifest, options) {
+ _classCallCheck(this, Resources);
+
+ this.settings = {
+ replacements: options && options.replacements || "base64",
+ archive: options && options.archive,
+ resolver: options && options.resolver,
+ request: options && options.request
+ };
+ this.manifest = manifest;
+ this.resources = Object.keys(manifest).map(function (key) {
+ return manifest[key];
+ });
+
+ this.replacementUrls = [];
+
+ this.html = [];
+ this.assets = [];
+ this.css = [];
+
+ this.urls = [];
+ this.cssUrls = [];
+
+ this.split();
+ this.splitUrls();
+ }
+
+ /**
+ * Split resources by type
+ * @private
+ */
+
+
+ _createClass(Resources, [{
+ key: "split",
+ value: function split() {
+
+ // HTML
+ this.html = this.resources.filter(function (item) {
+ if (item.type === "application/xhtml+xml" || item.type === "text/html") {
+ return true;
+ }
+ });
+
+ // Exclude HTML
+ this.assets = this.resources.filter(function (item) {
+ if (item.type !== "application/xhtml+xml" && item.type !== "text/html") {
+ return true;
+ }
+ });
+
+ // Only CSS
+ this.css = this.resources.filter(function (item) {
+ if (item.type === "text/css") {
+ return true;
+ }
+ });
+ }
+
+ /**
+ * Convert split resources into Urls
+ * @private
+ */
+
+ }, {
+ key: "splitUrls",
+ value: function splitUrls() {
+
+ // All Assets Urls
+ this.urls = this.assets.map(function (item) {
+ return item.href;
+ }.bind(this));
+
+ // Css Urls
+ this.cssUrls = this.css.map(function (item) {
+ return item.href;
+ });
+ }
+ }, {
+ key: "createUrl",
+ value: function createUrl(url) {
+ var parsedUrl = new _url2.default(url);
+ var mimeType = _mime2.default.lookup(parsedUrl.filename);
+
+ if (this.settings.archive) {
+ return this.settings.archive.createUrl(url, { "base64": this.settings.replacements === "base64" });
+ } else {
+ if (this.settings.replacements === "base64") {
+ return this.settings.request(url, 'blob').then(function (blob) {
+ return (0, _core.blob2base64)(blob);
+ }).then(function (blob) {
+ return (0, _core.createBase64Url)(blob, mimeType);
+ });
+ } else {
+ return this.settings.request(url, 'blob').then(function (blob) {
+ return (0, _core.createBlobUrl)(blob, mimeType);
+ });
+ }
+ }
+ }
+
+ /**
+ * Create blob urls for all the assets
+ * @return {Promise} returns replacement urls
+ */
+
+ }, {
+ key: "replacements",
+ value: function replacements() {
+ var _this = this;
+
+ if (this.settings.replacements === "none") {
+ return new Promise(function (resolve) {
+ resolve(this.urls);
+ }.bind(this));
+ }
+
+ var replacements = this.urls.map(function (url) {
+ var absolute = _this.settings.resolver(url);
+
+ return _this.createUrl(absolute).catch(function (err) {
+ console.error(err);
+ return null;
+ });
+ });
+
+ return Promise.all(replacements).then(function (replacementUrls) {
+ _this.replacementUrls = replacementUrls.filter(function (url) {
+ return typeof url === "string";
+ });
+ return replacementUrls;
+ });
+ }
+
+ /**
+ * Replace URLs in CSS resources
+ * @private
+ * @param {Archive} [archive]
+ * @param {method} [resolver]
+ * @return {Promise}
+ */
+
+ }, {
+ key: "replaceCss",
+ value: function replaceCss(archive, resolver) {
+ var replaced = [];
+ archive = archive || this.settings.archive;
+ resolver = resolver || this.settings.resolver;
+ this.cssUrls.forEach(function (href) {
+ var replacement = this.createCssFile(href, archive, resolver).then(function (replacementUrl) {
+ // switch the url in the replacementUrls
+ var indexInUrls = this.urls.indexOf(href);
+ if (indexInUrls > -1) {
+ this.replacementUrls[indexInUrls] = replacementUrl;
+ }
+ }.bind(this));
+
+ replaced.push(replacement);
+ }.bind(this));
+ return Promise.all(replaced);
+ }
+
+ /**
+ * Create a new CSS file with the replaced URLs
+ * @private
+ * @param {string} href the original css file
+ * @return {Promise} returns a BlobUrl to the new CSS file or a data url
+ */
+
+ }, {
+ key: "createCssFile",
+ value: function createCssFile(href) {
+ var _this2 = this;
+
+ var newUrl;
+
+ if (_pathWebpack2.default.isAbsolute(href)) {
+ return new Promise(function (resolve) {
+ resolve();
+ });
+ }
+
+ var absolute = this.settings.resolver(href);
+
+ // Get the text of the css file from the archive
+ var textResponse;
+
+ if (this.settings.archive) {
+ textResponse = this.settings.archive.getText(absolute);
+ } else {
+ textResponse = this.settings.request(absolute, "text");
+ }
+
+ // Get asset links relative to css file
+ var relUrls = this.urls.map(function (assetHref) {
+ var resolved = _this2.settings.resolver(assetHref);
+ var relative = new _path2.default(absolute).relative(resolved);
+
+ return relative;
+ });
+
+ if (!textResponse) {
+ // file not found, don't replace
+ return new Promise(function (resolve) {
+ resolve();
+ });
+ }
+
+ return textResponse.then(function (text) {
+ // Replacements in the css text
+ text = (0, _replacements.substitute)(text, relUrls, _this2.replacementUrls);
+
+ // Get the new url
+ if (_this2.settings.replacements === "base64") {
+ newUrl = (0, _core.createBase64Url)(text, "text/css");
+ } else {
+ newUrl = (0, _core.createBlobUrl)(text, "text/css");
+ }
+
+ return newUrl;
+ }, function (err) {
+ // handle response errors
+ return new Promise(function (resolve) {
+ resolve();
+ });
+ });
+ }
+
+ /**
+ * Resolve all resources URLs relative to an absolute URL
+ * @param {string} absolute to be resolved to
+ * @param {[resolver]} resolver
+ * @return {string[]} array with relative Urls
+ */
+
+ }, {
+ key: "relativeTo",
+ value: function relativeTo(absolute, resolver) {
+ resolver = resolver || this.settings.resolver;
+
+ // Get Urls relative to current sections
+ return this.urls.map(function (href) {
+ var resolved = resolver(href);
+ var relative = new _path2.default(absolute).relative(resolved);
+ return relative;
+ }.bind(this));
+ }
+
+ /**
+ * Get a URL for a resource
+ * @param {string} path
+ * @return {string} url
+ */
+
+ }, {
+ key: "get",
+ value: function get(path) {
+ var indexInUrls = this.urls.indexOf(path);
+ if (indexInUrls === -1) {
+ return;
+ }
+ if (this.replacementUrls.length) {
+ return new Promise(function (resolve, reject) {
+ resolve(this.replacementUrls[indexInUrls]);
+ }.bind(this));
+ } else {
+ return this.createUrl(path);
+ }
+ }
+
+ /**
+ * Substitute urls in content, with replacements,
+ * relative to a url if provided
+ * @param {string} content
+ * @param {string} [url] url to resolve to
+ * @return {string} content with urls substituted
+ */
+
+ }, {
+ key: "substitute",
+ value: function substitute(content, url) {
+ var relUrls;
+ if (url) {
+ relUrls = this.relativeTo(url);
+ } else {
+ relUrls = this.urls;
+ }
+ return (0, _replacements.substitute)(content, relUrls, this.replacementUrls);
+ }
+ }, {
+ key: "destroy",
+ value: function destroy() {
+ this.settings = undefined;
+ this.manifest = undefined;
+ this.resources = undefined;
+ this.replacementUrls = undefined;
+ this.html = undefined;
+ this.assets = undefined;
+ this.css = undefined;
+
+ this.urls = undefined;
+ this.cssUrls = undefined;
+ }
+ }]);
+
+ return Resources;
+}();
+
+exports.default = Resources;
+module.exports = exports["default"];
+
+/***/ }),
+/* 49 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+
+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; }; }();
+
+var _epubcfi = __webpack_require__(1);
+
+var _epubcfi2 = _interopRequireDefault(_epubcfi);
+
+var _core = __webpack_require__(0);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+/**
+ * Page List Parser
+ * @param {document} [xml]
+ */
+var PageList = function () {
+ function PageList(xml) {
+ _classCallCheck(this, PageList);
+
+ this.pages = [];
+ this.locations = [];
+ this.epubcfi = new _epubcfi2.default();
+
+ this.firstPage = 0;
+ this.lastPage = 0;
+ this.totalPages = 0;
+
+ this.toc = undefined;
+ this.ncx = undefined;
+
+ if (xml) {
+ this.pageList = this.parse(xml);
+ }
+
+ if (this.pageList && this.pageList.length) {
+ this.process(this.pageList);
+ }
+ }
+
+ /**
+ * Parse PageList Xml
+ * @param {document} xml
+ */
+
+
+ _createClass(PageList, [{
+ key: "parse",
+ value: function parse(xml) {
+ var html = (0, _core.qs)(xml, "html");
+ var ncx = (0, _core.qs)(xml, "ncx");
+
+ if (html) {
+ return this.parseNav(xml);
+ } else if (ncx) {
+ // Not supported
+ // return this.parseNcx(xml);
+ return;
+ }
+ }
+
+ /**
+ * Parse a Nav PageList
+ * @private
+ * @param {document} navHtml
+ * @return {PageList.item[]} list
+ */
+
+ }, {
+ key: "parseNav",
+ value: function parseNav(navHtml) {
+ var navElement = (0, _core.querySelectorByType)(navHtml, "nav", "page-list");
+ var navItems = navElement ? (0, _core.qsa)(navElement, "li") : [];
+ var length = navItems.length;
+ var i;
+ var list = [];
+ var item;
+
+ if (!navItems || length === 0) return list;
+
+ for (i = 0; i < length; ++i) {
+ item = this.item(navItems[i]);
+ list.push(item);
+ }
+
+ return list;
+ }
+
+ /**
+ * Page List Item
+ * @private
+ * @param {object} item
+ * @return {object} pageListItem
+ */
+
+ }, {
+ key: "item",
+ value: function item(_item) {
+ var content = (0, _core.qs)(_item, "a"),
+ href = content.getAttribute("href") || "",
+ text = content.textContent || "",
+ page = parseInt(text),
+ isCfi = href.indexOf("epubcfi"),
+ split,
+ packageUrl,
+ cfi;
+
+ if (isCfi != -1) {
+ split = href.split("#");
+ packageUrl = split[0];
+ cfi = split.length > 1 ? split[1] : false;
+ return {
+ "cfi": cfi,
+ "href": href,
+ "packageUrl": packageUrl,
+ "page": page
+ };
+ } else {
+ return {
+ "href": href,
+ "page": page
+ };
+ }
+ }
+
+ /**
+ * Process pageList items
+ * @private
+ * @param {array} pageList
+ */
+
+ }, {
+ key: "process",
+ value: function process(pageList) {
+ pageList.forEach(function (item) {
+ this.pages.push(item.page);
+ if (item.cfi) {
+ this.locations.push(item.cfi);
+ }
+ }, this);
+ this.firstPage = parseInt(this.pages[0]);
+ this.lastPage = parseInt(this.pages[this.pages.length - 1]);
+ this.totalPages = this.lastPage - this.firstPage;
+ }
+
+ /**
+ * Get a PageList result from a EpubCFI
+ * @param {string} cfi EpubCFI String
+ * @return {string} page
+ */
+
+ }, {
+ key: "pageFromCfi",
+ value: function pageFromCfi(cfi) {
+ var pg = -1;
+
+ // Check if the pageList has not been set yet
+ if (this.locations.length === 0) {
+ return -1;
+ }
+
+ // TODO: check if CFI is valid?
+
+ // check if the cfi is in the location list
+ // var index = this.locations.indexOf(cfi);
+ var index = (0, _core.indexOfSorted)(cfi, this.locations, this.epubcfi.compare);
+ if (index != -1) {
+ pg = this.pages[index];
+ } else {
+ // Otherwise add it to the list of locations
+ // Insert it in the correct position in the locations page
+ //index = EPUBJS.core.insert(cfi, this.locations, this.epubcfi.compare);
+ index = (0, _core.locationOf)(cfi, this.locations, this.epubcfi.compare);
+ // Get the page at the location just before the new one, or return the first
+ pg = index - 1 >= 0 ? this.pages[index - 1] : this.pages[0];
+ if (pg !== undefined) {
+ // Add the new page in so that the locations and page array match up
+ //this.pages.splice(index, 0, pg);
+ } else {
+ pg = -1;
+ }
+ }
+ return pg;
+ }
+
+ /**
+ * Get an EpubCFI from a Page List Item
+ * @param {string} pg
+ * @return {string} cfi
+ */
+
+ }, {
+ key: "cfiFromPage",
+ value: function cfiFromPage(pg) {
+ var cfi = -1;
+ // check that pg is an int
+ if (typeof pg != "number") {
+ pg = parseInt(pg);
+ }
+
+ // check if the cfi is in the page list
+ // Pages could be unsorted.
+ var index = this.pages.indexOf(pg);
+ if (index != -1) {
+ cfi = this.locations[index];
+ }
+ // TODO: handle pages not in the list
+ return cfi;
+ }
+
+ /**
+ * Get a Page from Book percentage
+ * @param {number} percent
+ * @return {string} page
+ */
+
+ }, {
+ key: "pageFromPercentage",
+ value: function pageFromPercentage(percent) {
+ var pg = Math.round(this.totalPages * percent);
+ return pg;
+ }
+
+ /**
+ * Returns a value between 0 - 1 corresponding to the location of a page
+ * @param {int} pg the page
+ * @return {number} percentage
+ */
+
+ }, {
+ key: "percentageFromPage",
+ value: function percentageFromPage(pg) {
+ var percentage = (pg - this.firstPage) / this.totalPages;
+ return Math.round(percentage * 1000) / 1000;
+ }
+
+ /**
+ * Returns a value between 0 - 1 corresponding to the location of a cfi
+ * @param {string} cfi EpubCFI String
+ * @return {number} percentage
+ */
+
+ }, {
+ key: "percentageFromCfi",
+ value: function percentageFromCfi(cfi) {
+ var pg = this.pageFromCfi(cfi);
+ var percentage = this.percentageFromPage(pg);
+ return percentage;
+ }
+ }, {
+ key: "destroy",
+ value: function destroy() {
+ this.pages = undefined;
+ this.locations = undefined;
+ this.epubcfi = undefined;
+
+ this.pageList = undefined;
+
+ this.toc = undefined;
+ this.ncx = undefined;
+ }
+ }]);
+
+ return PageList;
+}();
+
+exports.default = PageList;
+module.exports = exports["default"];
+
+/***/ }),
+/* 50 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+
+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; }; }();
+
+var _core = __webpack_require__(0);
+
+var _constants = __webpack_require__(3);
+
+var _eventEmitter = __webpack_require__(2);
+
+var _eventEmitter2 = _interopRequireDefault(_eventEmitter);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+/**
+ * Figures out the CSS values to apply for a layout
+ * @class
+ * @param {object} settings
+ * @param {string} [settings.layout='reflowable']
+ * @param {string} [settings.spread]
+ * @param {int} [settings.minSpreadWidth=800]
+ * @param {boolean} [settings.evenSpreads=false]
+ */
+var Layout = function () {
+ function Layout(settings) {
+ _classCallCheck(this, Layout);
+
+ this.settings = settings;
+ this.name = settings.layout || "reflowable";
+ this._spread = settings.spread === "none" ? false : true;
+ this._minSpreadWidth = settings.minSpreadWidth || 800;
+ this._evenSpreads = settings.evenSpreads || false;
+
+ if (settings.flow === "scrolled" || settings.flow === "scrolled-continuous" || settings.flow === "scrolled-doc") {
+ this._flow = "scrolled";
+ } else {
+ this._flow = "paginated";
+ }
+
+ this.width = 0;
+ this.height = 0;
+ this.spreadWidth = 0;
+ this.delta = 0;
+
+ this.columnWidth = 0;
+ this.gap = 0;
+ this.divisor = 1;
+
+ this.props = {
+ name: this.name,
+ spread: this._spread,
+ flow: this._flow,
+ width: 0,
+ height: 0,
+ spreadWidth: 0,
+ delta: 0,
+ columnWidth: 0,
+ gap: 0,
+ divisor: 1
+ };
+ }
+
+ /**
+ * Switch the flow between paginated and scrolled
+ * @param {string} flow paginated | scrolled
+ */
+
+
+ _createClass(Layout, [{
+ key: "flow",
+ value: function flow(_flow) {
+ if (typeof _flow != "undefined") {
+ if (_flow === "scrolled" || _flow === "scrolled-continuous" || _flow === "scrolled-doc") {
+ this._flow = "scrolled";
+ } else {
+ this._flow = "paginated";
+ }
+ // this.props.flow = this._flow;
+ this.update({ flow: this._flow });
+ }
+ return this._flow;
+ }
+
+ /**
+ * Switch between using spreads or not, and set the
+ * width at which they switch to single.
+ * @param {string} spread true | false
+ * @param {boolean} min integer in pixels
+ */
+
+ }, {
+ key: "spread",
+ value: function spread(_spread, min) {
+
+ if (_spread) {
+ this._spread = _spread === "none" ? false : true;
+ // this.props.spread = this._spread;
+ this.update({ spread: this._spread });
+ }
+
+ if (min >= 0) {
+ this._minSpreadWidth = min;
+ }
+
+ return this._spread;
+ }
+
+ /**
+ * Calculate the dimensions of the pagination
+ * @param {number} _width [description]
+ * @param {number} _height [description]
+ * @param {number} _gap [description]
+ */
+
+ }, {
+ key: "calculate",
+ value: function calculate(_width, _height, _gap) {
+
+ var divisor = 1;
+ var gap = _gap || 0;
+
+ //-- Check the width and create even width columns
+ // var fullWidth = Math.floor(_width);
+ var width = _width;
+ var height = _height;
+
+ var section = Math.floor(width / 12);
+
+ var columnWidth;
+ var spreadWidth;
+ var pageWidth;
+ var delta;
+
+ if (this._spread && width >= this._minSpreadWidth) {
+ divisor = 2;
+ } else {
+ divisor = 1;
+ }
+
+ if (this.name === "reflowable" && this._flow === "paginated" && !(_gap >= 0)) {
+ gap = section % 2 === 0 ? section : section - 1;
+ }
+
+ if (this.name === "pre-paginated") {
+ gap = 0;
+ }
+
+ //-- Double Page
+ if (divisor > 1) {
+ // width = width - gap;
+ // columnWidth = (width - gap) / divisor;
+ // gap = gap / divisor;
+ columnWidth = width / divisor - gap;
+ pageWidth = columnWidth + gap;
+ } else {
+ columnWidth = width;
+ pageWidth = width;
+ }
+
+ if (this.name === "pre-paginated" && divisor > 1) {
+ width = columnWidth;
+ }
+
+ spreadWidth = columnWidth * divisor + gap;
+
+ delta = width;
+
+ this.width = width;
+ this.height = height;
+ this.spreadWidth = spreadWidth;
+ this.pageWidth = pageWidth;
+ this.delta = delta;
+
+ this.columnWidth = columnWidth;
+ this.gap = gap;
+ this.divisor = divisor;
+
+ // this.props.width = width;
+ // this.props.height = _height;
+ // this.props.spreadWidth = spreadWidth;
+ // this.props.pageWidth = pageWidth;
+ // this.props.delta = delta;
+ //
+ // this.props.columnWidth = colWidth;
+ // this.props.gap = gap;
+ // this.props.divisor = divisor;
+
+ this.update({
+ width: width,
+ height: height,
+ spreadWidth: spreadWidth,
+ pageWidth: pageWidth,
+ delta: delta,
+ columnWidth: columnWidth,
+ gap: gap,
+ divisor: divisor
+ });
+ }
+
+ /**
+ * Apply Css to a Document
+ * @param {Contents} contents
+ * @return {Promise}
+ */
+
+ }, {
+ key: "format",
+ value: function format(contents) {
+ var formating;
+
+ if (this.name === "pre-paginated") {
+ formating = contents.fit(this.columnWidth, this.height);
+ } else if (this._flow === "paginated") {
+ formating = contents.columns(this.width, this.height, this.columnWidth, this.gap);
+ } else {
+ // scrolled
+ formating = contents.size(this.width, null);
+ }
+
+ return formating; // might be a promise in some View Managers
+ }
+
+ /**
+ * Count number of pages
+ * @param {number} totalLength
+ * @param {number} pageLength
+ * @return {{spreads: Number, pages: Number}}
+ */
+
+ }, {
+ key: "count",
+ value: function count(totalLength, pageLength) {
+
+ var spreads = void 0,
+ pages = void 0;
+
+ if (this.name === "pre-paginated") {
+ spreads = 1;
+ pages = 1;
+ } else if (this._flow === "paginated") {
+ pageLength = pageLength || this.delta;
+ spreads = Math.ceil(totalLength / pageLength);
+ pages = spreads * this.divisor;
+ } else {
+ // scrolled
+ pageLength = pageLength || this.height;
+ spreads = Math.ceil(totalLength / pageLength);
+ pages = spreads;
+ }
+
+ return {
+ spreads: spreads,
+ pages: pages
+ };
+ }
+ }, {
+ key: "update",
+ value: function update(props) {
+ var _this = this;
+
+ // Remove props that haven't changed
+ Object.keys(props).forEach(function (propName) {
+ if (_this.props[propName] === props[propName]) {
+ delete props[propName];
+ }
+ });
+
+ if (Object.keys(props).length > 0) {
+ var newProps = (0, _core.extend)(this.props, props);
+ this.emit(_constants.EVENTS.LAYOUT.UPDATED, newProps, props);
+ }
+ }
+ }]);
+
+ return Layout;
+}();
+
+(0, _eventEmitter2.default)(Layout.prototype);
+
+exports.default = Layout;
+module.exports = exports["default"];
+
+/***/ }),
+/* 51 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+
+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; };
+
+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; }; }();
+
+var _url = __webpack_require__(5);
+
+var _url2 = _interopRequireDefault(_url);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+/**
+ * Themes to apply to displayed content
+ * @class
+ * @param {Rendition} rendition
+ */
+var Themes = function () {
+ function Themes(rendition) {
+ _classCallCheck(this, Themes);
+
+ this.rendition = rendition;
+ this._themes = {
+ "default": {
+ "rules": {},
+ "url": "",
+ "serialized": ""
+ }
+ };
+ this._overrides = {};
+ this._current = "default";
+ this._injected = [];
+ this.rendition.hooks.content.register(this.inject.bind(this));
+ this.rendition.hooks.content.register(this.overrides.bind(this));
+ }
+
+ /**
+ * Add themes to be used by a rendition
+ * @param {object | string}
+ * @example themes.register("light", "http://example.com/light.css")
+ * @example themes.register("light", { "body": { "color": "purple"}})
+ * @example themes.register({ "light" : {...}, "dark" : {...}})
+ */
+
+
+ _createClass(Themes, [{
+ key: "register",
+ value: function register() {
+ if (arguments.length === 0) {
+ return;
+ }
+ if (arguments.length === 1 && _typeof(arguments[0]) === "object") {
+ return this.registerThemes(arguments[0]);
+ }
+ if (arguments.length === 1 && typeof arguments[0] === "string") {
+ return this.default(arguments[0]);
+ }
+ if (arguments.length === 2 && typeof arguments[1] === "string") {
+ return this.registerUrl(arguments[0], arguments[1]);
+ }
+ if (arguments.length === 2 && _typeof(arguments[1]) === "object") {
+ return this.registerRules(arguments[0], arguments[1]);
+ }
+ }
+
+ /**
+ * Add a default theme to be used by a rendition
+ * @param {object | string} theme
+ * @example themes.register("http://example.com/default.css")
+ * @example themes.register({ "body": { "color": "purple"}})
+ */
+
+ }, {
+ key: "default",
+ value: function _default(theme) {
+ if (!theme) {
+ return;
+ }
+ if (typeof theme === "string") {
+ return this.registerUrl("default", theme);
+ }
+ if ((typeof theme === "undefined" ? "undefined" : _typeof(theme)) === "object") {
+ return this.registerRules("default", theme);
+ }
+ }
+ }, {
+ key: "registerThemes",
+ value: function registerThemes(themes) {
+ for (var theme in themes) {
+ if (themes.hasOwnProperty(theme)) {
+ if (typeof themes[theme] === "string") {
+ this.registerUrl(theme, themes[theme]);
+ } else {
+ this.registerRules(theme, themes[theme]);
+ }
+ }
+ }
+ }
+ }, {
+ key: "registerUrl",
+ value: function registerUrl(name, input) {
+ var url = new _url2.default(input);
+ this._themes[name] = { "url": url.toString() };
+ if (this._injected[name]) {
+ this.update(name);
+ }
+ }
+ }, {
+ key: "registerRules",
+ value: function registerRules(name, rules) {
+ this._themes[name] = { "rules": rules };
+ // TODO: serialize css rules
+ if (this._injected[name]) {
+ this.update(name);
+ }
+ }
+ }, {
+ key: "select",
+ value: function select(name) {
+ var prev = this._current;
+ var contents;
+
+ this._current = name;
+ this.update(name);
+
+ contents = this.rendition.getContents();
+ contents.forEach(function (content) {
+ content.removeClass(prev);
+ content.addClass(name);
+ });
+ }
+ }, {
+ key: "update",
+ value: function update(name) {
+ var _this = this;
+
+ var contents = this.rendition.getContents();
+ contents.forEach(function (content) {
+ _this.add(name, content);
+ });
+ }
+ }, {
+ key: "inject",
+ value: function inject(contents) {
+ var links = [];
+ var themes = this._themes;
+ var theme;
+
+ for (var name in themes) {
+ if (themes.hasOwnProperty(name) && (name === this._current || name === "default")) {
+ theme = themes[name];
+ if (theme.rules && Object.keys(theme.rules).length > 0 || theme.url && links.indexOf(theme.url) === -1) {
+ this.add(name, contents);
+ }
+ this._injected.push(name);
+ }
+ }
+
+ if (this._current != "default") {
+ contents.addClass(this._current);
+ }
+ }
+ }, {
+ key: "add",
+ value: function add(name, contents) {
+ var theme = this._themes[name];
+
+ if (!theme || !contents) {
+ return;
+ }
+
+ if (theme.url) {
+ contents.addStylesheet(theme.url);
+ } else if (theme.serialized) {
+ // TODO: handle serialized
+ } else if (theme.rules) {
+ contents.addStylesheetRules(theme.rules);
+ theme.injected = true;
+ }
+ }
+ }, {
+ key: "override",
+ value: function override(name, value) {
+ var _this2 = this;
+
+ var contents = this.rendition.getContents();
+
+ this._overrides[name] = value;
+
+ contents.forEach(function (content) {
+ content.css(name, _this2._overrides[name]);
+ });
+ }
+ }, {
+ key: "overrides",
+ value: function overrides(contents) {
+ var overrides = this._overrides;
+
+ for (var rule in overrides) {
+ if (overrides.hasOwnProperty(rule)) {
+ contents.css(rule, overrides[rule]);
+ }
+ }
+ }
+
+ /**
+ * Adjust the font size of a rendition
+ * @param {number} size
+ */
+
+ }, {
+ key: "fontSize",
+ value: function fontSize(size) {
+ this.override("font-size", size);
+ }
+
+ /**
+ * Adjust the font-family of a rendition
+ * @param {string} f
+ */
+
+ }, {
+ key: "font",
+ value: function font(f) {
+ this.override("font-family", f);
+ }
+ }, {
+ key: "destroy",
+ value: function destroy() {
+ this.rendition = undefined;
+ this._themes = undefined;
+ this._overrides = undefined;
+ this._current = undefined;
+ this._injected = undefined;
+ }
+ }]);
+
+ return Themes;
+}();
+
+exports.default = Themes;
+module.exports = exports["default"];
+
+/***/ }),
+/* 52 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+
+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; }; }();
+
+var _eventEmitter = __webpack_require__(2);
+
+var _eventEmitter2 = _interopRequireDefault(_eventEmitter);
+
+var _epubcfi = __webpack_require__(1);
+
+var _epubcfi2 = _interopRequireDefault(_epubcfi);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+/**
+ * Handles managing adding & removing Annotations
+ * @param {Rendition} rendition
+ * @class
+ */
+var Annotations = function () {
+ function Annotations(rendition) {
+ _classCallCheck(this, Annotations);
+
+ this.rendition = rendition;
+ this.highlights = [];
+ this.underlines = [];
+ this.marks = [];
+ this._annotations = {};
+ this._annotationsBySectionIndex = {};
+
+ this.rendition.hooks.render.register(this.inject.bind(this));
+ this.rendition.hooks.unloaded.register(this.clear.bind(this));
+ }
+
+ /**
+ * Add an annotation to store
+ * @param {string} type Type of annotation to add: "highlight", "underline", "mark"
+ * @param {EpubCFI} cfiRange EpubCFI range to attach annotation to
+ * @param {object} data Data to assign to annotation
+ * @param {function} [cb] Callback after annotation is added
+ * @returns {Annotation} annotation
+ */
+
+
+ _createClass(Annotations, [{
+ key: "add",
+ value: function add(type, cfiRange, data, cb) {
+ var hash = encodeURI(cfiRange);
+ var cfi = new _epubcfi2.default(cfiRange);
+ var sectionIndex = cfi.spinePos;
+ var annotation = new Annotation({
+ type: type,
+ cfiRange: cfiRange,
+ data: data,
+ sectionIndex: sectionIndex,
+ cb: cb
+ });
+
+ this._annotations[hash] = annotation;
+
+ if (sectionIndex in this._annotationsBySectionIndex) {
+ this._annotationsBySectionIndex[sectionIndex].push(hash);
+ } else {
+ this._annotationsBySectionIndex[sectionIndex] = [hash];
+ }
+
+ var views = this.rendition.views();
+
+ views.forEach(function (view) {
+ if (annotation.sectionIndex === view.index) {
+ annotation.attach(view);
+ }
+ });
+
+ return annotation;
+ }
+
+ /**
+ * Remove an annotation from store
+ * @param {EpubCFI} cfiRange EpubCFI range the annotation is attached to
+ * @param {string} type Type of annotation to add: "highlight", "underline", "mark"
+ */
+
+ }, {
+ key: "remove",
+ value: function remove(cfiRange, type) {
+ var _this = this;
+
+ var hash = encodeURI(cfiRange);
+
+ if (hash in this._annotations) {
+ var annotation = this._annotations[hash];
+
+ if (type && annotation.type !== type) {
+ return;
+ }
+
+ var views = this.rendition.views();
+ views.forEach(function (view) {
+ _this._removeFromAnnotationBySectionIndex(annotation.sectionIndex, hash);
+ if (annotation.sectionIndex === view.index) {
+ annotation.detach(view);
+ }
+ });
+
+ delete this._annotations[hash];
+ }
+ }
+
+ /**
+ * Remove an annotations by Section Index
+ * @private
+ */
+
+ }, {
+ key: "_removeFromAnnotationBySectionIndex",
+ value: function _removeFromAnnotationBySectionIndex(sectionIndex, hash) {
+ this._annotationsBySectionIndex[sectionIndex] = this._annotationsAt(sectionIndex).filter(function (h) {
+ return h !== hash;
+ });
+ }
+
+ /**
+ * Get annotations by Section Index
+ * @private
+ */
+
+ }, {
+ key: "_annotationsAt",
+ value: function _annotationsAt(index) {
+ return this._annotationsBySectionIndex[index];
+ }
+
+ /**
+ * Add a highlight to the store
+ * @param {EpubCFI} cfiRange EpubCFI range to attach annotation to
+ * @param {object} data Data to assign to annotation
+ * @param {function} cb Callback after annotation is added
+ */
+
+ }, {
+ key: "highlight",
+ value: function highlight(cfiRange, data, cb) {
+ this.add("highlight", cfiRange, data, cb);
+ }
+
+ /**
+ * Add a underline to the store
+ * @param {EpubCFI} cfiRange EpubCFI range to attach annotation to
+ * @param {object} data Data to assign to annotation
+ * @param {function} cb Callback after annotation is added
+ */
+
+ }, {
+ key: "underline",
+ value: function underline(cfiRange, data, cb) {
+ this.add("underline", cfiRange, data, cb);
+ }
+
+ /**
+ * Add a mark to the store
+ * @param {EpubCFI} cfiRange EpubCFI range to attach annotation to
+ * @param {object} data Data to assign to annotation
+ * @param {function} cb Callback after annotation is added
+ */
+
+ }, {
+ key: "mark",
+ value: function mark(cfiRange, data, cb) {
+ this.add("mark", cfiRange, data, cb);
+ }
+
+ /**
+ * iterate over annotations in the store
+ */
+
+ }, {
+ key: "each",
+ value: function each() {
+ return this._annotations.forEach.apply(this._annotations, arguments);
+ }
+
+ /**
+ * Hook for injecting annotation into a view
+ * @param {View} view
+ * @private
+ */
+
+ }, {
+ key: "inject",
+ value: function inject(view) {
+ var _this2 = this;
+
+ var sectionIndex = view.index;
+ if (sectionIndex in this._annotationsBySectionIndex) {
+ var annotations = this._annotationsBySectionIndex[sectionIndex];
+ annotations.forEach(function (hash) {
+ var annotation = _this2._annotations[hash];
+ annotation.attach(view);
+ });
+ }
+ }
+
+ /**
+ * Hook for removing annotation from a view
+ * @param {View} view
+ * @private
+ */
+
+ }, {
+ key: "clear",
+ value: function clear(view) {
+ var _this3 = this;
+
+ var sectionIndex = view.index;
+ if (sectionIndex in this._annotationsBySectionIndex) {
+ var annotations = this._annotationsBySectionIndex[sectionIndex];
+ annotations.forEach(function (hash) {
+ var annotation = _this3._annotations[hash];
+ annotation.detach(view);
+ });
+ }
+ }
+
+ /**
+ * [Not Implemented] Show annotations
+ * @TODO: needs implementation in View
+ */
+
+ }, {
+ key: "show",
+ value: function show() {}
+
+ /**
+ * [Not Implemented] Hide annotations
+ * @TODO: needs implementation in View
+ */
+
+ }, {
+ key: "hide",
+ value: function hide() {}
+ }]);
+
+ return Annotations;
+}();
+
+/**
+ * Annotation object
+ * @class
+ * @param {object} options
+ * @param {string} options.type Type of annotation to add: "highlight", "underline", "mark"
+ * @param {EpubCFI} options.cfiRange EpubCFI range to attach annotation to
+ * @param {object} options.data Data to assign to annotation
+ * @param {int} options.sectionIndex Index in the Spine of the Section annotation belongs to
+ * @param {function} [options.cb] Callback after annotation is added
+ * @returns {Annotation} annotation
+ */
+
+
+var Annotation = function () {
+ function Annotation(_ref) {
+ var type = _ref.type,
+ cfiRange = _ref.cfiRange,
+ data = _ref.data,
+ sectionIndex = _ref.sectionIndex,
+ cb = _ref.cb;
+
+ _classCallCheck(this, Annotation);
+
+ this.type = type;
+ this.cfiRange = cfiRange;
+ this.data = data;
+ this.sectionIndex = sectionIndex;
+ this.mark = undefined;
+ this.cb = cb;
+ }
+
+ /**
+ * Update stored data
+ * @param {object} data
+ */
+
+
+ _createClass(Annotation, [{
+ key: "update",
+ value: function update(data) {
+ this.data = data;
+ }
+
+ /**
+ * Add to a view
+ * @param {View} view
+ */
+
+ }, {
+ key: "attach",
+ value: function attach(view) {
+ var cfiRange = this.cfiRange,
+ data = this.data,
+ type = this.type,
+ mark = this.mark,
+ cb = this.cb;
+
+ var result = void 0;
+
+ if (type === "highlight") {
+ result = view.highlight(cfiRange, data, cb);
+ } else if (type === "underline") {
+ result = view.underline(cfiRange, data, cb);
+ } else if (type === "mark") {
+ result = view.mark(cfiRange, data, cb);
+ }
+
+ this.mark = result;
+
+ return result;
+ }
+
+ /**
+ * Remove from a view
+ * @param {View} view
+ */
+
+ }, {
+ key: "detach",
+ value: function detach(view) {
+ var cfiRange = this.cfiRange,
+ type = this.type;
+
+ var result = void 0;
+
+ if (view) {
+ if (type === "highlight") {
+ result = view.unhighlight(cfiRange);
+ } else if (type === "underline") {
+ result = view.ununderline(cfiRange);
+ } else if (type === "mark") {
+ result = view.unmark(cfiRange);
+ }
+ }
+
+ this.mark = undefined;
+
+ return result;
+ }
+
+ /**
+ * [Not Implemented] Get text of an annotation
+ * @TODO: needs implementation in contents
+ */
+
+ }, {
+ key: "text",
+ value: function text() {}
+ }]);
+
+ return Annotation;
+}();
+
+(0, _eventEmitter2.default)(Annotation.prototype);
+
+exports.default = Annotations;
+module.exports = exports["default"];
+
+/***/ }),
+/* 53 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+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; };
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.Underline = exports.Highlight = exports.Mark = exports.Pane = undefined;
+
+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);
+ }
+};
+
+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;
+ };
+}();
+
+var _svg = __webpack_require__(54);
+
+var _svg2 = _interopRequireDefault(_svg);
+
+var _events = __webpack_require__(55);
+
+var _events2 = _interopRequireDefault(_events);
+
+function _interopRequireDefault(obj) {
+ return obj && obj.__esModule ? obj : { default: obj };
+}
+
+function _possibleConstructorReturn(self, call) {
+ if (!self) {
+ throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
+ }return call && ((typeof call === "undefined" ? "undefined" : _typeof(call)) === "object" || typeof call === "function") ? call : self;
+}
+
+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 === "undefined" ? "undefined" : _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;
+}
+
+function _classCallCheck(instance, Constructor) {
+ if (!(instance instanceof Constructor)) {
+ throw new TypeError("Cannot call a class as a function");
+ }
+}
+
+var Pane = exports.Pane = function () {
+ function Pane(target) {
+ var container = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : document.body;
+
+ _classCallCheck(this, Pane);
+
+ this.target = target;
+ this.element = _svg2.default.createElement('svg');
+ this.marks = [];
+
+ // Match the coordinates of the target element
+ this.element.style.position = 'absolute';
+ // Disable pointer events
+ this.element.setAttribute('pointer-events', 'none');
+
+ // Set up mouse event proxying between the target element and the marks
+ _events2.default.proxyMouse(this.target, this.marks);
+
+ this.container = container;
+ this.container.appendChild(this.element);
+
+ this.render();
+ }
+
+ _createClass(Pane, [{
+ key: 'addMark',
+ value: function addMark(mark) {
+ var g = _svg2.default.createElement('g');
+ this.element.appendChild(g);
+ mark.bind(g, this.container);
+
+ this.marks.push(mark);
+
+ mark.render();
+ return mark;
+ }
+ }, {
+ key: 'removeMark',
+ value: function removeMark(mark) {
+ var idx = this.marks.indexOf(mark);
+ if (idx === -1) {
+ return;
+ }
+ var el = mark.unbind();
+ this.element.removeChild(el);
+ this.marks.splice(idx, 1);
+ }
+ }, {
+ key: 'render',
+ value: function render() {
+ setCoords(this.element, coords(this.target, this.container));
+ var _iteratorNormalCompletion = true;
+ var _didIteratorError = false;
+ var _iteratorError = undefined;
+
+ try {
+ for (var _iterator = this.marks[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
+ var m = _step.value;
+
+ m.render();
+ }
+ } catch (err) {
+ _didIteratorError = true;
+ _iteratorError = err;
+ } finally {
+ try {
+ if (!_iteratorNormalCompletion && _iterator.return) {
+ _iterator.return();
+ }
+ } finally {
+ if (_didIteratorError) {
+ throw _iteratorError;
+ }
+ }
+ }
+ }
+ }]);
+
+ return Pane;
+}();
+
+var Mark = exports.Mark = function () {
+ function Mark() {
+ _classCallCheck(this, Mark);
+
+ this.element = null;
+ }
+
+ _createClass(Mark, [{
+ key: 'bind',
+ value: function bind(element, container) {
+ this.element = element;
+ this.container = container;
+ }
+ }, {
+ key: 'unbind',
+ value: function unbind() {
+ var el = this.element;
+ this.element = null;
+ return el;
+ }
+ }, {
+ key: 'render',
+ value: function render() {}
+ }, {
+ key: 'dispatchEvent',
+ value: function dispatchEvent(e) {
+ if (!this.element) return;
+ this.element.dispatchEvent(e);
+ }
+ }, {
+ key: 'getBoundingClientRect',
+ value: function getBoundingClientRect() {
+ return this.element.getBoundingClientRect();
+ }
+ }, {
+ key: 'getClientRects',
+ value: function getClientRects() {
+ var rects = [];
+ var el = this.element.firstChild;
+ while (el) {
+ rects.push(el.getBoundingClientRect());
+ el = el.nextSibling;
+ }
+ return rects;
+ }
+ }, {
+ key: 'filteredRanges',
+ value: function filteredRanges() {
+ var rects = Array.from(this.range.getClientRects());
+
+ // De-duplicate the boxes
+ return rects.filter(function (box) {
+ for (var i = 0; i < rects.length; i++) {
+ if (rects[i] === box) {
+ return true;
+ }
+ var contained = contains(rects[i], box);
+ if (contained) {
+ return false;
+ }
+ }
+ return true;
+ });
+ }
+ }]);
+
+ return Mark;
+}();
+
+var Highlight = exports.Highlight = function (_Mark) {
+ _inherits(Highlight, _Mark);
+
+ function Highlight(range, className, data, attributes) {
+ _classCallCheck(this, Highlight);
+
+ var _this = _possibleConstructorReturn(this, (Highlight.__proto__ || Object.getPrototypeOf(Highlight)).call(this));
+
+ _this.range = range;
+ _this.className = className;
+ _this.data = data || {};
+ _this.attributes = attributes || {};
+ return _this;
+ }
+
+ _createClass(Highlight, [{
+ key: 'bind',
+ value: function bind(element, container) {
+ _get(Highlight.prototype.__proto__ || Object.getPrototypeOf(Highlight.prototype), 'bind', this).call(this, element, container);
+
+ for (var attr in this.data) {
+ if (this.data.hasOwnProperty(attr)) {
+ this.element.dataset[attr] = this.data[attr];
+ }
+ }
+
+ for (var attr in this.attributes) {
+ if (this.attributes.hasOwnProperty(attr)) {
+ this.element.setAttribute(attr, this.attributes[attr]);
+ }
+ }
+
+ if (this.className) {
+ this.element.classList.add(this.className);
+ }
+ }
+ }, {
+ key: 'render',
+ value: function render() {
+ // Empty element
+ while (this.element.firstChild) {
+ this.element.removeChild(this.element.firstChild);
+ }
+
+ var docFrag = this.element.ownerDocument.createDocumentFragment();
+ var filtered = this.filteredRanges();
+ var offset = this.element.getBoundingClientRect();
+ var container = this.container.getBoundingClientRect();
+
+ for (var i = 0, len = filtered.length; i < len; i++) {
+ var r = filtered[i];
+ var el = _svg2.default.createElement('rect');
+ el.setAttribute('x', r.left - offset.left + container.left);
+ el.setAttribute('y', r.top - offset.top + container.top);
+ el.setAttribute('height', r.height);
+ el.setAttribute('width', r.width);
+ docFrag.appendChild(el);
+ }
+
+ this.element.appendChild(docFrag);
+ }
+ }]);
+
+ return Highlight;
+}(Mark);
+
+var Underline = exports.Underline = function (_Highlight) {
+ _inherits(Underline, _Highlight);
+
+ function Underline(range, className, data, attributes) {
+ _classCallCheck(this, Underline);
+
+ return _possibleConstructorReturn(this, (Underline.__proto__ || Object.getPrototypeOf(Underline)).call(this, range, className, data, attributes));
+ }
+
+ _createClass(Underline, [{
+ key: 'render',
+ value: function render() {
+ // Empty element
+ while (this.element.firstChild) {
+ this.element.removeChild(this.element.firstChild);
+ }
+
+ var docFrag = this.element.ownerDocument.createDocumentFragment();
+ var filtered = this.filteredRanges();
+ var offset = this.element.getBoundingClientRect();
+ var container = this.container.getBoundingClientRect();
+
+ for (var i = 0, len = filtered.length; i < len; i++) {
+ var r = filtered[i];
+
+ var rect = _svg2.default.createElement('rect');
+ rect.setAttribute('x', r.left - offset.left + container.left);
+ rect.setAttribute('y', r.top - offset.top + container.top);
+ rect.setAttribute('height', r.height);
+ rect.setAttribute('width', r.width);
+ rect.setAttribute('fill', 'none');
+
+ var line = _svg2.default.createElement('line');
+ line.setAttribute('x1', r.left - offset.left + container.left);
+ line.setAttribute('x2', r.left - offset.left + container.left + r.width);
+ line.setAttribute('y1', r.top - offset.top + container.top + r.height - 1);
+ line.setAttribute('y2', r.top - offset.top + container.top + r.height - 1);
+
+ line.setAttribute('stroke-width', 1);
+ line.setAttribute('stroke', 'black'); //TODO: match text color?
+ line.setAttribute('stroke-linecap', 'square');
+
+ docFrag.appendChild(rect);
+
+ docFrag.appendChild(line);
+ }
+
+ this.element.appendChild(docFrag);
+ }
+ }]);
+
+ return Underline;
+}(Highlight);
+
+function coords(el, container) {
+ var offset = container.getBoundingClientRect();
+ var rect = el.getBoundingClientRect();
+
+ return {
+ top: rect.top - offset.top,
+ left: rect.left - offset.left,
+ height: el.scrollHeight,
+ width: el.scrollWidth
+ };
+}
+
+function setCoords(el, coords) {
+ el.style.top = coords.top + 'px';
+ el.style.left = coords.left + 'px';
+ el.style.height = coords.height + 'px';
+ el.style.width = coords.width + 'px';
+}
+
+function contains(rect1, rect2) {
+ return rect2.right <= rect1.right && rect2.left >= rect1.left && rect2.top >= rect1.top && rect2.bottom <= rect1.bottom;
+}
+
+/***/ }),
+/* 54 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.createElement = createElement;
+function createElement(name) {
+ return document.createElementNS('http://www.w3.org/2000/svg', name);
+}
+
+exports.default = {
+ createElement: createElement
+};
+
+/***/ }),
+/* 55 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.proxyMouse = proxyMouse;
+exports.clone = clone;
+// import 'babelify/polyfill'; // needed for Object.assign
+
+exports.default = {
+ proxyMouse: proxyMouse
+};
+
+/**
+ * Start proxying all mouse events that occur on the target node to each node in
+ * a set of tracked nodes.
+ *
+ * The items in tracked do not strictly have to be DOM Nodes, but they do have
+ * to have dispatchEvent, getBoundingClientRect, and getClientRects methods.
+ *
+ * @param target {Node} The node on which to listen for mouse events.
+ * @param tracked {Node[]} A (possibly mutable) array of nodes to which to proxy
+ * events.
+ */
+
+function proxyMouse(target, tracked) {
+ function dispatch(e) {
+ // We walk through the set of tracked elements in reverse order so that
+ // events are sent to those most recently added first.
+ //
+ // This is the least surprising behaviour as it simulates the way the
+ // browser would work if items added later were drawn "on top of"
+ // earlier ones.
+ for (var i = tracked.length - 1; i >= 0; i--) {
+ var t = tracked[i];
+ var x = e.clientX;
+ var y = e.clientY;
+
+ if (e.touches && e.touches.length) {
+ x = e.touches[0].clientX;
+ y = e.touches[0].clientY;
+ }
+
+ if (!contains(t, target, x, y)) {
+ continue;
+ }
+
+ // The event targets this mark, so dispatch a cloned event:
+ t.dispatchEvent(clone(e));
+ // We only dispatch the cloned event to the first matching mark.
+ break;
+ }
+ }
+
+ if (target.nodeName === "iframe" || target.nodeName === "IFRAME") {
+
+ try {
+ // Try to get the contents if same domain
+ this.target = target.contentDocument;
+ } catch (err) {
+ this.target = target;
+ }
+ } else {
+ this.target = target;
+ }
+
+ var _arr = ['mouseup', 'mousedown', 'click', 'touchstart'];
+ for (var _i = 0; _i < _arr.length; _i++) {
+ var ev = _arr[_i];
+ this.target.addEventListener(ev, function (e) {
+ return dispatch(e);
+ }, false);
+ }
+}
+
+/**
+ * Clone a mouse event object.
+ *
+ * @param e {MouseEvent} A mouse event object to clone.
+ * @returns {MouseEvent}
+ */
+function clone(e) {
+ var opts = Object.assign({}, e, { bubbles: false });
+ try {
+ return new MouseEvent(e.type, opts);
+ } catch (err) {
+ // compat: webkit
+ var copy = document.createEvent('MouseEvents');
+ 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);
+ return copy;
+ }
+}
+
+/**
+ * Check if the item contains the point denoted by the passed coordinates
+ * @param item {Object} An object with getBoundingClientRect and getClientRects
+ * methods.
+ * @param x {Number}
+ * @param y {Number}
+ * @returns {Boolean}
+ */
+function contains(item, target, x, y) {
+ // offset
+ var offset = target.getBoundingClientRect();
+
+ function rectContains(r, x, y) {
+ var top = r.top - offset.top;
+ var left = r.left - offset.left;
+ var bottom = top + r.height;
+ var right = left + r.width;
+ return top <= y && left <= x && bottom > y && right > x;
+ }
+
+ // Check overall bounding box first
+ var rect = item.getBoundingClientRect();
+ if (!rectContains(rect, x, y)) {
+ return false;
+ }
+
+ // Then continue to check each child rect
+ var rects = item.getClientRects();
+ for (var i = 0, len = rects.length; i < len; i++) {
+ if (rectContains(rects[i], x, y)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+/***/ }),
+/* 56 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+
+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; }; }();
+
+var _core = __webpack_require__(0);
+
+var _throttle = __webpack_require__(57);
+
+var _throttle2 = _interopRequireDefault(_throttle);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+var Stage = function () {
+ function Stage(_options) {
+ _classCallCheck(this, Stage);
+
+ this.settings = _options || {};
+ this.id = "epubjs-container-" + (0, _core.uuid)();
+
+ this.container = this.create(this.settings);
+
+ if (this.settings.hidden) {
+ this.wrapper = this.wrap(this.container);
+ }
+ }
+
+ /*
+ * Creates an element to render to.
+ * Resizes to passed width and height or to the elements size
+ */
+
+
+ _createClass(Stage, [{
+ key: "create",
+ value: function create(options) {
+ var height = options.height; // !== false ? options.height : "100%";
+ var width = options.width; // !== false ? options.width : "100%";
+ var overflow = options.overflow || false;
+ var axis = options.axis || "vertical";
+ var direction = options.direction;
+
+ if (options.height && (0, _core.isNumber)(options.height)) {
+ height = options.height + "px";
+ }
+
+ if (options.width && (0, _core.isNumber)(options.width)) {
+ width = options.width + "px";
+ }
+
+ // Create new container element
+ var container = document.createElement("div");
+
+ container.id = this.id;
+ container.classList.add("epub-container");
+
+ // Style Element
+ // container.style.fontSize = "0";
+ container.style.wordSpacing = "0";
+ container.style.lineHeight = "0";
+ container.style.verticalAlign = "top";
+ container.style.position = "relative";
+
+ if (axis === "horizontal") {
+ // container.style.whiteSpace = "nowrap";
+ container.style.display = "flex";
+ container.style.flexDirection = "row";
+ container.style.flexWrap = "nowrap";
+ }
+
+ if (width) {
+ container.style.width = width;
+ }
+
+ if (height) {
+ container.style.height = height;
+ }
+
+ if (overflow) {
+ container.style.overflow = overflow;
+ }
+
+ if (direction) {
+ container.dir = direction;
+ container.style["direction"] = direction;
+ }
+
+ if (direction && this.settings.fullsize) {
+ document.body.style["direction"] = direction;
+ }
+
+ return container;
+ }
+ }, {
+ key: "wrap",
+ value: function wrap(container) {
+ var wrapper = document.createElement("div");
+
+ wrapper.style.visibility = "hidden";
+ wrapper.style.overflow = "hidden";
+ wrapper.style.width = "0";
+ wrapper.style.height = "0";
+
+ wrapper.appendChild(container);
+ return wrapper;
+ }
+ }, {
+ key: "getElement",
+ value: function getElement(_element) {
+ var element;
+
+ if ((0, _core.isElement)(_element)) {
+ element = _element;
+ } else if (typeof _element === "string") {
+ element = document.getElementById(_element);
+ }
+
+ if (!element) {
+ throw new Error("Not an Element");
+ }
+
+ return element;
+ }
+ }, {
+ key: "attachTo",
+ value: function attachTo(what) {
+
+ var element = this.getElement(what);
+ var base;
+
+ if (!element) {
+ return;
+ }
+
+ if (this.settings.hidden) {
+ base = this.wrapper;
+ } else {
+ base = this.container;
+ }
+
+ element.appendChild(base);
+
+ this.element = element;
+
+ return element;
+ }
+ }, {
+ key: "getContainer",
+ value: function getContainer() {
+ return this.container;
+ }
+ }, {
+ key: "onResize",
+ value: function onResize(func) {
+ // Only listen to window for resize event if width and height are not fixed.
+ // This applies if it is set to a percent or auto.
+ if (!(0, _core.isNumber)(this.settings.width) || !(0, _core.isNumber)(this.settings.height)) {
+ this.resizeFunc = (0, _throttle2.default)(func, 50);
+ window.addEventListener("resize", this.resizeFunc, false);
+ }
+ }
+ }, {
+ key: "onOrientationChange",
+ value: function onOrientationChange(func) {
+ this.orientationChangeFunc = func;
+ window.addEventListener("orientationchange", this.orientationChangeFunc, false);
+ }
+ }, {
+ key: "size",
+ value: function size(width, height) {
+ var bounds;
+ // var width = _width || this.settings.width;
+ // var height = _height || this.settings.height;
+
+ // If width or height are set to false, inherit them from containing element
+ if (width === null) {
+ bounds = this.element.getBoundingClientRect();
+
+ if (bounds.width) {
+ width = bounds.width;
+ this.container.style.width = bounds.width + "px";
+ }
+ }
+
+ if (height === null) {
+ bounds = bounds || this.element.getBoundingClientRect();
+
+ if (bounds.height) {
+ height = bounds.height;
+ this.container.style.height = bounds.height + "px";
+ }
+ }
+
+ if (!(0, _core.isNumber)(width)) {
+ bounds = this.container.getBoundingClientRect();
+ width = bounds.width;
+ //height = bounds.height;
+ }
+
+ if (!(0, _core.isNumber)(height)) {
+ bounds = bounds || this.container.getBoundingClientRect();
+ //width = bounds.width;
+ height = bounds.height;
+ }
+
+ this.containerStyles = window.getComputedStyle(this.container);
+
+ this.containerPadding = {
+ left: parseFloat(this.containerStyles["padding-left"]) || 0,
+ right: parseFloat(this.containerStyles["padding-right"]) || 0,
+ top: parseFloat(this.containerStyles["padding-top"]) || 0,
+ bottom: parseFloat(this.containerStyles["padding-bottom"]) || 0
+ };
+
+ // Bounds not set, get them from window
+ var _windowBounds = (0, _core.windowBounds)();
+ if (!width) {
+ width = _windowBounds.width;
+ }
+ if (this.settings.fullsize || !height) {
+ height = _windowBounds.height;
+ }
+
+ return {
+ width: width - this.containerPadding.left - this.containerPadding.right,
+ height: height - this.containerPadding.top - this.containerPadding.bottom
+ };
+ }
+ }, {
+ key: "bounds",
+ value: function bounds() {
+ var box = void 0;
+ if (this.container.style.overflow !== "visible") {
+ box = this.container && this.container.getBoundingClientRect();
+ }
+
+ if (!box || !box.width || !box.height) {
+ return (0, _core.windowBounds)();
+ } else {
+ return box;
+ }
+ }
+ }, {
+ key: "getSheet",
+ value: function getSheet() {
+ var style = document.createElement("style");
+
+ // WebKit hack --> https://davidwalsh.name/add-rules-stylesheets
+ style.appendChild(document.createTextNode(""));
+
+ document.head.appendChild(style);
+
+ return style.sheet;
+ }
+ }, {
+ key: "addStyleRules",
+ value: function addStyleRules(selector, rulesArray) {
+ var scope = "#" + this.id + " ";
+ var rules = "";
+
+ if (!this.sheet) {
+ this.sheet = this.getSheet();
+ }
+
+ rulesArray.forEach(function (set) {
+ for (var prop in set) {
+ if (set.hasOwnProperty(prop)) {
+ rules += prop + ":" + set[prop] + ";";
+ }
+ }
+ });
+
+ this.sheet.insertRule(scope + selector + " {" + rules + "}", 0);
+ }
+ }, {
+ key: "axis",
+ value: function axis(_axis) {
+ if (_axis === "horizontal") {
+ this.container.style.display = "flex";
+ this.container.style.flexDirection = "row";
+ this.container.style.flexWrap = "nowrap";
+ } else {
+ this.container.style.display = "block";
+ }
+ }
+
+ // orientation(orientation) {
+ // if (orientation === "landscape") {
+ //
+ // } else {
+ //
+ // }
+ //
+ // this.orientation = orientation;
+ // }
+
+ }, {
+ key: "direction",
+ value: function direction(dir) {
+ if (this.container) {
+ this.container.dir = dir;
+ this.container.style["direction"] = dir;
+ }
+
+ if (this.settings.fullsize) {
+ document.body.style["direction"] = dir;
+ }
+ }
+ }, {
+ key: "destroy",
+ value: function destroy() {
+ var base;
+
+ if (this.element) {
+
+ if (this.settings.hidden) {
+ base = this.wrapper;
+ } else {
+ base = this.container;
+ }
+
+ if (this.element.contains(this.container)) {
+ this.element.removeChild(this.container);
+ }
+
+ window.removeEventListener("resize", this.resizeFunc);
+ window.removeEventListener("orientationChange", this.orientationChangeFunc);
+ }
+ }
+ }]);
+
+ return Stage;
+}();
+
+exports.default = Stage;
+module.exports = exports["default"];
+
+/***/ }),
+/* 57 */
+/***/ (function(module, exports, __webpack_require__) {
+
+var debounce = __webpack_require__(21),
+ isObject = __webpack_require__(15);
+
+/** Error message constants. */
+var FUNC_ERROR_TEXT = 'Expected a function';
+
+/**
+ * Creates a throttled function that only invokes `func` at most once per
+ * every `wait` milliseconds. The throttled function comes with a `cancel`
+ * method to cancel delayed `func` invocations and a `flush` method to
+ * immediately invoke them. Provide `options` to indicate whether `func`
+ * should be invoked on the leading and/or trailing edge of the `wait`
+ * timeout. The `func` is invoked with the last arguments provided to the
+ * throttled function. Subsequent calls to the throttled function return the
+ * result of the last `func` invocation.
+ *
+ * **Note:** If `leading` and `trailing` options are `true`, `func` is
+ * invoked on the trailing edge of the timeout only if the throttled function
+ * is invoked more than once during the `wait` timeout.
+ *
+ * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred
+ * until to the next tick, similar to `setTimeout` with a timeout of `0`.
+ *
+ * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/)
+ * for details over the differences between `_.throttle` and `_.debounce`.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Function
+ * @param {Function} func The function to throttle.
+ * @param {number} [wait=0] The number of milliseconds to throttle invocations to.
+ * @param {Object} [options={}] The options object.
+ * @param {boolean} [options.leading=true]
+ * Specify invoking on the leading edge of the timeout.
+ * @param {boolean} [options.trailing=true]
+ * Specify invoking on the trailing edge of the timeout.
+ * @returns {Function} Returns the new throttled function.
+ * @example
+ *
+ * // Avoid excessively updating the position while scrolling.
+ * jQuery(window).on('scroll', _.throttle(updatePosition, 100));
+ *
+ * // Invoke `renewToken` when the click event is fired, but not more than once every 5 minutes.
+ * var throttled = _.throttle(renewToken, 300000, { 'trailing': false });
+ * jQuery(element).on('click', throttled);
+ *
+ * // Cancel the trailing throttled invocation.
+ * jQuery(window).on('popstate', throttled.cancel);
+ */
+function throttle(func, wait, options) {
+ var leading = true,
+ trailing = true;
+
+ if (typeof func != 'function') {
+ throw new TypeError(FUNC_ERROR_TEXT);
+ }
+ if (isObject(options)) {
+ leading = 'leading' in options ? !!options.leading : leading;
+ trailing = 'trailing' in options ? !!options.trailing : trailing;
+ }
+ return debounce(func, wait, {
+ 'leading': leading,
+ 'maxWait': wait,
+ 'trailing': trailing
+ });
+}
+
+module.exports = throttle;
+
+
+/***/ }),
+/* 58 */
+/***/ (function(module, exports, __webpack_require__) {
+
+var root = __webpack_require__(22);
+
+/**
+ * Gets the timestamp of the number of milliseconds that have elapsed since
+ * the Unix epoch (1 January 1970 00:00:00 UTC).
+ *
+ * @static
+ * @memberOf _
+ * @since 2.4.0
+ * @category Date
+ * @returns {number} Returns the timestamp.
+ * @example
+ *
+ * _.defer(function(stamp) {
+ * console.log(_.now() - stamp);
+ * }, _.now());
+ * // => Logs the number of milliseconds it took for the deferred invocation.
+ */
+var now = function() {
+ return root.Date.now();
+};
+
+module.exports = now;
+
+
+/***/ }),
+/* 59 */
+/***/ (function(module, exports, __webpack_require__) {
+
+/* WEBPACK VAR INJECTION */(function(global) {/** Detect free variable `global` from Node.js. */
+var freeGlobal = typeof global == 'object' && global && global.Object === Object && global;
+
+module.exports = freeGlobal;
+
+/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(8)))
+
+/***/ }),
+/* 60 */
+/***/ (function(module, exports, __webpack_require__) {
+
+var isObject = __webpack_require__(15),
+ isSymbol = __webpack_require__(61);
+
+/** Used as references for various `Number` constants. */
+var NAN = 0 / 0;
+
+/** Used to match leading and trailing whitespace. */
+var reTrim = /^\s+|\s+$/g;
+
+/** Used to detect bad signed hexadecimal string values. */
+var reIsBadHex = /^[-+]0x[0-9a-f]+$/i;
+
+/** Used to detect binary string values. */
+var reIsBinary = /^0b[01]+$/i;
+
+/** Used to detect octal string values. */
+var reIsOctal = /^0o[0-7]+$/i;
+
+/** Built-in method references without a dependency on `root`. */
+var freeParseInt = parseInt;
+
+/**
+ * Converts `value` to a number.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Lang
+ * @param {*} value The value to process.
+ * @returns {number} Returns the number.
+ * @example
+ *
+ * _.toNumber(3.2);
+ * // => 3.2
+ *
+ * _.toNumber(Number.MIN_VALUE);
+ * // => 5e-324
+ *
+ * _.toNumber(Infinity);
+ * // => Infinity
+ *
+ * _.toNumber('3.2');
+ * // => 3.2
+ */
+function toNumber(value) {
+ if (typeof value == 'number') {
+ return value;
+ }
+ if (isSymbol(value)) {
+ return NAN;
+ }
+ if (isObject(value)) {
+ var other = typeof value.valueOf == 'function' ? value.valueOf() : value;
+ value = isObject(other) ? (other + '') : other;
+ }
+ if (typeof value != 'string') {
+ return value === 0 ? value : +value;
+ }
+ value = value.replace(reTrim, '');
+ var isBinary = reIsBinary.test(value);
+ return (isBinary || reIsOctal.test(value))
+ ? freeParseInt(value.slice(2), isBinary ? 2 : 8)
+ : (reIsBadHex.test(value) ? NAN : +value);
+}
+
+module.exports = toNumber;
+
+
+/***/ }),
+/* 61 */
+/***/ (function(module, exports, __webpack_require__) {
+
+var baseGetTag = __webpack_require__(62),
+ isObjectLike = __webpack_require__(65);
+
+/** `Object#toString` result references. */
+var symbolTag = '[object Symbol]';
+
+/**
+ * Checks if `value` is classified as a `Symbol` primitive or object.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a symbol, else `false`.
+ * @example
+ *
+ * _.isSymbol(Symbol.iterator);
+ * // => true
+ *
+ * _.isSymbol('abc');
+ * // => false
+ */
+function isSymbol(value) {
+ return typeof value == 'symbol' ||
+ (isObjectLike(value) && baseGetTag(value) == symbolTag);
+}
+
+module.exports = isSymbol;
+
+
+/***/ }),
+/* 62 */
+/***/ (function(module, exports, __webpack_require__) {
+
+var Symbol = __webpack_require__(23),
+ getRawTag = __webpack_require__(63),
+ objectToString = __webpack_require__(64);
+
+/** `Object#toString` result references. */
+var nullTag = '[object Null]',
+ undefinedTag = '[object Undefined]';
+
+/** Built-in value references. */
+var symToStringTag = Symbol ? Symbol.toStringTag : undefined;
+
+/**
+ * The base implementation of `getTag` without fallbacks for buggy environments.
+ *
+ * @private
+ * @param {*} value The value to query.
+ * @returns {string} Returns the `toStringTag`.
+ */
+function baseGetTag(value) {
+ if (value == null) {
+ return value === undefined ? undefinedTag : nullTag;
+ }
+ return (symToStringTag && symToStringTag in Object(value))
+ ? getRawTag(value)
+ : objectToString(value);
+}
+
+module.exports = baseGetTag;
+
+
+/***/ }),
+/* 63 */
+/***/ (function(module, exports, __webpack_require__) {
+
+var Symbol = __webpack_require__(23);
+
+/** Used for built-in method references. */
+var objectProto = Object.prototype;
+
+/** Used to check objects for own properties. */
+var hasOwnProperty = objectProto.hasOwnProperty;
+
+/**
+ * Used to resolve the
+ * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
+ * of values.
+ */
+var nativeObjectToString = objectProto.toString;
+
+/** Built-in value references. */
+var symToStringTag = Symbol ? Symbol.toStringTag : undefined;
+
+/**
+ * A specialized version of `baseGetTag` which ignores `Symbol.toStringTag` values.
+ *
+ * @private
+ * @param {*} value The value to query.
+ * @returns {string} Returns the raw `toStringTag`.
+ */
+function getRawTag(value) {
+ var isOwn = hasOwnProperty.call(value, symToStringTag),
+ tag = value[symToStringTag];
+
+ try {
+ value[symToStringTag] = undefined;
+ var unmasked = true;
+ } catch (e) {}
+
+ var result = nativeObjectToString.call(value);
+ if (unmasked) {
+ if (isOwn) {
+ value[symToStringTag] = tag;
+ } else {
+ delete value[symToStringTag];
+ }
+ }
+ return result;
+}
+
+module.exports = getRawTag;
+
+
+/***/ }),
+/* 64 */
+/***/ (function(module, exports) {
+
+/** Used for built-in method references. */
+var objectProto = Object.prototype;
+
+/**
+ * Used to resolve the
+ * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
+ * of values.
+ */
+var nativeObjectToString = objectProto.toString;
+
+/**
+ * Converts `value` to a string using `Object.prototype.toString`.
+ *
+ * @private
+ * @param {*} value The value to convert.
+ * @returns {string} Returns the converted string.
+ */
+function objectToString(value) {
+ return nativeObjectToString.call(value);
+}
+
+module.exports = objectToString;
+
+
+/***/ }),
+/* 65 */
+/***/ (function(module, exports) {
+
+/**
+ * Checks if `value` is object-like. A value is object-like if it's not `null`
+ * and has a `typeof` result of "object".
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is object-like, else `false`.
+ * @example
+ *
+ * _.isObjectLike({});
+ * // => true
+ *
+ * _.isObjectLike([1, 2, 3]);
+ * // => true
+ *
+ * _.isObjectLike(_.noop);
+ * // => false
+ *
+ * _.isObjectLike(null);
+ * // => false
+ */
+function isObjectLike(value) {
+ return value != null && typeof value == 'object';
+}
+
+module.exports = isObjectLike;
+
+
+/***/ }),
+/* 66 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+
+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; }; }();
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+var Views = function () {
+ function Views(container) {
+ _classCallCheck(this, Views);
+
+ this.container = container;
+ this._views = [];
+ this.length = 0;
+ this.hidden = false;
+ }
+
+ _createClass(Views, [{
+ key: "all",
+ value: function all() {
+ return this._views;
+ }
+ }, {
+ key: "first",
+ value: function first() {
+ return this._views[0];
+ }
+ }, {
+ key: "last",
+ value: function last() {
+ return this._views[this._views.length - 1];
+ }
+ }, {
+ key: "indexOf",
+ value: function indexOf(view) {
+ return this._views.indexOf(view);
+ }
+ }, {
+ key: "slice",
+ value: function slice() {
+ return this._views.slice.apply(this._views, arguments);
+ }
+ }, {
+ key: "get",
+ value: function get(i) {
+ return this._views[i];
+ }
+ }, {
+ key: "append",
+ value: function append(view) {
+ this._views.push(view);
+ if (this.container) {
+ this.container.appendChild(view.element);
+ }
+ this.length++;
+ return view;
+ }
+ }, {
+ key: "prepend",
+ value: function prepend(view) {
+ this._views.unshift(view);
+ if (this.container) {
+ this.container.insertBefore(view.element, this.container.firstChild);
+ }
+ this.length++;
+ return view;
+ }
+ }, {
+ key: "insert",
+ value: function insert(view, index) {
+ this._views.splice(index, 0, view);
+
+ if (this.container) {
+ if (index < this.container.children.length) {
+ this.container.insertBefore(view.element, this.container.children[index]);
+ } else {
+ this.container.appendChild(view.element);
+ }
+ }
+
+ this.length++;
+ return view;
+ }
+ }, {
+ key: "remove",
+ value: function remove(view) {
+ var index = this._views.indexOf(view);
+
+ if (index > -1) {
+ this._views.splice(index, 1);
+ }
+
+ this.destroy(view);
+
+ this.length--;
+ }
+ }, {
+ key: "destroy",
+ value: function destroy(view) {
+ if (view.displayed) {
+ view.destroy();
+ }
+
+ if (this.container) {
+ this.container.removeChild(view.element);
+ }
+ view = null;
+ }
+
+ // Iterators
+
+ }, {
+ key: "forEach",
+ value: function forEach() {
+ return this._views.forEach.apply(this._views, arguments);
+ }
+ }, {
+ key: "clear",
+ value: function clear() {
+ // Remove all views
+ var view;
+ var len = this.length;
+
+ if (!this.length) return;
+
+ for (var i = 0; i < len; i++) {
+ view = this._views[i];
+ this.destroy(view);
+ }
+
+ this._views = [];
+ this.length = 0;
+ }
+ }, {
+ key: "find",
+ value: function find(section) {
+
+ var view;
+ var len = this.length;
+
+ for (var i = 0; i < len; i++) {
+ view = this._views[i];
+ if (view.displayed && view.section.index == section.index) {
+ return view;
+ }
+ }
+ }
+ }, {
+ key: "displayed",
+ value: function displayed() {
+ var displayed = [];
+ var view;
+ var len = this.length;
+
+ for (var i = 0; i < len; i++) {
+ view = this._views[i];
+ if (view.displayed) {
+ displayed.push(view);
+ }
+ }
+ return displayed;
+ }
+ }, {
+ key: "show",
+ value: function show() {
+ var view;
+ var len = this.length;
+
+ for (var i = 0; i < len; i++) {
+ view = this._views[i];
+ if (view.displayed) {
+ view.show();
+ }
+ }
+ this.hidden = false;
+ }
+ }, {
+ key: "hide",
+ value: function hide() {
+ var view;
+ var len = this.length;
+
+ for (var i = 0; i < len; i++) {
+ view = this._views[i];
+ if (view.displayed) {
+ view.hide();
+ }
+ }
+ this.hidden = true;
+ }
+ }]);
+
+ return Views;
+}();
+
+exports.default = Views;
+module.exports = exports["default"];
+
+/***/ }),
+/* 67 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+
+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; }; }();
+
+var _core = __webpack_require__(0);
+
+var _request = __webpack_require__(11);
+
+var _request2 = _interopRequireDefault(_request);
+
+var _mime = __webpack_require__(17);
+
+var _mime2 = _interopRequireDefault(_mime);
+
+var _path = __webpack_require__(4);
+
+var _path2 = _interopRequireDefault(_path);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+/**
+ * Handles Unzipping a requesting files from an Epub Archive
+ * @class
+ */
+var Archive = function () {
+ function Archive() {
+ _classCallCheck(this, Archive);
+
+ this.zip = undefined;
+ this.urlCache = {};
+
+ this.checkRequirements();
+ }
+
+ /**
+ * Checks to see if JSZip exists in global namspace,
+ * Requires JSZip if it isn't there
+ * @private
+ */
+
+
+ _createClass(Archive, [{
+ key: "checkRequirements",
+ value: function checkRequirements() {
+ try {
+ if (typeof JSZip === "undefined") {
+ var _JSZip = __webpack_require__(68);
+ this.zip = new _JSZip();
+ } else {
+ this.zip = new JSZip();
+ }
+ } catch (e) {
+ throw new Error("JSZip lib not loaded");
+ }
+ }
+
+ /**
+ * Open an archive
+ * @param {binary} input
+ * @param {boolean} isBase64 tells JSZip if the input data is base64 encoded
+ * @return {Promise} zipfile
+ */
+
+ }, {
+ key: "open",
+ value: function open(input, isBase64) {
+ return this.zip.loadAsync(input, { "base64": isBase64 });
+ }
+
+ /**
+ * Load and Open an archive
+ * @param {string} zipUrl
+ * @param {boolean} isBase64 tells JSZip if the input data is base64 encoded
+ * @return {Promise} zipfile
+ */
+
+ }, {
+ key: "openUrl",
+ value: function openUrl(zipUrl, isBase64) {
+ return (0, _request2.default)(zipUrl, "binary").then(function (data) {
+ return this.zip.loadAsync(data, { "base64": isBase64 });
+ }.bind(this));
+ }
+
+ /**
+ * Request a url from the archive
+ * @param {string} url a url to request from the archive
+ * @param {string} [type] specify the type of the returned result
+ * @return {Promise}
+ */
+
+ }, {
+ key: "request",
+ value: function request(url, type) {
+ var deferred = new _core.defer();
+ var response;
+ var path = new _path2.default(url);
+
+ // If type isn't set, determine it from the file extension
+ if (!type) {
+ type = path.extension;
+ }
+
+ if (type == "blob") {
+ response = this.getBlob(url);
+ } else {
+ response = this.getText(url);
+ }
+
+ if (response) {
+ response.then(function (r) {
+ var result = this.handleResponse(r, type);
+ deferred.resolve(result);
+ }.bind(this));
+ } else {
+ deferred.reject({
+ message: "File not found in the epub: " + url,
+ stack: new Error().stack
+ });
+ }
+ return deferred.promise;
+ }
+
+ /**
+ * Handle the response from request
+ * @private
+ * @param {any} response
+ * @param {string} [type]
+ * @return {any} the parsed result
+ */
+
+ }, {
+ key: "handleResponse",
+ value: function handleResponse(response, type) {
+ var r;
+
+ if (type == "json") {
+ r = JSON.parse(response);
+ } else if ((0, _core.isXml)(type)) {
+ r = (0, _core.parse)(response, "text/xml");
+ } else if (type == "xhtml") {
+ r = (0, _core.parse)(response, "application/xhtml+xml");
+ } else if (type == "html" || type == "htm") {
+ r = (0, _core.parse)(response, "text/html");
+ } else {
+ r = response;
+ }
+
+ return r;
+ }
+
+ /**
+ * Get a Blob from Archive by Url
+ * @param {string} url
+ * @param {string} [mimeType]
+ * @return {Blob}
+ */
+
+ }, {
+ key: "getBlob",
+ value: function getBlob(url, mimeType) {
+ var decodededUrl = window.decodeURIComponent(url.substr(1)); // Remove first slash
+ var entry = this.zip.file(decodededUrl);
+
+ if (entry) {
+ mimeType = mimeType || _mime2.default.lookup(entry.name);
+ return entry.async("uint8array").then(function (uint8array) {
+ return new Blob([uint8array], { type: mimeType });
+ });
+ }
+ }
+
+ /**
+ * Get Text from Archive by Url
+ * @param {string} url
+ * @param {string} [encoding]
+ * @return {string}
+ */
+
+ }, {
+ key: "getText",
+ value: function getText(url, encoding) {
+ var decodededUrl = window.decodeURIComponent(url.substr(1)); // Remove first slash
+ var entry = this.zip.file(decodededUrl);
+
+ if (entry) {
+ return entry.async("string").then(function (text) {
+ return text;
+ });
+ }
+ }
+
+ /**
+ * Get a base64 encoded result from Archive by Url
+ * @param {string} url
+ * @param {string} [mimeType]
+ * @return {string} base64 encoded
+ */
+
+ }, {
+ key: "getBase64",
+ value: function getBase64(url, mimeType) {
+ var decodededUrl = window.decodeURIComponent(url.substr(1)); // Remove first slash
+ var entry = this.zip.file(decodededUrl);
+
+ if (entry) {
+ mimeType = mimeType || _mime2.default.lookup(entry.name);
+ return entry.async("base64").then(function (data) {
+ return "data:" + mimeType + ";base64," + data;
+ });
+ }
+ }
+
+ /**
+ * Create a Url from an unarchived item
+ * @param {string} url
+ * @param {object} [options.base64] use base64 encoding or blob url
+ * @return {Promise} url promise with Url string
+ */
+
+ }, {
+ key: "createUrl",
+ value: function createUrl(url, options) {
+ var deferred = new _core.defer();
+ var _URL = window.URL || window.webkitURL || window.mozURL;
+ var tempUrl;
+ var response;
+ var useBase64 = options && options.base64;
+
+ if (url in this.urlCache) {
+ deferred.resolve(this.urlCache[url]);
+ return deferred.promise;
+ }
+
+ if (useBase64) {
+ response = this.getBase64(url);
+
+ if (response) {
+ response.then(function (tempUrl) {
+
+ this.urlCache[url] = tempUrl;
+ deferred.resolve(tempUrl);
+ }.bind(this));
+ }
+ } else {
+
+ response = this.getBlob(url);
+
+ if (response) {
+ response.then(function (blob) {
+
+ tempUrl = _URL.createObjectURL(blob);
+ this.urlCache[url] = tempUrl;
+ deferred.resolve(tempUrl);
+ }.bind(this));
+ }
+ }
+
+ if (!response) {
+ deferred.reject({
+ message: "File not found in the epub: " + url,
+ stack: new Error().stack
+ });
+ }
+
+ return deferred.promise;
+ }
+
+ /**
+ * Revoke Temp Url for a achive item
+ * @param {string} url url of the item in the archive
+ */
+
+ }, {
+ key: "revokeUrl",
+ value: function revokeUrl(url) {
+ var _URL = window.URL || window.webkitURL || window.mozURL;
+ var fromCache = this.urlCache[url];
+ if (fromCache) _URL.revokeObjectURL(fromCache);
+ }
+ }, {
+ key: "destroy",
+ value: function destroy() {
+ var _URL = window.URL || window.webkitURL || window.mozURL;
+ for (var fromCache in this.urlCache) {
+ _URL.revokeObjectURL(fromCache);
+ }
+ this.zip = undefined;
+ this.urlCache = {};
+ }
+ }]);
+
+ return Archive;
+}();
+
+exports.default = Archive;
+module.exports = exports["default"];
+
+/***/ }),
+/* 68 */
+/***/ (function(module, exports) {
+
+if(typeof __WEBPACK_EXTERNAL_MODULE_68__ === 'undefined') {var e = new Error("Cannot find module \"jszip\""); e.code = 'MODULE_NOT_FOUND'; throw e;}
+module.exports = __WEBPACK_EXTERNAL_MODULE_68__;
+
+/***/ }),
+/* 69 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+/* WEBPACK VAR INJECTION */(function(global, module) {var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/* From https://github.com/webcomponents/URL/blob/master/url.js
+ * Added UMD, file link handling */
+
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+
+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; };
+
+(function (root, factory) {
+ // Fix for this being undefined in modules
+ if (!root) {
+ root = window || global;
+ }
+ if (( false ? 'undefined' : _typeof(module)) === 'object' && module.exports) {
+ // Node
+ module.exports = factory(root);
+ } else if (true) {
+ // AMD. Register as an anonymous module.
+ !(__WEBPACK_AMD_DEFINE_ARRAY__ = [], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),
+ __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
+ (__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),
+ __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
+ } else {
+ // Browser globals (root is window)
+ root.URL = factory(root);
+ }
+})(undefined, function (scope) {
+ // feature detect for URL constructor
+ var hasWorkingUrl = false;
+ if (!scope.forceJURL) {
+ try {
+ var u = new URL('b', 'http://a');
+ u.pathname = 'c%20d';
+ hasWorkingUrl = u.href === 'http://a/c%20d';
+ } catch (e) {}
+ }
+
+ if (hasWorkingUrl) return scope.URL;
+
+ var relative = Object.create(null);
+ relative['ftp'] = 21;
+ relative['file'] = 0;
+ relative['gopher'] = 70;
+ relative['http'] = 80;
+ relative['https'] = 443;
+ relative['ws'] = 80;
+ relative['wss'] = 443;
+
+ var relativePathDotMapping = Object.create(null);
+ relativePathDotMapping['%2e'] = '.';
+ relativePathDotMapping['.%2e'] = '..';
+ relativePathDotMapping['%2e.'] = '..';
+ relativePathDotMapping['%2e%2e'] = '..';
+
+ function isRelativeScheme(scheme) {
+ return relative[scheme] !== undefined;
+ }
+
+ function invalid() {
+ clear.call(this);
+ this._isInvalid = true;
+ }
+
+ function IDNAToASCII(h) {
+ if ('' == h) {
+ invalid.call(this);
+ }
+ // XXX
+ return h.toLowerCase();
+ }
+
+ function percentEscape(c) {
+ var unicode = c.charCodeAt(0);
+ if (unicode > 0x20 && unicode < 0x7F &&
+ // " # < > ? `
+ [0x22, 0x23, 0x3C, 0x3E, 0x3F, 0x60].indexOf(unicode) == -1) {
+ return c;
+ }
+ return encodeURIComponent(c);
+ }
+
+ function percentEscapeQuery(c) {
+ // XXX This actually needs to encode c using encoding and then
+ // convert the bytes one-by-one.
+
+ var unicode = c.charCodeAt(0);
+ if (unicode > 0x20 && unicode < 0x7F &&
+ // " # < > ` (do not escape '?')
+ [0x22, 0x23, 0x3C, 0x3E, 0x60].indexOf(unicode) == -1) {
+ return c;
+ }
+ return encodeURIComponent(c);
+ }
+
+ var EOF = undefined,
+ ALPHA = /[a-zA-Z]/,
+ ALPHANUMERIC = /[a-zA-Z0-9\+\-\.]/;
+
+ function parse(input, stateOverride, base) {
+ function err(message) {
+ errors.push(message);
+ }
+
+ var state = stateOverride || 'scheme start',
+ cursor = 0,
+ buffer = '',
+ seenAt = false,
+ seenBracket = false,
+ errors = [];
+
+ loop: while ((input[cursor - 1] != EOF || cursor == 0) && !this._isInvalid) {
+ var c = input[cursor];
+ switch (state) {
+ case 'scheme start':
+ if (c && ALPHA.test(c)) {
+ buffer += c.toLowerCase(); // ASCII-safe
+ state = 'scheme';
+ } else if (!stateOverride) {
+ buffer = '';
+ state = 'no scheme';
+ continue;
+ } else {
+ err('Invalid scheme.');
+ break loop;
+ }
+ break;
+
+ case 'scheme':
+ if (c && ALPHANUMERIC.test(c)) {
+ buffer += c.toLowerCase(); // ASCII-safe
+ } else if (':' == c) {
+ this._scheme = buffer;
+ buffer = '';
+ if (stateOverride) {
+ break loop;
+ }
+ if (isRelativeScheme(this._scheme)) {
+ this._isRelative = true;
+ }
+ if ('file' == this._scheme) {
+ state = 'relative';
+ } else if (this._isRelative && base && base._scheme == this._scheme) {
+ state = 'relative or authority';
+ } else if (this._isRelative) {
+ state = 'authority first slash';
+ } else {
+ state = 'scheme data';
+ }
+ } else if (!stateOverride) {
+ buffer = '';
+ cursor = 0;
+ state = 'no scheme';
+ continue;
+ } else if (EOF == c) {
+ break loop;
+ } else {
+ err('Code point not allowed in scheme: ' + c);
+ break loop;
+ }
+ break;
+
+ case 'scheme data':
+ if ('?' == c) {
+ this._query = '?';
+ state = 'query';
+ } else if ('#' == c) {
+ this._fragment = '#';
+ state = 'fragment';
+ } else {
+ // XXX error handling
+ if (EOF != c && '\t' != c && '\n' != c && '\r' != c) {
+ this._schemeData += percentEscape(c);
+ }
+ }
+ break;
+
+ case 'no scheme':
+ if (!base || !isRelativeScheme(base._scheme)) {
+ err('Missing scheme.');
+ invalid.call(this);
+ } else {
+ state = 'relative';
+ continue;
+ }
+ break;
+
+ case 'relative or authority':
+ if ('/' == c && '/' == input[cursor + 1]) {
+ state = 'authority ignore slashes';
+ } else {
+ err('Expected /, got: ' + c);
+ state = 'relative';
+ continue;
+ }
+ break;
+
+ case 'relative':
+ this._isRelative = true;
+ if ('file' != this._scheme) this._scheme = base._scheme;
+ if (EOF == c) {
+ this._host = base._host;
+ this._port = base._port;
+ this._path = base._path.slice();
+ this._query = base._query;
+ this._username = base._username;
+ this._password = base._password;
+ break loop;
+ } else if ('/' == c || '\\' == c) {
+ if ('\\' == c) err('\\ is an invalid code point.');
+ state = 'relative slash';
+ } else if ('?' == c) {
+ this._host = base._host;
+ this._port = base._port;
+ this._path = base._path.slice();
+ this._query = '?';
+ this._username = base._username;
+ this._password = base._password;
+ state = 'query';
+ } else if ('#' == c) {
+ this._host = base._host;
+ this._port = base._port;
+ this._path = base._path.slice();
+ this._query = base._query;
+ this._fragment = '#';
+ this._username = base._username;
+ this._password = base._password;
+ state = 'fragment';
+ } else {
+ var nextC = input[cursor + 1];
+ var nextNextC = input[cursor + 2];
+ if ('file' != this._scheme || !ALPHA.test(c) || nextC != ':' && nextC != '|' || EOF != nextNextC && '/' != nextNextC && '\\' != nextNextC && '?' != nextNextC && '#' != nextNextC) {
+ this._host = base._host;
+ this._port = base._port;
+ this._username = base._username;
+ this._password = base._password;
+ this._path = base._path.slice();
+ this._path.pop();
+ }
+ state = 'relative path';
+ continue;
+ }
+ break;
+
+ case 'relative slash':
+ if ('/' == c || '\\' == c) {
+ if ('\\' == c) {
+ err('\\ is an invalid code point.');
+ }
+ if ('file' == this._scheme) {
+ state = 'file host';
+ } else {
+ state = 'authority ignore slashes';
+ }
+ } else {
+ if ('file' != this._scheme) {
+ this._host = base._host;
+ this._port = base._port;
+ this._username = base._username;
+ this._password = base._password;
+ }
+ state = 'relative path';
+ continue;
+ }
+ break;
+
+ case 'authority first slash':
+ if ('/' == c) {
+ state = 'authority second slash';
+ } else {
+ err("Expected '/', got: " + c);
+ state = 'authority ignore slashes';
+ continue;
+ }
+ break;
+
+ case 'authority second slash':
+ state = 'authority ignore slashes';
+ if ('/' != c) {
+ err("Expected '/', got: " + c);
+ continue;
+ }
+ break;
+
+ case 'authority ignore slashes':
+ if ('/' != c && '\\' != c) {
+ state = 'authority';
+ continue;
+ } else {
+ err('Expected authority, got: ' + c);
+ }
+ break;
+
+ case 'authority':
+ if ('@' == c) {
+ if (seenAt) {
+ err('@ already seen.');
+ buffer += '%40';
+ }
+ seenAt = true;
+ for (var i = 0; i < buffer.length; i++) {
+ var cp = buffer[i];
+ if ('\t' == cp || '\n' == cp || '\r' == cp) {
+ err('Invalid whitespace in authority.');
+ continue;
+ }
+ // XXX check URL code points
+ if (':' == cp && null === this._password) {
+ this._password = '';
+ continue;
+ }
+ var tempC = percentEscape(cp);
+ null !== this._password ? this._password += tempC : this._username += tempC;
+ }
+ buffer = '';
+ } else if (EOF == c || '/' == c || '\\' == c || '?' == c || '#' == c) {
+ cursor -= buffer.length;
+ buffer = '';
+ state = 'host';
+ continue;
+ } else {
+ buffer += c;
+ }
+ break;
+
+ case 'file host':
+ if (EOF == c || '/' == c || '\\' == c || '?' == c || '#' == c) {
+ if (buffer.length == 2 && ALPHA.test(buffer[0]) && (buffer[1] == ':' || buffer[1] == '|')) {
+ state = 'relative path';
+ } else if (buffer.length == 0) {
+ state = 'relative path start';
+ } else {
+ this._host = IDNAToASCII.call(this, buffer);
+ buffer = '';
+ state = 'relative path start';
+ }
+ continue;
+ } else if ('\t' == c || '\n' == c || '\r' == c) {
+ err('Invalid whitespace in file host.');
+ } else {
+ buffer += c;
+ }
+ break;
+
+ case 'host':
+ case 'hostname':
+ if (':' == c && !seenBracket) {
+ // XXX host parsing
+ this._host = IDNAToASCII.call(this, buffer);
+ buffer = '';
+ state = 'port';
+ if ('hostname' == stateOverride) {
+ break loop;
+ }
+ } else if (EOF == c || '/' == c || '\\' == c || '?' == c || '#' == c) {
+ this._host = IDNAToASCII.call(this, buffer);
+ buffer = '';
+ state = 'relative path start';
+ if (stateOverride) {
+ break loop;
+ }
+ continue;
+ } else if ('\t' != c && '\n' != c && '\r' != c) {
+ if ('[' == c) {
+ seenBracket = true;
+ } else if (']' == c) {
+ seenBracket = false;
+ }
+ buffer += c;
+ } else {
+ err('Invalid code point in host/hostname: ' + c);
+ }
+ break;
+
+ case 'port':
+ if (/[0-9]/.test(c)) {
+ buffer += c;
+ } else if (EOF == c || '/' == c || '\\' == c || '?' == c || '#' == c || stateOverride) {
+ if ('' != buffer) {
+ var temp = parseInt(buffer, 10);
+ if (temp != relative[this._scheme]) {
+ this._port = temp + '';
+ }
+ buffer = '';
+ }
+ if (stateOverride) {
+ break loop;
+ }
+ state = 'relative path start';
+ continue;
+ } else if ('\t' == c || '\n' == c || '\r' == c) {
+ err('Invalid code point in port: ' + c);
+ } else {
+ invalid.call(this);
+ }
+ break;
+
+ case 'relative path start':
+ if ('\\' == c) err("'\\' not allowed in path.");
+ state = 'relative path';
+ if ('/' != c && '\\' != c) {
+ continue;
+ }
+ break;
+
+ case 'relative path':
+ if (EOF == c || '/' == c || '\\' == c || !stateOverride && ('?' == c || '#' == c)) {
+ if ('\\' == c) {
+ err('\\ not allowed in relative path.');
+ }
+ var tmp;
+ if (tmp = relativePathDotMapping[buffer.toLowerCase()]) {
+ buffer = tmp;
+ }
+ if ('..' == buffer) {
+ this._path.pop();
+ if ('/' != c && '\\' != c) {
+ this._path.push('');
+ }
+ } else if ('.' == buffer && '/' != c && '\\' != c) {
+ this._path.push('');
+ } else if ('.' != buffer) {
+ if ('file' == this._scheme && this._path.length == 0 && buffer.length == 2 && ALPHA.test(buffer[0]) && buffer[1] == '|') {
+ buffer = buffer[0] + ':';
+ }
+ this._path.push(buffer);
+ }
+ buffer = '';
+ if ('?' == c) {
+ this._query = '?';
+ state = 'query';
+ } else if ('#' == c) {
+ this._fragment = '#';
+ state = 'fragment';
+ }
+ } else if ('\t' != c && '\n' != c && '\r' != c) {
+ buffer += percentEscape(c);
+ }
+ break;
+
+ case 'query':
+ if (!stateOverride && '#' == c) {
+ this._fragment = '#';
+ state = 'fragment';
+ } else if (EOF != c && '\t' != c && '\n' != c && '\r' != c) {
+ this._query += percentEscapeQuery(c);
+ }
+ break;
+
+ case 'fragment':
+ if (EOF != c && '\t' != c && '\n' != c && '\r' != c) {
+ this._fragment += c;
+ }
+ break;
+ }
+
+ cursor++;
+ }
+ }
+
+ function clear() {
+ this._scheme = '';
+ this._schemeData = '';
+ this._username = '';
+ this._password = null;
+ this._host = '';
+ this._port = '';
+ this._path = [];
+ this._query = '';
+ this._fragment = '';
+ this._isInvalid = false;
+ this._isRelative = false;
+ }
+
+ // Does not process domain names or IP addresses.
+ // Does not handle encoding for the query parameter.
+ function jURL(url, base /* , encoding */) {
+ if (base !== undefined && !(base instanceof jURL)) base = new jURL(String(base));
+
+ this._url = url;
+ clear.call(this);
+
+ var input = url.replace(/^[ \t\r\n\f]+|[ \t\r\n\f]+$/g, '');
+ // encoding = encoding || 'utf-8'
+
+ parse.call(this, input, null, base);
+ }
+
+ jURL.prototype = {
+ toString: function toString() {
+ return this.href;
+ },
+ get href() {
+ if (this._isInvalid) return this._url;
+
+ var authority = '';
+ if ('' != this._username || null != this._password) {
+ authority = this._username + (null != this._password ? ':' + this._password : '') + '@';
+ }
+
+ return this.protocol + (this._isRelative ? '//' + authority + this.host : '') + this.pathname + this._query + this._fragment;
+ },
+ set href(href) {
+ clear.call(this);
+ parse.call(this, href);
+ },
+
+ get protocol() {
+ return this._scheme + ':';
+ },
+ set protocol(protocol) {
+ if (this._isInvalid) return;
+ parse.call(this, protocol + ':', 'scheme start');
+ },
+
+ get host() {
+ return this._isInvalid ? '' : this._port ? this._host + ':' + this._port : this._host;
+ },
+ set host(host) {
+ if (this._isInvalid || !this._isRelative) return;
+ parse.call(this, host, 'host');
+ },
+
+ get hostname() {
+ return this._host;
+ },
+ set hostname(hostname) {
+ if (this._isInvalid || !this._isRelative) return;
+ parse.call(this, hostname, 'hostname');
+ },
+
+ get port() {
+ return this._port;
+ },
+ set port(port) {
+ if (this._isInvalid || !this._isRelative) return;
+ parse.call(this, port, 'port');
+ },
+
+ get pathname() {
+ return this._isInvalid ? '' : this._isRelative ? '/' + this._path.join('/') : this._schemeData;
+ },
+ set pathname(pathname) {
+ if (this._isInvalid || !this._isRelative) return;
+ this._path = [];
+ parse.call(this, pathname, 'relative path start');
+ },
+
+ get search() {
+ return this._isInvalid || !this._query || '?' == this._query ? '' : this._query;
+ },
+ set search(search) {
+ if (this._isInvalid || !this._isRelative) return;
+ this._query = '?';
+ if ('?' == search[0]) search = search.slice(1);
+ parse.call(this, search, 'query');
+ },
+
+ get hash() {
+ return this._isInvalid || !this._fragment || '#' == this._fragment ? '' : this._fragment;
+ },
+ set hash(hash) {
+ if (this._isInvalid) return;
+ this._fragment = '#';
+ if ('#' == hash[0]) hash = hash.slice(1);
+ parse.call(this, hash, 'fragment');
+ },
+
+ get origin() {
+ var host;
+ if (this._isInvalid || !this._scheme) {
+ return '';
+ }
+ // javascript: Gecko returns String(""), WebKit/Blink String("null")
+ // Gecko throws error for "data://"
+ // data: Gecko returns "", Blink returns "data://", WebKit returns "null"
+ // Gecko returns String("") for file: mailto:
+ // WebKit/Blink returns String("SCHEME://") for file: mailto:
+ switch (this._scheme) {
+ case 'file':
+ return 'file://'; // EPUBJS Added
+ case 'data':
+ case 'javascript':
+ case 'mailto':
+ return 'null';
+ }
+ host = this.host;
+ if (!host) {
+ return '';
+ }
+ return this._scheme + '://' + host;
+ }
+ };
+
+ // Copy over the static methods
+ var OriginalURL = scope.URL;
+ if (OriginalURL) {
+ jURL.createObjectURL = function (blob) {
+ // IE extension allows a second optional options argument.
+ // http://msdn.microsoft.com/en-us/library/ie/hh772302(v=vs.85).aspx
+ return OriginalURL.createObjectURL.apply(OriginalURL, arguments);
+ };
+ jURL.revokeObjectURL = function (url) {
+ OriginalURL.revokeObjectURL(url);
+ };
+ }
+
+ return jURL;
+});
+/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(8), __webpack_require__(70)(module)))
+
+/***/ }),
+/* 70 */
+/***/ (function(module, exports) {
+
+module.exports = function(module) {
+ if(!module.webpackPolyfill) {
+ module.deprecate = function() {};
+ module.paths = [];
+ // module.parent = undefined by default
+ if(!module.children) module.children = [];
+ Object.defineProperty(module, "loaded", {
+ enumerable: true,
+ get: function() {
+ return module.l;
+ }
+ });
+ Object.defineProperty(module, "id", {
+ enumerable: true,
+ get: function() {
+ return module.i;
+ }
+ });
+ module.webpackPolyfill = 1;
+ }
+ return module;
+};
+
+
+/***/ })
+/******/ ]);
+});
+//# sourceMappingURL=epub.js.map
\ No newline at end of file