Skip to content

Instantly share code, notes, and snippets.

@lisonge
Last active August 11, 2023 17:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lisonge/3aede893b68287a15ce61f2184fa6d87 to your computer and use it in GitHub Desktop.
Save lisonge/3aede893b68287a15ce61f2184fa6d87 to your computer and use it in GitHub Desktop.
(function(global2, factory) {
typeof exports === "object" && typeof module !== "undefined" ? factory(exports, require("jszip/dist/jszip")) : typeof define === "function" && define.amd ? define(["exports", "jszip/dist/jszip"], factory) : (global2 = typeof globalThis !== "undefined" ? globalThis : global2 || self, factory(global2.ePub = {}, global2.JSZip));
})(this, function(exports2, JSZip) {
"use strict";
var commonjsGlobal = typeof globalThis !== "undefined" ? globalThis : typeof window !== "undefined" ? window : typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : {};
function getDefaultExportFromCjs(x) {
return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, "default") ? x["default"] : x;
}
var eventEmitter = { exports: {} };
var d$1 = { exports: {} };
var _undefined$1 = void 0;
var is$4 = function(value) {
return value !== _undefined$1 && value !== null;
};
var isValue$3 = is$4;
var possibleTypes = {
"object": true,
"function": true,
"undefined": true
/* document.all */
};
var is$3 = function(value) {
if (!isValue$3(value))
return false;
return hasOwnProperty.call(possibleTypes, typeof value);
};
var isObject$4 = is$3;
var is$2 = function(value) {
if (!isObject$4(value))
return false;
try {
if (!value.constructor)
return false;
return value.constructor.prototype === value;
} catch (error) {
return false;
}
};
var isPrototype = is$2;
var is$1 = function(value) {
if (typeof value !== "function")
return false;
if (!hasOwnProperty.call(value, "length"))
return false;
try {
if (typeof value.length !== "number")
return false;
if (typeof value.call !== "function")
return false;
if (typeof value.apply !== "function")
return false;
} catch (error) {
return false;
}
return !isPrototype(value);
};
var isFunction = is$1;
var classRe = /^\s*class[\s{/}]/, functionToString = Function.prototype.toString;
var is = function(value) {
if (!isFunction(value))
return false;
if (classRe.test(functionToString.call(value)))
return false;
return true;
};
var isImplemented$2 = function() {
var assign2 = Object.assign, obj;
if (typeof assign2 !== "function")
return false;
obj = { foo: "raz" };
assign2(obj, { bar: "dwa" }, { trzy: "trzy" });
return obj.foo + obj.bar + obj.trzy === "razdwatrzy";
};
var isImplemented$1;
var hasRequiredIsImplemented;
function requireIsImplemented() {
if (hasRequiredIsImplemented)
return isImplemented$1;
hasRequiredIsImplemented = 1;
isImplemented$1 = function() {
try {
Object.keys("primitive");
return true;
} catch (e) {
return false;
}
};
return isImplemented$1;
}
var noop = function() {
};
var _undefined = noop();
var isValue$2 = function(val) {
return val !== _undefined && val !== null;
};
var shim$2;
var hasRequiredShim$2;
function requireShim$2() {
if (hasRequiredShim$2)
return shim$2;
hasRequiredShim$2 = 1;
var isValue2 = isValue$2;
var keys2 = Object.keys;
shim$2 = function(object) {
return keys2(isValue2(object) ? Object(object) : object);
};
return shim$2;
}
var keys;
var hasRequiredKeys;
function requireKeys() {
if (hasRequiredKeys)
return keys;
hasRequiredKeys = 1;
keys = requireIsImplemented()() ? Object.keys : requireShim$2();
return keys;
}
var validValue;
var hasRequiredValidValue;
function requireValidValue() {
if (hasRequiredValidValue)
return validValue;
hasRequiredValidValue = 1;
var isValue2 = isValue$2;
validValue = function(value) {
if (!isValue2(value))
throw new TypeError("Cannot use null or undefined");
return value;
};
return validValue;
}
var shim$1;
var hasRequiredShim$1;
function requireShim$1() {
if (hasRequiredShim$1)
return shim$1;
hasRequiredShim$1 = 1;
var keys2 = requireKeys(), value = requireValidValue(), max = Math.max;
shim$1 = function(dest, src) {
var error, i, length = max(arguments.length, 2), assign2;
dest = Object(value(dest));
assign2 = function(key) {
try {
dest[key] = src[key];
} catch (e) {
if (!error)
error = e;
}
};
for (i = 1; i < length; ++i) {
src = arguments[i];
keys2(src).forEach(assign2);
}
if (error !== void 0)
throw error;
return dest;
};
return shim$1;
}
var assign$1 = isImplemented$2() ? Object.assign : requireShim$1();
var isValue$1 = isValue$2;
var forEach = Array.prototype.forEach, create = Object.create;
var process$1 = function(src, obj) {
var key;
for (key in src)
obj[key] = src[key];
};
var normalizeOptions = function(opts1) {
var result = create(null);
forEach.call(arguments, function(options) {
if (!isValue$1(options))
return;
process$1(Object(options), result);
});
return result;
};
var str = "razdwatrzy";
var isImplemented = function() {
if (typeof str.contains !== "function")
return false;
return str.contains("dwa") === true && str.contains("foo") === false;
};
var shim;
var hasRequiredShim;
function requireShim() {
if (hasRequiredShim)
return shim;
hasRequiredShim = 1;
var indexOf = String.prototype.indexOf;
shim = function(searchString) {
return indexOf.call(this, searchString, arguments[1]) > -1;
};
return shim;
}
var contains$3 = isImplemented() ? String.prototype.contains : requireShim();
var isValue = is$4, isPlainFunction = is, assign = assign$1, normalizeOpts = normalizeOptions, contains$2 = contains$3;
var d = d$1.exports = function(dscr, value) {
var c, e, w, options, desc;
if (arguments.length < 2 || typeof dscr !== "string") {
options = value;
value = dscr;
dscr = null;
} else {
options = arguments[2];
}
if (isValue(dscr)) {
c = contains$2.call(dscr, "c");
e = contains$2.call(dscr, "e");
w = contains$2.call(dscr, "w");
} else {
c = w = true;
e = false;
}
desc = { value, configurable: c, enumerable: e, writable: w };
return !options ? desc : assign(normalizeOpts(options), desc);
};
d.gs = function(dscr, get, set) {
var c, e, options, desc;
if (typeof dscr !== "string") {
options = set;
set = get;
get = dscr;
dscr = null;
} else {
options = arguments[3];
}
if (!isValue(get)) {
get = void 0;
} else if (!isPlainFunction(get)) {
options = get;
get = set = void 0;
} else if (!isValue(set)) {
set = void 0;
} else if (!isPlainFunction(set)) {
options = set;
set = void 0;
}
if (isValue(dscr)) {
c = contains$2.call(dscr, "c");
e = contains$2.call(dscr, "e");
} else {
c = true;
e = false;
}
desc = { get, set, configurable: c, enumerable: e };
return !options ? desc : assign(normalizeOpts(options), desc);
};
var dExports = d$1.exports;
var validCallable = function(fn) {
if (typeof fn !== "function")
throw new TypeError(fn + " is not a function");
return fn;
};
(function(module2, exports3) {
var d2 = dExports, callable = validCallable, apply = Function.prototype.apply, call = Function.prototype.call, create2 = Object.create, defineProperty = Object.defineProperty, defineProperties = Object.defineProperties, hasOwnProperty2 = Object.prototype.hasOwnProperty, descriptor = { configurable: true, enumerable: false, writable: true }, on, once, off, emit, methods, descriptors, base;
on = function(type2, listener) {
var data;
callable(listener);
if (!hasOwnProperty2.call(this, "__ee__")) {
data = descriptor.value = create2(null);
defineProperty(this, "__ee__", descriptor);
descriptor.value = null;
} else {
data = this.__ee__;
}
if (!data[type2])
data[type2] = listener;
else if (typeof data[type2] === "object")
data[type2].push(listener);
else
data[type2] = [data[type2], listener];
return this;
};
once = function(type2, listener) {
var once2, self2;
callable(listener);
self2 = this;
on.call(this, type2, once2 = function() {
off.call(self2, type2, once2);
apply.call(listener, this, arguments);
});
once2.__eeOnceListener__ = listener;
return this;
};
off = function(type2, listener) {
var data, listeners, candidate, i;
callable(listener);
if (!hasOwnProperty2.call(this, "__ee__"))
return this;
data = this.__ee__;
if (!data[type2])
return this;
listeners = data[type2];
if (typeof listeners === "object") {
for (i = 0; candidate = listeners[i]; ++i) {
if (candidate === listener || candidate.__eeOnceListener__ === listener) {
if (listeners.length === 2)
data[type2] = listeners[i ? 0 : 1];
else
listeners.splice(i, 1);
}
}
} else {
if (listeners === listener || listeners.__eeOnceListener__ === listener) {
delete data[type2];
}
}
return this;
};
emit = function(type2) {
var i, l, listener, listeners, args;
if (!hasOwnProperty2.call(this, "__ee__"))
return;
listeners = this.__ee__[type2];
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,
once,
off,
emit
};
descriptors = {
on: d2(on),
once: d2(once),
off: d2(off),
emit: d2(emit)
};
base = defineProperties({}, descriptors);
module2.exports = exports3 = function(o) {
return o == null ? create2(base) : defineProperties(Object(o), descriptors);
};
exports3.methods = methods;
})(eventEmitter, eventEmitter.exports);
var eventEmitterExports = eventEmitter.exports;
const EventEmitter = /* @__PURE__ */ getDefaultExportFromCjs(eventEmitterExports);
var dom$1 = {};
var conventions$2 = {};
function find$1(list, predicate, ac) {
if (ac === void 0) {
ac = Array.prototype;
}
if (list && typeof ac.find === "function") {
return ac.find.call(list, predicate);
}
for (var i = 0; i < list.length; i++) {
if (Object.prototype.hasOwnProperty.call(list, i)) {
var item = list[i];
if (predicate.call(void 0, item, i, list)) {
return item;
}
}
}
}
function freeze(object, oc) {
if (oc === void 0) {
oc = Object;
}
return oc && typeof oc.freeze === "function" ? oc.freeze(object) : object;
}
var MIME_TYPE = freeze({
/**
* `text/html`, the only mime type that triggers treating an XML document as HTML.
*
* @see DOMParser.SupportedType.isHTML
* @see https://www.iana.org/assignments/media-types/text/html IANA MimeType registration
* @see https://en.wikipedia.org/wiki/HTML Wikipedia
* @see https://developer.mozilla.org/en-US/docs/Web/API/DOMParser/parseFromString MDN
* @see https://html.spec.whatwg.org/multipage/dynamic-markup-insertion.html#dom-domparser-parsefromstring WHATWG HTML Spec
*/
HTML: "text/html",
/**
* Helper method to check a mime type if it indicates an HTML document
*
* @param {string} [value]
* @returns {boolean}
*
* @see https://www.iana.org/assignments/media-types/text/html IANA MimeType registration
* @see https://en.wikipedia.org/wiki/HTML Wikipedia
* @see https://developer.mozilla.org/en-US/docs/Web/API/DOMParser/parseFromString MDN
* @see https://html.spec.whatwg.org/multipage/dynamic-markup-insertion.html#dom-domparser-parsefromstring */
isHTML: function(value) {
return value === MIME_TYPE.HTML;
},
/**
* `application/xml`, the standard mime type for XML documents.
*
* @see https://www.iana.org/assignments/media-types/application/xml IANA MimeType registration
* @see https://tools.ietf.org/html/rfc7303#section-9.1 RFC 7303
* @see https://en.wikipedia.org/wiki/XML_and_MIME Wikipedia
*/
XML_APPLICATION: "application/xml",
/**
* `text/html`, an alias for `application/xml`.
*
* @see https://tools.ietf.org/html/rfc7303#section-9.2 RFC 7303
* @see https://www.iana.org/assignments/media-types/text/xml IANA MimeType registration
* @see https://en.wikipedia.org/wiki/XML_and_MIME Wikipedia
*/
XML_TEXT: "text/xml",
/**
* `application/xhtml+xml`, indicates an XML document that has the default HTML namespace,
* but is parsed as an XML document.
*
* @see https://www.iana.org/assignments/media-types/application/xhtml+xml IANA MimeType registration
* @see https://dom.spec.whatwg.org/#dom-domimplementation-createdocument WHATWG DOM Spec
* @see https://en.wikipedia.org/wiki/XHTML Wikipedia
*/
XML_XHTML_APPLICATION: "application/xhtml+xml",
/**
* `image/svg+xml`,
*
* @see https://www.iana.org/assignments/media-types/image/svg+xml IANA MimeType registration
* @see https://www.w3.org/TR/SVG11/ W3C SVG 1.1
* @see https://en.wikipedia.org/wiki/Scalable_Vector_Graphics Wikipedia
*/
XML_SVG_IMAGE: "image/svg+xml"
});
var NAMESPACE$3 = freeze({
/**
* The XHTML namespace.
*
* @see http://www.w3.org/1999/xhtml
*/
HTML: "http://www.w3.org/1999/xhtml",
/**
* Checks if `uri` equals `NAMESPACE.HTML`.
*
* @param {string} [uri]
*
* @see NAMESPACE.HTML
*/
isHTML: function(uri) {
return uri === NAMESPACE$3.HTML;
},
/**
* The SVG namespace.
*
* @see http://www.w3.org/2000/svg
*/
SVG: "http://www.w3.org/2000/svg",
/**
* The `xml:` namespace.
*
* @see http://www.w3.org/XML/1998/namespace
*/
XML: "http://www.w3.org/XML/1998/namespace",
/**
* The `xmlns:` namespace
*
* @see https://www.w3.org/2000/xmlns/
*/
XMLNS: "http://www.w3.org/2000/xmlns/"
});
conventions$2.find = find$1;
conventions$2.freeze = freeze;
conventions$2.MIME_TYPE = MIME_TYPE;
conventions$2.NAMESPACE = NAMESPACE$3;
var conventions$1 = conventions$2;
var find = conventions$1.find;
var NAMESPACE$2 = conventions$1.NAMESPACE;
function notEmptyString(input) {
return input !== "";
}
function splitOnASCIIWhitespace(input) {
return input ? input.split(/[\t\n\f\r ]+/).filter(notEmptyString) : [];
}
function orderedSetReducer(current, element) {
if (!current.hasOwnProperty(element)) {
current[element] = true;
}
return current;
}
function toOrderedSet(input) {
if (!input)
return [];
var list = splitOnASCIIWhitespace(input);
return Object.keys(list.reduce(orderedSetReducer, {}));
}
function arrayIncludes(list) {
return function(element) {
return list && list.indexOf(element) !== -1;
};
}
function copy(src, dest) {
for (var p in src) {
if (Object.prototype.hasOwnProperty.call(src, p)) {
dest[p] = src[p];
}
}
}
function _extends(Class, Super) {
var pt = Class.prototype;
if (!(pt instanceof Super)) {
let t = function() {
};
t.prototype = Super.prototype;
t = new t();
copy(pt, t);
Class.prototype = pt = t;
}
if (pt.constructor != Class) {
if (typeof Class != "function") {
console.error("unknown Class:" + Class);
}
pt.constructor = Class;
}
}
var NodeType = {};
var ELEMENT_NODE$3 = NodeType.ELEMENT_NODE = 1;
var ATTRIBUTE_NODE = NodeType.ATTRIBUTE_NODE = 2;
var TEXT_NODE$2 = NodeType.TEXT_NODE = 3;
var CDATA_SECTION_NODE = NodeType.CDATA_SECTION_NODE = 4;
var ENTITY_REFERENCE_NODE = NodeType.ENTITY_REFERENCE_NODE = 5;
var ENTITY_NODE = NodeType.ENTITY_NODE = 6;
var PROCESSING_INSTRUCTION_NODE = NodeType.PROCESSING_INSTRUCTION_NODE = 7;
var COMMENT_NODE = NodeType.COMMENT_NODE = 8;
var DOCUMENT_NODE$1 = NodeType.DOCUMENT_NODE = 9;
var DOCUMENT_TYPE_NODE = NodeType.DOCUMENT_TYPE_NODE = 10;
var DOCUMENT_FRAGMENT_NODE = NodeType.DOCUMENT_FRAGMENT_NODE = 11;
var NOTATION_NODE = NodeType.NOTATION_NODE = 12;
var ExceptionCode = {};
var ExceptionMessage = {};
ExceptionCode.INDEX_SIZE_ERR = (ExceptionMessage[1] = "Index size error", 1);
ExceptionCode.DOMSTRING_SIZE_ERR = (ExceptionMessage[2] = "DOMString size error", 2);
var HIERARCHY_REQUEST_ERR = ExceptionCode.HIERARCHY_REQUEST_ERR = (ExceptionMessage[3] = "Hierarchy request error", 3);
ExceptionCode.WRONG_DOCUMENT_ERR = (ExceptionMessage[4] = "Wrong document", 4);
ExceptionCode.INVALID_CHARACTER_ERR = (ExceptionMessage[5] = "Invalid character", 5);
ExceptionCode.NO_DATA_ALLOWED_ERR = (ExceptionMessage[6] = "No data allowed", 6);
ExceptionCode.NO_MODIFICATION_ALLOWED_ERR = (ExceptionMessage[7] = "No modification allowed", 7);
var NOT_FOUND_ERR = ExceptionCode.NOT_FOUND_ERR = (ExceptionMessage[8] = "Not found", 8);
ExceptionCode.NOT_SUPPORTED_ERR = (ExceptionMessage[9] = "Not supported", 9);
var INUSE_ATTRIBUTE_ERR = ExceptionCode.INUSE_ATTRIBUTE_ERR = (ExceptionMessage[10] = "Attribute in use", 10);
ExceptionCode.INVALID_STATE_ERR = (ExceptionMessage[11] = "Invalid state", 11);
ExceptionCode.SYNTAX_ERR = (ExceptionMessage[12] = "Syntax error", 12);
ExceptionCode.INVALID_MODIFICATION_ERR = (ExceptionMessage[13] = "Invalid modification", 13);
ExceptionCode.NAMESPACE_ERR = (ExceptionMessage[14] = "Invalid namespace", 14);
ExceptionCode.INVALID_ACCESS_ERR = (ExceptionMessage[15] = "Invalid access", 15);
function DOMException(code, message) {
if (message instanceof Error) {
var error = message;
} else {
error = this;
Error.call(this, ExceptionMessage[code]);
this.message = ExceptionMessage[code];
if (Error.captureStackTrace)
Error.captureStackTrace(this, DOMException);
}
error.code = code;
if (message)
this.message = this.message + ": " + message;
return error;
}
DOMException.prototype = Error.prototype;
copy(ExceptionCode, DOMException);
function NodeList() {
}
NodeList.prototype = {
/**
* The number of nodes in the list. The range of valid child node indices is 0 to length-1 inclusive.
* @standard level1
*/
length: 0,
/**
* Returns the indexth item in the collection. If index is greater than or equal to the number of nodes in the list, this returns null.
* @standard level1
* @param index unsigned long
* Index into the collection.
* @return Node
* The node at the indexth position in the NodeList, or null if that is not a valid index.
*/
item: function(index) {
return index >= 0 && index < this.length ? this[index] : null;
},
toString: function(isHTML, nodeFilter) {
for (var buf = [], i = 0; i < this.length; i++) {
serializeToString(this[i], buf, isHTML, nodeFilter);
}
return buf.join("");
},
/**
* @private
* @param {function (Node):boolean} predicate
* @returns {Node[]}
*/
filter: function(predicate) {
return Array.prototype.filter.call(this, predicate);
},
/**
* @private
* @param {Node} item
* @returns {number}
*/
indexOf: function(item) {
return Array.prototype.indexOf.call(this, item);
}
};
function LiveNodeList(node, refresh) {
this._node = node;
this._refresh = refresh;
_updateLiveList(this);
}
function _updateLiveList(list) {
var inc = list._node._inc || list._node.ownerDocument._inc;
if (list._inc !== inc) {
var ls = list._refresh(list._node);
__set__(list, "length", ls.length);
if (!list.$$length || ls.length < list.$$length) {
for (var i = ls.length; i in list; i++) {
if (Object.prototype.hasOwnProperty.call(list, i)) {
delete list[i];
}
}
}
copy(ls, list);
list._inc = inc;
}
}
LiveNodeList.prototype.item = function(i) {
_updateLiveList(this);
return this[i] || null;
};
_extends(LiveNodeList, NodeList);
function NamedNodeMap() {
}
function _findNodeIndex(list, node) {
var i = list.length;
while (i--) {
if (list[i] === node) {
return i;
}
}
}
function _addNamedNode(el, list, newAttr, oldAttr) {
if (oldAttr) {
list[_findNodeIndex(list, oldAttr)] = newAttr;
} else {
list[list.length++] = newAttr;
}
if (el) {
newAttr.ownerElement = el;
var doc = el.ownerDocument;
if (doc) {
oldAttr && _onRemoveAttribute(doc, el, oldAttr);
_onAddAttribute(doc, el, newAttr);
}
}
}
function _removeNamedNode(el, list, attr) {
var i = _findNodeIndex(list, attr);
if (i >= 0) {
var lastIndex = list.length - 1;
while (i < lastIndex) {
list[i] = list[++i];
}
list.length = lastIndex;
if (el) {
var doc = el.ownerDocument;
if (doc) {
_onRemoveAttribute(doc, el, attr);
attr.ownerElement = null;
}
}
} else {
throw new DOMException(NOT_FOUND_ERR, new Error(el.tagName + "@" + attr));
}
}
NamedNodeMap.prototype = {
length: 0,
item: NodeList.prototype.item,
getNamedItem: function(key) {
var i = this.length;
while (i--) {
var attr = this[i];
if (attr.nodeName == key) {
return attr;
}
}
},
setNamedItem: function(attr) {
var el = attr.ownerElement;
if (el && el != this._ownerElement) {
throw new DOMException(INUSE_ATTRIBUTE_ERR);
}
var oldAttr = this.getNamedItem(attr.nodeName);
_addNamedNode(this._ownerElement, this, attr, oldAttr);
return oldAttr;
},
/* returns Node */
setNamedItemNS: function(attr) {
var el = attr.ownerElement, oldAttr;
if (el && el != this._ownerElement) {
throw new DOMException(INUSE_ATTRIBUTE_ERR);
}
oldAttr = this.getNamedItemNS(attr.namespaceURI, attr.localName);
_addNamedNode(this._ownerElement, this, attr, oldAttr);
return oldAttr;
},
/* returns Node */
removeNamedItem: function(key) {
var attr = this.getNamedItem(key);
_removeNamedNode(this._ownerElement, this, attr);
return attr;
},
// raises: NOT_FOUND_ERR,NO_MODIFICATION_ALLOWED_ERR
//for level2
removeNamedItemNS: function(namespaceURI, localName) {
var attr = this.getNamedItemNS(namespaceURI, localName);
_removeNamedNode(this._ownerElement, this, attr);
return attr;
},
getNamedItemNS: function(namespaceURI, localName) {
var i = this.length;
while (i--) {
var node = this[i];
if (node.localName == localName && node.namespaceURI == namespaceURI) {
return node;
}
}
return null;
}
};
function DOMImplementation$1() {
}
DOMImplementation$1.prototype = {
/**
* The DOMImplementation.hasFeature() method returns a Boolean flag indicating if a given feature is supported.
* The different implementations fairly diverged in what kind of features were reported.
* The latest version of the spec settled to force this method to always return true, where the functionality was accurate and in use.
*
* @deprecated It is deprecated and modern browsers return true in all cases.
*
* @param {string} feature
* @param {string} [version]
* @returns {boolean} always true
*
* @see https://developer.mozilla.org/en-US/docs/Web/API/DOMImplementation/hasFeature MDN
* @see https://www.w3.org/TR/REC-DOM-Level-1/level-one-core.html#ID-5CED94D7 DOM Level 1 Core
* @see https://dom.spec.whatwg.org/#dom-domimplementation-hasfeature DOM Living Standard
*/
hasFeature: function(feature, version) {
return true;
},
/**
* Creates an XML Document object of the specified type with its document element.
*
* __It behaves slightly different from the description in the living standard__:
* - There is no interface/class `XMLDocument`, it returns a `Document` instance.
* - `contentType`, `encoding`, `mode`, `origin`, `url` fields are currently not declared.
* - this implementation is not validating names or qualified names
* (when parsing XML strings, the SAX parser takes care of that)
*
* @param {string|null} namespaceURI
* @param {string} qualifiedName
* @param {DocumentType=null} doctype
* @returns {Document}
*
* @see https://developer.mozilla.org/en-US/docs/Web/API/DOMImplementation/createDocument MDN
* @see https://www.w3.org/TR/DOM-Level-2-Core/core.html#Level-2-Core-DOM-createDocument DOM Level 2 Core (initial)
* @see https://dom.spec.whatwg.org/#dom-domimplementation-createdocument DOM Level 2 Core
*
* @see https://dom.spec.whatwg.org/#validate-and-extract DOM: Validate and extract
* @see https://www.w3.org/TR/xml/#NT-NameStartChar XML Spec: Names
* @see https://www.w3.org/TR/xml-names/#ns-qualnames XML Namespaces: Qualified names
*/
createDocument: function(namespaceURI, qualifiedName, doctype) {
var doc = new Document();
doc.implementation = this;
doc.childNodes = new NodeList();
doc.doctype = doctype || null;
if (doctype) {
doc.appendChild(doctype);
}
if (qualifiedName) {
var root2 = doc.createElementNS(namespaceURI, qualifiedName);
doc.appendChild(root2);
}
return doc;
},
/**
* Returns a doctype, with the given `qualifiedName`, `publicId`, and `systemId`.
*
* __This behavior is slightly different from the in the specs__:
* - this implementation is not validating names or qualified names
* (when parsing XML strings, the SAX parser takes care of that)
*
* @param {string} qualifiedName
* @param {string} [publicId]
* @param {string} [systemId]
* @returns {DocumentType} which can either be used with `DOMImplementation.createDocument` upon document creation
* or can be put into the document via methods like `Node.insertBefore()` or `Node.replaceChild()`
*
* @see https://developer.mozilla.org/en-US/docs/Web/API/DOMImplementation/createDocumentType MDN
* @see https://www.w3.org/TR/DOM-Level-2-Core/core.html#Level-2-Core-DOM-createDocType DOM Level 2 Core
* @see https://dom.spec.whatwg.org/#dom-domimplementation-createdocumenttype DOM Living Standard
*
* @see https://dom.spec.whatwg.org/#validate-and-extract DOM: Validate and extract
* @see https://www.w3.org/TR/xml/#NT-NameStartChar XML Spec: Names
* @see https://www.w3.org/TR/xml-names/#ns-qualnames XML Namespaces: Qualified names
*/
createDocumentType: function(qualifiedName, publicId, systemId) {
var node = new DocumentType();
node.name = qualifiedName;
node.nodeName = qualifiedName;
node.publicId = publicId || "";
node.systemId = systemId || "";
return node;
}
};
function Node$1() {
}
Node$1.prototype = {
firstChild: null,
lastChild: null,
previousSibling: null,
nextSibling: null,
attributes: null,
parentNode: null,
childNodes: null,
ownerDocument: null,
nodeValue: null,
namespaceURI: null,
prefix: null,
localName: null,
// Modified in DOM Level 2:
insertBefore: function(newChild, refChild) {
return _insertBefore(this, newChild, refChild);
},
replaceChild: function(newChild, oldChild) {
_insertBefore(this, newChild, oldChild, assertPreReplacementValidityInDocument);
if (oldChild) {
this.removeChild(oldChild);
}
},
removeChild: function(oldChild) {
return _removeChild(this, oldChild);
},
appendChild: function(newChild) {
return this.insertBefore(newChild, null);
},
hasChildNodes: function() {
return this.firstChild != null;
},
cloneNode: function(deep) {
return cloneNode(this.ownerDocument || this, this, deep);
},
// Modified in DOM Level 2:
normalize: function() {
var child = this.firstChild;
while (child) {
var next = child.nextSibling;
if (next && next.nodeType == TEXT_NODE$2 && child.nodeType == TEXT_NODE$2) {
this.removeChild(next);
child.appendData(next.data);
} else {
child.normalize();
child = next;
}
}
},
// Introduced in DOM Level 2:
isSupported: function(feature, version) {
return this.ownerDocument.implementation.hasFeature(feature, version);
},
// Introduced in DOM Level 2:
hasAttributes: function() {
return this.attributes.length > 0;
},
/**
* Look up the prefix associated to the given namespace URI, starting from this node.
* **The default namespace declarations are ignored by this method.**
* See Namespace Prefix Lookup for details on the algorithm used by this method.
*
* _Note: The implementation seems to be incomplete when compared to the algorithm described in the specs._
*
* @param {string | null} namespaceURI
* @returns {string | null}
* @see https://www.w3.org/TR/DOM-Level-3-Core/core.html#Node3-lookupNamespacePrefix
* @see https://www.w3.org/TR/DOM-Level-3-Core/namespaces-algorithms.html#lookupNamespacePrefixAlgo
* @see https://dom.spec.whatwg.org/#dom-node-lookupprefix
* @see https://github.com/xmldom/xmldom/issues/322
*/
lookupPrefix: function(namespaceURI) {
var el = this;
while (el) {
var map = el._nsMap;
if (map) {
for (var n in map) {
if (Object.prototype.hasOwnProperty.call(map, n) && map[n] === namespaceURI) {
return n;
}
}
}
el = el.nodeType == ATTRIBUTE_NODE ? el.ownerDocument : el.parentNode;
}
return null;
},
// Introduced in DOM Level 3:
lookupNamespaceURI: function(prefix) {
var el = this;
while (el) {
var map = el._nsMap;
if (map) {
if (prefix in map) {
if (Object.prototype.hasOwnProperty.call(map, prefix)) {
return map[prefix];
}
}
}
el = el.nodeType == ATTRIBUTE_NODE ? el.ownerDocument : el.parentNode;
}
return null;
},
// Introduced in DOM Level 3:
isDefaultNamespace: function(namespaceURI) {
var prefix = this.lookupPrefix(namespaceURI);
return prefix == null;
}
};
function _xmlEncoder(c) {
return c == "<" && "&lt;" || c == ">" && "&gt;" || c == "&" && "&amp;" || c == '"' && "&quot;" || "&#" + c.charCodeAt() + ";";
}
copy(NodeType, Node$1);
copy(NodeType, Node$1.prototype);
function _visitNode(node, callback) {
if (callback(node)) {
return true;
}
if (node = node.firstChild) {
do {
if (_visitNode(node, callback)) {
return true;
}
} while (node = node.nextSibling);
}
}
function Document() {
this.ownerDocument = this;
}
function _onAddAttribute(doc, el, newAttr) {
doc && doc._inc++;
var ns = newAttr.namespaceURI;
if (ns === NAMESPACE$2.XMLNS) {
el._nsMap[newAttr.prefix ? newAttr.localName : ""] = newAttr.value;
}
}
function _onRemoveAttribute(doc, el, newAttr, remove) {
doc && doc._inc++;
var ns = newAttr.namespaceURI;
if (ns === NAMESPACE$2.XMLNS) {
delete el._nsMap[newAttr.prefix ? newAttr.localName : ""];
}
}
function _onUpdateChild(doc, el, newChild) {
if (doc && doc._inc) {
doc._inc++;
var cs = el.childNodes;
if (newChild) {
cs[cs.length++] = newChild;
} else {
var child = el.firstChild;
var i = 0;
while (child) {
cs[i++] = child;
child = child.nextSibling;
}
cs.length = i;
delete cs[cs.length];
}
}
}
function _removeChild(parentNode, child) {
var previous = child.previousSibling;
var next = child.nextSibling;
if (previous) {
previous.nextSibling = next;
} else {
parentNode.firstChild = next;
}
if (next) {
next.previousSibling = previous;
} else {
parentNode.lastChild = previous;
}
child.parentNode = null;
child.previousSibling = null;
child.nextSibling = null;
_onUpdateChild(parentNode.ownerDocument, parentNode);
return child;
}
function hasValidParentNodeType(node) {
return node && (node.nodeType === Node$1.DOCUMENT_NODE || node.nodeType === Node$1.DOCUMENT_FRAGMENT_NODE || node.nodeType === Node$1.ELEMENT_NODE);
}
function hasInsertableNodeType(node) {
return node && (isElementNode(node) || isTextNode(node) || isDocTypeNode(node) || node.nodeType === Node$1.DOCUMENT_FRAGMENT_NODE || node.nodeType === Node$1.COMMENT_NODE || node.nodeType === Node$1.PROCESSING_INSTRUCTION_NODE);
}
function isDocTypeNode(node) {
return node && node.nodeType === Node$1.DOCUMENT_TYPE_NODE;
}
function isElementNode(node) {
return node && node.nodeType === Node$1.ELEMENT_NODE;
}
function isTextNode(node) {
return node && node.nodeType === Node$1.TEXT_NODE;
}
function isElementInsertionPossible(doc, child) {
var parentChildNodes = doc.childNodes || [];
if (find(parentChildNodes, isElementNode) || isDocTypeNode(child)) {
return false;
}
var docTypeNode = find(parentChildNodes, isDocTypeNode);
return !(child && docTypeNode && parentChildNodes.indexOf(docTypeNode) > parentChildNodes.indexOf(child));
}
function isElementReplacementPossible(doc, child) {
var parentChildNodes = doc.childNodes || [];
function hasElementChildThatIsNotChild(node) {
return isElementNode(node) && node !== child;
}
if (find(parentChildNodes, hasElementChildThatIsNotChild)) {
return false;
}
var docTypeNode = find(parentChildNodes, isDocTypeNode);
return !(child && docTypeNode && parentChildNodes.indexOf(docTypeNode) > parentChildNodes.indexOf(child));
}
function assertPreInsertionValidity1to5(parent2, node, child) {
if (!hasValidParentNodeType(parent2)) {
throw new DOMException(HIERARCHY_REQUEST_ERR, "Unexpected parent node type " + parent2.nodeType);
}
if (child && child.parentNode !== parent2) {
throw new DOMException(NOT_FOUND_ERR, "child not in parent");
}
if (
// 4. If `node` is not a DocumentFragment, DocumentType, Element, or CharacterData node, then throw a "HierarchyRequestError" DOMException.
!hasInsertableNodeType(node) || // 5. If either `node` is a Text node and `parent` is a document,
// the sax parser currently adds top level text nodes, this will be fixed in 0.9.0
// || (node.nodeType === Node.TEXT_NODE && parent.nodeType === Node.DOCUMENT_NODE)
// or `node` is a doctype and `parent` is not a document, then throw a "HierarchyRequestError" DOMException.
isDocTypeNode(node) && parent2.nodeType !== Node$1.DOCUMENT_NODE
) {
throw new DOMException(
HIERARCHY_REQUEST_ERR,
"Unexpected node type " + node.nodeType + " for parent node type " + parent2.nodeType
);
}
}
function assertPreInsertionValidityInDocument(parent2, node, child) {
var parentChildNodes = parent2.childNodes || [];
var nodeChildNodes = node.childNodes || [];
if (node.nodeType === Node$1.DOCUMENT_FRAGMENT_NODE) {
var nodeChildElements = nodeChildNodes.filter(isElementNode);
if (nodeChildElements.length > 1 || find(nodeChildNodes, isTextNode)) {
throw new DOMException(HIERARCHY_REQUEST_ERR, "More than one element or text in fragment");
}
if (nodeChildElements.length === 1 && !isElementInsertionPossible(parent2, child)) {
throw new DOMException(HIERARCHY_REQUEST_ERR, "Element in fragment can not be inserted before doctype");
}
}
if (isElementNode(node)) {
if (!isElementInsertionPossible(parent2, child)) {
throw new DOMException(HIERARCHY_REQUEST_ERR, "Only one element can be added and only after doctype");
}
}
if (isDocTypeNode(node)) {
if (find(parentChildNodes, isDocTypeNode)) {
throw new DOMException(HIERARCHY_REQUEST_ERR, "Only one doctype is allowed");
}
var parentElementChild = find(parentChildNodes, isElementNode);
if (child && parentChildNodes.indexOf(parentElementChild) < parentChildNodes.indexOf(child)) {
throw new DOMException(HIERARCHY_REQUEST_ERR, "Doctype can only be inserted before an element");
}
if (!child && parentElementChild) {
throw new DOMException(HIERARCHY_REQUEST_ERR, "Doctype can not be appended since element is present");
}
}
}
function assertPreReplacementValidityInDocument(parent2, node, child) {
var parentChildNodes = parent2.childNodes || [];
var nodeChildNodes = node.childNodes || [];
if (node.nodeType === Node$1.DOCUMENT_FRAGMENT_NODE) {
var nodeChildElements = nodeChildNodes.filter(isElementNode);
if (nodeChildElements.length > 1 || find(nodeChildNodes, isTextNode)) {
throw new DOMException(HIERARCHY_REQUEST_ERR, "More than one element or text in fragment");
}
if (nodeChildElements.length === 1 && !isElementReplacementPossible(parent2, child)) {
throw new DOMException(HIERARCHY_REQUEST_ERR, "Element in fragment can not be inserted before doctype");
}
}
if (isElementNode(node)) {
if (!isElementReplacementPossible(parent2, child)) {
throw new DOMException(HIERARCHY_REQUEST_ERR, "Only one element can be added and only after doctype");
}
}
if (isDocTypeNode(node)) {
let hasDoctypeChildThatIsNotChild = function(node2) {
return isDocTypeNode(node2) && node2 !== child;
};
if (find(parentChildNodes, hasDoctypeChildThatIsNotChild)) {
throw new DOMException(HIERARCHY_REQUEST_ERR, "Only one doctype is allowed");
}
var parentElementChild = find(parentChildNodes, isElementNode);
if (child && parentChildNodes.indexOf(parentElementChild) < parentChildNodes.indexOf(child)) {
throw new DOMException(HIERARCHY_REQUEST_ERR, "Doctype can only be inserted before an element");
}
}
}
function _insertBefore(parent2, node, child, _inDocumentAssertion) {
assertPreInsertionValidity1to5(parent2, node, child);
if (parent2.nodeType === Node$1.DOCUMENT_NODE) {
(_inDocumentAssertion || assertPreInsertionValidityInDocument)(parent2, node, child);
}
var cp = node.parentNode;
if (cp) {
cp.removeChild(node);
}
if (node.nodeType === DOCUMENT_FRAGMENT_NODE) {
var newFirst = node.firstChild;
if (newFirst == null) {
return node;
}
var newLast = node.lastChild;
} else {
newFirst = newLast = node;
}
var pre = child ? child.previousSibling : parent2.lastChild;
newFirst.previousSibling = pre;
newLast.nextSibling = child;
if (pre) {
pre.nextSibling = newFirst;
} else {
parent2.firstChild = newFirst;
}
if (child == null) {
parent2.lastChild = newLast;
} else {
child.previousSibling = newLast;
}
do {
newFirst.parentNode = parent2;
} while (newFirst !== newLast && (newFirst = newFirst.nextSibling));
_onUpdateChild(parent2.ownerDocument || parent2, parent2);
if (node.nodeType == DOCUMENT_FRAGMENT_NODE) {
node.firstChild = node.lastChild = null;
}
return node;
}
function _appendSingleChild(parentNode, newChild) {
if (newChild.parentNode) {
newChild.parentNode.removeChild(newChild);
}
newChild.parentNode = parentNode;
newChild.previousSibling = parentNode.lastChild;
newChild.nextSibling = null;
if (newChild.previousSibling) {
newChild.previousSibling.nextSibling = newChild;
} else {
parentNode.firstChild = newChild;
}
parentNode.lastChild = newChild;
_onUpdateChild(parentNode.ownerDocument, parentNode, newChild);
return newChild;
}
Document.prototype = {
//implementation : null,
nodeName: "#document",
nodeType: DOCUMENT_NODE$1,
/**
* The DocumentType node of the document.
*
* @readonly
* @type DocumentType
*/
doctype: null,
documentElement: null,
_inc: 1,
insertBefore: function(newChild, refChild) {
if (newChild.nodeType == DOCUMENT_FRAGMENT_NODE) {
var child = newChild.firstChild;
while (child) {
var next = child.nextSibling;
this.insertBefore(child, refChild);
child = next;
}
return newChild;
}
_insertBefore(this, newChild, refChild);
newChild.ownerDocument = this;
if (this.documentElement === null && newChild.nodeType === ELEMENT_NODE$3) {
this.documentElement = newChild;
}
return newChild;
},
removeChild: function(oldChild) {
if (this.documentElement == oldChild) {
this.documentElement = null;
}
return _removeChild(this, oldChild);
},
replaceChild: function(newChild, oldChild) {
_insertBefore(this, newChild, oldChild, assertPreReplacementValidityInDocument);
newChild.ownerDocument = this;
if (oldChild) {
this.removeChild(oldChild);
}
if (isElementNode(newChild)) {
this.documentElement = newChild;
}
},
// Introduced in DOM Level 2:
importNode: function(importedNode, deep) {
return importNode(this, importedNode, deep);
},
// Introduced in DOM Level 2:
getElementById: function(id) {
var rtv = null;
_visitNode(this.documentElement, function(node) {
if (node.nodeType == ELEMENT_NODE$3) {
if (node.getAttribute("id") == id) {
rtv = node;
return true;
}
}
});
return rtv;
},
/**
* The `getElementsByClassName` method of `Document` interface returns an array-like object
* of all child elements which have **all** of the given class name(s).
*
* Returns an empty list if `classeNames` is an empty string or only contains HTML white space characters.
*
*
* Warning: This is a live LiveNodeList.
* Changes in the DOM will reflect in the array as the changes occur.
* If an element selected by this array no longer qualifies for the selector,
* it will automatically be removed. Be aware of this for iteration purposes.
*
* @param {string} classNames is a string representing the class name(s) to match; multiple class names are separated by (ASCII-)whitespace
*
* @see https://developer.mozilla.org/en-US/docs/Web/API/Document/getElementsByClassName
* @see https://dom.spec.whatwg.org/#concept-getelementsbyclassname
*/
getElementsByClassName: function(classNames) {
var classNamesSet = toOrderedSet(classNames);
return new LiveNodeList(this, function(base) {
var ls = [];
if (classNamesSet.length > 0) {
_visitNode(base.documentElement, function(node) {
if (node !== base && node.nodeType === ELEMENT_NODE$3) {
var nodeClassNames = node.getAttribute("class");
if (nodeClassNames) {
var matches = classNames === nodeClassNames;
if (!matches) {
var nodeClassNamesSet = toOrderedSet(nodeClassNames);
matches = classNamesSet.every(arrayIncludes(nodeClassNamesSet));
}
if (matches) {
ls.push(node);
}
}
}
});
}
return ls;
});
},
//document factory method:
createElement: function(tagName) {
var node = new Element$1();
node.ownerDocument = this;
node.nodeName = tagName;
node.tagName = tagName;
node.localName = tagName;
node.childNodes = new NodeList();
var attrs = node.attributes = new NamedNodeMap();
attrs._ownerElement = node;
return node;
},
createDocumentFragment: function() {
var node = new DocumentFragment();
node.ownerDocument = this;
node.childNodes = new NodeList();
return node;
},
createTextNode: function(data) {
var node = new Text();
node.ownerDocument = this;
node.appendData(data);
return node;
},
createComment: function(data) {
var node = new Comment();
node.ownerDocument = this;
node.appendData(data);
return node;
},
createCDATASection: function(data) {
var node = new CDATASection();
node.ownerDocument = this;
node.appendData(data);
return node;
},
createProcessingInstruction: function(target, data) {
var node = new ProcessingInstruction();
node.ownerDocument = this;
node.tagName = node.nodeName = node.target = target;
node.nodeValue = node.data = data;
return node;
},
createAttribute: function(name) {
var node = new Attr();
node.ownerDocument = this;
node.name = name;
node.nodeName = name;
node.localName = name;
node.specified = true;
return node;
},
createEntityReference: function(name) {
var node = new EntityReference();
node.ownerDocument = this;
node.nodeName = name;
return node;
},
// Introduced in DOM Level 2:
createElementNS: function(namespaceURI, qualifiedName) {
var node = new Element$1();
var pl = qualifiedName.split(":");
var attrs = node.attributes = new NamedNodeMap();
node.childNodes = new NodeList();
node.ownerDocument = this;
node.nodeName = qualifiedName;
node.tagName = qualifiedName;
node.namespaceURI = namespaceURI;
if (pl.length == 2) {
node.prefix = pl[0];
node.localName = pl[1];
} else {
node.localName = qualifiedName;
}
attrs._ownerElement = node;
return node;
},
// Introduced in DOM Level 2:
createAttributeNS: function(namespaceURI, qualifiedName) {
var node = new Attr();
var pl = qualifiedName.split(":");
node.ownerDocument = this;
node.nodeName = qualifiedName;
node.name = qualifiedName;
node.namespaceURI = namespaceURI;
node.specified = true;
if (pl.length == 2) {
node.prefix = pl[0];
node.localName = pl[1];
} else {
node.localName = qualifiedName;
}
return node;
}
};
_extends(Document, Node$1);
function Element$1() {
this._nsMap = {};
}
Element$1.prototype = {
nodeType: ELEMENT_NODE$3,
hasAttribute: function(name) {
return this.getAttributeNode(name) != null;
},
getAttribute: function(name) {
var attr = this.getAttributeNode(name);
return attr && attr.value || "";
},
getAttributeNode: function(name) {
return this.attributes.getNamedItem(name);
},
setAttribute: function(name, value) {
var attr = this.ownerDocument.createAttribute(name);
attr.value = attr.nodeValue = "" + value;
this.setAttributeNode(attr);
},
removeAttribute: function(name) {
var attr = this.getAttributeNode(name);
attr && this.removeAttributeNode(attr);
},
//four real opeartion method
appendChild: function(newChild) {
if (newChild.nodeType === DOCUMENT_FRAGMENT_NODE) {
return this.insertBefore(newChild, null);
} else {
return _appendSingleChild(this, newChild);
}
},
setAttributeNode: function(newAttr) {
return this.attributes.setNamedItem(newAttr);
},
setAttributeNodeNS: function(newAttr) {
return this.attributes.setNamedItemNS(newAttr);
},
removeAttributeNode: function(oldAttr) {
return this.attributes.removeNamedItem(oldAttr.nodeName);
},
//get real attribute name,and remove it by removeAttributeNode
removeAttributeNS: function(namespaceURI, localName) {
var old = this.getAttributeNodeNS(namespaceURI, localName);
old && this.removeAttributeNode(old);
},
hasAttributeNS: function(namespaceURI, localName) {
return this.getAttributeNodeNS(namespaceURI, localName) != null;
},
getAttributeNS: function(namespaceURI, localName) {
var attr = this.getAttributeNodeNS(namespaceURI, localName);
return attr && attr.value || "";
},
setAttributeNS: function(namespaceURI, qualifiedName, value) {
var attr = this.ownerDocument.createAttributeNS(namespaceURI, qualifiedName);
attr.value = attr.nodeValue = "" + value;
this.setAttributeNode(attr);
},
getAttributeNodeNS: function(namespaceURI, localName) {
return this.attributes.getNamedItemNS(namespaceURI, localName);
},
getElementsByTagName: function(tagName) {
return new LiveNodeList(this, function(base) {
var ls = [];
_visitNode(base, function(node) {
if (node !== base && node.nodeType == ELEMENT_NODE$3 && (tagName === "*" || node.tagName == tagName)) {
ls.push(node);
}
});
return ls;
});
},
getElementsByTagNameNS: function(namespaceURI, localName) {
return new LiveNodeList(this, function(base) {
var ls = [];
_visitNode(base, function(node) {
if (node !== base && node.nodeType === ELEMENT_NODE$3 && (namespaceURI === "*" || node.namespaceURI === namespaceURI) && (localName === "*" || node.localName == localName)) {
ls.push(node);
}
});
return ls;
});
}
};
Document.prototype.getElementsByTagName = Element$1.prototype.getElementsByTagName;
Document.prototype.getElementsByTagNameNS = Element$1.prototype.getElementsByTagNameNS;
_extends(Element$1, Node$1);
function Attr() {
}
Attr.prototype.nodeType = ATTRIBUTE_NODE;
_extends(Attr, Node$1);
function CharacterData() {
}
CharacterData.prototype = {
data: "",
substringData: function(offset, count) {
return this.data.substring(offset, offset + count);
},
appendData: function(text) {
text = this.data + text;
this.nodeValue = this.data = text;
this.length = text.length;
},
insertData: function(offset, text) {
this.replaceData(offset, 0, text);
},
appendChild: function(newChild) {
throw new Error(ExceptionMessage[HIERARCHY_REQUEST_ERR]);
},
deleteData: function(offset, count) {
this.replaceData(offset, count, "");
},
replaceData: function(offset, count, text) {
var start = this.data.substring(0, offset);
var end = this.data.substring(offset + count);
text = start + text + end;
this.nodeValue = this.data = text;
this.length = text.length;
}
};
_extends(CharacterData, Node$1);
function Text() {
}
Text.prototype = {
nodeName: "#text",
nodeType: TEXT_NODE$2,
splitText: function(offset) {
var text = this.data;
var newText = text.substring(offset);
text = text.substring(0, offset);
this.data = this.nodeValue = text;
this.length = text.length;
var newNode = this.ownerDocument.createTextNode(newText);
if (this.parentNode) {
this.parentNode.insertBefore(newNode, this.nextSibling);
}
return newNode;
}
};
_extends(Text, CharacterData);
function Comment() {
}
Comment.prototype = {
nodeName: "#comment",
nodeType: COMMENT_NODE
};
_extends(Comment, CharacterData);
function CDATASection() {
}
CDATASection.prototype = {
nodeName: "#cdata-section",
nodeType: CDATA_SECTION_NODE
};
_extends(CDATASection, CharacterData);
function DocumentType() {
}
DocumentType.prototype.nodeType = DOCUMENT_TYPE_NODE;
_extends(DocumentType, Node$1);
function Notation() {
}
Notation.prototype.nodeType = NOTATION_NODE;
_extends(Notation, Node$1);
function Entity() {
}
Entity.prototype.nodeType = ENTITY_NODE;
_extends(Entity, Node$1);
function EntityReference() {
}
EntityReference.prototype.nodeType = ENTITY_REFERENCE_NODE;
_extends(EntityReference, Node$1);
function DocumentFragment() {
}
DocumentFragment.prototype.nodeName = "#document-fragment";
DocumentFragment.prototype.nodeType = DOCUMENT_FRAGMENT_NODE;
_extends(DocumentFragment, Node$1);
function ProcessingInstruction() {
}
ProcessingInstruction.prototype.nodeType = PROCESSING_INSTRUCTION_NODE;
_extends(ProcessingInstruction, Node$1);
function XMLSerializer$1() {
}
XMLSerializer$1.prototype.serializeToString = function(node, isHtml, nodeFilter) {
return nodeSerializeToString.call(node, isHtml, nodeFilter);
};
Node$1.prototype.toString = nodeSerializeToString;
function nodeSerializeToString(isHtml, nodeFilter) {
var buf = [];
var refNode = this.nodeType == 9 && this.documentElement || this;
var prefix = refNode.prefix;
var uri = refNode.namespaceURI;
if (uri && prefix == null) {
var prefix = refNode.lookupPrefix(uri);
if (prefix == null) {
var visibleNamespaces = [
{ namespace: uri, prefix: null }
//{namespace:uri,prefix:''}
];
}
}
serializeToString(this, buf, isHtml, nodeFilter, visibleNamespaces);
return buf.join("");
}
function needNamespaceDefine(node, isHTML, visibleNamespaces) {
var prefix = node.prefix || "";
var uri = node.namespaceURI;
if (!uri) {
return false;
}
if (prefix === "xml" && uri === NAMESPACE$2.XML || uri === NAMESPACE$2.XMLNS) {
return false;
}
var i = visibleNamespaces.length;
while (i--) {
var ns = visibleNamespaces[i];
if (ns.prefix === prefix) {
return ns.namespace !== uri;
}
}
return true;
}
function addSerializedAttribute(buf, qualifiedName, value) {
buf.push(" ", qualifiedName, '="', value.replace(/[<&"]/g, _xmlEncoder), '"');
}
function serializeToString(node, buf, isHTML, nodeFilter, visibleNamespaces) {
if (!visibleNamespaces) {
visibleNamespaces = [];
}
if (nodeFilter) {
node = nodeFilter(node);
if (node) {
if (typeof node == "string") {
buf.push(node);
return;
}
} else {
return;
}
}
switch (node.nodeType) {
case ELEMENT_NODE$3:
var attrs = node.attributes;
var len = attrs.length;
var child = node.firstChild;
var nodeName = node.tagName;
isHTML = NAMESPACE$2.isHTML(node.namespaceURI) || isHTML;
var prefixedNodeName = nodeName;
if (!isHTML && !node.prefix && node.namespaceURI) {
var defaultNS;
for (var ai = 0; ai < attrs.length; ai++) {
if (attrs.item(ai).name === "xmlns") {
defaultNS = attrs.item(ai).value;
break;
}
}
if (!defaultNS) {
for (var nsi = visibleNamespaces.length - 1; nsi >= 0; nsi--) {
var namespace = visibleNamespaces[nsi];
if (namespace.prefix === "" && namespace.namespace === node.namespaceURI) {
defaultNS = namespace.namespace;
break;
}
}
}
if (defaultNS !== node.namespaceURI) {
for (var nsi = visibleNamespaces.length - 1; nsi >= 0; nsi--) {
var namespace = visibleNamespaces[nsi];
if (namespace.namespace === node.namespaceURI) {
if (namespace.prefix) {
prefixedNodeName = namespace.prefix + ":" + nodeName;
}
break;
}
}
}
}
buf.push("<", prefixedNodeName);
for (var i = 0; i < len; i++) {
var attr = attrs.item(i);
if (attr.prefix == "xmlns") {
visibleNamespaces.push({ prefix: attr.localName, namespace: attr.value });
} else if (attr.nodeName == "xmlns") {
visibleNamespaces.push({ prefix: "", namespace: attr.value });
}
}
for (var i = 0; i < len; i++) {
var attr = attrs.item(i);
if (needNamespaceDefine(attr, isHTML, visibleNamespaces)) {
var prefix = attr.prefix || "";
var uri = attr.namespaceURI;
addSerializedAttribute(buf, prefix ? "xmlns:" + prefix : "xmlns", uri);
visibleNamespaces.push({ prefix, namespace: uri });
}
serializeToString(attr, buf, isHTML, nodeFilter, visibleNamespaces);
}
if (nodeName === prefixedNodeName && needNamespaceDefine(node, isHTML, visibleNamespaces)) {
var prefix = node.prefix || "";
var uri = node.namespaceURI;
addSerializedAttribute(buf, prefix ? "xmlns:" + prefix : "xmlns", uri);
visibleNamespaces.push({ prefix, namespace: uri });
}
if (child || isHTML && !/^(?:meta|link|img|br|hr|input)$/i.test(nodeName)) {
buf.push(">");
if (isHTML && /^script$/i.test(nodeName)) {
while (child) {
if (child.data) {
buf.push(child.data);
} else {
serializeToString(child, buf, isHTML, nodeFilter, visibleNamespaces.slice());
}
child = child.nextSibling;
}
} else {
while (child) {
serializeToString(child, buf, isHTML, nodeFilter, visibleNamespaces.slice());
child = child.nextSibling;
}
}
buf.push("</", prefixedNodeName, ">");
} else {
buf.push("/>");
}
return;
case DOCUMENT_NODE$1:
case DOCUMENT_FRAGMENT_NODE:
var child = node.firstChild;
while (child) {
serializeToString(child, buf, isHTML, nodeFilter, visibleNamespaces.slice());
child = child.nextSibling;
}
return;
case ATTRIBUTE_NODE:
return addSerializedAttribute(buf, node.name, node.value);
case TEXT_NODE$2:
return buf.push(
node.data.replace(/[<&]/g, _xmlEncoder).replace(/]]>/g, "]]&gt;")
);
case CDATA_SECTION_NODE:
return buf.push("<![CDATA[", node.data, "]]>");
case COMMENT_NODE:
return buf.push("<!--", node.data, "-->");
case DOCUMENT_TYPE_NODE:
var pubid = node.publicId;
var sysid = node.systemId;
buf.push("<!DOCTYPE ", node.name);
if (pubid) {
buf.push(" PUBLIC ", pubid);
if (sysid && sysid != ".") {
buf.push(" ", sysid);
}
buf.push(">");
} else if (sysid && sysid != ".") {
buf.push(" SYSTEM ", sysid, ">");
} else {
var sub = node.internalSubset;
if (sub) {
buf.push(" [", sub, "]");
}
buf.push(">");
}
return;
case PROCESSING_INSTRUCTION_NODE:
return buf.push("<?", node.target, " ", node.data, "?>");
case ENTITY_REFERENCE_NODE:
return buf.push("&", node.nodeName, ";");
default:
buf.push("??", node.nodeName);
}
}
function importNode(doc, node, deep) {
var node2;
switch (node.nodeType) {
case ELEMENT_NODE$3:
node2 = node.cloneNode(false);
node2.ownerDocument = doc;
case DOCUMENT_FRAGMENT_NODE:
break;
case ATTRIBUTE_NODE:
deep = true;
break;
}
if (!node2) {
node2 = node.cloneNode(false);
}
node2.ownerDocument = doc;
node2.parentNode = null;
if (deep) {
var child = node.firstChild;
while (child) {
node2.appendChild(importNode(doc, child, deep));
child = child.nextSibling;
}
}
return node2;
}
function cloneNode(doc, node, deep) {
var node2 = new node.constructor();
for (var n in node) {
if (Object.prototype.hasOwnProperty.call(node, n)) {
var v = node[n];
if (typeof v != "object") {
if (v != node2[n]) {
node2[n] = v;
}
}
}
}
if (node.childNodes) {
node2.childNodes = new NodeList();
}
node2.ownerDocument = doc;
switch (node2.nodeType) {
case ELEMENT_NODE$3:
var attrs = node.attributes;
var attrs2 = node2.attributes = new NamedNodeMap();
var len = attrs.length;
attrs2._ownerElement = node2;
for (var i = 0; i < len; i++) {
node2.setAttributeNode(cloneNode(doc, attrs.item(i), true));
}
break;
case ATTRIBUTE_NODE:
deep = true;
}
if (deep) {
var child = node.firstChild;
while (child) {
node2.appendChild(cloneNode(doc, child, deep));
child = child.nextSibling;
}
}
return node2;
}
function __set__(object, key, value) {
object[key] = value;
}
try {
if (Object.defineProperty) {
let getTextContent = function(node) {
switch (node.nodeType) {
case ELEMENT_NODE$3:
case DOCUMENT_FRAGMENT_NODE:
var buf = [];
node = node.firstChild;
while (node) {
if (node.nodeType !== 7 && node.nodeType !== 8) {
buf.push(getTextContent(node));
}
node = node.nextSibling;
}
return buf.join("");
default:
return node.nodeValue;
}
};
Object.defineProperty(LiveNodeList.prototype, "length", {
get: function() {
_updateLiveList(this);
return this.$$length;
}
});
Object.defineProperty(Node$1.prototype, "textContent", {
get: function() {
return getTextContent(this);
},
set: function(data) {
switch (this.nodeType) {
case ELEMENT_NODE$3:
case DOCUMENT_FRAGMENT_NODE:
while (this.firstChild) {
this.removeChild(this.firstChild);
}
if (data || String(data)) {
this.appendChild(this.ownerDocument.createTextNode(data));
}
break;
default:
this.data = data;
this.value = data;
this.nodeValue = data;
}
}
});
__set__ = function(object, key, value) {
object["$$" + key] = value;
};
}
} catch (e) {
}
dom$1.DocumentType = DocumentType;
dom$1.DOMException = DOMException;
dom$1.DOMImplementation = DOMImplementation$1;
dom$1.Element = Element$1;
dom$1.Node = Node$1;
dom$1.NodeList = NodeList;
dom$1.XMLSerializer = XMLSerializer$1;
var domParser = {};
var entities$1 = {};
(function(exports3) {
var freeze2 = conventions$2.freeze;
exports3.XML_ENTITIES = freeze2({
amp: "&",
apos: "'",
gt: ">",
lt: "<",
quot: '"'
});
exports3.HTML_ENTITIES = freeze2({
Aacute: "Á",
aacute: "á",
Abreve: "Ă",
abreve: "ă",
ac: "∾",
acd: "∿",
acE: "∾̳",
Acirc: "Â",
acirc: "â",
acute: "´",
Acy: "А",
acy: "а",
AElig: "Æ",
aelig: "æ",
af: "⁡",
Afr: "𝔄",
afr: "𝔞",
Agrave: "À",
agrave: "à",
alefsym: "ℵ",
aleph: "ℵ",
Alpha: "Α",
alpha: "α",
Amacr: "Ā",
amacr: "ā",
amalg: "⨿",
AMP: "&",
amp: "&",
And: "⩓",
and: "∧",
andand: "⩕",
andd: "⩜",
andslope: "⩘",
andv: "⩚",
ang: "∠",
ange: "⦤",
angle: "∠",
angmsd: "∡",
angmsdaa: "⦨",
angmsdab: "⦩",
angmsdac: "⦪",
angmsdad: "⦫",
angmsdae: "⦬",
angmsdaf: "⦭",
angmsdag: "⦮",
angmsdah: "⦯",
angrt: "∟",
angrtvb: "⊾",
angrtvbd: "⦝",
angsph: "∢",
angst: "Å",
angzarr: "⍼",
Aogon: "Ą",
aogon: "ą",
Aopf: "𝔸",
aopf: "𝕒",
ap: "≈",
apacir: "⩯",
apE: "⩰",
ape: "≊",
apid: "≋",
apos: "'",
ApplyFunction: "⁡",
approx: "≈",
approxeq: "≊",
Aring: "Å",
aring: "å",
Ascr: "𝒜",
ascr: "𝒶",
Assign: "≔",
ast: "*",
asymp: "≈",
asympeq: "≍",
Atilde: "Ã",
atilde: "ã",
Auml: "Ä",
auml: "ä",
awconint: "∳",
awint: "⨑",
backcong: "≌",
backepsilon: "϶",
backprime: "‵",
backsim: "∽",
backsimeq: "⋍",
Backslash: "∖",
Barv: "⫧",
barvee: "⊽",
Barwed: "⌆",
barwed: "⌅",
barwedge: "⌅",
bbrk: "⎵",
bbrktbrk: "⎶",
bcong: "≌",
Bcy: "Б",
bcy: "б",
bdquo: "„",
becaus: "∵",
Because: "∵",
because: "∵",
bemptyv: "⦰",
bepsi: "϶",
bernou: "ℬ",
Bernoullis: "ℬ",
Beta: "Β",
beta: "β",
beth: "ℶ",
between: "≬",
Bfr: "𝔅",
bfr: "𝔟",
bigcap: "⋂",
bigcirc: "◯",
bigcup: "⋃",
bigodot: "⨀",
bigoplus: "⨁",
bigotimes: "⨂",
bigsqcup: "⨆",
bigstar: "★",
bigtriangledown: "▽",
bigtriangleup: "△",
biguplus: "⨄",
bigvee: "⋁",
bigwedge: "⋀",
bkarow: "⤍",
blacklozenge: "⧫",
blacksquare: "▪",
blacktriangle: "▴",
blacktriangledown: "▾",
blacktriangleleft: "◂",
blacktriangleright: "▸",
blank: "␣",
blk12: "▒",
blk14: "░",
blk34: "▓",
block: "█",
bne: "=⃥",
bnequiv: "≡⃥",
bNot: "⫭",
bnot: "⌐",
Bopf: "𝔹",
bopf: "𝕓",
bot: "⊥",
bottom: "⊥",
bowtie: "⋈",
boxbox: "⧉",
boxDL: "╗",
boxDl: "╖",
boxdL: "╕",
boxdl: "┐",
boxDR: "╔",
boxDr: "╓",
boxdR: "╒",
boxdr: "┌",
boxH: "═",
boxh: "─",
boxHD: "╦",
boxHd: "╤",
boxhD: "╥",
boxhd: "┬",
boxHU: "╩",
boxHu: "╧",
boxhU: "╨",
boxhu: "┴",
boxminus: "⊟",
boxplus: "⊞",
boxtimes: "⊠",
boxUL: "╝",
boxUl: "╜",
boxuL: "╛",
boxul: "┘",
boxUR: "╚",
boxUr: "╙",
boxuR: "╘",
boxur: "└",
boxV: "║",
boxv: "│",
boxVH: "╬",
boxVh: "╫",
boxvH: "╪",
boxvh: "┼",
boxVL: "╣",
boxVl: "╢",
boxvL: "╡",
boxvl: "┤",
boxVR: "╠",
boxVr: "╟",
boxvR: "╞",
boxvr: "├",
bprime: "‵",
Breve: "˘",
breve: "˘",
brvbar: "¦",
Bscr: "ℬ",
bscr: "𝒷",
bsemi: "⁏",
bsim: "∽",
bsime: "⋍",
bsol: "\\",
bsolb: "⧅",
bsolhsub: "⟈",
bull: "•",
bullet: "•",
bump: "≎",
bumpE: "⪮",
bumpe: "≏",
Bumpeq: "≎",
bumpeq: "≏",
Cacute: "Ć",
cacute: "ć",
Cap: "⋒",
cap: "∩",
capand: "⩄",
capbrcup: "⩉",
capcap: "⩋",
capcup: "⩇",
capdot: "⩀",
CapitalDifferentialD: "ⅅ",
caps: "∩︀",
caret: "⁁",
caron: "ˇ",
Cayleys: "ℭ",
ccaps: "⩍",
Ccaron: "Č",
ccaron: "č",
Ccedil: "Ç",
ccedil: "ç",
Ccirc: "Ĉ",
ccirc: "ĉ",
Cconint: "∰",
ccups: "⩌",
ccupssm: "⩐",
Cdot: "Ċ",
cdot: "ċ",
cedil: "¸",
Cedilla: "¸",
cemptyv: "⦲",
cent: "¢",
CenterDot: "·",
centerdot: "·",
Cfr: "ℭ",
cfr: "𝔠",
CHcy: "Ч",
chcy: "ч",
check: "✓",
checkmark: "✓",
Chi: "Χ",
chi: "χ",
cir: "○",
circ: "ˆ",
circeq: "≗",
circlearrowleft: "↺",
circlearrowright: "↻",
circledast: "⊛",
circledcirc: "⊚",
circleddash: "⊝",
CircleDot: "⊙",
circledR: "®",
circledS: "Ⓢ",
CircleMinus: "⊖",
CirclePlus: "⊕",
CircleTimes: "⊗",
cirE: "⧃",
cire: "≗",
cirfnint: "⨐",
cirmid: "⫯",
cirscir: "⧂",
ClockwiseContourIntegral: "∲",
CloseCurlyDoubleQuote: "”",
CloseCurlyQuote: "’",
clubs: "♣",
clubsuit: "♣",
Colon: "∷",
colon: ":",
Colone: "⩴",
colone: "≔",
coloneq: "≔",
comma: ",",
commat: "@",
comp: "∁",
compfn: "∘",
complement: "∁",
complexes: "ℂ",
cong: "≅",
congdot: "⩭",
Congruent: "≡",
Conint: "∯",
conint: "∮",
ContourIntegral: "∮",
Copf: "ℂ",
copf: "𝕔",
coprod: "∐",
Coproduct: "∐",
COPY: "©",
copy: "©",
copysr: "℗",
CounterClockwiseContourIntegral: "∳",
crarr: "↵",
Cross: "⨯",
cross: "✗",
Cscr: "𝒞",
cscr: "𝒸",
csub: "⫏",
csube: "⫑",
csup: "⫐",
csupe: "⫒",
ctdot: "⋯",
cudarrl: "⤸",
cudarrr: "⤵",
cuepr: "⋞",
cuesc: "⋟",
cularr: "↶",
cularrp: "⤽",
Cup: "⋓",
cup: "∪",
cupbrcap: "⩈",
CupCap: "≍",
cupcap: "⩆",
cupcup: "⩊",
cupdot: "⊍",
cupor: "⩅",
cups: "∪︀",
curarr: "↷",
curarrm: "⤼",
curlyeqprec: "⋞",
curlyeqsucc: "⋟",
curlyvee: "⋎",
curlywedge: "⋏",
curren: "¤",
curvearrowleft: "↶",
curvearrowright: "↷",
cuvee: "⋎",
cuwed: "⋏",
cwconint: "∲",
cwint: "∱",
cylcty: "⌭",
Dagger: "‡",
dagger: "†",
daleth: "ℸ",
Darr: "↡",
dArr: "⇓",
darr: "↓",
dash: "‐",
Dashv: "⫤",
dashv: "⊣",
dbkarow: "⤏",
dblac: "˝",
Dcaron: "Ď",
dcaron: "ď",
Dcy: "Д",
dcy: "д",
DD: "ⅅ",
dd: "ⅆ",
ddagger: "‡",
ddarr: "⇊",
DDotrahd: "⤑",
ddotseq: "⩷",
deg: "°",
Del: "∇",
Delta: "Δ",
delta: "δ",
demptyv: "⦱",
dfisht: "⥿",
Dfr: "𝔇",
dfr: "𝔡",
dHar: "⥥",
dharl: "⇃",
dharr: "⇂",
DiacriticalAcute: "´",
DiacriticalDot: "˙",
DiacriticalDoubleAcute: "˝",
DiacriticalGrave: "`",
DiacriticalTilde: "˜",
diam: "⋄",
Diamond: "⋄",
diamond: "⋄",
diamondsuit: "♦",
diams: "♦",
die: "¨",
DifferentialD: "ⅆ",
digamma: "ϝ",
disin: "⋲",
div: "÷",
divide: "÷",
divideontimes: "⋇",
divonx: "⋇",
DJcy: "Ђ",
djcy: "ђ",
dlcorn: "⌞",
dlcrop: "⌍",
dollar: "$",
Dopf: "𝔻",
dopf: "𝕕",
Dot: "¨",
dot: "˙",
DotDot: "⃜",
doteq: "≐",
doteqdot: "≑",
DotEqual: "≐",
dotminus: "∸",
dotplus: "∔",
dotsquare: "⊡",
doublebarwedge: "⌆",
DoubleContourIntegral: "∯",
DoubleDot: "¨",
DoubleDownArrow: "⇓",
DoubleLeftArrow: "⇐",
DoubleLeftRightArrow: "⇔",
DoubleLeftTee: "⫤",
DoubleLongLeftArrow: "⟸",
DoubleLongLeftRightArrow: "⟺",
DoubleLongRightArrow: "⟹",
DoubleRightArrow: "⇒",
DoubleRightTee: "⊨",
DoubleUpArrow: "⇑",
DoubleUpDownArrow: "⇕",
DoubleVerticalBar: "∥",
DownArrow: "↓",
Downarrow: "⇓",
downarrow: "↓",
DownArrowBar: "⤓",
DownArrowUpArrow: "⇵",
DownBreve: "̑",
downdownarrows: "⇊",
downharpoonleft: "⇃",
downharpoonright: "⇂",
DownLeftRightVector: "⥐",
DownLeftTeeVector: "⥞",
DownLeftVector: "↽",
DownLeftVectorBar: "⥖",
DownRightTeeVector: "⥟",
DownRightVector: "⇁",
DownRightVectorBar: "⥗",
DownTee: "⊤",
DownTeeArrow: "↧",
drbkarow: "⤐",
drcorn: "⌟",
drcrop: "⌌",
Dscr: "𝒟",
dscr: "𝒹",
DScy: "Ѕ",
dscy: "ѕ",
dsol: "⧶",
Dstrok: "Đ",
dstrok: "đ",
dtdot: "⋱",
dtri: "▿",
dtrif: "▾",
duarr: "⇵",
duhar: "⥯",
dwangle: "⦦",
DZcy: "Џ",
dzcy: "џ",
dzigrarr: "⟿",
Eacute: "É",
eacute: "é",
easter: "⩮",
Ecaron: "Ě",
ecaron: "ě",
ecir: "≖",
Ecirc: "Ê",
ecirc: "ê",
ecolon: "≕",
Ecy: "Э",
ecy: "э",
eDDot: "⩷",
Edot: "Ė",
eDot: "≑",
edot: "ė",
ee: "ⅇ",
efDot: "≒",
Efr: "𝔈",
efr: "𝔢",
eg: "⪚",
Egrave: "È",
egrave: "è",
egs: "⪖",
egsdot: "⪘",
el: "⪙",
Element: "∈",
elinters: "⏧",
ell: "ℓ",
els: "⪕",
elsdot: "⪗",
Emacr: "Ē",
emacr: "ē",
empty: "∅",
emptyset: "∅",
EmptySmallSquare: "◻",
emptyv: "∅",
EmptyVerySmallSquare: "▫",
emsp: " ",
emsp13: " ",
emsp14: " ",
ENG: "Ŋ",
eng: "ŋ",
ensp: " ",
Eogon: "Ę",
eogon: "ę",
Eopf: "𝔼",
eopf: "𝕖",
epar: "⋕",
eparsl: "⧣",
eplus: "⩱",
epsi: "ε",
Epsilon: "Ε",
epsilon: "ε",
epsiv: "ϵ",
eqcirc: "≖",
eqcolon: "≕",
eqsim: "≂",
eqslantgtr: "⪖",
eqslantless: "⪕",
Equal: "⩵",
equals: "=",
EqualTilde: "≂",
equest: "≟",
Equilibrium: "⇌",
equiv: "≡",
equivDD: "⩸",
eqvparsl: "⧥",
erarr: "⥱",
erDot: "≓",
Escr: "ℰ",
escr: "ℯ",
esdot: "≐",
Esim: "⩳",
esim: "≂",
Eta: "Η",
eta: "η",
ETH: "Ð",
eth: "ð",
Euml: "Ë",
euml: "ë",
euro: "€",
excl: "!",
exist: "∃",
Exists: "∃",
expectation: "ℰ",
ExponentialE: "ⅇ",
exponentiale: "ⅇ",
fallingdotseq: "≒",
Fcy: "Ф",
fcy: "ф",
female: "♀",
ffilig: "ffi",
fflig: "ff",
ffllig: "ffl",
Ffr: "𝔉",
ffr: "𝔣",
filig: "fi",
FilledSmallSquare: "◼",
FilledVerySmallSquare: "▪",
fjlig: "fj",
flat: "♭",
fllig: "fl",
fltns: "▱",
fnof: "ƒ",
Fopf: "𝔽",
fopf: "𝕗",
ForAll: "∀",
forall: "∀",
fork: "⋔",
forkv: "⫙",
Fouriertrf: "ℱ",
fpartint: "⨍",
frac12: "½",
frac13: "⅓",
frac14: "¼",
frac15: "⅕",
frac16: "⅙",
frac18: "⅛",
frac23: "⅔",
frac25: "⅖",
frac34: "¾",
frac35: "⅗",
frac38: "⅜",
frac45: "⅘",
frac56: "⅚",
frac58: "⅝",
frac78: "⅞",
frasl: "⁄",
frown: "⌢",
Fscr: "ℱ",
fscr: "𝒻",
gacute: "ǵ",
Gamma: "Γ",
gamma: "γ",
Gammad: "Ϝ",
gammad: "ϝ",
gap: "⪆",
Gbreve: "Ğ",
gbreve: "ğ",
Gcedil: "Ģ",
Gcirc: "Ĝ",
gcirc: "ĝ",
Gcy: "Г",
gcy: "г",
Gdot: "Ġ",
gdot: "ġ",
gE: "≧",
ge: "≥",
gEl: "⪌",
gel: "⋛",
geq: "≥",
geqq: "≧",
geqslant: "⩾",
ges: "⩾",
gescc: "⪩",
gesdot: "⪀",
gesdoto: "⪂",
gesdotol: "⪄",
gesl: "⋛︀",
gesles: "⪔",
Gfr: "𝔊",
gfr: "𝔤",
Gg: "⋙",
gg: "≫",
ggg: "⋙",
gimel: "ℷ",
GJcy: "Ѓ",
gjcy: "ѓ",
gl: "≷",
gla: "⪥",
glE: "⪒",
glj: "⪤",
gnap: "⪊",
gnapprox: "⪊",
gnE: "≩",
gne: "⪈",
gneq: "⪈",
gneqq: "≩",
gnsim: "⋧",
Gopf: "𝔾",
gopf: "𝕘",
grave: "`",
GreaterEqual: "≥",
GreaterEqualLess: "⋛",
GreaterFullEqual: "≧",
GreaterGreater: "⪢",
GreaterLess: "≷",
GreaterSlantEqual: "⩾",
GreaterTilde: "≳",
Gscr: "𝒢",
gscr: "ℊ",
gsim: "≳",
gsime: "⪎",
gsiml: "⪐",
Gt: "≫",
GT: ">",
gt: ">",
gtcc: "⪧",
gtcir: "⩺",
gtdot: "⋗",
gtlPar: "⦕",
gtquest: "⩼",
gtrapprox: "⪆",
gtrarr: "⥸",
gtrdot: "⋗",
gtreqless: "⋛",
gtreqqless: "⪌",
gtrless: "≷",
gtrsim: "≳",
gvertneqq: "≩︀",
gvnE: "≩︀",
Hacek: "ˇ",
hairsp: " ",
half: "½",
hamilt: "ℋ",
HARDcy: "Ъ",
hardcy: "ъ",
hArr: "⇔",
harr: "↔",
harrcir: "⥈",
harrw: "↭",
Hat: "^",
hbar: "ℏ",
Hcirc: "Ĥ",
hcirc: "ĥ",
hearts: "♥",
heartsuit: "♥",
hellip: "…",
hercon: "⊹",
Hfr: "ℌ",
hfr: "𝔥",
HilbertSpace: "ℋ",
hksearow: "⤥",
hkswarow: "⤦",
hoarr: "⇿",
homtht: "∻",
hookleftarrow: "↩",
hookrightarrow: "↪",
Hopf: "ℍ",
hopf: "𝕙",
horbar: "―",
HorizontalLine: "─",
Hscr: "ℋ",
hscr: "𝒽",
hslash: "ℏ",
Hstrok: "Ħ",
hstrok: "ħ",
HumpDownHump: "≎",
HumpEqual: "≏",
hybull: "⁃",
hyphen: "‐",
Iacute: "Í",
iacute: "í",
ic: "⁣",
Icirc: "Î",
icirc: "î",
Icy: "И",
icy: "и",
Idot: "İ",
IEcy: "Е",
iecy: "е",
iexcl: "¡",
iff: "⇔",
Ifr: "ℑ",
ifr: "𝔦",
Igrave: "Ì",
igrave: "ì",
ii: "ⅈ",
iiiint: "⨌",
iiint: "∭",
iinfin: "⧜",
iiota: "℩",
IJlig: "IJ",
ijlig: "ij",
Im: "ℑ",
Imacr: "Ī",
imacr: "ī",
image: "ℑ",
ImaginaryI: "ⅈ",
imagline: "ℐ",
imagpart: "ℑ",
imath: "ı",
imof: "⊷",
imped: "Ƶ",
Implies: "⇒",
in: "∈",
incare: "℅",
infin: "∞",
infintie: "⧝",
inodot: "ı",
Int: "∬",
int: "∫",
intcal: "⊺",
integers: "ℤ",
Integral: "∫",
intercal: "⊺",
Intersection: "⋂",
intlarhk: "⨗",
intprod: "⨼",
InvisibleComma: "⁣",
InvisibleTimes: "⁢",
IOcy: "Ё",
iocy: "ё",
Iogon: "Į",
iogon: "į",
Iopf: "𝕀",
iopf: "𝕚",
Iota: "Ι",
iota: "ι",
iprod: "⨼",
iquest: "¿",
Iscr: "ℐ",
iscr: "𝒾",
isin: "∈",
isindot: "⋵",
isinE: "⋹",
isins: "⋴",
isinsv: "⋳",
isinv: "∈",
it: "⁢",
Itilde: "Ĩ",
itilde: "ĩ",
Iukcy: "І",
iukcy: "і",
Iuml: "Ï",
iuml: "ï",
Jcirc: "Ĵ",
jcirc: "ĵ",
Jcy: "Й",
jcy: "й",
Jfr: "𝔍",
jfr: "𝔧",
jmath: "ȷ",
Jopf: "𝕁",
jopf: "𝕛",
Jscr: "𝒥",
jscr: "𝒿",
Jsercy: "Ј",
jsercy: "ј",
Jukcy: "Є",
jukcy: "є",
Kappa: "Κ",
kappa: "κ",
kappav: "ϰ",
Kcedil: "Ķ",
kcedil: "ķ",
Kcy: "К",
kcy: "к",
Kfr: "𝔎",
kfr: "𝔨",
kgreen: "ĸ",
KHcy: "Х",
khcy: "х",
KJcy: "Ќ",
kjcy: "ќ",
Kopf: "𝕂",
kopf: "𝕜",
Kscr: "𝒦",
kscr: "𝓀",
lAarr: "⇚",
Lacute: "Ĺ",
lacute: "ĺ",
laemptyv: "⦴",
lagran: "ℒ",
Lambda: "Λ",
lambda: "λ",
Lang: "⟪",
lang: "⟨",
langd: "⦑",
langle: "⟨",
lap: "⪅",
Laplacetrf: "ℒ",
laquo: "«",
Larr: "↞",
lArr: "⇐",
larr: "←",
larrb: "⇤",
larrbfs: "⤟",
larrfs: "⤝",
larrhk: "↩",
larrlp: "↫",
larrpl: "⤹",
larrsim: "⥳",
larrtl: "↢",
lat: "⪫",
lAtail: "⤛",
latail: "⤙",
late: "⪭",
lates: "⪭︀",
lBarr: "⤎",
lbarr: "⤌",
lbbrk: "❲",
lbrace: "{",
lbrack: "[",
lbrke: "⦋",
lbrksld: "⦏",
lbrkslu: "⦍",
Lcaron: "Ľ",
lcaron: "ľ",
Lcedil: "Ļ",
lcedil: "ļ",
lceil: "⌈",
lcub: "{",
Lcy: "Л",
lcy: "л",
ldca: "⤶",
ldquo: "“",
ldquor: "„",
ldrdhar: "⥧",
ldrushar: "⥋",
ldsh: "↲",
lE: "≦",
le: "≤",
LeftAngleBracket: "⟨",
LeftArrow: "←",
Leftarrow: "⇐",
leftarrow: "←",
LeftArrowBar: "⇤",
LeftArrowRightArrow: "⇆",
leftarrowtail: "↢",
LeftCeiling: "⌈",
LeftDoubleBracket: "⟦",
LeftDownTeeVector: "⥡",
LeftDownVector: "⇃",
LeftDownVectorBar: "⥙",
LeftFloor: "⌊",
leftharpoondown: "↽",
leftharpoonup: "↼",
leftleftarrows: "⇇",
LeftRightArrow: "↔",
Leftrightarrow: "⇔",
leftrightarrow: "↔",
leftrightarrows: "⇆",
leftrightharpoons: "⇋",
leftrightsquigarrow: "↭",
LeftRightVector: "⥎",
LeftTee: "⊣",
LeftTeeArrow: "↤",
LeftTeeVector: "⥚",
leftthreetimes: "⋋",
LeftTriangle: "⊲",
LeftTriangleBar: "⧏",
LeftTriangleEqual: "⊴",
LeftUpDownVector: "⥑",
LeftUpTeeVector: "⥠",
LeftUpVector: "↿",
LeftUpVectorBar: "⥘",
LeftVector: "↼",
LeftVectorBar: "⥒",
lEg: "⪋",
leg: "⋚",
leq: "≤",
leqq: "≦",
leqslant: "⩽",
les: "⩽",
lescc: "⪨",
lesdot: "⩿",
lesdoto: "⪁",
lesdotor: "⪃",
lesg: "⋚︀",
lesges: "⪓",
lessapprox: "⪅",
lessdot: "⋖",
lesseqgtr: "⋚",
lesseqqgtr: "⪋",
LessEqualGreater: "⋚",
LessFullEqual: "≦",
LessGreater: "≶",
lessgtr: "≶",
LessLess: "⪡",
lesssim: "≲",
LessSlantEqual: "⩽",
LessTilde: "≲",
lfisht: "⥼",
lfloor: "⌊",
Lfr: "𝔏",
lfr: "𝔩",
lg: "≶",
lgE: "⪑",
lHar: "⥢",
lhard: "↽",
lharu: "↼",
lharul: "⥪",
lhblk: "▄",
LJcy: "Љ",
ljcy: "љ",
Ll: "⋘",
ll: "≪",
llarr: "⇇",
llcorner: "⌞",
Lleftarrow: "⇚",
llhard: "⥫",
lltri: "◺",
Lmidot: "Ŀ",
lmidot: "ŀ",
lmoust: "⎰",
lmoustache: "⎰",
lnap: "⪉",
lnapprox: "⪉",
lnE: "≨",
lne: "⪇",
lneq: "⪇",
lneqq: "≨",
lnsim: "⋦",
loang: "⟬",
loarr: "⇽",
lobrk: "⟦",
LongLeftArrow: "⟵",
Longleftarrow: "⟸",
longleftarrow: "⟵",
LongLeftRightArrow: "⟷",
Longleftrightarrow: "⟺",
longleftrightarrow: "⟷",
longmapsto: "⟼",
LongRightArrow: "⟶",
Longrightarrow: "⟹",
longrightarrow: "⟶",
looparrowleft: "↫",
looparrowright: "↬",
lopar: "⦅",
Lopf: "𝕃",
lopf: "𝕝",
loplus: "⨭",
lotimes: "⨴",
lowast: "∗",
lowbar: "_",
LowerLeftArrow: "↙",
LowerRightArrow: "↘",
loz: "◊",
lozenge: "◊",
lozf: "⧫",
lpar: "(",
lparlt: "⦓",
lrarr: "⇆",
lrcorner: "⌟",
lrhar: "⇋",
lrhard: "⥭",
lrm: "‎",
lrtri: "⊿",
lsaquo: "‹",
Lscr: "ℒ",
lscr: "𝓁",
Lsh: "↰",
lsh: "↰",
lsim: "≲",
lsime: "⪍",
lsimg: "⪏",
lsqb: "[",
lsquo: "‘",
lsquor: "‚",
Lstrok: "Ł",
lstrok: "ł",
Lt: "≪",
LT: "<",
lt: "<",
ltcc: "⪦",
ltcir: "⩹",
ltdot: "⋖",
lthree: "⋋",
ltimes: "⋉",
ltlarr: "⥶",
ltquest: "⩻",
ltri: "◃",
ltrie: "⊴",
ltrif: "◂",
ltrPar: "⦖",
lurdshar: "⥊",
luruhar: "⥦",
lvertneqq: "≨︀",
lvnE: "≨︀",
macr: "¯",
male: "♂",
malt: "✠",
maltese: "✠",
Map: "⤅",
map: "↦",
mapsto: "↦",
mapstodown: "↧",
mapstoleft: "↤",
mapstoup: "↥",
marker: "▮",
mcomma: "⨩",
Mcy: "М",
mcy: "м",
mdash: "—",
mDDot: "∺",
measuredangle: "∡",
MediumSpace: " ",
Mellintrf: "ℳ",
Mfr: "𝔐",
mfr: "𝔪",
mho: "℧",
micro: "µ",
mid: "∣",
midast: "*",
midcir: "⫰",
middot: "·",
minus: "−",
minusb: "⊟",
minusd: "∸",
minusdu: "⨪",
MinusPlus: "∓",
mlcp: "⫛",
mldr: "…",
mnplus: "∓",
models: "⊧",
Mopf: "𝕄",
mopf: "𝕞",
mp: "∓",
Mscr: "ℳ",
mscr: "𝓂",
mstpos: "∾",
Mu: "Μ",
mu: "μ",
multimap: "⊸",
mumap: "⊸",
nabla: "∇",
Nacute: "Ń",
nacute: "ń",
nang: "∠⃒",
nap: "≉",
napE: "⩰̸",
napid: "≋̸",
napos: "ʼn",
napprox: "≉",
natur: "♮",
natural: "♮",
naturals: "ℕ",
nbsp: " ",
nbump: "≎̸",
nbumpe: "≏̸",
ncap: "⩃",
Ncaron: "Ň",
ncaron: "ň",
Ncedil: "Ņ",
ncedil: "ņ",
ncong: "≇",
ncongdot: "⩭̸",
ncup: "⩂",
Ncy: "Н",
ncy: "н",
ndash: "–",
ne: "≠",
nearhk: "⤤",
neArr: "⇗",
nearr: "↗",
nearrow: "↗",
nedot: "≐̸",
NegativeMediumSpace: "​",
NegativeThickSpace: "​",
NegativeThinSpace: "​",
NegativeVeryThinSpace: "​",
nequiv: "≢",
nesear: "⤨",
nesim: "≂̸",
NestedGreaterGreater: "≫",
NestedLessLess: "≪",
NewLine: "\n",
nexist: "∄",
nexists: "∄",
Nfr: "𝔑",
nfr: "𝔫",
ngE: "≧̸",
nge: "≱",
ngeq: "≱",
ngeqq: "≧̸",
ngeqslant: "⩾̸",
nges: "⩾̸",
nGg: "⋙̸",
ngsim: "≵",
nGt: "≫⃒",
ngt: "≯",
ngtr: "≯",
nGtv: "≫̸",
nhArr: "⇎",
nharr: "↮",
nhpar: "⫲",
ni: "∋",
nis: "⋼",
nisd: "⋺",
niv: "∋",
NJcy: "Њ",
njcy: "њ",
nlArr: "⇍",
nlarr: "↚",
nldr: "‥",
nlE: "≦̸",
nle: "≰",
nLeftarrow: "⇍",
nleftarrow: "↚",
nLeftrightarrow: "⇎",
nleftrightarrow: "↮",
nleq: "≰",
nleqq: "≦̸",
nleqslant: "⩽̸",
nles: "⩽̸",
nless: "≮",
nLl: "⋘̸",
nlsim: "≴",
nLt: "≪⃒",
nlt: "≮",
nltri: "⋪",
nltrie: "⋬",
nLtv: "≪̸",
nmid: "∤",
NoBreak: "⁠",
NonBreakingSpace: " ",
Nopf: "ℕ",
nopf: "𝕟",
Not: "⫬",
not: "¬",
NotCongruent: "≢",
NotCupCap: "≭",
NotDoubleVerticalBar: "∦",
NotElement: "∉",
NotEqual: "≠",
NotEqualTilde: "≂̸",
NotExists: "∄",
NotGreater: "≯",
NotGreaterEqual: "≱",
NotGreaterFullEqual: "≧̸",
NotGreaterGreater: "≫̸",
NotGreaterLess: "≹",
NotGreaterSlantEqual: "⩾̸",
NotGreaterTilde: "≵",
NotHumpDownHump: "≎̸",
NotHumpEqual: "≏̸",
notin: "∉",
notindot: "⋵̸",
notinE: "⋹̸",
notinva: "∉",
notinvb: "⋷",
notinvc: "⋶",
NotLeftTriangle: "⋪",
NotLeftTriangleBar: "⧏̸",
NotLeftTriangleEqual: "⋬",
NotLess: "≮",
NotLessEqual: "≰",
NotLessGreater: "≸",
NotLessLess: "≪̸",
NotLessSlantEqual: "⩽̸",
NotLessTilde: "≴",
NotNestedGreaterGreater: "⪢̸",
NotNestedLessLess: "⪡̸",
notni: "∌",
notniva: "∌",
notnivb: "⋾",
notnivc: "⋽",
NotPrecedes: "⊀",
NotPrecedesEqual: "⪯̸",
NotPrecedesSlantEqual: "⋠",
NotReverseElement: "∌",
NotRightTriangle: "⋫",
NotRightTriangleBar: "⧐̸",
NotRightTriangleEqual: "⋭",
NotSquareSubset: "⊏̸",
NotSquareSubsetEqual: "⋢",
NotSquareSuperset: "⊐̸",
NotSquareSupersetEqual: "⋣",
NotSubset: "⊂⃒",
NotSubsetEqual: "⊈",
NotSucceeds: "⊁",
NotSucceedsEqual: "⪰̸",
NotSucceedsSlantEqual: "⋡",
NotSucceedsTilde: "≿̸",
NotSuperset: "⊃⃒",
NotSupersetEqual: "⊉",
NotTilde: "≁",
NotTildeEqual: "≄",
NotTildeFullEqual: "≇",
NotTildeTilde: "≉",
NotVerticalBar: "∤",
npar: "∦",
nparallel: "∦",
nparsl: "⫽⃥",
npart: "∂̸",
npolint: "⨔",
npr: "⊀",
nprcue: "⋠",
npre: "⪯̸",
nprec: "⊀",
npreceq: "⪯̸",
nrArr: "⇏",
nrarr: "↛",
nrarrc: "⤳̸",
nrarrw: "↝̸",
nRightarrow: "⇏",
nrightarrow: "↛",
nrtri: "⋫",
nrtrie: "⋭",
nsc: "⊁",
nsccue: "⋡",
nsce: "⪰̸",
Nscr: "𝒩",
nscr: "𝓃",
nshortmid: "∤",
nshortparallel: "∦",
nsim: "≁",
nsime: "≄",
nsimeq: "≄",
nsmid: "∤",
nspar: "∦",
nsqsube: "⋢",
nsqsupe: "⋣",
nsub: "⊄",
nsubE: "⫅̸",
nsube: "⊈",
nsubset: "⊂⃒",
nsubseteq: "⊈",
nsubseteqq: "⫅̸",
nsucc: "⊁",
nsucceq: "⪰̸",
nsup: "⊅",
nsupE: "⫆̸",
nsupe: "⊉",
nsupset: "⊃⃒",
nsupseteq: "⊉",
nsupseteqq: "⫆̸",
ntgl: "≹",
Ntilde: "Ñ",
ntilde: "ñ",
ntlg: "≸",
ntriangleleft: "⋪",
ntrianglelefteq: "⋬",
ntriangleright: "⋫",
ntrianglerighteq: "⋭",
Nu: "Ν",
nu: "ν",
num: "#",
numero: "№",
numsp: " ",
nvap: "≍⃒",
nVDash: "⊯",
nVdash: "⊮",
nvDash: "⊭",
nvdash: "⊬",
nvge: "≥⃒",
nvgt: ">⃒",
nvHarr: "⤄",
nvinfin: "⧞",
nvlArr: "⤂",
nvle: "≤⃒",
nvlt: "<⃒",
nvltrie: "⊴⃒",
nvrArr: "⤃",
nvrtrie: "⊵⃒",
nvsim: "∼⃒",
nwarhk: "⤣",
nwArr: "⇖",
nwarr: "↖",
nwarrow: "↖",
nwnear: "⤧",
Oacute: "Ó",
oacute: "ó",
oast: "⊛",
ocir: "⊚",
Ocirc: "Ô",
ocirc: "ô",
Ocy: "О",
ocy: "о",
odash: "⊝",
Odblac: "Ő",
odblac: "ő",
odiv: "⨸",
odot: "⊙",
odsold: "⦼",
OElig: "Œ",
oelig: "œ",
ofcir: "⦿",
Ofr: "𝔒",
ofr: "𝔬",
ogon: "˛",
Ograve: "Ò",
ograve: "ò",
ogt: "⧁",
ohbar: "⦵",
ohm: "Ω",
oint: "∮",
olarr: "↺",
olcir: "⦾",
olcross: "⦻",
oline: "‾",
olt: "⧀",
Omacr: "Ō",
omacr: "ō",
Omega: "Ω",
omega: "ω",
Omicron: "Ο",
omicron: "ο",
omid: "⦶",
ominus: "⊖",
Oopf: "𝕆",
oopf: "𝕠",
opar: "⦷",
OpenCurlyDoubleQuote: "“",
OpenCurlyQuote: "‘",
operp: "⦹",
oplus: "⊕",
Or: "⩔",
or: "∨",
orarr: "↻",
ord: "⩝",
order: "ℴ",
orderof: "ℴ",
ordf: "ª",
ordm: "º",
origof: "⊶",
oror: "⩖",
orslope: "⩗",
orv: "⩛",
oS: "Ⓢ",
Oscr: "𝒪",
oscr: "ℴ",
Oslash: "Ø",
oslash: "ø",
osol: "⊘",
Otilde: "Õ",
otilde: "õ",
Otimes: "⨷",
otimes: "⊗",
otimesas: "⨶",
Ouml: "Ö",
ouml: "ö",
ovbar: "⌽",
OverBar: "‾",
OverBrace: "⏞",
OverBracket: "⎴",
OverParenthesis: "⏜",
par: "∥",
para: "¶",
parallel: "∥",
parsim: "⫳",
parsl: "⫽",
part: "∂",
PartialD: "∂",
Pcy: "П",
pcy: "п",
percnt: "%",
period: ".",
permil: "‰",
perp: "⊥",
pertenk: "‱",
Pfr: "𝔓",
pfr: "𝔭",
Phi: "Φ",
phi: "φ",
phiv: "ϕ",
phmmat: "ℳ",
phone: "☎",
Pi: "Π",
pi: "π",
pitchfork: "⋔",
piv: "ϖ",
planck: "ℏ",
planckh: "ℎ",
plankv: "ℏ",
plus: "+",
plusacir: "⨣",
plusb: "⊞",
pluscir: "⨢",
plusdo: "∔",
plusdu: "⨥",
pluse: "⩲",
PlusMinus: "±",
plusmn: "±",
plussim: "⨦",
plustwo: "⨧",
pm: "±",
Poincareplane: "ℌ",
pointint: "⨕",
Popf: "ℙ",
popf: "𝕡",
pound: "£",
Pr: "⪻",
pr: "≺",
prap: "⪷",
prcue: "≼",
prE: "⪳",
pre: "⪯",
prec: "≺",
precapprox: "⪷",
preccurlyeq: "≼",
Precedes: "≺",
PrecedesEqual: "⪯",
PrecedesSlantEqual: "≼",
PrecedesTilde: "≾",
preceq: "⪯",
precnapprox: "⪹",
precneqq: "⪵",
precnsim: "⋨",
precsim: "≾",
Prime: "″",
prime: "′",
primes: "ℙ",
prnap: "⪹",
prnE: "⪵",
prnsim: "⋨",
prod: "∏",
Product: "∏",
profalar: "⌮",
profline: "⌒",
profsurf: "⌓",
prop: "∝",
Proportion: "∷",
Proportional: "∝",
propto: "∝",
prsim: "≾",
prurel: "⊰",
Pscr: "𝒫",
pscr: "𝓅",
Psi: "Ψ",
psi: "ψ",
puncsp: " ",
Qfr: "𝔔",
qfr: "𝔮",
qint: "⨌",
Qopf: "ℚ",
qopf: "𝕢",
qprime: "⁗",
Qscr: "𝒬",
qscr: "𝓆",
quaternions: "ℍ",
quatint: "⨖",
quest: "?",
questeq: "≟",
QUOT: '"',
quot: '"',
rAarr: "⇛",
race: "∽̱",
Racute: "Ŕ",
racute: "ŕ",
radic: "√",
raemptyv: "⦳",
Rang: "⟫",
rang: "⟩",
rangd: "⦒",
range: "⦥",
rangle: "⟩",
raquo: "»",
Rarr: "↠",
rArr: "⇒",
rarr: "→",
rarrap: "⥵",
rarrb: "⇥",
rarrbfs: "⤠",
rarrc: "⤳",
rarrfs: "⤞",
rarrhk: "↪",
rarrlp: "↬",
rarrpl: "⥅",
rarrsim: "⥴",
Rarrtl: "⤖",
rarrtl: "↣",
rarrw: "↝",
rAtail: "⤜",
ratail: "⤚",
ratio: "∶",
rationals: "ℚ",
RBarr: "⤐",
rBarr: "⤏",
rbarr: "⤍",
rbbrk: "❳",
rbrace: "}",
rbrack: "]",
rbrke: "⦌",
rbrksld: "⦎",
rbrkslu: "⦐",
Rcaron: "Ř",
rcaron: "ř",
Rcedil: "Ŗ",
rcedil: "ŗ",
rceil: "⌉",
rcub: "}",
Rcy: "Р",
rcy: "р",
rdca: "⤷",
rdldhar: "⥩",
rdquo: "”",
rdquor: "”",
rdsh: "↳",
Re: "ℜ",
real: "ℜ",
realine: "ℛ",
realpart: "ℜ",
reals: "ℝ",
rect: "▭",
REG: "®",
reg: "®",
ReverseElement: "∋",
ReverseEquilibrium: "⇋",
ReverseUpEquilibrium: "⥯",
rfisht: "⥽",
rfloor: "⌋",
Rfr: "ℜ",
rfr: "𝔯",
rHar: "⥤",
rhard: "⇁",
rharu: "⇀",
rharul: "⥬",
Rho: "Ρ",
rho: "ρ",
rhov: "ϱ",
RightAngleBracket: "⟩",
RightArrow: "→",
Rightarrow: "⇒",
rightarrow: "→",
RightArrowBar: "⇥",
RightArrowLeftArrow: "⇄",
rightarrowtail: "↣",
RightCeiling: "⌉",
RightDoubleBracket: "⟧",
RightDownTeeVector: "⥝",
RightDownVector: "⇂",
RightDownVectorBar: "⥕",
RightFloor: "⌋",
rightharpoondown: "⇁",
rightharpoonup: "⇀",
rightleftarrows: "⇄",
rightleftharpoons: "⇌",
rightrightarrows: "⇉",
rightsquigarrow: "↝",
RightTee: "⊢",
RightTeeArrow: "↦",
RightTeeVector: "⥛",
rightthreetimes: "⋌",
RightTriangle: "⊳",
RightTriangleBar: "⧐",
RightTriangleEqual: "⊵",
RightUpDownVector: "⥏",
RightUpTeeVector: "⥜",
RightUpVector: "↾",
RightUpVectorBar: "⥔",
RightVector: "⇀",
RightVectorBar: "⥓",
ring: "˚",
risingdotseq: "≓",
rlarr: "⇄",
rlhar: "⇌",
rlm: "‏",
rmoust: "⎱",
rmoustache: "⎱",
rnmid: "⫮",
roang: "⟭",
roarr: "⇾",
robrk: "⟧",
ropar: "⦆",
Ropf: "ℝ",
ropf: "𝕣",
roplus: "⨮",
rotimes: "⨵",
RoundImplies: "⥰",
rpar: ")",
rpargt: "⦔",
rppolint: "⨒",
rrarr: "⇉",
Rrightarrow: "⇛",
rsaquo: "›",
Rscr: "ℛ",
rscr: "𝓇",
Rsh: "↱",
rsh: "↱",
rsqb: "]",
rsquo: "’",
rsquor: "’",
rthree: "⋌",
rtimes: "⋊",
rtri: "▹",
rtrie: "⊵",
rtrif: "▸",
rtriltri: "⧎",
RuleDelayed: "⧴",
ruluhar: "⥨",
rx: "℞",
Sacute: "Ś",
sacute: "ś",
sbquo: "‚",
Sc: "⪼",
sc: "≻",
scap: "⪸",
Scaron: "Š",
scaron: "š",
sccue: "≽",
scE: "⪴",
sce: "⪰",
Scedil: "Ş",
scedil: "ş",
Scirc: "Ŝ",
scirc: "ŝ",
scnap: "⪺",
scnE: "⪶",
scnsim: "⋩",
scpolint: "⨓",
scsim: "≿",
Scy: "С",
scy: "с",
sdot: "⋅",
sdotb: "⊡",
sdote: "⩦",
searhk: "⤥",
seArr: "⇘",
searr: "↘",
searrow: "↘",
sect: "§",
semi: ";",
seswar: "⤩",
setminus: "∖",
setmn: "∖",
sext: "✶",
Sfr: "𝔖",
sfr: "𝔰",
sfrown: "⌢",
sharp: "♯",
SHCHcy: "Щ",
shchcy: "щ",
SHcy: "Ш",
shcy: "ш",
ShortDownArrow: "↓",
ShortLeftArrow: "←",
shortmid: "∣",
shortparallel: "∥",
ShortRightArrow: "→",
ShortUpArrow: "↑",
shy: "­",
Sigma: "Σ",
sigma: "σ",
sigmaf: "ς",
sigmav: "ς",
sim: "∼",
simdot: "⩪",
sime: "≃",
simeq: "≃",
simg: "⪞",
simgE: "⪠",
siml: "⪝",
simlE: "⪟",
simne: "≆",
simplus: "⨤",
simrarr: "⥲",
slarr: "←",
SmallCircle: "∘",
smallsetminus: "∖",
smashp: "⨳",
smeparsl: "⧤",
smid: "∣",
smile: "⌣",
smt: "⪪",
smte: "⪬",
smtes: "⪬︀",
SOFTcy: "Ь",
softcy: "ь",
sol: "/",
solb: "⧄",
solbar: "⌿",
Sopf: "𝕊",
sopf: "𝕤",
spades: "♠",
spadesuit: "♠",
spar: "∥",
sqcap: "⊓",
sqcaps: "⊓︀",
sqcup: "⊔",
sqcups: "⊔︀",
Sqrt: "√",
sqsub: "⊏",
sqsube: "⊑",
sqsubset: "⊏",
sqsubseteq: "⊑",
sqsup: "⊐",
sqsupe: "⊒",
sqsupset: "⊐",
sqsupseteq: "⊒",
squ: "□",
Square: "□",
square: "□",
SquareIntersection: "⊓",
SquareSubset: "⊏",
SquareSubsetEqual: "⊑",
SquareSuperset: "⊐",
SquareSupersetEqual: "⊒",
SquareUnion: "⊔",
squarf: "▪",
squf: "▪",
srarr: "→",
Sscr: "𝒮",
sscr: "𝓈",
ssetmn: "∖",
ssmile: "⌣",
sstarf: "⋆",
Star: "⋆",
star: "☆",
starf: "★",
straightepsilon: "ϵ",
straightphi: "ϕ",
strns: "¯",
Sub: "⋐",
sub: "⊂",
subdot: "⪽",
subE: "⫅",
sube: "⊆",
subedot: "⫃",
submult: "⫁",
subnE: "⫋",
subne: "⊊",
subplus: "⪿",
subrarr: "⥹",
Subset: "⋐",
subset: "⊂",
subseteq: "⊆",
subseteqq: "⫅",
SubsetEqual: "⊆",
subsetneq: "⊊",
subsetneqq: "⫋",
subsim: "⫇",
subsub: "⫕",
subsup: "⫓",
succ: "≻",
succapprox: "⪸",
succcurlyeq: "≽",
Succeeds: "≻",
SucceedsEqual: "⪰",
SucceedsSlantEqual: "≽",
SucceedsTilde: "≿",
succeq: "⪰",
succnapprox: "⪺",
succneqq: "⪶",
succnsim: "⋩",
succsim: "≿",
SuchThat: "∋",
Sum: "∑",
sum: "∑",
sung: "♪",
Sup: "⋑",
sup: "⊃",
sup1: "¹",
sup2: "²",
sup3: "³",
supdot: "⪾",
supdsub: "⫘",
supE: "⫆",
supe: "⊇",
supedot: "⫄",
Superset: "⊃",
SupersetEqual: "⊇",
suphsol: "⟉",
suphsub: "⫗",
suplarr: "⥻",
supmult: "⫂",
supnE: "⫌",
supne: "⊋",
supplus: "⫀",
Supset: "⋑",
supset: "⊃",
supseteq: "⊇",
supseteqq: "⫆",
supsetneq: "⊋",
supsetneqq: "⫌",
supsim: "⫈",
supsub: "⫔",
supsup: "⫖",
swarhk: "⤦",
swArr: "⇙",
swarr: "↙",
swarrow: "↙",
swnwar: "⤪",
szlig: "ß",
Tab: " ",
target: "⌖",
Tau: "Τ",
tau: "τ",
tbrk: "⎴",
Tcaron: "Ť",
tcaron: "ť",
Tcedil: "Ţ",
tcedil: "ţ",
Tcy: "Т",
tcy: "т",
tdot: "⃛",
telrec: "⌕",
Tfr: "𝔗",
tfr: "𝔱",
there4: "∴",
Therefore: "∴",
therefore: "∴",
Theta: "Θ",
theta: "θ",
thetasym: "ϑ",
thetav: "ϑ",
thickapprox: "≈",
thicksim: "∼",
ThickSpace: "  ",
thinsp: " ",
ThinSpace: " ",
thkap: "≈",
thksim: "∼",
THORN: "Þ",
thorn: "þ",
Tilde: "∼",
tilde: "˜",
TildeEqual: "≃",
TildeFullEqual: "≅",
TildeTilde: "≈",
times: "×",
timesb: "⊠",
timesbar: "⨱",
timesd: "⨰",
tint: "∭",
toea: "⤨",
top: "⊤",
topbot: "⌶",
topcir: "⫱",
Topf: "𝕋",
topf: "𝕥",
topfork: "⫚",
tosa: "⤩",
tprime: "‴",
TRADE: "™",
trade: "™",
triangle: "▵",
triangledown: "▿",
triangleleft: "◃",
trianglelefteq: "⊴",
triangleq: "≜",
triangleright: "▹",
trianglerighteq: "⊵",
tridot: "◬",
trie: "≜",
triminus: "⨺",
TripleDot: "⃛",
triplus: "⨹",
trisb: "⧍",
tritime: "⨻",
trpezium: "⏢",
Tscr: "𝒯",
tscr: "𝓉",
TScy: "Ц",
tscy: "ц",
TSHcy: "Ћ",
tshcy: "ћ",
Tstrok: "Ŧ",
tstrok: "ŧ",
twixt: "≬",
twoheadleftarrow: "↞",
twoheadrightarrow: "↠",
Uacute: "Ú",
uacute: "ú",
Uarr: "↟",
uArr: "⇑",
uarr: "↑",
Uarrocir: "⥉",
Ubrcy: "Ў",
ubrcy: "ў",
Ubreve: "Ŭ",
ubreve: "ŭ",
Ucirc: "Û",
ucirc: "û",
Ucy: "У",
ucy: "у",
udarr: "⇅",
Udblac: "Ű",
udblac: "ű",
udhar: "⥮",
ufisht: "⥾",
Ufr: "𝔘",
ufr: "𝔲",
Ugrave: "Ù",
ugrave: "ù",
uHar: "⥣",
uharl: "↿",
uharr: "↾",
uhblk: "▀",
ulcorn: "⌜",
ulcorner: "⌜",
ulcrop: "⌏",
ultri: "◸",
Umacr: "Ū",
umacr: "ū",
uml: "¨",
UnderBar: "_",
UnderBrace: "⏟",
UnderBracket: "⎵",
UnderParenthesis: "⏝",
Union: "⋃",
UnionPlus: "⊎",
Uogon: "Ų",
uogon: "ų",
Uopf: "𝕌",
uopf: "𝕦",
UpArrow: "↑",
Uparrow: "⇑",
uparrow: "↑",
UpArrowBar: "⤒",
UpArrowDownArrow: "⇅",
UpDownArrow: "↕",
Updownarrow: "⇕",
updownarrow: "↕",
UpEquilibrium: "⥮",
upharpoonleft: "↿",
upharpoonright: "↾",
uplus: "⊎",
UpperLeftArrow: "↖",
UpperRightArrow: "↗",
Upsi: "ϒ",
upsi: "υ",
upsih: "ϒ",
Upsilon: "Υ",
upsilon: "υ",
UpTee: "⊥",
UpTeeArrow: "↥",
upuparrows: "⇈",
urcorn: "⌝",
urcorner: "⌝",
urcrop: "⌎",
Uring: "Ů",
uring: "ů",
urtri: "◹",
Uscr: "𝒰",
uscr: "𝓊",
utdot: "⋰",
Utilde: "Ũ",
utilde: "ũ",
utri: "▵",
utrif: "▴",
uuarr: "⇈",
Uuml: "Ü",
uuml: "ü",
uwangle: "⦧",
vangrt: "⦜",
varepsilon: "ϵ",
varkappa: "ϰ",
varnothing: "∅",
varphi: "ϕ",
varpi: "ϖ",
varpropto: "∝",
vArr: "⇕",
varr: "↕",
varrho: "ϱ",
varsigma: "ς",
varsubsetneq: "⊊︀",
varsubsetneqq: "⫋︀",
varsupsetneq: "⊋︀",
varsupsetneqq: "⫌︀",
vartheta: "ϑ",
vartriangleleft: "⊲",
vartriangleright: "⊳",
Vbar: "⫫",
vBar: "⫨",
vBarv: "⫩",
Vcy: "В",
vcy: "в",
VDash: "⊫",
Vdash: "⊩",
vDash: "⊨",
vdash: "⊢",
Vdashl: "⫦",
Vee: "⋁",
vee: "∨",
veebar: "⊻",
veeeq: "≚",
vellip: "⋮",
Verbar: "‖",
verbar: "|",
Vert: "‖",
vert: "|",
VerticalBar: "∣",
VerticalLine: "|",
VerticalSeparator: "❘",
VerticalTilde: "≀",
VeryThinSpace: " ",
Vfr: "𝔙",
vfr: "𝔳",
vltri: "⊲",
vnsub: "⊂⃒",
vnsup: "⊃⃒",
Vopf: "𝕍",
vopf: "𝕧",
vprop: "∝",
vrtri: "⊳",
Vscr: "𝒱",
vscr: "𝓋",
vsubnE: "⫋︀",
vsubne: "⊊︀",
vsupnE: "⫌︀",
vsupne: "⊋︀",
Vvdash: "⊪",
vzigzag: "⦚",
Wcirc: "Ŵ",
wcirc: "ŵ",
wedbar: "⩟",
Wedge: "⋀",
wedge: "∧",
wedgeq: "≙",
weierp: "℘",
Wfr: "𝔚",
wfr: "𝔴",
Wopf: "𝕎",
wopf: "𝕨",
wp: "℘",
wr: "≀",
wreath: "≀",
Wscr: "𝒲",
wscr: "𝓌",
xcap: "⋂",
xcirc: "◯",
xcup: "⋃",
xdtri: "▽",
Xfr: "𝔛",
xfr: "𝔵",
xhArr: "⟺",
xharr: "⟷",
Xi: "Ξ",
xi: "ξ",
xlArr: "⟸",
xlarr: "⟵",
xmap: "⟼",
xnis: "⋻",
xodot: "⨀",
Xopf: "𝕏",
xopf: "𝕩",
xoplus: "⨁",
xotime: "⨂",
xrArr: "⟹",
xrarr: "⟶",
Xscr: "𝒳",
xscr: "𝓍",
xsqcup: "⨆",
xuplus: "⨄",
xutri: "△",
xvee: "⋁",
xwedge: "⋀",
Yacute: "Ý",
yacute: "ý",
YAcy: "Я",
yacy: "я",
Ycirc: "Ŷ",
ycirc: "ŷ",
Ycy: "Ы",
ycy: "ы",
yen: "¥",
Yfr: "𝔜",
yfr: "𝔶",
YIcy: "Ї",
yicy: "ї",
Yopf: "𝕐",
yopf: "𝕪",
Yscr: "𝒴",
yscr: "𝓎",
YUcy: "Ю",
yucy: "ю",
Yuml: "Ÿ",
yuml: "ÿ",
Zacute: "Ź",
zacute: "ź",
Zcaron: "Ž",
zcaron: "ž",
Zcy: "З",
zcy: "з",
Zdot: "Ż",
zdot: "ż",
zeetrf: "ℨ",
ZeroWidthSpace: "​",
Zeta: "Ζ",
zeta: "ζ",
Zfr: "ℨ",
zfr: "𝔷",
ZHcy: "Ж",
zhcy: "ж",
zigrarr: "⇝",
Zopf: "ℤ",
zopf: "𝕫",
Zscr: "𝒵",
zscr: "𝓏",
zwj: "‍",
zwnj: "‌"
});
exports3.entityMap = exports3.HTML_ENTITIES;
})(entities$1);
var sax$1 = {};
var NAMESPACE$1 = conventions$2.NAMESPACE;
var nameStartChar = /[A-Z_a-z\xC0-\xD6\xD8-\xF6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD]/;
var nameChar = new RegExp("[\\-\\.0-9" + nameStartChar.source.slice(1, -1) + "\\u00B7\\u0300-\\u036F\\u203F-\\u2040]");
var tagNamePattern = new RegExp("^" + nameStartChar.source + nameChar.source + "*(?::" + nameStartChar.source + nameChar.source + "*)?$");
var S_TAG = 0;
var S_ATTR = 1;
var S_ATTR_SPACE = 2;
var S_EQ = 3;
var S_ATTR_NOQUOT_VALUE = 4;
var S_ATTR_END = 5;
var S_TAG_SPACE = 6;
var S_TAG_CLOSE = 7;
function ParseError$1(message, locator) {
this.message = message;
this.locator = locator;
if (Error.captureStackTrace)
Error.captureStackTrace(this, ParseError$1);
}
ParseError$1.prototype = new Error();
ParseError$1.prototype.name = ParseError$1.name;
function XMLReader$1() {
}
XMLReader$1.prototype = {
parse: function(source, defaultNSMap, entityMap) {
var domBuilder = this.domBuilder;
domBuilder.startDocument();
_copy(defaultNSMap, defaultNSMap = {});
parse$1(
source,
defaultNSMap,
entityMap,
domBuilder,
this.errorHandler
);
domBuilder.endDocument();
}
};
function parse$1(source, defaultNSMapCopy, entityMap, domBuilder, errorHandler) {
function fixedFromCharCode(code) {
if (code > 65535) {
code -= 65536;
var surrogate1 = 55296 + (code >> 10), surrogate2 = 56320 + (code & 1023);
return String.fromCharCode(surrogate1, surrogate2);
} else {
return String.fromCharCode(code);
}
}
function entityReplacer(a2) {
var k = a2.slice(1, -1);
if (k in entityMap) {
return entityMap[k];
} else if (k.charAt(0) === "#") {
return fixedFromCharCode(parseInt(k.substr(1).replace("x", "0x")));
} else {
errorHandler.error("entity not found:" + a2);
return a2;
}
}
function appendText(end2) {
if (end2 > start) {
var xt = source.substring(start, end2).replace(/&#?\w+;/g, entityReplacer);
locator && position2(start);
domBuilder.characters(xt, 0, end2 - start);
start = end2;
}
}
function position2(p, m) {
while (p >= lineEnd && (m = linePattern.exec(source))) {
lineStart = m.index;
lineEnd = lineStart + m[0].length;
locator.lineNumber++;
}
locator.columnNumber = p - lineStart + 1;
}
var lineStart = 0;
var lineEnd = 0;
var linePattern = /.*(?:\r\n?|\n)|.*$/g;
var locator = domBuilder.locator;
var parseStack = [{ currentNSMap: defaultNSMapCopy }];
var closeMap = {};
var start = 0;
while (true) {
try {
var tagStart = source.indexOf("<", start);
if (tagStart < 0) {
if (!source.substr(start).match(/^\s*$/)) {
var doc = domBuilder.doc;
var text = doc.createTextNode(source.substr(start));
doc.appendChild(text);
domBuilder.currentElement = text;
}
return;
}
if (tagStart > start) {
appendText(tagStart);
}
switch (source.charAt(tagStart + 1)) {
case "/":
var end = source.indexOf(">", tagStart + 3);
var tagName = source.substring(tagStart + 2, end).replace(/[ \t\n\r]+$/g, "");
var config = parseStack.pop();
if (end < 0) {
tagName = source.substring(tagStart + 2).replace(/[\s<].*/, "");
errorHandler.error("end tag name: " + tagName + " is not complete:" + config.tagName);
end = tagStart + 1 + tagName.length;
} else if (tagName.match(/\s</)) {
tagName = tagName.replace(/[\s<].*/, "");
errorHandler.error("end tag name: " + tagName + " maybe not complete");
end = tagStart + 1 + tagName.length;
}
var localNSMap = config.localNSMap;
var endMatch = config.tagName == tagName;
var endIgnoreCaseMach = endMatch || config.tagName && config.tagName.toLowerCase() == tagName.toLowerCase();
if (endIgnoreCaseMach) {
domBuilder.endElement(config.uri, config.localName, tagName);
if (localNSMap) {
for (var prefix in localNSMap) {
if (Object.prototype.hasOwnProperty.call(localNSMap, prefix)) {
domBuilder.endPrefixMapping(prefix);
}
}
}
if (!endMatch) {
errorHandler.fatalError("end tag name: " + tagName + " is not match the current start tagName:" + config.tagName);
}
} else {
parseStack.push(config);
}
end++;
break;
case "?":
locator && position2(tagStart);
end = parseInstruction(source, tagStart, domBuilder);
break;
case "!":
locator && position2(tagStart);
end = parseDCC(source, tagStart, domBuilder, errorHandler);
break;
default:
locator && position2(tagStart);
var el = new ElementAttributes();
var currentNSMap = parseStack[parseStack.length - 1].currentNSMap;
var end = parseElementStartPart(source, tagStart, el, currentNSMap, entityReplacer, errorHandler);
var len = el.length;
if (!el.closed && fixSelfClosed(source, end, el.tagName, closeMap)) {
el.closed = true;
if (!entityMap.nbsp) {
errorHandler.warning("unclosed xml attribute");
}
}
if (locator && len) {
var locator2 = copyLocator(locator, {});
for (var i = 0; i < len; i++) {
var a = el[i];
position2(a.offset);
a.locator = copyLocator(locator, {});
}
domBuilder.locator = locator2;
if (appendElement$1(el, domBuilder, currentNSMap)) {
parseStack.push(el);
}
domBuilder.locator = locator;
} else {
if (appendElement$1(el, domBuilder, currentNSMap)) {
parseStack.push(el);
}
}
if (NAMESPACE$1.isHTML(el.uri) && !el.closed) {
end = parseHtmlSpecialContent(source, end, el.tagName, entityReplacer, domBuilder);
} else {
end++;
}
}
} catch (e) {
if (e instanceof ParseError$1) {
throw e;
}
errorHandler.error("element parse error: " + e);
end = -1;
}
if (end > start) {
start = end;
} else {
appendText(Math.max(tagStart, start) + 1);
}
}
}
function copyLocator(f, t) {
t.lineNumber = f.lineNumber;
t.columnNumber = f.columnNumber;
return t;
}
function parseElementStartPart(source, start, el, currentNSMap, entityReplacer, errorHandler) {
function addAttribute(qname, value2, startIndex) {
if (el.attributeNames.hasOwnProperty(qname)) {
errorHandler.fatalError("Attribute " + qname + " redefined");
}
el.addValue(qname, value2, startIndex);
}
var attrName;
var value;
var p = ++start;
var s = S_TAG;
while (true) {
var c = source.charAt(p);
switch (c) {
case "=":
if (s === S_ATTR) {
attrName = source.slice(start, p);
s = S_EQ;
} else if (s === S_ATTR_SPACE) {
s = S_EQ;
} else {
throw new Error("attribute equal must after attrName");
}
break;
case "'":
case '"':
if (s === S_EQ || s === S_ATTR) {
if (s === S_ATTR) {
errorHandler.warning('attribute value must after "="');
attrName = source.slice(start, p);
}
start = p + 1;
p = source.indexOf(c, start);
if (p > 0) {
value = source.slice(start, p).replace(/&#?\w+;/g, entityReplacer);
addAttribute(attrName, value, start - 1);
s = S_ATTR_END;
} else {
throw new Error("attribute value no end '" + c + "' match");
}
} else if (s == S_ATTR_NOQUOT_VALUE) {
value = source.slice(start, p).replace(/&#?\w+;/g, entityReplacer);
addAttribute(attrName, value, start);
errorHandler.warning('attribute "' + attrName + '" missed start quot(' + c + ")!!");
start = p + 1;
s = S_ATTR_END;
} else {
throw new Error('attribute value must after "="');
}
break;
case "/":
switch (s) {
case S_TAG:
el.setTagName(source.slice(start, p));
case S_ATTR_END:
case S_TAG_SPACE:
case S_TAG_CLOSE:
s = S_TAG_CLOSE;
el.closed = true;
case S_ATTR_NOQUOT_VALUE:
case S_ATTR:
break;
case S_ATTR_SPACE:
el.closed = true;
break;
default:
throw new Error("attribute invalid close char('/')");
}
break;
case "":
errorHandler.error("unexpected end of input");
if (s == S_TAG) {
el.setTagName(source.slice(start, p));
}
return p;
case ">":
switch (s) {
case S_TAG:
el.setTagName(source.slice(start, p));
case S_ATTR_END:
case S_TAG_SPACE:
case S_TAG_CLOSE:
break;
case S_ATTR_NOQUOT_VALUE:
case S_ATTR:
value = source.slice(start, p);
if (value.slice(-1) === "/") {
el.closed = true;
value = value.slice(0, -1);
}
case S_ATTR_SPACE:
if (s === S_ATTR_SPACE) {
value = attrName;
}
if (s == S_ATTR_NOQUOT_VALUE) {
errorHandler.warning('attribute "' + value + '" missed quot(")!');
addAttribute(attrName, value.replace(/&#?\w+;/g, entityReplacer), start);
} else {
if (!NAMESPACE$1.isHTML(currentNSMap[""]) || !value.match(/^(?:disabled|checked|selected)$/i)) {
errorHandler.warning('attribute "' + value + '" missed value!! "' + value + '" instead!!');
}
addAttribute(value, value, start);
}
break;
case S_EQ:
throw new Error("attribute value missed!!");
}
return p;
case "€":
c = " ";
default:
if (c <= " ") {
switch (s) {
case S_TAG:
el.setTagName(source.slice(start, p));
s = S_TAG_SPACE;
break;
case S_ATTR:
attrName = source.slice(start, p);
s = S_ATTR_SPACE;
break;
case S_ATTR_NOQUOT_VALUE:
var value = source.slice(start, p).replace(/&#?\w+;/g, entityReplacer);
errorHandler.warning('attribute "' + value + '" missed quot(")!!');
addAttribute(attrName, value, start);
case S_ATTR_END:
s = S_TAG_SPACE;
break;
}
} else {
switch (s) {
case S_ATTR_SPACE:
el.tagName;
if (!NAMESPACE$1.isHTML(currentNSMap[""]) || !attrName.match(/^(?:disabled|checked|selected)$/i)) {
errorHandler.warning('attribute "' + attrName + '" missed value!! "' + attrName + '" instead2!!');
}
addAttribute(attrName, attrName, start);
start = p;
s = S_ATTR;
break;
case S_ATTR_END:
errorHandler.warning('attribute space is required"' + attrName + '"!!');
case S_TAG_SPACE:
s = S_ATTR;
start = p;
break;
case S_EQ:
s = S_ATTR_NOQUOT_VALUE;
start = p;
break;
case S_TAG_CLOSE:
throw new Error("elements closed character '/' and '>' must be connected to");
}
}
}
p++;
}
}
function appendElement$1(el, domBuilder, currentNSMap) {
var tagName = el.tagName;
var localNSMap = null;
var i = el.length;
while (i--) {
var a = el[i];
var qName = a.qName;
var value = a.value;
var nsp = qName.indexOf(":");
if (nsp > 0) {
var prefix = a.prefix = qName.slice(0, nsp);
var localName = qName.slice(nsp + 1);
var nsPrefix = prefix === "xmlns" && localName;
} else {
localName = qName;
prefix = null;
nsPrefix = qName === "xmlns" && "";
}
a.localName = localName;
if (nsPrefix !== false) {
if (localNSMap == null) {
localNSMap = {};
_copy(currentNSMap, currentNSMap = {});
}
currentNSMap[nsPrefix] = localNSMap[nsPrefix] = value;
a.uri = NAMESPACE$1.XMLNS;
domBuilder.startPrefixMapping(nsPrefix, value);
}
}
var i = el.length;
while (i--) {
a = el[i];
var prefix = a.prefix;
if (prefix) {
if (prefix === "xml") {
a.uri = NAMESPACE$1.XML;
}
if (prefix !== "xmlns") {
a.uri = currentNSMap[prefix || ""];
}
}
}
var nsp = tagName.indexOf(":");
if (nsp > 0) {
prefix = el.prefix = tagName.slice(0, nsp);
localName = el.localName = tagName.slice(nsp + 1);
} else {
prefix = null;
localName = el.localName = tagName;
}
var ns = el.uri = currentNSMap[prefix || ""];
domBuilder.startElement(ns, localName, tagName, el);
if (el.closed) {
domBuilder.endElement(ns, localName, tagName);
if (localNSMap) {
for (prefix in localNSMap) {
if (Object.prototype.hasOwnProperty.call(localNSMap, prefix)) {
domBuilder.endPrefixMapping(prefix);
}
}
}
} else {
el.currentNSMap = currentNSMap;
el.localNSMap = localNSMap;
return true;
}
}
function parseHtmlSpecialContent(source, elStartEnd, tagName, entityReplacer, domBuilder) {
if (/^(?:script|textarea)$/i.test(tagName)) {
var elEndStart = source.indexOf("</" + tagName + ">", elStartEnd);
var text = source.substring(elStartEnd + 1, elEndStart);
if (/[&<]/.test(text)) {
if (/^script$/i.test(tagName)) {
domBuilder.characters(text, 0, text.length);
return elEndStart;
}
text = text.replace(/&#?\w+;/g, entityReplacer);
domBuilder.characters(text, 0, text.length);
return elEndStart;
}
}
return elStartEnd + 1;
}
function fixSelfClosed(source, elStartEnd, tagName, closeMap) {
var pos = closeMap[tagName];
if (pos == null) {
pos = source.lastIndexOf("</" + tagName + ">");
if (pos < elStartEnd) {
pos = source.lastIndexOf("</" + tagName);
}
closeMap[tagName] = pos;
}
return pos < elStartEnd;
}
function _copy(source, target) {
for (var n in source) {
if (Object.prototype.hasOwnProperty.call(source, n)) {
target[n] = source[n];
}
}
}
function parseDCC(source, start, domBuilder, errorHandler) {
var next = source.charAt(start + 2);
switch (next) {
case "-":
if (source.charAt(start + 3) === "-") {
var end = source.indexOf("-->", start + 4);
if (end > start) {
domBuilder.comment(source, start + 4, end - start - 4);
return end + 3;
} else {
errorHandler.error("Unclosed comment");
return -1;
}
} else {
return -1;
}
default:
if (source.substr(start + 3, 6) == "CDATA[") {
var end = source.indexOf("]]>", start + 9);
domBuilder.startCDATA();
domBuilder.characters(source, start + 9, end - start - 9);
domBuilder.endCDATA();
return end + 3;
}
var matchs = split(source, start);
var len = matchs.length;
if (len > 1 && /!doctype/i.test(matchs[0][0])) {
var name = matchs[1][0];
var pubid = false;
var sysid = false;
if (len > 3) {
if (/^public$/i.test(matchs[2][0])) {
pubid = matchs[3][0];
sysid = len > 4 && matchs[4][0];
} else if (/^system$/i.test(matchs[2][0])) {
sysid = matchs[3][0];
}
}
var lastMatch = matchs[len - 1];
domBuilder.startDTD(name, pubid, sysid);
domBuilder.endDTD();
return lastMatch.index + lastMatch[0].length;
}
}
return -1;
}
function parseInstruction(source, start, domBuilder) {
var end = source.indexOf("?>", start);
if (end) {
var match = source.substring(start, end).match(/^<\?(\S*)\s*([\s\S]*?)\s*$/);
if (match) {
match[0].length;
domBuilder.processingInstruction(match[1], match[2]);
return end + 2;
} else {
return -1;
}
}
return -1;
}
function ElementAttributes() {
this.attributeNames = {};
}
ElementAttributes.prototype = {
setTagName: function(tagName) {
if (!tagNamePattern.test(tagName)) {
throw new Error("invalid tagName:" + tagName);
}
this.tagName = tagName;
},
addValue: function(qName, value, offset) {
if (!tagNamePattern.test(qName)) {
throw new Error("invalid attribute:" + qName);
}
this.attributeNames[qName] = this.length;
this[this.length++] = { qName, value, offset };
},
length: 0,
getLocalName: function(i) {
return this[i].localName;
},
getLocator: function(i) {
return this[i].locator;
},
getQName: function(i) {
return this[i].qName;
},
getURI: function(i) {
return this[i].uri;
},
getValue: function(i) {
return this[i].value;
}
// ,getIndex:function(uri, localName)){
// if(localName){
//
// }else{
// var qName = uri
// }
// },
// getValue:function(){return this.getValue(this.getIndex.apply(this,arguments))},
// getType:function(uri,localName){}
// getType:function(i){},
};
function split(source, start) {
var match;
var buf = [];
var reg = /'[^']+'|"[^"]+"|[^\s<>\/=]+=?|(\/?\s*>|<)/g;
reg.lastIndex = start;
reg.exec(source);
while (match = reg.exec(source)) {
buf.push(match);
if (match[1])
return buf;
}
}
sax$1.XMLReader = XMLReader$1;
sax$1.ParseError = ParseError$1;
var conventions = conventions$2;
var dom = dom$1;
var entities = entities$1;
var sax = sax$1;
var DOMImplementation = dom.DOMImplementation;
var NAMESPACE = conventions.NAMESPACE;
var ParseError = sax.ParseError;
var XMLReader = sax.XMLReader;
function DOMParser$2(options) {
this.options = options || { locator: {} };
}
DOMParser$2.prototype.parseFromString = function(source, mimeType) {
var options = this.options;
var sax2 = new XMLReader();
var domBuilder = options.domBuilder || new DOMHandler();
var errorHandler = options.errorHandler;
var locator = options.locator;
var defaultNSMap = options.xmlns || {};
var isHTML = /\/x?html?$/.test(mimeType);
var entityMap = isHTML ? entities.HTML_ENTITIES : entities.XML_ENTITIES;
if (locator) {
domBuilder.setDocumentLocator(locator);
}
sax2.errorHandler = buildErrorHandler(errorHandler, domBuilder, locator);
sax2.domBuilder = options.domBuilder || domBuilder;
if (isHTML) {
defaultNSMap[""] = NAMESPACE.HTML;
}
defaultNSMap.xml = defaultNSMap.xml || NAMESPACE.XML;
if (source && typeof source === "string") {
sax2.parse(source, defaultNSMap, entityMap);
} else {
sax2.errorHandler.error("invalid doc source");
}
return domBuilder.doc;
};
function buildErrorHandler(errorImpl, domBuilder, locator) {
if (!errorImpl) {
if (domBuilder instanceof DOMHandler) {
return domBuilder;
}
errorImpl = domBuilder;
}
var errorHandler = {};
var isCallback = errorImpl instanceof Function;
locator = locator || {};
function build(key) {
var fn = errorImpl[key];
if (!fn && isCallback) {
fn = errorImpl.length == 2 ? function(msg) {
errorImpl(key, msg);
} : errorImpl;
}
errorHandler[key] = fn && function(msg) {
fn("[xmldom " + key + "] " + msg + _locator(locator));
} || function() {
};
}
build("warning");
build("error");
build("fatalError");
return errorHandler;
}
function DOMHandler() {
this.cdata = false;
}
function position(locator, node) {
node.lineNumber = locator.lineNumber;
node.columnNumber = locator.columnNumber;
}
DOMHandler.prototype = {
startDocument: function() {
this.doc = new DOMImplementation().createDocument(null, null, null);
if (this.locator) {
this.doc.documentURI = this.locator.systemId;
}
},
startElement: function(namespaceURI, localName, qName, attrs) {
var doc = this.doc;
var el = doc.createElementNS(namespaceURI, qName || localName);
var len = attrs.length;
appendElement(this, el);
this.currentElement = el;
this.locator && position(this.locator, el);
for (var i = 0; i < len; i++) {
var namespaceURI = attrs.getURI(i);
var value = attrs.getValue(i);
var qName = attrs.getQName(i);
var attr = doc.createAttributeNS(namespaceURI, qName);
this.locator && position(attrs.getLocator(i), attr);
attr.value = attr.nodeValue = value;
el.setAttributeNode(attr);
}
},
endElement: function(namespaceURI, localName, qName) {
var current = this.currentElement;
current.tagName;
this.currentElement = current.parentNode;
},
startPrefixMapping: function(prefix, uri) {
},
endPrefixMapping: function(prefix) {
},
processingInstruction: function(target, data) {
var ins = this.doc.createProcessingInstruction(target, data);
this.locator && position(this.locator, ins);
appendElement(this, ins);
},
ignorableWhitespace: function(ch, start, length) {
},
characters: function(chars, start, length) {
chars = _toString.apply(this, arguments);
if (chars) {
if (this.cdata) {
var charNode = this.doc.createCDATASection(chars);
} else {
var charNode = this.doc.createTextNode(chars);
}
if (this.currentElement) {
this.currentElement.appendChild(charNode);
} else if (/^\s*$/.test(chars)) {
this.doc.appendChild(charNode);
}
this.locator && position(this.locator, charNode);
}
},
skippedEntity: function(name) {
},
endDocument: function() {
this.doc.normalize();
},
setDocumentLocator: function(locator) {
if (this.locator = locator) {
locator.lineNumber = 0;
}
},
//LexicalHandler
comment: function(chars, start, length) {
chars = _toString.apply(this, arguments);
var comm = this.doc.createComment(chars);
this.locator && position(this.locator, comm);
appendElement(this, comm);
},
startCDATA: function() {
this.cdata = true;
},
endCDATA: function() {
this.cdata = false;
},
startDTD: function(name, publicId, systemId) {
var impl = this.doc.implementation;
if (impl && impl.createDocumentType) {
var dt = impl.createDocumentType(name, publicId, systemId);
this.locator && position(this.locator, dt);
appendElement(this, dt);
this.doc.doctype = dt;
}
},
/**
* @see org.xml.sax.ErrorHandler
* @link http://www.saxproject.org/apidoc/org/xml/sax/ErrorHandler.html
*/
warning: function(error) {
console.warn("[xmldom warning] " + error, _locator(this.locator));
},
error: function(error) {
console.error("[xmldom error] " + error, _locator(this.locator));
},
fatalError: function(error) {
throw new ParseError(error, this.locator);
}
};
function _locator(l) {
if (l) {
return "\n@" + (l.systemId || "") + "#[line:" + l.lineNumber + ",col:" + l.columnNumber + "]";
}
}
function _toString(chars, start, length) {
if (typeof chars == "string") {
return chars.substr(start, length);
} else {
if (chars.length >= start + length || start) {
return new java.lang.String(chars, start, length) + "";
}
return chars;
}
}
"endDTD,startEntity,endEntity,attributeDecl,elementDecl,externalEntityDecl,internalEntityDecl,resolveEntity,getExternalSubset,notationDecl,unparsedEntityDecl".replace(/\w+/g, function(key) {
DOMHandler.prototype[key] = function() {
return null;
};
});
function appendElement(hander, node) {
if (!hander.currentElement) {
hander.doc.appendChild(node);
} else {
hander.currentElement.appendChild(node);
}
}
domParser.__DOMHandler = DOMHandler;
domParser.DOMParser = DOMParser$2;
domParser.DOMImplementation = dom.DOMImplementation;
domParser.XMLSerializer = dom.XMLSerializer;
var DOMParser$1 = domParser.DOMParser;
const requestAnimationFrame$1 = typeof window != "undefined" ? window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame : false;
const ELEMENT_NODE$2 = 1;
const TEXT_NODE$1 = 3;
const _URL = typeof URL != "undefined" ? URL : typeof window != "undefined" ? window.URL || window.webkitURL || window.mozURL : void 0;
function uuid() {
var d2 = (/* @__PURE__ */ new Date()).getTime();
var uuid2 = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(c) {
var r = (d2 + Math.random() * 16) % 16 | 0;
d2 = Math.floor(d2 / 16);
return (c == "x" ? r : r & 7 | 8).toString(16);
});
return uuid2;
}
function documentHeight() {
return Math.max(
document.documentElement.clientHeight,
document.body.scrollHeight,
document.documentElement.scrollHeight,
document.body.offsetHeight,
document.documentElement.offsetHeight
);
}
function isElement(obj) {
return !!(obj && obj.nodeType == 1);
}
function isNumber(n) {
return !isNaN(parseFloat(n)) && isFinite(n);
}
function isFloat(n) {
let f = parseFloat(n);
if (isNumber(n) === false) {
return false;
}
if (typeof n === "string" && n.indexOf(".") > -1) {
return true;
}
return Math.floor(f) !== f;
}
function prefixed(unprefixed) {
var vendors = ["Webkit", "webkit", "Moz", "O", "ms"];
var prefixes = ["-webkit-", "-webkit-", "-moz-", "-o-", "-ms-"];
var lower = unprefixed.toLowerCase();
var length = vendors.length;
if (typeof document === "undefined" || typeof document.body.style[lower] != "undefined") {
return unprefixed;
}
for (var i = 0; i < length; i++) {
if (typeof document.body.style[prefixes[i] + lower] != "undefined") {
return prefixes[i] + lower;
}
}
return unprefixed;
}
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;
}
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;
}
function insert(item, array, compareFunction) {
var location = locationOf(item, array, compareFunction);
array.splice(location, 0, item);
return location;
}
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(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);
}
}
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(a, b) {
if (a > b)
return 1;
if (a < b)
return -1;
if (a == b)
return 0;
};
}
if (end - start <= 0) {
return -1;
}
compared = compareFunction(array[pivot], item);
if (end - start === 1) {
return compared === 0 ? pivot : -1;
}
if (compared === 0) {
return pivot;
}
if (compared === -1) {
return indexOfSorted(item, array, compareFunction, pivot, end);
} else {
return indexOfSorted(item, array, compareFunction, start, pivot);
}
}
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,
width
};
}
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,
width
};
}
function nodeBounds(node) {
let elPos;
let doc = node.ownerDocument;
if (node.nodeType == Node.TEXT_NODE) {
let elRange = doc.createRange();
elRange.selectNodeContents(node);
elPos = elRange.getBoundingClientRect();
} else {
elPos = node.getBoundingClientRect();
}
return elPos;
}
function windowBounds() {
var width = window.innerWidth;
var height = window.innerHeight;
return {
top: 0,
left: 0,
right: width,
bottom: height,
width,
height
};
}
function indexOfNode(node, typeId) {
var parent2 = node.parentNode;
var children = parent2.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;
}
function indexOfTextNode(textNode) {
return indexOfNode(textNode, TEXT_NODE$1);
}
function indexOfElementNode(elementNode) {
return indexOfNode(elementNode, ELEMENT_NODE$2);
}
function isXml(ext) {
return ["xml", "opf", "ncx"].indexOf(ext) > -1;
}
function createBlob(content, mime2) {
return new Blob([content], { type: mime2 });
}
function createBlobUrl(content, mime2) {
var tempUrl;
var blob = createBlob(content, mime2);
tempUrl = _URL.createObjectURL(blob);
return tempUrl;
}
function revokeBlobUrl(url) {
return _URL.revokeObjectURL(url);
}
function createBase64Url(content, mime2) {
var data;
var datauri;
if (typeof content !== "string") {
return;
}
data = btoa(content);
datauri = "data:" + mime2 + ";base64," + data;
return datauri;
}
function type(obj) {
return Object.prototype.toString.call(obj).slice(8, -1);
}
function parse(markup, mime2, forceXMLDom) {
var doc;
var Parser;
if (typeof DOMParser === "undefined" || forceXMLDom) {
Parser = DOMParser$1;
} else {
Parser = DOMParser;
}
if (markup.charCodeAt(0) === 65279) {
markup = markup.slice(1);
}
doc = new Parser().parseFromString(markup, mime2);
return doc;
}
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];
}
}
}
function qsa(el, sel) {
if (typeof el.querySelector != "undefined") {
return el.querySelectorAll(sel);
} else {
return el.getElementsByTagName(sel);
}
}
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(el2) {
for (var prop2 in props) {
if (el2.getAttribute(prop2) === props[prop2]) {
return true;
}
}
return false;
});
if (filtered) {
return filtered[0];
}
}
}
function sprint(root2, func) {
var doc = root2.ownerDocument || root2;
if (typeof doc.createTreeWalker !== "undefined") {
treeWalker(root2, func, NodeFilter.SHOW_TEXT);
} else {
walk(root2, function(node) {
if (node && node.nodeType === 3) {
func(node);
}
});
}
}
function treeWalker(root2, func, filter) {
var treeWalker2 = document.createTreeWalker(root2, filter, null, false);
let node;
while (node = treeWalker2.nextNode()) {
func(node);
}
}
function walk(node, callback) {
if (callback(node)) {
return true;
}
node = node.firstChild;
if (node) {
do {
let walked = walk(node, callback);
if (walked) {
return true;
}
node = node.nextSibling;
} while (node);
}
}
function blob2base64(blob) {
return new Promise(function(resolve, reject) {
var reader = new FileReader();
reader.readAsDataURL(blob);
reader.onloadend = function() {
resolve(reader.result);
};
});
}
function defer() {
this.resolve = null;
this.reject = null;
this.id = uuid();
this.promise = new Promise((resolve, reject) => {
this.resolve = resolve;
this.reject = reject;
});
Object.freeze(this);
}
function querySelectorByType(html, element, type2) {
var query;
if (typeof html.querySelector != "undefined") {
query = html.querySelector(`${element}[*|type="${type2}"]`);
}
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") === type2 || query[i].getAttribute("epub:type") === type2) {
return query[i];
}
}
} else {
return query;
}
}
function findChildren(el) {
var result = [];
var childNodes = el.childNodes;
for (var i = 0; i < childNodes.length; i++) {
let node = childNodes[i];
if (node.nodeType === 1) {
result.push(node);
}
}
return result;
}
function parents(node) {
var nodes = [node];
for (; node; node = node.parentNode) {
nodes.unshift(node);
}
return nodes;
}
function filterChildren(el, nodeName, single) {
var result = [];
var childNodes = el.childNodes;
for (var i = 0; i < childNodes.length; i++) {
let node = childNodes[i];
if (node.nodeType === 1 && node.nodeName.toLowerCase() === nodeName) {
if (single) {
return node;
} else {
result.push(node);
}
}
}
if (!single) {
return result;
}
}
function getParentByTagName(node, tagname) {
let parent2;
if (node === null || tagname === "")
return;
parent2 = node.parentNode;
while (parent2.nodeType === 1) {
if (parent2.tagName.toLowerCase() === tagname) {
return parent2;
}
parent2 = parent2.parentNode;
}
}
class RangeObject {
constructor() {
this.collapsed = false;
this.commonAncestorContainer = void 0;
this.endContainer = void 0;
this.endOffset = void 0;
this.startContainer = void 0;
this.startOffset = void 0;
}
setStart(startNode, startOffset) {
this.startContainer = startNode;
this.startOffset = startOffset;
if (!this.endContainer) {
this.collapse(true);
} else {
this.commonAncestorContainer = this._commonAncestorContainer();
}
this._checkCollapsed();
}
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();
}
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;
}
}
selectNode(referenceNode) {
let parent2 = referenceNode.parentNode;
let index = Array.prototype.indexOf.call(parent2.childNodes, referenceNode);
this.setStart(parent2, index);
this.setEnd(parent2, index + 1);
}
selectNodeContents(referenceNode) {
referenceNode.childNodes[referenceNode.childNodes - 1];
let endIndex = referenceNode.nodeType === 3 ? referenceNode.textContent.length : parent.childNodes.length;
this.setStart(referenceNode, 0);
this.setEnd(referenceNode, endIndex);
}
_commonAncestorContainer(startContainer, endContainer) {
var startParents = parents(startContainer || this.startContainer);
var endParents = parents(endContainer || this.endContainer);
if (startParents[0] != endParents[0])
return void 0;
for (var i = 0; i < startParents.length; i++) {
if (startParents[i] != endParents[i]) {
return startParents[i - 1];
}
}
}
_checkCollapsed() {
if (this.startContainer === this.endContainer && this.startOffset === this.endOffset) {
this.collapsed = true;
} else {
this.collapsed = false;
}
}
toString() {
}
}
const utils = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
__proto__: null,
RangeObject,
blob2base64,
borders,
bounds,
createBase64Url,
createBlob,
createBlobUrl,
defaults,
defer,
documentHeight,
extend,
filterChildren,
findChildren,
getParentByTagName,
indexOfElementNode,
indexOfNode,
indexOfSorted,
indexOfTextNode,
insert,
isElement,
isFloat,
isNumber,
isXml,
locationOf,
nodeBounds,
parents,
parse,
prefixed,
qs,
qsa,
qsp,
querySelectorByType,
requestAnimationFrame: requestAnimationFrame$1,
revokeBlobUrl,
sprint,
treeWalker,
type,
uuid,
walk,
windowBounds
}, Symbol.toStringTag, { value: "Module" }));
if (!process) {
var process = {
"cwd": function() {
return "/";
}
};
}
function assertPath(path2) {
if (typeof path2 !== "string") {
throw new TypeError("Path must be a string. Received " + path2);
}
}
function normalizeStringPosix(path2, allowAboveRoot) {
var res = "";
var lastSlash = -1;
var dots = 0;
var code;
for (var i = 0; i <= path2.length; ++i) {
if (i < path2.length)
code = path2.charCodeAt(i);
else if (code === 47)
break;
else
code = 47;
if (code === 47) {
if (lastSlash === i - 1 || dots === 1)
;
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 += "/" + path2.slice(lastSlash + 1, i);
else
res = path2.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 path2;
if (i >= 0)
path2 = arguments[i];
else {
if (cwd === void 0)
cwd = process.cwd();
path2 = cwd;
}
assertPath(path2);
if (path2.length === 0) {
continue;
}
resolvedPath = path2 + "/" + resolvedPath;
resolvedAbsolute = path2.charCodeAt(0) === 47;
}
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(path2) {
assertPath(path2);
if (path2.length === 0)
return ".";
var isAbsolute = path2.charCodeAt(0) === 47;
var trailingSeparator = path2.charCodeAt(path2.length - 1) === 47;
path2 = normalizeStringPosix(path2, !isAbsolute);
if (path2.length === 0 && !isAbsolute)
path2 = ".";
if (path2.length > 0 && trailingSeparator)
path2 += "/";
if (isAbsolute)
return "/" + path2;
return path2;
},
isAbsolute: function isAbsolute(path2) {
assertPath(path2);
return path2.length > 0 && path2.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 === void 0)
joined = arg;
else
joined += "/" + arg;
}
}
if (joined === void 0)
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 "";
var fromStart = 1;
for (; fromStart < from.length; ++fromStart) {
if (from.charCodeAt(fromStart) !== 47)
break;
}
var fromEnd = from.length;
var fromLen = fromEnd - fromStart;
var toStart = 1;
for (; toStart < to.length; ++toStart) {
if (to.charCodeAt(toStart) !== 47)
break;
}
var toEnd = to.length;
var toLen = toEnd - toStart;
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) {
return to.slice(toStart + i + 1);
} else if (i === 0) {
return to.slice(toStart + i);
}
} else if (fromLen > length) {
if (from.charCodeAt(fromStart + i) === 47) {
lastCommonSep = i;
} else if (i === 0) {
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 = "";
for (i = fromStart + lastCommonSep + 1; i <= fromEnd; ++i) {
if (i === fromEnd || from.charCodeAt(i) === 47) {
if (out.length === 0)
out += "..";
else
out += "/..";
}
}
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(path2) {
return path2;
},
dirname: function dirname(path2) {
assertPath(path2);
if (path2.length === 0)
return ".";
var code = path2.charCodeAt(0);
var hasRoot = code === 47;
var end = -1;
var matchedSlash = true;
for (var i = path2.length - 1; i >= 1; --i) {
code = path2.charCodeAt(i);
if (code === 47) {
if (!matchedSlash) {
end = i;
break;
}
} else {
matchedSlash = false;
}
}
if (end === -1)
return hasRoot ? "/" : ".";
if (hasRoot && end === 1)
return "//";
return path2.slice(0, end);
},
basename: function basename(path2, ext) {
if (ext !== void 0 && typeof ext !== "string")
throw new TypeError('"ext" argument must be a string');
assertPath(path2);
var start = 0;
var end = -1;
var matchedSlash = true;
var i;
if (ext !== void 0 && ext.length > 0 && ext.length <= path2.length) {
if (ext.length === path2.length && ext === path2)
return "";
var extIdx = ext.length - 1;
var firstNonSlashEnd = -1;
for (i = path2.length - 1; i >= 0; --i) {
var code = path2.charCodeAt(i);
if (code === 47) {
if (!matchedSlash) {
start = i + 1;
break;
}
} else {
if (firstNonSlashEnd === -1) {
matchedSlash = false;
firstNonSlashEnd = i + 1;
}
if (extIdx >= 0) {
if (code === ext.charCodeAt(extIdx)) {
if (--extIdx === -1) {
end = i;
}
} else {
extIdx = -1;
end = firstNonSlashEnd;
}
}
}
}
if (start === end)
end = firstNonSlashEnd;
else if (end === -1)
end = path2.length;
return path2.slice(start, end);
} else {
for (i = path2.length - 1; i >= 0; --i) {
if (path2.charCodeAt(i) === 47) {
if (!matchedSlash) {
start = i + 1;
break;
}
} else if (end === -1) {
matchedSlash = false;
end = i + 1;
}
}
if (end === -1)
return "";
return path2.slice(start, end);
}
},
extname: function extname(path2) {
assertPath(path2);
var startDot = -1;
var startPart = 0;
var end = -1;
var matchedSlash = true;
var preDotState = 0;
for (var i = path2.length - 1; i >= 0; --i) {
var code = path2.charCodeAt(i);
if (code === 47) {
if (!matchedSlash) {
startPart = i + 1;
break;
}
continue;
}
if (end === -1) {
matchedSlash = false;
end = i + 1;
}
if (code === 46) {
if (startDot === -1)
startDot = i;
else if (preDotState !== 1)
preDotState = 1;
} else if (startDot !== -1) {
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 path2.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 parse2(path2) {
assertPath(path2);
var ret = { root: "", dir: "", base: "", ext: "", name: "" };
if (path2.length === 0)
return ret;
var code = path2.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 = path2.length - 1;
var preDotState = 0;
for (; i >= start; --i) {
code = path2.charCodeAt(i);
if (code === 47) {
if (!matchedSlash) {
startPart = i + 1;
break;
}
continue;
}
if (end === -1) {
matchedSlash = false;
end = i + 1;
}
if (code === 46) {
if (startDot === -1)
startDot = i;
else if (preDotState !== 1)
preDotState = 1;
} else if (startDot !== -1) {
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 = path2.slice(1, end);
else
ret.base = ret.name = path2.slice(startPart, end);
}
} else {
if (startPart === 0 && isAbsolute) {
ret.name = path2.slice(1, startDot);
ret.base = path2.slice(1, end);
} else {
ret.name = path2.slice(startPart, startDot);
ret.base = path2.slice(startPart, end);
}
ret.ext = path2.slice(startDot, end);
}
if (startPart > 0)
ret.dir = path2.slice(0, startPart - 1);
else if (isAbsolute)
ret.dir = "/";
return ret;
},
sep: "/",
delimiter: ":",
posix: null
};
var path = posix;
const path$1 = /* @__PURE__ */ getDefaultExportFromCjs(path);
class Path {
constructor(pathString) {
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}
*/
parse(what) {
return path$1.parse(what);
}
/**
* @param {string} what
* @returns {boolean}
*/
isAbsolute(what) {
return path$1.isAbsolute(what || this.path);
}
/**
* Check if path ends with a directory
* @param {string} what
* @returns {boolean}
*/
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
*/
resolve(what) {
return path$1.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
*/
relative(what) {
var isAbsolute = what && what.indexOf("://") > -1;
if (isAbsolute) {
return what;
}
return path$1.relative(this.directory, what);
}
splitPath(filename) {
return this.splitPathRe.exec(filename).slice(1);
}
/**
* Return the path string
* @returns {string} path
*/
toString() {
return this.path;
}
}
class Url {
constructor(urlString, baseString) {
var absolute = urlString.indexOf("://") > -1;
var pathname = urlString;
var basePath;
this.Url = void 0;
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;
}
if (absolute || this.base) {
try {
if (this.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 + (this.Url.search ? this.Url.search : "");
} catch (e) {
this.Url = void 0;
if (this.base) {
basePath = new Path(this.base);
pathname = basePath.resolve(pathname);
}
}
}
this.Path = new Path(pathname);
this.directory = this.Path.directory;
this.filename = this.Path.filename;
this.extension = this.Path.extension;
}
/**
* @returns {Path}
*/
path() {
return this.Path;
}
/**
* Resolves a relative path to a absolute url
* @param {string} what
* @returns {string} url
*/
resolve(what) {
var isAbsolute = what.indexOf("://") > -1;
var fullpath;
if (isAbsolute) {
return what;
}
fullpath = path$1.resolve(this.directory, what);
return this.origin + fullpath;
}
/**
* Resolve a path relative to the url
* @param {string} what
* @returns {string} path
*/
relative(what) {
return path$1.relative(what, this.directory);
}
/**
* @returns {string}
*/
toString() {
return this.href;
}
}
const ELEMENT_NODE$1 = 1;
const TEXT_NODE = 3;
const DOCUMENT_NODE = 9;
class EpubCFI {
constructor(cfiFrom, base, ignoreClass) {
var type2;
this.str = "";
this.base = {};
this.spinePos = 0;
this.range = false;
this.path = {};
this.start = null;
this.end = null;
if (!(this instanceof EpubCFI)) {
return new EpubCFI(cfiFrom, base, ignoreClass);
}
if (typeof base === "string") {
this.base = this.parseComponent(base);
} else if (typeof base === "object" && base.steps) {
this.base = base;
}
type2 = this.checkType(cfiFrom);
if (type2 === "string") {
this.str = cfiFrom;
return extend(this, this.parse(cfiFrom));
} else if (type2 === "range") {
return extend(this, this.fromRange(cfiFrom, this.base, ignoreClass));
} else if (type2 === "node") {
return extend(this, this.fromNode(cfiFrom, this.base, ignoreClass));
} else if (type2 === "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
*/
checkType(cfi) {
if (this.isCfiString(cfi)) {
return "string";
} else if (cfi && typeof cfi === "object" && (type(cfi) === "Range" || typeof cfi.startContainer != "undefined")) {
return "range";
} else if (cfi && typeof cfi === "object" && typeof cfi.nodeType != "undefined") {
return "node";
} else if (cfi && 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
*/
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] === ")") {
cfiStr = cfiStr.slice(8, cfiStr.length - 1);
}
baseComponent = this.getChapterComponent(cfiStr);
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]);
}
cfi.spinePos = cfi.base.steps[1].index;
return cfi;
}
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();
}
component.steps = steps.map((function(step) {
return this.parseStep(step);
}).bind(this));
return component;
}
parseStep(stepStr) {
var type2, num, index, has_brackets, id;
has_brackets = stepStr.match(/\[(.*)\]/);
if (has_brackets && has_brackets[1]) {
id = has_brackets[1];
}
num = parseInt(stepStr);
if (isNaN(num)) {
return;
}
if (num % 2 === 0) {
type2 = "element";
index = num / 2 - 1;
} else {
type2 = "text";
index = (num - 1) / 2;
}
return {
"type": type2,
"index": index,
"id": id || null
};
}
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 (!isNumber(characterOffset)) {
characterOffset = null;
}
return {
"offset": characterOffset,
"assertion": textLocationAssertion
};
}
getChapterComponent(cfiStr) {
var indirection = cfiStr.split("!");
return indirection[0];
}
getPathComponent(cfiStr) {
var indirection = cfiStr.split("!");
if (indirection[1]) {
let ranges = indirection[1].split(",");
return ranges[0];
}
}
getRange(cfiStr) {
var ranges = cfiStr.split(",");
if (ranges.length === 3) {
return [
ranges[1],
ranges[2]
];
}
return false;
}
getCharecterOffsetComponent(cfiStr) {
var splitStr = cfiStr.split(":");
return splitStr[1] || "";
}
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;
}
if (part.id) {
segment += "[" + part.id + "]";
}
return segment;
}).join("/");
}
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
*/
toString() {
var cfiString = "epubcfi(";
cfiString += this.segmentString(this.base);
cfiString += "!";
cfiString += this.segmentString(this.path);
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
*/
compare(cfiOne, cfiTwo) {
var stepsA, stepsB;
var terminalA, terminalB;
if (typeof cfiOne === "string") {
cfiOne = new EpubCFI(cfiOne);
}
if (typeof cfiTwo === "string") {
cfiTwo = new EpubCFI(cfiTwo);
}
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;
}
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;
}
}
if (stepsA.length < stepsB.length) {
return -1;
}
if (terminalA.offset > terminalB.offset) {
return 1;
}
if (terminalA.offset < terminalB.offset) {
return -1;
}
return 0;
}
step(node) {
var nodeType = node.nodeType === TEXT_NODE ? "text" : "element";
return {
"id": node.id,
"tagName": node.tagName,
"type": nodeType,
"index": this.position(node)
};
}
filteredStep(node, ignoreClass) {
var filteredNode = this.filter(node, ignoreClass);
var nodeType;
if (!filteredNode) {
return;
}
nodeType = filteredNode.nodeType === TEXT_NODE ? "text" : "element";
return {
"id": filteredNode.id,
"tagName": filteredNode.tagName,
"type": nodeType,
"index": this.filteredPosition(filteredNode, ignoreClass)
};
}
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;
if (segment.steps[segment.steps.length - 1].type != "text") {
segment.steps.push({
"type": "text",
"index": 0
});
}
}
return segment;
}
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
*/
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) {
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 === "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);
cfi.path = {
steps: [],
terminal: null
};
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) {
if (cfi.start.terminal === cfi.end.terminal) {
cfi.path.steps.push(cfi.start.steps[i]);
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);
}
return cfi;
}
/**
* Create a CFI object from a Node
* @param {Node} anchor
* @param {string | object} base
* @param {string} [ignoreClass]
* @returns {object} cfi
*/
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 === "object") {
cfi.base = base;
}
cfi.path = this.pathTo(anchor, null, ignoreClass);
return cfi;
}
filter(anchor, ignoreClass) {
var needsIgnoring;
var sibling;
var parent2, previousSibling, nextSibling;
var isText = false;
if (anchor.nodeType === TEXT_NODE) {
isText = true;
parent2 = anchor.parentNode;
needsIgnoring = anchor.parentNode.classList.contains(ignoreClass);
} else {
isText = false;
needsIgnoring = anchor.classList.contains(ignoreClass);
}
if (needsIgnoring && isText) {
previousSibling = parent2.previousSibling;
nextSibling = parent2.nextSibling;
if (previousSibling && previousSibling.nodeType === TEXT_NODE) {
sibling = previousSibling;
} else if (nextSibling && nextSibling.nodeType === TEXT_NODE) {
sibling = nextSibling;
}
if (sibling) {
return sibling;
} else {
return anchor;
}
} else if (needsIgnoring && !isText) {
return false;
} else {
return anchor;
}
}
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 (anchor.parentNode.classList.contains(ignoreClass)) {
curr = anchor.parentNode;
}
while (curr.previousSibling) {
if (curr.previousSibling.nodeType === ELEMENT_NODE$1) {
if (curr.previousSibling.classList.contains(ignoreClass)) {
totalOffset += curr.previousSibling.textContent.length;
} else {
break;
}
} else {
totalOffset += curr.previousSibling.textContent.length;
}
curr = curr.previousSibling;
}
return totalOffset;
}
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;
if (currNodeType === ELEMENT_NODE$1 && children[i].classList.contains(ignoreClass)) {
currNodeType = TEXT_NODE;
}
if (i > 0 && currNodeType === TEXT_NODE && prevNodeType === TEXT_NODE) {
output[i] = prevIndex;
} else if (nodeType === currNodeType) {
prevIndex = prevIndex + 1;
output[i] = prevIndex;
}
prevNodeType = currNodeType;
}
return output;
}
position(anchor) {
var children, index;
if (anchor.nodeType === ELEMENT_NODE$1) {
children = anchor.parentNode.children;
if (!children) {
children = findChildren(anchor.parentNode);
}
index = Array.prototype.indexOf.call(children, anchor);
} else {
children = this.textNodes(anchor.parentNode);
index = children.indexOf(anchor);
}
return index;
}
filteredPosition(anchor, ignoreClass) {
var children, index, map;
if (anchor.nodeType === ELEMENT_NODE$1) {
children = anchor.parentNode.children;
map = this.normalizedMap(children, ELEMENT_NODE$1, ignoreClass);
} else {
children = anchor.parentNode.childNodes;
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];
}
stepsToXpath(steps) {
var xpath = [".", "*"];
steps.forEach(function(step) {
var position2 = step.index + 1;
if (step.id) {
xpath.push("*[position()=" + position2 + " and @id='" + step.id + "']");
} else if (step.type === "text") {
xpath.push("text()[" + position2 + "]");
} else {
xpath.push("*[" + position2 + "]");
}
});
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];
}
*/
stepsToQuerySelector(steps) {
var query = ["html"];
steps.forEach(function(step) {
var position2 = step.index + 1;
if (step.id) {
query.push("#" + step.id);
} else if (step.type === "text")
;
else {
query.push("*:nth-child(" + position2 + ")");
}
});
return query.join(">");
}
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;
});
}
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") {
if (step.id) {
container = doc.getElementById(step.id);
} else {
children = container.children || findChildren(container);
container = children[step.index];
}
} else if (step.type === "text") {
container = this.textNodes(container, ignoreClass)[step.index];
}
if (!container) {
break;
}
}
return container;
}
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;
}
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 (let 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$1) {
container = child.childNodes[0];
} else {
container = child;
}
break;
}
}
}
return {
container,
offset
};
}
/**
* Creates a DOM range representing a CFI
* @param {document} _doc document referenced in the base
* @param {string} [ignoreClass]
* @return {Range}
*/
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 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());
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);
}
}
return range;
}
/**
* Check if a string is wrapped with "epubcfi()"
* @param {string} str
* @returns {boolean}
*/
isCfiString(str2) {
if (typeof str2 === "string" && str2.indexOf("epubcfi(") === 0 && str2[str2.length - 1] === ")") {
return true;
}
return false;
}
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]
*/
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;
}
}
}
class Hook {
constructor(context) {
this.context = context || this;
this.hooks = [];
}
/**
* Adds a function to be run before a hook completes
* @example this.content.register(function(){...});
*/
register() {
for (var i = 0; i < arguments.length; ++i) {
if (typeof arguments[i] === "function") {
this.hooks.push(arguments[i]);
} else {
for (var j = 0; j < arguments[i].length; ++j) {
this.hooks.push(arguments[i][j]);
}
}
}
}
/**
* Removes a function
* @example this.content.deregister(function(){...});
*/
deregister(func) {
let hook;
for (let i = 0; i < this.hooks.length; i++) {
hook = this.hooks[i];
if (hook === func) {
this.hooks.splice(i, 1);
break;
}
}
}
/**
* Triggers a hook to run all functions
* @example this.content.trigger(args).then(function(){...});
*/
trigger() {
var args = arguments;
var context = this.context;
var promises = [];
this.hooks.forEach(function(task) {
try {
var executing = task.apply(context, args);
} catch (err) {
console.log(err);
}
if (executing && typeof executing["then"] === "function") {
promises.push(executing);
}
});
return Promise.all(promises);
}
// Adds a function to be run before a hook completes
list() {
return this.hooks;
}
clear() {
return this.hooks = [];
}
}
function replaceBase(doc, section) {
var base;
var head;
var url = section.url;
var absolute = url.indexOf("://") > -1;
if (!doc) {
return;
}
head = qs(doc, "head");
base = qs(head, "base");
if (!base) {
base = doc.createElement("base");
head.insertBefore(base, head.firstChild);
}
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 = qs(doc, "head");
link = 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 = qs(doc, "head");
meta = 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);
}
}
function replaceLinks(contents, fn) {
var links = contents.querySelectorAll("a[href]");
if (!links.length) {
return;
}
var base = qs(contents.ownerDocument, "base");
var location = base ? base.getAttribute("href") : void 0;
var replaceLink = (function(link) {
var href = link.getAttribute("href");
if (href.indexOf("mailto:") === 0) {
return;
}
var absolute = href.indexOf("://") > -1;
if (absolute) {
link.setAttribute("target", "_blank");
} else {
var linkUrl;
try {
linkUrl = new Url(href, location);
} catch (error) {
}
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]) {
url = url.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
content = content.replace(new RegExp(url, "g"), replacements[i]);
}
});
return content;
}
function request(url, type2, withCredentials, headers) {
var supportsURL = typeof window != "undefined" ? window.URL : false;
var BLOB_RESPONSE = supportsURL ? "blob" : "arraybuffer";
var deferred = new defer();
var xhr = new XMLHttpRequest();
var xhrPrototype = XMLHttpRequest.prototype;
var header;
if (!("overrideMimeType" in xhrPrototype)) {
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 (type2 == "json") {
xhr.setRequestHeader("Accept", "application/json");
}
if (!type2) {
type2 = new Path(url).extension;
}
if (type2 == "blob") {
xhr.responseType = BLOB_RESPONSE;
}
if (isXml(type2)) {
xhr.overrideMimeType("text/xml");
}
if (type2 == "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 || this.status === 0 || responseXML) {
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 (isXml(type2)) {
r = parse(this.response, "text/xml");
} else if (type2 == "xhtml") {
r = parse(this.response, "application/xhtml+xml");
} else if (type2 == "html" || type2 == "htm") {
r = parse(this.response, "text/html");
} else if (type2 == "json") {
r = JSON.parse(this.response);
} else if (type2 == "blob") {
if (supportsURL) {
r = this.response;
} else {
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;
}
class Section {
constructor(item, hooks) {
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 Hook(this);
this.hooks.content = new Hook(this);
}
this.document = void 0;
this.contents = void 0;
this.output = void 0;
}
/**
* Load the section from its url
* @param {method} [_request] a request method to use for loading
* @return {document} a promise with the xml document
*/
load(_request) {
var request$1 = _request || this.request || request;
var loading = new defer();
var loaded = loading.promise;
if (this.contents) {
loading.resolve(this.contents);
} else {
request$1(this.url).then((function(xml) {
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
*/
base() {
return 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
*/
render(_request) {
var rendering = new defer();
var rendered = rendering.promise;
this.output;
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 = DOMParser$1;
} 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}
*/
find(_query) {
var section = this;
var matches = [];
var query = _query.toLowerCase();
var find2 = function(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) {
pos = text.indexOf(query, last + 1);
if (pos != -1) {
range = section.document.createRange();
range.setStart(node, pos);
range.setEnd(node, pos + query.length);
cfi = section.cfiFromRange(range);
if (node.textContent.length < limit) {
excerpt = node.textContent;
} else {
excerpt = node.textContent.substring(pos - limit / 2, pos + limit / 2);
excerpt = "..." + excerpt + "...";
}
matches.push({
cfi,
excerpt
});
}
last = pos;
}
};
sprint(section.document, function(node) {
find2(node);
});
return matches;
}
/**
* Search a string in multiple sequential Element of the section. If the document.createTreeWalker api is missed(eg: IE8), use `find` as a fallback.
* @param {string} _query The query string to search
* @param {int} maxSeqEle The maximum number of Element that are combined for search, default value is 5.
* @return {object[]} A list of matches, with form {cfi, excerpt}
*/
search(_query, maxSeqEle = 5) {
if (typeof document.createTreeWalker == "undefined") {
return this.find(_query);
}
let matches = [];
const excerptLimit = 150;
const section = this;
const query = _query.toLowerCase();
const search = function(nodeList2) {
const textWithCase = nodeList2.reduce((acc, current) => {
return acc + current.textContent;
}, "");
const text = textWithCase.toLowerCase();
const pos = text.indexOf(query);
if (pos != -1) {
const startNodeIndex = 0, endPos = pos + query.length;
let endNodeIndex = 0, l = 0;
if (pos < nodeList2[startNodeIndex].length) {
let cfi;
while (endNodeIndex < nodeList2.length - 1) {
l += nodeList2[endNodeIndex].length;
if (endPos <= l) {
break;
}
endNodeIndex += 1;
}
let startNode = nodeList2[startNodeIndex], endNode = nodeList2[endNodeIndex];
let range = section.document.createRange();
range.setStart(startNode, pos);
let beforeEndLengthCount = nodeList2.slice(0, endNodeIndex).reduce((acc, current) => {
return acc + current.textContent.length;
}, 0);
range.setEnd(endNode, beforeEndLengthCount > endPos ? endPos : endPos - beforeEndLengthCount);
cfi = section.cfiFromRange(range);
let excerpt = nodeList2.slice(0, endNodeIndex + 1).reduce((acc, current) => {
return acc + current.textContent;
}, "");
if (excerpt.length > excerptLimit) {
excerpt = excerpt.substring(pos - excerptLimit / 2, pos + excerptLimit / 2);
excerpt = "..." + excerpt + "...";
}
matches.push({
cfi,
excerpt
});
}
}
};
const treeWalker2 = document.createTreeWalker(section.document, NodeFilter.SHOW_TEXT, null, false);
let node, nodeList = [];
while (node = treeWalker2.nextNode()) {
nodeList.push(node);
if (nodeList.length == maxSeqEle) {
search(nodeList.slice(0, maxSeqEle));
nodeList = nodeList.slice(1, maxSeqEle);
}
}
if (nodeList.length > 0) {
search(nodeList);
}
return matches;
}
/**
* Reconciles the current chapters layout properties with
* the global layout properties.
* @param {object} globalLayout The global layout settings object, chapter properties string
* @return {object} layoutProperties Object with layout properties
*/
reconcileLayoutSettings(globalLayout) {
var settings = {
layout: globalLayout.layout,
spread: globalLayout.spread,
orientation: globalLayout.orientation
};
this.properties.forEach(function(prop) {
var rendition = prop.replace("rendition:", "");
var split2 = rendition.indexOf("-");
var property, value;
if (split2 != -1) {
property = rendition.slice(0, split2);
value = rendition.slice(split2 + 1);
settings[property] = value;
}
});
return settings;
}
/**
* Get a CFI from a Range in the Section
* @param {range} _range
* @return {string} cfi an EpubCFI string
*/
cfiFromRange(_range) {
return new EpubCFI(_range, this.cfiBase).toString();
}
/**
* Get a CFI from an Element in the Section
* @param {element} el
* @return {string} cfi an EpubCFI string
*/
cfiFromElement(el) {
return new EpubCFI(el, this.cfiBase).toString();
}
/**
* Unload the section document
*/
unload() {
this.document = void 0;
this.contents = void 0;
this.output = void 0;
}
destroy() {
this.unload();
this.hooks.serialize.clear();
this.hooks.content.clear();
this.hooks = void 0;
this.idref = void 0;
this.linear = void 0;
this.properties = void 0;
this.index = void 0;
this.href = void 0;
this.url = void 0;
this.next = void 0;
this.prev = void 0;
this.cfiBase = void 0;
}
}
class Spine {
constructor() {
this.spineItems = [];
this.spineByHref = {};
this.spineById = {};
this.hooks = {};
this.hooks.serialize = new Hook();
this.hooks.content = new Hook();
this.hooks.content.register(replaceBase);
this.hooks.content.register(replaceCanonical);
this.hooks.content.register(replaceMeta);
this.epubcfi = new EpubCFI();
this.loaded = false;
this.items = void 0;
this.manifest = void 0;
this.spineNodeIndex = void 0;
this.baseUrl = void 0;
this.length = void 0;
}
/**
* Unpack items from a opf into spine items
* @param {Packaging} _package
* @param {method} resolver URL resolver
* @param {method} canonical Resolve canonical url
*/
unpack(_package, resolver, canonical) {
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((item, index) => {
var manifestItem = this.manifest[item.idref];
var spineItem;
item.index = index;
item.cfiBase = this.epubcfi.generateChapterComponent(this.spineNodeIndex, item.index, item.id);
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() {
let prevIndex = item.index;
while (prevIndex > 0) {
let prev = this.get(prevIndex - 1);
if (prev && prev.linear) {
return prev;
}
prevIndex -= 1;
}
return;
}).bind(this);
item.next = (function() {
let nextIndex = item.index;
while (nextIndex < this.spineItems.length - 1) {
let 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 Section(item, this.hooks);
this.append(spineItem);
});
this.loaded = true;
}
/**
* Get an item from the spine
* @param {string|number} [target]
* @return {Section} section
* @example spine.get();
* @example spine.get(1);
* @example spine.get("chap1.html");
* @example spine.get("#id1234");
*/
get(target) {
var index = 0;
if (typeof target === "undefined") {
while (index < this.spineItems.length) {
let next = this.spineItems[index];
if (next && next.linear) {
break;
}
index += 1;
}
} else if (this.epubcfi.isCfiString(target)) {
let cfi = new EpubCFI(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") {
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
*/
append(section) {
var index = this.spineItems.length;
section.index = index;
this.spineItems.push(section);
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
*/
prepend(section) {
this.spineByHref[section.href] = 0;
this.spineById[section.idref] = 0;
this.spineItems.forEach(function(item, index) {
item.index = index;
});
return 0;
}
// insert(section, index) {
//
// };
/**
* Remove a Section from the Spine
* @private
* @param {Section} section
*/
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
*/
each() {
return this.spineItems.forEach.apply(this.spineItems, arguments);
}
/**
* Find the first Section in the Spine
* @return {Section} first section
*/
first() {
let index = 0;
do {
let next = this.get(index);
if (next && next.linear) {
return next;
}
index += 1;
} while (index < this.spineItems.length);
}
/**
* Find the last Section in the Spine
* @return {Section} last section
*/
last() {
let index = this.spineItems.length - 1;
do {
let prev = this.get(index);
if (prev && prev.linear) {
return prev;
}
index -= 1;
} while (index >= 0);
}
destroy() {
this.each((section) => section.destroy());
this.spineItems = void 0;
this.spineByHref = void 0;
this.spineById = void 0;
this.hooks.serialize.clear();
this.hooks.content.clear();
this.hooks = void 0;
this.epubcfi = void 0;
this.loaded = false;
this.items = void 0;
this.manifest = void 0;
this.spineNodeIndex = void 0;
this.baseUrl = void 0;
this.length = void 0;
}
}
class Queue {
constructor(context) {
this._q = [];
this.context = context;
this.tick = requestAnimationFrame$1;
this.running = false;
this.paused = false;
}
/**
* Add an item to the queue
* @return {Promise}
*/
enqueue() {
var deferred, promise;
var queued;
var task = [].shift.call(arguments);
var args = arguments;
if (!task) {
throw new Error("No Task Provided");
}
if (typeof task === "function") {
deferred = new defer();
promise = deferred.promise;
queued = {
"task": task,
"args": args,
//"context" : context,
"deferred": deferred,
"promise": promise
};
} else {
queued = {
"promise": task
};
}
this._q.push(queued);
if (this.paused == false && !this.running) {
this.run();
}
return queued.promise;
}
/**
* Run one item
* @return {Promise}
*/
dequeue() {
var inwait, task, result;
if (this._q.length && !this.paused) {
inwait = this._q.shift();
task = inwait.task;
if (task) {
result = task.apply(this.context, inwait.args);
if (result && typeof result["then"] === "function") {
return result.then((function() {
inwait.deferred.resolve.apply(this.context, arguments);
}).bind(this), (function() {
inwait.deferred.reject.apply(this.context, arguments);
}).bind(this));
} else {
inwait.deferred.resolve.apply(this.context, result);
return inwait.promise;
}
} else if (inwait.promise) {
return inwait.promise;
}
} else {
inwait = new defer();
inwait.deferred.resolve();
return inwait.promise;
}
}
// Run All Immediately
dump() {
while (this._q.length) {
this.dequeue();
}
}
/**
* Run all tasks sequentially, at convince
* @return {Promise}
*/
run() {
if (!this.running) {
this.running = true;
this.defered = new defer();
}
this.tick.call(window, () => {
if (this._q.length) {
this.dequeue().then((function() {
this.run();
}).bind(this));
} else {
this.defered.resolve();
this.running = void 0;
}
});
if (this.paused == true) {
this.paused = false;
}
return this.defered.promise;
}
/**
* Flush all, as quickly as possible
* @return {Promise}
*/
flush() {
if (this.running) {
return this.running;
}
if (this._q.length) {
this.running = this.dequeue().then((function() {
this.running = void 0;
return this.flush();
}).bind(this));
return this.running;
}
}
/**
* Clear all items in wait
*/
clear() {
this._q = [];
}
/**
* Get the number of tasks in the queue
* @return {number} tasks
*/
length() {
return this._q.length;
}
/**
* Pause a running queue
*/
pause() {
this.paused = true;
}
/**
* End the queue
*/
stop() {
this._q = [];
this.running = false;
this.paused = true;
}
}
const EPUBJS_VERSION = "0.3";
const DOM_EVENTS = ["keydown", "keyup", "keypressed", "mouseup", "mousedown", "mousemove", "click", "touchend", "touchstart", "touchmove"];
const 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",
REMOVED: "removed"
},
VIEWS: {
AXIS: "axis",
WRITING_MODE: "writingMode",
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"
},
ANNOTATION: {
ATTACH: "attach",
DETACH: "detach"
}
};
class Locations {
constructor(spine, request2, pause) {
this.spine = spine;
this.request = request2;
this.pause = pause || 100;
this.q = new Queue(this);
this.epubcfi = new EpubCFI();
this._locations = [];
this._locationsWords = [];
this.total = 0;
this.break = 150;
this._current = 0;
this._wordCounter = 0;
this.currentLocation = "";
this._currentCfi = "";
this.processingTimeout = void 0;
}
/**
* Load all of sections in the book to generate locations
* @param {int} chars how many chars to split on
* @return {Promise<Array<string>>} locations
*/
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;
}).bind(this));
}
createRange() {
return {
startContainer: void 0,
startOffset: void 0,
endContainer: void 0,
endOffset: void 0
};
}
process(section) {
return section.load(this.request).then((function(contents) {
var completed = new defer();
var locations = this.parse(contents, section.cfiBase);
this._locations = this._locations.concat(locations);
section.unload();
this.processingTimeout = setTimeout(() => completed.resolve(locations), this.pause);
return completed.promise;
}).bind(this));
}
parse(contents, cfiBase, chars) {
var locations = [];
var range;
var doc = contents.ownerDocument;
var body = qs(doc, "body");
var counter = 0;
var prev;
var _break = chars || this.break;
var parser = function(node) {
var len = node.length;
var dist;
var pos = 0;
if (node.textContent.trim().length === 0) {
return false;
}
if (counter == 0) {
range = this.createRange();
range.startContainer = node;
range.startOffset = 0;
}
dist = _break - counter;
if (dist > len) {
counter += len;
pos = len;
}
while (pos < len) {
dist = _break - counter;
if (counter === 0) {
pos += 1;
range = this.createRange();
range.startContainer = node;
range.startOffset = pos;
}
if (pos + dist >= len) {
counter += len - pos;
pos = len;
} else {
pos += dist;
range.endContainer = node;
range.endOffset = pos;
let cfi = new EpubCFI(range, cfiBase).toString();
locations.push(cfi);
counter = 0;
}
}
prev = node;
};
sprint(body, parser.bind(this));
if (range && range.startContainer && prev) {
range.endContainer = prev;
range.endOffset = prev.length;
let cfi = new EpubCFI(range, cfiBase).toString();
locations.push(cfi);
counter = 0;
}
return locations;
}
/**
* Load all of sections in the book to generate locations
* @param {string} startCfi start position
* @param {int} wordCount how many words to split on
* @param {int} count result count
* @return {object} locations
*/
generateFromWords(startCfi, wordCount, count) {
var start = startCfi ? new EpubCFI(startCfi) : void 0;
this.q.pause();
this._locationsWords = [];
this._wordCounter = 0;
this.spine.each((function(section) {
if (section.linear) {
if (start) {
if (section.index >= start.spinePos) {
this.q.enqueue(this.processWords.bind(this), section, wordCount, start, count);
}
} else {
this.q.enqueue(this.processWords.bind(this), section, wordCount, start, count);
}
}
}).bind(this));
return this.q.run().then((function() {
if (this._currentCfi) {
this.currentLocation = this._currentCfi;
}
return this._locationsWords;
}).bind(this));
}
processWords(section, wordCount, startCfi, count) {
if (count && this._locationsWords.length >= count) {
return Promise.resolve();
}
return section.load(this.request).then((function(contents) {
var completed = new defer();
var locations = this.parseWords(contents, section, wordCount, startCfi);
var remainingCount = count - this._locationsWords.length;
this._locationsWords = this._locationsWords.concat(locations.length >= count ? locations.slice(0, remainingCount) : locations);
section.unload();
this.processingTimeout = setTimeout(() => completed.resolve(locations), this.pause);
return completed.promise;
}).bind(this));
}
//http://stackoverflow.com/questions/18679576/counting-words-in-string
countWords(s) {
s = s.replace(/(^\s*)|(\s*$)/gi, "");
s = s.replace(/[ ]{2,}/gi, " ");
s = s.replace(/\n /, "\n");
return s.split(" ").length;
}
parseWords(contents, section, wordCount, startCfi) {
var cfiBase = section.cfiBase;
var locations = [];
var doc = contents.ownerDocument;
var body = qs(doc, "body");
var _break = wordCount;
var foundStartNode = startCfi ? startCfi.spinePos !== section.index : true;
var startNode;
if (startCfi && section.index === startCfi.spinePos) {
startNode = startCfi.findNode(startCfi.range ? startCfi.path.steps.concat(startCfi.start.steps) : startCfi.path.steps, contents.ownerDocument);
}
var parser = function(node) {
if (!foundStartNode) {
if (node === startNode) {
foundStartNode = true;
} else {
return false;
}
}
if (node.textContent.length < 10) {
if (node.textContent.trim().length === 0) {
return false;
}
}
var len = this.countWords(node.textContent);
var dist;
var pos = 0;
if (len === 0) {
return false;
}
dist = _break - this._wordCounter;
if (dist > len) {
this._wordCounter += len;
pos = len;
}
while (pos < len) {
dist = _break - this._wordCounter;
if (pos + dist >= len) {
this._wordCounter += len - pos;
pos = len;
} else {
pos += dist;
let cfi = new EpubCFI(node, cfiBase);
locations.push({ cfi: cfi.toString(), wordCount: this._wordCounter });
this._wordCounter = 0;
}
}
};
sprint(body, parser.bind(this));
return locations;
}
/**
* Get a location from an EpubCFI
* @param {EpubCFI} cfi
* @return {number}
*/
locationFromCfi(cfi) {
let loc;
if (EpubCFI.prototype.isCfiString(cfi)) {
cfi = new EpubCFI(cfi);
}
if (this._locations.length === 0) {
return -1;
}
loc = 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}
*/
percentageFromCfi(cfi) {
if (this._locations.length === 0) {
return null;
}
var loc = this.locationFromCfi(cfi);
return this.percentageFromLocation(loc);
}
/**
* Get a percentage position from a location index
* @param {number} location
* @return {number}
*/
percentageFromLocation(loc) {
if (!loc || !this.total) {
return 0;
}
return loc / this.total;
}
/**
* Get an EpubCFI from location index
* @param {number} loc
* @return {EpubCFI} cfi
*/
cfiFromLocation(loc) {
var cfi = -1;
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
*/
cfiFromPercentage(percentage) {
let loc;
if (percentage > 1) {
console.warn("Normalize cfiFromPercentage value to between 0 - 1");
}
if (percentage >= 1) {
let cfi = new EpubCFI(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
*/
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}
*/
save() {
return JSON.stringify(this._locations);
}
getCurrent() {
return this._current;
}
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(EVENTS.LOCATIONS.CHANGED, {
percentage: this.percentageFromLocation(loc)
});
}
/**
* Get the current location
*/
get currentLocation() {
return this._current;
}
/**
* Set the current location
*/
set currentLocation(curr) {
this.setCurrent(curr);
}
/**
* Locations length
*/
length() {
return this._locations.length;
}
destroy() {
this.spine = void 0;
this.request = void 0;
this.pause = void 0;
this.q.stop();
this.q = void 0;
this.epubcfi = void 0;
this._locations = void 0;
this.total = void 0;
this.break = void 0;
this._current = void 0;
this.currentLocation = void 0;
this._currentCfi = void 0;
clearTimeout(this.processingTimeout);
}
}
EventEmitter(Locations.prototype);
class Container {
constructor(containerDocument) {
this.packagePath = "";
this.directory = "";
this.encoding = "";
if (containerDocument) {
this.parse(containerDocument);
}
}
/**
* Parse the Container XML
* @param {document} containerDocument
*/
parse(containerDocument) {
var rootfile;
if (!containerDocument) {
throw new Error("Container File Not Found");
}
rootfile = qs(containerDocument, "rootfile");
if (!rootfile) {
throw new Error("No RootFile Found");
}
this.packagePath = rootfile.getAttribute("full-path");
this.directory = path$1.dirname(this.packagePath);
this.encoding = containerDocument.xmlEncoding;
}
destroy() {
this.packagePath = void 0;
this.directory = void 0;
this.encoding = void 0;
}
}
class Packaging {
constructor(packageDocument) {
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
*/
parse(packageDocument) {
var metadataNode, manifestNode, spineNode;
if (!packageDocument) {
throw new Error("Package File Not Found");
}
metadataNode = qs(packageDocument, "metadata");
if (!metadataNode) {
throw new Error("No Metadata Found");
}
manifestNode = qs(packageDocument, "manifest");
if (!manifestNode) {
throw new Error("No Manifest Found");
}
spineNode = 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 = indexOfElementNode(spineNode);
this.spine = this.parseSpine(spineNode, this.manifest);
this.uniqueIdentifier = this.findUniqueIdentifier(packageDocument);
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 {node} xml
* @return {object} metadata
*/
parseMetadata(xml) {
var metadata = {};
metadata.title = this.getElementText(xml, "title");
metadata.creator = this.getElementText(xml, "creator");
metadata.description = this.getElementText(xml, "description");
metadata.pubdate = this.getElementText(xml, "date");
metadata.publisher = this.getElementText(xml, "publisher");
metadata.identifier = this.getElementText(xml, "identifier");
metadata.language = this.getElementText(xml, "language");
metadata.rights = this.getElementText(xml, "rights");
metadata.modified_date = this.getPropertyText(xml, "dcterms:modified");
metadata.layout = this.getPropertyText(xml, "rendition:layout");
metadata.orientation = this.getPropertyText(xml, "rendition:orientation");
metadata.flow = this.getPropertyText(xml, "rendition:flow");
metadata.viewport = this.getPropertyText(xml, "rendition:viewport");
metadata.media_active_class = this.getPropertyText(xml, "media:active-class");
metadata.spread = this.getPropertyText(xml, "rendition:spread");
return metadata;
}
/**
* Parse Manifest
* @private
* @param {node} manifestXml
* @return {object} manifest
*/
parseManifest(manifestXml) {
var manifest = {};
var selected = qsa(manifestXml, "item");
var items = Array.prototype.slice.call(selected);
items.forEach(function(item) {
var id = item.getAttribute("id"), href = item.getAttribute("href") || "", type2 = item.getAttribute("media-type") || "", overlay = item.getAttribute("media-overlay") || "", properties = item.getAttribute("properties") || "";
manifest[id] = {
"href": href,
// "url" : href,
"type": type2,
"overlay": overlay,
"properties": properties.length ? properties.split(" ") : []
};
});
return manifest;
}
/**
* Parse Spine
* @private
* @param {node} spineXml
* @param {Packaging.manifest} manifest
* @return {object} spine
*/
parseSpine(spineXml, manifest) {
var spine = [];
var selected = qsa(spineXml, "itemref");
var items = Array.prototype.slice.call(selected);
items.forEach(function(item, index) {
var idref = item.getAttribute("idref");
var props = item.getAttribute("properties") || "";
var propArray = props.length ? props.split(" ") : [];
var itemref = {
"id": item.getAttribute("id"),
"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 Unique Identifier
* @private
* @param {node} packageXml
* @return {string} Unique Identifier text
*/
findUniqueIdentifier(packageXml) {
var uniqueIdentifierId = packageXml.documentElement.getAttribute("unique-identifier");
if (!uniqueIdentifierId) {
return "";
}
var identifier = packageXml.getElementById(uniqueIdentifierId);
if (!identifier) {
return "";
}
if (identifier.localName === "identifier" && identifier.namespaceURI === "http://purl.org/dc/elements/1.1/") {
return identifier.childNodes.length > 0 ? identifier.childNodes[0].nodeValue.trim() : "";
}
return "";
}
/**
* Find TOC NAV
* @private
* @param {element} manifestNode
* @return {string}
*/
findNavPath(manifestNode) {
var node = qsp(manifestNode, "item", { "properties": "nav" });
return node ? node.getAttribute("href") : false;
}
/**
* Find TOC NCX
* media-type="application/x-dtbncx+xml" href="toc.ncx"
* @private
* @param {element} manifestNode
* @param {element} spineNode
* @return {string}
*/
findNcxPath(manifestNode, spineNode) {
var node = qsp(manifestNode, "item", { "media-type": "application/x-dtbncx+xml" });
var tocId;
if (!node) {
tocId = spineNode.getAttribute("toc");
if (tocId) {
node = manifestNode.querySelector(`#${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
* @private
* @param {node} packageXml
* @return {string} href
*/
findCoverPath(packageXml) {
var pkg = qs(packageXml, "package");
pkg.getAttribute("version");
var node = qsp(packageXml, "item", { "properties": "cover-image" });
if (node)
return node.getAttribute("href");
var metaCover = qsp(packageXml, "meta", { "name": "cover" });
if (metaCover) {
var coverId = metaCover.getAttribute("content");
var cover = packageXml.getElementById(coverId);
return cover ? cover.getAttribute("href") : "";
} else {
return false;
}
}
/**
* Get text of a namespaced element
* @private
* @param {node} xml
* @param {string} tag
* @return {string} text
*/
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 {node} xml
* @param {string} property
* @return {string} text
*/
getPropertyText(xml, property) {
var el = qsp(xml, "meta", { "property": property });
if (el && el.childNodes.length) {
return el.childNodes[0].nodeValue;
}
return "";
}
/**
* Load JSON Manifest
* @param {document} packageDocument OPF XML
* @return {object} parsed package parts
*/
load(json) {
this.metadata = json.metadata;
let spine = json.readingOrder || json.spine;
this.spine = spine.map((item, index) => {
item.index = index;
item.linear = item.linear || "yes";
return item;
});
json.resources.forEach((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((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
};
}
destroy() {
this.manifest = void 0;
this.navPath = void 0;
this.ncxPath = void 0;
this.coverPath = void 0;
this.spineNodeIndex = void 0;
this.spine = void 0;
this.metadata = void 0;
}
}
class Navigation {
constructor(xml) {
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
*/
parse(xml) {
let isXml2 = xml.nodeType;
let html;
let ncx;
if (isXml2) {
html = qs(xml, "html");
ncx = qs(xml, "ncx");
}
if (!isXml2) {
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
*/
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} navItem
*/
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.getByIndex(target, index, this.toc);
}
/**
* Get an item from navigation subitems recursively by index
* @param {string} target
* @param {number} index
* @param {array} navItems
* @return {object} navItem
*/
getByIndex(target, index, navItems) {
if (navItems.length === 0) {
return;
}
const item = navItems[index];
if (item && (target === item.id || target === item.href)) {
return item;
} else {
let result;
for (let i = 0; i < navItems.length; ++i) {
result = this.getByIndex(target, index, navItems[i].subitems);
if (result) {
break;
}
}
return result;
}
}
/**
* Get a landmark by type
* List of types: https://idpf.github.io/epub-vocabs/structure/
* @param {string} type
* @return {object} landmarkItem
*/
landmark(type2) {
var index;
if (!type2) {
return this.landmarks;
}
index = this.landmarksByType[type2];
return this.landmarks[index];
}
/**
* Parse toc from a Epub > 3.0 Nav
* @private
* @param {document} navHtml
* @return {array} navigation list
*/
parseNav(navHtml) {
var navElement = querySelectorByType(navHtml, "nav", "toc");
var list = [];
if (!navElement)
return list;
let navList = filterChildren(navElement, "ol", true);
if (!navList)
return list;
list = this.parseNavList(navList);
return list;
}
/**
* Parses lists in the toc
* @param {document} navListHtml
* @param {string} parent id
* @return {array} navigation list
*/
parseNavList(navListHtml, parent2) {
const result = [];
if (!navListHtml)
return result;
if (!navListHtml.children)
return result;
for (let i = 0; i < navListHtml.children.length; i++) {
const item = this.navItem(navListHtml.children[i], parent2);
if (item) {
result.push(item);
}
}
return result;
}
/**
* Create a navItem
* @private
* @param {element} item
* @return {object} navItem
*/
navItem(item, parent2) {
let id = item.getAttribute("id") || void 0;
let content = filterChildren(item, "a", true) || filterChildren(item, "span", true);
if (!content) {
return;
}
let src = content.getAttribute("href") || "";
if (!id) {
id = src;
}
let text = content.textContent || "";
let subitems = [];
let nested = filterChildren(item, "ol", true);
if (nested) {
subitems = this.parseNavList(nested, id);
}
return {
"id": id,
"href": src,
"label": text,
"subitems": subitems,
"parent": parent2
};
}
/**
* Parse landmarks from a Epub > 3.0 Nav
* @private
* @param {document} navHtml
* @return {array} landmarks list
*/
parseLandmarks(navHtml) {
var navElement = querySelectorByType(navHtml, "nav", "landmarks");
var navItems = navElement ? 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
*/
landmarkItem(item) {
let content = filterChildren(item, "a", true);
if (!content) {
return;
}
let type2 = content.getAttributeNS("http://www.idpf.org/2007/ops", "type") || void 0;
let href = content.getAttribute("href") || "";
let text = content.textContent || "";
return {
"href": href,
"label": text,
"type": type2
};
}
/**
* Parse from a Epub > 3.0 NC
* @private
* @param {document} navHtml
* @return {array} navigation list
*/
parseNcx(tocXml) {
var navPoints = qsa(tocXml, "navPoint");
var length = navPoints.length;
var i;
var toc = {};
var list = [];
var item, parent2;
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 {
parent2 = toc[item.parent];
parent2.subitems.push(item);
}
}
return list;
}
/**
* Create a ncxItem
* @private
* @param {element} item
* @return {object} ncxItem
*/
ncxItem(item) {
var id = item.getAttribute("id") || false, content = qs(item, "content"), src = content.getAttribute("src"), navLabel = qs(item, "navLabel"), text = navLabel.textContent ? navLabel.textContent : "", subitems = [], parentNode = item.parentNode, parent2;
if (parentNode && (parentNode.nodeName === "navPoint" || parentNode.nodeName.split(":").slice(-1)[0] === "navPoint")) {
parent2 = parentNode.getAttribute("id");
}
return {
"id": id,
"href": src,
"label": text,
"subitems": subitems,
"parent": parent2
};
}
/**
* Load Spine Items
* @param {object} json the items to be loaded
* @return {Array} navItems
*/
load(json) {
return json.map((item) => {
item.label = item.title;
item.subitems = item.children ? this.load(item.children) : [];
return item;
});
}
/**
* forEach pass through
* @param {Function} fn function to run on each item
* @return {method} forEach loop
*/
forEach(fn) {
return this.toc.forEach(fn);
}
}
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 type2, subtype, val, index, mimeTypes2 = {};
for (type2 in table) {
if (table.hasOwnProperty(type2)) {
for (subtype in table[type2]) {
if (table[type2].hasOwnProperty(subtype)) {
val = table[type2][subtype];
if (typeof val == "string") {
mimeTypes2[val] = type2 + "/" + subtype;
} else {
for (index = 0; index < val.length; index++) {
mimeTypes2[val[index]] = type2 + "/" + subtype;
}
}
}
}
}
}
return mimeTypes2;
}();
var defaultValue = "text/plain";
function lookup(filename) {
return filename && mimeTypes[filename.split(".").pop().toLowerCase()] || defaultValue;
}
const mime = { lookup };
class Resources {
constructor(manifest, options) {
this.settings = {
replacements: options && options.replacements || "base64",
archive: options && options.archive,
resolver: options && options.resolver,
request: options && options.request
};
this.process(manifest);
}
/**
* Process resources
* @param {Manifest} manifest
*/
process(manifest) {
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
*/
split() {
this.html = this.resources.filter(function(item) {
if (item.type === "application/xhtml+xml" || item.type === "text/html") {
return true;
}
});
this.assets = this.resources.filter(function(item) {
if (item.type !== "application/xhtml+xml" && item.type !== "text/html") {
return true;
}
});
this.css = this.resources.filter(function(item) {
if (item.type === "text/css") {
return true;
}
});
}
/**
* Convert split resources into Urls
* @private
*/
splitUrls() {
this.urls = this.assets.map((function(item) {
return item.href;
}).bind(this));
this.cssUrls = this.css.map(function(item) {
return item.href;
});
}
/**
* Create a url to a resource
* @param {string} url
* @return {Promise<string>} Promise resolves with url string
*/
createUrl(url) {
var parsedUrl = new Url(url);
var mimeType = mime.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((blob) => {
return blob2base64(blob);
}).then((blob) => {
return createBase64Url(blob, mimeType);
});
} else {
return this.settings.request(url, "blob").then((blob) => {
return createBlobUrl(blob, mimeType);
});
}
}
}
/**
* Create blob urls for all the assets
* @return {Promise} returns replacement urls
*/
replacements() {
if (this.settings.replacements === "none") {
return new Promise((function(resolve) {
resolve(this.urls);
}).bind(this));
}
var replacements = this.urls.map((url) => {
var absolute = this.settings.resolver(url);
return this.createUrl(absolute).catch((err) => {
console.error(err);
return null;
});
});
return Promise.all(replacements).then((replacementUrls) => {
this.replacementUrls = replacementUrls.filter((url) => {
return typeof url === "string";
});
return replacementUrls;
});
}
/**
* Replace URLs in CSS resources
* @private
* @param {Archive} [archive]
* @param {method} [resolver]
* @return {Promise}
*/
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) {
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
*/
createCssFile(href) {
var newUrl;
if (path$1.isAbsolute(href)) {
return new Promise(function(resolve) {
resolve();
});
}
var absolute = this.settings.resolver(href);
var textResponse;
if (this.settings.archive) {
textResponse = this.settings.archive.getText(absolute);
} else {
textResponse = this.settings.request(absolute, "text");
}
var relUrls = this.urls.map((assetHref) => {
var resolved = this.settings.resolver(assetHref);
var relative = new Path(absolute).relative(resolved);
return relative;
});
if (!textResponse) {
return new Promise(function(resolve) {
resolve();
});
}
return textResponse.then((text) => {
text = substitute(text, relUrls, this.replacementUrls);
if (this.settings.replacements === "base64") {
newUrl = createBase64Url(text, "text/css");
} else {
newUrl = createBlobUrl(text, "text/css");
}
return newUrl;
}, (err) => {
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
*/
relativeTo(absolute, resolver) {
resolver = resolver || this.settings.resolver;
return this.urls.map((function(href) {
var resolved = resolver(href);
var relative = new Path(absolute).relative(resolved);
return relative;
}).bind(this));
}
/**
* Get a URL for a resource
* @param {string} path
* @return {string} url
*/
get(path2) {
var indexInUrls = this.urls.indexOf(path2);
if (indexInUrls === -1) {
return;
}
if (this.replacementUrls.length) {
return new Promise((function(resolve, reject) {
resolve(this.replacementUrls[indexInUrls]);
}).bind(this));
} else {
return this.createUrl(path2);
}
}
/**
* 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
*/
substitute(content, url) {
var relUrls;
if (url) {
relUrls = this.relativeTo(url);
} else {
relUrls = this.urls;
}
return substitute(content, relUrls, this.replacementUrls);
}
destroy() {
this.settings = void 0;
this.manifest = void 0;
this.resources = void 0;
this.replacementUrls = void 0;
this.html = void 0;
this.assets = void 0;
this.css = void 0;
this.urls = void 0;
this.cssUrls = void 0;
}
}
class PageList {
constructor(xml) {
this.pages = [];
this.locations = [];
this.epubcfi = new EpubCFI();
this.firstPage = 0;
this.lastPage = 0;
this.totalPages = 0;
this.toc = void 0;
this.ncx = void 0;
if (xml) {
this.pageList = this.parse(xml);
}
if (this.pageList && this.pageList.length) {
this.process(this.pageList);
}
}
/**
* Parse PageList Xml
* @param {document} xml
*/
parse(xml) {
var html = qs(xml, "html");
var ncx = qs(xml, "ncx");
if (html) {
return this.parseNav(xml);
} else if (ncx) {
return this.parseNcx(xml);
}
}
/**
* Parse a Nav PageList
* @private
* @param {node} navHtml
* @return {PageList.item[]} list
*/
parseNav(navHtml) {
var navElement = querySelectorByType(navHtml, "nav", "page-list");
var navItems = navElement ? 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;
}
parseNcx(navXml) {
var list = [];
var i = 0;
var item;
var pageList;
var pageTargets;
var length = 0;
pageList = qs(navXml, "pageList");
if (!pageList)
return list;
pageTargets = qsa(pageList, "pageTarget");
length = pageTargets.length;
if (!pageTargets || pageTargets.length === 0) {
return list;
}
for (i = 0; i < length; ++i) {
item = this.ncxItem(pageTargets[i]);
list.push(item);
}
return list;
}
ncxItem(item) {
var navLabel = qs(item, "navLabel");
var navLabelText = qs(navLabel, "text");
var pageText = navLabelText.textContent;
var content = qs(item, "content");
var href = content.getAttribute("src");
var page = parseInt(pageText, 10);
return {
"href": href,
"page": page
};
}
/**
* Page List Item
* @private
* @param {node} item
* @return {object} pageListItem
*/
item(item) {
var content = qs(item, "a"), href = content.getAttribute("href") || "", text = content.textContent || "", page = parseInt(text), isCfi = href.indexOf("epubcfi"), split2, packageUrl, cfi;
if (isCfi != -1) {
split2 = href.split("#");
packageUrl = split2[0];
cfi = split2.length > 1 ? split2[1] : false;
return {
"cfi": cfi,
"href": href,
"packageUrl": packageUrl,
"page": page
};
} else {
return {
"href": href,
"page": page
};
}
}
/**
* Process pageList items
* @private
* @param {array} pageList
*/
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 {number} page
*/
pageFromCfi(cfi) {
var pg = -1;
if (this.locations.length === 0) {
return -1;
}
var index = indexOfSorted(cfi, this.locations, this.epubcfi.compare);
if (index != -1) {
pg = this.pages[index];
} else {
index = locationOf(cfi, this.locations, this.epubcfi.compare);
pg = index - 1 >= 0 ? this.pages[index - 1] : this.pages[0];
if (pg !== void 0)
;
else {
pg = -1;
}
}
return pg;
}
/**
* Get an EpubCFI from a Page List Item
* @param {string | number} pg
* @return {string} cfi
*/
cfiFromPage(pg) {
var cfi = -1;
if (typeof pg != "number") {
pg = parseInt(pg);
}
var index = this.pages.indexOf(pg);
if (index != -1) {
cfi = this.locations[index];
}
return cfi;
}
/**
* Get a Page from Book percentage
* @param {number} percent
* @return {number} page
*/
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 {number} pg the page
* @return {number} percentage
*/
percentageFromPage(pg) {
var percentage = (pg - this.firstPage) / this.totalPages;
return Math.round(percentage * 1e3) / 1e3;
}
/**
* Returns a value between 0 - 1 corresponding to the location of a cfi
* @param {string} cfi EpubCFI String
* @return {number} percentage
*/
percentageFromCfi(cfi) {
var pg = this.pageFromCfi(cfi);
var percentage = this.percentageFromPage(pg);
return percentage;
}
/**
* Destroy
*/
destroy() {
this.pages = void 0;
this.locations = void 0;
this.epubcfi = void 0;
this.pageList = void 0;
this.toc = void 0;
this.ncx = void 0;
}
}
class Layout {
constructor(settings) {
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
* @return {string} simplified flow
*/
flow(flow) {
if (typeof flow != "undefined") {
if (flow === "scrolled" || flow === "scrolled-continuous" || flow === "scrolled-doc") {
this._flow = "scrolled";
} else {
this._flow = "paginated";
}
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 "none" | "always" | "auto"
* @param {number} min integer in pixels
* @return {boolean} spread true | false
*/
spread(spread, min) {
if (spread) {
this._spread = spread === "none" ? false : true;
this.update({ spread: this._spread });
}
if (min >= 0) {
this._minSpreadWidth = min;
}
return this._spread;
}
/**
* Calculate the dimensions of the pagination
* @param {number} _width width of the rendering
* @param {number} _height height of the rendering
* @param {number} _gap width of the gap between columns
*/
calculate(_width, _height, _gap) {
var divisor = 1;
var gap = _gap || 0;
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;
}
if (divisor > 1) {
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.update({
width,
height,
spreadWidth,
pageWidth,
delta,
columnWidth,
gap,
divisor
});
}
/**
* Apply Css to a Document
* @param {Contents} contents
* @return {Promise}
*/
format(contents, section, axis) {
var formating;
if (this.name === "pre-paginated") {
formating = contents.fit(this.columnWidth, this.height, section);
} else if (this._flow === "paginated") {
formating = contents.columns(this.width, this.height, this.columnWidth, this.gap, this.settings.direction);
} else if (axis && axis === "horizontal") {
formating = contents.size(null, this.height);
} else {
formating = contents.size(this.width, null);
}
return formating;
}
/**
* Count number of pages
* @param {number} totalLength
* @param {number} pageLength
* @return {{spreads: Number, pages: Number}}
*/
count(totalLength, pageLength) {
let spreads, pages;
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 {
pageLength = pageLength || this.height;
spreads = Math.ceil(totalLength / pageLength);
pages = spreads;
}
return {
spreads,
pages
};
}
/**
* Update props that have changed
* @private
* @param {object} props
*/
update(props) {
Object.keys(props).forEach((propName) => {
if (this.props[propName] === props[propName]) {
delete props[propName];
}
});
if (Object.keys(props).length > 0) {
let newProps = extend(this.props, props);
this.emit(EVENTS.LAYOUT.UPDATED, newProps, props);
}
}
}
EventEmitter(Layout.prototype);
class Themes {
constructor(rendition) {
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 | Array<object> | string}
* @example themes.register("light", "http://example.com/light.css")
* @example themes.register("light", { "body": { "color": "purple"}})
* @example themes.register({ "light" : {...}, "dark" : {...}})
*/
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"}})
*/
default(theme) {
if (!theme) {
return;
}
if (typeof theme === "string") {
return this.registerUrl("default", theme);
}
if (typeof theme === "object") {
return this.registerRules("default", theme);
}
}
/**
* Register themes object
* @param {object} themes
*/
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]);
}
}
}
}
/**
* Register a theme by passing its css as string
* @param {string} name
* @param {string} css
*/
registerCss(name, css) {
this._themes[name] = { "serialized": css };
if (this._injected[name] || name == "default") {
this.update(name);
}
}
/**
* Register a url
* @param {string} name
* @param {string} input
*/
registerUrl(name, input) {
var url = new Url(input);
this._themes[name] = { "url": url.toString() };
if (this._injected[name] || name == "default") {
this.update(name);
}
}
/**
* Register rule
* @param {string} name
* @param {object} rules
*/
registerRules(name, rules) {
this._themes[name] = { "rules": rules };
if (this._injected[name] || name == "default") {
this.update(name);
}
}
/**
* Select a theme
* @param {string} name
*/
select(name) {
var prev = this._current;
var contents;
this._current = name;
this.update(name);
contents = this.rendition.getContents();
contents.forEach((content) => {
content.removeClass(prev);
content.addClass(name);
});
}
/**
* Update a theme
* @param {string} name
*/
update(name) {
var contents = this.rendition.getContents();
contents.forEach((content) => {
this.add(name, content);
});
}
/**
* Inject all themes into contents
* @param {Contents} contents
*/
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);
}
}
/**
* Add Theme to contents
* @param {string} name
* @param {Contents} contents
*/
add(name, contents) {
var theme = this._themes[name];
if (!theme || !contents) {
return;
}
if (theme.url) {
contents.addStylesheet(theme.url);
} else if (theme.serialized) {
contents.addStylesheetCss(theme.serialized, name);
theme.injected = true;
} else if (theme.rules) {
contents.addStylesheetRules(theme.rules, name);
theme.injected = true;
}
}
/**
* Add override
* @param {string} name
* @param {string} value
* @param {boolean} priority
*/
override(name, value, priority) {
var contents = this.rendition.getContents();
this._overrides[name] = {
value,
priority: priority === true
};
contents.forEach((content) => {
content.css(name, this._overrides[name].value, this._overrides[name].priority);
});
}
removeOverride(name) {
var contents = this.rendition.getContents();
delete this._overrides[name];
contents.forEach((content) => {
content.css(name);
});
}
/**
* Add all overrides
* @param {Content} content
*/
overrides(contents) {
var overrides = this._overrides;
for (var rule in overrides) {
if (overrides.hasOwnProperty(rule)) {
contents.css(rule, overrides[rule].value, overrides[rule].priority);
}
}
}
/**
* Adjust the font size of a rendition
* @param {number} size
*/
fontSize(size) {
this.override("font-size", size);
}
/**
* Adjust the font-family of a rendition
* @param {string} f
*/
font(f) {
this.override("font-family", f, true);
}
destroy() {
this.rendition = void 0;
this._themes = void 0;
this._overrides = void 0;
this._current = void 0;
this._injected = void 0;
}
}
class Mapping {
constructor(layout, direction, axis, dev = false) {
this.layout = layout;
this.horizontal = axis === "horizontal" ? true : false;
this.direction = direction || "ltr";
this._dev = dev;
}
/**
* Find CFI pairs for entire section at once
*/
section(view) {
var ranges = this.findRanges(view);
var map = this.rangeListToCfiList(view.section.cfiBase, ranges);
return map;
}
/**
* Find CFI pairs for a page
* @param {Contents} contents Contents from view
* @param {string} cfiBase string of the base for a cfi
* @param {number} start position to start at
* @param {number} end position to end at
*/
page(contents, cfiBase, start, end) {
var root2 = contents && contents.document ? contents.document.body : false;
var result;
if (!root2) {
return;
}
result = this.rangePairToCfiPair(cfiBase, {
start: this.findStart(root2, start, end),
end: this.findEnd(root2, start, end)
});
if (this._dev === true) {
let doc = contents.document;
let startRange = new EpubCFI(result.start).toRange(doc);
let endRange = new EpubCFI(result.end).toRange(doc);
let selection = doc.defaultView.getSelection();
let r = doc.createRange();
selection.removeAllRanges();
r.setStart(startRange.startContainer, startRange.startOffset);
r.setEnd(endRange.endContainer, endRange.endOffset);
selection.addRange(r);
}
return result;
}
/**
* Walk a node, preforming a function on each node it finds
* @private
* @param {Node} root Node to walkToNode
* @param {function} func walk function
* @return {*} returns the result of the walk function
*/
walk(root2, func) {
if (root2 && root2.nodeType === Node.TEXT_NODE) {
return;
}
var filter = {
acceptNode: function(node2) {
if (node2.data.trim().length > 0) {
return NodeFilter.FILTER_ACCEPT;
} else {
return NodeFilter.FILTER_REJECT;
}
}
};
var safeFilter = filter.acceptNode;
safeFilter.acceptNode = filter.acceptNode;
var treeWalker2 = document.createTreeWalker(root2, NodeFilter.SHOW_TEXT, safeFilter, false);
var node;
var result;
while (node = treeWalker2.nextNode()) {
result = func(node);
if (result)
break;
}
return result;
}
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;
}
/**
* Find Start Range
* @private
* @param {Node} root root node
* @param {number} start position to start at
* @param {number} end position to end at
* @return {Range}
*/
findStart(root2, start, end) {
var stack = [root2];
var $el;
var found;
var $prev = root2;
while (stack.length) {
$el = stack.shift();
found = this.walk($el, (node) => {
var left, right, top, bottom;
var elPos;
elPos = nodeBounds(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 this.findTextStartRange($prev, start, end);
}
/**
* Find End Range
* @private
* @param {Node} root root node
* @param {number} start position to start at
* @param {number} end position to end at
* @return {Range}
*/
findEnd(root2, start, end) {
var stack = [root2];
var $el;
var $prev = root2;
var found;
while (stack.length) {
$el = stack.shift();
found = this.walk($el, (node) => {
var left, right, top, bottom;
var elPos;
elPos = nodeBounds(node);
if (this.horizontal && this.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 (this.horizontal && this.direction === "rtl") {
left = Math.round(this.horizontal ? elPos.left : elPos.top);
right = Math.round(this.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);
}
}
return this.findTextEndRange($prev, start, end);
}
/**
* Find Text Start Range
* @private
* @param {Node} root root node
* @param {number} start position to start at
* @param {number} end position to end at
* @return {Range}
*/
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;
}
}
}
return ranges[0];
}
/**
* Find Text End Range
* @private
* @param {Node} root root node
* @param {number} start position to start at
* @param {number} end position to end at
* @return {Range}
*/
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;
}
return ranges[ranges.length - 1];
}
/**
* Split up a text node into ranges for each word
* @private
* @param {Node} root root node
* @param {string} [_splitter] what to split on
* @return {Range[]}
*/
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;
}
/**
* Turn a pair of ranges into a pair of CFIs
* @private
* @param {string} cfiBase base string for an EpubCFI
* @param {object} rangePair { start: Range, end: Range }
* @return {object} { start: "epubcfi(...)", end: "epubcfi(...)" }
*/
rangePairToCfiPair(cfiBase, rangePair) {
var startRange = rangePair.start;
var endRange = rangePair.end;
startRange.collapse(true);
endRange.collapse(false);
let startCfi = new EpubCFI(startRange, cfiBase).toString();
let endCfi = new EpubCFI(endRange, cfiBase).toString();
return {
start: startCfi,
end: endCfi
};
}
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;
}
/**
* Set the axis for mapping
* @param {string} axis horizontal | vertical
* @return {boolean} is it horizontal?
*/
axis(axis) {
if (axis) {
this.horizontal = axis === "horizontal" ? true : false;
}
return this.horizontal;
}
}
const hasNavigator = typeof navigator !== "undefined";
const isChrome = hasNavigator && /Chrome/.test(navigator.userAgent);
const isWebkit = hasNavigator && !isChrome && /AppleWebKit/.test(navigator.userAgent);
const ELEMENT_NODE = 1;
class Contents {
constructor(doc, content, cfiBase, sectionIndex) {
this.epubcfi = new EpubCFI();
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", EPUBJS_VERSION);
this.called = 0;
this.active = true;
this.listeners();
}
/**
* Get DOM events that are listened for and passed along
*/
static get listenedEvents() {
return DOM_EVENTS;
}
/**
* Get or Set width
* @param {number} [w]
* @returns {number} width
*/
width(w) {
var frame = this.content;
if (w && isNumber(w)) {
w = w + "px";
}
if (w) {
frame.style.width = w;
}
return parseInt(this.window.getComputedStyle(frame)["width"]);
}
/**
* Get or Set height
* @param {number} [h]
* @returns {number} height
*/
height(h) {
var frame = this.content;
if (h && isNumber(h)) {
h = h + "px";
}
if (h) {
frame.style.height = h;
}
return parseInt(this.window.getComputedStyle(frame)["height"]);
}
/**
* Get or Set width of the contents
* @param {number} [w]
* @returns {number} width
*/
contentWidth(w) {
var content = this.content || this.document.body;
if (w && isNumber(w)) {
w = w + "px";
}
if (w) {
content.style.width = w;
}
return parseInt(this.window.getComputedStyle(content)["width"]);
}
/**
* Get or Set height of the contents
* @param {number} [h]
* @returns {number} height
*/
contentHeight(h) {
var content = this.content || this.document.body;
if (h && isNumber(h)) {
h = h + "px";
}
if (h) {
content.style.height = h;
}
return parseInt(this.window.getComputedStyle(content)["height"]);
}
/**
* Get the width of the text using Range
* @returns {number} width
*/
textWidth() {
let rect;
let width;
let range = this.document.createRange();
let content = this.content || this.document.body;
let border = borders(content);
range.selectNodeContents(content);
rect = range.getBoundingClientRect();
width = rect.width;
if (border && border.width) {
width += border.width;
}
return Math.round(width);
}
/**
* Get the height of the text using Range
* @returns {number} height
*/
textHeight() {
let rect;
let height;
let range = this.document.createRange();
let content = this.content || this.document.body;
range.selectNodeContents(content);
rect = range.getBoundingClientRect();
height = rect.bottom;
return Math.round(height);
}
/**
* Get documentElement scrollWidth
* @returns {number} width
*/
scrollWidth() {
var width = this.documentElement.scrollWidth;
return width;
}
/**
* Get documentElement scrollHeight
* @returns {number} height
*/
scrollHeight() {
var height = this.documentElement.scrollHeight;
return height;
}
/**
* Set overflow css style of the contents
* @param {string} [overflow]
*/
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]
*/
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]
*/
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"
*/
css(property, value, priority) {
var content = this.content || this.document.body;
if (value) {
content.style.setProperty(property, value, priority ? "important" : "");
} else {
content.style.removeProperty(property);
}
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]
*/
viewport(options) {
var $viewport = this.document.querySelector("meta[name='viewport']");
var parsed = {
"width": void 0,
"height": void 0,
"scale": void 0,
"minimum": void 0,
"maximum": void 0,
"scalable": void 0
};
var newContent = [];
var settings = {};
if ($viewport && $viewport.hasAttribute("content")) {
let content = $viewport.getAttribute("content");
let _width = content.match(/width\s*=\s*([^,]*)/);
let _height = content.match(/height\s*=\s*([^,]*)/);
let _scale = content.match(/initial-scale\s*=\s*([^,]*)/);
let _minimum = content.match(/minimum-scale\s*=\s*([^,]*)/);
let _maximum = content.match(/maximum-scale\s*=\s*([^,]*)/);
let _scalable = content.match(/user-scalable\s*=\s*([^,]*)/);
if (_width && _width.length && typeof _width[1] !== "undefined") {
parsed.width = _width[1];
}
if (_height && _height.length && typeof _height[1] !== "undefined") {
parsed.height = _height[1];
}
if (_scale && _scale.length && typeof _scale[1] !== "undefined") {
parsed.scale = _scale[1];
}
if (_minimum && _minimum.length && typeof _minimum[1] !== "undefined") {
parsed.minimum = _minimum[1];
}
if (_maximum && _maximum.length && typeof _maximum[1] !== "undefined") {
parsed.maximum = _maximum[1];
}
if (_scalable && _scalable.length && typeof _scalable[1] !== "undefined") {
parsed.scalable = _scalable[1];
}
}
settings = 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
*/
expand() {
this.emit(EVENTS.CONTENTS.EXPAND);
}
/**
* Add DOM listeners
* @private
*/
listeners() {
this.imageLoadListeners();
this.mediaQueryListeners();
this.addEventListeners();
this.addSelectionListeners();
if (typeof ResizeObserver === "undefined") {
this.resizeListeners();
this.visibilityListeners();
} else {
this.resizeObservers();
}
this.linksHandler();
}
/**
* Remove DOM listeners
* @private
*/
removeListeners() {
this.removeEventListeners();
this.removeSelectionListeners();
if (this.observer) {
this.observer.disconnect();
}
clearTimeout(this.expanding);
}
/**
* Check if size of contents has changed and
* emit 'resize' event if it has.
* @private
*/
resizeCheck() {
let width = this.textWidth();
let height = this.textHeight();
if (width != this._size.width || height != this._size.height) {
this._size = {
width,
height
};
this.onResize && this.onResize(this._size);
this.emit(EVENTS.CONTENTS.RESIZE, this._size);
}
}
/**
* Poll for resize detection
* @private
*/
resizeListeners() {
clearTimeout(this.expanding);
requestAnimationFrame(this.resizeCheck.bind(this));
this.expanding = setTimeout(this.resizeListeners.bind(this), 350);
}
/**
* Listen for visibility of tab to change
* @private
*/
visibilityListeners() {
document.addEventListener("visibilitychange", () => {
if (document.visibilityState === "visible" && this.active === false) {
this.active = true;
this.resizeListeners();
} else {
this.active = false;
clearTimeout(this.expanding);
}
});
}
/**
* Use css transitions to detect resize
* @private
*/
transitionListeners() {
let 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._resizeCheck = this.resizeCheck.bind(this);
this.document.addEventListener("transitionend", this._resizeCheck);
}
/**
* 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
*/
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;
try {
rules = sheets[i].cssRules;
} catch (e) {
return;
}
if (!rules)
return;
for (var j = 0; j < rules.length; j += 1) {
if (rules[j].media) {
var mql = this.window.matchMedia(rules[j].media.mediaText);
mql.addListener(mediaChangeHandler);
}
}
}
}
/**
* Use ResizeObserver to listen for changes in the DOM and check for resize
* @private
*/
resizeObservers() {
this.observer = new ResizeObserver((e) => {
requestAnimationFrame(this.resizeCheck.bind(this));
});
this.observer.observe(this.document.documentElement);
}
/**
* Use MutationObserver to listen for changes in the DOM and check for resize
* @private
*/
mutationObservers() {
this.observer = new MutationObserver((mutations) => {
this.resizeCheck();
});
let config = { attributes: true, childList: true, characterData: true, subtree: true };
this.observer.observe(this.document, config);
}
/**
* Test if images are loaded or add listener for when they load
* @private
*/
imageLoadListeners() {
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
*/
fontLoadListeners() {
if (!this.document || !this.document.fonts) {
return;
}
this.document.fonts.ready.then((function() {
this.resizeCheck();
}).bind(this));
}
/**
* Get the documentElement
* @returns {element} documentElement
*/
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 }
*/
locationOf(target, ignoreClass) {
var position2;
var targetPos = { "left": 0, "top": 0 };
if (!this.document)
return targetPos;
if (this.epubcfi.isCfiString(target)) {
let range = new EpubCFI(target).toRange(this.document, ignoreClass);
if (range) {
try {
if (!range.endContainer || range.startContainer == range.endContainer && range.startOffset == range.endOffset) {
let pos = range.startContainer.textContent.indexOf(" ", range.startOffset);
if (pos == -1) {
pos = range.startContainer.textContent.length;
}
range.setEnd(range.startContainer, pos);
}
} catch (e) {
console.error("setting end offset to start container length failed", e);
}
if (range.startContainer.nodeType === Node.ELEMENT_NODE) {
position2 = range.startContainer.getBoundingClientRect();
targetPos.left = position2.left;
targetPos.top = position2.top;
} else {
if (isWebkit) {
let container = range.startContainer;
let newRange = new Range();
try {
if (container.nodeType === ELEMENT_NODE) {
position2 = container.getBoundingClientRect();
} else if (range.startOffset + 2 < container.length) {
newRange.setStart(container, range.startOffset);
newRange.setEnd(container, range.startOffset + 2);
position2 = newRange.getBoundingClientRect();
} else if (range.startOffset - 2 > 0) {
newRange.setStart(container, range.startOffset - 2);
newRange.setEnd(container, range.startOffset);
position2 = newRange.getBoundingClientRect();
} else {
position2 = container.parentNode.getBoundingClientRect();
}
} catch (e) {
console.error(e, e.stack);
}
} else {
position2 = range.getBoundingClientRect();
}
}
}
} else if (typeof target === "string" && target.indexOf("#") > -1) {
let id = target.substring(target.indexOf("#") + 1);
let el = this.document.getElementById(id);
if (el) {
if (isWebkit) {
let newRange = new Range();
newRange.selectNode(el);
position2 = newRange.getBoundingClientRect();
} else {
position2 = el.getBoundingClientRect();
}
}
}
if (position2) {
targetPos.left = position2.left;
targetPos.top = position2.top;
}
return targetPos;
}
/**
* Append a stylesheet link to the document head
* @param {string} src url
*/
addStylesheet(src) {
return new Promise((function(resolve, reject) {
var $stylesheet;
var ready = false;
if (!this.document) {
resolve(false);
return;
}
$stylesheet = this.document.querySelector("link[href='" + src + "']");
if ($stylesheet) {
resolve(true);
return;
}
$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;
setTimeout(() => {
resolve(true);
}, 1);
}
};
this.document.head.appendChild($stylesheet);
}).bind(this));
}
_getStylesheetNode(key) {
var styleEl;
key = "epubjs-inserted-css-" + (key || "");
if (!this.document)
return false;
styleEl = this.document.getElementById(key);
if (!styleEl) {
styleEl = this.document.createElement("style");
styleEl.id = key;
this.document.head.appendChild(styleEl);
}
return styleEl;
}
/**
* Append stylesheet css
* @param {string} serializedCss
* @param {string} key If the key is the same, the CSS will be replaced instead of inserted
*/
addStylesheetCss(serializedCss, key) {
if (!this.document || !serializedCss)
return false;
var styleEl;
styleEl = this._getStylesheetNode(key);
styleEl.innerHTML = serializedCss;
return true;
}
/**
* 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
* @param {string} key If the key is the same, the CSS will be replaced instead of inserted
*/
addStylesheetRules(rules, key) {
var styleSheet;
if (!this.document || !rules || rules.length === 0)
return;
styleSheet = this._getStylesheetNode(key).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 (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";
}
styleSheet.insertRule(selector + "{" + propStr + "}", styleSheet.cssRules.length);
}
} else {
const selectors = Object.keys(rules);
selectors.forEach((selector2) => {
const definition = rules[selector2];
if (Array.isArray(definition)) {
definition.forEach((item) => {
const _rules = Object.keys(item);
const result = _rules.map((rule2) => {
return `${rule2}:${item[rule2]}`;
}).join(";");
styleSheet.insertRule(`${selector2}{${result}}`, styleSheet.cssRules.length);
});
} else {
const _rules = Object.keys(definition);
const result = _rules.map((rule2) => {
return `${rule2}:${definition[rule2]}`;
}).join(";");
styleSheet.insertRule(`${selector2}{${result}}`, styleSheet.cssRules.length);
}
});
}
}
/**
* Append a script tag to the document head
* @param {string} src url
* @returns {Promise} loaded
*/
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
*/
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
*/
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
*/
addEventListeners() {
if (!this.document) {
return;
}
this._triggerEvent = this.triggerEvent.bind(this);
DOM_EVENTS.forEach(function(eventName) {
this.document.addEventListener(eventName, this._triggerEvent, { passive: true });
}, this);
}
/**
* Remove DOM event listeners
* @private
*/
removeEventListeners() {
if (!this.document) {
return;
}
DOM_EVENTS.forEach(function(eventName) {
this.document.removeEventListener(eventName, this._triggerEvent, { passive: true });
}, this);
this._triggerEvent = void 0;
}
/**
* Emit passed browser events
* @private
*/
triggerEvent(e) {
this.emit(e.type, e);
}
/**
* Add listener for text selection
* @private
*/
addSelectionListeners() {
if (!this.document) {
return;
}
this._onSelectionChange = this.onSelectionChange.bind(this);
this.document.addEventListener("selectionchange", this._onSelectionChange, { passive: true });
}
/**
* Remove listener for text selection
* @private
*/
removeSelectionListeners() {
if (!this.document) {
return;
}
this.document.removeEventListener("selectionchange", this._onSelectionChange, { passive: true });
this._onSelectionChange = void 0;
}
/**
* Handle getting text on selection
* @private
*/
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
*/
triggerSelectedEvent(selection) {
var range, cfirange;
if (selection && selection.rangeCount > 0) {
range = selection.getRangeAt(0);
if (!range.collapsed) {
cfirange = new EpubCFI(range, this.cfiBase).toString();
this.emit(EVENTS.CONTENTS.SELECTED, cfirange);
this.emit(EVENTS.CONTENTS.SELECTED_RANGE, range);
}
}
}
/**
* Get a Dom Range from EpubCFI
* @param {EpubCFI} _cfi
* @param {string} [ignoreClass]
* @returns {Range} range
*/
range(_cfi, ignoreClass) {
var cfi = new EpubCFI(_cfi);
return cfi.toRange(this.document, ignoreClass);
}
/**
* Get an EpubCFI from a Dom Range
* @param {Range} range
* @param {string} [ignoreClass]
* @returns {EpubCFI} cfi
*/
cfiFromRange(range, ignoreClass) {
return new EpubCFI(range, this.cfiBase, ignoreClass).toString();
}
/**
* Get an EpubCFI from a Dom node
* @param {node} node
* @param {string} [ignoreClass]
* @returns {EpubCFI} cfi
*/
cfiFromNode(node, ignoreClass) {
return new EpubCFI(node, this.cfiBase, ignoreClass).toString();
}
// TODO: find where this is used - remove?
map(layout) {
var map = new Mapping(layout);
return map.section();
}
/**
* Size the contents to a given width and height
* @param {number} [width]
* @param {number} [height]
*/
size(width, height) {
var viewport = { scale: 1, scalable: "no" };
this.layoutStyle("scrolling");
if (width >= 0) {
this.width(width);
viewport.width = width;
this.css("padding", "0 " + width / 12 + "px");
}
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
*/
columns(width, height, columnWidth, gap, dir) {
let COLUMN_AXIS = prefixed("column-axis");
let COLUMN_GAP = prefixed("column-gap");
let COLUMN_WIDTH = prefixed("column-width");
let COLUMN_FILL = prefixed("column-fill");
let writingMode = this.writingMode();
let axis = writingMode.indexOf("vertical") === 0 ? "vertical" : "horizontal";
this.layoutStyle("paginated");
if (dir === "rtl" && axis === "horizontal") {
this.direction(dir);
}
this.width(width);
this.height(height);
this.viewport({ width, height, scale: 1, scalable: "no" });
this.css("overflow-y", "hidden");
this.css("margin", "0", true);
if (axis === "vertical") {
this.css("padding-top", gap / 2 + "px", true);
this.css("padding-bottom", gap / 2 + "px", true);
this.css("padding-left", "20px");
this.css("padding-right", "20px");
this.css(COLUMN_AXIS, "vertical");
} else {
this.css("padding-top", "20px");
this.css("padding-bottom", "20px");
this.css("padding-left", gap / 2 + "px", true);
this.css("padding-right", gap / 2 + "px", true);
this.css(COLUMN_AXIS, "horizontal");
}
this.css("box-sizing", "border-box");
this.css("max-width", "inherit");
this.css(COLUMN_FILL, "auto");
this.css(COLUMN_GAP, gap + "px");
this.css(COLUMN_WIDTH, columnWidth + "px");
this.css("-webkit-line-box-contain", "block glyphs replaced");
}
/**
* Scale contents from center
* @param {number} scale
* @param {number} offsetX
* @param {number} offsetY
*/
scaler(scale, offsetX, offsetY) {
var scaleStr = "scale(" + scale + ")";
var translateStr = "";
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
*/
fit(width, height, section) {
var viewport = this.viewport();
var viewportWidth = parseInt(viewport.width);
var viewportHeight = parseInt(viewport.height);
var widthScale = width / viewportWidth;
var heightScale = height / viewportHeight;
var scale = widthScale < heightScale ? widthScale : heightScale;
this.layoutStyle("paginated");
this.width(viewportWidth);
this.height(viewportHeight);
this.overflow("hidden");
this.scaler(scale, 0, 0);
this.css("background-size", viewportWidth * scale + "px " + viewportHeight * scale + "px");
this.css("background-color", "transparent");
if (section && section.properties.includes("page-spread-left")) {
var marginLeft = width - viewportWidth * scale;
this.css("margin-left", marginLeft + "px");
}
}
/**
* Set the direction of the text
* @param {string} [dir="ltr"] "rtl" | "ltr"
*/
direction(dir) {
if (this.documentElement) {
this.documentElement.style["direction"] = dir;
}
}
mapPage(cfiBase, layout, start, end, dev) {
var mapping = new Mapping(layout, dev);
return mapping.page(this, cfiBase, start, end);
}
/**
* Emit event when link in content is clicked
* @private
*/
linksHandler() {
replaceLinks(this.content, (href) => {
this.emit(EVENTS.CONTENTS.LINK_CLICKED, href);
});
}
/**
* Set the writingMode of the text
* @param {string} [mode="horizontal-tb"] "horizontal-tb" | "vertical-rl" | "vertical-lr"
*/
writingMode(mode) {
let WRITING_MODE = 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
*/
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
*/
epubReadingSystem(name, version) {
navigator.epubReadingSystem = {
name,
version,
layoutStyle: this.layoutStyle(),
hasFeature: function(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;
}
destroy() {
this.removeListeners();
}
}
EventEmitter(Contents.prototype);
class Annotations {
constructor(rendition) {
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
* @param {string} className CSS class to assign to annotation
* @param {object} styles CSS styles to assign to annotation
* @returns {Annotation} annotation
*/
add(type2, cfiRange, data, cb, className, styles) {
let hash = encodeURI(cfiRange + type2);
let cfi = new EpubCFI(cfiRange);
let sectionIndex = cfi.spinePos;
let annotation = new Annotation({
type: type2,
cfiRange,
data,
sectionIndex,
cb,
className,
styles
});
this._annotations[hash] = annotation;
if (sectionIndex in this._annotationsBySectionIndex) {
this._annotationsBySectionIndex[sectionIndex].push(hash);
} else {
this._annotationsBySectionIndex[sectionIndex] = [hash];
}
let views = this.rendition.views();
views.forEach((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"
*/
remove(cfiRange, type2) {
let hash = encodeURI(cfiRange + type2);
if (hash in this._annotations) {
let annotation = this._annotations[hash];
if (type2 && annotation.type !== type2) {
return;
}
let views = this.rendition.views();
views.forEach((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
*/
_removeFromAnnotationBySectionIndex(sectionIndex, hash) {
this._annotationsBySectionIndex[sectionIndex] = this._annotationsAt(sectionIndex).filter((h) => h !== hash);
}
/**
* Get annotations by Section Index
* @private
*/
_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 clicked
* @param {string} className CSS class to assign to annotation
* @param {object} styles CSS styles to assign to annotation
*/
highlight(cfiRange, data, cb, className, styles) {
return this.add("highlight", cfiRange, data, cb, className, styles);
}
/**
* 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 clicked
* @param {string} className CSS class to assign to annotation
* @param {object} styles CSS styles to assign to annotation
*/
underline(cfiRange, data, cb, className, styles) {
return this.add("underline", cfiRange, data, cb, className, styles);
}
/**
* 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 clicked
*/
mark(cfiRange, data, cb) {
return this.add("mark", cfiRange, data, cb);
}
/**
* iterate over annotations in the store
*/
each() {
return this._annotations.forEach.apply(this._annotations, arguments);
}
/**
* Hook for injecting annotation into a view
* @param {View} view
* @private
*/
inject(view) {
let sectionIndex = view.index;
if (sectionIndex in this._annotationsBySectionIndex) {
let annotations = this._annotationsBySectionIndex[sectionIndex];
annotations.forEach((hash) => {
let annotation = this._annotations[hash];
annotation.attach(view);
});
}
}
/**
* Hook for removing annotation from a view
* @param {View} view
* @private
*/
clear(view) {
let sectionIndex = view.index;
if (sectionIndex in this._annotationsBySectionIndex) {
let annotations = this._annotationsBySectionIndex[sectionIndex];
annotations.forEach((hash) => {
let annotation = this._annotations[hash];
annotation.detach(view);
});
}
}
/**
* [Not Implemented] Show annotations
* @TODO: needs implementation in View
*/
show() {
}
/**
* [Not Implemented] Hide annotations
* @TODO: needs implementation in View
*/
hide() {
}
}
class Annotation {
constructor({
type: type2,
cfiRange,
data,
sectionIndex,
cb,
className,
styles
}) {
this.type = type2;
this.cfiRange = cfiRange;
this.data = data;
this.sectionIndex = sectionIndex;
this.mark = void 0;
this.cb = cb;
this.className = className;
this.styles = styles;
}
/**
* Update stored data
* @param {object} data
*/
update(data) {
this.data = data;
}
/**
* Add to a view
* @param {View} view
*/
attach(view) {
let { cfiRange, data, type: type2, mark, cb, className, styles } = this;
let result;
if (type2 === "highlight") {
result = view.highlight(cfiRange, data, cb, className, styles);
} else if (type2 === "underline") {
result = view.underline(cfiRange, data, cb, className, styles);
} else if (type2 === "mark") {
result = view.mark(cfiRange, data, cb);
}
this.mark = result;
this.emit(EVENTS.ANNOTATION.ATTACH, result);
return result;
}
/**
* Remove from a view
* @param {View} view
*/
detach(view) {
let { cfiRange, type: type2 } = this;
let result;
if (view) {
if (type2 === "highlight") {
result = view.unhighlight(cfiRange);
} else if (type2 === "underline") {
result = view.ununderline(cfiRange);
} else if (type2 === "mark") {
result = view.unmark(cfiRange);
}
}
this.mark = void 0;
this.emit(EVENTS.ANNOTATION.DETACH, result);
return result;
}
/**
* [Not Implemented] Get text of an annotation
* @TODO: needs implementation in contents
*/
text() {
}
}
EventEmitter(Annotation.prototype);
var marks = {};
var svg = {};
Object.defineProperty(svg, "__esModule", {
value: true
});
svg.createElement = createElement;
function createElement(name) {
return document.createElementNS("http://www.w3.org/2000/svg", name);
}
svg.default = {
createElement
};
var events = {};
Object.defineProperty(events, "__esModule", {
value: true
});
events.proxyMouse = proxyMouse;
events.clone = clone;
events.default = {
proxyMouse
};
function proxyMouse(target, tracked) {
function dispatch(e) {
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$1(t, target, x, y)) {
continue;
}
t.dispatchEvent(clone(e));
break;
}
}
if (target.nodeName === "iframe" || target.nodeName === "IFRAME") {
try {
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);
}
}
function clone(e) {
var opts = Object.assign({}, e, { bubbles: false });
try {
return new MouseEvent(e.type, opts);
} catch (err) {
var copy2 = document.createEvent("MouseEvents");
copy2.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 copy2;
}
}
function contains$1(item, target, x, y) {
var offset = target.getBoundingClientRect();
function rectContains(r, x2, y2) {
var top = r.top - offset.top;
var left = r.left - offset.left;
var bottom = top + r.height;
var right = left + r.width;
return top <= y2 && left <= x2 && bottom > y2 && right > x2;
}
var rect = item.getBoundingClientRect();
if (!rectContains(rect, x, y)) {
return false;
}
var rects = item.getClientRects();
for (var i = 0, len = rects.length; i < len; i++) {
if (rectContains(rects[i], x, y)) {
return true;
}
}
return false;
}
var Pane_1;
var Highlight_1;
Object.defineProperty(marks, "__esModule", {
value: true
});
var Underline_1 = marks.Underline = Highlight_1 = marks.Highlight = marks.Mark = Pane_1 = marks.Pane = void 0;
var _get = function get(object, property, receiver) {
if (object === null)
object = Function.prototype;
var desc = Object.getOwnPropertyDescriptor(object, property);
if (desc === void 0) {
var parent2 = Object.getPrototypeOf(object);
if (parent2 === null) {
return void 0;
} else {
return get(parent2, property, receiver);
}
} else if ("value" in desc) {
return desc.value;
} else {
var getter = desc.get;
if (getter === void 0) {
return void 0;
}
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 = svg;
var _svg2 = _interopRequireDefault(_svg);
var _events = events;
var _events2 = _interopRequireDefault(_events);
function _interopRequireDefault(obj) {
return obj && obj.__esModule ? obj : { default: obj };
}
function _possibleConstructorReturn(self2, call) {
if (!self2) {
throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
}
return call && (typeof call === "object" || typeof call === "function") ? call : self2;
}
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;
}
function _classCallCheck(instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
}
Pane_1 = marks.Pane = function() {
function Pane(target) {
var container = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : document.body;
_classCallCheck(this, Pane);
this.target = target;
this.element = _svg2.default.createElement("svg");
this.marks = [];
this.element.style.position = "absolute";
this.element.setAttribute("pointer-events", "none");
_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 = void 0;
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 = marks.Mark = function() {
function Mark2() {
_classCallCheck(this, Mark2);
this.element = null;
}
_createClass(Mark2, [{
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());
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 Mark2;
}();
var Highlight = Highlight_1 = marks.Highlight = function(_Mark) {
_inherits(Highlight2, _Mark);
function Highlight2(range, className, data, attributes) {
_classCallCheck(this, Highlight2);
var _this = _possibleConstructorReturn(this, (Highlight2.__proto__ || Object.getPrototypeOf(Highlight2)).call(this));
_this.range = range;
_this.className = className;
_this.data = data || {};
_this.attributes = attributes || {};
return _this;
}
_createClass(Highlight2, [{
key: "bind",
value: function bind(element, container) {
_get(Highlight2.prototype.__proto__ || Object.getPrototypeOf(Highlight2.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() {
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 Highlight2;
}(Mark);
Underline_1 = marks.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() {
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");
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, coords2) {
el.style.setProperty("top", coords2.top + "px", "important");
el.style.setProperty("left", coords2.left + "px", "important");
el.style.setProperty("height", coords2.height + "px", "important");
el.style.setProperty("width", coords2.width + "px", "important");
}
function contains(rect1, rect2) {
return rect2.right <= rect1.right && rect2.left >= rect1.left && rect2.top >= rect1.top && rect2.bottom <= rect1.bottom;
}
class IframeView {
constructor(section, options) {
this.settings = extend({
ignoreClass: "",
axis: void 0,
//options.layout && options.layout.props.flow === "scrolled" ? "vertical" : "horizontal",
direction: void 0,
width: 0,
height: 0,
layout: void 0,
globalLayoutProperties: {},
method: void 0,
forceRight: false,
allowScriptedContent: false,
allowPopups: false
}, options || {});
this.id = "epubjs-view-" + 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.fixedWidth = 0;
this.fixedHeight = 0;
this.epubcfi = new EpubCFI();
this.layout = this.settings.layout;
this.pane = void 0;
this.highlights = {};
this.underlines = {};
this.marks = {};
}
container(axis) {
var element = document.createElement("div");
element.classList.add("epub-view");
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;
}
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";
this.iframe.style.overflow = "hidden";
this.iframe.seamless = "seamless";
this.iframe.style.border = "none";
this.iframe.sandbox = "allow-same-origin";
if (this.settings.allowScriptedContent) {
this.iframe.sandbox += " allow-scripts";
}
if (this.settings.allowPopups) {
this.iframe.sandbox += " allow-popups";
}
this.iframe.setAttribute("enable-annotation", "true");
this.resizing = true;
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.added = true;
this.elementBounds = bounds(this.element);
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;
}
render(request2, show) {
this.create();
this.size();
if (!this.sectionRender) {
this.sectionRender = this.section.render(request2);
}
return this.sectionRender.then((function(contents) {
return this.load(contents);
}).bind(this)).then((function() {
let writingMode = this.contents.writingMode();
let axis;
if (this.settings.flow === "scrolled") {
axis = writingMode.indexOf("vertical") === 0 ? "horizontal" : "vertical";
} else {
axis = writingMode.indexOf("vertical") === 0 ? "vertical" : "horizontal";
}
if (writingMode.indexOf("vertical") === 0 && this.settings.flow === "paginated") {
this.layout.delta = this.layout.height;
}
this.setAxis(axis);
this.emit(EVENTS.VIEWS.AXIS, axis);
this.setWritingMode(writingMode);
this.emit(EVENTS.VIEWS.WRITING_MODE, writingMode);
this.layout.format(this.contents, this.section, this.axis);
this.addListeners();
return new Promise((resolve, reject) => {
this.expand();
if (this.settings.forceRight) {
this.element.style.marginLeft = this.width() + "px";
}
resolve();
});
}).bind(this), (function(e) {
this.emit(EVENTS.VIEWS.LOAD_ERROR, e);
return new Promise((resolve, reject) => {
reject(e);
});
}).bind(this)).then((function() {
this.emit(EVENTS.VIEWS.RENDERED, this.section);
}).bind(this));
}
reset() {
if (this.iframe) {
this.iframe.style.width = "0";
this.iframe.style.height = "0";
this._width = 0;
this._height = 0;
this._textWidth = void 0;
this._contentWidth = void 0;
this._textHeight = void 0;
this._contentHeight = void 0;
}
this._needsReframe = true;
}
// Determine locks base on settings
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
lock(what, width, height) {
var elBorders = borders(this.element);
var iframeBorders;
if (this.iframe) {
iframeBorders = borders(this.iframe);
} else {
iframeBorders = { width: 0, height: 0 };
}
if (what == "width" && isNumber(width)) {
this.lockedWidth = width - elBorders.width - iframeBorders.width;
}
if (what == "height" && isNumber(height)) {
this.lockedHeight = height - elBorders.height - iframeBorders.height;
}
if (what === "both" && isNumber(width) && isNumber(height)) {
this.lockedWidth = width - elBorders.width - iframeBorders.width;
this.lockedHeight = height - elBorders.height - iframeBorders.height;
}
if (this.displayed && this.iframe) {
this.expand();
}
}
// Resize a single axis based on content dimensions
expand(force) {
var width = this.lockedWidth;
var height = this.lockedHeight;
var columns;
if (!this.iframe || this._expanding)
return;
this._expanding = true;
if (this.layout.name === "pre-paginated") {
width = this.layout.columnWidth;
height = this.layout.height;
} else if (this.settings.axis === "horizontal") {
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.pageWidth;
if (this.layout.divisor > 1 && this.layout.name === "reflowable" && columns % 2 > 0) {
width += this.layout.pageWidth;
}
}
} else if (this.settings.axis === "vertical") {
height = this.contents.textHeight();
if (this.settings.flow === "paginated" && height % this.layout.height > 0) {
height = Math.ceil(height / this.layout.height) * this.layout.height;
}
}
if (this._needsReframe || width != this._width || height != this._height) {
this.reframe(width, height);
}
this._expanding = false;
}
reframe(width, height) {
var size;
if (isNumber(width)) {
this.element.style.width = width + "px";
this.iframe.style.width = width + "px";
this._width = width;
}
if (isNumber(height)) {
this.element.style.height = height + "px";
this.iframe.style.height = height + "px";
this._height = height;
}
let widthDelta = this.prevBounds ? width - this.prevBounds.width : width;
let heightDelta = this.prevBounds ? height - this.prevBounds.height : height;
size = {
width,
height,
widthDelta,
heightDelta
};
this.pane && this.pane.render();
requestAnimationFrame(() => {
let mark;
for (let m in this.marks) {
if (this.marks.hasOwnProperty(m)) {
mark = this.marks[m];
this.placeMark(mark.element, mark.range);
}
}
});
this.onResize(this, size);
this.emit(EVENTS.VIEWS.RESIZED, size);
this.prevBounds = size;
this.elementBounds = bounds(this.element);
}
load(contents) {
var loading = new 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 = createBlobUrl(contents, "application/xhtml+xml");
this.iframe.src = this.blobUrl;
this.element.appendChild(this.iframe);
} else if (this.settings.method === "srcdoc") {
this.iframe.srcdoc = contents;
this.element.appendChild(this.iframe);
} else {
this.element.appendChild(this.iframe);
this.document = this.iframe.contentDocument;
if (!this.document) {
loading.reject(new Error("No Document Available"));
return loaded;
}
this.iframe.contentDocument.open();
if (window.MSApp && MSApp.execUnsafeLocalFunction) {
var outerThis = this;
MSApp.execUnsafeLocalFunction(function() {
outerThis.iframe.contentDocument.write(contents);
});
} else {
this.iframe.contentDocument.write(contents);
}
this.iframe.contentDocument.close();
}
return loaded;
}
onLoad(event, promise) {
this.window = this.iframe.contentWindow;
this.document = this.iframe.contentDocument;
this.contents = new Contents(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(EVENTS.CONTENTS.EXPAND, () => {
if (this.displayed && this.iframe) {
this.expand();
if (this.contents) {
this.layout.format(this.contents);
}
}
});
this.contents.on(EVENTS.CONTENTS.RESIZE, (e) => {
if (this.displayed && this.iframe) {
this.expand();
if (this.contents) {
this.layout.format(this.contents);
}
}
});
promise.resolve(this.contents);
}
setLayout(layout) {
this.layout = layout;
if (this.contents) {
this.layout.format(this.contents);
this.expand();
}
}
setAxis(axis) {
this.settings.axis = axis;
if (axis == "horizontal") {
this.element.style.flex = "none";
} else {
this.element.style.flex = "initial";
}
this.size();
}
setWritingMode(mode) {
this.writingMode = mode;
}
addListeners() {
}
removeListeners(layoutFunc) {
}
display(request2) {
var displayed = new defer();
if (!this.displayed) {
this.render(request2).then((function() {
this.emit(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;
}
show() {
this.element.style.visibility = "visible";
if (this.iframe) {
this.iframe.style.visibility = "visible";
this.iframe.style.transform = "translateZ(0)";
this.iframe.offsetWidth;
this.iframe.style.transform = null;
}
this.emit(EVENTS.VIEWS.SHOWN, this);
}
hide() {
this.element.style.visibility = "hidden";
this.iframe.style.visibility = "hidden";
this.stopExpanding = true;
this.emit(EVENTS.VIEWS.HIDDEN, this);
}
offset() {
return {
top: this.element.offsetTop,
left: this.element.offsetLeft
};
}
width() {
return this._width;
}
height() {
return this._height;
}
position() {
return this.element.getBoundingClientRect();
}
locationOf(target) {
this.iframe.getBoundingClientRect();
var targetPos = this.contents.locationOf(target, this.settings.ignoreClass);
return {
"left": targetPos.left,
"top": targetPos.top
};
}
onDisplayed(view) {
}
onResize(view, e) {
}
bounds(force) {
if (force || !this.elementBounds) {
this.elementBounds = bounds(this.element);
}
return this.elementBounds;
}
highlight(cfiRange, data = {}, cb, className = "epubjs-hl", styles = {}) {
if (!this.contents) {
return;
}
const attributes = Object.assign({ "fill": "yellow", "fill-opacity": "0.3", "mix-blend-mode": "multiply" }, styles);
let range = this.contents.range(cfiRange);
let emitter = () => {
this.emit(EVENTS.VIEWS.MARK_CLICKED, cfiRange, data);
};
data["epubcfi"] = cfiRange;
if (!this.pane) {
this.pane = new Pane_1(this.iframe, this.element);
}
let m = new Highlight_1(range, className, data, attributes);
let h = this.pane.addMark(m);
this.highlights[cfiRange] = { "mark": h, "element": h.element, "listeners": [emitter, cb] };
h.element.setAttribute("ref", className);
h.element.addEventListener("click", emitter);
h.element.addEventListener("touchstart", emitter);
if (cb) {
h.element.addEventListener("click", cb);
h.element.addEventListener("touchstart", cb);
}
return h;
}
underline(cfiRange, data = {}, cb, className = "epubjs-ul", styles = {}) {
if (!this.contents) {
return;
}
const attributes = Object.assign({ "stroke": "black", "stroke-opacity": "0.3", "mix-blend-mode": "multiply" }, styles);
let range = this.contents.range(cfiRange);
let emitter = () => {
this.emit(EVENTS.VIEWS.MARK_CLICKED, cfiRange, data);
};
data["epubcfi"] = cfiRange;
if (!this.pane) {
this.pane = new Pane_1(this.iframe, this.element);
}
let m = new Underline_1(range, className, data, attributes);
let h = this.pane.addMark(m);
this.underlines[cfiRange] = { "mark": h, "element": h.element, "listeners": [emitter, cb] };
h.element.setAttribute("ref", className);
h.element.addEventListener("click", emitter);
h.element.addEventListener("touchstart", emitter);
if (cb) {
h.element.addEventListener("click", cb);
h.element.addEventListener("touchstart", cb);
}
return h;
}
mark(cfiRange, data = {}, cb) {
if (!this.contents) {
return;
}
if (cfiRange in this.marks) {
let item = this.marks[cfiRange];
return item;
}
let range = this.contents.range(cfiRange);
if (!range) {
return;
}
let container = range.commonAncestorContainer;
let parent2 = container.nodeType === 1 ? container : container.parentNode;
let emitter = (e) => {
this.emit(EVENTS.VIEWS.MARK_CLICKED, cfiRange, data);
};
if (range.collapsed && container.nodeType === 1) {
range = new Range();
range.selectNodeContents(container);
} else if (range.collapsed) {
range = new Range();
range.selectNodeContents(parent2);
}
let mark = this.document.createElement("a");
mark.setAttribute("ref", "epubjs-mk");
mark.style.position = "absolute";
mark.dataset["epubcfi"] = cfiRange;
if (data) {
Object.keys(data).forEach((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.placeMark(mark, range);
this.element.appendChild(mark);
this.marks[cfiRange] = { "element": mark, "range": range, "listeners": [emitter, cb] };
return parent2;
}
placeMark(element, range) {
let top, right, left;
if (this.layout.name === "pre-paginated" || this.settings.axis !== "horizontal") {
let pos = range.getBoundingClientRect();
top = pos.top;
right = pos.right;
} else {
let rects = range.getClientRects();
let rect;
for (var i = 0; i != rects.length; i++) {
rect = rects[i];
if (!left || rect.left < left) {
left = rect.left;
right = Math.ceil(left / this.layout.props.pageWidth) * this.layout.props.pageWidth - this.layout.gap / 2;
top = rect.top;
}
}
}
element.style.top = `${top}px`;
element.style.left = `${right}px`;
}
unhighlight(cfiRange) {
let item;
if (cfiRange in this.highlights) {
item = this.highlights[cfiRange];
this.pane.removeMark(item.mark);
item.listeners.forEach((l) => {
if (l) {
item.element.removeEventListener("click", l);
item.element.removeEventListener("touchstart", l);
}
});
delete this.highlights[cfiRange];
}
}
ununderline(cfiRange) {
let item;
if (cfiRange in this.underlines) {
item = this.underlines[cfiRange];
this.pane.removeMark(item.mark);
item.listeners.forEach((l) => {
if (l) {
item.element.removeEventListener("click", l);
item.element.removeEventListener("touchstart", l);
}
});
delete this.underlines[cfiRange];
}
}
unmark(cfiRange) {
let item;
if (cfiRange in this.marks) {
item = this.marks[cfiRange];
this.element.removeChild(item.element);
item.listeners.forEach((l) => {
if (l) {
item.element.removeEventListener("click", l);
item.element.removeEventListener("touchstart", l);
}
});
delete this.marks[cfiRange];
}
}
destroy() {
for (let cfiRange in this.highlights) {
this.unhighlight(cfiRange);
}
for (let cfiRange in this.underlines) {
this.ununderline(cfiRange);
}
for (let cfiRange in this.marks) {
this.unmark(cfiRange);
}
if (this.blobUrl) {
revokeBlobUrl(this.blobUrl);
}
if (this.displayed) {
this.displayed = false;
this.removeListeners();
this.contents.destroy();
this.stopExpanding = true;
this.element.removeChild(this.iframe);
if (this.pane) {
this.pane.element.remove();
this.pane = void 0;
}
this.iframe = void 0;
this.contents = void 0;
this._textWidth = null;
this._textHeight = null;
this._width = null;
this._height = null;
}
}
}
EventEmitter(IframeView.prototype);
function scrollType() {
var type2 = "reverse";
var definer = createDefiner();
document.body.appendChild(definer);
if (definer.scrollLeft > 0) {
type2 = "default";
} else {
if (typeof Element !== "undefined" && Element.prototype.scrollIntoView) {
definer.children[0].children[1].scrollIntoView();
if (definer.scrollLeft < 0) {
type2 = "negative";
}
} else {
definer.scrollLeft = 1;
if (definer.scrollLeft === 0) {
type2 = "negative";
}
}
}
document.body.removeChild(definer);
return type2;
}
function createDefiner() {
var definer = document.createElement("div");
definer.dir = "rtl";
definer.style.position = "fixed";
definer.style.width = "1px";
definer.style.height = "1px";
definer.style.top = "0px";
definer.style.left = "0px";
definer.style.overflow = "hidden";
var innerDiv = document.createElement("div");
innerDiv.style.width = "2px";
var spanA = document.createElement("span");
spanA.style.width = "1px";
spanA.style.display = "inline-block";
var spanB = document.createElement("span");
spanB.style.width = "1px";
spanB.style.display = "inline-block";
innerDiv.appendChild(spanA);
innerDiv.appendChild(spanB);
definer.appendChild(innerDiv);
return definer;
}
function isObject$3(value) {
var type2 = typeof value;
return value != null && (type2 == "object" || type2 == "function");
}
var isObject_1 = isObject$3;
var freeGlobal$1 = typeof commonjsGlobal == "object" && commonjsGlobal && commonjsGlobal.Object === Object && commonjsGlobal;
var _freeGlobal = freeGlobal$1;
var freeGlobal = _freeGlobal;
var freeSelf = typeof self == "object" && self && self.Object === Object && self;
var root$2 = freeGlobal || freeSelf || Function("return this")();
var _root = root$2;
var root$1 = _root;
var now$1 = function() {
return root$1.Date.now();
};
var now_1 = now$1;
var reWhitespace = /\s/;
function trimmedEndIndex$1(string) {
var index = string.length;
while (index-- && reWhitespace.test(string.charAt(index))) {
}
return index;
}
var _trimmedEndIndex = trimmedEndIndex$1;
var trimmedEndIndex = _trimmedEndIndex;
var reTrimStart = /^\s+/;
function baseTrim$1(string) {
return string ? string.slice(0, trimmedEndIndex(string) + 1).replace(reTrimStart, "") : string;
}
var _baseTrim = baseTrim$1;
var root = _root;
var Symbol$3 = root.Symbol;
var _Symbol = Symbol$3;
var Symbol$2 = _Symbol;
var objectProto$1 = Object.prototype;
var hasOwnProperty$1 = objectProto$1.hasOwnProperty;
var nativeObjectToString$1 = objectProto$1.toString;
var symToStringTag$1 = Symbol$2 ? Symbol$2.toStringTag : void 0;
function getRawTag$1(value) {
var isOwn = hasOwnProperty$1.call(value, symToStringTag$1), tag = value[symToStringTag$1];
try {
value[symToStringTag$1] = void 0;
var unmasked = true;
} catch (e) {
}
var result = nativeObjectToString$1.call(value);
if (unmasked) {
if (isOwn) {
value[symToStringTag$1] = tag;
} else {
delete value[symToStringTag$1];
}
}
return result;
}
var _getRawTag = getRawTag$1;
var objectProto = Object.prototype;
var nativeObjectToString = objectProto.toString;
function objectToString$1(value) {
return nativeObjectToString.call(value);
}
var _objectToString = objectToString$1;
var Symbol$1 = _Symbol, getRawTag = _getRawTag, objectToString = _objectToString;
var nullTag = "[object Null]", undefinedTag = "[object Undefined]";
var symToStringTag = Symbol$1 ? Symbol$1.toStringTag : void 0;
function baseGetTag$1(value) {
if (value == null) {
return value === void 0 ? undefinedTag : nullTag;
}
return symToStringTag && symToStringTag in Object(value) ? getRawTag(value) : objectToString(value);
}
var _baseGetTag = baseGetTag$1;
function isObjectLike$1(value) {
return value != null && typeof value == "object";
}
var isObjectLike_1 = isObjectLike$1;
var baseGetTag = _baseGetTag, isObjectLike = isObjectLike_1;
var symbolTag = "[object Symbol]";
function isSymbol$1(value) {
return typeof value == "symbol" || isObjectLike(value) && baseGetTag(value) == symbolTag;
}
var isSymbol_1 = isSymbol$1;
var baseTrim = _baseTrim, isObject$2 = isObject_1, isSymbol = isSymbol_1;
var NAN = 0 / 0;
var reIsBadHex = /^[-+]0x[0-9a-f]+$/i;
var reIsBinary = /^0b[01]+$/i;
var reIsOctal = /^0o[0-7]+$/i;
var freeParseInt = parseInt;
function toNumber$1(value) {
if (typeof value == "number") {
return value;
}
if (isSymbol(value)) {
return NAN;
}
if (isObject$2(value)) {
var other = typeof value.valueOf == "function" ? value.valueOf() : value;
value = isObject$2(other) ? other + "" : other;
}
if (typeof value != "string") {
return value === 0 ? value : +value;
}
value = baseTrim(value);
var isBinary = reIsBinary.test(value);
return isBinary || reIsOctal.test(value) ? freeParseInt(value.slice(2), isBinary ? 2 : 8) : reIsBadHex.test(value) ? NAN : +value;
}
var toNumber_1 = toNumber$1;
var isObject$1 = isObject_1, now = now_1, toNumber = toNumber_1;
var FUNC_ERROR_TEXT$1 = "Expected a function";
var nativeMax = Math.max, nativeMin = Math.min;
function debounce$1(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$1);
}
wait = toNumber(wait) || 0;
if (isObject$1(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 = void 0;
lastInvokeTime = time;
result = func.apply(thisArg, args);
return result;
}
function leadingEdge(time) {
lastInvokeTime = time;
timerId = setTimeout(timerExpired, wait);
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;
return lastCallTime === void 0 || timeSinceLastCall >= wait || timeSinceLastCall < 0 || maxing && timeSinceLastInvoke >= maxWait;
}
function timerExpired() {
var time = now();
if (shouldInvoke(time)) {
return trailingEdge(time);
}
timerId = setTimeout(timerExpired, remainingWait(time));
}
function trailingEdge(time) {
timerId = void 0;
if (trailing && lastArgs) {
return invokeFunc(time);
}
lastArgs = lastThis = void 0;
return result;
}
function cancel() {
if (timerId !== void 0) {
clearTimeout(timerId);
}
lastInvokeTime = 0;
lastArgs = lastCallTime = lastThis = timerId = void 0;
}
function flush() {
return timerId === void 0 ? result : trailingEdge(now());
}
function debounced() {
var time = now(), isInvoking = shouldInvoke(time);
lastArgs = arguments;
lastThis = this;
lastCallTime = time;
if (isInvoking) {
if (timerId === void 0) {
return leadingEdge(lastCallTime);
}
if (maxing) {
clearTimeout(timerId);
timerId = setTimeout(timerExpired, wait);
return invokeFunc(lastCallTime);
}
}
if (timerId === void 0) {
timerId = setTimeout(timerExpired, wait);
}
return result;
}
debounced.cancel = cancel;
debounced.flush = flush;
return debounced;
}
var debounce_1 = debounce$1;
const debounce$2 = /* @__PURE__ */ getDefaultExportFromCjs(debounce_1);
var debounce = debounce_1, isObject = isObject_1;
var FUNC_ERROR_TEXT = "Expected a function";
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
});
}
var throttle_1 = throttle;
const throttle$1 = /* @__PURE__ */ getDefaultExportFromCjs(throttle_1);
class Stage {
constructor(_options) {
this.settings = _options || {};
this.id = "epubjs-container-" + 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
*/
create(options) {
let height = options.height;
let width = options.width;
let overflow = options.overflow || false;
let axis = options.axis || "vertical";
let direction = options.direction;
extend(this.settings, options);
if (options.height && isNumber(options.height)) {
height = options.height + "px";
}
if (options.width && isNumber(options.width)) {
width = options.width + "px";
}
let container = document.createElement("div");
container.id = this.id;
container.classList.add("epub-container");
container.style.wordSpacing = "0";
container.style.lineHeight = "0";
container.style.verticalAlign = "top";
container.style.position = "relative";
if (axis === "horizontal") {
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) {
if (overflow === "scroll" && axis === "vertical") {
container.style["overflow-y"] = overflow;
container.style["overflow-x"] = "hidden";
} else if (overflow === "scroll" && axis === "horizontal") {
container.style["overflow-y"] = "hidden";
container.style["overflow-x"] = overflow;
} else {
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;
}
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;
}
getElement(_element) {
var element;
if (isElement(_element)) {
element = _element;
} else if (typeof _element === "string") {
element = document.getElementById(_element);
}
if (!element) {
throw new Error("Not an Element");
}
return element;
}
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;
}
getContainer() {
return this.container;
}
onResize(func) {
if (!isNumber(this.settings.width) || !isNumber(this.settings.height)) {
this.resizeFunc = throttle$1(func, 50);
window.addEventListener("resize", this.resizeFunc, false);
}
}
onOrientationChange(func) {
this.orientationChangeFunc = func;
window.addEventListener("orientationchange", this.orientationChangeFunc, false);
}
size(width, height) {
var bounds2;
let _width = width || this.settings.width;
let _height = height || this.settings.height;
if (width === null) {
bounds2 = this.element.getBoundingClientRect();
if (bounds2.width) {
width = Math.floor(bounds2.width);
this.container.style.width = width + "px";
}
} else {
if (isNumber(width)) {
this.container.style.width = width + "px";
} else {
this.container.style.width = width;
}
}
if (height === null) {
bounds2 = bounds2 || this.element.getBoundingClientRect();
if (bounds2.height) {
height = bounds2.height;
this.container.style.height = height + "px";
}
} else {
if (isNumber(height)) {
this.container.style.height = height + "px";
} else {
this.container.style.height = height;
}
}
if (!isNumber(width)) {
width = this.container.clientWidth;
}
if (!isNumber(height)) {
height = this.container.clientHeight;
}
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
};
let _windowBounds = windowBounds();
let bodyStyles = window.getComputedStyle(document.body);
let bodyPadding = {
left: parseFloat(bodyStyles["padding-left"]) || 0,
right: parseFloat(bodyStyles["padding-right"]) || 0,
top: parseFloat(bodyStyles["padding-top"]) || 0,
bottom: parseFloat(bodyStyles["padding-bottom"]) || 0
};
if (!_width) {
width = _windowBounds.width - bodyPadding.left - bodyPadding.right;
}
if (this.settings.fullsize && !_height || !_height) {
height = _windowBounds.height - bodyPadding.top - bodyPadding.bottom;
}
return {
width: width - this.containerPadding.left - this.containerPadding.right,
height: height - this.containerPadding.top - this.containerPadding.bottom
};
}
bounds() {
let box;
if (this.container.style.overflow !== "visible") {
box = this.container && this.container.getBoundingClientRect();
}
if (!box || !box.width || !box.height) {
return windowBounds();
} else {
return box;
}
}
getSheet() {
var style = document.createElement("style");
style.appendChild(document.createTextNode(""));
document.head.appendChild(style);
return style.sheet;
}
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);
}
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";
}
this.settings.axis = axis;
}
// orientation(orientation) {
// if (orientation === "landscape") {
//
// } else {
//
// }
//
// this.orientation = orientation;
// }
direction(dir) {
if (this.container) {
this.container.dir = dir;
this.container.style["direction"] = dir;
}
if (this.settings.fullsize) {
document.body.style["direction"] = dir;
}
this.settings.dir = dir;
}
overflow(overflow) {
if (this.container) {
if (overflow === "scroll" && this.settings.axis === "vertical") {
this.container.style["overflow-y"] = overflow;
this.container.style["overflow-x"] = "hidden";
} else if (overflow === "scroll" && this.settings.axis === "horizontal") {
this.container.style["overflow-y"] = "hidden";
this.container.style["overflow-x"] = overflow;
} else {
this.container.style["overflow"] = overflow;
}
}
this.settings.overflow = overflow;
}
destroy() {
if (this.element) {
if (this.settings.hidden) {
this.wrapper;
} else {
this.container;
}
if (this.element.contains(this.container)) {
this.element.removeChild(this.container);
}
window.removeEventListener("resize", this.resizeFunc);
window.removeEventListener("orientationChange", this.orientationChangeFunc);
}
}
}
class Views {
constructor(container) {
this.container = container;
this._views = [];
this.length = 0;
this.hidden = false;
}
all() {
return this._views;
}
first() {
return this._views[0];
}
last() {
return this._views[this._views.length - 1];
}
indexOf(view) {
return this._views.indexOf(view);
}
slice() {
return this._views.slice.apply(this._views, arguments);
}
get(i) {
return this._views[i];
}
append(view) {
this._views.push(view);
if (this.container) {
this.container.appendChild(view.element);
}
this.length++;
return view;
}
prepend(view) {
this._views.unshift(view);
if (this.container) {
this.container.insertBefore(view.element, this.container.firstChild);
}
this.length++;
return view;
}
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;
}
remove(view) {
var index = this._views.indexOf(view);
if (index > -1) {
this._views.splice(index, 1);
}
this.destroy(view);
this.length--;
}
destroy(view) {
if (view.displayed) {
view.destroy();
}
if (this.container) {
this.container.removeChild(view.element);
}
view = null;
}
// Iterators
forEach() {
return this._views.forEach.apply(this._views, arguments);
}
clear() {
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;
}
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;
}
}
}
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;
}
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;
}
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;
}
}
class DefaultViewManager {
constructor(options) {
this.name = "default";
this.optsSettings = options.settings;
this.View = options.view;
this.request = options.request;
this.renditionQueue = options.queue;
this.q = new Queue(this);
this.settings = extend(this.settings || {}, {
infinite: true,
hidden: false,
width: void 0,
height: void 0,
axis: void 0,
writingMode: void 0,
flow: "scrolled",
ignoreClass: "",
fullsize: void 0,
allowScriptedContent: false,
allowPopups: false
});
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,
allowScriptedContent: this.settings.allowScriptedContent,
allowPopups: this.settings.allowPopups
};
this.rendered = false;
}
render(element, size) {
let tag = element.tagName;
if (typeof this.settings.fullsize === "undefined" && tag && (tag.toLowerCase() == "body" || tag.toLowerCase() == "html")) {
this.settings.fullsize = true;
}
if (this.settings.fullsize) {
this.settings.overflow = "visible";
this.overflow = this.settings.overflow;
}
this.settings.size = size;
this.settings.rtlScrollType = scrollType();
this.stage = new Stage({
width: size.width,
height: size.height,
overflow: this.overflow,
hidden: this.settings.hidden,
axis: this.settings.axis,
fullsize: this.settings.fullsize,
direction: this.settings.direction
});
this.stage.attachTo(element);
this.container = this.stage.getContainer();
this.views = new Views(this.container);
this._bounds = this.bounds();
this._stageSize = this.stage.size();
this.viewSettings.width = this._stageSize.width;
this.viewSettings.height = this._stageSize.height;
this.stage.onResize(this.onResized.bind(this));
this.stage.onOrientationChange(this.onOrientationChange.bind(this));
this.addEventListeners();
if (this.layout) {
this.updateLayout();
}
this.rendered = true;
}
addEventListeners() {
var scroller;
window.addEventListener("unload", (function(e) {
this.destroy();
}).bind(this));
if (!this.settings.fullsize) {
scroller = this.container;
} else {
scroller = window;
}
this._onScroll = this.onScroll.bind(this);
scroller.addEventListener("scroll", this._onScroll);
}
removeEventListeners() {
var scroller;
if (!this.settings.fullsize) {
scroller = this.container;
} else {
scroller = window;
}
scroller.removeEventListener("scroll", this._onScroll);
this._onScroll = void 0;
}
destroy() {
clearTimeout(this.orientationTimeout);
clearTimeout(this.resizeTimeout);
clearTimeout(this.afterScrolled);
this.clear();
this.removeEventListeners();
this.stage.destroy();
this.rendered = false;
}
onOrientationChange(e) {
let { orientation } = window;
if (this.optsSettings.resizeOnOrientationChange) {
this.resize();
}
clearTimeout(this.orientationTimeout);
this.orientationTimeout = setTimeout((function() {
this.orientationTimeout = void 0;
if (this.optsSettings.resizeOnOrientationChange) {
this.resize();
}
this.emit(EVENTS.MANAGERS.ORIENTATION_CHANGE, orientation);
}).bind(this), 500);
}
onResized(e) {
this.resize();
}
resize(width, height, epubcfi) {
let stageSize = this.stage.size(width, height);
this.winBounds = windowBounds();
if (this.orientationTimeout && this.winBounds.width === this.winBounds.height) {
this._stageSize = void 0;
return;
}
if (this._stageSize && this._stageSize.width === stageSize.width && this._stageSize.height === stageSize.height) {
return;
}
this._stageSize = stageSize;
this._bounds = this.bounds();
this.clear();
this.viewSettings.width = this._stageSize.width;
this.viewSettings.height = this._stageSize.height;
this.updateLayout();
this.emit(EVENTS.MANAGERS.RESIZED, {
width: this._stageSize.width,
height: this._stageSize.height
}, epubcfi);
}
createView(section, forceRight) {
return new this.View(section, extend(this.viewSettings, { forceRight }));
}
handleNextPrePaginated(forceRight, section, action) {
let next;
if (this.layout.name === "pre-paginated" && this.layout.divisor > 1) {
if (forceRight || section.index === 0) {
return;
}
next = section.next();
if (next && !next.properties.includes("page-spread-left")) {
return action.call(this, next);
}
}
}
display(section, target) {
var displaying = new defer();
var displayed = displaying.promise;
if (target === section.href || isNumber(target)) {
target = void 0;
}
var visible = this.views.find(section);
if (visible && section && this.layout.name !== "pre-paginated") {
let offset = visible.offset();
if (this.settings.direction === "ltr") {
this.scrollTo(offset.left, offset.top, true);
} else {
let width = visible.width();
this.scrollTo(offset.left + width, offset.top, true);
}
if (target) {
let offset2 = visible.locationOf(target);
let width = visible.width();
this.moveTo(offset2, width);
}
displaying.resolve();
return displayed;
}
this.clear();
let forceRight = false;
if (this.layout.name === "pre-paginated" && this.layout.divisor === 2 && section.properties.includes("page-spread-right")) {
forceRight = true;
}
this.add(section, forceRight).then((function(view) {
if (target) {
let offset = view.locationOf(target);
let width = view.width();
this.moveTo(offset, width);
}
}).bind(this), (err) => {
displaying.reject(err);
}).then((function() {
return this.handleNextPrePaginated(forceRight, section, this.add);
}).bind(this)).then((function() {
this.views.show();
displaying.resolve();
}).bind(this));
return displayed;
}
afterDisplayed(view) {
this.emit(EVENTS.MANAGERS.ADDED, view);
}
afterResized(view) {
this.emit(EVENTS.MANAGERS.RESIZE, view.section);
}
moveTo(offset, width) {
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;
}
distY = Math.floor(offset.top / this.layout.delta) * this.layout.delta;
if (distY + this.layout.delta > this.container.scrollHeight) {
distY = this.container.scrollHeight - this.layout.delta;
}
}
if (this.settings.direction === "rtl") {
distX = distX + this.layout.delta;
distX = distX - width;
}
this.scrollTo(distX, distY, true);
}
add(section, forceRight) {
var view = this.createView(section, forceRight);
this.views.append(view);
view.onDisplayed = this.afterDisplayed.bind(this);
view.onResize = this.afterResized.bind(this);
view.on(EVENTS.VIEWS.AXIS, (axis) => {
this.updateAxis(axis);
});
view.on(EVENTS.VIEWS.WRITING_MODE, (mode) => {
this.updateWritingMode(mode);
});
return view.display(this.request);
}
append(section, forceRight) {
var view = this.createView(section, forceRight);
this.views.append(view);
view.onDisplayed = this.afterDisplayed.bind(this);
view.onResize = this.afterResized.bind(this);
view.on(EVENTS.VIEWS.AXIS, (axis) => {
this.updateAxis(axis);
});
view.on(EVENTS.VIEWS.WRITING_MODE, (mode) => {
this.updateWritingMode(mode);
});
return view.display(this.request);
}
prepend(section, forceRight) {
var view = this.createView(section, forceRight);
view.on(EVENTS.VIEWS.RESIZED, (bounds2) => {
this.counter(bounds2);
});
this.views.prepend(view);
view.onDisplayed = this.afterDisplayed.bind(this);
view.onResize = this.afterResized.bind(this);
view.on(EVENTS.VIEWS.AXIS, (axis) => {
this.updateAxis(axis);
});
view.on(EVENTS.VIEWS.WRITING_MODE, (mode) => {
this.updateWritingMode(mode);
});
return view.display(this.request);
}
counter(bounds2) {
if (this.settings.axis === "vertical") {
this.scrollBy(0, bounds2.heightDelta, true);
} else {
this.scrollBy(bounds2.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);
// }
//
// };
next() {
var next;
var left;
let 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;
if (this.settings.rtlScrollType === "default") {
left = this.container.scrollLeft;
if (left > 0) {
this.scrollBy(this.layout.delta, 0, true);
} else {
next = this.views.last().section.next();
}
} else {
left = this.container.scrollLeft + this.layout.delta * -1;
if (left > this.container.scrollWidth * -1) {
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;
let 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();
this.updateLayout();
let forceRight = false;
if (this.layout.name === "pre-paginated" && this.layout.divisor === 2 && next.properties.includes("page-spread-right")) {
forceRight = true;
}
return this.append(next, forceRight).then((function() {
return this.handleNextPrePaginated(forceRight, next, this.append);
}).bind(this), (err) => {
return err;
}).then((function() {
if (!this.isPaginated && this.settings.axis === "horizontal" && this.settings.direction === "rtl" && this.settings.rtlScrollType === "default") {
this.scrollTo(this.container.scrollWidth, 0, true);
}
this.views.show();
}).bind(this));
}
}
prev() {
var prev;
var left;
let 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;
if (this.settings.rtlScrollType === "default") {
left = this.container.scrollLeft + this.container.offsetWidth;
if (left < this.container.scrollWidth) {
this.scrollBy(-this.layout.delta, 0, true);
} else {
prev = this.views.first().section.prev();
}
} else {
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 === "vertical") {
this.scrollTop = this.container.scrollTop;
let 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();
this.updateLayout();
let forceRight = false;
if (this.layout.name === "pre-paginated" && this.layout.divisor === 2 && typeof prev.prev() !== "object") {
forceRight = true;
}
return this.prepend(prev, forceRight).then((function() {
var left2;
if (this.layout.name === "pre-paginated" && this.layout.divisor > 1) {
left2 = prev.prev();
if (left2) {
return this.prepend(left2);
}
}
}).bind(this), (err) => {
return err;
}).then((function() {
if (this.isPaginated && this.settings.axis === "horizontal") {
if (this.settings.direction === "rtl") {
if (this.settings.rtlScrollType === "default") {
this.scrollTo(0, 0, true);
} else {
this.scrollTo(this.container.scrollWidth * -1 + this.layout.delta, 0, true);
}
} else {
this.scrollTo(this.container.scrollWidth - this.layout.delta, 0, true);
}
}
this.views.show();
}).bind(this));
}
}
current() {
var visible = this.visible();
if (visible.length) {
return visible[visible.length - 1];
}
return null;
}
clear() {
if (this.views) {
this.views.hide();
this.scrollTo(0, 0, true);
this.views.clear();
}
}
currentLocation() {
this.updateLayout();
if (this.isPaginated && this.settings.axis === "horizontal") {
this.location = this.paginatedLocation();
} else {
this.location = this.scrolledLocation();
}
return this.location;
}
scrolledLocation() {
let visible = this.visible();
let container = this.container.getBoundingClientRect();
let pageHeight = container.height < window.innerHeight ? container.height : window.innerHeight;
let pageWidth = container.width < window.innerWidth ? container.width : window.innerWidth;
let vertical = this.settings.axis === "vertical";
this.settings.direction === "rtl";
let offset = 0;
let used = 0;
if (this.settings.fullsize) {
offset = vertical ? window.scrollY : window.scrollX;
}
let sections = visible.map((view) => {
let { index, href } = view.section;
let position2 = view.position();
let width = view.width();
let height = view.height();
let startPos;
let endPos;
let stopPos;
let totalPages;
if (vertical) {
startPos = offset + container.top - position2.top + used;
endPos = startPos + pageHeight - used;
totalPages = this.layout.count(height, pageHeight).pages;
stopPos = pageHeight;
} else {
startPos = offset + container.left - position2.left + used;
endPos = startPos + pageWidth - used;
totalPages = this.layout.count(width, pageWidth).pages;
stopPos = pageWidth;
}
let currPage = Math.ceil(startPos / stopPos);
let pages = [];
let endPage = Math.ceil(endPos / stopPos);
if (this.settings.direction === "rtl" && !vertical) {
let tempStartPage = currPage;
currPage = totalPages - endPage;
endPage = totalPages - tempStartPage;
}
pages = [];
for (var i = currPage; i <= endPage; i++) {
let pg = i + 1;
pages.push(pg);
}
let mapping = this.mapping.page(view.contents, view.section.cfiBase, startPos, endPos);
return {
index,
href,
pages,
totalPages,
mapping
};
});
return sections;
}
paginatedLocation() {
let visible = this.visible();
let container = this.container.getBoundingClientRect();
let left = 0;
let used = 0;
if (this.settings.fullsize) {
left = window.scrollX;
}
let sections = visible.map((view) => {
let { index, href } = view.section;
let offset;
let position2 = view.position();
let width = view.width();
let start;
let end;
let pageWidth;
if (this.settings.direction === "rtl") {
offset = container.right - left;
pageWidth = Math.min(Math.abs(offset - position2.left), this.layout.width) - used;
end = position2.width - (position2.right - offset) - used;
start = end - pageWidth;
} else {
offset = container.left + left;
pageWidth = Math.min(position2.right - offset, this.layout.width) - used;
start = offset - position2.left + used;
end = start + pageWidth;
}
used += pageWidth;
let mapping = this.mapping.page(view.contents, view.section.cfiBase, start, end);
let totalPages = this.layout.count(width).pages;
let startPage = Math.floor(start / this.layout.pageWidth);
let pages = [];
let endPage = Math.floor(end / this.layout.pageWidth);
if (startPage < 0) {
startPage = 0;
endPage = endPage + 1;
}
if (this.settings.direction === "rtl") {
let tempStartPage = startPage;
startPage = totalPages - endPage;
endPage = totalPages - tempStartPage;
}
for (var i = startPage + 1; i <= endPage; i++) {
let pg = i;
pages.push(pg);
}
return {
index,
href,
pages,
totalPages,
mapping
};
});
return sections;
}
isVisible(view, offsetPrev, offsetNext, _container) {
var position2 = view.position();
var container = _container || this.bounds();
if (this.settings.axis === "horizontal" && position2.right > container.left - offsetPrev && position2.left < container.right + offsetNext) {
return true;
} else if (this.settings.axis === "vertical" && position2.bottom > container.top - offsetPrev && position2.top < container.bottom + offsetNext) {
return true;
}
return false;
}
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;
}
scrollBy(x, y, silent) {
let dir = this.settings.direction === "rtl" ? -1 : 1;
if (silent) {
this.ignore = true;
}
if (!this.settings.fullsize) {
if (x)
this.container.scrollLeft += x * dir;
if (y)
this.container.scrollTop += y;
} else {
window.scrollBy(x * dir, y * dir);
}
this.scrolled = true;
}
scrollTo(x, y, silent) {
if (silent) {
this.ignore = true;
}
if (!this.settings.fullsize) {
this.container.scrollLeft = x;
this.container.scrollTop = y;
} else {
window.scrollTo(x, y);
}
this.scrolled = true;
}
onScroll() {
let scrollTop;
let scrollLeft;
if (!this.settings.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(EVENTS.MANAGERS.SCROLL, {
top: scrollTop,
left: scrollLeft
});
clearTimeout(this.afterScrolled);
this.afterScrolled = setTimeout((function() {
this.emit(EVENTS.MANAGERS.SCROLLED, {
top: this.scrollTop,
left: this.scrollLeft
});
}).bind(this), 20);
} else {
this.ignore = false;
}
}
bounds() {
var bounds2;
bounds2 = this.stage.bounds();
return bounds2;
}
applyLayout(layout) {
this.layout = layout;
this.updateLayout();
if (this.views && this.views.length > 0 && this.layout.name === "pre-paginated") {
this.display(this.views.first().section);
}
}
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
);
this.settings.offset = this.layout.delta / this.layout.divisor;
}
this.viewSettings.width = this.layout.width;
this.viewSettings.height = this.layout.height;
this.setLayout(this.layout);
}
setLayout(layout) {
this.viewSettings.layout = layout;
this.mapping = new Mapping(layout.props, this.settings.direction, this.settings.axis);
if (this.views) {
this.views.forEach(function(view) {
if (view) {
view.setLayout(layout);
}
});
}
}
updateWritingMode(mode) {
this.writingMode = mode;
}
updateAxis(axis, forceUpdate) {
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 Mapping(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);
}
}
}
updateFlow(flow, defaultScrolledOverflow = "auto") {
let isPaginated = flow === "paginated" || flow === "auto";
this.isPaginated = isPaginated;
if (flow === "scrolled-doc" || flow === "scrolled-continuous" || flow === "scrolled") {
this.updateAxis("vertical");
} else {
this.updateAxis("horizontal");
}
this.viewSettings.flow = flow;
if (!this.settings.overflow) {
this.overflow = isPaginated ? "hidden" : defaultScrolledOverflow;
} else {
this.overflow = this.settings.overflow;
}
this.stage && this.stage.overflow(this.overflow);
this.updateLayout();
}
getContents() {
var contents = [];
if (!this.views) {
return contents;
}
this.views.forEach(function(view) {
const viewContents = view && view.contents;
if (viewContents) {
contents.push(viewContents);
}
});
return contents;
}
direction(dir = "ltr") {
this.settings.direction = dir;
this.stage && this.stage.direction(dir);
this.viewSettings.direction = dir;
this.updateLayout();
}
isRendered() {
return this.rendered;
}
}
EventEmitter(DefaultViewManager.prototype);
const PI_D2 = Math.PI / 2;
const EASING_EQUATIONS = {
easeOutSine: function(pos) {
return Math.sin(pos * PI_D2);
},
easeInOutSine: function(pos) {
return -0.5 * (Math.cos(Math.PI * pos) - 1);
},
easeInOutQuint: function(pos) {
if ((pos /= 0.5) < 1) {
return 0.5 * Math.pow(pos, 5);
}
return 0.5 * (Math.pow(pos - 2, 5) + 2);
},
easeInCubic: function(pos) {
return Math.pow(pos, 3);
}
};
class Snap {
constructor(manager, options) {
this.settings = extend({
duration: 80,
minVelocity: 0.2,
minDistance: 10,
easing: EASING_EQUATIONS["easeInCubic"]
}, options || {});
this.supportsTouch = this.supportsTouch();
if (this.supportsTouch) {
this.setup(manager);
}
}
setup(manager) {
this.manager = manager;
this.layout = this.manager.layout;
this.fullsize = this.manager.settings.fullsize;
if (this.fullsize) {
this.element = this.manager.stage.element;
this.scroller = window;
this.disableScroll();
} else {
this.element = this.manager.stage.container;
this.scroller = this.element;
this.element.style["WebkitOverflowScrolling"] = "touch";
}
this.manager.settings.offset = this.layout.width;
this.manager.settings.afterScrolledTimeout = this.settings.duration * 2;
this.isVertical = this.manager.settings.axis === "vertical";
if (!this.manager.isPaginated || this.isVertical) {
return;
}
this.touchCanceler = false;
this.resizeCanceler = false;
this.snapping = false;
this.scrollLeft;
this.scrollTop;
this.startTouchX = void 0;
this.startTouchY = void 0;
this.startTime = void 0;
this.endTouchX = void 0;
this.endTouchY = void 0;
this.endTime = void 0;
this.addListeners();
}
supportsTouch() {
if ("ontouchstart" in window || window.DocumentTouch && document instanceof DocumentTouch) {
return true;
}
return false;
}
disableScroll() {
this.element.style.overflow = "hidden";
}
enableScroll() {
this.element.style.overflow = "";
}
addListeners() {
this._onResize = this.onResize.bind(this);
window.addEventListener("resize", this._onResize);
this._onScroll = this.onScroll.bind(this);
this.scroller.addEventListener("scroll", this._onScroll);
this._onTouchStart = this.onTouchStart.bind(this);
this.scroller.addEventListener("touchstart", this._onTouchStart, { passive: true });
this.on("touchstart", this._onTouchStart);
this._onTouchMove = this.onTouchMove.bind(this);
this.scroller.addEventListener("touchmove", this._onTouchMove, { passive: true });
this.on("touchmove", this._onTouchMove);
this._onTouchEnd = this.onTouchEnd.bind(this);
this.scroller.addEventListener("touchend", this._onTouchEnd, { passive: true });
this.on("touchend", this._onTouchEnd);
this._afterDisplayed = this.afterDisplayed.bind(this);
this.manager.on(EVENTS.MANAGERS.ADDED, this._afterDisplayed);
}
removeListeners() {
window.removeEventListener("resize", this._onResize);
this._onResize = void 0;
this.scroller.removeEventListener("scroll", this._onScroll);
this._onScroll = void 0;
this.scroller.removeEventListener("touchstart", this._onTouchStart, { passive: true });
this.off("touchstart", this._onTouchStart);
this._onTouchStart = void 0;
this.scroller.removeEventListener("touchmove", this._onTouchMove, { passive: true });
this.off("touchmove", this._onTouchMove);
this._onTouchMove = void 0;
this.scroller.removeEventListener("touchend", this._onTouchEnd, { passive: true });
this.off("touchend", this._onTouchEnd);
this._onTouchEnd = void 0;
this.manager.off(EVENTS.MANAGERS.ADDED, this._afterDisplayed);
this._afterDisplayed = void 0;
}
afterDisplayed(view) {
let contents = view.contents;
["touchstart", "touchmove", "touchend"].forEach((e) => {
contents.on(e, (ev) => this.triggerViewEvent(ev, contents));
});
}
triggerViewEvent(e, contents) {
this.emit(e.type, e, contents);
}
onScroll(e) {
this.scrollLeft = this.fullsize ? window.scrollX : this.scroller.scrollLeft;
this.scrollTop = this.fullsize ? window.scrollY : this.scroller.scrollTop;
}
onResize(e) {
this.resizeCanceler = true;
}
onTouchStart(e) {
let { screenX, screenY } = e.touches[0];
if (this.fullsize) {
this.enableScroll();
}
this.touchCanceler = true;
if (!this.startTouchX) {
this.startTouchX = screenX;
this.startTouchY = screenY;
this.startTime = this.now();
}
this.endTouchX = screenX;
this.endTouchY = screenY;
this.endTime = this.now();
}
onTouchMove(e) {
let { screenX, screenY } = e.touches[0];
let deltaY = Math.abs(screenY - this.endTouchY);
this.touchCanceler = true;
if (!this.fullsize && deltaY < 10) {
this.element.scrollLeft -= screenX - this.endTouchX;
}
this.endTouchX = screenX;
this.endTouchY = screenY;
this.endTime = this.now();
}
onTouchEnd(e) {
if (this.fullsize) {
this.disableScroll();
}
this.touchCanceler = false;
let swipped = this.wasSwiped();
if (swipped !== 0) {
this.snap(swipped);
} else {
this.snap();
}
this.startTouchX = void 0;
this.startTouchY = void 0;
this.startTime = void 0;
this.endTouchX = void 0;
this.endTouchY = void 0;
this.endTime = void 0;
}
wasSwiped() {
let snapWidth = this.layout.pageWidth * this.layout.divisor;
let distance = this.endTouchX - this.startTouchX;
let absolute = Math.abs(distance);
let time = this.endTime - this.startTime;
let velocity = distance / time;
let minVelocity = this.settings.minVelocity;
if (absolute <= this.settings.minDistance || absolute >= snapWidth) {
return 0;
}
if (velocity > minVelocity) {
return -1;
} else if (velocity < -minVelocity) {
return 1;
}
}
needsSnap() {
let left = this.scrollLeft;
let snapWidth = this.layout.pageWidth * this.layout.divisor;
return left % snapWidth !== 0;
}
snap(howMany = 0) {
let left = this.scrollLeft;
let snapWidth = this.layout.pageWidth * this.layout.divisor;
let snapTo = Math.round(left / snapWidth) * snapWidth;
if (howMany) {
snapTo += howMany * snapWidth;
}
return this.smoothScrollTo(snapTo);
}
smoothScrollTo(destination) {
const deferred = new defer();
const start = this.scrollLeft;
const startTime = this.now();
const duration = this.settings.duration;
const easing = this.settings.easing;
this.snapping = true;
function tick() {
const now2 = this.now();
const time = Math.min(1, (now2 - startTime) / duration);
easing(time);
if (this.touchCanceler || this.resizeCanceler) {
this.resizeCanceler = false;
this.snapping = false;
deferred.resolve();
return;
}
if (time < 1) {
window.requestAnimationFrame(tick.bind(this));
this.scrollTo(start + (destination - start) * time, 0);
} else {
this.scrollTo(destination, 0);
this.snapping = false;
deferred.resolve();
}
}
tick.call(this);
return deferred.promise;
}
scrollTo(left = 0, top = 0) {
if (this.fullsize) {
window.scroll(left, top);
} else {
this.scroller.scrollLeft = left;
this.scroller.scrollTop = top;
}
}
now() {
return "now" in window.performance ? performance.now() : (/* @__PURE__ */ new Date()).getTime();
}
destroy() {
if (!this.scroller) {
return;
}
if (this.fullsize) {
this.enableScroll();
}
this.removeListeners();
this.scroller = void 0;
}
}
EventEmitter(Snap.prototype);
class ContinuousViewManager extends DefaultViewManager {
constructor(options) {
super(options);
this.name = "continuous";
this.settings = extend(this.settings || {}, {
infinite: true,
overflow: void 0,
axis: void 0,
writingMode: void 0,
flow: "scrolled",
offset: 500,
offsetDelta: 250,
width: void 0,
height: void 0,
snap: false,
afterScrolledTimeout: 10,
allowScriptedContent: false,
allowPopups: false
});
extend(this.settings, options.settings || {});
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,
allowScriptedContent: this.settings.allowScriptedContent,
allowPopups: this.settings.allowPopups
};
this.scrollTop = 0;
this.scrollLeft = 0;
}
display(section, target) {
return DefaultViewManager.prototype.display.call(this, section, target).then((function() {
return this.fill();
}).bind(this));
}
fill(_full) {
var full = _full || new defer();
this.q.enqueue(() => {
return this.check();
}).then((result) => {
if (result) {
this.fill(full);
} else {
full.resolve();
}
});
return full.promise;
}
moveTo(offset) {
var distX = 0, distY = 0;
if (!this.isPaginated) {
distY = offset.top;
offset.top + this.settings.offsetDelta;
} else {
distX = Math.floor(offset.left / this.layout.delta) * this.layout.delta;
distX + this.settings.offsetDelta;
}
if (distX > 0 || distY > 0) {
this.scrollBy(distX, distY, true);
}
}
afterResized(view) {
this.emit(EVENTS.MANAGERS.RESIZE, view.section);
}
// Remove Previous Listeners if present
removeShownListeners(view) {
view.onDisplayed = function() {
};
}
add(section) {
var view = this.createView(section);
this.views.append(view);
view.on(EVENTS.VIEWS.RESIZED, (bounds2) => {
view.expanded = true;
});
view.on(EVENTS.VIEWS.AXIS, (axis) => {
this.updateAxis(axis);
});
view.on(EVENTS.VIEWS.WRITING_MODE, (mode) => {
this.updateWritingMode(mode);
});
view.onDisplayed = this.afterDisplayed.bind(this);
view.onResize = this.afterResized.bind(this);
return view.display(this.request);
}
append(section) {
var view = this.createView(section);
view.on(EVENTS.VIEWS.RESIZED, (bounds2) => {
view.expanded = true;
});
view.on(EVENTS.VIEWS.AXIS, (axis) => {
this.updateAxis(axis);
});
view.on(EVENTS.VIEWS.WRITING_MODE, (mode) => {
this.updateWritingMode(mode);
});
this.views.append(view);
view.onDisplayed = this.afterDisplayed.bind(this);
return view;
}
prepend(section) {
var view = this.createView(section);
view.on(EVENTS.VIEWS.RESIZED, (bounds2) => {
this.counter(bounds2);
view.expanded = true;
});
view.on(EVENTS.VIEWS.AXIS, (axis) => {
this.updateAxis(axis);
});
view.on(EVENTS.VIEWS.WRITING_MODE, (mode) => {
this.updateWritingMode(mode);
});
this.views.prepend(view);
view.onDisplayed = this.afterDisplayed.bind(this);
return view;
}
counter(bounds2) {
if (this.settings.axis === "vertical") {
this.scrollBy(0, bounds2.heightDelta, true);
} else {
this.scrollBy(bounds2.widthDelta, 0, true);
}
}
update(_offset) {
var container = this.bounds();
var views = this.views.all();
var viewsLength = views.length;
var offset = typeof _offset != "undefined" ? _offset : this.settings.offset || 0;
var isVisible;
var view;
var updating = new defer();
var promises = [];
for (var i = 0; i < viewsLength; i++) {
view = views[i];
isVisible = this.isVisible(view, offset, offset, container);
if (isVisible === true) {
if (!view.displayed) {
let displayed = view.display(this.request).then(function(view2) {
view2.show();
}, (err) => {
view.hide();
});
promises.push(displayed);
} else {
view.show();
}
} else {
this.q.enqueue(view.destroy.bind(view));
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((err) => {
updating.reject(err);
});
} else {
updating.resolve();
return updating.promise;
}
}
check(_offsetLeft, _offsetTop) {
var checking = new 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 bounds2 = this._bounds;
let offset = horizontal ? this.scrollLeft : this.scrollTop;
let visibleLength = horizontal ? Math.floor(bounds2.width) : bounds2.height;
let contentLength = horizontal ? this.container.scrollWidth : this.container.scrollHeight;
let writingMode = this.writingMode && this.writingMode.indexOf("vertical") === 0 ? "vertical" : "horizontal";
let rtlScrollType = this.settings.rtlScrollType;
let rtl = this.settings.direction === "rtl";
if (!this.settings.fullsize) {
if (rtl && rtlScrollType === "default" && writingMode === "horizontal") {
offset = contentLength - visibleLength - offset;
}
if (rtl && rtlScrollType === "negative" && writingMode === "horizontal") {
offset = offset * -1;
}
} else {
if (horizontal && rtl && rtlScrollType === "negative" || !horizontal && rtl && rtlScrollType === "default") {
offset = offset * -1;
}
}
let prepend = () => {
let first = this.views.first();
let prev = first && first.section.prev();
if (prev) {
newViews.push(this.prepend(prev));
}
};
let append = () => {
let last = this.views.last();
let next = last && last.section.next();
if (next) {
newViews.push(this.append(next));
}
};
let end = offset + visibleLength + delta;
let start = offset - delta;
if (end >= contentLength) {
append();
}
if (start < 0) {
prepend();
}
let promises = newViews.map((view) => {
return view.display(this.request);
});
if (newViews.length) {
return Promise.all(promises).then(() => {
return this.check();
}).then(() => {
return this.update(delta);
}, (err) => {
return err;
});
} else {
this.q.enqueue((function() {
this.update();
}).bind(this));
checking.resolve(false);
return checking.promise;
}
}
trim() {
var task = new 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);
for (var i = 0; i < above.length - 1; i++) {
this.erase(above[i], above);
}
for (var j = 1; j < below.length; j++) {
this.erase(below[j]);
}
task.resolve();
return task.promise;
}
erase(view, above) {
var prevTop;
var prevLeft;
if (!this.settings.fullsize) {
prevTop = this.container.scrollTop;
prevLeft = this.container.scrollLeft;
} else {
prevTop = window.scrollY;
prevLeft = window.scrollX;
}
var bounds2 = view.bounds();
this.views.remove(view);
if (above) {
if (this.settings.axis === "vertical") {
this.scrollTo(0, prevTop - bounds2.height, true);
} else {
if (this.settings.direction === "rtl") {
if (!this.settings.fullsize) {
this.scrollTo(prevLeft, 0, true);
} else {
this.scrollTo(prevLeft + Math.floor(bounds2.width), 0, true);
}
} else {
this.scrollTo(prevLeft - Math.floor(bounds2.width), 0, true);
}
}
}
}
addEventListeners(stage) {
window.addEventListener("unload", (function(e) {
this.ignore = true;
this.destroy();
}).bind(this));
this.addScrollListeners();
if (this.isPaginated && this.settings.snap) {
this.snapper = new Snap(this, this.settings.snap && typeof this.settings.snap === "object" && this.settings.snap);
}
}
addScrollListeners() {
var scroller;
this.tick = requestAnimationFrame$1;
let dir = this.settings.direction === "rtl" && this.settings.rtlScrollType === "default" ? -1 : 1;
this.scrollDeltaVert = 0;
this.scrollDeltaHorz = 0;
if (!this.settings.fullsize) {
scroller = this.container;
this.scrollTop = this.container.scrollTop;
this.scrollLeft = this.container.scrollLeft;
} else {
scroller = window;
this.scrollTop = window.scrollY * dir;
this.scrollLeft = window.scrollX * dir;
}
this._onScroll = this.onScroll.bind(this);
scroller.addEventListener("scroll", this._onScroll);
this._scrolled = debounce$2(this.scrolled.bind(this), 30);
this.didScroll = false;
}
removeEventListeners() {
var scroller;
if (!this.settings.fullsize) {
scroller = this.container;
} else {
scroller = window;
}
scroller.removeEventListener("scroll", this._onScroll);
this._onScroll = void 0;
}
onScroll() {
let scrollTop;
let scrollLeft;
let dir = this.settings.direction === "rtl" && this.settings.rtlScrollType === "default" ? -1 : 1;
if (!this.settings.fullsize) {
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);
clearTimeout(this.afterScrolled);
this.didScroll = false;
}
scrolled() {
this.q.enqueue((function() {
return this.check();
}).bind(this));
this.emit(EVENTS.MANAGERS.SCROLL, {
top: this.scrollTop,
left: this.scrollLeft
});
clearTimeout(this.afterScrolled);
this.afterScrolled = setTimeout((function() {
if (this.snapper && this.snapper.supportsTouch && this.snapper.needsSnap()) {
return;
}
this.emit(EVENTS.MANAGERS.SCROLLED, {
top: this.scrollTop,
left: this.scrollLeft
});
}).bind(this), this.settings.afterScrolledTimeout);
}
next() {
let 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() {
return this.check();
}).bind(this));
}
prev() {
let 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() {
return this.check();
}).bind(this));
}
updateFlow(flow) {
if (this.rendered && this.snapper) {
this.snapper.destroy();
this.snapper = void 0;
}
super.updateFlow(flow, "scroll");
if (this.rendered && this.isPaginated && this.settings.snap) {
this.snapper = new Snap(this, this.settings.snap && typeof this.settings.snap === "object" && this.settings.snap);
}
}
destroy() {
super.destroy();
if (this.snapper) {
this.snapper.destroy();
}
}
}
class Rendition {
constructor(book, options) {
this.settings = extend(this.settings || {}, {
width: null,
height: null,
ignoreClass: "",
manager: "default",
view: "iframe",
flow: null,
layout: null,
spread: null,
minSpreadWidth: 800,
stylesheet: null,
resizeOnOrientationChange: true,
script: null,
snap: false,
defaultDirection: "ltr",
allowScriptedContent: false,
allowPopups: false
});
extend(this.settings, options);
if (typeof this.settings.manager === "object") {
this.manager = this.settings.manager;
}
this.book = book;
this.hooks = {};
this.hooks.display = new Hook(this);
this.hooks.serialize = new Hook(this);
this.hooks.content = new Hook(this);
this.hooks.unloaded = new Hook(this);
this.hooks.layout = new Hook(this);
this.hooks.render = new Hook(this);
this.hooks.show = new Hook(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));
}
this.themes = new Themes(this);
this.annotations = new Annotations(this);
this.epubcfi = new EpubCFI();
this.q = new Queue(this);
this.location = void 0;
this.q.enqueue(this.book.opened);
this.starting = new defer();
this.started = this.starting.promise;
this.q.enqueue(this.start);
}
/**
* Set the manager function
* @param {function} manager
*/
setManager(manager) {
this.manager = manager;
}
/**
* Require the manager from passed string, or as a class function
* @param {string|object} manager [description]
* @return {method}
*/
requireManager(manager) {
var viewManager;
if (typeof manager === "string" && manager === "default") {
viewManager = DefaultViewManager;
} else if (typeof manager === "string" && manager === "continuous") {
viewManager = ContinuousViewManager;
} else {
viewManager = manager;
}
return viewManager;
}
/**
* Require the view from passed string, or as a class function
* @param {string|object} view
* @return {view}
*/
requireView(view) {
var View;
if (typeof view == "string" && view === "iframe") {
View = IframeView;
} else {
View = view;
}
return View;
}
/**
* Start the rendering
* @return {Promise} rendering has started
*/
start() {
if (!this.settings.layout && (this.book.package.metadata.layout === "pre-paginated" || this.book.displayOptions.fixedLayout === "true")) {
this.settings.layout = "pre-paginated";
}
switch (this.book.package.metadata.spread) {
case "none":
this.settings.spread = "none";
break;
case "both":
this.settings.spread = true;
break;
}
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 || this.settings.defaultDirection);
this.settings.globalLayoutProperties = this.determineLayoutProperties(this.book.package.metadata);
this.flow(this.settings.globalLayoutProperties.flow);
this.layout(this.settings.globalLayoutProperties);
this.manager.on(EVENTS.MANAGERS.ADDED, this.afterDisplayed.bind(this));
this.manager.on(EVENTS.MANAGERS.REMOVED, this.afterRemoved.bind(this));
this.manager.on(EVENTS.MANAGERS.RESIZED, this.onResized.bind(this));
this.manager.on(EVENTS.MANAGERS.ORIENTATION_CHANGE, this.onOrientationChange.bind(this));
this.manager.on(EVENTS.MANAGERS.SCROLLED, this.reportLocation.bind(this));
this.emit(EVENTS.RENDITION.STARTED);
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}
*/
attachTo(element) {
return this.q.enqueue((function() {
this.manager.render(element, {
"width": this.settings.width,
"height": this.settings.height
});
this.emit(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}
*/
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}
*/
_display(target) {
if (!this.book) {
return;
}
this.epubcfi.isCfiString(target);
var displaying = new defer();
var displayed = displaying.promise;
var section;
this.displaying = displaying;
if (this.book.locations.length() && isFloat(target)) {
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(() => {
displaying.resolve(section);
this.displaying = void 0;
this.emit(EVENTS.RENDITION.DISPLAYED, section);
this.reportLocation();
}, (err) => {
this.emit(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
*/
afterDisplayed(view) {
view.on(EVENTS.VIEWS.MARK_CLICKED, (cfiRange, data) => this.triggerMarkEvent(cfiRange, data, view.contents));
this.hooks.render.trigger(view, this).then(() => {
if (view.contents) {
this.hooks.content.trigger(view.contents, this).then(() => {
this.emit(EVENTS.RENDITION.RENDERED, view.section, view);
});
} else {
this.emit(EVENTS.RENDITION.RENDERED, view.section, view);
}
});
}
/**
* Report what has been removed
* @private
* @param {*} view
*/
afterRemoved(view) {
this.hooks.unloaded.trigger(view, this).then(() => {
this.emit(EVENTS.RENDITION.REMOVED, view.section, view);
});
}
/**
* Report resize events and display the last seen location
* @private
*/
onResized(size, epubcfi) {
this.emit(EVENTS.RENDITION.RESIZED, {
width: size.width,
height: size.height
}, epubcfi);
if (this.location && this.location.start) {
this.display(epubcfi || this.location.start.cfi);
}
}
/**
* Report orientation events and display the last seen location
* @private
*/
onOrientationChange(orientation) {
this.emit(EVENTS.RENDITION.ORIENTATION_CHANGE, orientation);
}
/**
* Move the Rendition to a specific offset
* Usually you would be better off calling display()
* @param {object} offset
*/
moveTo(offset) {
this.manager.moveTo(offset);
}
/**
* Trigger a resize of the views
* @param {number} [width]
* @param {number} [height]
* @param {string} [epubcfi] (optional)
*/
resize(width, height, epubcfi) {
if (width) {
this.settings.width = width;
}
if (height) {
this.settings.height = height;
}
this.manager.resize(width, height, epubcfi);
}
/**
* Clear all rendered views
*/
clear() {
this.manager.clear();
}
/**
* Go to the next "page" in the rendition
* @return {Promise}
*/
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}
*/
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
*/
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))
;
properties = {
layout,
spread,
orientation,
flow,
viewport,
minSpreadWidth,
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
*/
flow(flow) {
var _flow = flow;
if (flow === "scrolled" || flow === "scrolled-doc" || flow === "scrolled-continuous") {
_flow = "scrolled";
}
if (flow === "auto" || flow === "paginated") {
_flow = "paginated";
}
this.settings.flow = flow;
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
*/
layout(settings) {
if (settings) {
this._layout = new Layout(settings);
this._layout.spread(settings.spread, this.settings.minSpreadWidth);
this._layout.on(EVENTS.LAYOUT.UPDATED, (props, changed) => {
this.emit(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
*/
spread(spread, min) {
this.settings.spread = spread;
if (min) {
this.settings.minSpreadWidth = min;
}
if (this._layout) {
this._layout.spread(spread, min);
}
if (this.manager && this.manager.isRendered()) {
this.manager.updateLayout();
}
}
/**
* Adjust the direction of the rendition
* @param {string} dir
*/
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
*/
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) {
let located = this.located(result);
if (!located || !located.start || !located.end) {
return;
}
this.location = located;
this.emit(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(EVENTS.RENDITION.RELOCATED, this.location);
}).bind(this));
} else if (location) {
let located = this.located(location);
if (!located || !located.start || !located.end) {
return;
}
this.location = located;
this.emit(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(EVENTS.RENDITION.RELOCATED, this.location);
}
}).bind(this));
}).bind(this));
}
/**
* Get the Current Location object
* @return {displayedLocation | promise} location (may be a promise)
*/
currentLocation() {
var location = this.manager.currentLocation();
if (location && location.then && typeof location.then === "function") {
location.then((function(result) {
let located = this.located(result);
return located;
}).bind(this));
} else if (location) {
let located = this.located(location);
return located;
}
}
/**
* Creates a Rendition#locationRange from location
* passed by the Manager
* @returns {displayedLocation}
* @private
*/
located(location) {
if (!location.length) {
return {};
}
let start = location[0];
let end = location[location.length - 1];
let 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
}
}
};
let locationStart = this.book.locations.locationFromCfi(start.mapping.start);
let 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);
}
let pageStart = this.book.pageList.pageFromCfi(start.mapping.start);
let 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
*/
destroy() {
this.manager && this.manager.destroy();
this.book = void 0;
}
/**
* Pass the events from a view's Contents
* @private
* @param {Contents} view contents
*/
passEvents(contents) {
DOM_EVENTS.forEach((e) => {
contents.on(e, (ev) => this.triggerViewEvent(ev, contents));
});
contents.on(EVENTS.CONTENTS.SELECTED, (e) => this.triggerSelectedEvent(e, contents));
}
/**
* Emit events passed by a view
* @private
* @param {event} e
*/
triggerViewEvent(e, contents) {
this.emit(e.type, e, contents);
}
/**
* Emit a selection event's CFI Range passed from a a view
* @private
* @param {string} cfirange
*/
triggerSelectedEvent(cfirange, contents) {
this.emit(EVENTS.RENDITION.SELECTED, cfirange, contents);
}
/**
* Emit a markClicked event with the cfiRange and data from a mark
* @private
* @param {EpubCFI} cfirange
*/
triggerMarkEvent(cfiRange, data, contents) {
this.emit(EVENTS.RENDITION.MARK_CLICKED, cfiRange, data, contents);
}
/**
* Get a Range from a Visible CFI
* @param {string} cfi EpubCfi String
* @param {string} ignoreClass
* @return {range}
*/
getRange(cfi, ignoreClass) {
var _cfi = new EpubCFI(cfi);
var found = this.manager.visible().filter(function(view) {
if (_cfi.spinePos === view.index)
return true;
});
if (found.length) {
return found[0].contents.range(_cfi, ignoreClass);
}
}
/**
* Hook to adjust images to fit in columns
* @param {Contents} contents
* @private
*/
adjustImages(contents) {
if (this._layout.name === "pre-paginated") {
return new Promise(function(resolve) {
resolve();
});
}
let computed = contents.window.getComputedStyle(contents.content, null);
let height = (contents.content.offsetHeight - (parseFloat(computed.paddingTop) + parseFloat(computed.paddingBottom))) * 0.95;
let horizontalPadding = parseFloat(computed.paddingLeft) + parseFloat(computed.paddingRight);
contents.addStylesheetRules({
"img": {
"max-width": (this._layout.columnWidth ? this._layout.columnWidth - horizontalPadding + "px" : "100%") + "!important",
"max-height": height + "px!important",
"object-fit": "contain",
"page-break-inside": "avoid",
"break-inside": "avoid",
"box-sizing": "border-box"
},
"svg": {
"max-width": (this._layout.columnWidth ? this._layout.columnWidth - horizontalPadding + "px" : "100%") + "!important",
"max-height": height + "px!important",
"page-break-inside": "avoid",
"break-inside": "avoid"
}
});
return new Promise(function(resolve, reject) {
setTimeout(function() {
resolve();
}, 1);
});
}
/**
* Get the Contents object of each rendered view
* @returns {Contents[]}
*/
getContents() {
return this.manager ? this.manager.getContents() : [];
}
/**
* Get the views member from the manager
* @returns {Views}
*/
views() {
let views = this.manager ? this.manager.views : void 0;
return views || [];
}
/**
* Hook to handle link clicks in rendered content
* @param {Contents} contents
* @private
*/
handleLinks(contents) {
if (contents) {
contents.on(EVENTS.CONTENTS.LINK_CLICKED, (href) => {
let relative = this.book.path.relative(href);
this.display(relative);
});
}
}
/**
* Hook to handle injecting stylesheet before
* a Section is serialized
* @param {document} doc
* @param {Section} section
* @private
*/
injectStylesheet(doc, section) {
let 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
*/
injectScript(doc, section) {
let script = doc.createElement("script");
script.setAttribute("type", "text/javascript");
script.setAttribute("src", this.settings.script);
script.textContent = " ";
doc.getElementsByTagName("head")[0].appendChild(script);
}
/**
* Hook to handle the document identifier before
* a Section is serialized
* @param {document} doc
* @param {Section} section
* @private
*/
injectIdentifier(doc, section) {
let ident = this.book.packaging.metadata.identifier;
let meta = doc.createElement("meta");
meta.setAttribute("name", "dc.relation.ispartof");
if (ident) {
meta.setAttribute("content", ident);
}
doc.getElementsByTagName("head")[0].appendChild(meta);
}
}
EventEmitter(Rendition.prototype);
class Archive {
constructor() {
this.zip = void 0;
this.urlCache = {};
this.checkRequirements();
}
/**
* Checks to see if JSZip exists in global namspace,
* Requires JSZip if it isn't there
* @private
*/
checkRequirements() {
try {
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
*/
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
*/
openUrl(zipUrl, isBase64) {
return request(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<Blob | string | JSON | Document | XMLDocument>}
*/
request(url, type2) {
var deferred = new defer();
var response;
var path2 = new Path(url);
if (!type2) {
type2 = path2.extension;
}
if (type2 == "blob") {
response = this.getBlob(url);
} else {
response = this.getText(url);
}
if (response) {
response.then((function(r) {
let result = this.handleResponse(r, type2);
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
*/
handleResponse(response, type2) {
var r;
if (type2 == "json") {
r = JSON.parse(response);
} else if (isXml(type2)) {
r = parse(response, "text/xml");
} else if (type2 == "xhtml") {
r = parse(response, "application/xhtml+xml");
} else if (type2 == "html" || type2 == "htm") {
r = parse(response, "text/html");
} else {
r = response;
}
return r;
}
/**
* Get a Blob from Archive by Url
* @param {string} url
* @param {string} [mimeType]
* @return {Blob}
*/
getBlob(url, mimeType) {
var decodededUrl = window.decodeURIComponent(url.substr(1));
var entry = this.zip.file(decodededUrl);
if (entry) {
mimeType = mimeType || mime.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}
*/
getText(url, encoding) {
var decodededUrl = window.decodeURIComponent(url.substr(1));
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
*/
getBase64(url, mimeType) {
var decodededUrl = window.decodeURIComponent(url.substr(1));
var entry = this.zip.file(decodededUrl);
if (entry) {
mimeType = mimeType || mime.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
*/
createUrl(url, options) {
var deferred = new defer();
var _URL2 = 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(tempUrl2) {
this.urlCache[url] = tempUrl2;
deferred.resolve(tempUrl2);
}).bind(this));
}
} else {
response = this.getBlob(url);
if (response) {
response.then((function(blob) {
tempUrl = _URL2.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 archive item
* @param {string} url url of the item in the archive
*/
revokeUrl(url) {
var _URL2 = window.URL || window.webkitURL || window.mozURL;
var fromCache = this.urlCache[url];
if (fromCache)
_URL2.revokeObjectURL(fromCache);
}
destroy() {
var _URL2 = window.URL || window.webkitURL || window.mozURL;
for (let fromCache in this.urlCache) {
_URL2.revokeObjectURL(fromCache);
}
this.zip = void 0;
this.urlCache = {};
}
}
function commonjsRequire(path2) {
throw new Error('Could not dynamically require "' + path2 + '". Please configure the dynamicRequireTargets or/and ignoreDynamicRequires option of @rollup/plugin-commonjs appropriately for this require call to work.');
}
var localforage$1 = { exports: {} };
/*!
localForage -- Offline Storage, Improved
Version 1.10.0
https://localforage.github.io/localForage
(c) 2013-2017 Mozilla, Apache License 2.0
*/
(function(module2, exports3) {
(function(f) {
{
module2.exports = f();
}
})(function() {
return function e(t, n, r) {
function s(o2, u) {
if (!n[o2]) {
if (!t[o2]) {
var a = typeof commonjsRequire == "function" && commonjsRequire;
if (!u && a)
return a(o2, true);
if (i)
return i(o2, true);
var f = new Error("Cannot find module '" + o2 + "'");
throw f.code = "MODULE_NOT_FOUND", f;
}
var l = n[o2] = { exports: {} };
t[o2][0].call(l.exports, function(e2) {
var n2 = t[o2][1][e2];
return s(n2 ? n2 : e2);
}, l, l.exports, e, t, n, r);
}
return n[o2].exports;
}
var i = typeof commonjsRequire == "function" && commonjsRequire;
for (var o = 0; o < r.length; o++)
s(r[o]);
return s;
}({ 1: [function(_dereq_, module3, exports4) {
(function(global2) {
var Mutation = global2.MutationObserver || global2.WebKitMutationObserver;
var scheduleDrain;
{
if (Mutation) {
var called = 0;
var observer = new Mutation(nextTick);
var element = global2.document.createTextNode("");
observer.observe(element, {
characterData: true
});
scheduleDrain = function() {
element.data = called = ++called % 2;
};
} else if (!global2.setImmediate && typeof global2.MessageChannel !== "undefined") {
var channel = new global2.MessageChannel();
channel.port1.onmessage = nextTick;
scheduleDrain = function() {
channel.port2.postMessage(0);
};
} else if ("document" in global2 && "onreadystatechange" in global2.document.createElement("script")) {
scheduleDrain = function() {
var scriptEl = global2.document.createElement("script");
scriptEl.onreadystatechange = function() {
nextTick();
scriptEl.onreadystatechange = null;
scriptEl.parentNode.removeChild(scriptEl);
scriptEl = null;
};
global2.document.documentElement.appendChild(scriptEl);
};
} else {
scheduleDrain = function() {
setTimeout(nextTick, 0);
};
}
}
var draining;
var queue = [];
function nextTick() {
draining = true;
var i, oldQueue;
var len = queue.length;
while (len) {
oldQueue = queue;
queue = [];
i = -1;
while (++i < len) {
oldQueue[i]();
}
len = queue.length;
}
draining = false;
}
module3.exports = immediate;
function immediate(task) {
if (queue.push(task) === 1 && !draining) {
scheduleDrain();
}
}
}).call(this, typeof commonjsGlobal !== "undefined" ? commonjsGlobal : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {});
}, {}], 2: [function(_dereq_, module3, exports4) {
var immediate = _dereq_(1);
function INTERNAL() {
}
var handlers = {};
var REJECTED = ["REJECTED"];
var FULFILLED = ["FULFILLED"];
var PENDING = ["PENDING"];
module3.exports = Promise2;
function Promise2(resolver) {
if (typeof resolver !== "function") {
throw new TypeError("resolver must be a function");
}
this.state = PENDING;
this.queue = [];
this.outcome = void 0;
if (resolver !== INTERNAL) {
safelyResolveThenable(this, resolver);
}
}
Promise2.prototype["catch"] = function(onRejected) {
return this.then(null, onRejected);
};
Promise2.prototype.then = function(onFulfilled, onRejected) {
if (typeof onFulfilled !== "function" && this.state === FULFILLED || typeof onRejected !== "function" && this.state === REJECTED) {
return this;
}
var promise = new this.constructor(INTERNAL);
if (this.state !== PENDING) {
var resolver = this.state === FULFILLED ? onFulfilled : onRejected;
unwrap(promise, resolver, this.outcome);
} else {
this.queue.push(new QueueItem(promise, onFulfilled, onRejected));
}
return promise;
};
function QueueItem(promise, onFulfilled, onRejected) {
this.promise = promise;
if (typeof onFulfilled === "function") {
this.onFulfilled = onFulfilled;
this.callFulfilled = this.otherCallFulfilled;
}
if (typeof onRejected === "function") {
this.onRejected = onRejected;
this.callRejected = this.otherCallRejected;
}
}
QueueItem.prototype.callFulfilled = function(value) {
handlers.resolve(this.promise, value);
};
QueueItem.prototype.otherCallFulfilled = function(value) {
unwrap(this.promise, this.onFulfilled, value);
};
QueueItem.prototype.callRejected = function(value) {
handlers.reject(this.promise, value);
};
QueueItem.prototype.otherCallRejected = function(value) {
unwrap(this.promise, this.onRejected, value);
};
function unwrap(promise, func, value) {
immediate(function() {
var returnValue;
try {
returnValue = func(value);
} catch (e) {
return handlers.reject(promise, e);
}
if (returnValue === promise) {
handlers.reject(promise, new TypeError("Cannot resolve promise with itself"));
} else {
handlers.resolve(promise, returnValue);
}
});
}
handlers.resolve = function(self2, value) {
var result = tryCatch(getThen, value);
if (result.status === "error") {
return handlers.reject(self2, result.value);
}
var thenable = result.value;
if (thenable) {
safelyResolveThenable(self2, thenable);
} else {
self2.state = FULFILLED;
self2.outcome = value;
var i = -1;
var len = self2.queue.length;
while (++i < len) {
self2.queue[i].callFulfilled(value);
}
}
return self2;
};
handlers.reject = function(self2, error) {
self2.state = REJECTED;
self2.outcome = error;
var i = -1;
var len = self2.queue.length;
while (++i < len) {
self2.queue[i].callRejected(error);
}
return self2;
};
function getThen(obj) {
var then = obj && obj.then;
if (obj && (typeof obj === "object" || typeof obj === "function") && typeof then === "function") {
return function appyThen() {
then.apply(obj, arguments);
};
}
}
function safelyResolveThenable(self2, thenable) {
var called = false;
function onError(value) {
if (called) {
return;
}
called = true;
handlers.reject(self2, value);
}
function onSuccess(value) {
if (called) {
return;
}
called = true;
handlers.resolve(self2, value);
}
function tryToUnwrap() {
thenable(onSuccess, onError);
}
var result = tryCatch(tryToUnwrap);
if (result.status === "error") {
onError(result.value);
}
}
function tryCatch(func, value) {
var out = {};
try {
out.value = func(value);
out.status = "success";
} catch (e) {
out.status = "error";
out.value = e;
}
return out;
}
Promise2.resolve = resolve;
function resolve(value) {
if (value instanceof this) {
return value;
}
return handlers.resolve(new this(INTERNAL), value);
}
Promise2.reject = reject;
function reject(reason) {
var promise = new this(INTERNAL);
return handlers.reject(promise, reason);
}
Promise2.all = all;
function all(iterable) {
var self2 = this;
if (Object.prototype.toString.call(iterable) !== "[object Array]") {
return this.reject(new TypeError("must be an array"));
}
var len = iterable.length;
var called = false;
if (!len) {
return this.resolve([]);
}
var values = new Array(len);
var resolved = 0;
var i = -1;
var promise = new this(INTERNAL);
while (++i < len) {
allResolver(iterable[i], i);
}
return promise;
function allResolver(value, i2) {
self2.resolve(value).then(resolveFromAll, function(error) {
if (!called) {
called = true;
handlers.reject(promise, error);
}
});
function resolveFromAll(outValue) {
values[i2] = outValue;
if (++resolved === len && !called) {
called = true;
handlers.resolve(promise, values);
}
}
}
}
Promise2.race = race;
function race(iterable) {
var self2 = this;
if (Object.prototype.toString.call(iterable) !== "[object Array]") {
return this.reject(new TypeError("must be an array"));
}
var len = iterable.length;
var called = false;
if (!len) {
return this.resolve([]);
}
var i = -1;
var promise = new this(INTERNAL);
while (++i < len) {
resolver(iterable[i]);
}
return promise;
function resolver(value) {
self2.resolve(value).then(function(response) {
if (!called) {
called = true;
handlers.resolve(promise, response);
}
}, function(error) {
if (!called) {
called = true;
handlers.reject(promise, error);
}
});
}
}
}, { "1": 1 }], 3: [function(_dereq_, module3, exports4) {
(function(global2) {
if (typeof global2.Promise !== "function") {
global2.Promise = _dereq_(2);
}
}).call(this, typeof commonjsGlobal !== "undefined" ? commonjsGlobal : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {});
}, { "2": 2 }], 4: [function(_dereq_, module3, exports4) {
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 _classCallCheck2(instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
}
function getIDB() {
try {
if (typeof indexedDB !== "undefined") {
return indexedDB;
}
if (typeof webkitIndexedDB !== "undefined") {
return webkitIndexedDB;
}
if (typeof mozIndexedDB !== "undefined") {
return mozIndexedDB;
}
if (typeof OIndexedDB !== "undefined") {
return OIndexedDB;
}
if (typeof msIndexedDB !== "undefined") {
return msIndexedDB;
}
} catch (e) {
return;
}
}
var idb = getIDB();
function isIndexedDBValid() {
try {
if (!idb || !idb.open) {
return false;
}
var isSafari = typeof openDatabase !== "undefined" && /(Safari|iPhone|iPad|iPod)/.test(navigator.userAgent) && !/Chrome/.test(navigator.userAgent) && !/BlackBerry/.test(navigator.platform);
var hasFetch = typeof fetch === "function" && fetch.toString().indexOf("[native code") !== -1;
return (!isSafari || hasFetch) && typeof indexedDB !== "undefined" && // some outdated implementations of IDB that appear on Samsung
// and HTC Android devices <4.4 are missing IDBKeyRange
// See: https://github.com/mozilla/localForage/issues/128
// See: https://github.com/mozilla/localForage/issues/272
typeof IDBKeyRange !== "undefined";
} catch (e) {
return false;
}
}
function createBlob2(parts, properties) {
parts = parts || [];
properties = properties || {};
try {
return new Blob(parts, properties);
} catch (e) {
if (e.name !== "TypeError") {
throw e;
}
var Builder = typeof BlobBuilder !== "undefined" ? BlobBuilder : typeof MSBlobBuilder !== "undefined" ? MSBlobBuilder : typeof MozBlobBuilder !== "undefined" ? MozBlobBuilder : WebKitBlobBuilder;
var builder = new Builder();
for (var i = 0; i < parts.length; i += 1) {
builder.append(parts[i]);
}
return builder.getBlob(properties.type);
}
}
if (typeof Promise === "undefined") {
_dereq_(3);
}
var Promise$1 = Promise;
function executeCallback(promise, callback) {
if (callback) {
promise.then(function(result) {
callback(null, result);
}, function(error) {
callback(error);
});
}
}
function executeTwoCallbacks(promise, callback, errorCallback) {
if (typeof callback === "function") {
promise.then(callback);
}
if (typeof errorCallback === "function") {
promise["catch"](errorCallback);
}
}
function normalizeKey(key2) {
if (typeof key2 !== "string") {
console.warn(key2 + " used as a key, but it is not a string.");
key2 = String(key2);
}
return key2;
}
function getCallback() {
if (arguments.length && typeof arguments[arguments.length - 1] === "function") {
return arguments[arguments.length - 1];
}
}
var DETECT_BLOB_SUPPORT_STORE = "local-forage-detect-blob-support";
var supportsBlobs = void 0;
var dbContexts = {};
var toString = Object.prototype.toString;
var READ_ONLY = "readonly";
var READ_WRITE = "readwrite";
function _binStringToArrayBuffer(bin) {
var length2 = bin.length;
var buf = new ArrayBuffer(length2);
var arr = new Uint8Array(buf);
for (var i = 0; i < length2; i++) {
arr[i] = bin.charCodeAt(i);
}
return buf;
}
function _checkBlobSupportWithoutCaching(idb2) {
return new Promise$1(function(resolve) {
var txn = idb2.transaction(DETECT_BLOB_SUPPORT_STORE, READ_WRITE);
var blob = createBlob2([""]);
txn.objectStore(DETECT_BLOB_SUPPORT_STORE).put(blob, "key");
txn.onabort = function(e) {
e.preventDefault();
e.stopPropagation();
resolve(false);
};
txn.oncomplete = function() {
var matchedChrome = navigator.userAgent.match(/Chrome\/(\d+)/);
var matchedEdge = navigator.userAgent.match(/Edge\//);
resolve(matchedEdge || !matchedChrome || parseInt(matchedChrome[1], 10) >= 43);
};
})["catch"](function() {
return false;
});
}
function _checkBlobSupport(idb2) {
if (typeof supportsBlobs === "boolean") {
return Promise$1.resolve(supportsBlobs);
}
return _checkBlobSupportWithoutCaching(idb2).then(function(value) {
supportsBlobs = value;
return supportsBlobs;
});
}
function _deferReadiness(dbInfo) {
var dbContext = dbContexts[dbInfo.name];
var deferredOperation = {};
deferredOperation.promise = new Promise$1(function(resolve, reject) {
deferredOperation.resolve = resolve;
deferredOperation.reject = reject;
});
dbContext.deferredOperations.push(deferredOperation);
if (!dbContext.dbReady) {
dbContext.dbReady = deferredOperation.promise;
} else {
dbContext.dbReady = dbContext.dbReady.then(function() {
return deferredOperation.promise;
});
}
}
function _advanceReadiness(dbInfo) {
var dbContext = dbContexts[dbInfo.name];
var deferredOperation = dbContext.deferredOperations.pop();
if (deferredOperation) {
deferredOperation.resolve();
return deferredOperation.promise;
}
}
function _rejectReadiness(dbInfo, err) {
var dbContext = dbContexts[dbInfo.name];
var deferredOperation = dbContext.deferredOperations.pop();
if (deferredOperation) {
deferredOperation.reject(err);
return deferredOperation.promise;
}
}
function _getConnection(dbInfo, upgradeNeeded) {
return new Promise$1(function(resolve, reject) {
dbContexts[dbInfo.name] = dbContexts[dbInfo.name] || createDbContext();
if (dbInfo.db) {
if (upgradeNeeded) {
_deferReadiness(dbInfo);
dbInfo.db.close();
} else {
return resolve(dbInfo.db);
}
}
var dbArgs = [dbInfo.name];
if (upgradeNeeded) {
dbArgs.push(dbInfo.version);
}
var openreq = idb.open.apply(idb, dbArgs);
if (upgradeNeeded) {
openreq.onupgradeneeded = function(e) {
var db = openreq.result;
try {
db.createObjectStore(dbInfo.storeName);
if (e.oldVersion <= 1) {
db.createObjectStore(DETECT_BLOB_SUPPORT_STORE);
}
} catch (ex) {
if (ex.name === "ConstraintError") {
console.warn('The database "' + dbInfo.name + '" has been upgraded from version ' + e.oldVersion + " to version " + e.newVersion + ', but the storage "' + dbInfo.storeName + '" already exists.');
} else {
throw ex;
}
}
};
}
openreq.onerror = function(e) {
e.preventDefault();
reject(openreq.error);
};
openreq.onsuccess = function() {
var db = openreq.result;
db.onversionchange = function(e) {
e.target.close();
};
resolve(db);
_advanceReadiness(dbInfo);
};
});
}
function _getOriginalConnection(dbInfo) {
return _getConnection(dbInfo, false);
}
function _getUpgradedConnection(dbInfo) {
return _getConnection(dbInfo, true);
}
function _isUpgradeNeeded(dbInfo, defaultVersion) {
if (!dbInfo.db) {
return true;
}
var isNewStore = !dbInfo.db.objectStoreNames.contains(dbInfo.storeName);
var isDowngrade = dbInfo.version < dbInfo.db.version;
var isUpgrade = dbInfo.version > dbInfo.db.version;
if (isDowngrade) {
if (dbInfo.version !== defaultVersion) {
console.warn('The database "' + dbInfo.name + `" can't be downgraded from version ` + dbInfo.db.version + " to version " + dbInfo.version + ".");
}
dbInfo.version = dbInfo.db.version;
}
if (isUpgrade || isNewStore) {
if (isNewStore) {
var incVersion = dbInfo.db.version + 1;
if (incVersion > dbInfo.version) {
dbInfo.version = incVersion;
}
}
return true;
}
return false;
}
function _encodeBlob(blob) {
return new Promise$1(function(resolve, reject) {
var reader = new FileReader();
reader.onerror = reject;
reader.onloadend = function(e) {
var base64 = btoa(e.target.result || "");
resolve({
__local_forage_encoded_blob: true,
data: base64,
type: blob.type
});
};
reader.readAsBinaryString(blob);
});
}
function _decodeBlob(encodedBlob) {
var arrayBuff = _binStringToArrayBuffer(atob(encodedBlob.data));
return createBlob2([arrayBuff], { type: encodedBlob.type });
}
function _isEncodedBlob(value) {
return value && value.__local_forage_encoded_blob;
}
function _fullyReady(callback) {
var self2 = this;
var promise = self2._initReady().then(function() {
var dbContext = dbContexts[self2._dbInfo.name];
if (dbContext && dbContext.dbReady) {
return dbContext.dbReady;
}
});
executeTwoCallbacks(promise, callback, callback);
return promise;
}
function _tryReconnect(dbInfo) {
_deferReadiness(dbInfo);
var dbContext = dbContexts[dbInfo.name];
var forages = dbContext.forages;
for (var i = 0; i < forages.length; i++) {
var forage = forages[i];
if (forage._dbInfo.db) {
forage._dbInfo.db.close();
forage._dbInfo.db = null;
}
}
dbInfo.db = null;
return _getOriginalConnection(dbInfo).then(function(db) {
dbInfo.db = db;
if (_isUpgradeNeeded(dbInfo)) {
return _getUpgradedConnection(dbInfo);
}
return db;
}).then(function(db) {
dbInfo.db = dbContext.db = db;
for (var i2 = 0; i2 < forages.length; i2++) {
forages[i2]._dbInfo.db = db;
}
})["catch"](function(err) {
_rejectReadiness(dbInfo, err);
throw err;
});
}
function createTransaction(dbInfo, mode, callback, retries) {
if (retries === void 0) {
retries = 1;
}
try {
var tx = dbInfo.db.transaction(dbInfo.storeName, mode);
callback(null, tx);
} catch (err) {
if (retries > 0 && (!dbInfo.db || err.name === "InvalidStateError" || err.name === "NotFoundError")) {
return Promise$1.resolve().then(function() {
if (!dbInfo.db || err.name === "NotFoundError" && !dbInfo.db.objectStoreNames.contains(dbInfo.storeName) && dbInfo.version <= dbInfo.db.version) {
if (dbInfo.db) {
dbInfo.version = dbInfo.db.version + 1;
}
return _getUpgradedConnection(dbInfo);
}
}).then(function() {
return _tryReconnect(dbInfo).then(function() {
createTransaction(dbInfo, mode, callback, retries - 1);
});
})["catch"](callback);
}
callback(err);
}
}
function createDbContext() {
return {
// Running localForages sharing a database.
forages: [],
// Shared database.
db: null,
// Database readiness (promise).
dbReady: null,
// Deferred operations on the database.
deferredOperations: []
};
}
function _initStorage(options) {
var self2 = this;
var dbInfo = {
db: null
};
if (options) {
for (var i in options) {
dbInfo[i] = options[i];
}
}
var dbContext = dbContexts[dbInfo.name];
if (!dbContext) {
dbContext = createDbContext();
dbContexts[dbInfo.name] = dbContext;
}
dbContext.forages.push(self2);
if (!self2._initReady) {
self2._initReady = self2.ready;
self2.ready = _fullyReady;
}
var initPromises = [];
function ignoreErrors() {
return Promise$1.resolve();
}
for (var j = 0; j < dbContext.forages.length; j++) {
var forage = dbContext.forages[j];
if (forage !== self2) {
initPromises.push(forage._initReady()["catch"](ignoreErrors));
}
}
var forages = dbContext.forages.slice(0);
return Promise$1.all(initPromises).then(function() {
dbInfo.db = dbContext.db;
return _getOriginalConnection(dbInfo);
}).then(function(db) {
dbInfo.db = db;
if (_isUpgradeNeeded(dbInfo, self2._defaultConfig.version)) {
return _getUpgradedConnection(dbInfo);
}
return db;
}).then(function(db) {
dbInfo.db = dbContext.db = db;
self2._dbInfo = dbInfo;
for (var k = 0; k < forages.length; k++) {
var forage2 = forages[k];
if (forage2 !== self2) {
forage2._dbInfo.db = dbInfo.db;
forage2._dbInfo.version = dbInfo.version;
}
}
});
}
function getItem(key2, callback) {
var self2 = this;
key2 = normalizeKey(key2);
var promise = new Promise$1(function(resolve, reject) {
self2.ready().then(function() {
createTransaction(self2._dbInfo, READ_ONLY, function(err, transaction) {
if (err) {
return reject(err);
}
try {
var store = transaction.objectStore(self2._dbInfo.storeName);
var req = store.get(key2);
req.onsuccess = function() {
var value = req.result;
if (value === void 0) {
value = null;
}
if (_isEncodedBlob(value)) {
value = _decodeBlob(value);
}
resolve(value);
};
req.onerror = function() {
reject(req.error);
};
} catch (e) {
reject(e);
}
});
})["catch"](reject);
});
executeCallback(promise, callback);
return promise;
}
function iterate(iterator, callback) {
var self2 = this;
var promise = new Promise$1(function(resolve, reject) {
self2.ready().then(function() {
createTransaction(self2._dbInfo, READ_ONLY, function(err, transaction) {
if (err) {
return reject(err);
}
try {
var store = transaction.objectStore(self2._dbInfo.storeName);
var req = store.openCursor();
var iterationNumber = 1;
req.onsuccess = function() {
var cursor = req.result;
if (cursor) {
var value = cursor.value;
if (_isEncodedBlob(value)) {
value = _decodeBlob(value);
}
var result = iterator(value, cursor.key, iterationNumber++);
if (result !== void 0) {
resolve(result);
} else {
cursor["continue"]();
}
} else {
resolve();
}
};
req.onerror = function() {
reject(req.error);
};
} catch (e) {
reject(e);
}
});
})["catch"](reject);
});
executeCallback(promise, callback);
return promise;
}
function setItem(key2, value, callback) {
var self2 = this;
key2 = normalizeKey(key2);
var promise = new Promise$1(function(resolve, reject) {
var dbInfo;
self2.ready().then(function() {
dbInfo = self2._dbInfo;
if (toString.call(value) === "[object Blob]") {
return _checkBlobSupport(dbInfo.db).then(function(blobSupport) {
if (blobSupport) {
return value;
}
return _encodeBlob(value);
});
}
return value;
}).then(function(value2) {
createTransaction(self2._dbInfo, READ_WRITE, function(err, transaction) {
if (err) {
return reject(err);
}
try {
var store = transaction.objectStore(self2._dbInfo.storeName);
if (value2 === null) {
value2 = void 0;
}
var req = store.put(value2, key2);
transaction.oncomplete = function() {
if (value2 === void 0) {
value2 = null;
}
resolve(value2);
};
transaction.onabort = transaction.onerror = function() {
var err2 = req.error ? req.error : req.transaction.error;
reject(err2);
};
} catch (e) {
reject(e);
}
});
})["catch"](reject);
});
executeCallback(promise, callback);
return promise;
}
function removeItem(key2, callback) {
var self2 = this;
key2 = normalizeKey(key2);
var promise = new Promise$1(function(resolve, reject) {
self2.ready().then(function() {
createTransaction(self2._dbInfo, READ_WRITE, function(err, transaction) {
if (err) {
return reject(err);
}
try {
var store = transaction.objectStore(self2._dbInfo.storeName);
var req = store["delete"](key2);
transaction.oncomplete = function() {
resolve();
};
transaction.onerror = function() {
reject(req.error);
};
transaction.onabort = function() {
var err2 = req.error ? req.error : req.transaction.error;
reject(err2);
};
} catch (e) {
reject(e);
}
});
})["catch"](reject);
});
executeCallback(promise, callback);
return promise;
}
function clear(callback) {
var self2 = this;
var promise = new Promise$1(function(resolve, reject) {
self2.ready().then(function() {
createTransaction(self2._dbInfo, READ_WRITE, function(err, transaction) {
if (err) {
return reject(err);
}
try {
var store = transaction.objectStore(self2._dbInfo.storeName);
var req = store.clear();
transaction.oncomplete = function() {
resolve();
};
transaction.onabort = transaction.onerror = function() {
var err2 = req.error ? req.error : req.transaction.error;
reject(err2);
};
} catch (e) {
reject(e);
}
});
})["catch"](reject);
});
executeCallback(promise, callback);
return promise;
}
function length(callback) {
var self2 = this;
var promise = new Promise$1(function(resolve, reject) {
self2.ready().then(function() {
createTransaction(self2._dbInfo, READ_ONLY, function(err, transaction) {
if (err) {
return reject(err);
}
try {
var store = transaction.objectStore(self2._dbInfo.storeName);
var req = store.count();
req.onsuccess = function() {
resolve(req.result);
};
req.onerror = function() {
reject(req.error);
};
} catch (e) {
reject(e);
}
});
})["catch"](reject);
});
executeCallback(promise, callback);
return promise;
}
function key(n, callback) {
var self2 = this;
var promise = new Promise$1(function(resolve, reject) {
if (n < 0) {
resolve(null);
return;
}
self2.ready().then(function() {
createTransaction(self2._dbInfo, READ_ONLY, function(err, transaction) {
if (err) {
return reject(err);
}
try {
var store = transaction.objectStore(self2._dbInfo.storeName);
var advanced = false;
var req = store.openKeyCursor();
req.onsuccess = function() {
var cursor = req.result;
if (!cursor) {
resolve(null);
return;
}
if (n === 0) {
resolve(cursor.key);
} else {
if (!advanced) {
advanced = true;
cursor.advance(n);
} else {
resolve(cursor.key);
}
}
};
req.onerror = function() {
reject(req.error);
};
} catch (e) {
reject(e);
}
});
})["catch"](reject);
});
executeCallback(promise, callback);
return promise;
}
function keys2(callback) {
var self2 = this;
var promise = new Promise$1(function(resolve, reject) {
self2.ready().then(function() {
createTransaction(self2._dbInfo, READ_ONLY, function(err, transaction) {
if (err) {
return reject(err);
}
try {
var store = transaction.objectStore(self2._dbInfo.storeName);
var req = store.openKeyCursor();
var keys3 = [];
req.onsuccess = function() {
var cursor = req.result;
if (!cursor) {
resolve(keys3);
return;
}
keys3.push(cursor.key);
cursor["continue"]();
};
req.onerror = function() {
reject(req.error);
};
} catch (e) {
reject(e);
}
});
})["catch"](reject);
});
executeCallback(promise, callback);
return promise;
}
function dropInstance(options, callback) {
callback = getCallback.apply(this, arguments);
var currentConfig = this.config();
options = typeof options !== "function" && options || {};
if (!options.name) {
options.name = options.name || currentConfig.name;
options.storeName = options.storeName || currentConfig.storeName;
}
var self2 = this;
var promise;
if (!options.name) {
promise = Promise$1.reject("Invalid arguments");
} else {
var isCurrentDb = options.name === currentConfig.name && self2._dbInfo.db;
var dbPromise = isCurrentDb ? Promise$1.resolve(self2._dbInfo.db) : _getOriginalConnection(options).then(function(db) {
var dbContext = dbContexts[options.name];
var forages = dbContext.forages;
dbContext.db = db;
for (var i = 0; i < forages.length; i++) {
forages[i]._dbInfo.db = db;
}
return db;
});
if (!options.storeName) {
promise = dbPromise.then(function(db) {
_deferReadiness(options);
var dbContext = dbContexts[options.name];
var forages = dbContext.forages;
db.close();
for (var i = 0; i < forages.length; i++) {
var forage = forages[i];
forage._dbInfo.db = null;
}
var dropDBPromise = new Promise$1(function(resolve, reject) {
var req = idb.deleteDatabase(options.name);
req.onerror = function() {
var db2 = req.result;
if (db2) {
db2.close();
}
reject(req.error);
};
req.onblocked = function() {
console.warn('dropInstance blocked for database "' + options.name + '" until all open connections are closed');
};
req.onsuccess = function() {
var db2 = req.result;
if (db2) {
db2.close();
}
resolve(db2);
};
});
return dropDBPromise.then(function(db2) {
dbContext.db = db2;
for (var i2 = 0; i2 < forages.length; i2++) {
var _forage = forages[i2];
_advanceReadiness(_forage._dbInfo);
}
})["catch"](function(err) {
(_rejectReadiness(options, err) || Promise$1.resolve())["catch"](function() {
});
throw err;
});
});
} else {
promise = dbPromise.then(function(db) {
if (!db.objectStoreNames.contains(options.storeName)) {
return;
}
var newVersion = db.version + 1;
_deferReadiness(options);
var dbContext = dbContexts[options.name];
var forages = dbContext.forages;
db.close();
for (var i = 0; i < forages.length; i++) {
var forage = forages[i];
forage._dbInfo.db = null;
forage._dbInfo.version = newVersion;
}
var dropObjectPromise = new Promise$1(function(resolve, reject) {
var req = idb.open(options.name, newVersion);
req.onerror = function(err) {
var db2 = req.result;
db2.close();
reject(err);
};
req.onupgradeneeded = function() {
var db2 = req.result;
db2.deleteObjectStore(options.storeName);
};
req.onsuccess = function() {
var db2 = req.result;
db2.close();
resolve(db2);
};
});
return dropObjectPromise.then(function(db2) {
dbContext.db = db2;
for (var j = 0; j < forages.length; j++) {
var _forage2 = forages[j];
_forage2._dbInfo.db = db2;
_advanceReadiness(_forage2._dbInfo);
}
})["catch"](function(err) {
(_rejectReadiness(options, err) || Promise$1.resolve())["catch"](function() {
});
throw err;
});
});
}
}
executeCallback(promise, callback);
return promise;
}
var asyncStorage = {
_driver: "asyncStorage",
_initStorage,
_support: isIndexedDBValid(),
iterate,
getItem,
setItem,
removeItem,
clear,
length,
key,
keys: keys2,
dropInstance
};
function isWebSQLValid() {
return typeof openDatabase === "function";
}
var BASE_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
var BLOB_TYPE_PREFIX = "~~local_forage_type~";
var BLOB_TYPE_PREFIX_REGEX = /^~~local_forage_type~([^~]+)~/;
var SERIALIZED_MARKER = "__lfsc__:";
var SERIALIZED_MARKER_LENGTH = SERIALIZED_MARKER.length;
var TYPE_ARRAYBUFFER = "arbf";
var TYPE_BLOB = "blob";
var TYPE_INT8ARRAY = "si08";
var TYPE_UINT8ARRAY = "ui08";
var TYPE_UINT8CLAMPEDARRAY = "uic8";
var TYPE_INT16ARRAY = "si16";
var TYPE_INT32ARRAY = "si32";
var TYPE_UINT16ARRAY = "ur16";
var TYPE_UINT32ARRAY = "ui32";
var TYPE_FLOAT32ARRAY = "fl32";
var TYPE_FLOAT64ARRAY = "fl64";
var TYPE_SERIALIZED_MARKER_LENGTH = SERIALIZED_MARKER_LENGTH + TYPE_ARRAYBUFFER.length;
var toString$1 = Object.prototype.toString;
function stringToBuffer(serializedString) {
var bufferLength = serializedString.length * 0.75;
var len = serializedString.length;
var i;
var p = 0;
var encoded1, encoded2, encoded3, encoded4;
if (serializedString[serializedString.length - 1] === "=") {
bufferLength--;
if (serializedString[serializedString.length - 2] === "=") {
bufferLength--;
}
}
var buffer = new ArrayBuffer(bufferLength);
var bytes = new Uint8Array(buffer);
for (i = 0; i < len; i += 4) {
encoded1 = BASE_CHARS.indexOf(serializedString[i]);
encoded2 = BASE_CHARS.indexOf(serializedString[i + 1]);
encoded3 = BASE_CHARS.indexOf(serializedString[i + 2]);
encoded4 = BASE_CHARS.indexOf(serializedString[i + 3]);
bytes[p++] = encoded1 << 2 | encoded2 >> 4;
bytes[p++] = (encoded2 & 15) << 4 | encoded3 >> 2;
bytes[p++] = (encoded3 & 3) << 6 | encoded4 & 63;
}
return buffer;
}
function bufferToString(buffer) {
var bytes = new Uint8Array(buffer);
var base64String = "";
var i;
for (i = 0; i < bytes.length; i += 3) {
base64String += BASE_CHARS[bytes[i] >> 2];
base64String += BASE_CHARS[(bytes[i] & 3) << 4 | bytes[i + 1] >> 4];
base64String += BASE_CHARS[(bytes[i + 1] & 15) << 2 | bytes[i + 2] >> 6];
base64String += BASE_CHARS[bytes[i + 2] & 63];
}
if (bytes.length % 3 === 2) {
base64String = base64String.substring(0, base64String.length - 1) + "=";
} else if (bytes.length % 3 === 1) {
base64String = base64String.substring(0, base64String.length - 2) + "==";
}
return base64String;
}
function serialize(value, callback) {
var valueType = "";
if (value) {
valueType = toString$1.call(value);
}
if (value && (valueType === "[object ArrayBuffer]" || value.buffer && toString$1.call(value.buffer) === "[object ArrayBuffer]")) {
var buffer;
var marker = SERIALIZED_MARKER;
if (value instanceof ArrayBuffer) {
buffer = value;
marker += TYPE_ARRAYBUFFER;
} else {
buffer = value.buffer;
if (valueType === "[object Int8Array]") {
marker += TYPE_INT8ARRAY;
} else if (valueType === "[object Uint8Array]") {
marker += TYPE_UINT8ARRAY;
} else if (valueType === "[object Uint8ClampedArray]") {
marker += TYPE_UINT8CLAMPEDARRAY;
} else if (valueType === "[object Int16Array]") {
marker += TYPE_INT16ARRAY;
} else if (valueType === "[object Uint16Array]") {
marker += TYPE_UINT16ARRAY;
} else if (valueType === "[object Int32Array]") {
marker += TYPE_INT32ARRAY;
} else if (valueType === "[object Uint32Array]") {
marker += TYPE_UINT32ARRAY;
} else if (valueType === "[object Float32Array]") {
marker += TYPE_FLOAT32ARRAY;
} else if (valueType === "[object Float64Array]") {
marker += TYPE_FLOAT64ARRAY;
} else {
callback(new Error("Failed to get type for BinaryArray"));
}
}
callback(marker + bufferToString(buffer));
} else if (valueType === "[object Blob]") {
var fileReader = new FileReader();
fileReader.onload = function() {
var str2 = BLOB_TYPE_PREFIX + value.type + "~" + bufferToString(this.result);
callback(SERIALIZED_MARKER + TYPE_BLOB + str2);
};
fileReader.readAsArrayBuffer(value);
} else {
try {
callback(JSON.stringify(value));
} catch (e) {
console.error("Couldn't convert value into a JSON string: ", value);
callback(null, e);
}
}
}
function deserialize(value) {
if (value.substring(0, SERIALIZED_MARKER_LENGTH) !== SERIALIZED_MARKER) {
return JSON.parse(value);
}
var serializedString = value.substring(TYPE_SERIALIZED_MARKER_LENGTH);
var type2 = value.substring(SERIALIZED_MARKER_LENGTH, TYPE_SERIALIZED_MARKER_LENGTH);
var blobType;
if (type2 === TYPE_BLOB && BLOB_TYPE_PREFIX_REGEX.test(serializedString)) {
var matcher = serializedString.match(BLOB_TYPE_PREFIX_REGEX);
blobType = matcher[1];
serializedString = serializedString.substring(matcher[0].length);
}
var buffer = stringToBuffer(serializedString);
switch (type2) {
case TYPE_ARRAYBUFFER:
return buffer;
case TYPE_BLOB:
return createBlob2([buffer], { type: blobType });
case TYPE_INT8ARRAY:
return new Int8Array(buffer);
case TYPE_UINT8ARRAY:
return new Uint8Array(buffer);
case TYPE_UINT8CLAMPEDARRAY:
return new Uint8ClampedArray(buffer);
case TYPE_INT16ARRAY:
return new Int16Array(buffer);
case TYPE_UINT16ARRAY:
return new Uint16Array(buffer);
case TYPE_INT32ARRAY:
return new Int32Array(buffer);
case TYPE_UINT32ARRAY:
return new Uint32Array(buffer);
case TYPE_FLOAT32ARRAY:
return new Float32Array(buffer);
case TYPE_FLOAT64ARRAY:
return new Float64Array(buffer);
default:
throw new Error("Unkown type: " + type2);
}
}
var localforageSerializer = {
serialize,
deserialize,
stringToBuffer,
bufferToString
};
function createDbTable(t, dbInfo, callback, errorCallback) {
t.executeSql("CREATE TABLE IF NOT EXISTS " + dbInfo.storeName + " (id INTEGER PRIMARY KEY, key unique, value)", [], callback, errorCallback);
}
function _initStorage$1(options) {
var self2 = this;
var dbInfo = {
db: null
};
if (options) {
for (var i in options) {
dbInfo[i] = typeof options[i] !== "string" ? options[i].toString() : options[i];
}
}
var dbInfoPromise = new Promise$1(function(resolve, reject) {
try {
dbInfo.db = openDatabase(dbInfo.name, String(dbInfo.version), dbInfo.description, dbInfo.size);
} catch (e) {
return reject(e);
}
dbInfo.db.transaction(function(t) {
createDbTable(t, dbInfo, function() {
self2._dbInfo = dbInfo;
resolve();
}, function(t2, error) {
reject(error);
});
}, reject);
});
dbInfo.serializer = localforageSerializer;
return dbInfoPromise;
}
function tryExecuteSql(t, dbInfo, sqlStatement, args, callback, errorCallback) {
t.executeSql(sqlStatement, args, callback, function(t2, error) {
if (error.code === error.SYNTAX_ERR) {
t2.executeSql("SELECT name FROM sqlite_master WHERE type='table' AND name = ?", [dbInfo.storeName], function(t3, results) {
if (!results.rows.length) {
createDbTable(t3, dbInfo, function() {
t3.executeSql(sqlStatement, args, callback, errorCallback);
}, errorCallback);
} else {
errorCallback(t3, error);
}
}, errorCallback);
} else {
errorCallback(t2, error);
}
}, errorCallback);
}
function getItem$1(key2, callback) {
var self2 = this;
key2 = normalizeKey(key2);
var promise = new Promise$1(function(resolve, reject) {
self2.ready().then(function() {
var dbInfo = self2._dbInfo;
dbInfo.db.transaction(function(t) {
tryExecuteSql(t, dbInfo, "SELECT * FROM " + dbInfo.storeName + " WHERE key = ? LIMIT 1", [key2], function(t2, results) {
var result = results.rows.length ? results.rows.item(0).value : null;
if (result) {
result = dbInfo.serializer.deserialize(result);
}
resolve(result);
}, function(t2, error) {
reject(error);
});
});
})["catch"](reject);
});
executeCallback(promise, callback);
return promise;
}
function iterate$1(iterator, callback) {
var self2 = this;
var promise = new Promise$1(function(resolve, reject) {
self2.ready().then(function() {
var dbInfo = self2._dbInfo;
dbInfo.db.transaction(function(t) {
tryExecuteSql(t, dbInfo, "SELECT * FROM " + dbInfo.storeName, [], function(t2, results) {
var rows = results.rows;
var length2 = rows.length;
for (var i = 0; i < length2; i++) {
var item = rows.item(i);
var result = item.value;
if (result) {
result = dbInfo.serializer.deserialize(result);
}
result = iterator(result, item.key, i + 1);
if (result !== void 0) {
resolve(result);
return;
}
}
resolve();
}, function(t2, error) {
reject(error);
});
});
})["catch"](reject);
});
executeCallback(promise, callback);
return promise;
}
function _setItem(key2, value, callback, retriesLeft) {
var self2 = this;
key2 = normalizeKey(key2);
var promise = new Promise$1(function(resolve, reject) {
self2.ready().then(function() {
if (value === void 0) {
value = null;
}
var originalValue = value;
var dbInfo = self2._dbInfo;
dbInfo.serializer.serialize(value, function(value2, error) {
if (error) {
reject(error);
} else {
dbInfo.db.transaction(function(t) {
tryExecuteSql(t, dbInfo, "INSERT OR REPLACE INTO " + dbInfo.storeName + " (key, value) VALUES (?, ?)", [key2, value2], function() {
resolve(originalValue);
}, function(t2, error2) {
reject(error2);
});
}, function(sqlError) {
if (sqlError.code === sqlError.QUOTA_ERR) {
if (retriesLeft > 0) {
resolve(_setItem.apply(self2, [key2, originalValue, callback, retriesLeft - 1]));
return;
}
reject(sqlError);
}
});
}
});
})["catch"](reject);
});
executeCallback(promise, callback);
return promise;
}
function setItem$1(key2, value, callback) {
return _setItem.apply(this, [key2, value, callback, 1]);
}
function removeItem$1(key2, callback) {
var self2 = this;
key2 = normalizeKey(key2);
var promise = new Promise$1(function(resolve, reject) {
self2.ready().then(function() {
var dbInfo = self2._dbInfo;
dbInfo.db.transaction(function(t) {
tryExecuteSql(t, dbInfo, "DELETE FROM " + dbInfo.storeName + " WHERE key = ?", [key2], function() {
resolve();
}, function(t2, error) {
reject(error);
});
});
})["catch"](reject);
});
executeCallback(promise, callback);
return promise;
}
function clear$1(callback) {
var self2 = this;
var promise = new Promise$1(function(resolve, reject) {
self2.ready().then(function() {
var dbInfo = self2._dbInfo;
dbInfo.db.transaction(function(t) {
tryExecuteSql(t, dbInfo, "DELETE FROM " + dbInfo.storeName, [], function() {
resolve();
}, function(t2, error) {
reject(error);
});
});
})["catch"](reject);
});
executeCallback(promise, callback);
return promise;
}
function length$1(callback) {
var self2 = this;
var promise = new Promise$1(function(resolve, reject) {
self2.ready().then(function() {
var dbInfo = self2._dbInfo;
dbInfo.db.transaction(function(t) {
tryExecuteSql(t, dbInfo, "SELECT COUNT(key) as c FROM " + dbInfo.storeName, [], function(t2, results) {
var result = results.rows.item(0).c;
resolve(result);
}, function(t2, error) {
reject(error);
});
});
})["catch"](reject);
});
executeCallback(promise, callback);
return promise;
}
function key$1(n, callback) {
var self2 = this;
var promise = new Promise$1(function(resolve, reject) {
self2.ready().then(function() {
var dbInfo = self2._dbInfo;
dbInfo.db.transaction(function(t) {
tryExecuteSql(t, dbInfo, "SELECT key FROM " + dbInfo.storeName + " WHERE id = ? LIMIT 1", [n + 1], function(t2, results) {
var result = results.rows.length ? results.rows.item(0).key : null;
resolve(result);
}, function(t2, error) {
reject(error);
});
});
})["catch"](reject);
});
executeCallback(promise, callback);
return promise;
}
function keys$1(callback) {
var self2 = this;
var promise = new Promise$1(function(resolve, reject) {
self2.ready().then(function() {
var dbInfo = self2._dbInfo;
dbInfo.db.transaction(function(t) {
tryExecuteSql(t, dbInfo, "SELECT key FROM " + dbInfo.storeName, [], function(t2, results) {
var keys3 = [];
for (var i = 0; i < results.rows.length; i++) {
keys3.push(results.rows.item(i).key);
}
resolve(keys3);
}, function(t2, error) {
reject(error);
});
});
})["catch"](reject);
});
executeCallback(promise, callback);
return promise;
}
function getAllStoreNames(db) {
return new Promise$1(function(resolve, reject) {
db.transaction(function(t) {
t.executeSql("SELECT name FROM sqlite_master WHERE type='table' AND name <> '__WebKitDatabaseInfoTable__'", [], function(t2, results) {
var storeNames = [];
for (var i = 0; i < results.rows.length; i++) {
storeNames.push(results.rows.item(i).name);
}
resolve({
db,
storeNames
});
}, function(t2, error) {
reject(error);
});
}, function(sqlError) {
reject(sqlError);
});
});
}
function dropInstance$1(options, callback) {
callback = getCallback.apply(this, arguments);
var currentConfig = this.config();
options = typeof options !== "function" && options || {};
if (!options.name) {
options.name = options.name || currentConfig.name;
options.storeName = options.storeName || currentConfig.storeName;
}
var self2 = this;
var promise;
if (!options.name) {
promise = Promise$1.reject("Invalid arguments");
} else {
promise = new Promise$1(function(resolve) {
var db;
if (options.name === currentConfig.name) {
db = self2._dbInfo.db;
} else {
db = openDatabase(options.name, "", "", 0);
}
if (!options.storeName) {
resolve(getAllStoreNames(db));
} else {
resolve({
db,
storeNames: [options.storeName]
});
}
}).then(function(operationInfo) {
return new Promise$1(function(resolve, reject) {
operationInfo.db.transaction(function(t) {
function dropTable(storeName) {
return new Promise$1(function(resolve2, reject2) {
t.executeSql("DROP TABLE IF EXISTS " + storeName, [], function() {
resolve2();
}, function(t2, error) {
reject2(error);
});
});
}
var operations = [];
for (var i = 0, len = operationInfo.storeNames.length; i < len; i++) {
operations.push(dropTable(operationInfo.storeNames[i]));
}
Promise$1.all(operations).then(function() {
resolve();
})["catch"](function(e) {
reject(e);
});
}, function(sqlError) {
reject(sqlError);
});
});
});
}
executeCallback(promise, callback);
return promise;
}
var webSQLStorage = {
_driver: "webSQLStorage",
_initStorage: _initStorage$1,
_support: isWebSQLValid(),
iterate: iterate$1,
getItem: getItem$1,
setItem: setItem$1,
removeItem: removeItem$1,
clear: clear$1,
length: length$1,
key: key$1,
keys: keys$1,
dropInstance: dropInstance$1
};
function isLocalStorageValid() {
try {
return typeof localStorage !== "undefined" && "setItem" in localStorage && // in IE8 typeof localStorage.setItem === 'object'
!!localStorage.setItem;
} catch (e) {
return false;
}
}
function _getKeyPrefix(options, defaultConfig) {
var keyPrefix = options.name + "/";
if (options.storeName !== defaultConfig.storeName) {
keyPrefix += options.storeName + "/";
}
return keyPrefix;
}
function checkIfLocalStorageThrows() {
var localStorageTestKey = "_localforage_support_test";
try {
localStorage.setItem(localStorageTestKey, true);
localStorage.removeItem(localStorageTestKey);
return false;
} catch (e) {
return true;
}
}
function _isLocalStorageUsable() {
return !checkIfLocalStorageThrows() || localStorage.length > 0;
}
function _initStorage$2(options) {
var self2 = this;
var dbInfo = {};
if (options) {
for (var i in options) {
dbInfo[i] = options[i];
}
}
dbInfo.keyPrefix = _getKeyPrefix(options, self2._defaultConfig);
if (!_isLocalStorageUsable()) {
return Promise$1.reject();
}
self2._dbInfo = dbInfo;
dbInfo.serializer = localforageSerializer;
return Promise$1.resolve();
}
function clear$2(callback) {
var self2 = this;
var promise = self2.ready().then(function() {
var keyPrefix = self2._dbInfo.keyPrefix;
for (var i = localStorage.length - 1; i >= 0; i--) {
var key2 = localStorage.key(i);
if (key2.indexOf(keyPrefix) === 0) {
localStorage.removeItem(key2);
}
}
});
executeCallback(promise, callback);
return promise;
}
function getItem$2(key2, callback) {
var self2 = this;
key2 = normalizeKey(key2);
var promise = self2.ready().then(function() {
var dbInfo = self2._dbInfo;
var result = localStorage.getItem(dbInfo.keyPrefix + key2);
if (result) {
result = dbInfo.serializer.deserialize(result);
}
return result;
});
executeCallback(promise, callback);
return promise;
}
function iterate$2(iterator, callback) {
var self2 = this;
var promise = self2.ready().then(function() {
var dbInfo = self2._dbInfo;
var keyPrefix = dbInfo.keyPrefix;
var keyPrefixLength = keyPrefix.length;
var length2 = localStorage.length;
var iterationNumber = 1;
for (var i = 0; i < length2; i++) {
var key2 = localStorage.key(i);
if (key2.indexOf(keyPrefix) !== 0) {
continue;
}
var value = localStorage.getItem(key2);
if (value) {
value = dbInfo.serializer.deserialize(value);
}
value = iterator(value, key2.substring(keyPrefixLength), iterationNumber++);
if (value !== void 0) {
return value;
}
}
});
executeCallback(promise, callback);
return promise;
}
function key$2(n, callback) {
var self2 = this;
var promise = self2.ready().then(function() {
var dbInfo = self2._dbInfo;
var result;
try {
result = localStorage.key(n);
} catch (error) {
result = null;
}
if (result) {
result = result.substring(dbInfo.keyPrefix.length);
}
return result;
});
executeCallback(promise, callback);
return promise;
}
function keys$2(callback) {
var self2 = this;
var promise = self2.ready().then(function() {
var dbInfo = self2._dbInfo;
var length2 = localStorage.length;
var keys3 = [];
for (var i = 0; i < length2; i++) {
var itemKey = localStorage.key(i);
if (itemKey.indexOf(dbInfo.keyPrefix) === 0) {
keys3.push(itemKey.substring(dbInfo.keyPrefix.length));
}
}
return keys3;
});
executeCallback(promise, callback);
return promise;
}
function length$2(callback) {
var self2 = this;
var promise = self2.keys().then(function(keys3) {
return keys3.length;
});
executeCallback(promise, callback);
return promise;
}
function removeItem$2(key2, callback) {
var self2 = this;
key2 = normalizeKey(key2);
var promise = self2.ready().then(function() {
var dbInfo = self2._dbInfo;
localStorage.removeItem(dbInfo.keyPrefix + key2);
});
executeCallback(promise, callback);
return promise;
}
function setItem$2(key2, value, callback) {
var self2 = this;
key2 = normalizeKey(key2);
var promise = self2.ready().then(function() {
if (value === void 0) {
value = null;
}
var originalValue = value;
return new Promise$1(function(resolve, reject) {
var dbInfo = self2._dbInfo;
dbInfo.serializer.serialize(value, function(value2, error) {
if (error) {
reject(error);
} else {
try {
localStorage.setItem(dbInfo.keyPrefix + key2, value2);
resolve(originalValue);
} catch (e) {
if (e.name === "QuotaExceededError" || e.name === "NS_ERROR_DOM_QUOTA_REACHED") {
reject(e);
}
reject(e);
}
}
});
});
});
executeCallback(promise, callback);
return promise;
}
function dropInstance$2(options, callback) {
callback = getCallback.apply(this, arguments);
options = typeof options !== "function" && options || {};
if (!options.name) {
var currentConfig = this.config();
options.name = options.name || currentConfig.name;
options.storeName = options.storeName || currentConfig.storeName;
}
var self2 = this;
var promise;
if (!options.name) {
promise = Promise$1.reject("Invalid arguments");
} else {
promise = new Promise$1(function(resolve) {
if (!options.storeName) {
resolve(options.name + "/");
} else {
resolve(_getKeyPrefix(options, self2._defaultConfig));
}
}).then(function(keyPrefix) {
for (var i = localStorage.length - 1; i >= 0; i--) {
var key2 = localStorage.key(i);
if (key2.indexOf(keyPrefix) === 0) {
localStorage.removeItem(key2);
}
}
});
}
executeCallback(promise, callback);
return promise;
}
var localStorageWrapper = {
_driver: "localStorageWrapper",
_initStorage: _initStorage$2,
_support: isLocalStorageValid(),
iterate: iterate$2,
getItem: getItem$2,
setItem: setItem$2,
removeItem: removeItem$2,
clear: clear$2,
length: length$2,
key: key$2,
keys: keys$2,
dropInstance: dropInstance$2
};
var sameValue = function sameValue2(x, y) {
return x === y || typeof x === "number" && typeof y === "number" && isNaN(x) && isNaN(y);
};
var includes = function includes2(array, searchElement) {
var len = array.length;
var i = 0;
while (i < len) {
if (sameValue(array[i], searchElement)) {
return true;
}
i++;
}
return false;
};
var isArray = Array.isArray || function(arg) {
return Object.prototype.toString.call(arg) === "[object Array]";
};
var DefinedDrivers = {};
var DriverSupport = {};
var DefaultDrivers = {
INDEXEDDB: asyncStorage,
WEBSQL: webSQLStorage,
LOCALSTORAGE: localStorageWrapper
};
var DefaultDriverOrder = [DefaultDrivers.INDEXEDDB._driver, DefaultDrivers.WEBSQL._driver, DefaultDrivers.LOCALSTORAGE._driver];
var OptionalDriverMethods = ["dropInstance"];
var LibraryMethods = ["clear", "getItem", "iterate", "key", "keys", "length", "removeItem", "setItem"].concat(OptionalDriverMethods);
var DefaultConfig = {
description: "",
driver: DefaultDriverOrder.slice(),
name: "localforage",
// Default DB size is _JUST UNDER_ 5MB, as it's the highest size
// we can use without a prompt.
size: 4980736,
storeName: "keyvaluepairs",
version: 1
};
function callWhenReady(localForageInstance, libraryMethod) {
localForageInstance[libraryMethod] = function() {
var _args = arguments;
return localForageInstance.ready().then(function() {
return localForageInstance[libraryMethod].apply(localForageInstance, _args);
});
};
}
function extend2() {
for (var i = 1; i < arguments.length; i++) {
var arg = arguments[i];
if (arg) {
for (var _key in arg) {
if (arg.hasOwnProperty(_key)) {
if (isArray(arg[_key])) {
arguments[0][_key] = arg[_key].slice();
} else {
arguments[0][_key] = arg[_key];
}
}
}
}
}
return arguments[0];
}
var LocalForage = function() {
function LocalForage2(options) {
_classCallCheck2(this, LocalForage2);
for (var driverTypeKey in DefaultDrivers) {
if (DefaultDrivers.hasOwnProperty(driverTypeKey)) {
var driver = DefaultDrivers[driverTypeKey];
var driverName = driver._driver;
this[driverTypeKey] = driverName;
if (!DefinedDrivers[driverName]) {
this.defineDriver(driver);
}
}
}
this._defaultConfig = extend2({}, DefaultConfig);
this._config = extend2({}, this._defaultConfig, options);
this._driverSet = null;
this._initDriver = null;
this._ready = false;
this._dbInfo = null;
this._wrapLibraryMethodsWithReady();
this.setDriver(this._config.driver)["catch"](function() {
});
}
LocalForage2.prototype.config = function config(options) {
if ((typeof options === "undefined" ? "undefined" : _typeof(options)) === "object") {
if (this._ready) {
return new Error("Can't call config() after localforage has been used.");
}
for (var i in options) {
if (i === "storeName") {
options[i] = options[i].replace(/\W/g, "_");
}
if (i === "version" && typeof options[i] !== "number") {
return new Error("Database version must be a number.");
}
this._config[i] = options[i];
}
if ("driver" in options && options.driver) {
return this.setDriver(this._config.driver);
}
return true;
} else if (typeof options === "string") {
return this._config[options];
} else {
return this._config;
}
};
LocalForage2.prototype.defineDriver = function defineDriver(driverObject, callback, errorCallback) {
var promise = new Promise$1(function(resolve, reject) {
try {
var driverName = driverObject._driver;
var complianceError = new Error("Custom driver not compliant; see https://mozilla.github.io/localForage/#definedriver");
if (!driverObject._driver) {
reject(complianceError);
return;
}
var driverMethods = LibraryMethods.concat("_initStorage");
for (var i = 0, len = driverMethods.length; i < len; i++) {
var driverMethodName = driverMethods[i];
var isRequired = !includes(OptionalDriverMethods, driverMethodName);
if ((isRequired || driverObject[driverMethodName]) && typeof driverObject[driverMethodName] !== "function") {
reject(complianceError);
return;
}
}
var configureMissingMethods = function configureMissingMethods2() {
var methodNotImplementedFactory = function methodNotImplementedFactory2(methodName) {
return function() {
var error = new Error("Method " + methodName + " is not implemented by the current driver");
var promise2 = Promise$1.reject(error);
executeCallback(promise2, arguments[arguments.length - 1]);
return promise2;
};
};
for (var _i = 0, _len = OptionalDriverMethods.length; _i < _len; _i++) {
var optionalDriverMethod = OptionalDriverMethods[_i];
if (!driverObject[optionalDriverMethod]) {
driverObject[optionalDriverMethod] = methodNotImplementedFactory(optionalDriverMethod);
}
}
};
configureMissingMethods();
var setDriverSupport = function setDriverSupport2(support) {
if (DefinedDrivers[driverName]) {
console.info("Redefining LocalForage driver: " + driverName);
}
DefinedDrivers[driverName] = driverObject;
DriverSupport[driverName] = support;
resolve();
};
if ("_support" in driverObject) {
if (driverObject._support && typeof driverObject._support === "function") {
driverObject._support().then(setDriverSupport, reject);
} else {
setDriverSupport(!!driverObject._support);
}
} else {
setDriverSupport(true);
}
} catch (e) {
reject(e);
}
});
executeTwoCallbacks(promise, callback, errorCallback);
return promise;
};
LocalForage2.prototype.driver = function driver() {
return this._driver || null;
};
LocalForage2.prototype.getDriver = function getDriver(driverName, callback, errorCallback) {
var getDriverPromise = DefinedDrivers[driverName] ? Promise$1.resolve(DefinedDrivers[driverName]) : Promise$1.reject(new Error("Driver not found."));
executeTwoCallbacks(getDriverPromise, callback, errorCallback);
return getDriverPromise;
};
LocalForage2.prototype.getSerializer = function getSerializer(callback) {
var serializerPromise = Promise$1.resolve(localforageSerializer);
executeTwoCallbacks(serializerPromise, callback);
return serializerPromise;
};
LocalForage2.prototype.ready = function ready(callback) {
var self2 = this;
var promise = self2._driverSet.then(function() {
if (self2._ready === null) {
self2._ready = self2._initDriver();
}
return self2._ready;
});
executeTwoCallbacks(promise, callback, callback);
return promise;
};
LocalForage2.prototype.setDriver = function setDriver(drivers, callback, errorCallback) {
var self2 = this;
if (!isArray(drivers)) {
drivers = [drivers];
}
var supportedDrivers = this._getSupportedDrivers(drivers);
function setDriverToConfig() {
self2._config.driver = self2.driver();
}
function extendSelfWithDriver(driver) {
self2._extend(driver);
setDriverToConfig();
self2._ready = self2._initStorage(self2._config);
return self2._ready;
}
function initDriver(supportedDrivers2) {
return function() {
var currentDriverIndex = 0;
function driverPromiseLoop() {
while (currentDriverIndex < supportedDrivers2.length) {
var driverName = supportedDrivers2[currentDriverIndex];
currentDriverIndex++;
self2._dbInfo = null;
self2._ready = null;
return self2.getDriver(driverName).then(extendSelfWithDriver)["catch"](driverPromiseLoop);
}
setDriverToConfig();
var error = new Error("No available storage method found.");
self2._driverSet = Promise$1.reject(error);
return self2._driverSet;
}
return driverPromiseLoop();
};
}
var oldDriverSetDone = this._driverSet !== null ? this._driverSet["catch"](function() {
return Promise$1.resolve();
}) : Promise$1.resolve();
this._driverSet = oldDriverSetDone.then(function() {
var driverName = supportedDrivers[0];
self2._dbInfo = null;
self2._ready = null;
return self2.getDriver(driverName).then(function(driver) {
self2._driver = driver._driver;
setDriverToConfig();
self2._wrapLibraryMethodsWithReady();
self2._initDriver = initDriver(supportedDrivers);
});
})["catch"](function() {
setDriverToConfig();
var error = new Error("No available storage method found.");
self2._driverSet = Promise$1.reject(error);
return self2._driverSet;
});
executeTwoCallbacks(this._driverSet, callback, errorCallback);
return this._driverSet;
};
LocalForage2.prototype.supports = function supports(driverName) {
return !!DriverSupport[driverName];
};
LocalForage2.prototype._extend = function _extend(libraryMethodsAndProperties) {
extend2(this, libraryMethodsAndProperties);
};
LocalForage2.prototype._getSupportedDrivers = function _getSupportedDrivers(drivers) {
var supportedDrivers = [];
for (var i = 0, len = drivers.length; i < len; i++) {
var driverName = drivers[i];
if (this.supports(driverName)) {
supportedDrivers.push(driverName);
}
}
return supportedDrivers;
};
LocalForage2.prototype._wrapLibraryMethodsWithReady = function _wrapLibraryMethodsWithReady() {
for (var i = 0, len = LibraryMethods.length; i < len; i++) {
callWhenReady(this, LibraryMethods[i]);
}
};
LocalForage2.prototype.createInstance = function createInstance(options) {
return new LocalForage2(options);
};
return LocalForage2;
}();
var localforage_js = new LocalForage();
module3.exports = localforage_js;
}, { "3": 3 }] }, {}, [4])(4);
});
})(localforage$1);
var localforageExports = localforage$1.exports;
const localforage = /* @__PURE__ */ getDefaultExportFromCjs(localforageExports);
class Store {
constructor(name, requester, resolver) {
this.urlCache = {};
this.storage = void 0;
this.name = name;
this.requester = requester || request;
this.resolver = resolver;
this.online = true;
this.checkRequirements();
this.addListeners();
}
/**
* Checks to see if localForage exists in global namspace,
* Requires localForage if it isn't there
* @private
*/
checkRequirements() {
try {
let store;
if (typeof localforage === "undefined") {
store = localforage;
}
this.storage = store.createInstance({
name: this.name
});
} catch (e) {
throw new Error("localForage lib not loaded");
}
}
/**
* Add online and offline event listeners
* @private
*/
addListeners() {
this._status = this.status.bind(this);
window.addEventListener("online", this._status);
window.addEventListener("offline", this._status);
}
/**
* Remove online and offline event listeners
* @private
*/
removeListeners() {
window.removeEventListener("online", this._status);
window.removeEventListener("offline", this._status);
this._status = void 0;
}
/**
* Update the online / offline status
* @private
*/
status(event) {
let online = navigator.onLine;
this.online = online;
if (online) {
this.emit("online", this);
} else {
this.emit("offline", this);
}
}
/**
* Add all of a book resources to the store
* @param {Resources} resources book resources
* @param {boolean} [force] force resaving resources
* @return {Promise<object>} store objects
*/
add(resources, force) {
let mapped = resources.resources.map((item) => {
let { href } = item;
let url = this.resolver(href);
let encodedUrl = window.encodeURIComponent(url);
return this.storage.getItem(encodedUrl).then((item2) => {
if (!item2 || force) {
return this.requester(url, "binary").then((data) => {
return this.storage.setItem(encodedUrl, data);
});
} else {
return item2;
}
});
});
return Promise.all(mapped);
}
/**
* Put binary data from a url to storage
* @param {string} url a url to request from storage
* @param {boolean} [withCredentials]
* @param {object} [headers]
* @return {Promise<Blob>}
*/
put(url, withCredentials, headers) {
let encodedUrl = window.encodeURIComponent(url);
return this.storage.getItem(encodedUrl).then((result) => {
if (!result) {
return this.requester(url, "binary", withCredentials, headers).then((data) => {
return this.storage.setItem(encodedUrl, data);
});
}
return result;
});
}
/**
* Request a url
* @param {string} url a url to request from storage
* @param {string} [type] specify the type of the returned result
* @param {boolean} [withCredentials]
* @param {object} [headers]
* @return {Promise<Blob | string | JSON | Document | XMLDocument>}
*/
request(url, type2, withCredentials, headers) {
if (this.online) {
return this.requester(url, type2, withCredentials, headers).then((data) => {
this.put(url);
return data;
});
} else {
return this.retrieve(url, type2);
}
}
/**
* Request a url from storage
* @param {string} url a url to request from storage
* @param {string} [type] specify the type of the returned result
* @return {Promise<Blob | string | JSON | Document | XMLDocument>}
*/
retrieve(url, type2) {
new defer();
var response;
var path2 = new Path(url);
if (!type2) {
type2 = path2.extension;
}
if (type2 == "blob") {
response = this.getBlob(url);
} else {
response = this.getText(url);
}
return response.then((r) => {
var deferred = new defer();
var result;
if (r) {
result = this.handleResponse(r, type2);
deferred.resolve(result);
} else {
deferred.reject({
message: "File not found in storage: " + 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
*/
handleResponse(response, type2) {
var r;
if (type2 == "json") {
r = JSON.parse(response);
} else if (isXml(type2)) {
r = parse(response, "text/xml");
} else if (type2 == "xhtml") {
r = parse(response, "application/xhtml+xml");
} else if (type2 == "html" || type2 == "htm") {
r = parse(response, "text/html");
} else {
r = response;
}
return r;
}
/**
* Get a Blob from Storage by Url
* @param {string} url
* @param {string} [mimeType]
* @return {Blob}
*/
getBlob(url, mimeType) {
let encodedUrl = window.encodeURIComponent(url);
return this.storage.getItem(encodedUrl).then(function(uint8array) {
if (!uint8array)
return;
mimeType = mimeType || mime.lookup(url);
return new Blob([uint8array], { type: mimeType });
});
}
/**
* Get Text from Storage by Url
* @param {string} url
* @param {string} [mimeType]
* @return {string}
*/
getText(url, mimeType) {
let encodedUrl = window.encodeURIComponent(url);
mimeType = mimeType || mime.lookup(url);
return this.storage.getItem(encodedUrl).then(function(uint8array) {
var deferred = new defer();
var reader = new FileReader();
var blob;
if (!uint8array)
return;
blob = new Blob([uint8array], { type: mimeType });
reader.addEventListener("loadend", () => {
deferred.resolve(reader.result);
});
reader.readAsText(blob, mimeType);
return deferred.promise;
});
}
/**
* Get a base64 encoded result from Storage by Url
* @param {string} url
* @param {string} [mimeType]
* @return {string} base64 encoded
*/
getBase64(url, mimeType) {
let encodedUrl = window.encodeURIComponent(url);
mimeType = mimeType || mime.lookup(url);
return this.storage.getItem(encodedUrl).then((uint8array) => {
var deferred = new defer();
var reader = new FileReader();
var blob;
if (!uint8array)
return;
blob = new Blob([uint8array], { type: mimeType });
reader.addEventListener("loadend", () => {
deferred.resolve(reader.result);
});
reader.readAsDataURL(blob, mimeType);
return deferred.promise;
});
}
/**
* Create a Url from a stored item
* @param {string} url
* @param {object} [options.base64] use base64 encoding or blob url
* @return {Promise} url promise with Url string
*/
createUrl(url, options) {
var deferred = new defer();
var _URL2 = 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(tempUrl2) {
this.urlCache[url] = tempUrl2;
deferred.resolve(tempUrl2);
}).bind(this));
}
} else {
response = this.getBlob(url);
if (response) {
response.then((function(blob) {
tempUrl = _URL2.createObjectURL(blob);
this.urlCache[url] = tempUrl;
deferred.resolve(tempUrl);
}).bind(this));
}
}
if (!response) {
deferred.reject({
message: "File not found in storage: " + url,
stack: new Error().stack
});
}
return deferred.promise;
}
/**
* Revoke Temp Url for a archive item
* @param {string} url url of the item in the store
*/
revokeUrl(url) {
var _URL2 = window.URL || window.webkitURL || window.mozURL;
var fromCache = this.urlCache[url];
if (fromCache)
_URL2.revokeObjectURL(fromCache);
}
destroy() {
var _URL2 = window.URL || window.webkitURL || window.mozURL;
for (let fromCache in this.urlCache) {
_URL2.revokeObjectURL(fromCache);
}
this.urlCache = {};
this.removeListeners();
}
}
EventEmitter(Store.prototype);
class DisplayOptions {
constructor(displayOptionsDocument) {
this.interactive = "";
this.fixedLayout = "";
this.openToSpread = "";
this.orientationLock = "";
if (displayOptionsDocument) {
this.parse(displayOptionsDocument);
}
}
/**
* Parse XML
* @param {document} displayOptionsDocument XML
* @return {DisplayOptions} self
*/
parse(displayOptionsDocument) {
if (!displayOptionsDocument) {
return this;
}
const displayOptionsNode = qs(displayOptionsDocument, "display_options");
if (!displayOptionsNode) {
return this;
}
const options = qsa(displayOptionsNode, "option");
options.forEach((el) => {
let value = "";
if (el.childNodes.length) {
value = el.childNodes[0].nodeValue;
}
switch (el.attributes.name.value) {
case "interactive":
this.interactive = value;
break;
case "fixed-layout":
this.fixedLayout = value;
break;
case "open-to-spread":
this.openToSpread = value;
break;
case "orientation-lock":
this.orientationLock = value;
break;
}
});
return this;
}
destroy() {
this.interactive = void 0;
this.fixedLayout = void 0;
this.openToSpread = void 0;
this.orientationLock = void 0;
}
}
const CONTAINER_PATH = "META-INF/container.xml";
const IBOOKS_DISPLAY_OPTIONS_PATH = "META-INF/com.apple.ibooks.display-options.xml";
const INPUT_TYPE = {
BINARY: "binary",
BASE64: "base64",
EPUB: "epub",
OPF: "opf",
MANIFEST: "json",
DIRECTORY: "directory"
};
class Book {
constructor(url, options) {
if (typeof options === "undefined" && typeof url !== "string" && url instanceof Blob === false && url instanceof ArrayBuffer === false) {
options = url;
url = void 0;
}
this.settings = extend(this.settings || {}, {
requestMethod: void 0,
requestCredentials: void 0,
requestHeaders: void 0,
encoding: void 0,
replacements: void 0,
canonical: void 0,
openAs: void 0,
store: void 0
});
extend(this.settings, options);
this.opening = new defer();
this.opened = this.opening.promise;
this.isOpen = false;
this.loading = {
manifest: new defer(),
spine: new defer(),
metadata: new defer(),
cover: new defer(),
navigation: new defer(),
pageList: new defer(),
resources: new defer(),
displayOptions: new 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,
displayOptions: this.loading.displayOptions.promise
};
this.ready = Promise.all([
this.loaded.manifest,
this.loaded.spine,
this.loaded.metadata,
this.loaded.cover,
this.loaded.navigation,
this.loaded.resources,
this.loaded.displayOptions
]);
this.isRendered = false;
this.request = this.settings.requestMethod || request;
this.spine = new Spine();
this.locations = new Locations(this.spine, this.load.bind(this));
this.navigation = void 0;
this.pageList = void 0;
this.url = void 0;
this.path = void 0;
this.archived = false;
this.archive = void 0;
this.storage = void 0;
this.resources = void 0;
this.rendition = void 0;
this.container = void 0;
this.packaging = void 0;
this.displayOptions = void 0;
if (this.settings.store) {
this.store(this.settings.store);
}
if (url) {
this.open(url, this.settings.openAs).catch((error) => {
var err = new Error("Cannot load book at " + url);
this.emit(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")
*/
open(input, what) {
var opening;
var type2 = what || this.determineType(input);
if (type2 === INPUT_TYPE.BINARY) {
this.archived = true;
this.url = new Url("/", "");
opening = this.openEpub(input);
} else if (type2 === INPUT_TYPE.BASE64) {
this.archived = true;
this.url = new Url("/", "");
opening = this.openEpub(input, type2);
} else if (type2 === INPUT_TYPE.EPUB) {
this.archived = true;
this.url = new Url("/", "");
opening = this.request(input, "binary", this.settings.requestCredentials, this.settings.requestHeaders).then(this.openEpub.bind(this));
} else if (type2 == INPUT_TYPE.OPF) {
this.url = new Url(input);
opening = this.openPackaging(this.url.Path.toString());
} else if (type2 == INPUT_TYPE.MANIFEST) {
this.url = new Url(input);
opening = this.openManifest(this.url.Path.toString());
} else {
this.url = new Url(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}
*/
openEpub(data, encoding) {
return this.unarchive(data, encoding || this.settings.encoding).then(() => {
return this.openContainer(CONTAINER_PATH);
}).then((packagePath) => {
return this.openPackaging(packagePath);
});
}
/**
* Open the epub container
* @private
* @param {string} url
* @return {string} packagePath
*/
openContainer(url) {
return this.load(url).then((xml) => {
this.container = new Container(xml);
return this.resolve(this.container.packagePath);
});
}
/**
* Open the Open Packaging Format Xml
* @private
* @param {string} url
* @return {Promise}
*/
openPackaging(url) {
this.path = new Path(url);
return this.load(url).then((xml) => {
this.packaging = new Packaging(xml);
return this.unpack(this.packaging);
});
}
/**
* Open the manifest JSON
* @private
* @param {string} url
* @return {Promise}
*/
openManifest(url) {
this.path = new Path(url);
return this.load(url).then((json) => {
this.packaging = new Packaging();
this.packaging.load(json);
return this.unpack(this.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
*/
load(path2) {
var resolved = this.resolve(path2);
if (this.archived) {
return this.archive.request(resolved);
} else {
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
*/
resolve(path2, absolute) {
if (!path2) {
return;
}
var resolved = path2;
var isAbsolute = path2.indexOf("://") > -1;
if (isAbsolute) {
return path2;
}
if (this.path) {
resolved = this.path.resolve(path2);
}
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
*/
canonical(path2) {
var url = path2;
if (!path2) {
return "";
}
if (this.settings.canonical) {
url = this.settings.canonical(path2);
} else {
url = this.resolve(path2, true);
}
return url;
}
/**
* Determine the type of they input passed to open
* @private
* @param {string} input
* @return {string} binary | directory | epub | opf
*/
determineType(input) {
var url;
var path2;
var extension;
if (this.settings.encoding === "base64") {
return INPUT_TYPE.BASE64;
}
if (typeof input != "string") {
return INPUT_TYPE.BINARY;
}
url = new Url(input);
path2 = url.path();
extension = path2.extension;
if (extension) {
extension = extension.replace(/\?.*$/, "");
}
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 packaging
* @private
* @param {Packaging} packaging object
*/
unpack(packaging) {
this.package = packaging;
if (this.packaging.metadata.layout === "") {
this.load(this.url.resolve(IBOOKS_DISPLAY_OPTIONS_PATH)).then((xml) => {
this.displayOptions = new DisplayOptions(xml);
this.loading.displayOptions.resolve(this.displayOptions);
}).catch((err) => {
this.displayOptions = new DisplayOptions();
this.loading.displayOptions.resolve(this.displayOptions);
});
} else {
this.displayOptions = new DisplayOptions();
this.loading.displayOptions.resolve(this.displayOptions);
}
this.spine.unpack(this.packaging, this.resolve.bind(this), this.canonical.bind(this));
this.resources = new Resources(this.packaging.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.packaging).then(() => {
this.loading.navigation.resolve(this.navigation);
});
if (this.packaging.coverPath) {
this.cover = this.resolve(this.packaging.coverPath);
}
this.loading.manifest.resolve(this.packaging.manifest);
this.loading.metadata.resolve(this.packaging.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(() => {
this.loaded.displayOptions.then(() => {
this.opening.resolve(this);
});
}).catch((err) => {
console.error(err);
});
} else {
this.loaded.displayOptions.then(() => {
this.opening.resolve(this);
});
}
}
/**
* Load Navigation and PageList from package
* @private
* @param {Packaging} packaging
*/
loadNavigation(packaging) {
let navPath = packaging.navPath || packaging.ncxPath;
let toc = packaging.toc;
if (toc) {
return new Promise((resolve, reject) => {
this.navigation = new Navigation(toc);
if (packaging.pageList) {
this.pageList = new PageList(packaging.pageList);
}
resolve(this.navigation);
});
}
if (!navPath) {
return new Promise((resolve, reject) => {
this.navigation = new Navigation();
this.pageList = new PageList();
resolve(this.navigation);
});
}
return this.load(navPath, "xml").then((xml) => {
this.navigation = new Navigation(xml);
this.pageList = new PageList(xml);
return this.navigation;
});
}
/**
* Gets a Section of the Book from the Spine
* Alias for `book.spine.get`
* @param {string} target
* @return {Section}
*/
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}
*/
renderTo(element, options) {
this.rendition = new Rendition(this, options);
this.rendition.attachTo(element);
return this.rendition;
}
/**
* Set if request should use withCredentials
* @param {boolean} credentials
*/
setRequestCredentials(credentials) {
this.settings.requestCredentials = credentials;
}
/**
* Set headers request should use
* @param {object} headers
*/
setRequestHeaders(headers) {
this.settings.requestHeaders = headers;
}
/**
* Unarchive a zipped epub
* @private
* @param {binary} input epub data
* @param {string} [encoding]
* @return {Archive}
*/
unarchive(input, encoding) {
this.archive = new Archive();
return this.archive.open(input, encoding);
}
/**
* Store the epubs contents
* @private
* @param {binary} input epub data
* @param {string} [encoding]
* @return {Store}
*/
store(name) {
let replacementsSetting = this.settings.replacements && this.settings.replacements !== "none";
let originalUrl = this.url;
let requester = this.settings.requestMethod || request.bind(this);
this.storage = new Store(name, requester, this.resolve.bind(this));
this.request = this.storage.request.bind(this.storage);
this.opened.then(() => {
if (this.archived) {
this.storage.requester = this.archive.request.bind(this.archive);
}
let substituteResources = (output, section) => {
section.output = this.resources.substitute(output, section.url);
};
this.resources.settings.replacements = replacementsSetting || "blobUrl";
this.resources.replacements().then(() => {
return this.resources.replaceCss();
});
this.storage.on("offline", () => {
this.url = new Url("/", "");
this.spine.hooks.serialize.register(substituteResources);
});
this.storage.on("online", () => {
this.url = originalUrl;
this.spine.hooks.serialize.deregister(substituteResources);
});
});
return this.storage;
}
/**
* Get the cover url
* @return {Promise<?string>} coverUrl
*/
coverUrl() {
return this.loaded.cover.then(() => {
if (!this.cover) {
return null;
}
if (this.archived) {
return this.archive.createUrl(this.cover);
} else {
return this.cover;
}
});
}
/**
* Load replacement urls
* @private
* @return {Promise} completed loading urls
*/
replacements() {
this.spine.hooks.serialize.register((output, section) => {
section.output = this.resources.substitute(output, section.url);
});
return this.resources.replacements().then(() => {
return this.resources.replaceCss();
});
}
/**
* Find a DOM Range for a given CFI Range
* @param {EpubCFI} cfiRange a epub cfi range
* @return {Promise}
*/
getRange(cfiRange) {
var cfi = new EpubCFI(cfiRange);
var item = this.spine.get(cfi.spinePos);
var _request = this.load.bind(this);
if (!item) {
return new Promise((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 identifier in the manifest or other string provided
* @param {string} [identifier] to use instead of metadata identifier
* @return {string} key
*/
key(identifier) {
var ident = identifier || this.packaging.metadata.identifier || this.url.filename;
return `epubjs:${EPUBJS_VERSION}:${ident}`;
}
/**
* Destroy the Book and all associated objects
*/
destroy() {
this.opened = void 0;
this.loading = void 0;
this.loaded = void 0;
this.ready = void 0;
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.displayOptions && this.displayOptions.destroy();
this.spine = void 0;
this.locations = void 0;
this.pageList = void 0;
this.archive = void 0;
this.resources = void 0;
this.container = void 0;
this.packaging = void 0;
this.rendition = void 0;
this.navigation = void 0;
this.url = void 0;
this.path = void 0;
this.archived = false;
}
}
EventEmitter(Book.prototype);
function ePub(url, options) {
return new Book(url, options);
}
ePub.VERSION = EPUBJS_VERSION;
if (typeof global !== "undefined") {
global.EPUBJS_VERSION = EPUBJS_VERSION;
}
ePub.Book = Book;
ePub.Rendition = Rendition;
ePub.Contents = Contents;
ePub.CFI = EpubCFI;
ePub.utils = utils;
exports2.Book = Book;
exports2.Contents = Contents;
exports2.EpubCFI = EpubCFI;
exports2.Layout = Layout;
exports2.Rendition = Rendition;
exports2.default = ePub;
Object.defineProperties(exports2, { __esModule: { value: true }, [Symbol.toStringTag]: { value: "Module" } });
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment