Spaces:
No application file
No application file
| (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__) { | |
| ; | |
| 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__) { | |
| ; | |
| 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__) { | |
| ; | |
| 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__) { | |
| ; | |
| 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__) { | |
| ; | |
| 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__) { | |
| ; | |
| 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__) { | |
| ; | |
| 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__) { | |
| ; | |
| 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__) { | |
| ; | |
| var _undefined = __webpack_require__(34)(); // Support ES3 engines | |
| module.exports = function (val) { | |
| return (val !== _undefined) && (val !== null); | |
| }; | |
| /***/ }), | |
| /* 10 */ | |
| /***/ (function(module, exports, __webpack_require__) { | |
| ; | |
| 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__) { | |
| ; | |
| 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__) { | |
| ; | |
| 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__) { | |
| ; | |
| 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 | |
| * <meta name="viewport" content="width=1024,height=697" /> | |
| */ | |
| 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-left", gap / 2 + "px", true); | |
| this.css("padding-right", 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__) { | |
| ; | |
| 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__) { | |
| ; | |
| /* | |
| 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__) { | |
| ; | |
| 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__) { | |
| ; | |
| 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__) { | |
| ; | |
| 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__) { | |
| ; | |
| 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__) { | |
| ; | |
| /* 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__) { | |
| ; | |
| 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__) { | |
| ; | |
| 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__) { | |
| ; | |
| module.exports = __webpack_require__(29)() | |
| ? Object.assign | |
| : __webpack_require__(30); | |
| /***/ }), | |
| /* 29 */ | |
| /***/ (function(module, exports, __webpack_require__) { | |
| ; | |
| 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__) { | |
| ; | |
| 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__) { | |
| ; | |
| module.exports = __webpack_require__(32)() | |
| ? Object.keys | |
| : __webpack_require__(33); | |
| /***/ }), | |
| /* 32 */ | |
| /***/ (function(module, exports, __webpack_require__) { | |
| ; | |
| module.exports = function () { | |
| try { | |
| Object.keys("primitive"); | |
| return true; | |
| } catch (e) { | |
| return false; | |
| } | |
| }; | |
| /***/ }), | |
| /* 33 */ | |
| /***/ (function(module, exports, __webpack_require__) { | |
| ; | |
| 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__) { | |
| ; | |
| // eslint-disable-next-line no-empty-function | |
| module.exports = function () {}; | |
| /***/ }), | |
| /* 35 */ | |
| /***/ (function(module, exports, __webpack_require__) { | |
| ; | |
| 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__) { | |
| ; | |
| 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__) { | |
| ; | |
| // Deprecated | |
| module.exports = function (obj) { | |
| return typeof obj === "function"; | |
| }; | |
| /***/ }), | |
| /* 38 */ | |
| /***/ (function(module, exports, __webpack_require__) { | |
| ; | |
| module.exports = __webpack_require__(39)() | |
| ? String.prototype.contains | |
| : __webpack_require__(40); | |
| /***/ }), | |
| /* 39 */ | |
| /***/ (function(module, exports, __webpack_require__) { | |
| ; | |
| 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__) { | |
| ; | |
| var indexOf = String.prototype.indexOf; | |
| module.exports = function (searchString/*, position*/) { | |
| return indexOf.call(this, searchString, arguments[1]) > -1; | |
| }; | |
| /***/ }), | |
| /* 41 */ | |
| /***/ (function(module, exports, __webpack_require__) { | |
| ; | |
| module.exports = function (fn) { | |
| if (typeof fn !== "function") throw new TypeError(fn + " is not a function"); | |
| return fn; | |
| }; | |
| /***/ }), | |
| /* 42 */ | |
| /***/ (function(module, exports, __webpack_require__) { | |
| ; | |
| 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__) { | |
| ; | |
| 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__) { | |
| ; | |
| 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__) { | |
| ; | |
| 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) { | |
| //-- <rootfile full-path="OPS/package.opf" media-type="application/oebps-package+xml"/> | |
| 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__) { | |
| ; | |
| 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.series = this.getMetaContent(xml, "calibre:series"); | |
| metadata.seriesIndex = this.getMetaContent(xml, "calibre:series_index"); | |
| 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 | |
| * <item properties="cover-image" id="ci" href="cover.svg" media-type="image/svg+xml" /> | |
| * 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 ""; | |
| } | |
| /** | |
| * Get meta content | |
| * @private | |
| * @param {document} xml | |
| * @param {string} name | |
| * @return {string} text | |
| */ | |
| }, { | |
| key: 'getMetaContent', | |
| value: function getMetaContent(xml, name) { | |
| var el = (0, _core.qsp)(xml, "meta", { "name": name }); | |
| if (el && el.getAttribute("content")) { | |
| return el.getAttribute("content"); | |
| } | |
| 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__) { | |
| ; | |
| 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__) { | |
| ; | |
| 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__) { | |
| ; | |
| 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__) { | |
| ; | |
| 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__) { | |
| ; | |
| 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__) { | |
| ; | |
| 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__) { | |
| ; | |
| 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__) { | |
| ; | |
| 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__) { | |
| ; | |
| 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__) { | |
| ; | |
| 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__) { | |
| ; | |
| 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__) { | |
| ; | |
| 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__) { | |
| ; | |
| /* 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; | |
| }; | |
| /***/ }) | |
| /******/ ]); | |
| }); |